1
0
Fork 0

(svn r16060) [0.7] -Backport from trunk:

- Fix: Storing/loading some currencies failed due to inconsistent settings "tables" [FS#2826] (r16028)
- Fix: Usage of uninitialised memory when trying to build a random new industry, but there are no industrytypes to choose from (i.e. all appearance probabilities are zero) (r16027)
- Fix: "Build separate station" in the station picker would reuse deleted stations [FS#2818] (r16025)
- Fix: 32 bpp sprites in tars would also be shown in the list of heightmaps [FS#2817] (r16023)
- Fix: Sometimes the unregister "query" thread could be delayed so much that the network stuff was already closed and the packet would never reach the master server causing the server to appear online longer than necessary (r16022)
- Fix: Chance16() did not work for b = 1. Also transform the formula to not use divisions (r16006)
release/0.7
rubidium 2009-04-14 21:13:07 +00:00
parent 9f5e690118
commit 60901368cc
11 changed files with 91 additions and 35 deletions

View File

@ -108,7 +108,7 @@ static FORCEINLINE uint32 InteractiveRandomRange(uint16 max)
* Checks if a given randomize-number is below a given probability.
*
* This function is used to check if the given probability by the fraction of (a/b)
* is greater than low 16 bits of the given randomize-number v.
* is greater than low 16 bits of the given randomize-number r.
*
* Do not use this function twice on the same random 16 bits as it will yield
* the same result. One can use a random number for two calls to Chance16I,
@ -117,12 +117,12 @@ static FORCEINLINE uint32 InteractiveRandomRange(uint16 max)
* @param a The numerator of the fraction
* @param b The denominator of the fraction, must of course not be null
* @param r The given randomize-number
* @return True if v is less or equals (a/b)
* @return True if the probability given by r is less or equal to (a/b)
*/
static FORCEINLINE bool Chance16I(const uint a, const uint b, const uint32 r)
{
assert(b != 0);
return (uint16)r < (uint16)(((a << 16) + b / 2) / b);
return (((uint16)r * b + b / 2) >> 16) < a;
}
/**

View File

@ -8,6 +8,7 @@
#include "openttd.h"
#include "fios.h"
#include "fileio_func.h"
#include "tar_type.h"
#include "string_func.h"
#include <sys/stat.h>
@ -469,7 +470,31 @@ static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char
if (strcasecmp(ext, ".bmp") == 0) type = FIOS_TYPE_BMP;
if (type != FIOS_TYPE_INVALID) GetFileTitle(file, title, last);
if (type == FIOS_TYPE_INVALID) return FIOS_TYPE_INVALID;
TarFileList::iterator it = _tar_filelist.find(file);
if (it != _tar_filelist.end()) {
/* If the file is in a tar and that tar is not in a heightmap
* directory we are for sure not supposed to see it.
* Examples of this are pngs part of documentation within
* collections of NewGRFs or 32 bpp graphics replacement PNGs.
*/
bool match = false;
Searchpath sp;
FOR_ALL_SEARCHPATHS(sp) {
char buf[MAX_PATH];
FioAppendDirectory(buf, sizeof(buf), sp, HEIGHTMAP_DIR);
if (strncmp(buf, it->second.tar_filename, strlen(buf)) == 0) {
match = true;
break;
}
}
if (!match) return FIOS_TYPE_INVALID;
}
GetFileTitle(file, title, last);
return type;
}

View File

@ -1872,6 +1872,9 @@ static void MaybeNewIndustry(void)
}
}
/* Abort if there is no industry buildable */
if (probability_max == 0) return;
/* Find a random type, with maximum being what has been evaluate above*/
rndtype = RandomRange(probability_max);
for (j = 0; j < NUM_INDUSTRYTYPES; j++) {

View File

@ -622,7 +622,7 @@ static void NetworkClose()
/* We are a server, also close the listensocket */
closesocket(_listensocket);
_listensocket = INVALID_SOCKET;
DEBUG(net, 1, "Closed listener");
DEBUG(net, 1, "[tcp] closed listeners");
}
NetworkUDPCloseAll();
@ -841,8 +841,11 @@ void NetworkReboot()
NetworkClose();
}
/* We want to disconnect from the host/clients */
void NetworkDisconnect()
/**
* We want to disconnect from the host/clients.
* @param blocking whether to wait till everything has been closed
*/
void NetworkDisconnect(bool blocking)
{
if (_network_server) {
NetworkClientSocket *cs;
@ -852,7 +855,7 @@ void NetworkDisconnect()
}
}
if (_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise();
if (_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(blocking);
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
@ -1148,7 +1151,7 @@ void NetworkStartUp()
/** This shuts the network down */
void NetworkShutDown()
{
NetworkDisconnect();
NetworkDisconnect(true);
NetworkUDPShutdown();
DEBUG(net, 3, "[core] shutting down network");

View File

@ -28,7 +28,7 @@ void NetworkUpdateClientName();
bool NetworkCompanyHasClients(CompanyID company);
bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
void NetworkReboot();
void NetworkDisconnect();
void NetworkDisconnect(bool blocking = false);
void NetworkGameLoop();
void NetworkUDPGameLoop();
void NetworkUDPCloseAll();

View File

@ -53,7 +53,7 @@ DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER)
DEBUG(net, 2, "[udp] advertising on master server successful");
/* We are advertised, but we don't want to! */
if (!_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise();
if (!_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(false);
}
///*** Communication with clients (we are server) ***/
@ -497,8 +497,11 @@ void NetworkUDPRemoveAdvertiseThread(void *pntr)
_network_udp_mutex->EndCritical();
}
/* Remove our advertise from the master-server */
void NetworkUDPRemoveAdvertise()
/**
* Remove our advertise from the master-server.
* @param blocking whether to wait until the removal has finished.
*/
void NetworkUDPRemoveAdvertise(bool blocking)
{
/* Check if we are advertising */
if (!_networking || !_network_server || !_network_udp_server) return;
@ -508,7 +511,7 @@ void NetworkUDPRemoveAdvertise()
if (!_udp_master_socket->Listen(_network_server_bind_ip, 0, false)) return;
}
if (!ThreadObject::New(NetworkUDPRemoveAdvertiseThread, NULL)) {
if (blocking || !ThreadObject::New(NetworkUDPRemoveAdvertiseThread, NULL)) {
NetworkUDPRemoveAdvertiseThread(NULL);
}
}

View File

@ -12,7 +12,7 @@ void NetworkUDPSearchGame();
void NetworkUDPQueryMasterServer();
void NetworkUDPQueryServer(NetworkAddress address, bool manually = false);
void NetworkUDPAdvertise();
void NetworkUDPRemoveAdvertise();
void NetworkUDPRemoveAdvertise(bool blocking);
void NetworkUDPShutdown();
#endif /* ENABLE_NETWORK */

View File

@ -1262,6 +1262,19 @@ static const SettingDescGlobVarList _misc_settings[] = {
static const uint GAME_DIFFICULTY_NUM = 18;
uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
/* Most of these strings are used both for gameopt-backward compatability
* and the settings tables. The rest is here for consistency. */
static const char *_locale_currencies = "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom";
static const char *_locale_units = "imperial|metric|si";
static const char *_town_names = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan";
static const char *_climates = "temperate|arctic|tropic|toyland";
static const char *_autosave_interval = "off|monthly|quarterly|half year|yearly";
static const char *_roadsides = "left|right";
static const char *_savegame_date = "long|short|iso";
#ifdef ENABLE_NETWORK
static const char *_server_langs = "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";
#endif /* ENABLE_NETWORK */
static const SettingDesc _gameopt_settings[] = {
/* In version 4 a new difficulty setting has been added to the difficulty settings,
* town attitude towards demolishing. Needs special handling because some dimwit thought
@ -1276,15 +1289,15 @@ static const SettingDesc _gameopt_settings[] = {
SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16, C, 0, _old_diff_custom, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, 4, SL_MAX_VERSION),
SDT_VAR(GameSettings, difficulty.diff_level, SLE_UINT8, 0, 0, 0, 0, 3, 0, STR_NULL, NULL),
SDT_OMANY(GameSettings, locale.currency, SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom", STR_NULL, NULL, NULL),
SDT_OMANY(GameSettings, locale.units, SLE_UINT8, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL),
SDT_OMANY(GameSettings, locale.currency, SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, _locale_currencies, STR_NULL, NULL, NULL),
SDT_OMANY(GameSettings, locale.units, SLE_UINT8, N, 0, 1, 2, _locale_units, STR_NULL, NULL, NULL),
/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
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_OMANY(GameSettings, game_creation.town_name, SLE_UINT8, 0, 0, 0, 255, _town_names, STR_NULL, NULL, NULL),
SDT_OMANY(GameSettings, game_creation.landscape, SLE_UINT8, 0, 0, 0, 3, _climates, 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),
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),
SDTC_CONDOMANY( gui.autosave, SLE_UINT8, 23, SL_MAX_VERSION, S, 0, 1, 4, _autosave_interval, STR_NULL, NULL),
SDT_OMANY(GameSettings, vehicle.road_side, SLE_UINT8, 0, 0, 1, 1, _roadsides, STR_NULL, NULL, NULL),
SDT_END()
};
@ -1322,10 +1335,10 @@ const SettingDesc _settings[] = {
SDT_CONDVAR(GameSettings, difficulty.diff_level, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 0, 0, 3, 0, STR_NULL, DifficultyReset),
/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
SDT_CONDOMANY(GameSettings, game_creation.town_name, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 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_CONDOMANY(GameSettings, game_creation.landscape, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
SDT_CONDOMANY(GameSettings, game_creation.town_name, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 255, _town_names, STR_NULL, NULL, NULL),
SDT_CONDOMANY(GameSettings, game_creation.landscape, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 3, _climates, STR_NULL, NULL, ConvertLandscape),
SDT_CONDVAR(GameSettings, game_creation.snow_line, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
SDT_CONDOMANY(GameSettings, vehicle.road_side, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 1, 1, "left|right", STR_NULL, CheckRoadSide, NULL),
SDT_CONDOMANY(GameSettings, vehicle.road_side, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 1, 1, _roadsides, STR_NULL, CheckRoadSide, NULL),
SDT_BOOL(GameSettings, construction.build_on_slopes, 0,NN, true, STR_CONFIG_SETTING_BUILDONSLOPES, NULL),
SDT_CONDBOOL(GameSettings, construction.autoslope, 75, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_AUTOSLOPE, NULL),
@ -1485,13 +1498,13 @@ const SettingDesc _settings[] = {
SDT_CONDVAR(GameSettings, game_creation.water_borders, SLE_UINT8,111, SL_MAX_VERSION, 0, 0, 15, 0, 16, 0, STR_NULL, NULL),
SDT_CONDVAR(GameSettings, game_creation.custom_town_number, SLE_UINT16,115, SL_MAX_VERSION, 0, 0, 1, 1, 5000, 0, STR_NULL, NULL),
SDT_CONDOMANY(GameSettings, locale.currency, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL),
SDT_CONDOMANY(GameSettings, locale.units, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL),
SDT_CONDOMANY(GameSettings, locale.currency, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 0, CUSTOM_CURRENCY_ID, _locale_currencies, STR_NULL, NULL, NULL),
SDT_CONDOMANY(GameSettings, locale.units, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 1, 2, _locale_units, STR_NULL, NULL, NULL),
/***************************************************************************/
/* Unsaved setting variables. */
SDTC_OMANY(gui.autosave, SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL),
SDTC_OMANY(gui.date_format_in_default_names,SLE_UINT8,S,MS, 0, 2, "long|short|iso", STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES, NULL),
SDTC_OMANY(gui.autosave, SLE_UINT8, S, 0, 1, 4, _autosave_interval, STR_NULL, NULL),
SDTC_OMANY(gui.date_format_in_default_names,SLE_UINT8,S,MS, 0, 2, _savegame_date, STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES, NULL),
SDTC_BOOL(gui.vehicle_speed, S, 0, true, STR_CONFIG_SETTING_VEHICLESPEED, NULL),
SDTC_BOOL(gui.status_long_date, S, 0, true, STR_CONFIG_SETTING_LONGDATE, NULL),
SDTC_BOOL(gui.show_finances, S, 0, true, STR_CONFIG_SETTING_SHOWFINANCES, NULL),
@ -1573,7 +1586,7 @@ const SettingDesc _settings[] = {
SDTC_VAR(network.max_spectators, SLE_UINT8, S, NO, 8, 0, MAX_CLIENTS, 0, STR_NULL, UpdateClientConfigValues),
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_active_clients, SLE_UINT8, S, NO, 0, 0, MAX_CLIENTS, 0, STR_NULL, NULL),
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_OMANY(network.server_lang, SLE_UINT8, S, NO, 0, 35, _server_langs, 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),

View File

@ -922,6 +922,8 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, DoCommandFlag flags, uin
}
StationID station_to_join = GB(p2, 16, 16);
bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = INVALID_STATION;
bool distant_join = (station_to_join != INVALID_STATION);
if (distant_join && (!_settings_game.station.distant_join_stations || !IsValidStationID(station_to_join))) return CMD_ERROR;
@ -975,7 +977,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, DoCommandFlag flags, uin
if (st == NULL && distant_join) st = GetStation(station_to_join);
/* See if there is a deleted station close to us. */
if (st == NULL) st = GetClosestDeletedStation(tile_org);
if (st == NULL && reuse) st = GetClosestDeletedStation(tile_org);
if (st != NULL) {
/* Reuse an existing station. */
@ -1403,6 +1405,8 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
bool build_over_road = is_drive_through && IsNormalRoadTile(tile);
RoadTypes rts = (RoadTypes)GB(p2, 2, 2);
StationID station_to_join = GB(p2, 16, 16);
bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = INVALID_STATION;
bool distant_join = (station_to_join != INVALID_STATION);
Owner tram_owner = _current_company;
Owner road_owner = _current_company;
@ -1470,7 +1474,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (st == NULL && distant_join) st = GetStation(station_to_join);
/* Find a deleted station close to us */
if (st == NULL) st = GetClosestDeletedStation(tile);
if (st == NULL && reuse) st = GetClosestDeletedStation(tile);
/* give us a road stop in the list, and check if something went wrong */
if (!RoadStop::CanAllocateItem()) return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
@ -1855,6 +1859,8 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
{
bool airport_upgrade = true;
StationID station_to_join = GB(p2, 16, 16);
bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = INVALID_STATION;
bool distant_join = (station_to_join != INVALID_STATION);
if (distant_join && (!_settings_game.station.distant_join_stations || !IsValidStationID(station_to_join))) return CMD_ERROR;
@ -1919,7 +1925,7 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (st == NULL && distant_join) st = GetStation(station_to_join);
/* Find a deleted station close to us */
if (st == NULL) st = GetClosestDeletedStation(tile);
if (st == NULL && reuse) st = GetClosestDeletedStation(tile);
if (st != NULL) {
if (st->owner != _current_company) {
@ -2175,6 +2181,8 @@ static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
StationID station_to_join = GB(p2, 16, 16);
bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = INVALID_STATION;
bool distant_join = (station_to_join != INVALID_STATION);
if (distant_join && (!_settings_game.station.distant_join_stations || !IsValidStationID(station_to_join))) return CMD_ERROR;
@ -2224,7 +2232,7 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
if (st == NULL && distant_join) st = GetStation(station_to_join);
/* Find a deleted station close to us */
if (st == NULL) st = GetClosestDeletedStation(tile);
if (st == NULL && reuse) st = GetClosestDeletedStation(tile);
if (st != NULL) {
if (st->owner != _current_company) {

View File

@ -1170,7 +1170,7 @@ struct SelectStationWindow : Window {
/* Insert station to be joined into stored command */
SB(this->select_station_cmd.p2, 16, 16,
(distant_join ? _stations_nearby_list[st_index] : INVALID_STATION));
(distant_join ? _stations_nearby_list[st_index] : NEW_STATION));
/* Execute stored Command */
DoCommandP(&this->select_station_cmd);

View File

@ -12,6 +12,7 @@ struct Station;
struct RoadStop;
struct StationSpec;
static const StationID NEW_STATION = 0xFFFE;
static const StationID INVALID_STATION = 0xFFFF;
/** Station types */