1
0
Fork 0

(svn r19857) [1.0] -Backport from trunk:

- Fix: If a waypoint is immediately followed by a path signal a reservation would be made from that path signal before the waypoint is marked passed. As a result the order to go to the waypoint is used to reserve the path after the waypoint and as such trains get lost [FS#3770] (r19784)
- Fix: NULL pointer deference when testing relative scope *action2 on an unbuilt engine [FS#3828] (r19782)
- Fix: Crash on too long paths [FS#3807] (r19780, r19779, r19778, r19777, r19776)
- Fix: MP_VOID tiles shall have no tropic zone [FS#3820] (r19769)
- Fix: Half-desert tiles would never revert back to clear tiles (r19768)
release/1.0
rubidium 2010-05-18 21:44:47 +00:00
parent 3f1bc42eb0
commit eee6e228c7
12 changed files with 90 additions and 84 deletions

View File

@ -189,19 +189,40 @@ static void TileLoopClearAlps(TileIndex tile)
MarkTileDirtyByTile(tile);
}
/**
* Tests if at least one surrounding tile is desert
* @param tile tile to check
* @return does this tile have at least one desert tile around?
*/
static inline bool NeighbourIsDesert(TileIndex tile)
{
return GetTropicZone(tile + TileDiffXY( 1, 0)) == TROPICZONE_DESERT ||
GetTropicZone(tile + TileDiffXY( -1, 0)) == TROPICZONE_DESERT ||
GetTropicZone(tile + TileDiffXY( 0, 1)) == TROPICZONE_DESERT ||
GetTropicZone(tile + TileDiffXY( 0, -1)) == TROPICZONE_DESERT;
}
static void TileLoopClearDesert(TileIndex tile)
{
if (IsClearGround(tile, CLEAR_DESERT)) return;
/* Current desert level - 0 if it is not desert */
uint current = 0;
if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
/* Expected desert level - 0 if it shouldn't be desert */
uint expected = 0;
if (GetTropicZone(tile) == TROPICZONE_DESERT) {
SetClearGroundDensity(tile, CLEAR_DESERT, 3);
expected = 3;
} else if (NeighbourIsDesert(tile)) {
expected = 1;
}
if (current == expected) return;
if (expected == 0) {
SetClearGroundDensity(tile, CLEAR_GRASS, 3);
} else {
if (GetTropicZone(tile + TileDiffXY( 1, 0)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY(-1, 0)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY( 0, 1)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
return;
SetClearGroundDensity(tile, CLEAR_DESERT, 1);
/* Transition from clear to desert is not smooth (after clearing desert tile) */
SetClearGroundDensity(tile, CLEAR_DESERT, expected);
}
MarkTileDirtyByTile(tile);

View File

@ -448,16 +448,21 @@ void FioCreateDirectory(const char *name)
* It does not add the path separator to zero-sized strings.
* @param buf string to append the separator to
* @param buflen the length of the buf
* @return true iff the operation succeeded
*/
void AppendPathSeparator(char *buf, size_t buflen)
bool AppendPathSeparator(char *buf, size_t buflen)
{
size_t s = strlen(buf);
/* Length of string + path separator + '\0' */
if (s != 0 && buf[s - 1] != PATHSEPCHAR && s + 2 < buflen) {
if (s != 0 && buf[s - 1] != PATHSEPCHAR) {
if (s + 2 >= buflen) return false;
buf[s] = PATHSEPCHAR;
buf[s + 1] = '\0';
}
return true;
}
/**
@ -534,7 +539,18 @@ static void SimplifyFileName(char *name)
#endif
}
bool TarListAddFile(const char *filename)
/* static */ uint TarScanner::DoScan() {
DEBUG(misc, 1, "Scanning for tars");
TarScanner fs;
uint num = fs.Scan(".tar", DATA_DIR, false);
num += fs.Scan(".tar", AI_DIR, false);
num += fs.Scan(".tar", AI_LIBRARY_DIR, false);
num += fs.Scan(".tar", SCENARIO_DIR, false);
DEBUG(misc, 1, "Scan complete, found %d files", num);
return num;
}
bool TarScanner::AddFile(const char *filename, size_t basepath_length)
{
/* The TAR-header, repeated for every file */
typedef struct TarHeader {
@ -820,66 +836,6 @@ bool ExtractTar(const char *tar_filename)
return true;
}
static int ScanPathForTarFiles(const char *path, size_t basepath_length)
{
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
uint num = 0;
struct stat sb;
struct dirent *dirent;
DIR *dir;
if (path == NULL || (dir = ttd_opendir(path)) == NULL) return 0;
while ((dirent = readdir(dir)) != NULL) {
const char *d_name = FS2OTTD(dirent->d_name);
char filename[MAX_PATH];
if (!FiosIsValidFile(path, dirent, &sb)) continue;
snprintf(filename, lengthof(filename), "%s%s", path, d_name);
if (S_ISDIR(sb.st_mode)) {
/* Directory */
if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
AppendPathSeparator(filename, lengthof(filename));
num += ScanPathForTarFiles(filename, basepath_length);
} else if (S_ISREG(sb.st_mode)) {
/* File */
char *ext = strrchr(filename, '.');
/* If no extension or extension isn't .tar, skip the file */
if (ext == NULL) continue;
if (strcasecmp(ext, ".tar") != 0) continue;
if (TarListAddFile(filename)) num++;
}
}
closedir(dir);
return num;
}
void ScanForTarFiles()
{
Searchpath sp;
char path[MAX_PATH];
uint num = 0;
DEBUG(misc, 1, "Scanning for tars");
FOR_ALL_SEARCHPATHS(sp) {
FioAppendDirectory(path, MAX_PATH, sp, DATA_DIR);
num += ScanPathForTarFiles(path, strlen(path));
FioAppendDirectory(path, MAX_PATH, sp, AI_DIR);
num += ScanPathForTarFiles(path, strlen(path));
FioAppendDirectory(path, MAX_PATH, sp, AI_LIBRARY_DIR);
num += ScanPathForTarFiles(path, strlen(path));
FioAppendDirectory(path, MAX_PATH, sp, SCENARIO_DIR);
num += ScanPathForTarFiles(path, strlen(path));
}
DEBUG(misc, 1, "Scan complete, found %d files", num);
}
#if defined(WIN32) || defined(WINCE)
/**
* Determine the base (personal dir and game data dir) paths
@ -1079,7 +1035,7 @@ void DeterminePaths(const char *exe)
}
#endif /* ENABLE_NETWORK */
ScanForTarFiles();
TarScanner::DoScan();
}
/**
@ -1158,7 +1114,7 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s
/* Directory */
if (!recursive) continue;
if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
AppendPathSeparator(filename, lengthof(filename));
if (!AppendPathSeparator(filename, lengthof(filename))) continue;
num += ScanPath(fs, extension, filename, basepath_length, recursive);
} else if (S_ISREG(sb.st_mode)) {
/* File */
@ -1245,6 +1201,6 @@ uint FileScanner::Scan(const char *extension, const char *directory, bool recurs
{
char path[MAX_PATH];
strecpy(path, directory, lastof(path));
AppendPathSeparator(path, lengthof(path));
if (!AppendPathSeparator(path, lengthof(path))) return 0;
return ScanPath(this, extension, path, strlen(path), recursive);
}

View File

@ -57,7 +57,7 @@ char *FioAppendDirectory(char *buf, size_t buflen, Searchpath sp, Subdirectory s
char *FioGetDirectory(char *buf, size_t buflen, Subdirectory subdir);
void SanitizeFilename(char *filename);
void AppendPathSeparator(char *buf, size_t buflen);
bool AppendPathSeparator(char *buf, size_t buflen);
void DeterminePaths(const char *exe);
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
bool FileExists(const char *filename);
@ -87,6 +87,14 @@ public:
virtual bool AddFile(const char *filename, size_t basepath_length) = 0;
};
/** Helper for scanning for files with tar as extension */
class TarScanner : FileScanner {
public:
/* virtual */ bool AddFile(const char *filename, size_t basepath_length);
/** Do the scan for Tars. */
static uint DoScan();
};
/* Implementation of opendir/readdir/closedir for Windows */
#if defined(WIN32)

View File

@ -827,6 +827,8 @@ static void CreateDesertOrRainForest()
for (TileIndex tile = 0; tile != MapSize(); ++tile) {
if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
if (!IsValidTile(tile)) continue;
for (data = _make_desert_or_rainforest_data;
data != endof(_make_desert_or_rainforest_data); ++data) {
TileIndex t = AddTileIndexDiffCWrap(tile, *data);
@ -845,6 +847,8 @@ static void CreateDesertOrRainForest()
for (TileIndex tile = 0; tile != MapSize(); ++tile) {
if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
if (!IsValidTile(tile)) continue;
for (data = _make_desert_or_rainforest_data;
data != endof(_make_desert_or_rainforest_data); ++data) {
TileIndex t = AddTileIndexDiffCWrap(tile, *data);

View File

@ -27,7 +27,6 @@
#include <zlib.h>
#endif
extern bool TarListAddFile(const char *filename);
extern bool HasScenario(const ContentInfo *ci, bool md5sum);
ClientNetworkContentSocketHandler _network_content_client;
@ -498,7 +497,8 @@ void ClientNetworkContentSocketHandler::AfterDownload()
if (GunzipFile(this->curInfo)) {
unlink(GetFullFilename(this->curInfo, true));
TarListAddFile(GetFullFilename(this->curInfo, false));
TarScanner ts;
ts.AddFile(GetFullFilename(this->curInfo, false), 0);
if (this->curInfo->type == CONTENT_TYPE_BASE_MUSIC) {
/* Music can't be in a tar. So extract the tar! */

View File

@ -383,6 +383,7 @@ static inline const Vehicle *GRV(const ResolverObject *object)
case VSG_SCOPE_SELF: return object->u.vehicle.self;
case VSG_SCOPE_PARENT: return object->u.vehicle.parent;
case VSG_SCOPE_RELATIVE: {
if (object->u.vehicle.self == NULL) return NULL;
const Vehicle *v = NULL;
switch (GB(object->count, 6, 2)) {
default: NOT_REACHED();

View File

@ -92,17 +92,20 @@ bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
{
char filename[MAX_PATH];
int res;
#if defined(__MORPHOS__) || defined(__AMIGAOS__)
/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
if (FiosIsRoot(path)) {
snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
res = snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
} else // XXX - only next line!
#else
assert(path[strlen(path) - 1] == PATHSEPCHAR);
if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
#endif
snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name);
res = snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name);
/* Could we fully concatenate the path and filename? */
if (res >= (int)lengthof(filename) || res < 0) return false;
return stat(filename, sb) == 0;
}

View File

@ -2065,6 +2065,13 @@ bool AfterLoadGame()
}
}
if (CheckSavegameVersion(141)) {
for (TileIndex t = 0; t < map_size; t++) {
/* Reset tropic zone for VOID tiles, they shall not have any. */
if (IsTileType(t, MP_VOID)) SetTropicZone(t, TROPICZONE_NORMAL);
}
}
/* Road stops is 'only' updating some caches */
AfterLoadRoadStops();
AfterLoadLabelMaps();

View File

@ -87,9 +87,6 @@ void ScriptScanner::ScanScriptDir(const char *info_file_name, Subdirectory searc
char buf[MAX_PATH];
Searchpath sp;
extern void ScanForTarFiles();
ScanForTarFiles();
FOR_ALL_SEARCHPATHS(sp) {
FioAppendDirectory(buf, MAX_PATH, sp, search_dir);
if (FileExists(buf)) this->ScanDir(buf, info_file_name);

View File

@ -395,7 +395,13 @@ void NORETURN CDECL error(const char *str, ...) WARN_FORMAT(1, 2);
#define _stricmp strcasecmp
#endif
#if !defined(MAX_PATH)
#if defined(MAX_PATH)
/* It's already defined, no need to override */
#elif defined(PATH_MAX) && PATH_MAX > 0
/* Use the value from PATH_MAX, if it exists */
#define MAX_PATH PATH_MAX
#else
/* If all else fails, hardcode something :( */
#define MAX_PATH 260
#endif

View File

@ -186,6 +186,7 @@ static inline bool IsTileOwner(TileIndex tile, Owner owner)
static inline void SetTropicZone(TileIndex tile, TropicZone type)
{
assert(tile < MapSize());
assert(!IsTileType(tile, MP_VOID) || type == TROPICZONE_NORMAL);
SB(_m[tile].m6, 0, 2, type);
}

View File

@ -2230,6 +2230,8 @@ static void CheckNextTrainTile(Train *v)
if ((v->tile == v->dest_tile && v->current_order.IsType(OT_GOTO_DEPOT)) || v->track == TRACK_BIT_DEPOT) return;
/* Exit if we are on a station tile and are going to stop. */
if (IsRailStationTile(v->tile) && v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile))) return;
/* If we reached our waypoint, make sure we see that. */
if (v->current_order.IsType(OT_GOTO_WAYPOINT) && IsRailWaypointTile(v->tile) && GetStationIndex(v->tile) == v->current_order.GetDestination()) ProcessOrders(v);
/* Exit if the current order doesn't have a destination, but the train has orders. */
if ((v->current_order.IsType(OT_NOTHING) || v->current_order.IsType(OT_LEAVESTATION) || v->current_order.IsType(OT_LOADING)) && v->GetNumOrders() > 0) return;