--- a/Makefile.src.in Mon Jun 02 01:46:03 2008 +0000
+++ b/Makefile.src.in Wed Jun 04 22:34:45 2008 +0000
@@ -89,6 +89,32 @@
$(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
+
+# Determine if we are using a modified version
+ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
+REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
+else
+# Are we a git dir?
+ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1)
+REV_MODIFIED := $(shell if cd "$(SRC_DIR)/.." && git diff-index HEAD src | read dummy; then echo M; fi)
+else
+# Are we a hg (Mercurial) dir?
+ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1)
+REV_MODIFIED := $(shell if hg status $(SRC_DIR) | grep -v '^?' | read dummy; then echo M; fi)
+else
+MODIFIED="1"
+endif
+endif
+endif
+
+ifneq ($(MODIFIED),"1")
+ifeq ($(REV_MODIFIED),)
+MODIFIED="0"
+else
+MODIFIED="2"
+endif
+endif
+
# Make the revision number
ifdef REVISION
REV := $(REVISION)
@@ -97,7 +123,6 @@
# Are we a SVN dir?
ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
# Find if the local source if modified
-REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
# Find the revision like: rXXXX-branch
REV := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^URL:.*branch/ { split($$2, a, "/"); BRANCH="-"a[5] } /^Last Changed Rev:/ { REV="r"$$4"$(REV_MODIFIED)" } END { print REV BRANCH }')
REV_NR := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^Last Changed Rev:/ { print $$4 }')
@@ -105,13 +130,13 @@
# Are we a git dir?
ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1)
# Find the revision like: gXXXXM-branch
-REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(shell if cd "$(SRC_DIR)/.." && git diff-index HEAD src | read dummy; then echo M; fi)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//')
+REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(REV_MODIFIED)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//')
REV_NR := $(shell LC_ALL=C cd "$(SRC_DIR)/.." && git log --pretty=format:%s src | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
else
# Are we a hg (Mercurial) dir?
ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1)
# Find the revision like: hXXXXM-branch
-REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(shell if hg status $(SRC_DIR) | grep -v '^?' | read dummy; then echo M; fi)$(shell hg branch | sed 's/^/-/;s/^-default$$//')
+REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(REV_MODIFIED)$(shell hg branch | sed 's/^/-/;s/^-default$$//')
REV_NR := $(shell LC_ALL=C hg log -k "svn" -l 1 --template "{desc}\n" $(SRC_DIR) | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
endif
endif
@@ -287,7 +312,7 @@
# Revision files
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
- $(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/rev.cpp
+ $(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@MODIFIED@@#$(MODIFIED)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/rev.cpp
$(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in
$(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/ottdres.rc
Binary file bin/data/openttdd.grf has changed
Binary file bin/data/openttdw.grf has changed
--- a/config.lib Mon Jun 02 01:46:03 2008 +0000
+++ b/config.lib Wed Jun 04 22:34:45 2008 +0000
@@ -936,6 +936,10 @@
if [ $cc_version -ge 30 ]; then
CFLAGS="$CFLAGS -W -Wno-unused-parameter -Wformat=2"
CFLAGS="$CFLAGS -Wredundant-decls"
+ # Do not warn about unused variables when building without asserts
+ if [ $enable_assert -eq 0 ]; then
+ CFLAGS="$CFLAGS -Wno-unused-variable"
+ fi
fi
if [ $cc_version -ge 34 ]; then
--- a/projects/determineversion.vbs Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/determineversion.vbs Wed Jun 04 22:34:45 2008 +0000
@@ -14,23 +14,28 @@
file.Close
End Sub
-Sub UpdateFile(revision, version, cur_date, filename)
+Sub UpdateFile(modified, revision, version, cur_date, filename)
FSO.CopyFile filename & ".in", filename
+ FindReplaceInFile filename, "@@MODIFIED@@", modified
FindReplaceInFile filename, "@@REVISION@@", revision
FindReplaceInFile filename, "@@VERSION@@", version
FindReplaceInFile filename, "@@DATE@@", cur_date
End Sub
Sub UpdateFiles(version)
- Dim WshShell, cur_date, revision, oExec
+ Dim WshShell, cur_date, modified, revision, oExec
Set WshShell = CreateObject("WScript.Shell")
cur_date = DatePart("D", Date) & "." & DatePart("M", Date) & "." & DatePart("YYYY", Date)
revision = 0
+ modified = 1
Select Case Mid(version, 1, 1)
Case "r" ' svn
revision = Mid(version, 2)
If InStr(revision, "M") Then
revision = Mid(revision, 1, InStr(revision, "M") - 1)
+ modified = 2
+ Else
+ modified = 0
End If
If InStr(revision, "-") Then
revision = Mid(revision, 1, InStr(revision, "-") - 1)
@@ -49,8 +54,8 @@
End If
End Select
- UpdateFile revision, version, cur_date, "../src/rev.cpp"
- UpdateFile revision, version, cur_date, "../src/ottdres.rc"
+ UpdateFile modified, revision, version, cur_date, "../src/rev.cpp"
+ UpdateFile modified, revision, version, cur_date, "../src/ottdres.rc"
End Sub
Function ReadRegistryKey(shive, subkey, valuename, architecture)
--- a/projects/openttd_vs80.vcproj Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/openttd_vs80.vcproj Wed Jun 04 22:34:45 2008 +0000
@@ -568,6 +568,10 @@
>
</File>
<File
+ RelativePath=".\..\src\gamelog.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\genworld.cpp"
>
</File>
@@ -1036,6 +1040,10 @@
>
</File>
<File
+ RelativePath=".\..\src\gamelog.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\genworld.h"
>
</File>
@@ -1140,7 +1148,7 @@
>
</File>
<File
- RelativePath=".\..\src\network\network_data.h"
+ RelativePath=".\..\src\network\network_func.h"
>
</File>
<File
@@ -1160,6 +1168,10 @@
>
</File>
<File
+ RelativePath=".\..\src\network\network_type.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\network\network_udp.h"
>
</File>
--- a/projects/openttd_vs90.vcproj Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/openttd_vs90.vcproj Wed Jun 04 22:34:45 2008 +0000
@@ -565,6 +565,10 @@
>
</File>
<File
+ RelativePath=".\..\src\gamelog.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\genworld.cpp"
>
</File>
@@ -1033,6 +1037,10 @@
>
</File>
<File
+ RelativePath=".\..\src\gamelog.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\genworld.h"
>
</File>
@@ -1137,7 +1145,7 @@
>
</File>
<File
- RelativePath=".\..\src\network\network_data.h"
+ RelativePath=".\..\src\network\network_func.h"
>
</File>
<File
@@ -1157,6 +1165,10 @@
>
</File>
<File
+ RelativePath=".\..\src\network\network_type.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\network\network_udp.h"
>
</File>
--- a/readme.txt Mon Jun 02 01:46:03 2008 +0000
+++ b/readme.txt Wed Jun 04 22:34:45 2008 +0000
@@ -203,6 +203,35 @@
http://wiki.openttd.org/index.php/Console
+5.1) Logging of potentially dangerous actions:
+---- ----------------------------------------
+
+OpenTTD is a complex program, and together with NewGRF, it may show a buggy
+behaviour. But not only bugs in code can cause problems. There are several
+ways to affect game state possibly resulting in program crash or multiplayer
+desyncs.
+Easier way would be to forbid all these unsafe actions, but that would affect
+game usability for many players. We certainly do not want that.
+However, we receive bugreports because of this. To reduce time spent with
+solving these problems, these potentially unsafe actions are logged in
+the savegame (including crash.sav). Log is stored in crash logs, too.
+
+Information logged:
+
+* Adding / removing / changing order of NewGRFs
+* Changing NewGRF parameters, loading compatible NewGRF
+* Changing game mode (scenario editor <-> normal game)
+* Loading game saved in a different OTTD / TTDPatch / TTD version
+* Running a modified OTTD build
+* Changing patch settings affecting NewGRF behaviour (non-networksafe patches)
+* Changing landscape (by cheat)
+
+No personal information is stored.
+
+You can show the gamelog by typing 'gamelog' in the console or by running
+OpenTTD in debug mode.
+
+
6.0) Configuration File:
---- -------------------
The configuration file for OpenTTD (openttd.cfg) is in a simple Windows-like
--- a/source.list Mon Jun 02 01:46:03 2008 +0000
+++ b/source.list Wed Jun 04 22:34:45 2008 +0000
@@ -28,6 +28,7 @@
fileio.cpp
fios.cpp
fontcache.cpp
+gamelog.cpp
genworld.cpp
gfx.cpp
gfxinit.cpp
@@ -184,6 +185,7 @@
fios.h
fontcache.h
functions.h
+gamelog.h
genworld.h
core/geometry_type.hpp
gfx_func.h
@@ -210,11 +212,12 @@
namegen_func.h
network/network.h
network/network_client.h
-network/network_data.h
+network/network_func.h
network/network_gamelist.h
network/network_gui.h
network/network_internal.h
network/network_server.h
+network/network_type.h
network/network_udp.h
newgrf.h
newgrf_callbacks.h
--- a/src/blitter/8bpp_optimized.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/blitter/8bpp_optimized.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -6,38 +6,34 @@
#include "../zoom_func.h"
#include "../debug.h"
#include "../core/alloc_func.hpp"
+#include "../core/math_func.hpp"
#include "8bpp_optimized.hpp"
static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
- const uint8 *src, *src_next;
- uint8 *dst, *dst_line;
- uint offset = 0;
-
/* Find the offset of this zoom-level */
- offset = ((const uint8 *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2] | ((const byte *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2 + 1] << 8;
+ uint offset = ((const uint8 *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2] | ((const byte *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2 + 1] << 8;
/* Find where to start reading in the source sprite */
- src = (const uint8 *)bp->sprite + offset;
- dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
+ const uint8 *src = (const uint8 *)bp->sprite + offset;
+ uint8 *dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
/* Skip over the top lines in the source image */
for (int y = 0; y < bp->skip_top; y++) {
- uint trans, pixels;
for (;;) {
- trans = *src++;
- pixels = *src++;
+ uint trans = *src++;
+ uint pixels = *src++;
if (trans == 0 && pixels == 0) break;
src += pixels;
}
}
- src_next = src;
+ const uint8 *src_next = src;
for (int y = 0; y < bp->height; y++) {
- dst = dst_line;
+ uint8 *dst = dst_line;
dst_line += bp->pitch;
uint skip_left = bp->skip_left;
@@ -45,8 +41,8 @@
for (;;) {
src = src_next;
- uint8 trans = *src++;
- uint8 pixels = *src++;
+ uint trans = *src++;
+ uint pixels = *src++;
src_next = src + pixels;
if (trans == 0 && pixels == 0) break;
if (width <= 0) continue;
@@ -75,7 +71,7 @@
dst += trans;
width -= trans;
if (width <= 0) continue;
- if (pixels > width) pixels = width;
+ pixels = min<uint>(pixels, (uint)width);
width -= pixels;
switch (mode) {
@@ -104,99 +100,98 @@
Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
{
- Sprite *dest_sprite;
- byte *temp_dst;
- uint memory = 0;
- uint index = 0;
+ /* Make memory for all zoom-levels */
+ uint memory = (int)(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * sizeof(uint16);
- /* Make memory for all zoom-levels */
- memory += (int)(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * sizeof(uint16);
for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
memory += UnScaleByZoom(sprite->height, i) * UnScaleByZoom(sprite->width, i);
- index += 2;
}
/* We have no idea how much memory we really need, so just guess something */
memory *= 5;
- temp_dst = MallocT<byte>(memory);
+ byte *temp_dst = MallocT<byte>(memory);
+ byte *dst = &temp_dst[(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * 2];
/* Make the sprites per zoom-level */
for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
- /* Store the scaled image */
- const SpriteLoader::CommonPixel *src;
-
/* Store the index table */
+ uint index = dst - temp_dst;
temp_dst[i * 2] = index & 0xFF;
temp_dst[i * 2 + 1] = (index >> 8) & 0xFF;
- byte *dst = &temp_dst[index];
+ /* cache values, because compiler can't cache it */
+ int scaled_height = UnScaleByZoom(sprite->height, i);
+ int scaled_width = UnScaleByZoom(sprite->width, i);
+ int scaled_1 = ScaleByZoom(1, i);
- for (int y = 0; y < UnScaleByZoom(sprite->height, i); y++) {
+ for (int y = 0; y < scaled_height; y++) {
uint trans = 0;
uint pixels = 0;
- uint last_color = 0;
- uint count_index = 0;
- uint rx = 0;
- src = &sprite->data[ScaleByZoom(y, i) * sprite->width];
+ uint last_colour = 0;
+ byte *count_dst = NULL;
- for (int x = 0; x < UnScaleByZoom(sprite->width, i); x++) {
- uint color = 0;
+ /* Store the scaled image */
+ const SpriteLoader::CommonPixel *src = &sprite->data[ScaleByZoom(y, i) * sprite->width];
+ const SpriteLoader::CommonPixel *src_end = &src[sprite->width];
+
+ for (int x = 0; x < scaled_width; x++) {
+ uint colour = 0;
/* Get the color keeping in mind the zoom-level */
- for (int j = 0; j < ScaleByZoom(1, i); j++) {
- if (src->m != 0) color = src->m;
- src++;
- rx++;
+ for (int j = 0; j < scaled_1; j++) {
+ if (src->m != 0) colour = src->m;
/* Because of the scaling it might happen we read outside the buffer. Avoid that. */
- if (rx == sprite->width) break;
+ if (++src == src_end) break;
}
- if (last_color == 0 || color == 0 || pixels == 255) {
- if (count_index != 0) {
+ if (last_colour == 0 || colour == 0 || pixels == 255) {
+ if (count_dst != NULL) {
/* Write how many non-transparent bytes we get */
- temp_dst[count_index] = pixels;
+ *count_dst = pixels;
pixels = 0;
- count_index = 0;
+ count_dst = NULL;
}
/* As long as we find transparency bytes, keep counting */
- if (color == 0) {
- last_color = 0;
+ if (colour == 0) {
+ last_colour = 0;
trans++;
continue;
}
/* No longer transparency, so write the amount of transparent bytes */
*dst = trans;
- dst++; index++;
+ dst++;
trans = 0;
/* Reserve a byte for the pixel counter */
- count_index = index;
- dst++; index++;
+ count_dst = dst;
+ dst++;
}
- last_color = color;
+ last_colour = colour;
pixels++;
- *dst = color;
- dst++; index++;
+ *dst = colour;
+ dst++;
}
- if (count_index != 0) temp_dst[count_index] = pixels;
+ if (count_dst != NULL) *count_dst = pixels;
/* Write line-ending */
- *dst = 0; dst++; index++;
- *dst = 0; dst++; index++;
+ *dst = 0; dst++;
+ *dst = 0; dst++;
}
}
+ uint size = dst - temp_dst;
+
/* Safety check, to make sure we guessed the size correctly */
- assert(index < memory);
+ assert(size < memory);
/* Allocate the exact amount of memory we need */
- dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + index);
+ Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + size);
dest_sprite->height = sprite->height;
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
- memcpy(dest_sprite->data, temp_dst, index);
+ memcpy(dest_sprite->data, temp_dst, size);
free(temp_dst);
return dest_sprite;
--- a/src/blitter/factory.hpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/blitter/factory.hpp Wed Jun 04 22:34:45 2008 +0000
@@ -43,11 +43,8 @@
if (name == NULL) return;
this->name = strdup(name);
-#if !defined(NDEBUG) || defined(WITH_ASSERT)
- /* NDEBUG disables asserts and gives a warning: unused variable 'P' */
- std::pair<Blitters::iterator, bool> P =
-#endif /* !NDEBUG */
- GetBlitters().insert(Blitters::value_type(name, this));
+
+ std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(name, this));
assert(P.second);
}
--- a/src/cheat_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/cheat_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -19,6 +19,7 @@
#include "rail_gui.h"
#include "gui.h"
#include "player_gui.h"
+#include "gamelog.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -65,7 +66,12 @@
if (p1 == -1) p1 = 3;
if (p1 == 4) p1 = 0;
_settings_game.game_creation.landscape = p1;
+
+ GamelogStartAction(GLAT_CHEAT);
+ GamelogTestMode();
ReloadNewGRFData();
+ GamelogStopAction();
+
return _settings_game.game_creation.landscape;
}
--- a/src/console.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -3,11 +3,13 @@
/** @file console.cpp Handling of the in-game console. */
#include "stdafx.h"
-#include "console_internal.h"
-#include "network/network_data.h"
-#include "network/network_server.h"
#include "core/alloc_func.hpp"
#include "string_func.h"
+#include "strings_type.h"
+#include "core/math_func.hpp"
+#include "console_internal.h"
+#include "network/network.h"
+#include "network/network_func.h"
#include "rev.h"
#include <stdarg.h>
@@ -90,7 +92,7 @@
#ifdef ENABLE_NETWORK
if (_redirect_console_to_client != 0) {
/* Redirect the string to the client */
- SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string);
+ NetworkServerSendRcon(_redirect_console_to_client, color_code, string);
return;
}
#endif
--- a/src/console_cmds.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_cmds.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -10,17 +10,14 @@
#include "landscape.h"
#include "saveload.h"
#include "variables.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_server.h"
-#include "network/network_udp.h"
+#include "network/network.h"
+#include "network/network_func.h"
#include "command_func.h"
#include "settings_func.h"
#include "fios.h"
#include "fileio.h"
#include "screenshot.h"
#include "genworld.h"
-#include "network/network.h"
#include "strings_func.h"
#include "viewport_func.h"
#include "window_func.h"
@@ -32,6 +29,7 @@
#include "player_func.h"
#include "player_base.h"
#include "settings_type.h"
+#include "gamelog.h"
#include "ai/ai.h"
#ifdef ENABLE_NETWORK
@@ -219,32 +217,25 @@
static const FiosItem* GetFiosItem(const char* file)
{
- int i;
-
_saveload_mode = SLD_LOAD_GAME;
BuildFileList();
- for (i = 0; i < _fios_num; i++) {
- if (strcmp(file, _fios_list[i].name) == 0) break;
- if (strcmp(file, _fios_list[i].title) == 0) break;
+ for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
+ if (strcmp(file, item->name) == 0) return item;
+ if (strcmp(file, item->title) == 0) return item;
}
- if (i == _fios_num) { // If no name matches, try to parse it as number
- char* endptr;
+ /* If no name matches, try to parse it as number */
+ char *endptr;
+ int i = strtol(file, &endptr, 10);
+ if (file == endptr || *endptr != '\0') i = -1;
- i = strtol(file, &endptr, 10);
- if (file == endptr || *endptr != '\0') i = -1;
- }
-
- return IsInsideMM(i, 0, _fios_num) ? &_fios_list[i] : NULL;
+ return IsInsideMM(i, 0, _fios_items.Length()) ? _fios_items.Get(i) : NULL;
}
DEF_CONSOLE_CMD(ConLoad)
{
- const FiosItem *item;
- const char *file;
-
if (argc == 0) {
IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
return true;
@@ -252,8 +243,8 @@
if (argc != 2) return false;
- file = argv[1];
- item = GetFiosItem(file);
+ const char *file = argv[1];
+ const FiosItem *item = GetFiosItem(file);
if (item != NULL) {
switch (item->type) {
case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
@@ -276,9 +267,6 @@
DEF_CONSOLE_CMD(ConRemove)
{
- const FiosItem* item;
- const char* file;
-
if (argc == 0) {
IConsoleHelp("Remove a savegame by name or index. Usage: 'rm <file | number>'");
return true;
@@ -286,8 +274,8 @@
if (argc != 2) return false;
- file = argv[1];
- item = GetFiosItem(file);
+ const char *file = argv[1];
+ const FiosItem *item = GetFiosItem(file);
if (item != NULL) {
if (!FiosDelete(item->name))
IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
@@ -303,8 +291,6 @@
/* List all the files in the current dir via console */
DEF_CONSOLE_CMD(ConListFiles)
{
- int i;
-
if (argc == 0) {
IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
return true;
@@ -312,9 +298,8 @@
BuildFileList();
- for (i = 0; i < _fios_num; i++) {
- const FiosItem *item = &_fios_list[i];
- IConsolePrintF(CC_DEFAULT, "%d) %s", i, item->title);
+ for (uint i = 0; i < _fios_items.Length(); i++) {
+ IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
}
FiosFreeSavegameList();
@@ -324,9 +309,6 @@
/* Change the dir via console */
DEF_CONSOLE_CMD(ConChangeDirectory)
{
- const FiosItem *item;
- const char *file;
-
if (argc == 0) {
IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
return true;
@@ -334,8 +316,8 @@
if (argc != 2) return false;
- file = argv[1];
- item = GetFiosItem(file);
+ const char *file = argv[1];
+ const FiosItem *item = GetFiosItem(file);
if (item != NULL) {
switch (item->type) {
case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
@@ -426,8 +408,8 @@
}
if (ci != NULL) {
- banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
- SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+ banip = GetPlayerIP(ci);
+ NetworkServerSendError(index, NETWORK_ERROR_KICKED);
IConsolePrint(CC_DEFAULT, "Client banned");
} else {
IConsolePrint(CC_DEFAULT, "Client not online, banned IP");
@@ -540,98 +522,34 @@
if (_network_server) {
IConsoleCmdExec(argv[2]);
} else {
- SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
+ NetworkClientSendRcon(argv[1], argv[2]);
}
return true;
}
DEF_CONSOLE_CMD(ConStatus)
{
- static const char* const stat_str[] = {
- "inactive",
- "authorizing",
- "authorized",
- "waiting",
- "loading map",
- "map done",
- "ready",
- "active"
- };
-
- NetworkTCPSocketHandler *cs;
-
if (argc == 0) {
IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
return true;
}
- FOR_ALL_CLIENTS(cs) {
- int lag = NetworkCalculateLag(cs);
- const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
- const char* status;
-
- status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
- IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'",
- cs->index, ci->client_name, status, lag,
- ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
- GetPlayerIP(ci), ci->unique_id);
- }
-
+ NetworkServerShowStatusToConsole();
return true;
}
DEF_CONSOLE_CMD(ConServerInfo)
{
- const NetworkGameInfo *gi;
-
if (argc == 0) {
IConsoleHelp("List current and maximum client/player limits. Usage 'server_info'");
IConsoleHelp("You can change these values by setting the variables 'max_clients', 'max_companies' and 'max_spectators'");
return true;
}
- gi = &_network_game_info;
- IConsolePrintF(CC_DEFAULT, "Current/maximum clients: %2d/%2d", gi->clients_on, gi->clients_max);
- IConsolePrintF(CC_DEFAULT, "Current/maximum companies: %2d/%2d", ActivePlayerCount(), gi->companies_max);
- IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max);
-
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount)
-{
- if (_network_game_info.clients_max > MAX_CLIENTS) {
- _network_game_info.clients_max = MAX_CLIENTS;
- IConsoleError("Maximum clients out of bounds, truncating to limit.");
- }
-
- return true;
-}
+ IConsolePrintF(CC_DEFAULT, "Current/maximum clients: %2d/%2d", _network_game_info.clients_on, _settings_client.network.max_clients);
+ IConsolePrintF(CC_DEFAULT, "Current/maximum companies: %2d/%2d", ActivePlayerCount(), _settings_client.network.max_companies);
+ IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), _settings_client.network.max_spectators);
-DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
-{
- if (_network_game_info.companies_max > MAX_PLAYERS) {
- _network_game_info.companies_max = MAX_PLAYERS;
- IConsoleError("Maximum companies out of bounds, truncating to limit.");
- }
-
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
-{
- /* XXX see ConHookValidateMaxClientsCount */
- if (_network_game_info.spectators_max > 10) {
- _network_game_info.spectators_max = 10;
- IConsoleError("Maximum spectators out of bounds, truncating to limit.");
- }
-
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookCheckMinPlayers)
-{
- CheckMinPlayers();
return true;
}
@@ -667,7 +585,7 @@
}
if (ci != NULL) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+ NetworkServerSendError(index, NETWORK_ERROR_KICKED);
} else {
IConsoleError("Client not found");
}
@@ -678,8 +596,6 @@
DEF_CONSOLE_CMD(ConResetCompany)
{
const Player *p;
- NetworkTCPSocketHandler *cs;
- const NetworkClientInfo *ci;
PlayerID index;
if (argc == 0) {
@@ -710,15 +626,11 @@
return true;
}
- /* Check if the company has active players */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (ci->client_playas == index) {
- IConsoleError("Cannot remove company: a client is connected to that company.");
- return true;
- }
+ if (NetworkCompanyHasPlayers(index)) {
+ IConsoleError("Cannot remove company: a client is connected to that company.");
+ return false;
}
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ const NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
if (ci->client_playas == index) {
IConsoleError("Cannot remove company: the server is connected to that company.");
return true;
@@ -1274,9 +1186,9 @@
if (argc != 2) return false;
if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
+ NetworkClientSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
} else {
- NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
+ NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
}
return true;
@@ -1328,9 +1240,9 @@
}
if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
+ NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
} else {
- NetworkServer_HandleChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+ NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
}
return true;
@@ -1347,37 +1259,14 @@
if (argc != 3) return false;
if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
+ NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
} else {
- NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+ NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
}
return true;
}
-DEF_CONSOLE_HOOK(ConHookServerPW)
-{
- if (strcmp(_network_server_password, "*") == 0) {
- _network_server_password[0] = '\0';
- _network_game_info.use_password = 0;
- } else {
- ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
- _network_game_info.use_password = 1;
- }
-
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookRconPW)
-{
- if (strcmp(_network_rcon_password, "*") == 0)
- _network_rcon_password[0] = '\0';
-
- ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
-
- return true;
-}
-
extern void HashCurrentCompanyPassword();
/* Also use from within player_gui to change the password graphically */
@@ -1401,7 +1290,7 @@
ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
+ NetworkClientSetPassword();
} else {
HashCurrentCompanyPassword();
}
@@ -1411,56 +1300,6 @@
return true;
}
-DEF_CONSOLE_HOOK(ConProcPlayerName)
-{
- NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
-
- if (ci == NULL) return false;
-
- /* Don't change the name if it is the same as the old name */
- if (strcmp(ci->client_name, _network_player_name) != 0) {
- if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
- } else {
- if (NetworkFindName(_network_player_name)) {
- NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _network_player_name);
- ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
- NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
- }
- }
- }
-
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookServerName)
-{
- ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
- return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookServerAdvertise)
-{
- if (!_network_advertise) // remove us from advertising
- NetworkUDPRemoveAdvertise();
-
- return true;
-}
-
-DEF_CONSOLE_CMD(ConProcServerIP)
-{
- if (argc == 0) {
- IConsolePrintF(CC_WARNING, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
- return true;
- }
-
- if (argc != 1) return false;
-
- _network_server_bind_ip = (strcmp(argv[0], "all") == 0) ? inet_addr("0.0.0.0") : inet_addr(argv[0]);
- snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
- IConsolePrintF(CC_WARNING, "'server_ip' changed to: %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
- return true;
-}
#endif /* ENABLE_NETWORK */
DEF_CONSOLE_CMD(ConPatch)
@@ -1476,17 +1315,7 @@
if (argc == 2) {
IConsoleGetPatchSetting(argv[1]);
} else {
- uint32 val;
-
- if (GetArgumentInteger(&val, argv[2])) {
- if (!IConsoleSetPatchSetting(argv[1], val)) {
- if (_network_server) {
- IConsoleError("This command/variable is not available during network games.");
- } else {
- IConsoleError("This command/variable is only available to a network server.");
- }
- }
- }
+ IConsoleSetPatchSetting(argv[1], argv[2]);
}
return true;
@@ -1525,6 +1354,11 @@
return true;
}
+DEF_CONSOLE_CMD(ConGamelogPrint)
+{
+ GamelogPrintConsole();
+ return true;
+}
#ifdef _DEBUG
/* ****************************************** */
@@ -1590,6 +1424,7 @@
IConsoleCmdRegister("clear", ConClearBuffer);
IConsoleCmdRegister("patch", ConPatch);
IConsoleCmdRegister("list_patches", ConListPatches);
+ IConsoleCmdRegister("gamelog", ConGamelogPrint);
IConsoleAliasRegister("dir", "ls");
IConsoleAliasRegister("del", "rm %+");
@@ -1646,71 +1481,36 @@
IConsoleCmdHookAdd("unpause", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
/*** Networking variables ***/
- IConsoleVarRegister("net_frame_freq", &_network_frame_freq, ICONSOLE_VAR_BYTE, "The amount of frames before a command will be (visibly) executed. Default value: 1");
- IConsoleVarHookAdd("net_frame_freq", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarRegister("net_sync_freq", &_network_sync_freq, ICONSOLE_VAR_UINT16, "The amount of frames to check if the game is still in sync. Default value: 100");
- IConsoleVarHookAdd("net_sync_freq", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
- IConsoleVarStringRegister("server_pw", &_network_server_password, sizeof(_network_server_password), "Set the server password to protect your server. Use '*' to clear the password");
- IConsoleVarHookAdd("server_pw", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("server_pw", ICONSOLE_HOOK_POST_ACTION, ConHookServerPW);
- IConsoleAliasRegister("server_password", "server_pw %+");
- IConsoleVarStringRegister("rcon_pw", &_network_rcon_password, sizeof(_network_rcon_password), "Set the rcon-password to change server behaviour. Use '*' to disable rcon");
- IConsoleVarHookAdd("rcon_pw", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("rcon_pw", ICONSOLE_HOOK_POST_ACTION, ConHookRconPW);
- IConsoleAliasRegister("rcon_password", "rcon_pw %+");
IConsoleVarStringRegister("company_pw", NULL, 0, "Set a password for your company, so no one without the correct password can join. Use '*' to clear the password");
IConsoleVarHookAdd("company_pw", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleVarProcAdd("company_pw", NetworkChangeCompanyPassword);
IConsoleAliasRegister("company_password", "company_pw %+");
- IConsoleVarStringRegister("name", &_network_player_name, sizeof(_network_player_name), "Set your name for multiplayer");
- IConsoleVarHookAdd("name", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
- IConsoleVarHookAdd("name", ICONSOLE_HOOK_POST_ACTION, ConProcPlayerName);
- IConsoleVarStringRegister("server_name", &_network_server_name, sizeof(_network_server_name), "Set the name of the server for multiplayer");
- IConsoleVarHookAdd("server_name", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("server_name", ICONSOLE_HOOK_POST_ACTION, ConHookServerName);
-
- IConsoleVarRegister("server_port", &_network_server_port, ICONSOLE_VAR_UINT32, "Set the server port. Changes take effect the next time you start a server");
- IConsoleVarRegister("server_ip", &_network_server_bind_ip, ICONSOLE_VAR_UINT32, "Set the IP the server binds to. Changes take effect the next time you start a server. Use 'all' to bind to any IP.");
- IConsoleVarProcAdd("server_ip", ConProcServerIP);
- IConsoleAliasRegister("server_bind_ip", "server_ip %+");
- IConsoleAliasRegister("server_ip_bind", "server_ip %+");
- IConsoleAliasRegister("server_bind", "server_ip %+");
- IConsoleVarRegister("server_advertise", &_network_advertise, ICONSOLE_VAR_BOOLEAN, "Set if the server will advertise to the master server and show up there");
- IConsoleVarHookAdd("server_advertise", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("server_advertise", ICONSOLE_HOOK_POST_ACTION, ConHookServerAdvertise);
-
- IConsoleVarRegister("max_clients", &_network_game_info.clients_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of connected players during runtime. Default value: 10");
- IConsoleVarHookAdd("max_clients", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("max_clients", ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxClientsCount);
- IConsoleVarRegister("max_companies", &_network_game_info.companies_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active companies during runtime. Default value: 8");
- IConsoleVarHookAdd("max_companies", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("max_companies", ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxCompaniesCount);
- IConsoleVarRegister("max_spectators", &_network_game_info.spectators_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active spectators during runtime. Default value: 9");
- IConsoleVarHookAdd("max_spectators", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("max_spectators", ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxSpectatorsCount);
-
- IConsoleVarRegister("max_join_time", &_network_max_join_time, ICONSOLE_VAR_UINT16, "Set the maximum amount of time (ticks) a client is allowed to join. Default value: 500");
-
- IConsoleVarRegister("pause_on_join", &_network_pause_on_join, ICONSOLE_VAR_BOOLEAN, "Set if the server should pause gameplay while a client is joining. This might help slow users");
- IConsoleVarHookAdd("pause_on_join", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
- IConsoleVarRegister("autoclean_companies", &_network_autoclean_companies, ICONSOLE_VAR_BOOLEAN, "Automatically shut down inactive companies to free them up for other players. Customize with 'autoclean_(un)protected'");
- IConsoleVarHookAdd("autoclean_companies", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarRegister("autoclean_protected", &_network_autoclean_protected, ICONSOLE_VAR_BYTE, "Automatically remove the password from an inactive company after the given amount of months");
- IConsoleVarHookAdd("autoclean_protected", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarRegister("autoclean_unprotected", &_network_autoclean_unprotected, ICONSOLE_VAR_BYTE, "Automatically shut down inactive companies after the given amount of months");
- IConsoleVarHookAdd("autoclean_unprotected", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarRegister("restart_game_year", &_network_restart_game_year, ICONSOLE_VAR_UINT16, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
- IConsoleVarHookAdd("restart_game_year", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
- IConsoleVarRegister("min_players", &_network_min_players, ICONSOLE_VAR_BYTE, "Automatically pause the game when the number of active players passes below the given amount");
- IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
- IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_POST_ACTION, ConHookCheckMinPlayers);
- IConsoleVarRegister("reload_cfg", &_network_reload_cfg, ICONSOLE_VAR_BOOLEAN, "reload the entire config file between the end of this game, and starting the next new game - dedicated servers");
- IConsoleVarHookAdd("reload_cfg", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
+ IConsoleAliasRegister("net_frame_freq", "patch frame_freq %+");
+ IConsoleAliasRegister("net_sync_freq", "patch sync_freq %+");
+ IConsoleAliasRegister("server_pw", "patch server_password %+");
+ IConsoleAliasRegister("server_password", "patch server_password %+");
+ IConsoleAliasRegister("rcon_pw", "patch rcon_password %+");
+ IConsoleAliasRegister("rcon_password", "patch rcon_password %+");
+ IConsoleAliasRegister("name", "patch player_name %+");
+ IConsoleAliasRegister("server_name", "patch server_name %+");
+ IConsoleAliasRegister("server_port", "patch server_port %+");
+ IConsoleAliasRegister("server_ip", "patch server_bind_ip %+");
+ IConsoleAliasRegister("server_bind_ip", "patch server_bind_ip %+");
+ IConsoleAliasRegister("server_ip_bind", "patch server_bind_ip %+");
+ IConsoleAliasRegister("server_bind", "patch server_bind_ip %+");
+ IConsoleAliasRegister("server_advertise", "patch server_advertise %+");
+ IConsoleAliasRegister("max_clients", "patch max_clients %+");
+ IConsoleAliasRegister("max_companies", "patch max_companies %+");
+ IConsoleAliasRegister("max_spectators", "patch max_spectators %+");
+ IConsoleAliasRegister("max_join_time", "patch max_join_time %+");
+ IConsoleAliasRegister("pause_on_join", "patch pause_on_join %+");
+ IConsoleAliasRegister("autoclean_companies", "patch autoclean_companies %+");
+ IConsoleAliasRegister("autoclean_protected", "patch autoclean_protected %+");
+ IConsoleAliasRegister("autoclean_unprotected", "patch autoclean_unprotected %+");
+ IConsoleAliasRegister("restart_game_year", "patch restart_game_year %+");
+ IConsoleAliasRegister("min_players", "patch min_players %+");
+ IConsoleAliasRegister("reload_cfg", "patch reload_cfg %+");
#endif /* ENABLE_NETWORK */
// debugging stuff
--- a/src/console_func.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_func.h Wed Jun 04 22:34:45 2008 +0000
@@ -19,6 +19,8 @@
void IConsolePrint(ConsoleColour color_code, const char *string);
void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...);
void IConsoleDebug(const char *dbg, const char *string);
+void IConsoleWarning(const char *string);
+void IConsoleError(const char *string);
/* Parser */
void IConsoleCmdExec(const char *cmdstr);
--- a/src/console_internal.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_internal.h Wed Jun 04 22:34:45 2008 +0000
@@ -105,10 +105,6 @@
void IConsoleClearBuffer();
void IConsoleOpen();
-/* console output */
-void IConsoleWarning(const char *string);
-void IConsoleError(const char *string);
-
/* Commands */
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
void IConsoleAliasRegister(const char *name, const char *cmd);
--- a/src/date.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/date.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -7,8 +7,7 @@
#include "variables.h"
#include "settings_type.h"
#include "network/network.h"
-#include "network/network_data.h"
-#include "network/network_server.h"
+#include "network/network_func.h"
#include "currency.h"
#include "window_func.h"
#include "functions.h"
@@ -268,7 +267,9 @@
TownsMonthlyLoop();
IndustryMonthlyLoop();
StationMonthlyLoop();
+#ifdef ENABLE_NETWORK
if (_network_server) NetworkServerMonthlyLoop();
+#endif /* ENABLE_NETWORK */
}
/* check if we entered a new year? */
@@ -281,7 +282,9 @@
RoadVehiclesYearlyLoop();
AircraftYearlyLoop();
ShipsYearlyLoop();
+#ifdef ENABLE_NETWORK
if (_network_server) NetworkServerYearlyLoop();
+#endif /* ENABLE_NETWORK */
if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
--- a/src/debug.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/debug.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -30,6 +30,7 @@
int _debug_freetype_level;
int _debug_sl_level;
int _debug_station_level;
+int _debug_gamelog_level;
struct DebugLevel {
@@ -54,24 +55,17 @@
DEBUG_LEVEL(freetype),
DEBUG_LEVEL(sl),
DEBUG_LEVEL(station),
+ DEBUG_LEVEL(gamelog),
};
#undef DEBUG_LEVEL
#if !defined(NO_DEBUG_MESSAGES)
-void CDECL debug(const char *dbg, ...)
+void CDECL debug_print(const char *dbg, const char *buf)
{
- va_list va;
- va_start(va, dbg);
- const char *s;
- char buf[1024];
-
- s = va_arg(va, const char*);
- vsnprintf(buf, lengthof(buf), s, va);
- va_end(va);
#if defined(ENABLE_NETWORK)
if (_debug_socket != INVALID_SOCKET) {
- char buf2[lengthof(buf) + 32];
+ char buf2[1024 + 32];
snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
send(_debug_socket, buf2, (int)strlen(buf2), 0);
@@ -89,6 +83,20 @@
IConsoleDebug(dbg, buf);
}
}
+
+void CDECL debug(const char *dbg, ...)
+{
+ va_list va;
+ va_start(va, dbg);
+ const char *s;
+ char buf[1024];
+
+ s = va_arg(va, const char*);
+ vsnprintf(buf, lengthof(buf), s, va);
+ va_end(va);
+
+ debug_print(dbg, buf);
+}
#endif /* NO_DEBUG_MESSAGES */
void SetDebugString(const char *s)
--- a/src/debug.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/debug.h Wed Jun 04 22:34:45 2008 +0000
@@ -47,8 +47,10 @@
extern int _debug_freetype_level;
extern int _debug_sl_level;
extern int _debug_station_level;
+ extern int _debug_gamelog_level;
void CDECL debug(const char *dbg, ...);
+ void CDECL debug_print(const char *dbg, const char *buf);
#endif /* NO_DEBUG_MESSAGES */
void SetDebugString(const char *s);
--- a/src/driver.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/driver.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -156,11 +156,7 @@
strecpy(buf, GetDriverTypeName(type), lastof(buf));
strecpy(buf + 5, name, lastof(buf));
-#if !defined(NDEBUG) || defined(WITH_ASSERT)
- /* NDEBUG disables asserts and gives a warning: unused variable 'P' */
- std::pair<Drivers::iterator, bool> P =
-#endif /* !NDEBUG */
- GetDrivers().insert(Drivers::value_type(buf, this));
+ std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(buf, this));
assert(P.second);
}
--- a/src/economy.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/economy.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -14,7 +14,7 @@
#include "town.h"
#include "news_func.h"
#include "network/network.h"
-#include "network/network_data.h"
+#include "network/network_func.h"
#include "variables.h"
#include "vehicle_gui.h"
#include "ai/ai.h"
@@ -489,25 +489,7 @@
if (!_network_server) return;
- /* The server has to handle all administrative issues, for example
- * updating and notifying all clients of what has happened */
- NetworkTCPSocketHandler *cs;
- NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
-
- /* The server has just changed from player */
- if (current_player == ci->client_playas) {
- ci->client_playas = new_player;
- NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
- }
-
- /* Find all clients that were in control of this company, and mark them as new_player */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (current_player == ci->client_playas) {
- ci->client_playas = new_player;
- NetworkUpdateClientInfo(ci->client_index);
- }
- }
+ NetworkServerChangeOwner(current_player, new_player);
#endif /* ENABLE_NETWORK */
}
@@ -670,7 +652,7 @@
* 12 -> months per year
* This is only a good approxiamtion for small values
*/
- Money inf = _economy.infl_amount * 54;
+ int32 inf = _economy.infl_amount * 54;
for (uint i = 0; i != NUM_PRICES; i++) {
AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
--- a/src/economy_type.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/economy_type.h Wed Jun 04 22:34:45 2008 +0000
@@ -18,7 +18,7 @@
int fluct;
byte interest_rate; ///< Interest
byte infl_amount; ///< inflation amount
- byte infl_amount_pr; ///< "floating" portion of inflation
+ byte infl_amount_pr; ///< inflation rate for payment rates
};
struct Subsidy {
--- a/src/effectvehicle.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/effectvehicle.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,6 @@
#include "industry_map.h"
#include "station_map.h"
#include "water_map.h"
-#include "network/network.h"
#include "yapf/yapf.h"
#include "newgrf_callbacks.h"
#include "newgrf_engine.h"
--- a/src/engine.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/engine.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -29,7 +29,7 @@
#include "ai/ai.h"
#include "core/alloc_func.hpp"
#include "vehicle_func.h"
-#include "map"
+#include <map>
#include "table/strings.h"
#include "table/engines.h"
--- a/src/fios.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/fios.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -10,7 +10,6 @@
#include "heightmap.h"
#include "fios.h"
#include "fileio.h"
-#include "core/alloc_func.hpp"
#include "functions.h"
#include "string_func.h"
#include <sys/types.h>
@@ -30,12 +29,9 @@
#include "table/strings.h"
/* Variables to display file lists */
-int _fios_num;
-
+SmallVector<FiosItem, 32> _fios_items;
static char *_fios_path;
-static FiosItem *_fios_items;
SmallFiosItem _file_to_saveload;
-static int _fios_count, _fios_alloc;
/* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */
extern bool FiosIsRoot(const char *path);
@@ -48,19 +44,6 @@
extern void GetOldSaveGameName(char *title, const char *path, const char *file);
/**
- * Allocate a new FiosItem.
- * @return A pointer to the newly allocated FiosItem.
- */
-FiosItem *FiosAlloc()
-{
- if (_fios_count == _fios_alloc) {
- _fios_alloc += 256;
- _fios_items = ReallocT(_fios_items, _fios_alloc);
- }
- return &_fios_items[_fios_count++];
-}
-
-/**
* Compare two FiosItem's. Used with qsort when sorting the file list.
* @param a A pointer to the first FiosItem to compare.
* @param b A pointer to the second FiosItem to compare.
@@ -82,15 +65,12 @@
return r;
}
-/**
- * Free the list of savegames
- */
+/** Clear the list */
void FiosFreeSavegameList()
{
- free(_fios_items);
- _fios_items = NULL;
- _fios_alloc = _fios_count = 0;
-}
+ _fios_items.Clear();
+ _fios_items.Compact();
+};
/**
* Get descriptive texts. Returns the path and free space
@@ -229,9 +209,11 @@
int sort_start;
char d_name[sizeof(fios->name)];
+ _fios_items.Clear();
+
/* A parent directory link exists if we are not in the root directory */
if (!FiosIsRoot(_fios_path) && mode != SLD_NEW_GAME) {
- fios = FiosAlloc();
+ fios = _fios_items.Append();
fios->type = FIOS_TYPE_PARENT;
fios->mtime = 0;
ttd_strlcpy(fios->name, "..", lengthof(fios->name));
@@ -247,7 +229,7 @@
if (FiosIsValidFile(_fios_path, dirent, &sb) && (sb.st_mode & S_IFDIR) &&
(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
- fios = FiosAlloc();
+ fios = _fios_items.Append();
fios->type = FIOS_TYPE_DIR;
fios->mtime = 0;
ttd_strlcpy(fios->name, d_name, lengthof(fios->name));
@@ -262,12 +244,12 @@
{
byte order = _savegame_sort_order;
_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
- qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
+ qsort(_fios_items.Begin(), _fios_items.Length(), sizeof(FiosItem), compare_FiosItems);
_savegame_sort_order = order;
}
/* This is where to start sorting for the filenames */
- sort_start = _fios_count;
+ sort_start = _fios_items.Length();
/* Show files */
dir = ttd_opendir(_fios_path);
@@ -285,7 +267,7 @@
FiosType type = callback_proc(mode, d_name, t, fios_title);
if (type != FIOS_TYPE_INVALID) {
- fios = FiosAlloc();
+ fios = _fios_items.Append();
fios->mtime = sb.st_mtime;
fios->type = type;
ttd_strlcpy(fios->name, d_name, lengthof(fios->name));
@@ -300,13 +282,14 @@
closedir(dir);
}
- qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
+ qsort(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, sizeof(FiosItem), compare_FiosItems);
/* Show drives */
if (mode != SLD_NEW_GAME) FiosGetDrives();
- _fios_num = _fios_count;
- return _fios_items;
+ _fios_items.Compact();
+
+ return _fios_items.Begin();
}
/**
@@ -345,7 +328,7 @@
* @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
* @see FiosGetFileList
*/
-FiosItem *FiosGetSavegameList(SaveLoadDialogMode mode)
+void FiosGetSavegameList(SaveLoadDialogMode mode)
{
static char *fios_save_path = NULL;
@@ -356,7 +339,7 @@
_fios_path = fios_save_path;
- return FiosGetFileList(mode, &FiosGetSavegameListCallback);
+ FiosGetFileList(mode, &FiosGetSavegameListCallback);
}
/**
@@ -393,7 +376,7 @@
* @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
* @see FiosGetFileList
*/
-FiosItem *FiosGetScenarioList(SaveLoadDialogMode mode)
+void FiosGetScenarioList(SaveLoadDialogMode mode)
{
static char *fios_scn_path = NULL;
@@ -405,7 +388,7 @@
_fios_path = fios_scn_path;
- return FiosGetFileList(mode, &FiosGetScenarioListCallback);
+ FiosGetFileList(mode, &FiosGetScenarioListCallback);
}
static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title)
@@ -425,7 +408,7 @@
}
/* Get a list of Heightmaps */
-FiosItem *FiosGetHeightmapList(SaveLoadDialogMode mode)
+void FiosGetHeightmapList(SaveLoadDialogMode mode)
{
static char *fios_hmap_path = NULL;
@@ -436,5 +419,5 @@
_fios_path = fios_hmap_path;
- return FiosGetFileList(mode, &FiosGetHeightmapListCallback);
+ FiosGetFileList(mode, &FiosGetHeightmapListCallback);
}
--- a/src/fios.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/fios.h Wed Jun 04 22:34:45 2008 +0000
@@ -6,6 +6,7 @@
#define FIOS_H
#include "strings_type.h"
+#include "misc/smallvec.h"
enum {
/**
@@ -80,8 +81,7 @@
};
/* Variables to display file lists */
-extern FiosItem *_fios_list; ///< defined in misc_gui.cpp
-extern int _fios_num; ///< defined in fios.cpp, read_only version of _fios_count
+extern SmallVector<FiosItem, 32> _fios_items; ///< defined in fios.cpp
extern SmallFiosItem _file_to_saveload;
extern SaveLoadDialogMode _saveload_mode; ///< defined in misc_gui.cpp
extern byte _savegame_sort_order;
@@ -90,11 +90,11 @@
void ShowSaveLoadDialog(SaveLoadDialogMode mode);
/* Get a list of savegames */
-FiosItem *FiosGetSavegameList(SaveLoadDialogMode mode);
+void FiosGetSavegameList(SaveLoadDialogMode mode);
/* Get a list of scenarios */
-FiosItem *FiosGetScenarioList(SaveLoadDialogMode mode);
+void FiosGetScenarioList(SaveLoadDialogMode mode);
/* Get a list of Heightmaps */
-FiosItem *FiosGetHeightmapList(SaveLoadDialogMode mode);
+void FiosGetHeightmapList(SaveLoadDialogMode mode);
/* Free the list of savegames */
void FiosFreeSavegameList();
/* Browse to. Returns a filename w/path if we reached a file. */
@@ -105,8 +105,6 @@
bool FiosDelete(const char *name);
/* Make a filename from a name */
void FiosMakeSavegameName(char *buf, const char *name, size_t size);
-/* Allocate a new FiosItem */
-FiosItem *FiosAlloc();
int CDECL compare_FiosItems(const void *a, const void *b);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gamelog.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,801 @@
+/* $Id$ */
+
+/** @file gamelog.cpp Definition of functions used for logging of important changes in the game */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "saveload.h"
+#include "core/alloc_func.hpp"
+#include "core/bitmath_func.hpp"
+#include "core/math_func.hpp"
+#include "network/core/config.h"
+#include "variables.h"
+#include "string_func.h"
+#include "settings_type.h"
+#include "newgrf_config.h"
+#include <string.h>
+#include <stdarg.h>
+#include "gamelog.h"
+#include "console_func.h"
+#include "debug.h"
+#include "rev.h"
+
+extern const uint16 SAVEGAME_VERSION; ///< current savegame version
+
+extern SavegameType _savegame_type; ///< type of savegame we are loading
+
+extern uint32 _ttdp_version; ///< version of TTDP savegame (if applicable)
+extern uint16 _sl_version; ///< the major savegame version identifier
+extern byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!
+
+/** Type of logged change */
+enum GamelogChangeType {
+ GLCT_MODE, ///< Scenario editor x Game, different landscape
+ GLCT_REVISION, ///< Changed game revision string
+ GLCT_OLDVER, ///< Loaded from savegame without logged data
+ GLCT_PATCH, ///< Non-networksafe patch value changed
+ GLCT_GRFADD, ///< Removed GRF
+ GLCT_GRFREM, ///< Added GRF
+ GLCT_GRFCOMPAT, ///< Loading compatible GRF
+ GLCT_GRFPARAM, ///< GRF parameter changed
+ GLCT_GRFMOVE, ///< GRF order changed
+ GLCT_END, ///< So we know how many GLCTs are there
+ GLCT_NONE = 0xFF, ///< In savegames, end of list
+};
+
+
+/** Contains information about one logged change */
+struct LoggedChange {
+ GamelogChangeType ct; ///< Type of change logged in this struct
+ union {
+ struct {
+ byte mode; ///< new game mode - Editor x Game
+ byte landscape; ///< landscape (temperate, arctic, ...)
+ } mode;
+ struct {
+ char text[NETWORK_REVISION_LENGTH]; ///< revision string, _openttd_revision
+ uint32 newgrf; ///< _openttd_newgrf_version
+ uint16 slver; ///< _sl_version
+ byte modified; ///< _openttd_revision_modified
+ } revision;
+ struct {
+ uint32 type; ///< type of savegame, @see SavegameType
+ uint32 version; ///< major and minor version OR ttdp version
+ } oldver;
+ GRFIdentifier grfadd; ///< ID and md5sum of added GRF
+ struct {
+ uint32 grfid; ///< ID of removed GRF
+ } grfrem;
+ GRFIdentifier grfcompat; ///< ID and new md5sum of changed GRF
+ struct {
+ uint32 grfid; ///< ID of GRF with changed parameters
+ } grfparam;
+ struct {
+ uint32 grfid; ///< ID of moved GRF
+ int32 offset; ///< offset, positive = move down
+ } grfmove;
+ struct {
+ char *name; ///< name of the patch
+ int32 oldval; ///< old value
+ int32 newval; ///< new value
+ } patch;
+ };
+};
+
+
+/** Contains information about one logged action that caused at least one logged change */
+struct LoggedAction {
+ LoggedChange *change; ///< First logged change in this action
+ uint32 changes; ///< Number of changes in this action
+ GamelogActionType at; ///< Type of action
+ uint16 tick; ///< Tick when it happened
+};
+
+static GamelogActionType _gamelog_action_type = GLAT_NONE; ///< action to record if anything changes
+
+static LoggedAction *_gamelog_action = NULL; ///< first logged action
+static uint _gamelog_actions = 0; ///< number of actions
+static LoggedAction *_current_action = NULL; ///< current action we are logging, NULL when there is no action active
+
+
+/** Stores information about new action, but doesn't allocate it
+ * Action is allocated only when there is at least one change
+ * @param at type of action
+ */
+void GamelogStartAction(GamelogActionType at)
+{
+ assert(_gamelog_action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
+ _gamelog_action_type = at;
+}
+
+/** Stops logging of any changes
+ */
+void GamelogStopAction()
+{
+ assert(_gamelog_action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
+
+ _current_action = NULL;
+ _gamelog_action_type = GLAT_NONE;
+
+ if (_debug_gamelog_level > 4) GamelogPrintDebug();
+}
+
+/** Resets and frees all memory allocated - used before loading or starting a new game
+ */
+void GamelogReset()
+{
+ assert(_gamelog_action_type == GLAT_NONE);
+
+ for (uint i = 0; i < _gamelog_actions; i++) {
+ const LoggedAction *la = &_gamelog_action[i];
+ for (uint j = 0; j < la->changes; j++) {
+ const LoggedChange *lc = &la->change[j];
+ if (lc->ct == GLCT_PATCH) free(lc->patch.name);
+ }
+ free(la->change);
+ }
+
+ free(_gamelog_action);
+
+ _gamelog_action = NULL;
+ _gamelog_actions = 0;
+ _current_action = NULL;
+}
+
+enum {
+ GAMELOG_BUF_LEN = 1024 ///< length of buffer for one line of text
+};
+
+static int _dbgofs = 0; ///< offset in current output buffer
+
+static void AddDebugText(char *buf, const char *s, ...)
+{
+ if (GAMELOG_BUF_LEN <= _dbgofs) return;
+
+ va_list va;
+
+ va_start(va, s);
+ _dbgofs += vsnprintf(buf + _dbgofs, GAMELOG_BUF_LEN - _dbgofs, s, va);
+ va_end(va);
+}
+
+
+/** Prints GRF filename if found
+ * @param grfid GRF which filename to print
+ */
+static void PrintGrfFilename(char *buf, uint grfid)
+{
+ const GRFConfig *gc = FindGRFConfig(grfid);
+
+ if (gc == NULL) return;
+
+ AddDebugText(buf, ", filename: %s", gc->filename);
+}
+
+/** Prints GRF ID, checksum and filename if found
+ * @param grfid GRF ID
+ * @param md5sum array of md5sum to print
+ */
+static void PrintGrfInfo(char *buf, uint grfid, const uint8 *md5sum)
+{
+ char txt[40];
+
+ md5sumToString(txt, lastof(txt), md5sum);
+
+ AddDebugText(buf, "GRF ID %08X, checksum %s", BSWAP32(grfid), txt);
+
+ PrintGrfFilename(buf, grfid);
+
+ return;
+}
+
+
+/** Text messages for various logged actions */
+static const char *la_text[] = {
+ "new game started",
+ "game loaded",
+ "GRF config changed",
+ "cheat was used",
+ "patch settings changed"
+};
+
+assert_compile(lengthof(la_text) == GLAT_END);
+
+
+/** Prints active gamelog */
+void GamelogPrint(GamelogPrintProc *proc)
+{
+ char buf[GAMELOG_BUF_LEN];
+
+ proc("---- gamelog start ----");
+
+ const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+
+ for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+ assert((uint)la->at < GLAT_END);
+
+ snprintf(buf, GAMELOG_BUF_LEN, "Tick %u: %s", (uint)la->tick, la_text[(uint)la->at]);
+ proc(buf);
+
+ const LoggedChange *lcend = &la->change[la->changes];
+
+ for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+ _dbgofs = 0;
+ AddDebugText(buf, " ");
+
+ switch (lc->ct) {
+ default: NOT_REACHED();
+ case GLCT_MODE:
+ AddDebugText(buf, "New game mode: %u landscape: %u",
+ (uint)lc->mode.mode, (uint)lc->mode.landscape);
+ break;
+
+ case GLCT_REVISION:
+ AddDebugText(buf, "Revision text changed to %s, savegame version %u, ",
+ lc->revision.text, lc->revision.slver);
+
+ switch (lc->revision.modified) {
+ case 0: AddDebugText(buf, "not "); break;
+ case 1: AddDebugText(buf, "maybe "); break;
+ default: break;
+ }
+
+ AddDebugText(buf, "modified, _openttd_newgrf_version = 0x%08x", lc->revision.newgrf);
+ break;
+
+ case GLCT_OLDVER:
+ AddDebugText(buf, "Conversion from ");
+ switch (lc->oldver.type) {
+ default: NOT_REACHED();
+ case SGT_OTTD:
+ AddDebugText(buf, "OTTD savegame without gamelog: version %u, %u",
+ GB(lc->oldver.version, 8, 16), GB(lc->oldver.version, 0, 8));
+ break;
+
+ case SGT_TTD:
+ AddDebugText(buf, "TTD savegame");
+ break;
+
+ case SGT_TTDP1:
+ case SGT_TTDP2:
+ AddDebugText(buf, "TTDP savegame, %s format",
+ lc->oldver.type == SGT_TTDP1 ? "old" : "new");
+ if (lc->oldver.version != 0) {
+ AddDebugText(buf, ", TTDP version %u.%u.%u.%u",
+ GB(lc->oldver.version, 24, 8), GB(lc->oldver.version, 20, 4),
+ GB(lc->oldver.version, 16, 4), GB(lc->oldver.version, 0, 16));
+ }
+ break;
+ }
+ break;
+
+ case GLCT_PATCH:
+ AddDebugText(buf, "Patch setting changed: %s : %d -> %d", lc->patch.name, lc->patch.oldval, lc->patch.newval);
+ break;
+
+ case GLCT_GRFADD:
+ AddDebugText(buf, "Added NewGRF: ");
+ PrintGrfInfo(buf, lc->grfadd.grfid, lc->grfadd.md5sum);
+ break;
+
+ case GLCT_GRFREM:
+ AddDebugText(buf, "Removed NewGRF: %08X", BSWAP32(lc->grfrem.grfid));
+ PrintGrfFilename(buf, lc->grfrem.grfid);
+ break;
+
+ case GLCT_GRFCOMPAT:
+ AddDebugText(buf, "Compatible NewGRF loaded: ");
+ PrintGrfInfo(buf, lc->grfcompat.grfid, lc->grfcompat.md5sum);
+ break;
+
+ case GLCT_GRFPARAM:
+ AddDebugText(buf, "GRF parameter changed: %08X", BSWAP32(lc->grfparam.grfid));
+ PrintGrfFilename(buf, lc->grfparam.grfid);
+ break;
+
+ case GLCT_GRFMOVE:
+ AddDebugText(buf, "GRF order changed: %08X moved %d places %s",
+ BSWAP32(lc->grfmove.grfid), abs(lc->grfmove.offset), lc->grfmove.offset >= 0 ? "down" : "up" );
+ PrintGrfFilename(buf, lc->grfmove.grfid);
+ break;
+ }
+
+ proc(buf);
+ }
+ }
+
+ proc("---- gamelog end ----");
+}
+
+
+static void GamelogPrintConsoleProc(const char *s)
+{
+ IConsolePrint(CC_WARNING, s);
+}
+
+void GamelogPrintConsole()
+{
+ GamelogPrint(&GamelogPrintConsoleProc);
+}
+
+
+static void GamelogPrintDebugProc(const char *s)
+{
+ debug_print("gamelog", s);
+}
+
+void GamelogPrintDebug()
+{
+ GamelogPrint(&GamelogPrintDebugProc);
+}
+
+
+/** Allocates new LoggedChange and new LoggedAction if needed.
+ * If there is no action active, NULL is returned.
+ * @param ct type of change
+ * @return new LoggedChange, or NULL if there is no action active
+ */
+static LoggedChange *GamelogChange(GamelogChangeType ct)
+{
+ if (_current_action == NULL) {
+ if (_gamelog_action_type == GLAT_NONE) return NULL;
+
+ _gamelog_action = ReallocT(_gamelog_action, _gamelog_actions + 1);
+ _current_action = &_gamelog_action[_gamelog_actions++];
+
+ _current_action->at = _gamelog_action_type;
+ _current_action->tick = _tick_counter;
+ _current_action->change = NULL;
+ _current_action->changes = 0;
+ }
+
+ _current_action->change = ReallocT(_current_action->change, _current_action->changes + 1);
+
+ LoggedChange *lc = &_current_action->change[_current_action->changes++];
+ lc->ct = ct;
+
+ return lc;
+}
+
+
+/** Logs a change in game revision
+ * @param revision new revision string
+ */
+void GamelogRevision()
+{
+ assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
+
+ LoggedChange *lc = GamelogChange(GLCT_REVISION);
+ if (lc == NULL) return;
+
+ strncpy(lc->revision.text, _openttd_revision, lengthof(lc->revision.text));
+ lc->revision.slver = SAVEGAME_VERSION;
+ lc->revision.modified = _openttd_revision_modified;
+ lc->revision.newgrf = _openttd_newgrf_version;
+}
+
+/** Logs a change in game mode (scenario editor or game)
+ */
+void GamelogMode()
+{
+ assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_CHEAT);
+
+ LoggedChange *lc = GamelogChange(GLCT_MODE);
+ if (lc == NULL) return;
+
+ lc->mode.mode = _game_mode;
+ lc->mode.landscape = _settings_game.game_creation.landscape;
+}
+
+/** Logs loading from savegame without gamelog
+ */
+void GamelogOldver()
+{
+ assert(_gamelog_action_type == GLAT_LOAD);
+
+ LoggedChange *lc = GamelogChange(GLCT_OLDVER);
+ if (lc == NULL) return;
+
+ lc->oldver.type = _savegame_type;
+ lc->oldver.version = (_savegame_type == SGT_OTTD ? ((uint32)_sl_version << 8 | _sl_minor_version) : _ttdp_version);
+}
+
+/** Logs change in game patches. Only non-networksafe patches are logged
+ * @param name patch name
+ * @param oldval old patch value
+ * @param newval new patch value
+ */
+void GamelogPatch(const char *name, int32 oldval, int32 newval)
+{
+ assert(_gamelog_action_type == GLAT_PATCH);
+
+ LoggedChange *lc = GamelogChange(GLCT_PATCH);
+ if (lc == NULL) return;
+
+ lc->patch.name = strdup(name);
+ lc->patch.oldval = oldval;
+ lc->patch.newval = newval;
+}
+
+
+/** Finds out if current revision is different than last revision stored in the savegame.
+ * Appends GLCT_REVISION when the revision string changed
+ */
+void GamelogTestRevision()
+{
+ const LoggedChange *rev = NULL;
+
+ const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+ for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+ const LoggedChange *lcend = &la->change[la->changes];
+ for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+ if (lc->ct == GLCT_REVISION) rev = lc;
+ }
+ }
+
+ if (rev == NULL || strcmp(rev->revision.text, _openttd_revision) != 0 ||
+ rev->revision.modified != _openttd_revision_modified ||
+ rev->revision.newgrf != _openttd_newgrf_version) {
+ GamelogRevision();
+ }
+}
+
+/** Finds last stored game mode or landscape.
+ * Any change is logged
+ */
+void GamelogTestMode()
+{
+ const LoggedChange *mode = NULL;
+
+ const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+ for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+ const LoggedChange *lcend = &la->change[la->changes];
+ for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+ if (lc->ct == GLCT_MODE) mode = lc;
+ }
+ }
+
+ if (mode == NULL || mode->mode.mode != _game_mode || mode->mode.landscape != _settings_game.game_creation.landscape) GamelogMode();
+}
+
+
+/** Decides if GRF should be logged
+ * @param g grf to determine
+ * @return true iff GRF is not static and is loaded
+ */
+static inline bool IsLoggableGrfConfig(const GRFConfig *g)
+{
+ return !HasBit(g->flags, GCF_STATIC) && g->status != GCS_NOT_FOUND;
+}
+
+/** Logs removal of a GRF
+ * @param grfid ID of removed GRF
+ */
+void GamelogGRFRemove(uint32 grfid)
+{
+ assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_GRF);
+
+ LoggedChange *lc = GamelogChange(GLCT_GRFREM);
+ if (lc == NULL) return;
+
+ lc->grfrem.grfid = grfid;
+}
+
+/** Logs adding of a GRF
+ * @param newg added GRF
+ */
+void GamelogGRFAdd(const GRFConfig *newg)
+{
+ assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_GRF);
+
+ if (!IsLoggableGrfConfig(newg)) return;
+
+ LoggedChange *lc = GamelogChange(GLCT_GRFADD);
+ if (lc == NULL) return;
+
+ memcpy(&lc->grfadd, newg, sizeof(GRFIdentifier));
+}
+
+/** Logs loading compatible GRF
+ * (the same ID, but different MD5 hash)
+ * @param newg new (updated) GRF
+ */
+void GamelogGRFCompatible(const GRFIdentifier *newg)
+{
+ assert(_gamelog_action_type == GLAT_LOAD);
+
+ LoggedChange *lc = GamelogChange(GLCT_GRFCOMPAT);
+ if (lc == NULL) return;
+
+ memcpy(&lc->grfcompat, newg, sizeof(GRFIdentifier));
+}
+
+/** Logs changing GRF order
+ * @param grfid GRF that is moved
+ * @param offset how far it is moved, positive = moved down
+ */
+static void GamelogGRFMove(uint32 grfid, int32 offset)
+{
+ assert(_gamelog_action_type == GLAT_GRF);
+
+ LoggedChange *lc = GamelogChange(GLCT_GRFMOVE);
+ if (lc == NULL) return;
+
+ lc->grfmove.grfid = grfid;
+ lc->grfmove.offset = offset;
+}
+
+/** Logs change in GRF parameters.
+ * Details about parameters changed are not stored
+ * @param grfid ID of GRF to store
+ */
+static void GamelogGRFParameters(uint32 grfid)
+{
+ assert(_gamelog_action_type == GLAT_GRF);
+
+ LoggedChange *lc = GamelogChange(GLCT_GRFPARAM);
+ if (lc == NULL) return;
+
+ lc->grfparam.grfid = grfid;
+}
+
+/** Logs adding of list of GRFs.
+ * Useful when old savegame is loaded or when new game is started
+ * @param newg head of GRF linked list
+ */
+void GamelogGRFAddList(const GRFConfig *newg)
+{
+ assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
+
+ for (; newg != NULL; newg = newg->next) {
+ GamelogGRFAdd(newg);
+ }
+}
+
+/** List of GRFs using array of pointers instead of linked list */
+struct GRFList {
+ uint n;
+ const GRFConfig *grf[VARARRAY_SIZE];
+};
+
+/** Generates GRFList
+ * @param grfc head of GRF linked list
+ */
+static GRFList *GenerateGRFList(const GRFConfig *grfc)
+{
+ uint n = 0;
+ for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
+ if (IsLoggableGrfConfig(g)) n++;
+ }
+
+ GRFList *list = (GRFList*)MallocT<byte>(sizeof(GRFList) + n * sizeof(GRFConfig*));
+
+ list->n = 0;
+ for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
+ if (IsLoggableGrfConfig(g)) list->grf[list->n++] = g;
+ }
+
+ return list;
+}
+
+/** Compares two NewGRF lists and logs any change
+ * @param oldc original GRF list
+ * @param newc new GRF list
+ */
+void GamelogGRFUpdate(const GRFConfig *oldc, const GRFConfig *newc)
+{
+ GRFList *ol = GenerateGRFList(oldc);
+ GRFList *nl = GenerateGRFList(newc);
+
+ uint o = 0, n = 0;
+
+ while (o < ol->n && n < nl->n) {
+ const GRFConfig *og = ol->grf[o];
+ const GRFConfig *ng = nl->grf[n];
+
+ if (og->grfid != ng->grfid) {
+ uint oi, ni;
+ for (oi = 0; oi < ol->n; oi++) {
+ if (ol->grf[oi]->grfid == nl->grf[n]->grfid) break;
+ }
+ if (oi < o) {
+ /* GRF was moved, this change has been logged already */
+ n++;
+ continue;
+ }
+ if (oi == ol->n) {
+ /* GRF couldn't be found in the OLD list, GRF was ADDED */
+ GamelogGRFAdd(nl->grf[n++]);
+ continue;
+ }
+ for (ni = 0; ni < nl->n; ni++) {
+ if (nl->grf[ni]->grfid == ol->grf[o]->grfid) break;
+ }
+ if (ni < n) {
+ /* GRF was moved, this change has been logged already */
+ o++;
+ continue;
+ }
+ if (ni == nl->n) {
+ /* GRF couldn't be found in the NEW list, GRF was REMOVED */
+ GamelogGRFRemove(ol->grf[o++]->grfid);
+ continue;
+ }
+
+ /* o < oi < ol->n
+ * n < ni < nl->n */
+ assert(ni > n && ni < nl->n);
+ assert(oi > o && oi < ol->n);
+
+ ni -= n; // number of GRFs it was moved downwards
+ oi -= o; // number of GRFs it was moved upwards
+
+ if (ni >= oi) { // prefer the one that is moved further
+ /* GRF was moved down */
+ GamelogGRFMove(ol->grf[o++]->grfid, ni);
+ } else {
+ GamelogGRFMove(nl->grf[n++]->grfid, -(int)oi);
+ }
+ } else {
+ if (memcmp(og->md5sum, ng->md5sum, sizeof(og->md5sum)) != 0) {
+ /* md5sum changed, probably loading 'compatible' GRF */
+ GamelogGRFCompatible(nl->grf[n]);
+ }
+
+ if (og->num_params != ng->num_params || memcmp(og->param, ng->param, og->num_params * sizeof(og->param[0])) != 0) {
+ GamelogGRFParameters(ol->grf[o]->grfid);
+ }
+
+ o++;
+ n++;
+ }
+ }
+
+ while (o < ol->n) GamelogGRFRemove(ol->grf[o++]->grfid); // remaining GRFs were removed ...
+ while (n < nl->n) GamelogGRFAdd (nl->grf[n++]); // ... or added
+
+ free(ol);
+ free(nl);
+}
+
+
+static const SaveLoad _glog_action_desc[] = {
+ SLE_VAR(LoggedAction, tick, SLE_UINT16),
+ SLE_END()
+};
+
+static const SaveLoad _glog_mode_desc[] = {
+ SLE_VAR(LoggedChange, mode.mode, SLE_UINT8),
+ SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8),
+ SLE_END()
+};
+
+static const SaveLoad _glog_revision_desc[] = {
+ SLE_ARR(LoggedChange, revision.text, SLE_UINT8, NETWORK_REVISION_LENGTH),
+ SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32),
+ SLE_VAR(LoggedChange, revision.slver, SLE_UINT16),
+ SLE_VAR(LoggedChange, revision.modified, SLE_UINT8),
+ SLE_END()
+};
+
+static const SaveLoad _glog_oldver_desc[] = {
+ SLE_VAR(LoggedChange, oldver.type, SLE_UINT32),
+ SLE_VAR(LoggedChange, oldver.version, SLE_UINT32),
+ SLE_END()
+};
+
+static const SaveLoad _glog_patch_desc[] = {
+ SLE_STR(LoggedChange, patch.name, SLE_STR, 128),
+ SLE_VAR(LoggedChange, patch.oldval, SLE_INT32),
+ SLE_VAR(LoggedChange, patch.newval, SLE_INT32),
+ SLE_END()
+};
+
+static const SaveLoad _glog_grfadd_desc[] = {
+ SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ),
+ SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16),
+ SLE_END()
+};
+
+static const SaveLoad _glog_grfrem_desc[] = {
+ SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32),
+ SLE_END()
+};
+
+static const SaveLoad _glog_grfcompat_desc[] = {
+ SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ),
+ SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16),
+ SLE_END()
+};
+
+static const SaveLoad _glog_grfparam_desc[] = {
+ SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32),
+ SLE_END()
+};
+
+static const SaveLoad _glog_grfmove_desc[] = {
+ SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32),
+ SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32),
+ SLE_END()
+};
+
+static const SaveLoad *_glog_desc[] = {
+ _glog_mode_desc,
+ _glog_revision_desc,
+ _glog_oldver_desc,
+ _glog_patch_desc,
+ _glog_grfadd_desc,
+ _glog_grfrem_desc,
+ _glog_grfcompat_desc,
+ _glog_grfparam_desc,
+ _glog_grfmove_desc
+};
+
+assert_compile(lengthof(_glog_desc) == GLCT_END);
+
+static void Load_GLOG()
+{
+ assert(_gamelog_action == NULL);
+ assert(_gamelog_actions == 0);
+
+ GamelogActionType at;
+ while ((at = (GamelogActionType)SlReadByte()) != GLAT_NONE) {
+ _gamelog_action = ReallocT(_gamelog_action, _gamelog_actions + 1);
+ LoggedAction *la = &_gamelog_action[_gamelog_actions++];
+
+ la->at = at;
+
+ SlObject(la, _glog_action_desc); // has to be saved after 'DATE'!
+ la->change = NULL;
+ la->changes = 0;
+
+ GamelogChangeType ct;
+ while ((ct = (GamelogChangeType)SlReadByte()) != GLCT_NONE) {
+ la->change = ReallocT(la->change, la->changes + 1);
+
+ LoggedChange *lc = &la->change[la->changes++];
+ lc->ct = ct;
+
+ assert((uint)ct < GLCT_END);
+
+ SlObject(lc, _glog_desc[ct]);
+ }
+ }
+}
+
+static void Save_GLOG()
+{
+ const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+ size_t length = 0;
+
+ for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+ const LoggedChange *lcend = &la->change[la->changes];
+ for (LoggedChange *lc = la->change; lc != lcend; lc++) {
+ assert((uint)lc->ct < lengthof(_glog_desc));
+ length += SlCalcObjLength(lc, _glog_desc[lc->ct]) + 1;
+ }
+ length += 4;
+ }
+ length++;
+
+ SlSetLength(length);
+
+ for (LoggedAction *la = _gamelog_action; la != laend; la++) {
+ SlWriteByte(la->at);
+ SlObject(la, _glog_action_desc);
+
+ const LoggedChange *lcend = &la->change[la->changes];
+ for (LoggedChange *lc = la->change; lc != lcend; lc++) {
+ SlWriteByte(lc->ct);
+ assert((uint)lc->ct < GLCT_END);
+ SlObject(lc, _glog_desc[lc->ct]);
+ }
+ SlWriteByte(GLCT_NONE);
+ }
+ SlWriteByte(GLAT_NONE);
+}
+
+
+extern const ChunkHandler _gamelog_chunk_handlers[] = {
+ { 'GLOG', Save_GLOG, Load_GLOG, CH_RIFF | CH_LAST }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gamelog.h Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,46 @@
+/* $Id$ */
+
+/** @file gamelog.h Functions to be called to log possibly unsafe game events */
+
+#ifndef GAMELOG_H
+#define GAMELOG_H
+
+#include "newgrf_config.h"
+
+enum GamelogActionType {
+ GLAT_START, ///< Game created
+ GLAT_LOAD, ///< Game loaded
+ GLAT_GRF, ///< GRF changed
+ GLAT_CHEAT, ///< Cheat was used
+ GLAT_PATCH, ///< Patches setting changed
+ GLAT_END, ///< So we know how many GLATs are there
+ GLAT_NONE = 0xFF, ///< No logging active; in savegames, end of list
+};
+
+void GamelogStartAction(GamelogActionType at);
+void GamelogStopAction();
+
+void GamelogReset();
+
+typedef void GamelogPrintProc(const char *s);
+void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 / WINCE crash.log
+
+void GamelogPrintDebug();
+void GamelogPrintConsole();
+
+void GamelogRevision();
+void GamelogMode();
+void GamelogOldver();
+void GamelogPatch(const char *name, int32 oldval, int32 newval);
+
+void GamelogGRFUpdate(const GRFConfig *oldg, const GRFConfig *newg);
+void GamelogGRFAddList(const GRFConfig *newg);
+void GamelogGRFRemove(uint32 grfid);
+void GamelogGRFAdd(const GRFConfig *newg);
+void GamelogGRFCompatible(const GRFIdentifier *newg);
+
+void GamelogTestRevision();
+void GamelogTestMode();
+void GamelogTestGRF();
+
+#endif /* GAMELOG_H */
--- a/src/gfxinit.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/gfxinit.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -71,12 +71,8 @@
uint end = *index_tbl++;
do {
- #ifdef NDEBUG
- LoadNextSprite(start, file_index, *sprite_id);
- #else
bool b = LoadNextSprite(start, file_index, *sprite_id);
assert(b);
- #endif
(*sprite_id)++;
} while (++start <= end);
}
--- a/src/industry_cmd.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/industry_cmd.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -334,6 +334,20 @@
static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
{
+ IndustryGfx gfx = GetIndustryGfx(tile);
+
+ /* For NewGRF industry tiles we might not be drawing a foundation. We need to
+ * account for this, otherwise we might be applying a FOUNDATION_LEVELED
+ * on a steep slope which is not allowed. Furthermore other structures should
+ * draw the wall of the foundation in this case.
+ */
+ if (gfx >= NEW_INDUSTRYTILEOFFSET) {
+ const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
+ if (indts->grf_prop.spritegroup != NULL && HasBit(indts->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
+ uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, GetIndustryByTile(tile), tile);
+ if (callback_res == 0) return FOUNDATION_NONE;
+ }
+ }
return FlatteningFoundation(tileh);
}
@@ -981,7 +995,7 @@
if (!IsIndustryCompleted(tile)) return; ///< Can't proceed if not completed
- if (CircularTileSearch(tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles to search
+ if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles to search
i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo
}
--- a/src/main_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/main_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -35,9 +35,7 @@
#include "tilehighlight_func.h"
#include "network/network.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_server.h"
+#include "network/network_func.h"
#include "network/network_gui.h"
#include "table/sprites.h"
@@ -56,9 +54,9 @@
snprintf(msg, sizeof(msg), "%d", p1);
if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
+ NetworkClientSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
} else {
- NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
+ NetworkServerSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
}
#endif /* ENABLE_NETWORK */
}
--- a/src/map.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/map.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -258,7 +258,7 @@
* Although it really is a square search...
* Every tile will be tested by means of the callback function proc,
* which will determine if yes or no the given tile meets criteria of search.
- * @param tile to start the search from
+ * @param tile to start the search from. Upon completion, it will return the tile matching the search
* @param size: number of tiles per side of the desired search area
* @param proc: callback testing function pointer.
* @param data to be passed to the callback function. Depends on the implementation
@@ -266,7 +266,7 @@
* @pre proc != NULL
* @pre size > 0
*/
-bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data)
+bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, uint32 data)
{
uint n, x, y;
DiagDirection dir;
@@ -274,14 +274,17 @@
assert(proc != NULL);
assert(size > 0);
- x = TileX(tile);
- y = TileY(tile);
+ x = TileX(*tile);
+ y = TileY(*tile);
if (size % 2 == 1) {
/* If the length of the side is uneven, the center has to be checked
* separately, as the pattern of uneven sides requires to go around the center */
n = 2;
- if (proc(TileXY(x, y), data)) return true;
+ if (proc(TileXY(x, y), data)) {
+ *tile = TileXY(x, y);
+ return true;
+ }
/* If tile test is not successful, get one tile down and left,
* ready for a test in first circle around center tile */
@@ -302,6 +305,7 @@
for (j = n; j != 0; j--) {
if (x <= MapMaxX() && y <= MapMaxY() && ///< Is the tile within the map?
proc(TileXY(x, y), data)) { ///< Is the callback successful?
+ *tile = TileXY(x, y);
return true; ///< then stop the search
}
@@ -314,5 +318,7 @@
x += _tileoffs_by_dir[DIR_W].x;
y += _tileoffs_by_dir[DIR_W].y;
}
+
+ *tile = INVALID_TILE;
return false;
}
--- a/src/map_func.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/map_func.h Wed Jun 04 22:34:45 2008 +0000
@@ -391,7 +391,7 @@
/**
* Searches for some cirumstances of a tile around a given tile with a helper function.
*/
-bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data);
+bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, uint32 data);
/**
* Get a random tile out of a given seed.
--- a/src/misc.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -25,6 +25,7 @@
#include "texteff.hpp"
#include "gfx_func.h"
#include "core/alloc_type.hpp"
+#include "gamelog.h"
#include "animated_tile_func.h"
#include "settings_type.h"
#include "tilehighlight_func.h"
@@ -110,6 +111,13 @@
InitializeLandscapeVariables(false);
ResetObjectToPlace();
+
+ GamelogReset();
+ GamelogStartAction(GLAT_START);
+ GamelogRevision();
+ GamelogMode();
+ GamelogGRFAddList(_grfconfig);
+ GamelogStopAction();
}
--- a/src/misc/smallvec.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc/smallvec.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,9 @@
#ifndef SMALLVEC_H
#define SMALLVEC_H
+#include "../core/alloc_func.hpp"
+#include "../core/math_func.hpp"
+
template <typename T, uint S>
struct SmallVector {
T *data;
--- a/src/misc_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -50,7 +50,6 @@
#include "table/strings.h"
/* Variables to display file lists */
-FiosItem *_fios_list;
SaveLoadDialogMode _saveload_mode;
@@ -1300,11 +1299,11 @@
case SLD_NEW_GAME:
case SLD_LOAD_SCENARIO:
case SLD_SAVE_SCENARIO:
- _fios_list = FiosGetScenarioList(_saveload_mode); break;
+ FiosGetScenarioList(_saveload_mode); break;
case SLD_LOAD_HEIGHTMAP:
- _fios_list = FiosGetHeightmapList(_saveload_mode); break;
+ FiosGetHeightmapList(_saveload_mode); break;
- default: _fios_list = FiosGetSavegameList(_saveload_mode); break;
+ default: FiosGetSavegameList(_saveload_mode); break;
}
}
@@ -1333,8 +1332,8 @@
* Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE)
* Only sort savegames/scenarios, not directories
*/
- for (int i = 0; i < _fios_num; i++) {
- switch (_fios_list[i].type) {
+ for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
+ switch (item->type) {
case FIOS_TYPE_DIR: sort_start++; break;
case FIOS_TYPE_PARENT: sort_start++; break;
case FIOS_TYPE_DRIVE: sort_end++; break;
@@ -1342,9 +1341,9 @@
}
}
- uint s_amount = _fios_num - sort_start - sort_end;
+ uint s_amount = _fios_items.Length() - sort_start - sort_end;
if (s_amount > 0) {
- qsort(_fios_list + sort_start, s_amount, sizeof(FiosItem), compare_FiosItems);
+ qsort(_fios_items.Get(sort_start), s_amount, sizeof(FiosItem), compare_FiosItems);
}
}
@@ -1443,10 +1442,9 @@
virtual void OnPaint()
{
- int pos;
int y;
- SetVScrollCount(this, _fios_num);
+ SetVScrollCount(this, _fios_items.Length());
this->DrawWidgets();
DrawFiosTexts(this->width);
@@ -1459,8 +1457,8 @@
this->DrawSortButtonState(_savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
y = this->widget[7].top + 1;
- for (pos = this->vscroll.pos; pos < _fios_num; pos++) {
- const FiosItem *item = _fios_list + pos;
+ for (uint pos = this->vscroll.pos; pos < _fios_items.Length(); pos++) {
+ const FiosItem *item = _fios_items.Get(pos);
DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], this->width - 18);
y += 10;
@@ -1497,14 +1495,12 @@
case 7: { // Click the listbox
int y = (pt.y - this->widget[widget].top - 1) / 10;
- char *name;
- const FiosItem *file;
if (y < 0 || (y += this->vscroll.pos) >= this->vscroll.count) return;
- file = _fios_list + y;
+ const FiosItem *file = _fios_items.Get(y);
- name = FiosBrowseTo(file);
+ char *name = FiosBrowseTo(file);
if (name != NULL) {
if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
_switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
--- a/src/network/core/config.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/config.h Wed Jun 04 22:34:45 2008 +0000
@@ -1,14 +1,12 @@
/* $Id$ */
/**
- * @file config.h Configuration options of the network stuff
+ * @file config.h Configuration options of the network stuff. It is used even when compiling without network support.
*/
#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 */
@@ -54,6 +52,4 @@
NETWORK_NUM_LANDSCAPES = 4,
};
-#endif /* ENABLE_NETWORK */
-
#endif /* NETWORK_CORE_CONFIG_H */
--- a/src/network/core/core.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/core.h Wed Jun 04 22:34:45 2008 +0000
@@ -62,7 +62,7 @@
* Whether this socket is currently bound to a socket.
* @return true when the socket is bound, false otherwise
*/
- bool IsConnected() { return this->sock != INVALID_SOCKET; }
+ bool IsConnected() const { return this->sock != INVALID_SOCKET; }
/**
* Whether the current client connected to the socket has quit.
@@ -70,7 +70,7 @@
* data), the socket in not closed; only the packet is dropped.
* @return true when the current client has quit, false otherwise
*/
- bool HasClientQuit() { return this->has_quit; }
+ bool HasClientQuit() const { return this->has_quit; }
void Send_GRFIdentifier(Packet *p, const GRFIdentifier *grf);
void Recv_GRFIdentifier(Packet *p, GRFIdentifier *grf);
--- a/src/network/core/game.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/game.h Wed Jun 04 22:34:45 2008 +0000
@@ -19,7 +19,13 @@
* some fields will be empty on the client (like game_password) by default
* and only filled with data a player enters.
*/
-struct NetworkGameInfo {
+struct NetworkServerGameInfo {
+ byte clients_on; ///< Current count of clients on server
+ Date start_date; ///< When the game started
+ char map_name[NETWORK_NAME_LENGTH]; ///< Map which is played ["random" for a randomized map]
+};
+
+struct NetworkGameInfo : NetworkServerGameInfo {
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)
@@ -28,21 +34,16 @@
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)
bool use_password; ///< Is this server passworded?
- 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 companies_max; ///< Max companies allowed on server
byte spectators_on; ///< How many spectators do we have?
+ byte spectators_max; ///< Max spectators allowed on server
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
GRFConfig *grfconfig; ///< List of NewGRF files used
};
--- a/src/network/core/tcp.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/tcp.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -11,7 +11,7 @@
#include "../../openttd.h"
#include "../../variables.h"
-#include "../network_data.h"
+#include "../network_internal.h"
#include "packet.h"
#include "tcp.h"
--- a/src/network/network.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -3,7 +3,7 @@
/** @file network.cpp Base functions for networking support. */
#include "../stdafx.h"
-#include "network_data.h"
+#include "../player_type.h"
#ifdef ENABLE_NETWORK
@@ -15,6 +15,7 @@
#include "../variables.h"
#include "../date_func.h"
#include "../newgrf_config.h"
+#include "network_internal.h"
#include "network_client.h"
#include "network_server.h"
#include "network_udp.h"
@@ -38,7 +39,6 @@
#ifdef DEBUG_DUMP_COMMANDS
#include "../core/alloc_func.hpp"
#endif /* DEBUG_DUMP_COMMANDS */
-
#include "table/strings.h"
bool _network_reload_cfg;
@@ -46,6 +46,29 @@
bool _network_available; ///< is network mode available?
bool _network_dedicated; ///< are we a dedicated server?
bool _network_advertise; ///< is the server advertising to the master server?
+bool _is_network_server; ///< Does this client wants to be a network-server?
+NetworkServerGameInfo _network_game_info;
+NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
+NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
+uint16 _network_own_client_index;
+uint16 _redirect_console_to_client;
+bool _network_need_advertise;
+uint32 _network_last_advertise_frame;
+uint8 _network_reconnect;
+char *_network_host_list[10];
+char *_network_ban_list[25];
+uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
+uint32 _frame_counter_max; // To where we may go with our clients
+uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
+uint32 _broadcast_list[MAX_INTERFACES + 1];
+uint32 _network_server_bind_ip;
+uint32 _sync_seed_1, _sync_seed_2;
+uint32 _sync_frame;
+bool _network_first_time;
+uint32 _network_last_host_ip;
+bool _network_udp_server;
+uint16 _network_udp_broadcast;
+uint8 _network_advertise_retries;
/* Check whether NETWORK_NUM_LANDSCAPES is still in sync with NUM_LANDSCAPE */
assert_compile((int)NETWORK_NUM_LANDSCAPES == (int)NUM_LANDSCAPE);
@@ -216,8 +239,8 @@
// 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);
+ if (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq < _frame_counter)
+ lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq);
return lag;
}
@@ -332,18 +355,18 @@
{
if (!_network_dedicated) return;
- if (NetworkCountPlayers() < _network_min_players) {
+ if (NetworkCountPlayers() < _settings_client.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);
+ NetworkServerSendChat(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);
+ NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
}
}
@@ -601,7 +624,7 @@
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;
+ if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL;
// Register the login
client_no = _network_clients_connected++;
@@ -662,9 +685,9 @@
}
/* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
- if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
+ if (cs->status == STATUS_PRE_ACTIVE && _settings_client.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);
+ NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
}
cs->Destroy();
@@ -802,7 +825,7 @@
SOCKET ls;
struct sockaddr_in sin;
- DEBUG(net, 1, "Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
+ DEBUG(net, 1, "Listening on %s:%d", _settings_client.network.server_bind_ip, _settings_client.network.server_port);
ls = socket(AF_INET, SOCK_STREAM, 0);
if (ls == INVALID_SOCKET) {
@@ -823,7 +846,7 @@
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = _network_server_bind_ip;
- sin.sin_port = htons(_network_server_port);
+ sin.sin_port = htons(_settings_client.network.server_port);
if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
ServerStartError("bind() failed");
@@ -854,12 +877,22 @@
}
if (_network_server) {
- // We are a server, also close the listensocket
+ /* We are a server, also close the listensocket */
closesocket(_listensocket);
_listensocket = INVALID_SOCKET;
DEBUG(net, 1, "Closed listener");
- NetworkUDPCloseAll();
}
+ NetworkUDPCloseAll();
+
+ /* 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;
}
// Inits the network (cleans sockets and stuff)
@@ -923,7 +956,7 @@
ttd_strlcpy(host, b, lengthof(host));
- ttd_strlcpy(_network_default_ip, b, lengthof(_network_default_ip));
+ ttd_strlcpy(_settings_client.network.connect_to_ip, b, lengthof(_settings_client.network.connect_to_ip));
rport = NETWORK_DEFAULT_PORT;
ParseConnectionString(&player, &port, host);
@@ -961,11 +994,10 @@
if (port == 0) return false;
- ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
- _network_last_port = port;
+ ttd_strlcpy(_settings_client.network.last_host, host, sizeof(_settings_client.network.last_host));
+ _settings_client.network.last_port = port;
NetworkDisconnect();
- NetworkUDPCloseAll();
NetworkInitialize();
// Try to connect
@@ -987,34 +1019,13 @@
{
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;
+ if (StrEmpty(_settings_client.network.server_name)) {
+ snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server");
}
- _network_game_info.spectators_on = 0;
-
- _network_game_info.game_date = _date;
+ /* The server is a client too */
+ _network_game_info.clients_on = _network_dedicated ? 0 : 1;
_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
- _network_game_info.map_width = MapSizeX();
- _network_game_info.map_height = MapSizeY();
- _network_game_info.map_set = _settings_game.game_creation.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)
@@ -1024,8 +1035,8 @@
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));
+ ttd_strlcpy(ci->client_name, _settings_client.network.player_name, sizeof(ci->client_name));
+ ttd_strlcpy(ci->unique_id, _settings_client.network.network_id, sizeof(ci->unique_id));
}
bool NetworkServerStart()
@@ -1041,7 +1052,7 @@
// Try to start UDP-server
_network_udp_server = true;
- _network_udp_server = _udp_server_socket->Listen(_network_server_bind_ip, _network_server_port, false);
+ _network_udp_server = _udp_server_socket->Listen(_network_server_bind_ip, _settings_client.network.server_port, false);
_network_server = true;
_networking = true;
@@ -1086,16 +1097,6 @@
}
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
@@ -1114,16 +1115,6 @@
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
@@ -1332,7 +1323,7 @@
_frame_counter++;
// Update max-frame-counter
if (_frame_counter > _frame_counter_max) {
- _frame_counter_max = _frame_counter + _network_frame_freq;
+ _frame_counter_max = _frame_counter + _settings_client.network.frame_freq;
send_frame = true;
}
@@ -1382,7 +1373,7 @@
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);
+ snprintf(_settings_client.network.network_id, sizeof(_settings_client.network.network_id), "%s", hex_output);
}
void NetworkStartDebugLog(const char *hostname, uint16 port)
@@ -1429,26 +1420,14 @@
_network_advertise_retries = 0;
/* Load the ip from the openttd.cfg */
- _network_server_bind_ip = inet_addr(_network_server_bind_ip_host);
+ _network_server_bind_ip = inet_addr(_settings_client.network.server_bind_ip);
/* 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));
+ snprintf(_settings_client.network.server_bind_ip, sizeof(_settings_client.network.server_bind_ip), "%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();
+ if (StrEmpty(_settings_client.network.network_id)) 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;
- byte s_lang = _network_game_info.server_lang;
-
- 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;
- _network_game_info.server_lang = s_lang;
- }
-
+ memset(&_network_game_info, 0, sizeof(_network_game_info));
NetworkInitialize();
DEBUG(net, 3, "[core] network online, multiplayer available");
--- a/src/network/network.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network.h Wed Jun 04 22:34:45 2008 +0000
@@ -17,7 +17,7 @@
extern bool _network_available; ///< is network mode available?
extern bool _network_dedicated; ///< are we a dedicated server?
extern bool _network_advertise; ///< is the server advertising to the master server?
-extern bool _network_reload_cfg; ///< will we reload the entire config for the next game?
+extern bool _is_network_server; ///< Does this client wants to be a network-server?
#else /* ENABLE_NETWORK */
/* Network function stubs when networking is disabled */
@@ -30,6 +30,7 @@
#define _network_available 0
#define _network_dedicated 0
#define _network_advertise 0
+#define _is_network_server 0
#endif /* ENABLE_NETWORK */
--- a/src/network/network_client.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_client.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -7,7 +7,7 @@
#include "../stdafx.h"
#include "../debug.h"
#include "../openttd.h"
-#include "network_data.h"
+#include "network_internal.h"
#include "core/tcp.h"
#include "network_client.h"
#include "network_gamelist.h"
@@ -84,7 +84,7 @@
if (StrEmpty(_network_player_info[_local_player].password)) return;
_password_game_seed = _settings_game.game_creation.generation_seed;
- ttd_strlcpy(_password_server_unique_id, _network_unique_id, sizeof(_password_server_unique_id));
+ ttd_strlcpy(_password_server_unique_id, _settings_client.network.network_id, sizeof(_password_server_unique_id));
const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password);
ttd_strlcpy(_network_player_info[_local_player].password, new_pw, sizeof(_network_player_info[_local_player].password));
@@ -131,10 +131,10 @@
p = NetworkSend_Init(PACKET_CLIENT_JOIN);
p->Send_string(_openttd_revision);
- p->Send_string(_network_player_name); // Player name
+ p->Send_string(_settings_client.network.player_name); // Player name
p->Send_uint8 (_network_playas); // PlayAs
p->Send_uint8 (NETLANG_ANY); // Language
- p->Send_string(_network_unique_id);
+ p->Send_string(_settings_client.network.network_id);
MY_CLIENT->Send_Packet(p);
}
@@ -938,4 +938,39 @@
return res;
}
+void NetworkClientSendRcon(const char *password, const char *command)
+{
+ SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
+}
+
+void NetworkUpdatePlayerName()
+{
+ NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
+
+ if (ci == NULL) return;
+
+ /* Don't change the name if it is the same as the old name */
+ if (strcmp(ci->client_name, _settings_client.network.player_name) != 0) {
+ if (!_network_server) {
+ SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_settings_client.network.player_name);
+ } else {
+ if (NetworkFindName(_settings_client.network.player_name)) {
+ NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _settings_client.network.player_name);
+ ttd_strlcpy(ci->client_name, _settings_client.network.player_name, sizeof(ci->client_name));
+ NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+ }
+ }
+ }
+}
+
+void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg)
+{
+ SEND_COMMAND(PACKET_CLIENT_CHAT)(action, type, dest, msg);
+}
+
+void NetworkClientSetPassword()
+{
+ SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
+}
+
#endif /* ENABLE_NETWORK */
--- a/src/network/network_data.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_data.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -6,7 +6,7 @@
#include "../stdafx.h"
#include "../debug.h"
-#include "network_data.h"
+#include "network_internal.h"
#include "network_client.h"
#include "../command_func.h"
#include "../callback_table.h"
--- a/src/network/network_data.h Mon Jun 02 01:46:03 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/* $Id$ */
-
-/** @file network_data.h Internal functions. */
-
-#ifndef NETWORK_DATA_H
-#define NETWORK_DATA_H
-
-#include "../openttd.h"
-#include "../console_type.h"
-#include "network.h"
-#include "network_internal.h"
-
-// Is the network enabled?
-#ifdef ENABLE_NETWORK
-
-#include "core/os_abstraction.h"
-#include "core/core.h"
-#include "core/config.h"
-#include "core/packet.h"
-#include "core/tcp.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
-
-enum MapPacket {
- MAP_PACKET_START,
- MAP_PACKET_NORMAL,
- MAP_PACKET_END,
-};
-
-enum NetworkErrorCode {
- 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,
- NETWORK_ERROR_NEWGRF_MISMATCH,
-
- // 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,
-};
-
-// Actions that can be used for NetworkTextMessage
-enum NetworkAction {
- 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,
-};
-
-enum NetworkPasswordType {
- NETWORK_GAME_PASSWORD,
- NETWORK_COMPANY_PASSWORD,
-};
-
-enum DestType {
- 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)
-};
-
-// following externs are instantiated at network.cpp
-extern CommandPacket *_local_command_queue;
-
-// Here we keep track of the clients
-// (and the client uses [0] for his own communication)
-extern NetworkTCPSocketHandler _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()
-#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkTCPSocketHandler *cs, Packet *p)
-#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkTCPSocketHandler *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->IsConnected(); 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(NetworkTCPSocketHandler *cs, CommandPacket *cp);
-
-// from network.c
-void NetworkCloseClient(NetworkTCPSocketHandler *cs);
-void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
-void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
-uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
-byte NetworkGetCurrentLanguageIndex();
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
-NetworkTCPSocketHandler *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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/network_func.h Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,63 @@
+/* $Id$ */
+
+/** @file network_internal.h Variables and function used internally. */
+
+#ifndef NETWORK_FUNC_H
+#define NETWORK_FUNC_H
+
+#ifdef ENABLE_NETWORK
+
+#include "network_type.h"
+#include "../console_type.h"
+
+extern NetworkServerGameInfo _network_game_info;
+extern NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
+extern NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
+
+extern uint16 _network_own_client_index;
+extern uint16 _redirect_console_to_client;
+extern bool _network_need_advertise;
+extern uint32 _network_last_advertise_frame;
+extern uint8 _network_reconnect;
+extern char *_network_host_list[10];
+extern char *_network_ban_list[25];
+
+byte NetworkSpectatorCount();
+void CheckMinPlayers();
+void NetworkUpdatePlayerName();
+bool NetworkCompanyHasPlayers(PlayerID company);
+bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
+void NetworkReboot();
+void NetworkDisconnect();
+void NetworkGameLoop();
+void NetworkUDPGameLoop();
+void NetworkUDPCloseAll();
+void ParseConnectionString(const char **player, const char **port, char *connection_string);
+void NetworkStartDebugLog(const char *hostname, uint16 port);
+void NetworkPopulateCompanyInfo();
+
+void NetworkUpdateClientInfo(uint16 client_index);
+bool NetworkClientConnectGame(const char *host, uint16 port);
+void NetworkClientSendRcon(const char *password, const char *command);
+void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg);
+void NetworkClientSetPassword();
+
+/*** Commands ran by the server ***/
+void NetworkServerMonthlyLoop();
+void NetworkServerYearlyLoop();
+void NetworkServerChangeOwner(PlayerID current_player, PlayerID new_player);
+void NetworkServerShowStatusToConsole();
+bool NetworkServerStart();
+
+NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
+NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
+const char* GetPlayerIP(const NetworkClientInfo *ci);
+
+void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string);
+void NetworkServerSendError(uint16 client_index, NetworkErrorCode error);
+void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
+
+#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)
+
+#endif /* ENABLE_NETWORK */
+#endif /* NETWORK_FUNC_H */
--- a/src/network/network_gamelist.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gamelist.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -11,6 +11,7 @@
#include "../debug.h"
#include "../newgrf_config.h"
#include "../core/alloc_func.hpp"
+#include "network_internal.h"
#include "core/game.h"
#include "network_udp.h"
#include "network_gamelist.h"
--- a/src/network/network_gamelist.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gamelist.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,8 @@
#ifndef NETWORK_GAMELIST_H
#define NETWORK_GAMELIST_H
+#include "network_type.h"
+
/** Structure with information shown in the game list (GUI) */
struct NetworkGameList {
NetworkGameInfo info; ///< The game information of this server
--- a/src/network/network_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -9,7 +9,7 @@
#include "network.h"
#include "../date_func.h"
#include "../fios.h"
-#include "network_data.h"
+#include "network_internal.h"
#include "network_client.h"
#include "network_gui.h"
#include "network_gamelist.h"
@@ -38,9 +38,6 @@
#define BGC 5
#define BTC 15
-/* Global to remember sorting after window has been closed */
-static Listing _ng_sorting;
-
static bool _chat_tab_completion_active;
static void ShowNetworkStartServerWindow();
@@ -87,57 +84,6 @@
InvalidateWindowData(WC_NETWORK_WINDOW, 0, unselect);
}
-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;
-
- /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
- int r = StrEmpty(cmp1->info.server_revision) - StrEmpty(cmp2->info.server_revision);
-
- /* Reverse default as we are interested in version-compatible clients first */
- if (r == 0) r = cmp2->info.version_compatible - cmp1->info.version_compatible;
- /* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
- if (r == 0) r = cmp2->info.compatible - cmp1->info.compatible;
- /* Passworded servers should be below unpassworded servers */
- if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
- /* Finally sort on the name of the server */
- if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
enum NetworkGameWindowWidgets {
NGWW_CLOSE, ///< Close 'X' button
@@ -171,42 +117,25 @@
typedef GUIList<NetworkGameList*> GUIGameServerList;
-struct NetworkGameWindow : public QueryStringBaseWindow {
+class NetworkGameWindow : public QueryStringBaseWindow {
+protected:
+ /* Runtime saved values */
+ static Listing last_sorting;
+
+ /* Constants for sorting servers */
+ static GUIGameServerList::SortFunction *const sorter_funcs[];
+
byte field; ///< selected text-field
NetworkGameList *server; ///< selected server
GUIGameServerList servers; ///< list with game servers.
- NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
- {
- ttd_strlcpy(this->edit_str_buf, _network_player_name, lengthof(this->edit_str_buf));
- this->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
-
- UpdateNetworkGameWindow(true);
-
- this->vscroll.cap = 11;
- this->resize.step_height = NET_PRC__SIZE_OF_ROW;
-
- this->field = NGWW_PLAYER;
- this->server = NULL;
-
- this->servers.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
- this->servers.sort_type = _ng_sorting.criteria;
-
- this->FindWindowPlacementAndResize(desc);
- }
-
- ~NetworkGameWindow()
- {
- }
-
/**
* (Re)build the network game list as its amount has changed because
* an item has been added or deleted for example
*/
void BuildNetworkGameList()
{
- if (!(this->servers.flags & VL_REBUILD)) return;
+ if (!this->servers.NeedRebuild()) return;
/* Create temporary array of games to use for listing */
this->servers.Clear();
@@ -216,40 +145,63 @@
}
this->servers.Compact();
-
- /* Force resort */
- this->servers.flags &= ~VL_REBUILD;
- this->servers.flags |= VL_RESORT;
+ this->servers.RebuildDone();
}
+ /** Sort servers by name. */
+ static int CDECL NGameNameSorter(NetworkGameList* const *a, NetworkGameList* const *b)
+ {
+ return strcasecmp((*a)->info.server_name, (*b)->info.server_name);
+ }
+
+ /** Sort servers 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(NetworkGameList* const *a, NetworkGameList* const *b)
+ {
+ /* Reverse as per default we are interested in most-clients first */
+ int r = (*a)->info.clients_on - (*b)->info.clients_on;
+
+ if (r == 0) r = (*a)->info.clients_max - (*b)->info.clients_max;
+ if (r == 0) r = NGameNameSorter(a, b);
+
+ return r;
+ }
+
+ /** Sort servers by joinability. If both servers are the
+ * same, prefer the non-passworded server first. */
+ static int CDECL NGameAllowedSorter(NetworkGameList* const *a, NetworkGameList* const *b)
+ {
+ /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
+ int r = StrEmpty((*a)->info.server_revision) - StrEmpty((*b)->info.server_revision);
+
+ /* Reverse default as we are interested in version-compatible clients first */
+ if (r == 0) r = (*b)->info.version_compatible - (*a)->info.version_compatible;
+ /* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
+ if (r == 0) r = (*b)->info.compatible - (*a)->info.compatible;
+ /* Passworded servers should be below unpassworded servers */
+ if (r == 0) r = (*a)->info.use_password - (*b)->info.use_password;
+ /* Finally sort on the name of the server */
+ if (r == 0) r = NGameNameSorter(a, b);
+
+ return r;
+ }
+
+ /** Sort the server list */
void SortNetworkGameList()
{
- static NGameNameSortFunction * const ngame_sorter[] = {
- &NGameNameSorter,
- &NGameClientSorter,
- &NGameAllowedSorter
- };
-
- NetworkGameList *item;
- uint i;
-
- if (!(this->servers.flags & VL_RESORT)) return;
- if (this->servers.Length() == 0) return;
-
- _internal_sort_order = !!(this->servers.flags & VL_DESC);
- qsort(this->servers.Begin(), this->servers.Length(), sizeof(*this->servers.Begin()), ngame_sorter[this->servers.sort_type]);
+ if (!this->servers.Sort()) return;
/* 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 = this->servers[0];
- for (item = _network_game_list, i = 1; i != this->servers.Length(); i++) {
+ NetworkGameList *item = _network_game_list;
+ for (uint i = 1; i != this->servers.Length(); i++) {
item->next = this->servers[i];
item = item->next;
}
item->next = NULL;
-
- this->servers.flags &= ~VL_RESORT;
}
/**
@@ -285,16 +237,44 @@
}
}
+public:
+ NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ ttd_strlcpy(this->edit_str_buf, _settings_client.network.player_name, lengthof(this->edit_str_buf));
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
+
+ UpdateNetworkGameWindow(true);
+
+ this->vscroll.cap = 11;
+ this->resize.step_height = NET_PRC__SIZE_OF_ROW;
+
+ this->field = NGWW_PLAYER;
+ this->server = NULL;
+
+ this->servers.SetListing(this->last_sorting);
+ this->servers.SetSortFuncs(this->sorter_funcs);
+ this->servers.ForceRebuild();
+ this->SortNetworkGameList();
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ ~NetworkGameWindow()
+ {
+ this->last_sorting = this->servers.GetListing();
+ }
+
virtual void OnPaint()
{
const NetworkGameList *sel = this->server;
- const SortButtonState arrow = (this->servers.flags & VL_DESC) ? SBS_DOWN : SBS_UP;
+ const SortButtonState arrow = this->servers.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
- if (this->servers.flags & VL_REBUILD) {
+ if (this->servers.NeedRebuild()) {
this->BuildNetworkGameList();
SetVScrollCount(this, this->servers.Length());
}
- if (this->servers.flags & VL_RESORT) this->SortNetworkGameList();
+ this->SortNetworkGameList();
/* 'Refresh' button invisible if no server selected */
this->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
@@ -310,7 +290,7 @@
sel->info.grfconfig == NULL);
SetDParam(0, 0x00);
- SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
+ SetDParam(1, _lan_internet_types_dropdown[_settings_client.network.lan_internet]);
this->DrawWidgets();
/* Edit box to set player name */
@@ -319,31 +299,23 @@
DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
/* Sort based on widgets: name, clients, compatibility */
- switch (this->servers.sort_type) {
+ switch (this->servers.SortType()) {
case NGWW_NAME - NGWW_NAME: this->DrawSortButtonState(NGWW_NAME, arrow); break;
case NGWW_CLIENTS - NGWW_NAME: this->DrawSortButtonState(NGWW_CLIENTS, arrow); break;
case NGWW_INFO - NGWW_NAME: this->DrawSortButtonState(NGWW_INFO, arrow); break;
}
uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
- int32 n = 0;
- int32 pos = this->vscroll.pos;
- const NetworkGameList *cur_item = _network_game_list;
- while (pos > 0 && cur_item != NULL) {
- pos--;
- cur_item = cur_item->next;
+ const int max = min(this->vscroll.pos + this->vscroll.cap, (int)this->servers.Length());
+
+ for (int i = this->vscroll.pos; i < max; ++i) {
+ const NetworkGameList *ngl = this->servers[i];
+ this->DrawServerLine(ngl, y, ngl == sel);
+ y += NET_PRC__SIZE_OF_ROW;
}
- while (cur_item != NULL) {
- this->DrawServerLine(cur_item, y, cur_item == sel);
-
- cur_item = cur_item->next;
- y += NET_PRC__SIZE_OF_ROW;
- if (++n == this->vscroll.cap) break; // max number of games in the window
- }
-
- const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_settings_client.network.last_host), _settings_client.network.last_port);
/* Draw the last joined server, if any */
if (last_joined != NULL) this->DrawServerLine(last_joined, y = this->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
@@ -411,7 +383,7 @@
if (!sel->info.compatible) {
DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
} else if (sel->info.clients_on == sel->info.clients_max) {
- /* Show: server full, when clients_on == clients_max */
+ /* Show: server full, when clients_on == max_clients */
DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
} else if (sel->info.use_password) {
DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
@@ -434,37 +406,33 @@
break;
case NGWW_CONN_BTN: // 'Connection' droplist
- ShowDropDownMenu(this, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
+ ShowDropDownMenu(this, _lan_internet_types_dropdown, _settings_client.network.lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
break;
case NGWW_NAME: // Sort by name
case NGWW_CLIENTS: // Sort by connected clients
case NGWW_INFO: // Connectivity (green dot)
- if (this->servers.sort_type == widget - NGWW_NAME) this->servers.flags ^= VL_DESC;
- this->servers.flags |= VL_RESORT;
- this->servers.sort_type = widget - NGWW_NAME;
-
- _ng_sorting.order = !!(this->servers.flags & VL_DESC);
- _ng_sorting.criteria = this->servers.sort_type;
+ if (this->servers.SortType() == widget - NGWW_NAME) {
+ this->servers.ToggleSortOrder();
+ } else {
+ this->servers.SetSortType(widget - NGWW_NAME);
+ this->servers.ForceResort();
+ }
this->SetDirty();
break;
case NGWW_MATRIX: { // Matrix to show networkgames
- NetworkGameList *cur_item;
uint32 id_v = (pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
if (id_v >= this->vscroll.cap) return; // click out of bounds
id_v += this->vscroll.pos;
- cur_item = _network_game_list;
- for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
-
- this->server = cur_item;
+ this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL;
this->SetDirty();
} break;
case NGWW_LASTJOINED: {
- NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_settings_client.network.last_host), _settings_client.network.last_port);
if (last_joined != NULL) {
this->server = last_joined;
this->SetDirty();
@@ -472,7 +440,7 @@
} break;
case NGWW_FIND: // Find server automatically
- switch (_network_lan_internet) {
+ switch (_settings_client.network.lan_internet) {
case 0: NetworkUDPSearchGame(); break;
case 1: NetworkUDPQueryMasterServer(); break;
}
@@ -480,7 +448,7 @@
case NGWW_ADD: // Add a server
ShowQueryString(
- BindCString(_network_default_ip),
+ BindCString(_settings_client.network.connect_to_ip),
STR_NETWORK_ENTER_IP,
31 | 0x1000, // maximum number of characters OR
250, // characters up to this width pixels, whichever is satisfied first
@@ -493,8 +461,8 @@
case NGWW_JOIN: // Join Game
if (this->server != NULL) {
- snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
- _network_last_port = this->server->port;
+ snprintf(_settings_client.network.last_host, sizeof(_settings_client.network.last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
+ _settings_client.network.last_port = this->server->port;
ShowNetworkLobbyWindow(this->server);
}
break;
@@ -513,7 +481,7 @@
{
switch (widget) {
case NGWW_CONN_BTN:
- _network_lan_internet = index;
+ _settings_client.network.lan_internet = index;
break;
default:
@@ -531,7 +499,7 @@
virtual void OnInvalidateData(int data)
{
if (data != 0) this->server = NULL;
- this->servers.flags |= VL_REBUILD;
+ this->servers.ForceRebuild();
this->SetDirty();
}
@@ -549,13 +517,13 @@
return state;
}
- if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, state) == 1) return state; // enter pressed
+ if (this->HandleEditBoxKey(NGWW_PLAYER, key, keycode, state) == 1) return state; // enter pressed
/* The name is only allowed when it starts with a letter! */
- if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
- ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
+ if (!StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
+ ttd_strlcpy(_settings_client.network.player_name, this->edit_str_buf, lengthof(_settings_client.network.player_name));
} else {
- ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
+ ttd_strlcpy(_settings_client.network.player_name, "Player", lengthof(_settings_client.network.player_name));
}
return state;
}
@@ -589,6 +557,14 @@
}
};
+Listing NetworkGameWindow::last_sorting = {false, 2};
+GUIGameServerList::SortFunction *const NetworkGameWindow::sorter_funcs[] = {
+ &NGameNameSorter,
+ &NGameClientSorter,
+ &NGameAllowedSorter
+};
+
+
static const Widget _network_game_window_widgets[] = {
/* TOP */
{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // NGWW_CLOSE
@@ -650,9 +626,6 @@
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
}
new NetworkGameWindow(&_network_game_window_desc);
@@ -692,47 +665,45 @@
NetworkStartServerWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
{
- ttd_strlcpy(this->edit_str_buf, _network_server_name, lengthof(this->edit_str_buf));
+ ttd_strlcpy(this->edit_str_buf, _settings_client.network.server_name, lengthof(this->edit_str_buf));
_saveload_mode = SLD_NEW_GAME;
BuildFileList();
this->vscroll.cap = 12;
- this->vscroll.count = _fios_num + 1;
+ this->vscroll.count = _fios_items.Length();
this->afilter = CS_ALPHANUMERAL;
InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 160);
this->field = NSSW_GAMENAME;
- _network_game_info.use_password = !StrEmpty(_network_server_password);
this->FindWindowPlacementAndResize(desc);
}
virtual void OnPaint()
{
- int y = NSSWND_START, pos;
+ int y = NSSWND_START;
const FiosItem *item;
/* draw basic widgets */
SetDParam(1, _connection_types_dropdown[_network_advertise]);
- SetDParam(2, _network_game_info.clients_max);
- SetDParam(3, _network_game_info.companies_max);
- SetDParam(4, _network_game_info.spectators_max);
- SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
+ SetDParam(2, _settings_client.network.max_clients);
+ SetDParam(3, _settings_client.network.max_companies);
+ SetDParam(4, _settings_client.network.max_spectators);
+ SetDParam(5, STR_NETWORK_LANG_ANY + _settings_client.network.server_lang);
this->DrawWidgets();
/* editbox to set game name */
this->DrawEditBox(NSSW_GAMENAME);
/* if password is set, draw red '*' next to 'Set password' button */
- if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
+ if (!StrEmpty(_settings_client.network.server_password)) DoDrawString("*", 408, 23, TC_RED);
/* draw list of maps */
GfxFillRect(11, 63, 258, 215, 0xD7); // black background of maps list
- pos = this->vscroll.pos;
- while (pos < _fios_num + 1) {
- item = _fios_list + pos - 1;
+ for (uint pos = this->vscroll.pos; pos < _fios_items.Length() + 1; pos++) {
+ item = _fios_items.Get(pos - 1);
if (item == this->map || (pos == 0 && this->map == NULL))
GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
@@ -741,7 +712,6 @@
} else {
DoDrawString(item->title, 14, y, _fios_colors[item->type] );
}
- pos++;
y += NSSWND_ROWSIZE;
if (y >= this->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
@@ -764,7 +734,7 @@
case NSSW_SETPWD: // Set password button
this->widget_id = NSSW_SETPWD;
- ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
+ ShowQueryString(BindCString(_settings_client.network.server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
break;
case NSSW_SELMAP: { // Select map
@@ -773,7 +743,7 @@
y += this->vscroll.pos;
if (y >= this->vscroll.count) return;
- this->map = (y == 0) ? NULL : _fios_list + y - 1;
+ this->map = (y == 0) ? NULL : _fios_items.Get(y - 1);
this->SetDirty();
} break;
@@ -791,13 +761,13 @@
switch (widget) {
default: NOT_REACHED();
case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
- _network_game_info.clients_max = Clamp(_network_game_info.clients_max + widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
+ _settings_client.network.max_clients = Clamp(_settings_client.network.max_clients + widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
break;
case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
- _network_game_info.companies_max = Clamp(_network_game_info.companies_max + widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
+ _settings_client.network.max_companies = Clamp(_settings_client.network.max_companies + widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
break;
case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
- _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
+ _settings_client.network.max_spectators = Clamp(_settings_client.network.max_spectators + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
break;
}
}
@@ -806,26 +776,26 @@
case NSSW_CLIENTS_TXT: // Click on number of players
this->widget_id = NSSW_CLIENTS_TXT;
- SetDParam(0, _network_game_info.clients_max);
+ SetDParam(0, _settings_client.network.max_clients);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, this, CS_NUMERAL);
break;
case NSSW_COMPANIES_TXT: // Click on number of companies
this->widget_id = NSSW_COMPANIES_TXT;
- SetDParam(0, _network_game_info.companies_max);
+ SetDParam(0, _settings_client.network.max_companies);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, this, CS_NUMERAL);
break;
case NSSW_SPECTATORS_TXT: // Click on number of spectators
this->widget_id = NSSW_SPECTATORS_TXT;
- SetDParam(0, _network_game_info.spectators_max);
+ SetDParam(0, _settings_client.network.max_spectators);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, this, CS_NUMERAL);
break;
case NSSW_LANGUAGE_BTN: { // Language
uint sel = 0;
for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
- if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
+ if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _settings_client.network.server_lang) {
sel = i;
break;
}
@@ -869,7 +839,7 @@
_network_advertise = (index != 0);
break;
case NSSW_LANGUAGE_BTN:
- _network_game_info.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
+ _settings_client.network.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
break;
default:
NOT_REACHED();
@@ -889,7 +859,7 @@
if (this->field == NSSW_GAMENAME) {
if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == 1) return state; // enter pressed
- ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
+ ttd_strlcpy(_settings_client.network.server_name, this->text.buf, sizeof(_settings_client.network.server_name));
}
return state;
@@ -900,16 +870,15 @@
if (str == NULL) return;
if (this->widget_id == NSSW_SETPWD) {
- ttd_strlcpy(_network_server_password, str, lengthof(_network_server_password));
- _network_game_info.use_password = !StrEmpty(_network_server_password);
+ ttd_strlcpy(_settings_client.network.server_password, str, lengthof(_settings_client.network.server_password));
} else {
int32 value = atoi(str);
this->InvalidateWidget(this->widget_id);
switch (this->widget_id) {
default: NOT_REACHED();
- case NSSW_CLIENTS_TXT: _network_game_info.clients_max = Clamp(value, 2, MAX_CLIENTS); break;
- case NSSW_COMPANIES_TXT: _network_game_info.companies_max = Clamp(value, 1, MAX_PLAYERS); break;
- case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
+ case NSSW_CLIENTS_TXT: _settings_client.network.max_clients = Clamp(value, 2, MAX_CLIENTS); break;
+ case NSSW_COMPANIES_TXT: _settings_client.network.max_companies = Clamp(value, 1, MAX_PLAYERS); break;
+ case NSSW_SPECTATORS_TXT: _settings_client.network.max_spectators = Clamp(value, 0, MAX_CLIENTS); break;
}
}
@@ -1131,22 +1100,22 @@
case NLWW_JOIN: // Join company
/* Button can be clicked only when it is enabled */
_network_playas = this->company;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
+ NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
break;
case NLWW_NEW: // New company
_network_playas = PLAYER_NEW_COMPANY;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
+ NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
break;
case NLWW_SPECTATE: // Spectate game
_network_playas = PLAYER_SPECTATOR;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
+ NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
break;
case NLWW_REFRESH: // Refresh
- NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+ NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info
+ NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data
break;
}
}
@@ -1189,8 +1158,8 @@
{
DeleteWindowById(WC_NETWORK_WINDOW, 0);
- NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+ NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info
+ NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
}
@@ -1586,6 +1555,12 @@
ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
}
+// Vars needed for the join-GUI
+NetworkJoinStatus _network_join_status;
+uint8 _network_join_waiting;
+uint16 _network_join_kbytes;
+uint16 _network_join_kbytes_total;
+
struct NetworkJoinStatusWindow : Window {
NetworkJoinStatusWindow(const WindowDesc *desc) : Window(desc)
{
@@ -1667,7 +1642,7 @@
if (!_network_server) {
SEND_COMMAND(PACKET_CLIENT_CHAT)((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf);
} else {
- NetworkServer_HandleChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, NETWORK_SERVER_INDEX);
+ NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, NETWORK_SERVER_INDEX);
}
}
@@ -1921,7 +1896,7 @@
{
this->parent = parent;
this->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
+ InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_settings_client.network.default_company_pass), lengthof(this->edit_str_buf)), 0);
this->FindWindowPlacementAndResize(desc);
}
@@ -1929,7 +1904,7 @@
void OnOk()
{
if (this->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
- snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", this->edit_str_buf);
+ snprintf(_settings_client.network.default_company_pass, lengthof(_settings_client.network.default_company_pass), "%s", this->edit_str_buf);
}
/* empty password is a '*' because of console argument */
--- a/src/network/network_gui.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gui.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,11 +5,10 @@
#ifndef NETWORK_GUI_H
#define NETWORK_GUI_H
-#include "../window_type.h"
-
#ifdef ENABLE_NETWORK
-#include "network_data.h"
+#include "../window_type.h"
+#include "network_type.h"
void ShowNetworkNeedPassword(NetworkPasswordType npt);
void ShowNetworkGiveMoneyWindow(PlayerID player); // PlayerID
--- a/src/network/network_internal.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_internal.h Wed Jun 04 22:34:45 2008 +0000
@@ -7,10 +7,13 @@
#ifdef ENABLE_NETWORK
-#include "../player_type.h"
-#include "../economy_type.h"
+#include "network.h"
+#include "network_func.h"
+#include "core/os_abstraction.h"
+#include "core/core.h"
#include "core/config.h"
-#include "core/game.h"
+#include "core/packet.h"
+#include "core/tcp.h"
/**
* If this line is enable, every frame will have a sync test
@@ -29,50 +32,14 @@
*/
//#define NETWORK_SEND_DOUBLE_SEED
-
-enum {
- /**
- * 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
- */
- MAX_CLIENTS = MAX_PLAYERS + 3,
+#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
- /** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
- MAX_CLIENT_INFO = MAX_CLIENTS + 1,
-
- /** Maximum number of internet interfaces supported. */
- MAX_INTERFACES = 9,
-
- /** How many vehicle/station types we put over the network */
- NETWORK_VEHICLE_TYPES = 5,
- NETWORK_STATION_TYPES = 5,
+enum MapPacket {
+ MAP_PACKET_START,
+ MAP_PACKET_NORMAL,
+ MAP_PACKET_END,
};
-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
- Money company_value; ///< The company value
- Money money; ///< The amount of money the company has
- Money income; ///< How much did the company earned last year
- uint16 performance; ///< What was his performance last month?
- bool use_password; ///< Is there 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
-};
-
-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
- PlayerID 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_UNIQUE_ID_LENGTH]; ///< Every play sends an unique id so we can indentify him
-};
enum NetworkJoinStatus {
NETWORK_JOIN_STATUS_CONNECTING,
@@ -126,100 +93,80 @@
NETLANG_COUNT
};
-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];
+extern NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
-VARDEF uint16 _network_own_client_index;
-VARDEF char _network_unique_id[NETWORK_UNIQUE_ID_LENGTH]; // Our own unique ID
+extern uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
+extern uint32 _frame_counter_max; // To where we may go with our clients
-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.
+extern 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 char _network_default_company_pass[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;
+extern uint32 _broadcast_list[MAX_INTERFACES + 1];
-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;
+extern uint32 _network_server_bind_ip;
-VARDEF bool _network_udp_server;
-VARDEF uint16 _network_udp_broadcast;
-
-VARDEF byte _network_lan_internet;
+extern uint32 _sync_seed_1, _sync_seed_2;
+extern uint32 _sync_frame;
+extern bool _network_first_time;
+// Vars needed for the join-GUI
+extern NetworkJoinStatus _network_join_status;
+extern uint8 _network_join_waiting;
+extern uint16 _network_join_kbytes;
+extern uint16 _network_join_kbytes_total;
-VARDEF bool _network_need_advertise;
-VARDEF uint32 _network_last_advertise_frame;
-VARDEF uint8 _network_advertise_retries;
+extern uint32 _network_last_host_ip;
+extern uint8 _network_reconnect;
-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
+extern bool _network_udp_server;
+extern uint16 _network_udp_broadcast;
-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
+extern uint8 _network_advertise_retries;
+
+// following externs are instantiated at network.cpp
+extern CommandPacket *_local_command_queue;
+
+// Here we keep track of the clients
+// (and the client uses [0] for his own communication)
+extern NetworkTCPSocketHandler _clients[MAX_CLIENTS];
void NetworkTCPQueryServer(const char* host, unsigned short port);
-byte NetworkSpectatorCount();
-
-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();
-bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
-void NetworkPopulateCompanyInfo();
void UpdateNetworkGameWindow(bool unselect);
-void CheckMinPlayers();
-void NetworkStartDebugLog(const char *hostname, uint16 port);
-
-void NetworkUDPCloseAll();
-void NetworkGameLoop();
-void NetworkUDPGameLoop();
-bool NetworkServerStart();
-bool NetworkClientConnectGame(const char *host, uint16 port);
-void NetworkReboot();
-void NetworkDisconnect();
bool IsNetworkCompatibleVersion(const char *version);
+void NetworkExecuteCommand(CommandPacket *cp);
+void NetworkAddCommandQueue(NetworkTCPSocketHandler *cs, CommandPacket *cp);
+
+// from network.c
+void NetworkCloseClient(NetworkTCPSocketHandler *cs);
+void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
+void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
+uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
+byte NetworkGetCurrentLanguageIndex();
+NetworkTCPSocketHandler *NetworkFindClientStateFromIndex(uint16 client_index);
+unsigned long NetworkResolveHost(const char *hostname);
+char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
+bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
+
+#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()
+#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
+#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkTCPSocketHandler *cs, Packet *p)
+#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkTCPSocketHandler *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->IsConnected(); cs++)
+
#endif /* ENABLE_NETWORK */
#endif /* NETWORK_INTERNAL_H */
--- a/src/network/network_server.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_server.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -8,7 +8,7 @@
#include "../openttd.h" // XXX StringID
#include "../debug.h"
#include "../strings_func.h"
-#include "network_data.h"
+#include "network_internal.h"
#include "core/tcp.h"
#include "../vehicle_base.h"
#include "../vehicle_func.h"
@@ -230,7 +230,7 @@
Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
p->Send_uint8(type);
p->Send_uint32(_settings_game.game_creation.generation_seed);
- p->Send_string(_network_unique_id);
+ p->Send_string(_settings_client.network.network_id);
cs->Send_Packet(p);
}
@@ -255,7 +255,7 @@
p = NetworkSend_Init(PACKET_SERVER_WELCOME);
p->Send_uint16(cs->index);
p->Send_uint32(_settings_game.game_creation.generation_seed);
- p->Send_string(_network_unique_id);
+ p->Send_string(_settings_client.network.network_id);
cs->Send_Packet(p);
// Transmit info about all the active clients
@@ -614,7 +614,7 @@
NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
/* We now want a password from the client else we do not allow him in! */
- if (_network_game_info.use_password) {
+ if (!StrEmpty(_settings_client.network.server_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') {
@@ -655,13 +655,13 @@
// join another company does not affect these values
switch (playas) {
case PLAYER_NEW_COMPANY: /* New company */
- if (ActivePlayerCount() >= _network_game_info.companies_max) {
+ if (ActivePlayerCount() >= _settings_client.network.max_companies) {
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
return;
}
break;
case PLAYER_SPECTATOR: /* Spectator */
- if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
+ if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
return;
}
@@ -711,7 +711,7 @@
if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
// Check game-password
- if (strcmp(password, _network_game_info.server_password) != 0) {
+ if (strcmp(password, _settings_client.network.server_password) != 0) {
// Password is invalid
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
return;
@@ -800,11 +800,11 @@
}
}
- if (_network_pause_on_join) {
+ if (_settings_client.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);
+ NetworkServerSendChat(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
@@ -1021,9 +1021,9 @@
/* Now he is! Unpause the game */
cs->status = STATUS_ACTIVE;
- if (_network_pause_on_join) {
+ if (_settings_client.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);
+ NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
}
CheckMinPlayers();
@@ -1040,7 +1040,7 @@
-void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
+void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
{
NetworkTCPSocketHandler *cs;
const NetworkClientInfo *ci, *ci_own, *ci_to;
@@ -1146,7 +1146,7 @@
p->Recv_string(msg, MAX_TEXT_MSG_LEN);
- NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
+ NetworkServerSendChat(action, desttype, dest, msg, cs->index);
}
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
@@ -1187,12 +1187,12 @@
char pass[NETWORK_PASSWORD_LENGTH];
char command[NETWORK_RCONCOMMAND_LENGTH];
- if (_network_game_info.rcon_password[0] == '\0') return;
+ if (StrEmpty(_settings_client.network.rcon_password)) return;
p->Recv_string(pass, sizeof(pass));
p->Recv_string(command, sizeof(command));
- if (strcmp(pass, _network_game_info.rcon_password) != 0) {
+ if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
return;
}
@@ -1365,7 +1365,7 @@
/* Check if we want to restart the map */
static void NetworkCheckRestartMap()
{
- if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
+ if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
StartNewGameWithoutGUI(GENERATE_NEW_SEED);
@@ -1384,7 +1384,7 @@
const Player *p;
bool clients_in_company[MAX_PLAYERS];
- if (!_network_autoclean_companies) return;
+ if (!_settings_client.network.autoclean_companies) return;
memset(clients_in_company, 0, sizeof(clients_in_company));
@@ -1409,13 +1409,13 @@
_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') {
+ if (_network_player_info[p->index].months_empty > _settings_client.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(CC_DEFAULT, "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') {
+ if (_network_player_info[p->index].months_empty > _settings_client.network.autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
/* Unprotect the company */
_network_player_info[p->index].password[0] = '\0';
IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", p->index+1);
@@ -1510,7 +1510,7 @@
#endif
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
+ if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
_last_sync_frame = _frame_counter;
send_sync = true;
}
@@ -1542,8 +1542,8 @@
}
} else if (cs->status == STATUS_PRE_ACTIVE) {
int lag = NetworkCalculateLag(cs);
- if (lag > _network_max_join_time) {
- IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
+ if (lag > _settings_client.network.max_join_time) {
+ IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _settings_client.network.max_join_time);
NetworkCloseClient(cs);
}
} else if (cs->status == STATUS_INACTIVE) {
@@ -1582,4 +1582,82 @@
NetworkAutoCleanCompanies();
}
+void NetworkServerChangeOwner(PlayerID current_player, PlayerID new_player)
+{
+ /* The server has to handle all administrative issues, for example
+ * updating and notifying all clients of what has happened */
+ NetworkTCPSocketHandler *cs;
+ NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+
+ /* The server has just changed from player */
+ if (current_player == ci->client_playas) {
+ ci->client_playas = new_player;
+ NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+ }
+
+ /* Find all clients that were in control of this company, and mark them as new_player */
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (current_player == ci->client_playas) {
+ ci->client_playas = new_player;
+ NetworkUpdateClientInfo(ci->client_index);
+ }
+ }
+}
+
+const char* GetPlayerIP(const NetworkClientInfo* ci)
+{
+ struct in_addr addr;
+
+ addr.s_addr = ci->client_ip;
+ return inet_ntoa(addr);
+}
+
+void NetworkServerShowStatusToConsole()
+{
+ static const char* const stat_str[] = {
+ "inactive",
+ "authorizing",
+ "authorized",
+ "waiting",
+ "loading map",
+ "map done",
+ "ready",
+ "active"
+ };
+
+ NetworkTCPSocketHandler *cs;
+ FOR_ALL_CLIENTS(cs) {
+ int lag = NetworkCalculateLag(cs);
+ const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+ const char* status;
+
+ status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
+ IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'",
+ cs->index, ci->client_name, status, lag,
+ ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
+ GetPlayerIP(ci), ci->unique_id);
+ }
+}
+
+void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string)
+{
+ SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(client_index), colour_code, string);
+}
+
+void NetworkServerSendError(uint16 client_index, NetworkErrorCode error)
+{
+ SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(client_index), error);
+}
+
+bool NetworkCompanyHasPlayers(PlayerID company)
+{
+ const NetworkTCPSocketHandler *cs;
+ const NetworkClientInfo *ci;
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (ci->client_playas == company) return true;
+ }
+ return false;
+}
#endif /* ENABLE_NETWORK */
--- a/src/network/network_server.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_server.h Wed Jun 04 22:34:45 2008 +0000
@@ -14,21 +14,8 @@
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *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(NetworkTCPSocketHandler *cs);
void NetworkServer_Tick(bool send_frame);
-void NetworkServerMonthlyLoop();
-void NetworkServerYearlyLoop();
-
-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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/network_type.h Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,108 @@
+/* $Id$ */
+
+/** @file network_internal.h Variables and function used internally. */
+
+#ifndef NETWORK_TYPE_H
+#define NETWORK_TYPE_H
+
+#ifdef ENABLE_NETWORK
+
+#include "../player_type.h"
+#include "../economy_type.h"
+#include "core/config.h"
+#include "core/game.h"
+
+enum {
+ /**
+ * 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
+ */
+ MAX_CLIENTS = MAX_PLAYERS + 3,
+
+ /** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
+ MAX_CLIENT_INFO = MAX_CLIENTS + 1,
+
+ /** Maximum number of internet interfaces supported. */
+ MAX_INTERFACES = 9,
+
+ /** How many vehicle/station types we put over the network */
+ NETWORK_VEHICLE_TYPES = 5,
+ NETWORK_STATION_TYPES = 5,
+
+ NETWORK_SERVER_INDEX = 1,
+ NETWORK_EMPTY_INDEX = 0,
+};
+
+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
+ Money company_value; ///< The company value
+ Money money; ///< The amount of money the company has
+ Money income; ///< How much did the company earned last year
+ uint16 performance; ///< What was his performance last month?
+ bool use_password; ///< Is there 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
+};
+
+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
+ PlayerID 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_UNIQUE_ID_LENGTH]; ///< Every play sends an unique id so we can indentify him
+};
+
+enum NetworkPasswordType {
+ NETWORK_GAME_PASSWORD,
+ NETWORK_COMPANY_PASSWORD,
+};
+
+enum DestType {
+ 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)
+};
+
+/** Actions that can be used for NetworkTextMessage */
+enum NetworkAction {
+ 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,
+};
+
+enum NetworkErrorCode {
+ NETWORK_ERROR_GENERAL, // Try to use this one like never
+
+ /* Signals from clients */
+ NETWORK_ERROR_DESYNC,
+ NETWORK_ERROR_SAVEGAME_FAILED,
+ NETWORK_ERROR_CONNECTION_LOST,
+ NETWORK_ERROR_ILLEGAL_PACKET,
+ NETWORK_ERROR_NEWGRF_MISMATCH,
+
+ /* 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,
+};
+
+#endif /* ENABLE_NETWORK */
+#endif /* NETWORK_TYPE_H */
--- a/src/network/network_udp.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_udp.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -11,11 +11,11 @@
#include "../stdafx.h"
#include "../debug.h"
-#include "network_data.h"
#include "../date_func.h"
#include "../map_func.h"
#include "network_gamelist.h"
#include "network_udp.h"
+#include "network_internal.h"
#include "../variables.h"
#include "../newgrf_config.h"
#include "../core/endian_func.hpp"
@@ -23,6 +23,7 @@
#include "../player_base.h"
#include "../player_func.h"
#include "../settings_type.h"
+#include "../rev.h"
#include "core/udp.h"
@@ -68,21 +69,36 @@
DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
{
// Just a fail-safe.. should never happen
- if (!_network_udp_server)
+ if (!_network_udp_server) {
return;
+ }
+
+ NetworkGameInfo ngi;
+
+ /* Update some game_info */
+ ngi.clients_on = _network_game_info.clients_on;
+ ngi.start_date = _network_game_info.start_date;
+
+ ngi.server_lang = _settings_client.network.server_lang;
+ ngi.use_password = !StrEmpty(_settings_client.network.server_password);
+ ngi.clients_max = _settings_client.network.max_clients;
+ ngi.companies_on = ActivePlayerCount();
+ ngi.companies_max = _settings_client.network.max_companies;
+ ngi.spectators_on = NetworkSpectatorCount();
+ ngi.spectators_max = _settings_client.network.max_spectators;
+ ngi.game_date = _date;
+ ngi.map_width = MapSizeX();
+ ngi.map_height = MapSizeY();
+ ngi.map_set = _settings_game.game_creation.landscape;
+ ngi.dedicated = _network_dedicated;
+ ngi.grfconfig = _grfconfig;
+
+ ttd_strlcpy(ngi.map_name, _network_game_info.map_name, lengthof(ngi.map_name));
+ ttd_strlcpy(ngi.server_name, _settings_client.network.server_name, lengthof(ngi.server_name));
+ ttd_strlcpy(ngi.server_revision, _openttd_revision, lengthof(ngi.server_revision));
Packet packet(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 = _settings_game.game_creation.landscape;
- _network_game_info.companies_on = ActivePlayerCount();
- _network_game_info.spectators_on = NetworkSpectatorCount();
- _network_game_info.grfconfig = _grfconfig;
-
- this->Send_NetworkGameInfo(&packet, &_network_game_info);
+ this->Send_NetworkGameInfo(&packet, &ngi);
// Let the client know that we are here
this->SendPacket(&packet, client_addr);
@@ -428,7 +444,7 @@
struct sockaddr_in out_addr;
out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(_network_server_port);
+ out_addr.sin_port = htons(_settings_client.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));
@@ -535,7 +551,7 @@
Packet p(PACKET_UDP_SERVER_UNREGISTER);
/* Packet is: Version, server_port */
p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
- p.Send_uint16(_network_server_port);
+ p.Send_uint16(_settings_client.network.server_port);
_udp_master_socket->SendPacket(&p, &out_addr);
}
@@ -584,7 +600,7 @@
/* Packet is: WELCOME_MESSAGE, Version, server_port */
p.Send_string(NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
- p.Send_uint16(_network_server_port);
+ p.Send_uint16(_settings_client.network.server_port);
_udp_master_socket->SendPacket(&p, &out_addr);
}
--- a/src/newgrf.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -1404,7 +1404,7 @@
* date before 1930, as this breaks the build date stuff.
* @see FinaliseHouseArray() for more details.
*/
- if (housespec->min_date < 1930) housespec->min_date = 1930;
+ if (housespec->min_year < 1930) housespec->min_year = 1930;
_loaded_newgrf_features.has_newhouses = true;
} break;
@@ -1415,8 +1415,8 @@
case 0x0A: { // Availability years
uint16 years = grf_load_word(&buf);
- housespec->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
- housespec->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
+ housespec->min_year = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
+ housespec->max_year = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
} break;
case 0x0B: // Population
@@ -2906,17 +2906,28 @@
}
-static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount, uint8 cidcount, bool wagover)
+static bool IsValidGroupID(uint16 groupid, const char *function)
+{
+ if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+ grfmsg(1, "%s: Spriteset 0x%04X out of range (maximum 0x%02X) or empty, skipping.", function, groupid, _cur_grffile->spritegroups_count - 1);
+ return false;
+ }
+
+ return true;
+}
+
+static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount)
{
static EngineID *last_engines;
static uint last_engines_count;
-
- if (!wagover) {
- if (last_engines_count != idcount) {
- last_engines = ReallocT(last_engines, idcount);
- last_engines_count = idcount;
- }
- } else {
+ bool wagover = false;
+
+ /* Test for 'wagon override' flag */
+ if (HasBit(idcount, 7)) {
+ wagover = true;
+ /* Strip off the flag */
+ idcount = GB(idcount, 0, 7);
+
if (last_engines_count == 0) {
grfmsg(0, "VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
return;
@@ -2924,79 +2935,76 @@
grfmsg(6, "VehicleMapSpriteGroup: WagonOverride: %u engines, %u wagons",
last_engines_count, idcount);
+ } else {
+ if (last_engines_count != idcount) {
+ last_engines = ReallocT(last_engines, idcount);
+ last_engines_count = idcount;
+ }
}
+ EngineID *engines = (EngineID*)alloca(idcount * sizeof(*engines));
for (uint i = 0; i < idcount; i++) {
- uint8 engine_id = buf[3 + i];
- EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, engine_id)->index;
- byte *bp = &buf[4 + idcount];
-
- grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
-
- for (uint c = 0; c < cidcount; c++) {
- uint8 ctype = grf_load_byte(&bp);
- uint16 groupid = grf_load_word(&bp);
-
- grfmsg(8, "VehicleMapSpriteGroup: * [%d] Cargo type 0x%X, group id 0x%02X", c, ctype, groupid);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping", groupid, _cur_grffile->spritegroups_count);
- continue;
- }
-
- ctype = TranslateCargo(feature, ctype);
- if (ctype == CT_INVALID) continue;
+ engines[i] = GetNewEngine(_cur_grffile, (VehicleType)feature, grf_load_byte(&buf))->index;
+ if (!wagover) last_engines[i] = engines[i];
+ }
+
+ uint8 cidcount = grf_load_byte(&buf);
+ for (uint c = 0; c < cidcount; c++) {
+ uint8 ctype = grf_load_byte(&buf);
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) continue;
+
+ grfmsg(8, "VehicleMapSpriteGroup: * [%d] Cargo type 0x%X, group id 0x%02X", c, ctype, groupid);
+
+ ctype = TranslateCargo(feature, ctype);
+ if (ctype == CT_INVALID) continue;
+
+ for (uint i = 0; i < idcount; i++) {
+ EngineID engine = engines[i];
+
+ grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
if (wagover) {
SetWagonOverrideSprites(engine, ctype, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
} else {
SetCustomEngineSprites(engine, ctype, _cur_grffile->spritegroups[groupid]);
- last_engines[i] = engine;
}
}
}
- {
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- grfmsg(8, "-- Default group id 0x%04X", groupid);
-
- for (uint i = 0; i < idcount; i++) {
- EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, buf[3 + i])->index;
-
- /* Don't tell me you don't love duplicated code! */
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
- groupid, _cur_grffile->spritegroups_count);
- continue;
- }
-
- if (wagover) {
- SetWagonOverrideSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
- } else {
- SetCustomEngineSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid]);
- SetEngineGRF(engine, _cur_grffile);
- last_engines[i] = engine;
- }
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
+
+ grfmsg(8, "-- Default group id 0x%04X", groupid);
+
+ for (uint i = 0; i < idcount; i++) {
+ EngineID engine = engines[i];
+
+ if (wagover) {
+ SetWagonOverrideSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
+ } else {
+ SetCustomEngineSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid]);
+ SetEngineGRF(engine, _cur_grffile);
}
}
}
-static void CanalMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void CanalMapSpriteGroup(byte *buf, uint8 idcount)
{
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "CanalMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ CanalFeature *cfs = (CanalFeature*)alloca(idcount * sizeof(*cfs));
+ for (uint i = 0; i < idcount; i++) {
+ cfs[i] = (CanalFeature)grf_load_byte(&buf);
}
+ uint8 cidcount = grf_load_byte(&buf);
+ buf += cidcount * 3;
+
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "CanalMapSpriteGroup")) return;
+
for (uint i = 0; i < idcount; i++) {
- CanalFeature cf = (CanalFeature)buf[3 + i];
+ CanalFeature cf = cfs[i];
if (cf >= CF_END) {
grfmsg(1, "CanalMapSpriteGroup: Canal subset %d out of range, skipping", cf);
@@ -3008,77 +3016,69 @@
}
-static void StationMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void StationMapSpriteGroup(byte *buf, uint8 idcount)
{
+ uint8 *stations = (uint8*)alloca(idcount * sizeof(*stations));
for (uint i = 0; i < idcount; i++) {
- uint8 stid = buf[3 + i];
- StationSpec *statspec = _cur_grffile->stations[stid];
-
- if (statspec == NULL) {
- grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stid);
- return;
- }
-
- byte *bp = &buf[4 + idcount];
-
- for (uint c = 0; c < cidcount; c++) {
- uint8 ctype = grf_load_byte(&bp);
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "StationMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
- groupid, _cur_grffile->spritegroups_count);
- continue;
+ stations[i] = grf_load_byte(&buf);
+ }
+
+ uint8 cidcount = grf_load_byte(&buf);
+ for (uint c = 0; c < cidcount; c++) {
+ uint8 ctype = grf_load_byte(&buf);
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) continue;
+
+ ctype = TranslateCargo(GSF_STATION, ctype);
+ if (ctype == CT_INVALID) continue;
+
+ for (uint i = 0; i < idcount; i++) {
+ StationSpec *statspec = _cur_grffile->stations[stations[i]];
+
+ if (statspec == NULL) {
+ grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
+ return;
}
- ctype = TranslateCargo(GSF_STATION, ctype);
- if (ctype == CT_INVALID) continue;
-
statspec->spritegroup[ctype] = _cur_grffile->spritegroups[groupid];
}
}
- {
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "StationMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) return;
+
+ for (uint i = 0; i < idcount; i++) {
+ StationSpec *statspec = _cur_grffile->stations[stations[i]];
+
+ if (statspec == NULL) {
+ grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
+ continue;
}
- for (uint i = 0; i < idcount; i++) {
- uint8 stid = buf[3 + i];
- StationSpec *statspec = _cur_grffile->stations[stid];
- if (statspec == NULL) {
- grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stid);
- continue;
- }
-
- statspec->spritegroup[CT_DEFAULT] = _cur_grffile->spritegroups[groupid];
- statspec->grffile = _cur_grffile;
- statspec->localidx = stid;
- SetCustomStationSpec(statspec);
- }
+ statspec->spritegroup[CT_DEFAULT] = _cur_grffile->spritegroups[groupid];
+ statspec->grffile = _cur_grffile;
+ statspec->localidx = stations[i];
+ SetCustomStationSpec(statspec);
}
}
-static void TownHouseMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void TownHouseMapSpriteGroup(byte *buf, uint8 idcount)
{
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "TownHouseMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ uint8 *houses = (uint8*)alloca(idcount * sizeof(*houses));
+ for (uint i = 0; i < idcount; i++) {
+ houses[i] = grf_load_byte(&buf);
}
+ /* Skip the cargo type section, we only care about the default group */
+ uint8 cidcount = grf_load_byte(&buf);
+ buf += cidcount * 3;
+
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return;
+
for (uint i = 0; i < idcount; i++) {
- uint8 hid = buf[3 + i];
- HouseSpec *hs = _cur_grffile->housespec[hid];
+ HouseSpec *hs = _cur_grffile->housespec[houses[i]];
if (hs == NULL) {
grfmsg(1, "TownHouseMapSpriteGroup: Too many houses defined, skipping");
@@ -3089,20 +3089,22 @@
}
}
-static void IndustryMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void IndustryMapSpriteGroup(byte *buf, uint8 idcount)
{
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "IndustryMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ uint8 *industries = (uint8*)alloca(idcount * sizeof(*industries));
+ for (uint i = 0; i < idcount; i++) {
+ industries[i] = grf_load_byte(&buf);
}
+ /* Skip the cargo type section, we only care about the default group */
+ uint8 cidcount = grf_load_byte(&buf);
+ buf += cidcount * 3;
+
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return;
+
for (uint i = 0; i < idcount; i++) {
- uint8 id = buf[3 + i];
- IndustrySpec *indsp = _cur_grffile->industryspec[id];
+ IndustrySpec *indsp = _cur_grffile->industryspec[industries[i]];
if (indsp == NULL) {
grfmsg(1, "IndustryMapSpriteGroup: Too many industries defined, skipping");
@@ -3113,20 +3115,22 @@
}
}
-static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount)
{
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "IndustrytileMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ uint8 *indtiles = (uint8*)alloca(idcount * sizeof(*indtiles));
+ for (uint i = 0; i < idcount; i++) {
+ indtiles[i] = grf_load_byte(&buf);
}
+ /* Skip the cargo type section, we only care about the default group */
+ uint8 cidcount = grf_load_byte(&buf);
+ buf += cidcount * 3;
+
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return;
+
for (uint i = 0; i < idcount; i++) {
- uint8 id = buf[3 + i];
- IndustryTileSpec *indtsp = _cur_grffile->indtspec[id];
+ IndustryTileSpec *indtsp = _cur_grffile->indtspec[indtiles[i]];
if (indtsp == NULL) {
grfmsg(1, "IndustrytileMapSpriteGroup: Too many industry tiles defined, skipping");
@@ -3137,22 +3141,25 @@
}
}
-static void CargoMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void CargoMapSpriteGroup(byte *buf, uint8 idcount)
{
- byte *bp = &buf[4 + idcount + cidcount * 3];
- uint16 groupid = grf_load_word(&bp);
-
- if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "CargoMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
- groupid, _cur_grffile->spritegroups_count);
- return;
+ CargoID *cargos = (CargoID*)alloca(idcount * sizeof(*cargos));
+ for (uint i = 0; i < idcount; i++) {
+ cargos[i] = grf_load_byte(&buf);
}
+ /* Skip the cargo type section, we only care about the default group */
+ uint8 cidcount = grf_load_byte(&buf);
+ buf += cidcount * 3;
+
+ uint16 groupid = grf_load_word(&buf);
+ if (!IsValidGroupID(groupid, "CargoMapSpriteGroup")) return;
+
for (uint i = 0; i < idcount; i++) {
- CargoID cid = buf[3 + i];
+ CargoID cid = cargos[i];
if (cid >= NUM_CARGO) {
- grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping");
+ grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping", cid);
continue;
}
@@ -3187,16 +3194,15 @@
if (!check_length(len, 6, "FeatureMapSpriteGroup")) return;
- uint8 feature = buf[1];
- uint8 idcount = buf[2] & 0x7F;
- bool wagover = (buf[2] & 0x80) == 0x80;
-
- if (!check_length(len, 3 + idcount, "FeatureMapSpriteGroup")) return;
+ buf++;
+ uint8 feature = grf_load_byte(&buf);
+ uint8 idcount = grf_load_byte(&buf);
/* If idcount is zero, this is a feature callback */
if (idcount == 0) {
- byte *bp = &buf[4];
- uint16 groupid = grf_load_word(&bp);
+ /* Skip number of cargo ids? */
+ grf_load_byte(&buf);
+ uint16 groupid = grf_load_word(&buf);
grfmsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature %d", feature);
@@ -3204,42 +3210,38 @@
return;
}
- uint8 cidcount = buf[3 + idcount];
- if (!check_length(len, 4 + idcount + cidcount * 3, "FeatureMapSpriteGroup")) return;
-
- grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d",
- feature, idcount, cidcount, wagover);
+ grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids", feature, idcount);
switch (feature) {
case GSF_TRAIN:
case GSF_ROAD:
case GSF_SHIP:
case GSF_AIRCRAFT:
- VehicleMapSpriteGroup(buf, feature, idcount, cidcount, wagover);
+ VehicleMapSpriteGroup(buf, feature, idcount);
return;
case GSF_CANAL:
- CanalMapSpriteGroup(buf, idcount, cidcount);
+ CanalMapSpriteGroup(buf, idcount);
return;
case GSF_STATION:
- StationMapSpriteGroup(buf, idcount, cidcount);
+ StationMapSpriteGroup(buf, idcount);
return;
case GSF_TOWNHOUSE:
- TownHouseMapSpriteGroup(buf, idcount, cidcount);
+ TownHouseMapSpriteGroup(buf, idcount);
return;
case GSF_INDUSTRIES:
- IndustryMapSpriteGroup(buf, idcount, cidcount);
+ IndustryMapSpriteGroup(buf, idcount);
return;
case GSF_INDUSTRYTILES:
- IndustrytileMapSpriteGroup(buf, idcount, cidcount);
+ IndustrytileMapSpriteGroup(buf, idcount);
return;
case GSF_CARGOS:
- CargoMapSpriteGroup(buf, idcount, cidcount);
+ CargoMapSpriteGroup(buf, idcount);
return;
default:
@@ -3299,7 +3301,7 @@
case GSF_ROAD:
case GSF_SHIP:
case GSF_AIRCRAFT:
- if (id < GetEnginePoolSize()) {
+ if (!generic) {
Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, id);
StringID string = AddGRFString(_cur_grffile->grfid, e->index, lang, new_scheme, name, e->info.string_id);
e->info.string_id = string;
@@ -3462,16 +3464,16 @@
/* Special not-TTDP-compatible case used in openttd(d/w).grf
* Missing shore sprites and initialisation of SPR_SHORE_BASE */
grfmsg(2, "GraphicsNew: Loading 10 missing shore sprites from openttd(d/w).grf.");
- LoadNextSprite( SPR_SHORE_BASE + 0, _file_index, _nfo_line++); // SLOPE_STEEP_S
- LoadNextSprite( SPR_SHORE_BASE + 5, _file_index, _nfo_line++); // SLOPE_STEEP_W
- LoadNextSprite( SPR_SHORE_BASE + 7, _file_index, _nfo_line++); // SLOPE_WSE
- LoadNextSprite( SPR_SHORE_BASE + 10, _file_index, _nfo_line++); // SLOPE_STEEP_N
- LoadNextSprite( SPR_SHORE_BASE + 11, _file_index, _nfo_line++); // SLOPE_NWS
- LoadNextSprite( SPR_SHORE_BASE + 13, _file_index, _nfo_line++); // SLOPE_ENW
- LoadNextSprite( SPR_SHORE_BASE + 14, _file_index, _nfo_line++); // SLOPE_SEN
- LoadNextSprite( SPR_SHORE_BASE + 15, _file_index, _nfo_line++); // SLOPE_STEEP_E
- LoadNextSprite( SPR_SHORE_BASE + 16, _file_index, _nfo_line++); // SLOPE_EW
- LoadNextSprite( SPR_SHORE_BASE + 17, _file_index, _nfo_line++); // SLOPE_NS
+ LoadNextSprite(SPR_SHORE_BASE + 0, _file_index, _nfo_line++); // SLOPE_STEEP_S
+ LoadNextSprite(SPR_SHORE_BASE + 5, _file_index, _nfo_line++); // SLOPE_STEEP_W
+ LoadNextSprite(SPR_SHORE_BASE + 7, _file_index, _nfo_line++); // SLOPE_WSE
+ LoadNextSprite(SPR_SHORE_BASE + 10, _file_index, _nfo_line++); // SLOPE_STEEP_N
+ LoadNextSprite(SPR_SHORE_BASE + 11, _file_index, _nfo_line++); // SLOPE_NWS
+ LoadNextSprite(SPR_SHORE_BASE + 13, _file_index, _nfo_line++); // SLOPE_ENW
+ LoadNextSprite(SPR_SHORE_BASE + 14, _file_index, _nfo_line++); // SLOPE_SEN
+ LoadNextSprite(SPR_SHORE_BASE + 15, _file_index, _nfo_line++); // SLOPE_STEEP_E
+ LoadNextSprite(SPR_SHORE_BASE + 16, _file_index, _nfo_line++); // SLOPE_EW
+ LoadNextSprite(SPR_SHORE_BASE + 17, _file_index, _nfo_line++); // SLOPE_NS
if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ONLY_NEW;
return;
}
@@ -3646,6 +3648,14 @@
*value = _settings_game.difficulty.diff_level;
return true;
+ case 0x23: // long format date
+ *value = _date;
+ return true;
+
+ case 0x24: // long format year
+ *value = _cur_year;
+ return true;
+
default: return false;
}
}
@@ -5582,7 +5592,7 @@
* On the other hand, why 1930? Just 'fix' the houses with the lowest
* minimum introduction date to 0.
*/
- Year min_date = MAX_YEAR;
+ Year min_year = MAX_YEAR;
for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
if (file->housespec == NULL) continue;
@@ -5591,16 +5601,16 @@
HouseSpec *hs = file->housespec[i];
if (hs != NULL) {
_house_mngr.SetEntitySpec(hs);
- if (hs->min_date < min_date) min_date = hs->min_date;
+ if (hs->min_year < min_year) min_year = hs->min_year;
}
}
}
- if (min_date != 0) {
+ if (min_year != 0) {
for (int i = 0; i < HOUSE_MAX; i++) {
HouseSpec *hs = GetHouseSpecs(i);
- if (hs->enabled && hs->min_date == min_date) hs->min_date = 0;
+ if (hs->enabled && hs->min_year == min_year) hs->min_year = 0;
}
}
}
--- a/src/newgrf_config.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_config.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -8,11 +8,12 @@
#include "variables.h"
#include "saveload.h"
#include "md5.h"
-#include "network/network_data.h"
#include "newgrf.h"
#include "newgrf_config.h"
#include "core/alloc_func.hpp"
#include "string_func.h"
+#include "gamelog.h"
+#include "network/network_type.h"
#include "fileio.h"
#include "fios.h"
@@ -231,6 +232,7 @@
/* Non-found has precedence over compatibility load */
if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
+ GamelogGRFCompatible(f);
goto compatible_grf;
}
@@ -238,6 +240,8 @@
md5sumToString(buf, lastof(buf), c->md5sum);
DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf);
+ GamelogGRFRemove(c->grfid);
+
c->status = GCS_NOT_FOUND;
res = GLC_NOT_FOUND;
} else {
--- a/src/newgrf_engine.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_engine.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -476,6 +476,7 @@
case 0x43: return _current_player | (LiveryHelper(object->u.vehicle.self_type, NULL) << 24); // Owner information
case 0x46: return 0; // Motion counter
case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
+ case 0x49: return _cur_year; // 'Long' format build year
case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
case 0xDA: return INVALID_VEHICLE; // Next vehicle
case 0x7F: return GetGRFParameter(object->u.vehicle.self_type, parameter); // Read GRF parameter
@@ -616,6 +617,7 @@
}
case 0x48: return GetEngine(v->engine_type)->flags; // Vehicle Type Info
+ case 0x49: return v->build_year;
/* Variables which use the parameter */
case 0x60: // Count consist's engine ID occurance
@@ -886,23 +888,19 @@
SpriteID GetRotorOverrideSprite(EngineID engine, const Vehicle *v, bool info_view)
{
- #if !defined(NDEBUG) || defined(WITH_ASSERT)
const Engine *e = GetEngine(engine);
- #endif /* !defined(NDEBUG) || defined(WITH_ASSERT) */
-
- const SpriteGroup *group;
- ResolverObject object;
-
- assert(e->type == VEH_AIRCRAFT);
/* Only valid for helicopters */
+ assert(e->type == VEH_AIRCRAFT);
assert(!(e->u.air.subtype & AIR_CTOL));
+ ResolverObject object;
+
NewVehicleResolver(&object, engine, v);
object.info_view = info_view;
- group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
+ const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
group = Resolve(group, &object);
if (group == NULL || group->type != SGT_RESULT) return 0;
--- a/src/newgrf_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -15,6 +15,7 @@
#include "core/alloc_func.hpp"
#include "string_func.h"
#include "gfx_func.h"
+#include "gamelog.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -564,8 +565,11 @@
GRFConfig *c;
int i = 0;
+ GamelogStartAction(GLAT_GRF);
+ GamelogGRFUpdate(_grfconfig, nw->list); // log GRF changes
CopyGRFConfigList(nw->orig_list, nw->list, false);
ReloadNewGRFData();
+ GamelogStopAction();
/* Show new, updated list */
for (c = nw->list; c != NULL && c != nw->sel; c = c->next, i++) {}
--- a/src/news_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/news_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -168,9 +168,11 @@
struct NewsWindow : Window {
uint16 chat_height;
NewsItem *ni;
+ static uint duration;
NewsWindow(const WindowDesc *desc, NewsItem *ni) : Window(desc), ni(ni)
{
+ NewsWindow::duration = 555;
const Window *w = FindWindowById(WC_SEND_NETWORK_MSG, 0);
this->chat_height = (w != NULL) ? w->height : 0;
@@ -258,7 +260,7 @@
{
switch (widget) {
case 1:
- this->ni->duration = 0;
+ NewsWindow::duration = 0;
delete this;
_forced_news = NULL;
break;
@@ -314,6 +316,8 @@
}
};
+/* static */ uint NewsWindow::duration; ///< Remaining time for showing current news message
+
static const Widget _news_type13_widgets[] = {
{ WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL},
@@ -360,9 +364,6 @@
/** Open up an own newspaper window for the news item */
static void ShowNewspaper(NewsItem *ni)
{
- ni->flags &= ~NF_FORCE_BIG;
- ni->duration = 555;
-
SoundFx sound = _news_type_data[_news_subtype_data[ni->subtype].type].sound;
if (sound != 0) SndPlayFx(sound);
@@ -438,10 +439,10 @@
if (IsNewsTickerShown()) return false;
/* Newspaper message, decrement duration counter */
- if (ni->duration != 0) ni->duration--;
+ if (NewsWindow::duration != 0) NewsWindow::duration--;
/* neither newsticker nor newspaper are running */
- return (ni->duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
+ return (NewsWindow::duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
}
/** Move to the next news item */
@@ -465,12 +466,9 @@
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_REMINDER);
break;
- case ND_SUMMARY: // Summary - show ticker, but if forced big, cascade to full
- if (!(ni->flags & NF_FORCE_BIG)) {
- ShowTicker(ni);
- break;
- }
- /* Fallthrough */
+ case ND_SUMMARY: // Summary - show ticker
+ ShowTicker(ni);
+ break;
case ND_FULL: // Full - show newspaper
ShowNewspaper(ni);
@@ -613,8 +611,6 @@
_forced_news = ni;
if (_forced_news != NULL) {
- ni->duration = 555;
- ni->flags |= NF_FORCE_BIG;
DeleteWindowById(WC_NEWS_WINDOW, 0);
ShowNewspaper(ni);
}
--- a/src/news_type.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/news_type.h Wed Jun 04 22:34:45 2008 +0000
@@ -74,7 +74,6 @@
NF_VIEWPORT = (1 << 1), ///< Does the news message have a viewport? (ingame picture of happening)
NF_TILE = (1 << 2), ///< When clicked on the news message scroll to a given tile? Tile is in data_a
NF_VEHICLE = (1 << 3), ///< When clicked on the message scroll to the vehicle? VehicleID is in data_a
- NF_FORCE_BIG = (1 << 4), ///< Force the appearance of a news message if it has already been shown (internal)
NF_INCOLOR = (1 << 5), ///< Show the newsmessage in colour, otherwise it defaults to black & white
NF_TILE2 = (1 << 6), ///< There is a second tile to scroll to; tile is in data_b
};
@@ -104,7 +103,6 @@
NewsItem *prev; ///< Previous news item
NewsItem *next; ///< Next news item
StringID string_id; ///< Message text
- uint16 duration; ///< Remaining time for showing this news message
Date date; ///< Date of the news
NewsSubtype subtype; ///< News subtype @see NewsSubtype
NewsFlag flags; ///< NewsFlags bits @see NewsFlag
--- a/src/openttd.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/openttd.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -6,7 +6,6 @@
#define VARDEF
#include "variables.h"
-#include "network/network_internal.h"
#undef VARDEF
#include "openttd.h"
@@ -41,6 +40,7 @@
#include "console_func.h"
#include "screenshot.h"
#include "network/network.h"
+#include "network/network_func.h"
#include "signs_base.h"
#include "signs_func.h"
#include "waypoint.h"
@@ -54,6 +54,7 @@
#include "strings_func.h"
#include "date_func.h"
#include "vehicle_func.h"
+#include "gamelog.h"
#include "cheat_func.h"
#include "animated_tile_func.h"
#include "functions.h"
@@ -311,6 +312,7 @@
UnInitializeAirports();
/* Uninitialize variables that are allocated dynamically */
+ GamelogReset();
_Town_pool.CleanPool();
_Industry_pool.CleanPool();
_Station_pool.CleanPool();
@@ -495,8 +497,8 @@
if (_cur_resolution[1] == 0) _cur_resolution[1] = 1;
#if defined(ENABLE_NETWORK)
- if (dedicated_host) snprintf(_network_server_bind_ip_host, NETWORK_HOSTNAME_LENGTH, "%s", dedicated_host);
- if (dedicated_port) _network_server_port = dedicated_port;
+ if (dedicated_host) snprintf(_settings_client.network.server_bind_ip, sizeof(_settings_client.network.server_bind_ip), "%s", dedicated_host);
+ if (dedicated_port) _settings_client.network.server_port = dedicated_port;
if (_dedicated_forks && !dedicated) _dedicated_forks = false;
#endif /* ENABLE_NETWORK */
@@ -690,8 +692,8 @@
#ifdef ENABLE_NETWORK
/* We are the server, we start a new player (not dedicated),
* so set the default password *if* needed. */
- if (_network_server && !StrEmpty(_network_default_company_pass)) {
- char *password = _network_default_company_pass;
+ if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
+ char *password = _settings_client.network.default_company_pass;
NetworkChangeCompanyPassword(1, &password);
}
#endif /* ENABLE_NETWORK */
@@ -820,10 +822,8 @@
if (_networking) {
if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
NetworkReboot();
- NetworkUDPCloseAll();
} else {
NetworkDisconnect();
- NetworkUDPCloseAll();
}
}
@@ -832,7 +832,7 @@
/* But not if we are going to the menu */
if (new_mode != SM_MENU) {
/* check if we should reload the config */
- if (_network_reload_cfg) {
+ if (_settings_client.network.reload_cfg) {
LoadFromConfig();
_settings_game = _settings_newgame;
ResetGRFConfig(false);
@@ -1113,7 +1113,7 @@
if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host
* We do this here, because it means that the network is really closed */
- NetworkClientConnectGame(_network_last_host, _network_last_port);
+ NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
}
/* Singleplayer */
StateGameLoop();
@@ -1270,6 +1270,13 @@
TileIndex map_size = MapSize();
Player *p;
+ if (CheckSavegameVersion(98)) GamelogOldver();
+
+ GamelogTestRevision();
+ GamelogTestMode();
+
+ if (CheckSavegameVersion(98)) GamelogGRFAddList(_grfconfig);
+
/* in version 2.1 of the savegame, town owner was unified. */
if (CheckSavegameVersionOldStyle(2, 1)) ConvertTownOwner();
@@ -2433,6 +2440,8 @@
}
}
+ if (_debug_gamelog_level > 0) GamelogPrintDebug();
+
return InitializeWindowsAndCaches();
}
--- a/src/openttd.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/openttd.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,10 +5,6 @@
#ifndef OPENTTD_H
#define OPENTTD_H
-#ifndef VARDEF
-#define VARDEF extern
-#endif
-
enum GameModes {
GM_MENU,
GM_NORMAL,
--- a/src/order_cmd.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/order_cmd.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -1613,6 +1613,95 @@
}
/**
+ * Process a conditional order and determine the next order.
+ * @param order the order the vehicle currently has
+ * @param v the vehicle to update
+ * @return index of next order to jump to, or INVALID_VEH_ORDER_ID to use the next order
+ */
+static VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
+{
+ if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
+
+ bool skip_order = false;
+ OrderConditionComparator occ = order->GetConditionComparator();
+ uint16 value = order->GetConditionValue();
+
+ switch (order->GetConditionVariable()) {
+ case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
+ case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16, value); break;
+ case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(), value); break;
+ case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / 366, value); break;
+ case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
+ case OCV_UNCONDITIONALLY: skip_order = true; break;
+ default: NOT_REACHED();
+ }
+
+ return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
+}
+
+/**
+ * Update the vehicle's destination tile from an order.
+ * @param order the order the vehicle currently has
+ * @param v the vehicle to update
+ */
+static bool UpdateOrderDest(Vehicle *v, const Order *order)
+{
+ switch (order->GetType()) {
+ case OT_GOTO_STATION:
+ v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
+ break;
+
+ case OT_GOTO_DEPOT:
+ if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
+ /* We need to search for the nearest depot (hangar). */
+ TileIndex location;
+ DestinationID destination;
+ bool reverse;
+
+ if (v->FindClosestDepot(&location, &destination, &reverse)) {
+ v->dest_tile = location;
+ v->current_order.MakeGoToDepot(destination, ODTFB_PART_OF_ORDERS);
+
+ /* If there is no depot in front, reverse automatically (trains only) */
+ if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
+
+ if (v->type == VEH_AIRCRAFT && v->u.air.state == FLYING && v->u.air.targetairport != destination) {
+ /* The aircraft is now heading for a different hangar than the next in the orders */
+ extern void AircraftNextAirportPos_and_Order(Vehicle *v);
+ AircraftNextAirportPos_and_Order(v);
+ }
+ } else {
+ UpdateVehicleTimetable(v, true);
+ v->cur_order_index++;
+ }
+ } else if (v->type != VEH_AIRCRAFT) {
+ v->dest_tile = GetDepot(order->GetDestination())->xy;
+ }
+ break;
+
+ case OT_GOTO_WAYPOINT:
+ v->dest_tile = GetWaypoint(order->GetDestination())->xy;
+ break;
+
+ case OT_CONDITIONAL: {
+ VehicleOrderID next_order = ProcessConditionalOrder(order, v);
+ UpdateVehicleTimetable(v, true);
+ if (next_order != INVALID_VEH_ORDER_ID) {
+ v->cur_order_index = next_order;
+ } else {
+ v->cur_order_index++;
+ }
+ return false;
+ }
+
+ default:
+ v->dest_tile = 0;
+ return false;
+ }
+ return true;
+}
+
+/**
* Handle the orders of a vehicle and determine the next place
* to go to if needed.
* @param v the vehicle to do this for.
@@ -1710,71 +1799,7 @@
break;
}
- switch (order->GetType()) {
- case OT_GOTO_STATION:
- v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
- break;
-
- case OT_GOTO_DEPOT:
- if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
- /* We need to search for the nearest depot (hangar). */
- TileIndex location;
- DestinationID destination;
- bool reverse;
-
- if (v->FindClosestDepot(&location, &destination, &reverse)) {
- v->dest_tile = location;
- v->current_order.MakeGoToDepot(destination, ODTFB_PART_OF_ORDERS);
-
- /* If there is no depot in front, reverse automatically (trains only) */
- if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
-
- if (v->type == VEH_AIRCRAFT && v->u.air.state == FLYING && v->u.air.targetairport != destination) {
- /* The aircraft is now heading for a different hangar than the next in the orders */
- extern void AircraftNextAirportPos_and_Order(Vehicle *v);
- AircraftNextAirportPos_and_Order(v);
- }
- } else {
- UpdateVehicleTimetable(v, true);
- v->cur_order_index++;
- }
- } else if (v->type != VEH_AIRCRAFT) {
- v->dest_tile = GetDepot(order->GetDestination())->xy;
- }
- break;
-
- case OT_GOTO_WAYPOINT:
- v->dest_tile = GetWaypoint(order->GetDestination())->xy;
- break;
-
- case OT_CONDITIONAL: {
- bool skip_order = false;
- OrderConditionComparator occ = order->GetConditionComparator();
- uint16 value = order->GetConditionValue();
-
- switch (order->GetConditionVariable()) {
- case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
- case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16, value); break;
- case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(), value); break;
- case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / 366, value); break;
- case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
- case OCV_UNCONDITIONALLY: skip_order = true; break;
- default: NOT_REACHED();
- }
- UpdateVehicleTimetable(v, true);
- if (skip_order) {
- v->cur_order_index = order->GetConditionSkipToOrder();
- } else {
- v->cur_order_index++;
- }
- } return false;
-
- default:
- v->dest_tile = 0;
- return false;
- }
-
- return may_reverse;
+ return UpdateOrderDest(v, order) && may_reverse;
}
/**
--- a/src/os2.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/os2.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -67,7 +67,7 @@
#endif
if (disk == disk2) {
- FiosItem *fios = FiosAlloc();
+ FiosItem *fios = _fios_items.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
#ifndef __INNOTEK_LIBC__
--- a/src/ottdres.rc.in Mon Jun 02 01:46:03 2008 +0000
+++ b/src/ottdres.rc.in Wed Jun 04 22:34:45 2008 +0000
@@ -65,8 +65,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,6,0,@@REVISION@@
- PRODUCTVERSION 0,6,0,@@REVISION@@
+ FILEVERSION 0,7,0,@@REVISION@@
+ PRODUCTVERSION 0,7,0,@@REVISION@@
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
--- a/src/player_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/player_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -13,14 +13,12 @@
#include "player_base.h"
#include "command_func.h"
#include "network/network.h"
+#include "network/network_gui.h"
#include "variables.h"
#include "roadveh.h"
#include "train.h"
#include "aircraft.h"
#include "newgrf.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_gui.h"
#include "player_face.h"
#include "strings_func.h"
#include "functions.h"
--- a/src/players.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/players.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -13,7 +13,7 @@
#include "saveload.h"
#include "command_func.h"
#include "network/network.h"
-#include "network/network_internal.h"
+#include "network/network_func.h"
#include "variables.h"
#include "cheat_func.h"
#include "ai/ai.h"
@@ -863,8 +863,8 @@
assert(_local_player == PLAYER_SPECTATOR);
SetLocalPlayer(p->index);
#ifdef ENABLE_NETWORK
- if (!StrEmpty(_network_default_company_pass)) {
- char *password = _network_default_company_pass;
+ if (!StrEmpty(_settings_client.network.default_company_pass)) {
+ char *password = _settings_client.network.default_company_pass;
NetworkChangeCompanyPassword(1, &password);
}
#endif /* ENABLE_NETWORK */
--- a/src/rail_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rail_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -1649,7 +1649,7 @@
{ WWT_PANEL, RESIZE_NONE, 7, 207, 272, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP}, // BRWW_WAYPOINT_4
{ WWT_PANEL, RESIZE_NONE, 7, 275, 340, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP}, // BRWW_WAYPOINT_5
-{ WWT_HSCROLLBAR, RESIZE_NONE, 7, 1, 343, 80, 91, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BRWW_SCROLL
+{ WWT_HSCROLLBAR, RESIZE_NONE, 7, 1, 343, 80, 91, 0x0, STR_HSCROLL_BAR_SCROLLS_LIST}, // BRWW_SCROLL
{ WIDGETS_END},
};
--- a/src/rev.cpp.in Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rev.cpp.in Wed Jun 04 22:34:45 2008 +0000
@@ -23,6 +23,16 @@
const char _openttd_revision[] = "@@VERSION@@";
/**
+ * Let us know if current build was modified. This detection
+ * works even in the case when revision string is overriden by
+ * --revision argument.
+ * Value 0 means no modification, 1 is for unknown state
+ * (compiling from sources without any version control software)
+ * and 2 is for modified revision.
+ */
+const byte _openttd_revision_modified = @@MODIFIED@@;
+
+/**
* The NewGRF revision of OTTD:
* bits meaning.
* 28-31 major version
--- a/src/rev.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rev.h Wed Jun 04 22:34:45 2008 +0000
@@ -6,6 +6,7 @@
#define REV_H
extern const char _openttd_revision[];
+extern const byte _openttd_revision_modified;
extern const uint32 _openttd_newgrf_version;
#endif /* REV_H */
--- a/src/road_cmd.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/road_cmd.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -69,7 +69,7 @@
if (flags & DC_EXEC) {
if (_game_mode == GM_MENU) {
- _settings_game.vehicle.road_side = p1;
+ _settings_newgame.vehicle.road_side = p1;
} else {
_settings_game.vehicle.road_side = p1;
}
--- a/src/saveload.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/saveload.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -32,10 +32,11 @@
#include "autoreplace_base.h"
#include "statusbar_gui.h"
#include <list>
+#include "gamelog.h"
#include "table/strings.h"
-extern const uint16 SAVEGAME_VERSION = 97;
+extern const uint16 SAVEGAME_VERSION = 98;
SavegameType _savegame_type; ///< type of savegame we are loading
@@ -651,10 +652,18 @@
/* NOTICE - handle some buggy stuff, in really old versions everything was saved
* as a byte-type. So detect this, and adjust array size accordingly */
if (!_sl.save && _sl_version == 0) {
+ /* all arrays except difficulty settings */
if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
conv == SLE_INT32 || conv == SLE_UINT32) {
- length *= SlCalcConvFileLen(conv);
- conv = SLE_INT8;
+ SlCopyBytes(array, length * SlCalcConvFileLen(conv));
+ return;
+ }
+ /* used for conversion of Money 32bit->64bit */
+ if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
+ for (uint i = 0; i < length; i++) {
+ ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
+ }
+ return;
}
}
@@ -757,7 +766,7 @@
* @param sld The SaveLoad description of the object so we know how to manipulate it
* @return size of given objetc
*/
-static size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
+size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
{
size_t length = 0;
@@ -1278,6 +1287,7 @@
*******************************************/
/* these define the chunks */
+extern const ChunkHandler _gamelog_chunk_handlers[];
extern const ChunkHandler _misc_chunk_handlers[];
extern const ChunkHandler _name_chunk_handlers[];
extern const ChunkHandler _cheat_chunk_handlers[] ;
@@ -1299,6 +1309,7 @@
extern const ChunkHandler _cargopacket_chunk_handlers[];
static const ChunkHandler * const _chunk_handlers[] = {
+ _gamelog_chunk_handlers,
_misc_chunk_handlers,
_name_chunk_handlers,
_cheat_chunk_handlers,
@@ -1635,10 +1646,16 @@
/* Load a TTDLX or TTDPatch game */
if (mode == SL_OLD_LOAD) {
InitializeGame(256, 256, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
+ GamelogReset();
if (!LoadOldSaveGame(filename)) return SL_REINIT;
_sl_version = 0;
_sl_minor_version = 0;
- if (!AfterLoadGame()) return SL_REINIT;
+ GamelogStartAction(GLAT_LOAD);
+ if (!AfterLoadGame()) {
+ GamelogStopAction();
+ return SL_REINIT;
+ }
+ GamelogStopAction();
return SL_OK;
}
@@ -1749,15 +1766,24 @@
* confuse old games */
InitializeGame(256, 256, true);
+ GamelogReset();
+
SlLoadChunks();
fmt->uninit_read();
fclose(_sl.fh);
+ GamelogStartAction(GLAT_LOAD);
+
_savegame_type = SGT_OTTD;
/* After loading fix up savegame for any internal changes that
* might've occured since then. If it fails, load back the old game */
- if (!AfterLoadGame()) return SL_REINIT;
+ if (!AfterLoadGame()) {
+ GamelogStopAction();
+ return SL_REINIT;
+ }
+
+ GamelogStopAction();
}
return SL_OK;
--- a/src/saveload.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/saveload.h Wed Jun 04 22:34:45 2008 +0000
@@ -318,6 +318,7 @@
size_t SlGetFieldLength();
void SlSetLength(size_t length);
size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld);
+size_t SlCalcObjLength(const void *object, const SaveLoad *sld);
byte SlReadByte();
void SlWriteByte(byte b);
--- a/src/settings.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,7 @@
#include "screenshot.h"
#include "variables.h"
#include "network/network.h"
-#include "network/network_internal.h"
+#include "network/network_func.h"
#include "settings_internal.h"
#include "command_func.h"
#include "console_func.h"
@@ -60,6 +60,7 @@
#include "sound/sound_driver.hpp"
#include "music/music_driver.hpp"
#include "blitter/factory.hpp"
+#include "gamelog.h"
#include "station_func.h"
#include "table/strings.h"
@@ -1124,27 +1125,27 @@
#define SDTC_CONDVAR(var, type, from, to, flags, guiflags, def, min, max, interval, str, proc)\
- SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 0, def, min, max, interval, NULL, str, proc, from, to)
+ SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, NULL, str, proc, from, to)
#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, proc)\
SDTC_CONDVAR(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, min, max, interval, str, proc)
#define SDTC_CONDBOOL(var, from, to, flags, guiflags, def, str, proc)\
- SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 0, def, 0, 1, 0, NULL, str, proc, from, to)
+ SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, NULL, str, proc, from, to)
#define SDTC_BOOL(var, flags, guiflags, def, str, proc)\
SDTC_CONDBOOL(var, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
#define SDTC_CONDLIST(var, type, length, flags, guiflags, def, str, proc, from, to)\
SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
#define SDTC_LIST(var, type, flags, guiflags, def, str, proc)\
- SDTG_GENERAL(var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+ SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
#define SDTC_CONDSTR(var, type, length, flags, guiflags, def, str, proc, from, to)\
SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
#define SDTC_STR(var, type, flags, guiflags, def, str, proc)\
- SDTG_GENERAL(var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+ SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
#define SDTC_CONDOMANY(var, type, from, to, flags, guiflags, def, max, full, str, proc)\
- SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 0, def, 0, max, 0, full, str, proc, from, to)
+ SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, proc, from, to)
#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, proc)\
SDTC_CONDOMANY(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, max, full, str, proc)
@@ -1427,6 +1428,41 @@
return 0;
}
+#ifdef ENABLE_NETWORK
+
+static int32 UpdateMinPlayers(int32 p1)
+{
+ CheckMinPlayers();
+ return 0;
+}
+
+static int32 UpdatePlayerName(int32 p1)
+{
+ NetworkUpdatePlayerName();
+ return 0;
+}
+
+static int32 UpdateServerPassword(int32 p1)
+{
+ if (strcmp(_settings_client.network.server_password, "*") == 0) {
+ _settings_client.network.server_password[0] = '\0';
+ }
+
+ return 0;
+}
+
+static int32 UpdateRconPassword(int32 p1)
+{
+ if (strcmp(_settings_client.network.rcon_password, "*") == 0) {
+ _settings_client.network.rcon_password[0] = '\0';
+ }
+
+ return 0;
+}
+
+#endif /* ENABLE_NETWORK */
+
+
/* End - Callback Functions */
#ifndef EXTERNAL_PLAYER
@@ -1493,39 +1529,6 @@
SDTG_END()
};
-#ifdef ENABLE_NETWORK
-static const SettingDescGlobVarList _network_settings[] = {
- SDTG_VAR("sync_freq", SLE_UINT16,C|S,0, _network_sync_freq, 100, 0, 100, 0, STR_NULL, NULL),
- SDTG_VAR("frame_freq", SLE_UINT8,C|S,0, _network_frame_freq, 0, 0, 100, 0, STR_NULL, NULL),
- SDTG_VAR("max_join_time", SLE_UINT16, S, 0, _network_max_join_time, 500, 0, 32000, 0, STR_NULL, NULL),
- SDTG_BOOL("pause_on_join", S, 0, _network_pause_on_join, true, STR_NULL, NULL),
- SDTG_STR("server_bind_ip", SLE_STRB, S, 0, _network_server_bind_ip_host, "0.0.0.0", STR_NULL, NULL),
- SDTG_VAR("server_port", SLE_UINT16, S, 0, _network_server_port, NETWORK_DEFAULT_PORT, 0, 65535, 0, STR_NULL, NULL),
- SDTG_BOOL("server_advertise", S, 0, _network_advertise, false, STR_NULL, NULL),
- SDTG_VAR("lan_internet", SLE_UINT8, S, 0, _network_lan_internet, 0, 0, 1, 0, STR_NULL, NULL),
- SDTG_STR("player_name", SLE_STRB, S, 0, _network_player_name, NULL, STR_NULL, NULL),
- SDTG_STR("server_password", SLE_STRB, S, 0, _network_server_password, NULL, STR_NULL, NULL),
- SDTG_STR("rcon_password", SLE_STRB, S, 0, _network_rcon_password, NULL, STR_NULL, NULL),
- SDTG_STR("default_company_pass", SLE_STRB, S, 0, _network_default_company_pass, NULL, STR_NULL, NULL),
- SDTG_STR("server_name", SLE_STRB, S, 0, _network_server_name, NULL, STR_NULL, NULL),
- SDTG_STR("connect_to_ip", SLE_STRB, S, 0, _network_default_ip, NULL, STR_NULL, NULL),
- SDTG_STR("network_id", SLE_STRB, S, 0, _network_unique_id, NULL, STR_NULL, NULL),
- SDTG_BOOL("autoclean_companies", S, 0, _network_autoclean_companies, false, STR_NULL, NULL),
- SDTG_VAR("autoclean_unprotected",SLE_UINT8, S, 0, _network_autoclean_unprotected,12, 0, 60, 0, STR_NULL, NULL),
- SDTG_VAR("autoclean_protected", SLE_UINT8, S, 0, _network_autoclean_protected, 36, 0, 180, 0, STR_NULL, NULL),
- SDTG_VAR("max_companies", SLE_UINT8, S, 0, _network_game_info.companies_max, 8, 1, MAX_PLAYERS, 0, STR_NULL, NULL),
- SDTG_VAR("max_clients", SLE_UINT8, S, 0, _network_game_info.clients_max, 10, 2, MAX_CLIENTS, 0, STR_NULL, NULL),
- SDTG_VAR("max_spectators", SLE_UINT8, S, 0, _network_game_info.spectators_max, 10, 0, MAX_CLIENTS, 0, STR_NULL, NULL),
- SDTG_VAR("restart_game_year", SLE_INT32, S,D0, _network_restart_game_year, 0, MIN_YEAR, MAX_YEAR, 1, STR_NULL, NULL),
- SDTG_VAR("min_players", SLE_UINT8, S, 0, _network_min_players, 0, 0, 10, 0, STR_NULL, NULL),
- SDTG_OMANY("server_lang", SLE_UINT8, S, 0, _network_game_info.server_lang, 0, 35, "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN", STR_NULL, NULL),
- SDTG_BOOL("reload_cfg", S, 0, _network_reload_cfg, false, STR_NULL, NULL),
- SDTG_STR("last_host", SLE_STRB, S, 0, _network_last_host, "0.0.0.0", STR_NULL, NULL),
- SDTG_VAR("last_port", SLE_UINT16, S, 0, _network_last_port, 0, 0, UINT16_MAX, 0, STR_NULL ,NULL),
- SDTG_END()
-};
-#endif /* ENABLE_NETWORK */
-
static const uint GAME_DIFFICULTY_NUM = 18;
uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
@@ -1549,7 +1552,7 @@
SDT_OMANY(GameSettings, game_creation.town_name, SLE_UINT8, 0, 0, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
SDT_OMANY(GameSettings, game_creation.landscape, SLE_UINT8, 0, 0, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
SDT_VAR(GameSettings, game_creation.snow_line, SLE_UINT8, 0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
- SDTC_CONDOMANY( gui.autosave, SLE_UINT8, 0, 22, N, 0, 0, 0, "", STR_NULL, NULL),
+ SDT_CONDNULL( 1, 0, 22),
SDTC_CONDOMANY( gui.autosave, SLE_UINT8, 23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL),
SDT_OMANY(GameSettings, vehicle.road_side, SLE_UINT8, 0, 0, 1, 1, "left|right", STR_NULL, NULL, NULL),
SDT_END()
@@ -1740,45 +1743,75 @@
/***************************************************************************/
/* Unsaved patch variables. */
- SDTC_OMANY(gui.autosave, SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL),
- SDTC_BOOL(gui.vehicle_speed, S, 0, true, STR_CONFIG_PATCHES_VEHICLESPEED, NULL),
- SDTC_BOOL(gui.status_long_date, S, 0, true, STR_CONFIG_PATCHES_LONGDATE, NULL),
- SDTC_BOOL(gui.show_finances, S, 0, true, STR_CONFIG_PATCHES_SHOWFINANCES, NULL),
- SDTC_BOOL(gui.autoscroll, S, 0, false, STR_CONFIG_PATCHES_AUTOSCROLL, NULL),
- SDTC_BOOL(gui.reverse_scroll, S, 0, false, STR_CONFIG_PATCHES_REVERSE_SCROLLING, NULL),
- SDTC_BOOL(gui.smooth_scroll, S, 0, false, STR_CONFIG_PATCHES_SMOOTH_SCROLLING, NULL),
- SDTC_BOOL(gui.measure_tooltip, S, 0, false, STR_CONFIG_PATCHES_MEASURE_TOOLTIP, NULL),
- SDTC_VAR(gui.errmsg_duration, SLE_UINT8, S, 0, 5, 0, 20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, NULL),
- SDTC_VAR(gui.toolbar_pos, SLE_UINT8, S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS, v_PositionMainToolbar),
- SDTC_VAR(gui.window_snap_radius, SLE_UINT8, S,D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS, NULL),
- SDTC_BOOL(gui.population_in_label, S, 0, true, STR_CONFIG_PATCHES_POPULATION_IN_LABEL, PopulationInLabelActive),
- SDTC_BOOL(gui.link_terraform_toolbar, S, 0, false, STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR, NULL),
- SDTC_VAR(gui.liveries, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_LIVERIES, RedrawScreen),
- SDTC_BOOL(gui.prefer_teamchat, S, 0, false, STR_CONFIG_PATCHES_PREFER_TEAMCHAT, NULL),
- SDTC_VAR(gui.scrollwheel_scrolling, SLE_UINT8, S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL),
- SDTC_VAR(gui.scrollwheel_multiplier, SLE_UINT8, S, 0, 5, 1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER, NULL),
- SDTC_BOOL(gui.pause_on_newgame, S, 0, false, STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME, NULL),
- SDTC_VAR(gui.advanced_vehicle_list, SLE_UINT8, S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS, NULL),
- SDTC_BOOL(gui.timetable_in_ticks, S, 0, false, STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS, NULL),
- SDTC_VAR(gui.loading_indicators, SLE_UINT8, S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS, RedrawScreen),
- SDTC_VAR(gui.default_rail_type, SLE_UINT8, S,MS, 4, 0, 6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE, NULL),
- SDTC_BOOL(gui.enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, CloseSignalGUI),
- SDTC_VAR(gui.drag_signals_density, SLE_UINT8, S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY, DragSignalsDensityChanged),
- SDTC_VAR(gui.semaphore_build_before, SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
- SDTC_BOOL(gui.train_income_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_INCOME_LESS, NULL),
- SDTC_VAR(gui.order_review_system, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW, NULL),
- SDTC_BOOL(gui.lost_train_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_TRAIN, NULL),
- SDTC_BOOL(gui.autorenew, S, 0, false, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE, EngineRenewUpdate),
- SDTC_VAR(gui.autorenew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, EngineRenewMonthsUpdate),
- SDTC_VAR(gui.autorenew_money, SLE_UINT, S,CR,100000, 0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY, EngineRenewMoneyUpdate),
- SDTC_BOOL(gui.always_build_infrastructure, S, 0, false, STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
- SDTC_BOOL(gui.new_nonstop, S, 0, false, STR_CONFIG_PATCHES_NEW_NONSTOP, NULL),
- SDTC_BOOL(gui.keep_all_autosave, S, 0, false, STR_NULL, NULL),
- SDTC_BOOL(gui.autosave_on_exit, S, 0, false, STR_NULL, NULL),
- SDTC_VAR(gui.max_num_autosaves, SLE_UINT8, S, 0, 16, 0, 255, 0, STR_NULL, NULL),
- SDTC_BOOL(gui.bridge_pillars, S, 0, true, STR_NULL, NULL),
- SDTC_BOOL(gui.auto_euro, S, 0, true, STR_NULL, NULL),
- SDTC_VAR(gui.news_message_timeout, SLE_UINT8, S, 0, 2, 1, 255, 0, STR_NULL, NULL),
+ SDTC_OMANY(gui.autosave, SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL),
+ SDTC_BOOL(gui.vehicle_speed, S, 0, true, STR_CONFIG_PATCHES_VEHICLESPEED, NULL),
+ SDTC_BOOL(gui.status_long_date, S, 0, true, STR_CONFIG_PATCHES_LONGDATE, NULL),
+ SDTC_BOOL(gui.show_finances, S, 0, true, STR_CONFIG_PATCHES_SHOWFINANCES, NULL),
+ SDTC_BOOL(gui.autoscroll, S, 0, false, STR_CONFIG_PATCHES_AUTOSCROLL, NULL),
+ SDTC_BOOL(gui.reverse_scroll, S, 0, false, STR_CONFIG_PATCHES_REVERSE_SCROLLING, NULL),
+ SDTC_BOOL(gui.smooth_scroll, S, 0, false, STR_CONFIG_PATCHES_SMOOTH_SCROLLING, NULL),
+ SDTC_BOOL(gui.measure_tooltip, S, 0, false, STR_CONFIG_PATCHES_MEASURE_TOOLTIP, NULL),
+ SDTC_VAR(gui.errmsg_duration, SLE_UINT8, S, 0, 5, 0, 20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, NULL),
+ SDTC_VAR(gui.toolbar_pos, SLE_UINT8, S, MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS, v_PositionMainToolbar),
+ SDTC_VAR(gui.window_snap_radius, SLE_UINT8, S, D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS, NULL),
+ SDTC_BOOL(gui.population_in_label, S, 0, true, STR_CONFIG_PATCHES_POPULATION_IN_LABEL, PopulationInLabelActive),
+ SDTC_BOOL(gui.link_terraform_toolbar, S, 0, false, STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR, NULL),
+ SDTC_VAR(gui.liveries, SLE_UINT8, S, MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_LIVERIES, RedrawScreen),
+ SDTC_BOOL(gui.prefer_teamchat, S, 0, false, STR_CONFIG_PATCHES_PREFER_TEAMCHAT, NULL),
+ SDTC_VAR(gui.scrollwheel_scrolling, SLE_UINT8, S, MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL),
+ SDTC_VAR(gui.scrollwheel_multiplier, SLE_UINT8, S, 0, 5, 1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER, NULL),
+ SDTC_BOOL(gui.pause_on_newgame, S, 0, false, STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME, NULL),
+ SDTC_VAR(gui.advanced_vehicle_list, SLE_UINT8, S, MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS, NULL),
+ SDTC_BOOL(gui.timetable_in_ticks, S, 0, false, STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS, NULL),
+ SDTC_VAR(gui.loading_indicators, SLE_UINT8, S, MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS, RedrawScreen),
+ SDTC_VAR(gui.default_rail_type, SLE_UINT8, S, MS, 4, 0, 6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE, NULL),
+ SDTC_BOOL(gui.enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, CloseSignalGUI),
+ SDTC_VAR(gui.drag_signals_density, SLE_UINT8, S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY, DragSignalsDensityChanged),
+ SDTC_VAR(gui.semaphore_build_before, SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
+ SDTC_BOOL(gui.train_income_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_INCOME_LESS, NULL),
+ SDTC_VAR(gui.order_review_system, SLE_UINT8, S, MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW, NULL),
+ SDTC_BOOL(gui.lost_train_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_TRAIN, NULL),
+ SDTC_BOOL(gui.autorenew, S, 0, false, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE, EngineRenewUpdate),
+ SDTC_VAR(gui.autorenew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, EngineRenewMonthsUpdate),
+ SDTC_VAR(gui.autorenew_money, SLE_UINT, S, CR,100000, 0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY, EngineRenewMoneyUpdate),
+ SDTC_BOOL(gui.always_build_infrastructure, S, 0, false, STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
+ SDTC_BOOL(gui.new_nonstop, S, 0, false, STR_CONFIG_PATCHES_NEW_NONSTOP, NULL),
+ SDTC_BOOL(gui.keep_all_autosave, S, 0, false, STR_NULL, NULL),
+ SDTC_BOOL(gui.autosave_on_exit, S, 0, false, STR_NULL, NULL),
+ SDTC_VAR(gui.max_num_autosaves, SLE_UINT8, S, 0, 16, 0, 255, 0, STR_NULL, NULL),
+ SDTC_BOOL(gui.bridge_pillars, S, 0, true, STR_NULL, NULL),
+ SDTC_BOOL(gui.auto_euro, S, 0, true, STR_NULL, NULL),
+ SDTC_VAR(gui.news_message_timeout, SLE_UINT8, S, 0, 2, 1, 255, 0, STR_NULL, NULL),
+
+#ifdef ENABLE_NETWORK
+ SDTC_VAR(network.sync_freq, SLE_UINT16,C|S,NO, 100, 0, 100, 0, STR_NULL, NULL),
+ SDTC_VAR(network.frame_freq, SLE_UINT8,C|S,NO, 0, 0, 100, 0, STR_NULL, NULL),
+ SDTC_VAR(network.max_join_time, SLE_UINT16, S, NO, 500, 0, 32000, 0, STR_NULL, NULL),
+ SDTC_BOOL(network.pause_on_join, S, NO, true, STR_NULL, NULL),
+ SDTC_STR(network.server_bind_ip, SLE_STRB, S, NO, "0.0.0.0", STR_NULL, NULL),
+ SDTC_VAR(network.server_port, SLE_UINT16, S, NO,NETWORK_DEFAULT_PORT,0,65535,0,STR_NULL, NULL),
+ SDTC_BOOL(network.server_advertise, S, NO, false, STR_NULL, NULL),
+ SDTC_VAR(network.lan_internet, SLE_UINT8, S, NO, 0, 0, 1, 0, STR_NULL, NULL),
+ SDTC_STR(network.player_name, SLE_STRB, S, 0, NULL, STR_NULL, UpdatePlayerName),
+ SDTC_STR(network.server_password, SLE_STRB, S, NO, NULL, STR_NULL, UpdateServerPassword),
+ SDTC_STR(network.rcon_password, SLE_STRB, S, NO, NULL, STR_NULL, UpdateRconPassword),
+ SDTC_STR(network.default_company_pass, SLE_STRB, S, 0, NULL, STR_NULL, NULL),
+ SDTC_STR(network.server_name, SLE_STRB, S, NO, NULL, STR_NULL, NULL),
+ SDTC_STR(network.connect_to_ip, SLE_STRB, S, 0, NULL, STR_NULL, NULL),
+ SDTC_STR(network.network_id, SLE_STRB, S, NO, NULL, STR_NULL, NULL),
+ SDTC_BOOL(network.autoclean_companies, S, NO, false, STR_NULL, NULL),
+ SDTC_VAR(network.autoclean_unprotected, SLE_UINT8, S, NO, 12, 0, 60, 0, STR_NULL, NULL),
+ SDTC_VAR(network.autoclean_protected, SLE_UINT8, S, NO, 36, 0, 180, 0, STR_NULL, NULL),
+ SDTC_VAR(network.max_companies, SLE_UINT8, S, NO, 8, 1, MAX_PLAYERS, 0, STR_NULL, NULL),
+ SDTC_VAR(network.max_clients, SLE_UINT8, S, NO, 10, 2, MAX_CLIENTS, 0, STR_NULL, NULL),
+ SDTC_VAR(network.max_spectators, SLE_UINT8, S, NO, 10, 0, MAX_CLIENTS, 0, STR_NULL, NULL),
+ SDTC_VAR(network.restart_game_year, SLE_INT32, S,D0|NO|NC,0, MIN_YEAR, MAX_YEAR, 1, STR_NULL, NULL),
+ SDTC_VAR(network.min_players, SLE_UINT8, S, NO, 0, 0, 10, 0, STR_NULL, UpdateMinPlayers),
+ SDTC_OMANY(network.server_lang, SLE_UINT8, S, NO, 0, 35, "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN", STR_NULL, NULL),
+ SDTC_BOOL(network.reload_cfg, S, NO, false, STR_NULL, NULL),
+ SDTC_STR(network.last_host, SLE_STRB, S, 0, "0.0.0.0", STR_NULL, NULL),
+ SDTC_VAR(network.last_port, SLE_UINT16, S, 0, 0, 0, UINT16_MAX, 0, STR_NULL, NULL),
+#endif /* ENABLE_NETWORK */
/*
* Since the network code (CmdChangePatchSetting and friends) use the index in this array to decide
@@ -2020,7 +2053,6 @@
proc(ini, _currency_settings,"currency", &_custom_currency);
#ifdef ENABLE_NETWORK
- proc(ini, (const SettingDesc*)_network_settings, "network", NULL);
proc_list(ini, "servers", _network_host_list, lengthof(_network_host_list), NULL);
proc_list(ini, "bans", _network_ban_list, lengthof(_network_ban_list), NULL);
#endif /* ENABLE_NETWORK */
@@ -2084,15 +2116,27 @@
if (sd == NULL) return CMD_ERROR;
if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR;
- if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return CMD_ERROR;
+ if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return CMD_ERROR;
if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return CMD_ERROR;
if ((sd->desc.flags & SGF_NEWGAME_ONLY) && _game_mode != GM_MENU) return CMD_ERROR;
if (flags & DC_EXEC) {
GameSettings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game;
void *var = GetVariableAddress(s, &sd->save);
- Write_ValidateSetting(var, sd, (int32)p2);
- if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
+
+ int32 oldval = (int32)ReadValue(var, sd->save.conv);
+ int32 newval = (int32)p2;
+
+ Write_ValidateSetting(var, sd, newval);
+ newval = (int32)ReadValue(var, sd->save.conv);
+
+ if (sd->desc.proc != NULL) sd->desc.proc(newval);
+
+ if ((sd->desc.flags & SGF_NO_NETWORK) && oldval != newval) {
+ GamelogStartAction(GLAT_PATCH);
+ GamelogPatch(sd->desc.name, oldval, newval);
+ GamelogStopAction();
+ }
InvalidateWindow(WC_GAME_OPTIONS, 0);
}
@@ -2134,6 +2178,24 @@
return false;
}
+/**
+ * Set a patch value with a string.
+ * @param index the patch settings index.
+ * @param value the value to write
+ * @note CANNOT BE SAVED IN THE SAVEGAME.
+ */
+bool SetPatchValue(uint index, const char *value)
+{
+ const SettingDesc *sd = &_patch_settings[index];
+ assert(sd->save.conv & SLF_NETWORK_NO);
+
+ char *var = (char*)GetVariableAddress(NULL, &sd->save);
+ ttd_strlcpy(var, value, sd->save.length);
+ if (sd->desc.proc != NULL) sd->desc.proc(0);
+
+ return true;
+}
+
const SettingDesc *GetPatchFromName(const char *name, uint *i)
{
const SettingDesc *sd;
@@ -2159,23 +2221,41 @@
/* Those 2 functions need to be here, else we have to make some stuff non-static
* and besides, it is also better to keep stuff like this at the same place */
-bool IConsoleSetPatchSetting(const char *name, int32 value)
+void IConsoleSetPatchSetting(const char *name, const char *value)
{
- bool success;
uint index;
const SettingDesc *sd = GetPatchFromName(name, &index);
- void *ptr;
if (sd == NULL) {
IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name);
- return true;
+ return;
}
- GameSettings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game;
- ptr = GetVariableAddress(s, &sd->save);
+ bool success;
+ if (sd->desc.cmd == SDT_STRING) {
+ success = SetPatchValue(index, value);
+ } else {
+ uint32 val;
+ extern bool GetArgumentInteger(uint32 *value, const char *arg);
+ success = GetArgumentInteger(&val, value);
+ if (success) success = SetPatchValue(index, val);
+ }
- success = SetPatchValue(index, value);
- return success;
+ if (!success) {
+ if (_network_server) {
+ IConsoleError("This command/variable is not available during network games.");
+ } else {
+ IConsoleError("This command/variable is only available to a network server.");
+ }
+ }
+}
+
+void IConsoleSetPatchSetting(const char *name, int value)
+{
+ uint index;
+ const SettingDesc *sd = GetPatchFromName(name, &index);
+ assert(sd != NULL);
+ SetPatchValue(index, value);
}
void IConsoleGetPatchSetting(const char *name)
@@ -2192,14 +2272,18 @@
ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game, &sd->save);
- if (sd->desc.cmd == SDT_BOOLX) {
- snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off");
+ if (sd->desc.cmd == SDT_STRING) {
+ IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, (const char *)ptr);
} else {
- snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv));
+ if (sd->desc.cmd == SDT_BOOLX) {
+ snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off");
+ } else {
+ snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv));
+ }
+
+ IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
+ name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
}
-
- IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
- name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
}
void IConsoleListPatches()
@@ -2212,6 +2296,8 @@
if (sd->desc.cmd == SDT_BOOLX) {
snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off");
+ } else if (sd->desc.cmd == SDT_STRING) {
+ snprintf(value, sizeof(value), "%s", (const char *)ptr);
} else {
snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv));
}
--- a/src/settings_func.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_func.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,7 +5,8 @@
#ifndef SETTINGS_FUNC_H
#define SETTINGS_FUNC_H
-bool IConsoleSetPatchSetting(const char *name, int32 value);
+void IConsoleSetPatchSetting(const char *name, const char *value);
+void IConsoleSetPatchSetting(const char *name, int32 value);
void IConsoleGetPatchSetting(const char *name);
void IConsoleListPatches();
--- a/src/settings_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -761,7 +761,6 @@
page->entries = MallocT<PatchEntry>(page->num);
for (i = 0; i != page->num; i++) {
uint index;
- printf("%s\n", page->names[i]);
const SettingDesc *sd = GetPatchFromName(page->names[i], &index);
assert(sd != NULL);
--- a/src/settings_internal.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_internal.h Wed Jun 04 22:34:45 2008 +0000
@@ -85,5 +85,6 @@
const SettingDesc *GetPatchFromName(const char *name, uint *i);
bool SetPatchValue(uint index, int32 value);
+bool SetPatchValue(uint index, const char *value);
#endif /* SETTINGS_H */
--- a/src/settings_type.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_type.h Wed Jun 04 22:34:45 2008 +0000
@@ -8,6 +8,7 @@
#include "date_type.h"
#include "town_type.h"
#include "transport_type.h"
+#include "network/core/config.h"
/** Settings related to the difficulty of the game */
struct DifficultySettings {
@@ -82,6 +83,40 @@
byte news_message_timeout; ///< how much longer than the news message "age" should we keep the message in the history
};
+/** All settings related to the network. */
+struct NetworkSettings {
+#ifdef ENABLE_NETWORK
+ uint16 sync_freq; ///< how often do we check whether we are still in-sync
+ uint8 frame_freq; ///< how often do we send commands to the clients
+ uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to join
+ bool pause_on_join; ///< pause the game when people join
+ char server_bind_ip[NETWORK_HOSTNAME_LENGTH]; ///< IP address the server binds to
+ uint16 server_port; ///< port the server listens on
+ char server_name[NETWORK_NAME_LENGTH]; ///< name of the server
+ char server_password[NETWORK_PASSWORD_LENGTH]; ///< passowrd for joining this server
+ char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< passowrd for rconsole (server side)
+ bool server_advertise; ///< advertise the server to the masterserver
+ uint8 lan_internet; ///< search on the LAN or internet for servers
+ char player_name[NETWORK_NAME_LENGTH]; ///< name of the player
+ char default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form
+ char connect_to_ip[NETWORK_HOSTNAME_LENGTH]; ///< default for the "Add server" query
+ char network_id[NETWORK_UNIQUE_ID_LENGTH]; ///< semi-unique ID of the client
+ bool autoclean_companies; ///< automatically remove companies that are not in use
+ uint8 autoclean_unprotected; ///< remove passwordless companies after this many months
+ uint8 autoclean_protected; ///< remove the password from passworded companies after this many months
+ uint8 max_companies; ///< maximum amount of companies
+ uint8 max_clients; ///< maximum amount of clients
+ uint8 max_spectators; ///< maximum amount of spectators
+ Year restart_game_year; ///< year the server restarts
+ uint8 min_players; ///< minimum amount of players to unpause the game
+ uint8 server_lang; ///< language of the server
+ bool reload_cfg; ///< reload the config file before restarting
+ char last_host[NETWORK_HOSTNAME_LENGTH]; ///< IP address of the last joined server
+ uint16 last_port; ///< port of the last joined server
+#else /* ENABLE_NETWORK */
+#endif
+};
+
/** Settings related to the creation of games. */
struct GameCreationSettings {
uint32 generation_seed; ///< noise seed for world generation
@@ -280,6 +315,7 @@
/** All settings that are only important for the local client. */
struct ClientSettings {
GUISettings gui; ///< settings related to the GUI
+ NetworkSettings network; ///< settings related to the network
};
/** The current settings for this game. */
--- a/src/sortlist_type.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/sortlist_type.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,8 @@
#ifndef SORTLIST_TYPE_H
#define SORTLIST_TYPE_H
+#include "core/enum_type.hpp"
+#include "core/bitmath_func.hpp"
#include "misc/smallvec.h"
#include "date_type.h"
--- a/src/subsidy_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/subsidy_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -37,23 +37,29 @@
for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
if (s->cargo_type != CT_INVALID && s->age < 12) {
y -= 10;
- if (y < 0) this->HandleClick(s);
+ if (y < 0) {
+ this->HandleClick(s);
+ return;
+ }
num++;
}
}
if (num == 0) {
- y -= 10;
+ y -= 10; // "None"
if (y < 0) return;
}
- y -= 11;
+ y -= 11; // "Services already subsidised:"
if (y < 0) return;
for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
if (s->cargo_type != CT_INVALID && s->age >= 12) {
y -= 10;
- if (y < 0) this->HandleClick(s);
+ if (y < 0) {
+ this->HandleClick(s);
+ return;
+ }
}
}
}
--- a/src/table/files.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/files.h Wed Jun 04 22:34:45 2008 +0000
@@ -35,7 +35,7 @@
{ "TRGT.GRF", {0xfc, 0xde, 0x1d, 0x7e, 0x8a, 0x74, 0x19, 0x7d, 0x72, 0xa6, 0x26, 0x95, 0x88, 0x4b, 0x90, 0x9e} }
},
{ "SAMPLE.CAT", {0x42, 0x2e, 0xa3, 0xdd, 0x07, 0x4d, 0x28, 0x59, 0xbb, 0x51, 0x63, 0x9a, 0x6e, 0x0e, 0x85, 0xda} },
- { "OPENTTDD.GRF", {0xb2, 0xbd, 0xd2, 0xa4, 0x1b, 0xfa, 0x2c, 0x60, 0x4f, 0xd5, 0x5e, 0x4c, 0xb5, 0xba, 0x37, 0x73} }
+ { "OPENTTDD.GRF", {0xb6, 0xed, 0x9a, 0x20, 0x89, 0xad, 0x6e, 0xa1, 0x55, 0x10, 0xad, 0x00, 0x53, 0xa3, 0xd5, 0xbc} }
};
@@ -49,5 +49,5 @@
{ "TRGTR.GRF", {0xde, 0x53, 0x65, 0x05, 0x17, 0xfe, 0x66, 0x1c, 0xea, 0xa3, 0x13, 0x8c, 0x6e, 0xdb, 0x0e, 0xb8} }
},
{ "SAMPLE.CAT", {0x92, 0x12, 0xe8, 0x1e, 0x72, 0xba, 0xdd, 0x4b, 0xbe, 0x1e, 0xae, 0xae, 0x66, 0x45, 0x8e, 0x10} },
- { "OPENTTDW.GRF", {0x3b, 0x1a, 0x0d, 0x8c, 0x2d, 0x01, 0x0e, 0xee, 0x47, 0x7f, 0x5d, 0x70, 0x8f, 0xb2, 0xe4, 0xfb} }
+ { "OPENTTDW.GRF", {0x41, 0x1e, 0xb6, 0xb2, 0xd2, 0xc4, 0x30, 0x6e, 0x7b, 0xc7, 0xdc, 0x39, 0xd4, 0x40, 0x46, 0xfb} }
};
--- a/src/table/sprites.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/sprites.h Wed Jun 04 22:34:45 2008 +0000
@@ -49,7 +49,7 @@
/* Extra graphic spritenumbers */
SPR_OPENTTD_BASE = 4896,
- OPENTTD_SPRITE_COUNT = 144,
+ OPENTTD_SPRITE_COUNT = 145,
/* Halftile-selection sprites */
SPR_HALFTILE_SELECTION_FLAT = SPR_OPENTTD_BASE,
@@ -122,6 +122,8 @@
SPR_GROUP_REPLACE_OFF_SHIP = SPR_OPENTTD_BASE + 132,
SPR_GROUP_REPLACE_OFF_AIRCRAFT = SPR_OPENTTD_BASE + 133,
+ SPR_SWITCH_TOOLBAR = SPR_OPENTTD_BASE + 144,
+
SPR_SIGNALS_BASE = SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT,
PRESIGNAL_SPRITE_COUNT = 48,
PRESIGNAL_AND_SEMAPHORE_SPRITE_COUNT = 112,
--- a/src/table/town_land.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/town_land.h Wed Jun 04 22:34:45 2008 +0000
@@ -1809,8 +1809,8 @@
/**
* remove_rating_decrease
* | mail_generation
- * min_date | | 1st CargoID acceptance
- * | max_date | | | 2nd CargoID acceptance
+ * min_year | | 1st CargoID acceptance
+ * | max_year | | | 2nd CargoID acceptance
* | | population | | | | 3th CargoID acceptance
* | | | removal_cost | | | | |
* | | | | building_name | | | | |
--- a/src/toolbar_gui.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/toolbar_gui.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -48,10 +48,19 @@
static void PopupMainToolbMenu(Window *parent, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask = 0, int sel_index = 0, int checked_items = 0);
static void PopupMainPlayerToolbMenu(Window *parent, int main_button, int gray);
+static void SplitToolbar(Window *w);
RailType _last_built_railtype;
RoadType _last_built_roadtype;
+enum ToolbarMode {
+ TB_NORMAL,
+ TB_UPPER,
+ TB_LOWER
+};
+
+static ToolbarMode _toolbar_mode;
+
static void SelectSignTool()
{
if (_cursor.sprite == SPR_CURSOR_SIGN) {
@@ -283,7 +292,7 @@
static void ToolbarGraphsClick(Window *w)
{
- PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6);
+ PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
}
static void MenuClickGraphs(int index)
@@ -295,6 +304,9 @@
case 3: ShowPerformanceHistoryGraph(); break;
case 4: ShowCompanyValueGraph(); break;
case 5: ShowCargoPaymentRates(); break;
+ /* functions for combined graphs/league button */
+ case 6: ShowCompanyLeagueTable(); break;
+ case 7: ShowPerformanceRatingDetail(); break;
}
}
@@ -535,6 +547,22 @@
}
}
+/* --- Switch toolbar button --- */
+
+static void ToolbarSwitchClick(Window *w)
+{
+ if (_toolbar_mode != TB_LOWER) {
+ _toolbar_mode = TB_LOWER;
+ } else {
+ _toolbar_mode = TB_UPPER;
+ }
+
+ SplitToolbar(w);
+ w->HandleButtonClick(27);
+ SetWindowDirty(w);
+ SndPlayFx(SND_15_BEEP);
+}
+
/* --- Scenario editor specific handlers. */
static void ToolbarScenDateBackward(Window *w)
@@ -633,6 +661,90 @@
{
}
+/* --- Resizing the toolbar */
+
+static void ResizeToolbar(Window *w)
+{
+ /* There are 27 buttons plus some spacings if the space allows it */
+ uint button_width;
+ uint spacing;
+ if (w->width >= 27 * 22) {
+ button_width = 22;
+ spacing = w->width - (27 * button_width);
+ } else {
+ button_width = w->width / 27;
+ spacing = 0;
+ }
+ uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
+
+ for (uint i = 0, x = 0, j = 0; i < 27; i++) {
+ if (extra_spacing_at[j] == i) {
+ j++;
+ uint add = spacing / (lengthof(extra_spacing_at) - j);
+ spacing -= add;
+ x += add;
+ }
+
+ w->widget[i].type = WWT_IMGBTN;
+ w->widget[i].left = x;
+ x += (spacing != 0) ? button_width : (w->width - x) / (27 - i);
+ w->widget[i].right = x - 1;
+ }
+
+ w->widget[27].type = WWT_EMPTY;
+ _toolbar_mode = TB_NORMAL;
+}
+
+/* --- Split the toolbar */
+
+static void SplitToolbar(Window *w)
+{
+ static const byte arrange14[] = {
+ 0, 1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 27,
+ };
+ static const byte arrange15[] = {
+ 0, 1, 4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+ 0, 2, 4, 3, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 27,
+ };
+ static const byte arrange16[] = {
+ 0, 1, 2, 4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+ 0, 1, 3, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 17, 18, 27,
+ };
+ static const byte arrange17[] = {
+ 0, 1, 2, 4, 6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+ 0, 1, 3, 4, 6, 5, 7, 8, 9, 10, 12, 24, 25, 26, 17, 18, 27,
+ };
+ static const byte arrange18[] = {
+ 0, 1, 2, 4, 5, 6, 7, 8, 9, 12, 19, 20, 21, 22, 23, 17, 18, 27,
+ 0, 1, 3, 4, 5, 6, 7, 10, 13, 14, 15, 16, 24, 25, 26, 17, 18, 27,
+ };
+ static const byte arrange19[] = {
+ 0, 1, 2, 4, 5, 6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 17, 18, 27,
+ 0, 1, 3, 4, 7, 8, 9, 10, 12, 25, 19, 20, 21, 22, 23, 26, 17, 18, 27,
+ };
+
+ static const byte *arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19 };
+
+ static const uint icon_size = 22;
+ uint max_icons = max(14U, (w->width + icon_size / 2) / icon_size);
+
+ assert(max_icons >= 14 && max_icons <= 19);
+
+ /* first hide all icons */
+ for (uint i = 0; i < 27; i++) {
+ w->widget[i].type = WWT_EMPTY;
+ }
+
+ /* now activate them all on their proper positions */
+ for (uint i = 0, x = 0, n = max_icons - 14; i < max_icons; i++) {
+ uint icon = arrangements[n][i + ((_toolbar_mode == TB_LOWER) ? max_icons : 0)];
+ w->widget[icon].type = WWT_IMGBTN;
+ w->widget[icon].left = x;
+ x += (w->width - x) / (max_icons - i);
+ w->widget[icon].right = x - 1;
+ }
+}
/* --- Toolbar handling for the 'normal' case */
@@ -666,6 +778,7 @@
ToolbarMusicClick,
ToolbarNewspaperClick,
ToolbarHelpClick,
+ ToolbarSwitchClick,
};
struct MainToolbarWindow : Window {
@@ -776,29 +889,10 @@
virtual void OnResize(Point new_size, Point delta)
{
- /* There are 27 buttons plus some spacings if the space allows it */
- uint button_width;
- uint spacing;
- if (this->width >= 27 * 22) {
- button_width = 22;
- spacing = this->width - (27 * button_width);
+ if (this->width <= 19 * 22) {
+ SplitToolbar(this);
} else {
- button_width = this->width / 27;
- spacing = 0;
- }
- uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
-
- for (uint i = 0, x = 0, j = 0; i < 27; i++) {
- if (extra_spacing_at[j] == i) {
- j++;
- uint add = spacing / (lengthof(extra_spacing_at) - j);
- spacing -= add;
- x += add;
- }
-
- this->widget[i].left = x;
- x += (spacing != 0) ? button_width : (this->width - x) / (27 - i);
- this->widget[i].right = x - 1;
+ ResizeToolbar(this);
}
}
@@ -852,6 +946,7 @@
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MUSIC, STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MESSAGES, STR_0203_SHOW_LAST_MESSAGE_NEWS},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_QUERY, STR_0186_LAND_BLOCK_INFORMATION},
+{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_SWITCH_TOOLBAR, STR_EMPTY}, // switch toolbar button. only active when toolbar has been split
{ WIDGETS_END},
};
--- a/src/town.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/town.h Wed Jun 04 22:34:45 2008 +0000
@@ -212,8 +212,8 @@
struct HouseSpec {
/* Standard properties */
- Year min_date; ///< introduction year of the house
- Year max_date; ///< last year it can be built
+ Year min_year; ///< introduction year of the house
+ Year max_year; ///< last year it can be built
byte population; ///< population (Zero on other tiles in multi tile house.)
byte removal_cost; ///< cost multiplier for removing it
StringID building_name; ///< building name
--- a/src/town_cmd.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/town_cmd.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -1639,11 +1639,7 @@
*/
static inline void ClearMakeHouseTile(TileIndex tile, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
{
- #if !defined(NDEBUG) || defined(WITH_ASSERT)
- CommandCost cc =
- #endif /* !defined(NDEBUG) || defined(WITH_ASSERT) */
-
- DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
+ CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
assert(CmdSucceeded(cc));
@@ -1935,7 +1931,7 @@
}
}
- if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
+ if (_cur_year < hs->min_year || _cur_year > hs->max_year) continue;
/* Special houses that there can be only one of. */
uint oneof = 0;
@@ -2197,7 +2193,7 @@
{
TileIndex tile = t->xy;
- if (CircularTileSearch(tile, 9, SearchTileForStatue, t->index)) {
+ if (CircularTileSearch(&tile, 9, SearchTileForStatue, t->index)) {
SetBit(t->statues, _current_player); // Once found and built, "inform" the Town
}
}
@@ -2247,6 +2243,7 @@
*/
if (t->ratings[_current_player] > RATING_BRIBE_DOWN_TO) {
t->ratings[_current_player] = RATING_BRIBE_DOWN_TO;
+ InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
}
} else {
ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM);
@@ -2328,6 +2325,8 @@
t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
}
+ InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
+
ClrBit(t->flags12, TOWN_IS_FUNDED);
if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
@@ -2499,6 +2498,7 @@
_town_test_ratings[t] = rating;
} else {
t->ratings[_current_player] = rating;
+ InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
}
}
--- a/src/variables.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/variables.h Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,10 @@
#ifndef VARIABLES_H
#define VARIABLES_H
+#ifndef VARDEF
+#define VARDEF extern
+#endif
+
/* Amount of game ticks */
VARDEF uint16 _tick_counter;
--- a/src/vehicle.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/vehicle.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,6 @@
#include "industry_map.h"
#include "station_map.h"
#include "water_map.h"
-#include "network/network.h"
#include "yapf/yapf.h"
#include "newgrf_callbacks.h"
#include "newgrf_engine.h"
--- a/src/win32.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/win32.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -25,6 +25,7 @@
#include "core/random_func.hpp"
#include "core/bitmath_func.hpp"
#include "string_func.h"
+#include "gamelog.h"
#include <ctype.h>
#include <tchar.h>
#include <errno.h>
@@ -454,6 +455,15 @@
extern bool CloseConsoleLogIfActive();
+static HANDLE _file_crash_log;
+
+static void GamelogPrintCrashLogProc(const char *s)
+{
+ DWORD num_written;
+ WriteFile(_file_crash_log, s, strlen(s), &num_written, NULL);
+ WriteFile(_file_crash_log, "\r\n", strlen("\r\n"), &num_written, NULL);
+}
+
static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
{
char *output;
@@ -588,17 +598,15 @@
os.dwOSVersionInfoSize = sizeof(os);
GetVersionEx(&os);
output += sprintf(output, "\r\nSystem information:\r\n"
- " Windows version %d.%d %d %s\r\n",
+ " Windows version %d.%d %d %s\r\n\r\n",
os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion);
}
- {
- HANDLE file = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ _file_crash_log = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+
+ if (_file_crash_log != INVALID_HANDLE_VALUE) {
DWORD num_written;
- if (file != INVALID_HANDLE_VALUE) {
- WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL);
- CloseHandle(file);
- }
+ WriteFile(_file_crash_log, _crash_msg, output - _crash_msg, &num_written, NULL);
}
#if !defined(_DEBUG)
@@ -636,6 +644,11 @@
}
#endif
+ if (_file_crash_log != INVALID_HANDLE_VALUE) {
+ GamelogPrint(&GamelogPrintCrashLogProc);
+ CloseHandle(_file_crash_log);
+ }
+
/* Close any possible log files */
CloseConsoleLogIfActive();
@@ -780,7 +793,7 @@
{
#if defined(WINCE)
/* WinCE only knows one drive: / */
- FiosItem *fios = FiosAlloc();
+ FiosItem *fios = _fios_items.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
snprintf(fios->name, lengthof(fios->name), PATHSEP "");
@@ -791,7 +804,7 @@
GetLogicalDriveStrings(sizeof(drives), drives);
for (s = drives; *s != '\0';) {
- FiosItem *fios = FiosAlloc();
+ FiosItem *fios = _fios_items.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
snprintf(fios->name, lengthof(fios->name), "%c:", s[0] & 0xFF);
--- a/src/window.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/window.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -721,9 +721,14 @@
}
/**
- * Find a nice spot for this window and resize it towards the default size.
+ * Resize window towards the default size.
+ * Prior to construction, a position for the new window (for its default size)
+ * has been found with LocalGetWindowPlacement(). Initially, the window is
+ * constructed with minimal size. Resizing the window to its default size is
+ * done here.
* @param def_width default width in pixels of the window
* @param def_height default height in pixels of the window
+ * @see Window::Window(), Window::Initialize()
*/
void Window::FindWindowPlacementAndResize(int def_width, int def_height)
{
@@ -802,7 +807,17 @@
this->Initialize(x, y, width, height, cls, widget, 0);
}
-
+/**
+ * Decide whether a given rectangle is a good place to open a completely visible new window.
+ * The new window should be within screen borders, and not overlap with another already
+ * existing window (except for the main window in the background).
+ * @param left Left edge of the rectangle
+ * @param top Top edge of the rectangle
+ * @param width Width of the rectangle
+ * @param height Height of the rectangle
+ * @param pos If rectangle is good, use this parameter to return the top-left corner of the new window
+ * @return Boolean indication that the rectangle is a good place for the new window
+ */
static bool IsGoodAutoPlace1(int left, int top, int width, int height, Point &pos)
{
Window* const *wz;
@@ -830,11 +845,26 @@
return true;
}
+/**
+ * Decide whether a given rectangle is a good place to open a mostly visible new window.
+ * The new window should be mostly within screen borders, and not overlap with another already
+ * existing window (except for the main window in the background).
+ * @param left Left edge of the rectangle
+ * @param top Top edge of the rectangle
+ * @param width Width of the rectangle
+ * @param height Height of the rectangle
+ * @param pos If rectangle is good, use this parameter to return the top-left corner of the new window
+ * @return Boolean indication that the rectangle is a good place for the new window
+ */
static bool IsGoodAutoPlace2(int left, int top, int width, int height, Point &pos)
{
Window* const *wz;
+ /* Left part of the rectangle may be at most 1/4 off-screen,
+ * right part of the rectangle may be at most 1/2 off-screen
+ */
if (left < -(width>>2) || left > _screen.width - (width>>1)) return false;
+ /* Bottom part of the rectangle may be at most 1/4 off-screen */
if (top < 22 || top > _screen.height - (height>>2)) return false;
/* Make sure it is not obscured by any window. */
@@ -855,13 +885,24 @@
return true;
}
+/**
+ * Find a good place for opening a new window of a given width and height.
+ * @param width Width of the new window
+ * @param height Height of the new window
+ * @return Top-left coordinate of the new window
+ */
static Point GetAutoPlacePosition(int width, int height)
{
Window* const *wz;
Point pt;
+ /* First attempt, try top-left of the screen */
if (IsGoodAutoPlace1(0, 24, width, height, pt)) return pt;
+ /* Second attempt, try around all existing windows with a distance of 2 pixels.
+ * The new window must be entirely on-screen, and not overlap with an existing window.
+ * Eight starting points are tried, two at each corner.
+ */
FOR_ALL_WINDOWS(wz) {
const Window *w = *wz;
if (w->window_class == WC_MAIN_WINDOW) continue;
@@ -876,6 +917,10 @@
if (IsGoodAutoPlace1(w->left + w->width - width, w->top - height - 2, width, height, pt)) return pt;
}
+ /* Third attempt, try around all existing windows with a distance of 2 pixels.
+ * The new window may be partly off-screen, and must not overlap with an existing window.
+ * Only four starting points are tried.
+ */
FOR_ALL_WINDOWS(wz) {
const Window *w = *wz;
if (w->window_class == WC_MAIN_WINDOW) continue;
@@ -886,6 +931,9 @@
if (IsGoodAutoPlace2(w->left, w->top - height - 2, width, height, pt)) return pt;
}
+ /* Fourth and final attempt, put window at diagonal starting from (0, 24), try multiples
+ * of (+5, +5)
+ */
{
int left = 0, top = 24;
@@ -1748,14 +1796,12 @@
{ 0, 0}, ///< 15 : left + up + right + down = nothing
};
-static bool HandleKeyScrolling()
+static void HandleKeyScrolling()
{
if (_dirkeys && !_no_scroll) {
int factor = _shift_pressed ? 50 : 10;
ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
- return false;
}
- return true;
}
void MouseLoop(MouseClick click, int mousewheel)
@@ -1763,13 +1809,14 @@
DecreaseWindowCounters();
HandlePlacePresize();
UpdateTileSelection();
+ HandleKeyScrolling();
+
if (!VpHandlePlaceSizingDrag()) return;
if (!HandleDragDrop()) return;
if (!HandleWindowDragging()) return;
if (!HandleScrollbarScrolling()) return;
if (!HandleViewportScroll()) return;
if (!HandleMouseOver()) return;
- if (!HandleKeyScrolling()) return;
bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
--- a/src/yapf/follow_track.hpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/follow_track.hpp Wed Jun 04 22:34:45 2008 +0000
@@ -22,7 +22,7 @@
EC_NO_WAY,
};
- const Vehicle* m_veh; ///< moving vehicle
+ const Vehicle *m_veh; ///< moving vehicle
TileIndex m_old_tile; ///< the origin (vehicle moved from) before move
Trackdir m_old_td; ///< the trackdir (the vehicle was on) before move
TileIndex m_new_tile; ///< the new tile (the vehicle has entered)
@@ -33,14 +33,14 @@
bool m_is_station; ///< last turn passed station
int m_tiles_skipped; ///< number of skipped tunnel or station tiles
ErrorCode m_err;
- CPerformanceTimer* m_pPerf;
+ CPerformanceTimer *m_pPerf;
- FORCEINLINE CFollowTrackT(const Vehicle* v = NULL, CPerformanceTimer* pPerf = NULL)
+ FORCEINLINE CFollowTrackT(const Vehicle *v = NULL, CPerformanceTimer* pPerf = NULL)
{
Init(v, pPerf);
}
- FORCEINLINE void Init(const Vehicle* v, CPerformanceTimer* pPerf)
+ FORCEINLINE void Init(const Vehicle *v, CPerformanceTimer* pPerf)
{
assert(!IsRailTT() || (v != NULL && v->type == VEH_TRAIN));
m_veh = v;
--- a/src/yapf/yapf.h Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf.h Wed Jun 04 22:34:45 2008 +0000
@@ -16,7 +16,7 @@
* @param tracks available tracks on the new tile (to choose from)
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
*/
-Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks);
+Trackdir YapfChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks);
/** Finds the best path for given road vehicle.
* @param v the RV that needs to find a path
@@ -24,7 +24,7 @@
* @param enterdir diagonal direction which the RV will enter this new tile from
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
*/
-Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir);
+Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir);
/** Finds the best path for given train.
* @param v the train that needs to find a path
@@ -34,7 +34,7 @@
* @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
*/
-Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found);
+Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found);
/** Used by RV multistop feature to find the nearest road stop that has a free slot.
* @param v RV (its current tile will be the origin)
@@ -58,17 +58,17 @@
* @param reversed receives true if train needs to reversed first
* @return the true if depot was found.
*/
-bool YapfFindNearestRailDepotTwoWay(Vehicle *v, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed);
+bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed);
/** Returns true if it is better to reverse the train before leaving station */
-bool YapfCheckReverseTrain(Vehicle* v);
+bool YapfCheckReverseTrain(const Vehicle* v);
/** Use this function to notify YAPF that track layout (or signal configuration) has change */
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track);
/** performance measurement helpers */
void* NpfBeginInterval();
-int NpfEndInterval(void* perf);
+int NpfEndInterval(void *perf);
extern int _aystar_stats_open_size;
--- a/src/yapf/yapf_base.hpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_base.hpp Wed Jun 04 22:34:45 2008 +0000
@@ -51,11 +51,11 @@
NodeList m_nodes; ///< node list multi-container
protected:
- Node* m_pBestDestNode; ///< pointer to the destination node found at last round
- Node* m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found
+ Node *m_pBestDestNode; ///< pointer to the destination node found at last round
+ Node *m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found
const YAPFSettings *m_settings; ///< current settings (_settings_game.yapf)
int m_max_search_nodes; ///< maximum number of nodes we are allowed to visit before we give up
- const Vehicle* m_veh; ///< vehicle that we are trying to drive
+ const Vehicle *m_veh; ///< vehicle that we are trying to drive
int m_stats_cost_calcs; ///< stats - how many node's costs were calculated
int m_stats_cache_hits; ///< stats - how many node's costs were reused from cache
@@ -281,7 +281,7 @@
m_nodes.InsertOpenNode(n);
}
- const Vehicle* GetVehicle() const {return m_veh;}
+ const Vehicle * GetVehicle() const {return m_veh;}
void DumpBase(DumpTarget &dmp) const
{
--- a/src/yapf/yapf_costrail.hpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_costrail.hpp Wed Jun 04 22:34:45 2008 +0000
@@ -191,7 +191,7 @@
FORCEINLINE int PlatformLengthPenalty(int platform_length)
{
int cost = 0;
- const Vehicle* v = Yapf().GetVehicle();
+ const Vehicle *v = Yapf().GetVehicle();
assert(v != NULL);
assert(v->type == VEH_TRAIN);
assert(v->u.rail.cached_total_length != 0);
@@ -261,7 +261,7 @@
int segment_entry_cost = 0;
int segment_cost = 0;
- const Vehicle* v = Yapf().GetVehicle();
+ const Vehicle *v = Yapf().GetVehicle();
// start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment
TILE cur(n.m_key.m_tile, n.m_key.m_td);
--- a/src/yapf/yapf_destrail.hpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_destrail.hpp Wed Jun 04 22:34:45 2008 +0000
@@ -11,7 +11,7 @@
RailTypes m_compatible_railtypes;
public:
- void SetDestination(Vehicle* v)
+ void SetDestination(const Vehicle* v)
{
m_compatible_railtypes = v->u.rail.compatible_railtypes;
}
@@ -84,7 +84,7 @@
}
public:
- void SetDestination(Vehicle* v)
+ void SetDestination(const Vehicle* v)
{
switch (v->current_order.GetType()) {
case OT_GOTO_STATION:
--- a/src/yapf/yapf_rail.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_rail.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -45,7 +45,7 @@
/// return debug report character to identify the transportation type
FORCEINLINE char TransportTypeChar() const {return 't';}
- static bool stFindNearestDepotTwoWay(Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+ static bool stFindNearestDepotTwoWay(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
{
Tpf pf1;
bool result1 = pf1.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_distance, reverse_penalty, depot_tile, reversed);
@@ -64,7 +64,7 @@
return result1;
}
- FORCEINLINE bool FindNearestDepotTwoWay(Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+ FORCEINLINE bool FindNearestDepotTwoWay(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
{
// set origin and destination nodes
Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty, true);
@@ -121,7 +121,7 @@
/// return debug report character to identify the transportation type
FORCEINLINE char TransportTypeChar() const {return 't';}
- static Trackdir stChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+ static Trackdir stChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
{
// create pathfinder instance
Tpf pf1;
@@ -148,7 +148,7 @@
return result1;
}
- FORCEINLINE Trackdir ChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+ FORCEINLINE Trackdir ChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
{
// set origin and destination nodes
Yapf().SetOrigin(v->tile, GetVehicleTrackdir(v), INVALID_TILE, INVALID_TRACKDIR, 1, true);
@@ -181,7 +181,7 @@
return next_trackdir;
}
- static bool stCheckReverseTrain(Vehicle* v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
+ static bool stCheckReverseTrain(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
{
Tpf pf1;
bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
@@ -198,7 +198,7 @@
return result1;
}
- FORCEINLINE bool CheckReverseTrain(Vehicle* v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
+ FORCEINLINE bool CheckReverseTrain(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
{
// create pathfinder instance
// set origin and destination nodes
@@ -247,10 +247,10 @@
struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
-Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
{
// default is YAPF type 2
- typedef Trackdir (*PfnChooseRailTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits, bool*);
+ typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*);
PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack;
// check if non-default YAPF type needed
@@ -263,10 +263,10 @@
return td_ret;
}
-bool YapfCheckReverseTrain(Vehicle* v)
+bool YapfCheckReverseTrain(const Vehicle* v)
{
/* last wagon */
- Vehicle* last_veh = GetLastVehicleInChain(v);
+ const Vehicle *last_veh = GetLastVehicleInChain(v);
// get trackdirs of both ends
Trackdir td = GetVehicleTrackdir(v);
@@ -307,7 +307,7 @@
reverse_penalty += DistanceManhattan(cur_tile, tile_rev) * YAPF_TILE_LENGTH;
}
- typedef bool (*PfnCheckReverseTrain)(Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int);
+ typedef bool (*PfnCheckReverseTrain)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int);
PfnCheckReverseTrain pfnCheckReverseTrain = CYapfRail1::stCheckReverseTrain;
// check if non-default YAPF type needed
@@ -323,12 +323,12 @@
return reverse;
}
-bool YapfFindNearestRailDepotTwoWay(Vehicle *v, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed)
{
*depot_tile = INVALID_TILE;
*reversed = false;
- Vehicle* last_veh = GetLastVehicleInChain(v);
+ const Vehicle *last_veh = GetLastVehicleInChain(v);
TileIndex tile = v->tile;
TileIndex last_tile = last_veh->tile;
@@ -337,7 +337,7 @@
Trackdir td = GetVehicleTrackdir(v);
Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
- typedef bool (*PfnFindNearestDepotTwoWay)(Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
+ typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay;
// check if non-default YAPF type needed
--- a/src/yapf/yapf_road.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_road.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -83,7 +83,7 @@
// base tile cost depending on distance between edges
segment_cost += Yapf().OneTileCost(tile, trackdir);
- const Vehicle* v = Yapf().GetVehicle();
+ const Vehicle *v = Yapf().GetVehicle();
// we have reached the vehicle's destination - segment should end here to avoid target skipping
if (v->current_order.IsType(OT_GOTO_STATION) && tile == v->dest_tile) break;
@@ -253,13 +253,13 @@
/// return debug report character to identify the transportation type
FORCEINLINE char TransportTypeChar() const {return 'r';}
- static Trackdir stChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+ static Trackdir stChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
{
Tpf pf;
return pf.ChooseRoadTrack(v, tile, enterdir);
}
- FORCEINLINE Trackdir ChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+ FORCEINLINE Trackdir ChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
{
// handle special case - when next tile is destination tile
if (tile == v->dest_tile) {
@@ -400,21 +400,22 @@
struct CYapfRoadAnyDepot2 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyDepot2, CRoadNodeListExitDir , CYapfDestinationAnyDepotRoadT> > {};
-Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
{
// default is YAPF type 2
- typedef Trackdir (*PfnChooseRoadTrack)(Vehicle*, TileIndex, DiagDirection);
+ typedef Trackdir (*PfnChooseRoadTrack)(const Vehicle*, TileIndex, DiagDirection);
PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg
// check if non-default YAPF type should be used
- if (_settings_game.pf.yapf.disable_node_optimization)
+ if (_settings_game.pf.yapf.disable_node_optimization) {
pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg
+ }
Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir);
return td_ret;
}
-uint YapfRoadVehDistanceToTile(const Vehicle* v, TileIndex tile)
+uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile)
{
// default is YAPF type 2
typedef uint (*PfnDistanceToTile)(const Vehicle*, TileIndex);
--- a/src/yapf/yapf_ship.cpp Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_ship.cpp Wed Jun 04 22:34:45 2008 +0000
@@ -34,7 +34,7 @@
/// return debug report character to identify the transportation type
FORCEINLINE char TransportTypeChar() const {return 'w';}
- static Trackdir ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
+ static Trackdir ChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
{
// handle special case - when next tile is destination tile
if (tile == v->dest_tile) {
@@ -147,24 +147,25 @@
struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
/** Ship controller helper - path finder invoker */
-Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
+Trackdir YapfChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
{
// default is YAPF type 2
- typedef Trackdir (*PfnChooseShipTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits);
+ typedef Trackdir (*PfnChooseShipTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits);
PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg
// check if non-default YAPF type needed
- if (_settings_game.pf.forbid_90_deg)
+ if (_settings_game.pf.forbid_90_deg) {
pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack; // Trackdir, forbid 90-deg
- else if (_settings_game.pf.yapf.disable_node_optimization)
+ } else if (_settings_game.pf.yapf.disable_node_optimization) {
pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg
+ }
Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);
return td_ret;
}
/** performance measurement helper */
-void* NpfBeginInterval()
+void * NpfBeginInterval()
{
CPerformanceTimer& perf = *new CPerformanceTimer;
perf.Start();
@@ -172,7 +173,7 @@
}
/** performance measurement helper */
-int NpfEndInterval(void* vperf)
+int NpfEndInterval(void *vperf)
{
CPerformanceTimer& perf = *(CPerformanceTimer*)vperf;
perf.Stop();