mirror of https://github.com/OpenTTD/OpenTTD
Fix: Rail/road type conversion data is not populated on new game. (#13403)
This means that the rail/road type conversion that happens if NewGRFs are changed does not work the first time for a new game, only with a savegame.pull/11338/merge
parent
402aaf3d11
commit
bf6293a13f
|
@ -37,6 +37,8 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/game_instance.hpp"
|
#include "game/game_instance.hpp"
|
||||||
|
#include "newgrf_railtype.h"
|
||||||
|
#include "newgrf_roadtype.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "tgp.h"
|
#include "tgp.h"
|
||||||
|
@ -320,6 +322,8 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
|
||||||
|
|
||||||
/* Load the right landscape stuff, and the NewGRFs! */
|
/* Load the right landscape stuff, and the NewGRFs! */
|
||||||
GfxLoadSprites();
|
GfxLoadSprites();
|
||||||
|
SetCurrentRailTypeLabelList();
|
||||||
|
SetCurrentRoadTypeLabelList();
|
||||||
InitializeBuildingCounts();
|
InitializeBuildingCounts();
|
||||||
LoadStringWidthTable();
|
LoadStringWidthTable();
|
||||||
|
|
||||||
|
|
|
@ -329,4 +329,11 @@ struct GRFFileProps : GRFFilePropsBase<1> {
|
||||||
uint16_t override; ///< id of the entity been replaced by
|
uint16_t override; ///< id of the entity been replaced by
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Container for a label for rail or road type conversion. */
|
||||||
|
template <typename T>
|
||||||
|
struct LabelObject {
|
||||||
|
T label = {}; ///< Label of rail or road type.
|
||||||
|
uint8_t subtype = 0; ///< Subtype of type (road or tram).
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* NEWGRF_COMMONS_H */
|
#endif /* NEWGRF_COMMONS_H */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
#include "depot_base.h"
|
#include "depot_base.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
|
#include "tunnelbridge_map.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
@ -174,3 +175,73 @@ uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
|
||||||
/* If not found, return as invalid */
|
/* If not found, return as invalid */
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<LabelObject<RailTypeLabel>> _railtype_list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if any saved rail type labels are different to the currently loaded
|
||||||
|
* rail types. Rail types stored in the map will be converted if necessary.
|
||||||
|
*/
|
||||||
|
void ConvertRailTypes()
|
||||||
|
{
|
||||||
|
std::vector<RailType> railtype_conversion_map;
|
||||||
|
bool needs_conversion = false;
|
||||||
|
|
||||||
|
for (auto it = std::begin(_railtype_list); it != std::end(_railtype_list); ++it) {
|
||||||
|
RailType rt = GetRailTypeByLabel(it->label);
|
||||||
|
if (rt == INVALID_RAILTYPE) {
|
||||||
|
rt = RAILTYPE_RAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
railtype_conversion_map.push_back(rt);
|
||||||
|
|
||||||
|
/* Conversion is needed if the rail type is in a different position than the list. */
|
||||||
|
if (it->label != 0 && rt != std::distance(std::begin(_railtype_list), it)) needs_conversion = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!needs_conversion) return;
|
||||||
|
|
||||||
|
for (const auto t : Map::Iterate()) {
|
||||||
|
switch (GetTileType(t)) {
|
||||||
|
case MP_RAILWAY:
|
||||||
|
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP_ROAD:
|
||||||
|
if (IsLevelCrossing(t)) {
|
||||||
|
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP_STATION:
|
||||||
|
if (HasStationRail(t)) {
|
||||||
|
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP_TUNNELBRIDGE:
|
||||||
|
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
|
||||||
|
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Populate railtype label list with current values. */
|
||||||
|
void SetCurrentRailTypeLabelList()
|
||||||
|
{
|
||||||
|
_railtype_list.clear();
|
||||||
|
|
||||||
|
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
||||||
|
_railtype_list.push_back({GetRailTypeInfo(rt)->label, 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearRailTypeLabelList()
|
||||||
|
{
|
||||||
|
_railtype_list.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -59,4 +59,8 @@ SpriteID GetCustomSignalSprite(const RailTypeInfo *rti, TileIndex tile, SignalTy
|
||||||
RailType GetRailTypeTranslation(uint8_t railtype, const GRFFile *grffile);
|
RailType GetRailTypeTranslation(uint8_t railtype, const GRFFile *grffile);
|
||||||
uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile);
|
uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile);
|
||||||
|
|
||||||
|
void ConvertRailTypes();
|
||||||
|
void SetCurrentRailTypeLabelList();
|
||||||
|
void ClearRailTypeLabelList();
|
||||||
|
|
||||||
#endif /* NEWGRF_RAILTYPE_H */
|
#endif /* NEWGRF_RAILTYPE_H */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
#include "depot_base.h"
|
#include "depot_base.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
|
#include "tunnelbridge_map.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
@ -167,3 +168,67 @@ uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
|
||||||
/* If not found, return as invalid */
|
/* If not found, return as invalid */
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<LabelObject<RoadTypeLabel>> _roadtype_list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if any saved road type labels are different to the currently loaded
|
||||||
|
* road types. Road types stored in the map will be converted if necessary.
|
||||||
|
*/
|
||||||
|
void ConvertRoadTypes()
|
||||||
|
{
|
||||||
|
std::vector<RoadType> roadtype_conversion_map;
|
||||||
|
bool needs_conversion = false;
|
||||||
|
for (auto it = std::begin(_roadtype_list); it != std::end(_roadtype_list); ++it) {
|
||||||
|
RoadType rt = GetRoadTypeByLabel(it->label);
|
||||||
|
if (rt == INVALID_ROADTYPE || GetRoadTramType(rt) != it->subtype) {
|
||||||
|
rt = it->subtype ? ROADTYPE_TRAM : ROADTYPE_ROAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
roadtype_conversion_map.push_back(rt);
|
||||||
|
|
||||||
|
/* Conversion is needed if the road type is in a different position than the list. */
|
||||||
|
if (it->label != 0 && rt != std::distance(std::begin(_roadtype_list), it)) needs_conversion = true;
|
||||||
|
}
|
||||||
|
if (!needs_conversion) return;
|
||||||
|
|
||||||
|
for (TileIndex t : Map::Iterate()) {
|
||||||
|
switch (GetTileType(t)) {
|
||||||
|
case MP_ROAD:
|
||||||
|
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
||||||
|
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP_STATION:
|
||||||
|
if (IsStationRoadStop(t) || IsRoadWaypoint(t)) {
|
||||||
|
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
||||||
|
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP_TUNNELBRIDGE:
|
||||||
|
if (GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD) {
|
||||||
|
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
||||||
|
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Populate road type label list with current values. */
|
||||||
|
void SetCurrentRoadTypeLabelList()
|
||||||
|
{
|
||||||
|
_roadtype_list.clear();
|
||||||
|
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||||
|
_roadtype_list.push_back({GetRoadTypeInfo(rt)->label, GetRoadTramType(rt)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearRoadTypeLabelList()
|
||||||
|
{
|
||||||
|
_roadtype_list.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -59,4 +59,8 @@ SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSp
|
||||||
RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8_t tracktype, const GRFFile *grffile);
|
RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8_t tracktype, const GRFFile *grffile);
|
||||||
uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile);
|
uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile);
|
||||||
|
|
||||||
|
void ConvertRoadTypes();
|
||||||
|
void SetCurrentRoadTypeLabelList();
|
||||||
|
void ClearRoadTypeLabelList();
|
||||||
|
|
||||||
#endif /* NEWGRF_ROADTYPE_H */
|
#endif /* NEWGRF_ROADTYPE_H */
|
||||||
|
|
|
@ -15,134 +15,13 @@
|
||||||
#include "saveload_internal.h"
|
#include "saveload_internal.h"
|
||||||
#include "../rail.h"
|
#include "../rail.h"
|
||||||
#include "../road.h"
|
#include "../road.h"
|
||||||
#include "../station_map.h"
|
#include "../newgrf_railtype.h"
|
||||||
#include "../tunnelbridge_map.h"
|
#include "../newgrf_roadtype.h"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
/** Container for a label for rail or road type conversion. */
|
extern std::vector<LabelObject<RailTypeLabel>> _railtype_list;
|
||||||
template <typename T>
|
extern std::vector<LabelObject<RoadTypeLabel>> _roadtype_list;
|
||||||
struct LabelObject {
|
|
||||||
T label = {}; ///< Label of rail or road type.
|
|
||||||
uint8_t subtype = 0; ///< Subtype of type (road or tram).
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::vector<LabelObject<RailTypeLabel>> _railtype_list;
|
|
||||||
static std::vector<LabelObject<RoadTypeLabel>> _roadtype_list;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if any saved rail type labels are different to the currently loaded
|
|
||||||
* rail types. Rail types stored in the map will be converted if necessary.
|
|
||||||
*/
|
|
||||||
static void ConvertRailTypes()
|
|
||||||
{
|
|
||||||
std::vector<RailType> railtype_conversion_map;
|
|
||||||
bool needs_conversion = false;
|
|
||||||
|
|
||||||
for (auto it = std::begin(_railtype_list); it != std::end(_railtype_list); ++it) {
|
|
||||||
RailType rt = GetRailTypeByLabel(it->label);
|
|
||||||
if (rt == INVALID_RAILTYPE) {
|
|
||||||
rt = RAILTYPE_RAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
railtype_conversion_map.push_back(rt);
|
|
||||||
|
|
||||||
/* Conversion is needed if the rail type is in a different position than the list. */
|
|
||||||
if (it->label != 0 && rt != std::distance(std::begin(_railtype_list), it)) needs_conversion = true;
|
|
||||||
}
|
|
||||||
if (!needs_conversion) return;
|
|
||||||
|
|
||||||
for (const auto t : Map::Iterate()) {
|
|
||||||
switch (GetTileType(t)) {
|
|
||||||
case MP_RAILWAY:
|
|
||||||
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_ROAD:
|
|
||||||
if (IsLevelCrossing(t)) {
|
|
||||||
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_STATION:
|
|
||||||
if (HasStationRail(t)) {
|
|
||||||
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_TUNNELBRIDGE:
|
|
||||||
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
|
|
||||||
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if any saved road type labels are different to the currently loaded
|
|
||||||
* road types. Road types stored in the map will be converted if necessary.
|
|
||||||
*/
|
|
||||||
static void ConvertRoadTypes()
|
|
||||||
{
|
|
||||||
std::vector<RoadType> roadtype_conversion_map;
|
|
||||||
bool needs_conversion = false;
|
|
||||||
for (auto it = std::begin(_roadtype_list); it != std::end(_roadtype_list); ++it) {
|
|
||||||
RoadType rt = GetRoadTypeByLabel(it->label);
|
|
||||||
if (rt == INVALID_ROADTYPE || GetRoadTramType(rt) != it->subtype) {
|
|
||||||
rt = it->subtype ? ROADTYPE_TRAM : ROADTYPE_ROAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
roadtype_conversion_map.push_back(rt);
|
|
||||||
|
|
||||||
/* Conversion is needed if the road type is in a different position than the list. */
|
|
||||||
if (it->label != 0 && rt != std::distance(std::begin(_roadtype_list), it)) needs_conversion = true;
|
|
||||||
}
|
|
||||||
if (!needs_conversion) return;
|
|
||||||
|
|
||||||
for (TileIndex t : Map::Iterate()) {
|
|
||||||
switch (GetTileType(t)) {
|
|
||||||
case MP_ROAD:
|
|
||||||
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
|
||||||
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_STATION:
|
|
||||||
if (IsStationRoadStop(t) || IsRoadWaypoint(t)) {
|
|
||||||
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
|
||||||
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_TUNNELBRIDGE:
|
|
||||||
if (GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD) {
|
|
||||||
if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
|
|
||||||
if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Populate label lists with current values. */
|
|
||||||
static void SetCurrentLabelLists()
|
|
||||||
{
|
|
||||||
_railtype_list.clear();
|
|
||||||
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
|
||||||
_railtype_list.push_back({GetRailTypeInfo(rt)->label, 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
_roadtype_list.clear();
|
|
||||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
|
||||||
_roadtype_list.push_back({GetRoadTypeInfo(rt)->label, GetRoadTramType(rt)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Perform rail type and road type conversion if necessary. */
|
/** Perform rail type and road type conversion if necessary. */
|
||||||
void AfterLoadLabelMaps()
|
void AfterLoadLabelMaps()
|
||||||
|
@ -150,13 +29,8 @@ void AfterLoadLabelMaps()
|
||||||
ConvertRailTypes();
|
ConvertRailTypes();
|
||||||
ConvertRoadTypes();
|
ConvertRoadTypes();
|
||||||
|
|
||||||
SetCurrentLabelLists();
|
SetCurrentRailTypeLabelList();
|
||||||
}
|
SetCurrentRoadTypeLabelList();
|
||||||
|
|
||||||
void ResetLabelMaps()
|
|
||||||
{
|
|
||||||
_railtype_list.clear();
|
|
||||||
_roadtype_list.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RAILChunkHandler : ChunkHandler {
|
struct RAILChunkHandler : ChunkHandler {
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
#include "../string_func.h"
|
#include "../string_func.h"
|
||||||
#include "../fios.h"
|
#include "../fios.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
#include "../newgrf_railtype.h"
|
||||||
|
#include "../newgrf_roadtype.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
# include <emscripten.h>
|
# include <emscripten.h>
|
||||||
|
@ -2789,7 +2792,8 @@ extern bool LoadOldSaveGame(const std::string &file);
|
||||||
static void ResetSaveloadData()
|
static void ResetSaveloadData()
|
||||||
{
|
{
|
||||||
ResetTempEngineData();
|
ResetTempEngineData();
|
||||||
ResetLabelMaps();
|
ClearRailTypeLabelList();
|
||||||
|
ClearRoadTypeLabelList();
|
||||||
ResetOldWaypoints();
|
ResetOldWaypoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ void AfterLoadVehiclesPhase2(bool part_of_load);
|
||||||
void FixupTrainLengths();
|
void FixupTrainLengths();
|
||||||
void AfterLoadStations();
|
void AfterLoadStations();
|
||||||
void AfterLoadRoadStops();
|
void AfterLoadRoadStops();
|
||||||
void ResetLabelMaps();
|
|
||||||
void AfterLoadLabelMaps();
|
void AfterLoadLabelMaps();
|
||||||
void AfterLoadStoryBook();
|
void AfterLoadStoryBook();
|
||||||
void AfterLoadLinkGraphs();
|
void AfterLoadLinkGraphs();
|
||||||
|
|
Loading…
Reference in New Issue