Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138465 additions and 70987 deletions

View File

@@ -23,11 +23,12 @@
#include "querystring_gui.h"
#include "engine_func.h"
#include "landscape_type.h"
#include "date_func.h"
#include "timer/timer_game_calendar.h"
#include "core/geometry_func.hpp"
#include "gamelog.h"
#include "stringfilter_type.h"
#include "misc_cmd.h"
#include "gamelog_internal.h"
#include "widgets/fios_widget.h"
@@ -41,7 +42,6 @@ LoadCheckData _load_check_data; ///< Data loaded from save during SL_LOAD_CHE
static bool _fios_path_changed;
static bool _savegame_sort_dirty;
/**
* Reset read data.
*/
@@ -49,27 +49,21 @@ void LoadCheckData::Clear()
{
this->checkable = false;
this->error = INVALID_STRING_ID;
free(this->error_data);
this->error_data = nullptr;
this->error_msg.clear();
this->map_size_x = this->map_size_y = 256; // Default for old savegames which do not store mapsize.
this->current_date = 0;
this->settings = {};
for (auto &pair : this->companies) {
delete pair.second;
}
companies.clear();
GamelogFree(this->gamelog_action, this->gamelog_actions);
this->gamelog_action = nullptr;
this->gamelog_actions = 0;
this->gamelog.Reset();
ClearGRFConfigList(&this->grfconfig);
}
/** Load game/scenario with optional content download */
static const NWidgetPart _nested_load_dialog_widgets[] = {
static constexpr NWidgetPart _nested_load_dialog_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION),
@@ -130,7 +124,7 @@ static const NWidgetPart _nested_load_dialog_widgets[] = {
};
/** Load heightmap with content download */
static const NWidgetPart _nested_load_heightmap_dialog_widgets[] = {
static constexpr NWidgetPart _nested_load_heightmap_dialog_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION),
@@ -175,7 +169,7 @@ static const NWidgetPart _nested_load_heightmap_dialog_widgets[] = {
};
/** Save game/scenario */
static const NWidgetPart _nested_save_dialog_widgets[] = {
static constexpr NWidgetPart _nested_save_dialog_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION),
@@ -286,15 +280,15 @@ private:
StringFilter string_filter; ///< Filter for available games.
QueryString filter_editbox; ///< Filter editbox;
std::vector<bool> fios_items_shown; ///< Map of the filtered out fios items
std::vector<FiosItem *> display_list; ///< Filtered display list
static void SaveGameConfirmationCallback(Window *w, bool confirmed)
static void SaveGameConfirmationCallback(Window *, bool confirmed)
{
/* File name has already been written to _file_to_saveload */
if (confirmed) _switch_mode = SM_SAVE_GAME;
}
static void SaveHeightmapConfirmationCallback(Window *w, bool confirmed)
static void SaveHeightmapConfirmationCallback(Window *, bool confirmed)
{
/* File name has already been written to _file_to_saveload */
if (confirmed) _switch_mode = SM_SAVE_HEIGHTMAP;
@@ -305,8 +299,7 @@ public:
/** Generate a default save filename. */
void GenerateFileName()
{
GenerateDefaultSaveName(this->filename_editbox.text.buf, &this->filename_editbox.text.buf[this->filename_editbox.text.max_bytes - 1]);
this->filename_editbox.text.UpdateSize();
this->filename_editbox.text.Assign(GenerateDefaultSaveName());
}
SaveLoadWindow(WindowDesc *desc, AbstractFileType abstract_filetype, SaveLoadOperation fop)
@@ -333,7 +326,7 @@ public:
this->querystrings[WID_SL_SAVE_OSK_TITLE] = &this->filename_editbox;
this->filename_editbox.ok_button = WID_SL_SAVE_GAME;
this->CreateNestedTree(true);
this->CreateNestedTree();
if (this->fop == SLO_LOAD && this->abstract_filetype == FT_SAVEGAME) {
this->GetWidget<NWidgetStacked>(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
}
@@ -378,24 +371,22 @@ public:
/* Select the initial directory. */
o_dir.type = FIOS_TYPE_DIRECT;
std::string dir;
switch (this->abstract_filetype) {
case FT_SAVEGAME:
dir = FioFindDirectory(SAVE_DIR);
o_dir.name = FioFindDirectory(SAVE_DIR);
break;
case FT_SCENARIO:
dir = FioFindDirectory(SCENARIO_DIR);
o_dir.name = FioFindDirectory(SCENARIO_DIR);
break;
case FT_HEIGHTMAP:
dir = FioFindDirectory(HEIGHTMAP_DIR);
o_dir.name = FioFindDirectory(HEIGHTMAP_DIR);
break;
default:
dir = _personal_dir;
o_dir.name = _personal_dir;
}
strecpy(o_dir.name, dir.c_str(), lastof(o_dir.name));
switch (this->fop) {
case SLO_SAVE:
@@ -408,7 +399,7 @@ public:
}
}
void Close() override
void Close([[maybe_unused]] int data = 0) override
{
/* pause is only used in single-player, non-editor mode, non menu mode */
if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
@@ -417,7 +408,7 @@ public:
this->Window::Close();
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
switch (widget) {
case WID_SL_SORT_BYNAME:
@@ -428,19 +419,19 @@ public:
break;
case WID_SL_BACKGROUND: {
static const char *path = nullptr;
static StringID str = STR_ERROR_UNABLE_TO_READ_DRIVE;
static uint64 tot = 0;
static std::string path;
static std::optional<uint64_t> free_space = std::nullopt;
if (_fios_path_changed) {
str = FiosGetDescText(&path, &tot);
path = FiosGetCurrentPath();
free_space = FiosGetDiskFreeSpace(path);
_fios_path_changed = false;
}
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
if (str != STR_ERROR_UNABLE_TO_READ_DRIVE) SetDParam(0, tot);
DrawString(ir.left, ir.right, ir.top + FONT_HEIGHT_NORMAL, str);
if (free_space.has_value()) SetDParam(0, free_space.value());
DrawString(ir.left, ir.right, ir.top + GetCharacterHeight(FS_NORMAL), free_space.has_value() ? STR_SAVELOAD_BYTES_FREE : STR_ERROR_UNABLE_TO_READ_DRIVE);
DrawString(ir.left, ir.right, ir.top, path, TC_BLACK);
break;
}
@@ -451,14 +442,8 @@ public:
Rect tr = r.Shrink(WidgetDimensions::scaled.inset).WithHeight(this->resize.step_height);
uint scroll_pos = this->vscroll->GetPosition();
for (uint row = 0; row < this->fios_items.size() && tr.top < br.bottom; row++) {
if (!this->fios_items_shown[row]) {
/* The current item is filtered out : we do not show it */
scroll_pos++;
continue;
}
if (row < scroll_pos) continue;
const FiosItem *item = &this->fios_items[row];
for (auto it = this->display_list.begin() + scroll_pos; it != this->display_list.end() && tr.top < br.bottom; ++it) {
const FiosItem *item = *it;
if (item == this->selected) {
GfxFillRect(br.left, tr.top, br.right, tr.bottom, PC_DARK_BLUE);
@@ -480,7 +465,7 @@ public:
void DrawDetails(const Rect &r) const
{
/* Header panel */
int HEADER_HEIGHT = FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.frametext.Vertical();
int HEADER_HEIGHT = GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.frametext.Vertical();
Rect hr = r.WithHeight(HEADER_HEIGHT).Shrink(WidgetDimensions::scaled.frametext);
Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
@@ -493,23 +478,23 @@ public:
if (this->selected == nullptr) return;
/* Details panel */
tr.bottom -= FONT_HEIGHT_NORMAL - 1;
tr.bottom -= GetCharacterHeight(FS_NORMAL) - 1;
if (tr.top > tr.bottom) return;
if (!_load_check_data.checkable) {
/* Old savegame, no information available */
DrawString(tr, STR_SAVELOAD_DETAIL_NOT_AVAILABLE);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
} else if (_load_check_data.error != INVALID_STRING_ID) {
/* Incompatible / broken savegame */
SetDParamStr(0, _load_check_data.error_data);
SetDParamStr(0, _load_check_data.error_msg);
tr.top = DrawStringMultiLine(tr, _load_check_data.error, TC_RED);
} else {
/* Mapsize */
SetDParam(0, _load_check_data.map_size_x);
SetDParam(1, _load_check_data.map_size_y);
DrawString(tr, STR_NETWORK_SERVER_LIST_MAP_SIZE);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
if (tr.top > tr.bottom) return;
/* Climate */
@@ -517,7 +502,7 @@ public:
if (landscape < NUM_LANDSCAPE) {
SetDParam(0, STR_CLIMATE_TEMPERATE_LANDSCAPE + landscape);
DrawString(tr, STR_NETWORK_SERVER_LIST_LANDSCAPE);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
}
tr.top += WidgetDimensions::scaled.vsep_normal;
@@ -525,9 +510,9 @@ public:
/* Start date (if available) */
if (_load_check_data.settings.game_creation.starting_year != 0) {
SetDParam(0, ConvertYMDToDate(_load_check_data.settings.game_creation.starting_year, 0, 1));
SetDParam(0, TimerGameCalendar::ConvertYMDToDate(_load_check_data.settings.game_creation.starting_year, 0, 1));
DrawString(tr, STR_NETWORK_SERVER_LIST_START_DATE);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
}
if (tr.top > tr.bottom) return;
@@ -536,7 +521,7 @@ public:
/* Current date */
SetDParam(0, _load_check_data.current_date);
DrawString(tr, STR_NETWORK_SERVER_LIST_CURRENT_DATE);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
}
/* Hide the NewGRF stuff when saving. We also hide the button. */
@@ -548,7 +533,7 @@ public:
SetDParam(0, _load_check_data.grfconfig == nullptr ? STR_NEWGRF_LIST_NONE :
STR_NEWGRF_LIST_ALL_FOUND + _load_check_data.grf_compatibility);
DrawString(tr, STR_SAVELOAD_DETAIL_GRFSTATUS);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
}
if (tr.top > tr.bottom) return;
@@ -569,22 +554,22 @@ public:
SetDParam(2, c.name_2);
}
DrawString(tr, STR_SAVELOAD_DETAIL_COMPANY_INDEX);
tr.top += FONT_HEIGHT_NORMAL;
tr.top += GetCharacterHeight(FS_NORMAL);
if (tr.top > tr.bottom) break;
}
}
}
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
switch (widget) {
case WID_SL_BACKGROUND:
size->height = 2 * FONT_HEIGHT_NORMAL + padding.height;
size->height = 2 * GetCharacterHeight(FS_NORMAL) + padding.height;
break;
case WID_SL_DRIVES_DIRECTORIES_LIST:
resize->height = FONT_HEIGHT_NORMAL;
resize->height = GetCharacterHeight(FS_NORMAL);
size->height = resize->height * 10 + padding.height;
break;
case WID_SL_SORT_BYNAME:
@@ -609,7 +594,7 @@ public:
this->DrawWidgets();
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_SL_SORT_BYNAME: // Sort save names by name
@@ -634,10 +619,7 @@ public:
case WID_SL_LOAD_BUTTON: {
if (this->selected == nullptr || _load_check_data.HasErrors()) break;
const char *name = FiosBrowseTo(this->selected);
_file_to_saveload.SetMode(this->selected->type);
_file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(this->selected->title);
_file_to_saveload.Set(*this->selected);
if (this->abstract_filetype == FT_HEIGHTMAP) {
this->Close();
@@ -665,19 +647,13 @@ public:
break;
case WID_SL_DRIVES_DIRECTORIES_LIST: { // Click the listbox
int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top);
if (y == INT_MAX) return;
auto it = this->vscroll->GetScrolledItemFromWidget(this->display_list, pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top);
if (it == this->display_list.end()) return;
/* Get the corresponding non-filtered out item from the list */
int i = 0;
while (i <= y) {
if (!this->fios_items_shown[i]) y++;
i++;
}
const FiosItem *file = &this->fios_items[y];
const FiosItem *file = *it;
const char *name = FiosBrowseTo(file);
if (name == nullptr) {
if (FiosBrowseTo(file)) {
/* Changed directory, need refresh. */
this->InvalidateData(SLIWD_RESCAN_FILES);
break;
@@ -690,7 +666,7 @@ public:
if (GetDetailedFileType(file->type) == DFT_GAME_FILE) {
/* Other detailed file types cannot be checked before. */
SaveOrLoad(name, SLO_CHECK, DFT_GAME_FILE, NO_DIRECTORY, false);
SaveOrLoad(file->name, SLO_CHECK, DFT_GAME_FILE, NO_DIRECTORY, false);
}
this->InvalidateData(SLIWD_SELECTION_CHANGES);
@@ -707,9 +683,7 @@ public:
this->OnClick(pt, WID_SL_LOAD_BUTTON, 1);
} else {
assert(this->abstract_filetype == FT_HEIGHTMAP);
_file_to_saveload.SetMode(file->type);
_file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(file->title);
_file_to_saveload.Set(*file);
this->Close();
ShowHeightmapLoad();
@@ -742,19 +716,14 @@ public:
}
}
void OnMouseOver(Point pt, int widget) override
void OnMouseOver([[maybe_unused]] Point pt, WidgetID widget) override
{
if (widget == WID_SL_DRIVES_DIRECTORIES_LIST) {
int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top);
if (y == INT_MAX) return;
auto it = this->vscroll->GetScrolledItemFromWidget(this->display_list, pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top);
if (it == this->display_list.end()) return;
/* Get the corresponding non-filtered out item from the list */
int i = 0;
while (i <= y) {
if (!this->fios_items_shown[i]) y++;
i++;
}
const FiosItem *file = &this->fios_items[y];
const FiosItem *file = *it;
if (file != this->highlighted) {
this->highlighted = file;
@@ -766,7 +735,7 @@ public:
}
}
EventState OnKeyPress(WChar key, uint16 keycode) override
EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
{
if (keycode == WKC_ESC) {
this->Close();
@@ -816,6 +785,35 @@ public:
this->vscroll->SetCapacityFromWidget(this, WID_SL_DRIVES_DIRECTORIES_LIST);
}
void BuildDisplayList()
{
/* Filter changes */
this->display_list.clear();
this->display_list.reserve(this->fios_items.size());
if (this->string_filter.IsEmpty()) {
/* We don't filter anything out if the filter editbox is empty */
for (auto &it : this->fios_items) {
this->display_list.push_back(&it);
}
} else {
for (auto &it : this->fios_items) {
this->string_filter.ResetState();
this->string_filter.AddLine(it.title);
/* We set the vector to show this fios element as filtered depending on the result of the filter */
if (this->string_filter.GetState()) {
this->display_list.push_back(&it);
} else if (&it == this->selected) {
/* The selected element has been filtered out */
this->selected = nullptr;
this->OnInvalidateData(SLIWD_SELECTION_CHANGES);
}
}
}
this->vscroll->SetCount(this->display_list.size());
}
/**
* Some data on this window has become invalid.
* @param data Information about the changed data.
@@ -831,15 +829,14 @@ public:
if (!gui_scope) break;
_fios_path_changed = true;
this->fios_items.BuildFileList(this->abstract_filetype, this->fop);
this->vscroll->SetCount((uint)this->fios_items.size());
this->fios_items.BuildFileList(this->abstract_filetype, this->fop, true);
this->selected = nullptr;
_load_check_data.Clear();
/* We reset the files filtered */
this->OnInvalidateData(SLIWD_FILTER_CHANGES);
FALLTHROUGH;
[[fallthrough]];
case SLIWD_SELECTION_CHANGES:
/* Selection changes */
@@ -871,35 +868,12 @@ public:
break;
case SLIWD_FILTER_CHANGES:
/* Filter changes */
this->fios_items_shown.resize(this->fios_items.size());
uint items_shown_count = 0; ///< The number of items shown in the list
/* We pass through every fios item */
for (uint i = 0; i < this->fios_items.size(); i++) {
if (this->string_filter.IsEmpty()) {
/* We don't filter anything out if the filter editbox is empty */
this->fios_items_shown[i] = true;
items_shown_count++;
} else {
this->string_filter.ResetState();
this->string_filter.AddLine(this->fios_items[i].title);
/* We set the vector to show this fios element as filtered depending on the result of the filter */
this->fios_items_shown[i] = this->string_filter.GetState();
if (this->fios_items_shown[i]) items_shown_count++;
if (&(this->fios_items[i]) == this->selected && !this->fios_items_shown[i]) {
/* The selected element has been filtered out */
this->selected = nullptr;
this->OnInvalidateData(SLIWD_SELECTION_CHANGES);
}
}
}
this->vscroll->SetCount(items_shown_count);
this->BuildDisplayList();
break;
}
}
void OnEditboxChanged(int wid) override
void OnEditboxChanged(WidgetID wid) override
{
if (wid == WID_SL_FILTER) {
this->string_filter.SetFilterTerm(this->filter_editbox.text.buf);
@@ -909,27 +883,27 @@ public:
};
/** Load game/scenario */
static WindowDesc _load_dialog_desc(
static WindowDesc _load_dialog_desc(__FILE__, __LINE__,
WDP_CENTER, "load_game", 500, 294,
WC_SAVELOAD, WC_NONE,
0,
_nested_load_dialog_widgets, lengthof(_nested_load_dialog_widgets)
std::begin(_nested_load_dialog_widgets), std::end(_nested_load_dialog_widgets)
);
/** Load heightmap */
static WindowDesc _load_heightmap_dialog_desc(
static WindowDesc _load_heightmap_dialog_desc(__FILE__, __LINE__,
WDP_CENTER, "load_heightmap", 257, 320,
WC_SAVELOAD, WC_NONE,
0,
_nested_load_heightmap_dialog_widgets, lengthof(_nested_load_heightmap_dialog_widgets)
std::begin(_nested_load_heightmap_dialog_widgets), std::end(_nested_load_heightmap_dialog_widgets)
);
/** Save game/scenario */
static WindowDesc _save_dialog_desc(
static WindowDesc _save_dialog_desc(__FILE__, __LINE__,
WDP_CENTER, "save_game", 500, 294,
WC_SAVELOAD, WC_NONE,
0,
_nested_save_dialog_widgets, lengthof(_nested_save_dialog_widgets)
std::begin(_nested_save_dialog_widgets), std::end(_nested_save_dialog_widgets)
);
/**