Merge branch 'master' into jgrpp
# Conflicts: # .gitignore # CMakeLists.txt # src/3rdparty/optional/optional.hpp # src/group_cmd.cpp # src/industry_cmd.cpp # src/misc_gui.cpp # src/video/sdl2_v.cpp
This commit is contained in:
23
src/3rdparty/optional/LICENSE_1_0.txt
vendored
23
src/3rdparty/optional/LICENSE_1_0.txt
vendored
@@ -1,23 +0,0 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
1066
src/3rdparty/optional/optional.hpp
vendored
1066
src/3rdparty/optional/optional.hpp
vendored
File diff suppressed because it is too large
Load Diff
33
src/3rdparty/optional/ottd_optional.h
vendored
33
src/3rdparty/optional/ottd_optional.h
vendored
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file ottd_optional.h Header to select between native. */
|
||||
|
||||
#ifndef OTTD_OPTIONAL_H
|
||||
#define OTTD_OPTIONAL_H
|
||||
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<version>)
|
||||
# include <version>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201703L) || (defined(__cpp_lib_optional) && __cpp_lib_optional >= 201606L)
|
||||
|
||||
/* Native std::optional. */
|
||||
#include <optional>
|
||||
namespace opt = std;
|
||||
|
||||
#else
|
||||
|
||||
/* No std::optional, use local copy instead. */
|
||||
#include "optional.hpp"
|
||||
namespace opt = std::experimental;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* OTTD_OPTIONAL_H */
|
||||
@@ -1,3 +1,11 @@
|
||||
add_subdirectory(script)
|
||||
add_subdirectory(settingsgen)
|
||||
add_subdirectory(strgen)
|
||||
|
||||
if(OPTION_TOOLS_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_subdirectory(3rdparty)
|
||||
add_subdirectory(ai)
|
||||
add_subdirectory(blitter)
|
||||
@@ -11,11 +19,8 @@ add_subdirectory(network)
|
||||
add_subdirectory(os)
|
||||
add_subdirectory(pathfinder)
|
||||
add_subdirectory(saveload)
|
||||
add_subdirectory(script)
|
||||
add_subdirectory(settingsgen)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(spriteloader)
|
||||
add_subdirectory(strgen)
|
||||
add_subdirectory(table)
|
||||
add_subdirectory(video)
|
||||
add_subdirectory(widgets)
|
||||
|
||||
@@ -55,15 +55,15 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
|
||||
}
|
||||
|
||||
fetch_metadata("shortname");
|
||||
for (uint i = 0; item->value.value()[i] != '\0' && i < 4; i++) {
|
||||
this->shortname |= ((uint8)item->value.value()[i]) << (i * 8);
|
||||
for (uint i = 0; (*item->value)[i] != '\0' && i < 4; i++) {
|
||||
this->shortname |= ((uint8)(*item->value)[i]) << (i * 8);
|
||||
}
|
||||
|
||||
fetch_metadata("version");
|
||||
this->version = atoi(item->value->c_str());
|
||||
|
||||
item = metadata->GetItem("fallback", false);
|
||||
this->fallback = (item != nullptr && item->value && item->value.value() != "0" && item->value.value() != "false");
|
||||
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
|
||||
|
||||
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
|
||||
IniGroup *files = ini->GetGroup("files");
|
||||
|
||||
@@ -442,8 +442,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
||||
/* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */
|
||||
if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue;
|
||||
/* bridge is accepted, add to list */
|
||||
/*C++17: BuildBridgeData &item = */ bl->emplace_back();
|
||||
BuildBridgeData &item = bl->back();
|
||||
BuildBridgeData &item = bl->emplace_back();
|
||||
item.index = brd_type;
|
||||
item.spec = GetBridgeSpec(brd_type);
|
||||
/* Add to terraforming & bulldozing costs the cost of the
|
||||
|
||||
@@ -142,8 +142,7 @@ struct SmallMap : std::vector<std::pair<T, U> > {
|
||||
for (uint i = 0; i < std::vector<Pair>::size(); i++) {
|
||||
if (key == std::vector<Pair>::operator[](i).first) return std::vector<Pair>::operator[](i).second;
|
||||
}
|
||||
/*C++17: Pair &n = */ std::vector<Pair>::emplace_back();
|
||||
Pair &n = std::vector<Pair>::back();
|
||||
Pair &n = std::vector<Pair>::emplace_back();
|
||||
n.first = key;
|
||||
return n.second;
|
||||
}
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
* | | | | | | | */
|
||||
/** The original currency specifications. */
|
||||
static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
||||
{ 1, "", CF_NOEURO, "\xC2\xA3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound
|
||||
{ 1, "", CF_NOEURO, u8"\u00a3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound
|
||||
{ 2, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_USD }, ///< american dollar
|
||||
{ 2, "", CF_ISEURO, "\xE2\x82\xAC", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro
|
||||
{ 220, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen
|
||||
{ 2, "", CF_ISEURO, u8"\u20ac", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro
|
||||
{ 220, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen
|
||||
{ 27, "", 2002, "", NBSP "S.", 1, STR_GAME_OPTIONS_CURRENCY_ATS }, ///< austrian schilling
|
||||
{ 81, "", 2002, "BEF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BEF }, ///< belgian franc
|
||||
{ 2, "", CF_NOEURO, "CHF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_CHF }, ///< swiss franc
|
||||
{ 41, "", CF_NOEURO, "", NBSP "K\xC4\x8D", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna
|
||||
{ 41, "", CF_NOEURO, "", NBSP u8"K\u010d", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna
|
||||
{ 4, "", 2002, "DM" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_DEM }, ///< deutsche mark
|
||||
{ 11, "", CF_NOEURO, "", NBSP "kr", 1, STR_GAME_OPTIONS_CURRENCY_DKK }, ///< danish krone
|
||||
{ 333, "", 2002, "Pts" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ESP }, ///< spanish peseta
|
||||
@@ -45,7 +45,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
||||
{ 3873, "", 2002, "", NBSP "L.", 1, STR_GAME_OPTIONS_CURRENCY_ITL }, ///< italian lira
|
||||
{ 4, "", 2002, "NLG" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NLG }, ///< dutch gulden
|
||||
{ 12, "", CF_NOEURO, "", NBSP "Kr", 1, STR_GAME_OPTIONS_CURRENCY_NOK }, ///< norwegian krone
|
||||
{ 6, "", CF_NOEURO, "", NBSP "z\xC5\x82", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty
|
||||
{ 6, "", CF_NOEURO, "", NBSP u8"z\u0142", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty
|
||||
{ 5, "", CF_NOEURO, "", NBSP "Lei", 1, STR_GAME_OPTIONS_CURRENCY_RON }, ///< romanian leu
|
||||
{ 50, "", CF_NOEURO, "", NBSP "p", 1, STR_GAME_OPTIONS_CURRENCY_RUR }, ///< russian rouble
|
||||
{ 479, "", 2007, "", NBSP "SIT", 1, STR_GAME_OPTIONS_CURRENCY_SIT }, ///< slovenian tolar
|
||||
@@ -55,7 +55,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
||||
{ 4, "", CF_NOEURO, "R$" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BRL }, ///< brazil real
|
||||
{ 31, "", 2011, "", NBSP "EEK", 1, STR_GAME_OPTIONS_CURRENCY_EEK }, ///< estonian krooni
|
||||
{ 4, "", 2015, "", NBSP "Lt", 1, STR_GAME_OPTIONS_CURRENCY_LTL }, ///< lithuanian litas
|
||||
{ 1850, "", CF_NOEURO, "\xE2\x82\xA9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won
|
||||
{ 1850, "", CF_NOEURO, u8"\u20a9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won
|
||||
{ 13, "", CF_NOEURO, "R" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ZAR }, ///< south african rand
|
||||
{ 1, "", CF_NOEURO, "", "", 2, STR_GAME_OPTIONS_CURRENCY_CUSTOM }, ///< custom currency (add further languages below)
|
||||
{ 3, "", CF_NOEURO, "", NBSP "GEL", 1, STR_GAME_OPTIONS_CURRENCY_GEL }, ///< Georgian Lari
|
||||
@@ -63,9 +63,9 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
||||
{ 80, "", CF_NOEURO, "", NBSP "rub", 1, STR_GAME_OPTIONS_CURRENCY_RUB }, ///< New Russian Ruble
|
||||
{ 24, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_MXN }, ///< Mexican peso
|
||||
{ 40, "", CF_NOEURO, "NTD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NTD }, ///< new taiwan dollar
|
||||
{ 8, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi
|
||||
{ 8, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi
|
||||
{ 10, "", CF_NOEURO, "HKD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_HKD }, ///< hong kong dollar
|
||||
{ 90, "", CF_NOEURO, "\xE2\x82\xB9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee
|
||||
{ 90, "", CF_NOEURO, u8"\u20b9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee
|
||||
};
|
||||
|
||||
/** Array of currencies used by the system */
|
||||
|
||||
@@ -496,8 +496,7 @@ void EngineOverrideManager::ResetToDefaultMapping()
|
||||
this->clear();
|
||||
for (VehicleType type = VEH_TRAIN; type <= VEH_AIRCRAFT; type++) {
|
||||
for (uint internal_id = 0; internal_id < _engine_counts[type]; internal_id++) {
|
||||
/*C++17: EngineIDMapping &eid = */ this->emplace_back();
|
||||
EngineIDMapping &eid = this->back();
|
||||
EngineIDMapping &eid = this->emplace_back();
|
||||
eid.type = type;
|
||||
eid.grfid = INVALID_GRFID;
|
||||
eid.internal_id = internal_id;
|
||||
|
||||
@@ -126,8 +126,7 @@ public:
|
||||
*/
|
||||
inline FiosItem *Append()
|
||||
{
|
||||
/*C++17: return &*/ this->files.emplace_back();
|
||||
return &this->files.back();
|
||||
return &this->files.emplace_back();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "safeguards.h"
|
||||
|
||||
static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter.
|
||||
static const int MAX_FONT_SIZE = 72; ///< Maximum font size.
|
||||
|
||||
/** Default heights for the different sizes of fonts. */
|
||||
static const int _default_font_height[FS_END] = {10, 6, 18, 10};
|
||||
@@ -200,6 +199,8 @@ void UpdateFontHeightCache()
|
||||
|
||||
FreeTypeSettings _freetype;
|
||||
|
||||
static const int MAX_FONT_SIZE = 72; ///< Maximum font size.
|
||||
|
||||
static const byte FACE_COLOUR = 1;
|
||||
static const byte SHADOW_COLOUR = 2;
|
||||
|
||||
|
||||
24
src/gfx.cpp
24
src/gfx.cpp
@@ -2090,6 +2090,30 @@ void SetAnimatedMouseCursor(const AnimCursor *table)
|
||||
SwitchAnimatedCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cursor position on mouse movement for relative modes.
|
||||
* @param delta_x How much change in the X position.
|
||||
* @param delta_y How much change in the Y position.
|
||||
*/
|
||||
void CursorVars::UpdateCursorPositionRelative(int delta_x, int delta_y)
|
||||
{
|
||||
if (this->fix_at) {
|
||||
this->delta.x = delta_x;
|
||||
this->delta.y = delta_y;
|
||||
} else {
|
||||
int last_position_x = this->pos.x;
|
||||
int last_position_y = this->pos.y;
|
||||
|
||||
this->pos.x = Clamp(this->pos.x + delta_x, 0, _cur_resolution.width - 1);
|
||||
this->pos.y = Clamp(this->pos.y + delta_y, 0, _cur_resolution.height - 1);
|
||||
|
||||
this->delta.x = last_position_x - this->pos.x;
|
||||
this->delta.y = last_position_y - this->pos.y;
|
||||
|
||||
this->dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cursor position on mouse movement.
|
||||
* @param x New X position.
|
||||
|
||||
@@ -144,6 +144,7 @@ struct CursorVars {
|
||||
/* Drag data */
|
||||
bool vehchain; ///< vehicle chain is dragged
|
||||
|
||||
void UpdateCursorPositionRelative(int delta_x, int delta_y);
|
||||
bool UpdateCursorPosition(int x, int y, bool queued_warp);
|
||||
|
||||
private:
|
||||
@@ -163,7 +164,9 @@ struct DrawPixelInfo {
|
||||
union Colour {
|
||||
uint32 data; ///< Conversion of the channel information to a 32 bit number.
|
||||
struct {
|
||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
uint8 r, g, b, a; ///< colour channels as used in browsers
|
||||
#elif TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
uint8 a, r, g, b; ///< colour channels in BE order
|
||||
#else
|
||||
uint8 b, g, r, a; ///< colour channels in LE order
|
||||
@@ -178,7 +181,9 @@ union Colour {
|
||||
* @param a The channel for the alpha/transparency.
|
||||
*/
|
||||
Colour(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) :
|
||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
r(r), g(g), b(b), a(a)
|
||||
#elif TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
a(a), r(r), g(g), b(b)
|
||||
#else
|
||||
b(b), g(g), r(r), a(a)
|
||||
|
||||
@@ -504,11 +504,11 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path, const char *ful
|
||||
IniItem *item;
|
||||
|
||||
fetch_metadata("palette");
|
||||
this->palette = (item->value.value()[0] == 'D' || item->value.value()[0] == 'd') ? PAL_DOS : PAL_WINDOWS;
|
||||
this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS;
|
||||
|
||||
/* Get optional blitter information. */
|
||||
item = metadata->GetItem("blitter", false);
|
||||
this->blitter = (item != nullptr && item->value.value()[0] == '3') ? BLT_32BPP : BLT_8BPP;
|
||||
this->blitter = (item != nullptr && (*item->value)[0] == '3') ? BLT_32BPP : BLT_8BPP;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -473,6 +473,8 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||
InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type, 1);
|
||||
InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
|
||||
InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type);
|
||||
InvalidateWindowClassesData(WC_VEHICLE_VIEW);
|
||||
InvalidateWindowClassesData(WC_VEHICLE_DETAILS);
|
||||
InvalidateWindowData(WC_TEMPLATEGUI_MAIN, 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -609,6 +611,8 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
||||
InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
|
||||
InvalidateWindowData(WC_VEHICLE_VIEW, v->index);
|
||||
InvalidateWindowData(WC_VEHICLE_DETAILS, v->index);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
|
||||
@@ -2633,8 +2633,7 @@ struct IndustryCargoesWindow : public Window {
|
||||
_displayed_industries.set(it);
|
||||
|
||||
this->fields.clear();
|
||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
||||
CargoesRow &row = this->fields.back();
|
||||
CargoesRow &row = this->fields.emplace_back();
|
||||
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
||||
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
||||
row.columns[2].MakeEmpty(CFT_SMALL_EMPTY);
|
||||
@@ -2649,8 +2648,7 @@ struct IndustryCargoesWindow : public Window {
|
||||
int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept;
|
||||
int num_indrows = max(3, max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels.
|
||||
for (int i = 0; i < num_indrows; i++) {
|
||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
||||
CargoesRow &row = this->fields.back();
|
||||
CargoesRow &row = this->fields.emplace_back();
|
||||
row.columns[0].MakeEmpty(CFT_EMPTY);
|
||||
row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo));
|
||||
row.columns[2].MakeEmpty(CFT_EMPTY);
|
||||
@@ -2713,8 +2711,7 @@ struct IndustryCargoesWindow : public Window {
|
||||
_displayed_industries.reset();
|
||||
|
||||
this->fields.clear();
|
||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
||||
CargoesRow &row = this->fields.back();
|
||||
CargoesRow &row = this->fields.emplace_back();
|
||||
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
||||
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
||||
row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS);
|
||||
@@ -2727,8 +2724,7 @@ struct IndustryCargoesWindow : public Window {
|
||||
int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept;
|
||||
int num_indrows = max(num_supp, num_cust);
|
||||
for (int i = 0; i < num_indrows; i++) {
|
||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
||||
CargoesRow &row = this->fields.back();
|
||||
CargoesRow &row = this->fields.emplace_back();
|
||||
row.columns[0].MakeEmpty(CFT_EMPTY);
|
||||
row.columns[1].MakeCargo(&cid, 1);
|
||||
row.columns[2].MakeEmpty(CFT_EMPTY);
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include "string_func.h"
|
||||
#include "fileio_func.h"
|
||||
#include <fstream>
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500)
|
||||
# include <unistd.h>
|
||||
@@ -115,6 +118,10 @@ bool IniFile::SaveToDisk(const char *filename)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "fileio_type.h"
|
||||
#include <string>
|
||||
#include "3rdparty/optional/ottd_optional.h"
|
||||
#include <optional>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -27,7 +27,7 @@ enum IniGroupType {
|
||||
struct IniItem {
|
||||
IniItem *next; ///< The next item in this group
|
||||
std::string name; ///< The name of this item
|
||||
opt::optional<std::string> value; ///< The value of this item
|
||||
std::optional<std::string> value; ///< The value of this item
|
||||
std::string comment; ///< The comment associated with this item
|
||||
|
||||
IniItem(struct IniGroup *parent, const std::string &name);
|
||||
|
||||
@@ -5825,10 +5825,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sugar Mine
|
||||
##id 0x6000
|
||||
STR_SV_EMPTY :
|
||||
STR_SV_UNNAMED :Unnamed
|
||||
STR_SV_TRAIN_NAME :Train {COMMA}
|
||||
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle {COMMA}
|
||||
STR_SV_SHIP_NAME :Ship {COMMA}
|
||||
STR_SV_AIRCRAFT_NAME :Aircraft {COMMA}
|
||||
STR_SV_TRAIN_NAME :Train #{COMMA}
|
||||
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle #{COMMA}
|
||||
STR_SV_SHIP_NAME :Ship #{COMMA}
|
||||
STR_SV_AIRCRAFT_NAME :Aircraft #{COMMA}
|
||||
|
||||
STR_SV_STNAME :{STRING1}
|
||||
STR_SV_STNAME_NORTH :{STRING1} North
|
||||
@@ -6135,6 +6135,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Buoy
|
||||
STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA}
|
||||
STR_FORMAT_COMPANY_NUM :(Company {COMMA})
|
||||
STR_FORMAT_GROUP_NAME :Group {COMMA}
|
||||
STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA}
|
||||
STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING}
|
||||
STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint
|
||||
STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA}
|
||||
|
||||
134
src/misc_gui.cpp
134
src/misc_gui.cpp
@@ -450,73 +450,73 @@ static WindowDesc _about_desc(
|
||||
);
|
||||
|
||||
static const char * const _credits[] = {
|
||||
"Original design by Chris Sawyer",
|
||||
"Original graphics by Simon Foster",
|
||||
"",
|
||||
"The OpenTTD team (in alphabetical order):",
|
||||
" Grzegorz Duczy\xC5\x84ski (adf88) - General coding (since 1.7.2)",
|
||||
" Albert Hofkamp (Alberth) - GUI expert (since 0.7)",
|
||||
" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
|
||||
" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)",
|
||||
" Christoph Elsenhans (frosch) - General coding (since 0.6)",
|
||||
" Lo\xC3\xAF""c Guilloux (glx) - General / Windows Expert (since 0.4.5)",
|
||||
" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
|
||||
" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
|
||||
" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
|
||||
" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
|
||||
" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
|
||||
" Ingo von Borstel (planetmaker) - General, Support (since 1.1)",
|
||||
" Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)",
|
||||
" Jos\xC3\xA9 Soler (Terkhen) - General coding (since 1.0)",
|
||||
" Leif Linse (Zuu) - AI/Game Script (since 1.2)",
|
||||
"",
|
||||
"Inactive Developers:",
|
||||
" Jean-Fran\xC3\xA7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
|
||||
" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
|
||||
" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
|
||||
" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
|
||||
" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
|
||||
" Attila B\xC3\xA1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
|
||||
" Zden\xC4\x9Bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
|
||||
" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
|
||||
" Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)",
|
||||
" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
|
||||
"",
|
||||
"Retired Developers:",
|
||||
" Tam\xC3\xA1s Farag\xC3\xB3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
|
||||
" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
|
||||
" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
|
||||
" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
|
||||
" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
|
||||
" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
|
||||
" Petr Baudi\xC5\xA1 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
|
||||
" Benedikt Br\xC3\xBCggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
|
||||
" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
|
||||
"",
|
||||
"Special thanks go out to:",
|
||||
" Josef Drexler - For his great work on TTDPatch",
|
||||
" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
|
||||
" Stefan Mei\xC3\x9Fner (sign_de) - For his work on the console",
|
||||
" Mike Ragsdale - OpenTTD installer",
|
||||
" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
|
||||
" Richard Kempton (richK) - additional airports, initial TGP implementation",
|
||||
"",
|
||||
" Alberto Demichelis - Squirrel scripting language \xC2\xA9 2003-2008",
|
||||
" L. Peter Deutsch - MD5 implementation \xC2\xA9 1999, 2000, 2002",
|
||||
" Michael Blunck - Pre-signals and semaphores \xC2\xA9 2003",
|
||||
" George - Canal/Lock graphics \xC2\xA9 2003-2004",
|
||||
" Andrew Parkhouse (andythenorth) - River graphics",
|
||||
" David Dallaston (Pikka) - Tram tracks",
|
||||
" All Translators - Who made OpenTTD a truly international game",
|
||||
" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
|
||||
"",
|
||||
"",
|
||||
"Developer of this patchpack:",
|
||||
" Jonathan G. Rennison (JGR)",
|
||||
"",
|
||||
"",
|
||||
"And last but not least:",
|
||||
" Chris Sawyer - For an amazing game!"
|
||||
u8"Original design by Chris Sawyer",
|
||||
u8"Original graphics by Simon Foster",
|
||||
u8"",
|
||||
u8"The OpenTTD team (in alphabetical order):",
|
||||
u8" Grzegorz Duczy\u0144ski (adf88) - General coding (since 1.7.2)",
|
||||
u8" Albert Hofkamp (Alberth) - GUI expert (since 0.7)",
|
||||
u8" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
|
||||
u8" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)",
|
||||
u8" Christoph Elsenhans (frosch) - General coding (since 0.6)",
|
||||
u8" Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)",
|
||||
u8" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
|
||||
u8" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
|
||||
u8" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
|
||||
u8" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
|
||||
u8" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
|
||||
u8" Ingo von Borstel (planetmaker) - General, Support (since 1.1)",
|
||||
u8" Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)",
|
||||
u8" Jos\u00e9 Soler (Terkhen) - General coding (since 1.0)",
|
||||
u8" Leif Linse (Zuu) - AI/Game Script (since 1.2)",
|
||||
u8"",
|
||||
u8"Inactive Developers:",
|
||||
u8" Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
|
||||
u8" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
|
||||
u8" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
|
||||
u8" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
|
||||
u8" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
|
||||
u8" Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
|
||||
u8" Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
|
||||
u8" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
|
||||
u8" Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)",
|
||||
u8" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
|
||||
u8"",
|
||||
u8"Retired Developers:",
|
||||
u8" Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
|
||||
u8" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
|
||||
u8" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
|
||||
u8" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
|
||||
u8" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
|
||||
u8" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
|
||||
u8" Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
|
||||
u8" Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
|
||||
u8" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
|
||||
u8"",
|
||||
u8"Special thanks go out to:",
|
||||
u8" Josef Drexler - For his great work on TTDPatch",
|
||||
u8" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
|
||||
u8" Stefan Mei\u00dfner (sign_de) - For his work on the console",
|
||||
u8" Mike Ragsdale - OpenTTD installer",
|
||||
u8" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
|
||||
u8" Richard Kempton (richK) - additional airports, initial TGP implementation",
|
||||
u8"",
|
||||
u8" Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008",
|
||||
u8" L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002",
|
||||
u8" Michael Blunck - Pre-signals and semaphores \u00a9 2003",
|
||||
u8" George - Canal/Lock graphics \u00a9 2003-2004",
|
||||
u8" Andrew Parkhouse (andythenorth) - River graphics",
|
||||
u8" David Dallaston (Pikka) - Tram tracks",
|
||||
u8" All Translators - Who made OpenTTD a truly international game",
|
||||
u8" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
|
||||
u8"",
|
||||
u8"",
|
||||
u8"Developer of this patchpack:",
|
||||
u8" Jonathan G. Rennison (JGR)",
|
||||
u8"",
|
||||
u8"",
|
||||
u8"And last but not least:",
|
||||
u8" Chris Sawyer - For an amazing game!"
|
||||
};
|
||||
|
||||
struct AboutWindow : public Window {
|
||||
|
||||
@@ -265,6 +265,18 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
|
||||
this->address_length = (int)runp->ai_addrlen;
|
||||
assert(sizeof(this->address) >= runp->ai_addrlen);
|
||||
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Emscripten doesn't zero sin_zero, but as we compare addresses
|
||||
* to see if they are the same address, we need them to be zero'd.
|
||||
* Emscripten is, as far as we know, the only OS not doing this.
|
||||
*
|
||||
* https://github.com/emscripten-core/emscripten/issues/12998
|
||||
*/
|
||||
if (this->address.ss_family == AF_INET) {
|
||||
sockaddr_in *address_ipv4 = (sockaddr_in *)&this->address;
|
||||
memset(address_ipv4->sin_zero, 0, sizeof(address_ipv4->sin_zero));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -297,7 +309,15 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
|
||||
|
||||
if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type);
|
||||
|
||||
if (connect(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
|
||||
int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Emscripten is asynchronous, and as such a connect() is still in
|
||||
* progress by the time the call returns. */
|
||||
if (err != 0 && errno != EINPROGRESS)
|
||||
#else
|
||||
if (err != 0)
|
||||
#endif
|
||||
{
|
||||
DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno));
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
|
||||
@@ -99,6 +99,16 @@ typedef unsigned long in_addr_t;
|
||||
# include <errno.h>
|
||||
# include <sys/time.h>
|
||||
# include <netdb.h>
|
||||
|
||||
# if defined(__EMSCRIPTEN__)
|
||||
/* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */
|
||||
# undef AI_ADDRCONFIG
|
||||
# define AI_ADDRCONFIG 0
|
||||
/* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64.
|
||||
* https://github.com/emscripten-core/emscripten/issues/1711 */
|
||||
# undef FD_SETSIZE
|
||||
# define FD_SETSIZE 64
|
||||
# endif
|
||||
#endif /* UNIX */
|
||||
|
||||
/* OS/2 stuff */
|
||||
@@ -160,6 +170,28 @@ typedef unsigned long in_addr_t;
|
||||
|
||||
#endif /* OS/2 */
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/**
|
||||
* Emscripten doesn't set 'addrlen' for accept(), getsockname(), getpeername()
|
||||
* and recvfrom(), which confuses other functions and causes them to crash.
|
||||
* This function needs to be called after these four functions to make sure
|
||||
* 'addrlen' is patched up.
|
||||
*
|
||||
* https://github.com/emscripten-core/emscripten/issues/12996
|
||||
*
|
||||
* @param address The address returned by those four functions.
|
||||
* @return The correct value for addrlen.
|
||||
*/
|
||||
static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address)
|
||||
{
|
||||
switch (address.ss_family) {
|
||||
case AF_INET6: return sizeof(struct sockaddr_in6);
|
||||
case AF_INET: return sizeof(struct sockaddr_in);
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Try to set the socket into non-blocking mode.
|
||||
* @param d The socket to set the non-blocking more for.
|
||||
@@ -167,12 +199,16 @@ typedef unsigned long in_addr_t;
|
||||
*/
|
||||
static inline bool SetNonBlocking(SOCKET d)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u_long nonblocking = 1;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return true;
|
||||
#else
|
||||
# ifdef _WIN32
|
||||
u_long nonblocking = 1;
|
||||
# else
|
||||
int nonblocking = 1;
|
||||
#endif
|
||||
# endif
|
||||
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,10 +233,14 @@ static inline bool SetBlocking(SOCKET d)
|
||||
*/
|
||||
static inline bool SetNoDelay(SOCKET d)
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return true;
|
||||
#else
|
||||
/* XXX should this be done at all? */
|
||||
int b = 1;
|
||||
/* The (const char*) cast is needed for windows */
|
||||
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ public:
|
||||
socklen_t sin_len = sizeof(sin);
|
||||
SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
|
||||
if (s == INVALID_SOCKET) return;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
sin_len = FixAddrLenForEmscripten(sin);
|
||||
#endif
|
||||
|
||||
SetNonBlocking(s); // XXX error handling?
|
||||
|
||||
|
||||
@@ -164,6 +164,9 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
||||
/* Did we get the bytes for the base header of the packet? */
|
||||
if (nbytes <= 0) break; // No data, i.e. no packet
|
||||
if (nbytes <= 2) continue; // Invalid data; try next packet
|
||||
#ifdef __EMSCRIPTEN__
|
||||
client_len = FixAddrLenForEmscripten(client_addr);
|
||||
#endif
|
||||
|
||||
NetworkAddress address(client_addr, client_len);
|
||||
p.PrepareToRead();
|
||||
|
||||
@@ -1122,3 +1122,14 @@ bool IsNetworkCompatibleVersion(const char *other, bool extended)
|
||||
{
|
||||
return strncmp(_openttd_revision, other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
extern "C" {
|
||||
|
||||
void CDECL em_openttd_add_server(const char *host, int port)
|
||||
{
|
||||
NetworkUDPQueryServer(NetworkAddress(host, port), true);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern bool HasScenario(const ContentInfo *ci, bool md5sum);
|
||||
@@ -296,6 +300,13 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContent(uint &files, uin
|
||||
{
|
||||
bytes = 0;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Emscripten is loaded via an HTTPS connection. As such, it is very
|
||||
* difficult to make HTTP connections. So always use the TCP method of
|
||||
* downloading content. */
|
||||
fallback = true;
|
||||
#endif
|
||||
|
||||
ContentIDList content;
|
||||
for (const ContentInfo *ci : this->infos) {
|
||||
if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue;
|
||||
@@ -542,6 +553,10 @@ void ClientNetworkContentSocketHandler::AfterDownload()
|
||||
unlink(GetFullFilename(this->curInfo, false));
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||
#endif
|
||||
|
||||
this->OnDownloadComplete(this->curInfo->id);
|
||||
} else {
|
||||
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR);
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
#endif
|
||||
|
||||
static void ShowNetworkStartServerWindow();
|
||||
static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
|
||||
@@ -490,6 +493,14 @@ public:
|
||||
this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
|
||||
this->SetFocusedWidget(WID_NG_FILTER);
|
||||
|
||||
/* As the master-server doesn't support "websocket" servers yet, we
|
||||
* let "os/emscripten/pre.js" hardcode a list of servers people can
|
||||
* join. This means the serverlist is curated for now, but it is the
|
||||
* best we can offer. */
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
|
||||
#endif
|
||||
|
||||
this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
|
||||
this->server = this->last_joined;
|
||||
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
|
||||
@@ -630,6 +641,12 @@ public:
|
||||
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr);
|
||||
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr || !sel->info.version_compatible || sel->info.compatible);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
this->SetWidgetDisabledState(WID_NG_FIND, true);
|
||||
this->SetWidgetDisabledState(WID_NG_ADD, true);
|
||||
this->SetWidgetDisabledState(WID_NG_START, true);
|
||||
#endif
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
||||
|
||||
@@ -1951,8 +1951,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons
|
||||
tmp_layout.clear();
|
||||
for (;;) {
|
||||
/* no relative bounding box support */
|
||||
/*C++17: DrawTileSeqStruct &dtss = */ tmp_layout.emplace_back();
|
||||
DrawTileSeqStruct &dtss = tmp_layout.back();
|
||||
DrawTileSeqStruct &dtss = tmp_layout.emplace_back();
|
||||
MemSetT(&dtss, 0);
|
||||
|
||||
dtss.delta_x = buf->ReadByte();
|
||||
@@ -5159,8 +5158,7 @@ static void NewSpriteGroup(ByteReader *buf)
|
||||
/* Loop through the var adjusts. Unfortunately we don't know how many we have
|
||||
* from the outset, so we shall have to keep reallocing. */
|
||||
do {
|
||||
/*C++17: DeterministicSpriteGroupAdjust &adjust = */ adjusts.emplace_back();
|
||||
DeterministicSpriteGroupAdjust &adjust = adjusts.back();
|
||||
DeterministicSpriteGroupAdjust &adjust = adjusts.emplace_back();
|
||||
|
||||
/* The first var adjust doesn't have an operation specified, so we set it to add. */
|
||||
adjust.operation = adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte();
|
||||
|
||||
@@ -664,8 +664,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun
|
||||
|
||||
/* Create a copy of the spritelayout, so we can modify some values.
|
||||
* Also include the groundsprite into the sequence for easier processing. */
|
||||
/*C++17: DrawTileSeqStruct *result = &*/ result_seq.emplace_back();
|
||||
DrawTileSeqStruct *result = &result_seq.back();
|
||||
DrawTileSeqStruct *result = &result_seq.emplace_back();
|
||||
result->image = ground;
|
||||
result->delta_x = 0;
|
||||
result->delta_y = 0;
|
||||
@@ -675,8 +674,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun
|
||||
foreach_draw_tile_seq(dtss, this->seq) {
|
||||
result_seq.push_back(*dtss);
|
||||
}
|
||||
result_seq.emplace_back() /*C++17: .MakeTerminator()*/;
|
||||
result_seq.back().MakeTerminator();
|
||||
result_seq.emplace_back().MakeTerminator();
|
||||
/* Determine the var10 values the action-1-2-3 chains needs to be resolved for,
|
||||
* and apply the default sprite offsets (unless disabled). */
|
||||
const TileLayoutRegisters *regs = this->registers;
|
||||
|
||||
@@ -87,6 +87,11 @@
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
# include <emscripten/html5.h>
|
||||
#endif
|
||||
|
||||
void CallLandscapeTick();
|
||||
void IncreaseDate();
|
||||
void MusicLoop();
|
||||
@@ -123,6 +128,15 @@ void CDECL usererror(const char *s, ...)
|
||||
ShowOSErrorBox(buf, false);
|
||||
if (VideoDriver::GetInstance() != nullptr) VideoDriver::GetInstance()->Stop();
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_exit_pointerlock();
|
||||
/* In effect, the game ends here. As emscripten_set_main_loop() caused
|
||||
* the stack to be unwound, the code after MainLoop() in
|
||||
* openttd_main() is never executed. */
|
||||
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||
EM_ASM(if (window["openttd_abort"]) openttd_abort());
|
||||
#endif
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -3293,8 +3293,7 @@ bool AfterLoadGame()
|
||||
cur_skip = prev_tile_skip;
|
||||
}
|
||||
|
||||
/*C++17: uint &this_skip = */ skip_frames.push_back(prev_tile_skip);
|
||||
uint &this_skip = skip_frames.back();
|
||||
uint &this_skip = skip_frames.emplace_back(prev_tile_skip);
|
||||
|
||||
/* The following 3 curves now take longer than before */
|
||||
switch (u->state) {
|
||||
|
||||
@@ -191,8 +191,7 @@ static void Load_EIDS()
|
||||
_engine_mngr.clear();
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
/*C++17: EngineIDMapping *eid = &*/ _engine_mngr.emplace_back();
|
||||
EngineIDMapping *eid = &_engine_mngr.back();
|
||||
EngineIDMapping *eid = &_engine_mngr.emplace_back();
|
||||
SlObject(eid, _engine_id_mapping_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#include "../scope.h"
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "../tbtr_template_vehicle.h"
|
||||
|
||||
@@ -2928,6 +2931,10 @@ static void SaveFileDone()
|
||||
|
||||
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
|
||||
_sl.saveinprogress = false;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friends) */
|
||||
|
||||
@@ -192,8 +192,7 @@ static void Load_WAYP()
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
/*C++17: OldWaypoint *wp = &*/ _old_waypoints.emplace_back();
|
||||
OldWaypoint *wp = &_old_waypoints.back();
|
||||
OldWaypoint *wp = &_old_waypoints.emplace_back();
|
||||
|
||||
wp->index = index;
|
||||
SlObject(wp, _old_waypoint_desc);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
add_subdirectory(api)
|
||||
|
||||
if(OPTION_TOOLS_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_files(
|
||||
script_config.cpp
|
||||
script_config.hpp
|
||||
|
||||
@@ -131,6 +131,10 @@ foreach(API "ai;AI" "game;GS" "template;Template")
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(OPTION_TOOLS_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_library(openttd::script_api ALIAS script_api)
|
||||
|
||||
|
||||
|
||||
@@ -118,8 +118,7 @@ public:
|
||||
text += stored_size;
|
||||
}
|
||||
while (length > 0) {
|
||||
/*C++17: OutputBuffer &block =*/ this->output_buffer.emplace_back();
|
||||
OutputBuffer &block = this->output_buffer.back();
|
||||
OutputBuffer &block = this->output_buffer.emplace_back();
|
||||
block.Clear(); // Initialize the new block.
|
||||
size_t stored_size = block.Add(text, length);
|
||||
length -= stored_size;
|
||||
|
||||
@@ -22,6 +22,10 @@ if (NOT HOST_BINARY_DIR)
|
||||
add_dependencies(tools strgen)
|
||||
endif()
|
||||
|
||||
if(OPTION_TOOLS_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Source Files
|
||||
add_files(strgen_base.cpp)
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#include <string>
|
||||
|
||||
/** A non-breaking space. */
|
||||
#define NBSP "\xC2\xA0"
|
||||
#define NBSP u8"\u00a0"
|
||||
|
||||
/** A left-to-right marker, marks the next character as left-to-right. */
|
||||
#define LRM "\xE2\x80\x8E"
|
||||
#define LRM u8"\u200e"
|
||||
|
||||
/**
|
||||
* Valid filter types for IsValidChar.
|
||||
|
||||
@@ -74,8 +74,7 @@ void StringFilter::SetFilterTerm(const char *str)
|
||||
|
||||
/* Add to word */
|
||||
if (word == nullptr) {
|
||||
/*C++17: word = &*/ this->word_index.push_back({dest, false});
|
||||
word = &this->word_index.back();
|
||||
word = &this->word_index.emplace_back(WordState{ dest, false });
|
||||
}
|
||||
|
||||
memcpy(dest, pos, len);
|
||||
|
||||
@@ -1758,6 +1758,11 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg
|
||||
int64 args_array[] = {(int64)(size_t)v->name.c_str()};
|
||||
StringParameters tmp_params(args_array);
|
||||
buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
|
||||
} else if (v->group_id != DEFAULT_GROUP) {
|
||||
/* The vehicle has no name, but is member of a group, so print group name */
|
||||
int64 args_array[] = {v->group_id, v->unitnumber};
|
||||
StringParameters tmp_params(args_array);
|
||||
buff = GetStringWithArgs(buff, STR_FORMAT_GROUP_VEHICLE_NAME, &tmp_params, last);
|
||||
} else {
|
||||
int64 args_array[] = {v->unitnumber};
|
||||
StringParameters tmp_params(args_array);
|
||||
|
||||
1150
src/table/townname.h
1150
src/table/townname.h
File diff suppressed because it is too large
Load Diff
@@ -359,7 +359,7 @@ static void Xunzip(byte **bufp, size_t *sizep)
|
||||
}
|
||||
|
||||
/* Check for the byte-order-mark, and skip it if needed. */
|
||||
char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0);
|
||||
char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0);
|
||||
|
||||
/* Make sure the string is a valid UTF-8 sequence. */
|
||||
str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
||||
|
||||
@@ -505,7 +505,7 @@ static char *MakeFinnishTownName(char *buf, const char *last, uint32 seed)
|
||||
strstr(orig, "A") != nullptr || strstr(orig, "O") != nullptr || strstr(orig, "U") != nullptr) {
|
||||
buf = strecpy(buf, "la", last);
|
||||
} else {
|
||||
buf = strecpy(buf, "l\xC3\xA4", last);
|
||||
buf = strecpy(buf, u8"l\u00e4", last);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -1013,8 +1013,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
||||
* Do this for all tiles (like trees), not only objects. */
|
||||
ClearedObjectArea *coa = FindClearedObject(end_tile);
|
||||
if (coa == nullptr) {
|
||||
/*C++17: coa = &*/ _cleared_object_areas.push_back({end_tile, TileArea(end_tile, 1, 1)});
|
||||
coa = &_cleared_object_areas.back();
|
||||
coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ end_tile, TileArea(end_tile, 1, 1) });
|
||||
}
|
||||
|
||||
/* Hide the tile from the terraforming command */
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include "../3rdparty/mingw-std-threads/mingw.mutex.h"
|
||||
#include "../3rdparty/mingw-std-threads/mingw.condition_variable.h"
|
||||
#endif
|
||||
#ifdef __EMSCRIPTEN__
|
||||
# include <emscripten.h>
|
||||
# include <emscripten/html5.h>
|
||||
#endif
|
||||
|
||||
#if defined(WITH_FCITX)
|
||||
#include <fcitx/frontend.h>
|
||||
@@ -61,6 +65,11 @@ static volatile bool _draw_continue;
|
||||
static Palette _local_palette;
|
||||
static SDL_Palette *_sdl_palette;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/** Whether we just had a window-enter event. */
|
||||
static bool _cursor_new_in_window = false;
|
||||
#endif
|
||||
|
||||
#define MAX_DIRTY_RECTS 100
|
||||
static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
|
||||
static int _num_dirty_rects;
|
||||
@@ -578,6 +587,9 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
|
||||
bool VideoDriver_SDL::ClaimMousePointer()
|
||||
{
|
||||
SDL_ShowCursor(0);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -796,9 +808,27 @@ int VideoDriver_SDL::PollEvent()
|
||||
|
||||
switch (ev.type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if (_cursor_new_in_window) {
|
||||
/* The cursor just moved into the window; this means we don't
|
||||
* know the absolutely position yet to move relative from.
|
||||
* Before this time, SDL didn't know it either, and this is
|
||||
* why we postpone it till now. Update the absolute position
|
||||
* for this once, and work relative after. */
|
||||
_cursor.pos.x = ev.motion.x;
|
||||
_cursor.pos.y = ev.motion.y;
|
||||
_cursor.dirty = true;
|
||||
|
||||
_cursor_new_in_window = false;
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
} else {
|
||||
_cursor.UpdateCursorPositionRelative(ev.motion.xrel, ev.motion.yrel);
|
||||
}
|
||||
#else
|
||||
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
|
||||
SDL_WarpMouseInWindow(_sdl_window, _cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
#endif
|
||||
HandleMouseEvents();
|
||||
break;
|
||||
|
||||
@@ -932,6 +962,12 @@ int VideoDriver_SDL::PollEvent()
|
||||
} else if (ev.window.event == SDL_WINDOWEVENT_ENTER) {
|
||||
// mouse entered the window, enable cursor
|
||||
_cursor.in_window = true;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Disable relative mouse mode for the first mouse motion,
|
||||
* so we can pick up the absolutely position again. */
|
||||
_cursor_new_in_window = true;
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
#endif
|
||||
} else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) {
|
||||
// mouse left the window, undraw cursor
|
||||
UndrawMouseCursor();
|
||||
@@ -968,7 +1004,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm)
|
||||
/* Explicitly disable hardware acceleration. Enabling this causes
|
||||
* UpdateWindowSurface() to update the window's texture instead of
|
||||
* its surface. */
|
||||
SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION , "0");
|
||||
SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0");
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
|
||||
|
||||
/* Just on the offchance the audio subsystem started before the video system,
|
||||
* check whether any part of SDL has been initialised before getting here.
|
||||
@@ -1012,19 +1049,114 @@ void VideoDriver_SDL::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDriver_SDL::MainLoop()
|
||||
void VideoDriver_SDL::LoopOnce()
|
||||
{
|
||||
uint32 cur_ticks = SDL_GetTicks();
|
||||
uint32 last_cur_ticks = cur_ticks;
|
||||
uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||
uint32 mod;
|
||||
int numkeys;
|
||||
const Uint8 *keys;
|
||||
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
||||
InteractiveRandom(); // randomness
|
||||
|
||||
while (PollEvent() == -1) {}
|
||||
if (_exit_game) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Emscripten is event-driven, and as such the main loop is inside
|
||||
* the browser. So if _exit_game goes true, the main loop ends (the
|
||||
* cancel call), but we still have to call the cleanup that is
|
||||
* normally done at the end of the main loop for non-Emscripten.
|
||||
* After that, Emscripten just halts, and the HTML shows a nice
|
||||
* "bye, see you next time" message. */
|
||||
emscripten_cancel_main_loop();
|
||||
MainLoopCleanup();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
mod = SDL_GetModState();
|
||||
keys = SDL_GetKeyboardState(&numkeys);
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (_shift_pressed)
|
||||
#else
|
||||
/* Speedup when pressing tab, except when using ALT+TAB
|
||||
* to switch to another application */
|
||||
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
|
||||
#endif /* defined(_DEBUG) */
|
||||
{
|
||||
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
|
||||
} else if (_fast_forward & 2) {
|
||||
_fast_forward = 0;
|
||||
}
|
||||
|
||||
cur_ticks = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) {
|
||||
_realtime_tick += cur_ticks - last_cur_ticks;
|
||||
last_cur_ticks = cur_ticks;
|
||||
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||
|
||||
bool old_ctrl_pressed = _ctrl_pressed;
|
||||
bool old_shift_pressed = _shift_pressed;
|
||||
|
||||
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
|
||||
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
|
||||
|
||||
/* determine which directional keys are down */
|
||||
_dirkeys =
|
||||
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
|
||||
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
|
||||
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
|
||||
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
|
||||
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
|
||||
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
|
||||
|
||||
/* The gameloop is the part that can run asynchronously. The rest
|
||||
* except sleeping can't. */
|
||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
||||
|
||||
GameLoop();
|
||||
|
||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
||||
|
||||
GameLoopPaletteAnimations();
|
||||
|
||||
UpdateWindows();
|
||||
_local_palette = _cur_palette;
|
||||
} else {
|
||||
/* Release the thread while sleeping */
|
||||
if (_draw_mutex != nullptr) {
|
||||
draw_lock.unlock();
|
||||
CSleep(1);
|
||||
draw_lock.lock();
|
||||
} else {
|
||||
/* Emscripten is running an event-based mainloop; there is already some
|
||||
* downtime between each iteration, so no need to sleep. */
|
||||
#ifndef __EMSCRIPTEN__
|
||||
CSleep(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
NetworkDrawChatMessage();
|
||||
DrawMouseCursor();
|
||||
}
|
||||
|
||||
/* End of the critical part. */
|
||||
if (_draw_mutex != nullptr && !HasModalProgress()) {
|
||||
_draw_signal->notify_one();
|
||||
} else {
|
||||
/* Oh, we didn't have threads, then just draw unthreaded */
|
||||
CheckPaletteAnim();
|
||||
DrawSurfaceToScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDriver_SDL::MainLoop()
|
||||
{
|
||||
cur_ticks = SDL_GetTicks();
|
||||
last_cur_ticks = cur_ticks;
|
||||
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||
|
||||
CheckPaletteAnim();
|
||||
|
||||
std::thread draw_thread;
|
||||
std::unique_lock<std::recursive_mutex> draw_lock;
|
||||
if (_draw_threaded) {
|
||||
/* Initialise the mutex first, because that's the thing we *need*
|
||||
* directly in the newly created thread. */
|
||||
@@ -1055,82 +1187,20 @@ void VideoDriver_SDL::MainLoop()
|
||||
|
||||
DEBUG(driver, 1, "SDL2: using %sthreads", _draw_threaded ? "" : "no ");
|
||||
|
||||
for (;;) {
|
||||
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
||||
InteractiveRandom(); // randomness
|
||||
|
||||
while (PollEvent() == -1) {}
|
||||
if (_exit_game) break;
|
||||
|
||||
mod = SDL_GetModState();
|
||||
keys = SDL_GetKeyboardState(&numkeys);
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (_shift_pressed)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Run the main loop event-driven, based on RequestAnimationFrame. */
|
||||
emscripten_set_main_loop_arg(&this->EmscriptenLoop, this, 0, 1);
|
||||
#else
|
||||
/* Speedup when pressing tab, except when using ALT+TAB
|
||||
* to switch to another application */
|
||||
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
|
||||
#endif /* defined(_DEBUG) */
|
||||
{
|
||||
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
|
||||
} else if (_fast_forward & 2) {
|
||||
_fast_forward = 0;
|
||||
}
|
||||
|
||||
cur_ticks = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) {
|
||||
_realtime_tick += cur_ticks - last_cur_ticks;
|
||||
last_cur_ticks = cur_ticks;
|
||||
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||
|
||||
bool old_ctrl_pressed = _ctrl_pressed;
|
||||
bool old_shift_pressed = _shift_pressed;
|
||||
|
||||
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
|
||||
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
|
||||
|
||||
/* determine which directional keys are down */
|
||||
_dirkeys =
|
||||
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
|
||||
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
|
||||
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
|
||||
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
|
||||
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
|
||||
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
|
||||
|
||||
/* The gameloop is the part that can run asynchronously. The rest
|
||||
* except sleeping can't. */
|
||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
||||
|
||||
GameLoop();
|
||||
|
||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
||||
|
||||
GameLoopPaletteAnimations();
|
||||
|
||||
UpdateWindows();
|
||||
_local_palette = _cur_palette;
|
||||
} else {
|
||||
/* Release the thread while sleeping */
|
||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
||||
CSleep(1);
|
||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
||||
|
||||
NetworkDrawChatMessage();
|
||||
DrawMouseCursor();
|
||||
}
|
||||
|
||||
/* End of the critical part. */
|
||||
if (_draw_mutex != nullptr && !HasModalProgress()) {
|
||||
_draw_signal->notify_one();
|
||||
} else {
|
||||
/* Oh, we didn't have threads, then just draw unthreaded */
|
||||
CheckPaletteAnim();
|
||||
DrawSurfaceToScreen();
|
||||
}
|
||||
while (!_exit_game) {
|
||||
LoopOnce();
|
||||
}
|
||||
|
||||
MainLoopCleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void VideoDriver_SDL::MainLoopCleanup()
|
||||
{
|
||||
if (_draw_mutex != nullptr) {
|
||||
_draw_continue = false;
|
||||
/* Sending signal if there is no thread blocked
|
||||
@@ -1146,6 +1216,15 @@ void VideoDriver_SDL::MainLoop()
|
||||
_draw_mutex = nullptr;
|
||||
_draw_signal = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_exit_pointerlock();
|
||||
/* In effect, the game ends here. As emscripten_set_main_loop() caused
|
||||
* the stack to be unwound, the code after MainLoop() in
|
||||
* openttd_main() is never executed. */
|
||||
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||
EM_ASM(if (window["openttd_exit"]) openttd_exit());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VideoDriver_SDL::ChangeResolution(int w, int h)
|
||||
|
||||
@@ -42,12 +42,26 @@ public:
|
||||
const char *GetName() const override { return "sdl"; }
|
||||
private:
|
||||
int PollEvent();
|
||||
void LoopOnce();
|
||||
void MainLoopCleanup();
|
||||
bool CreateMainSurface(uint w, uint h, bool resize);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Convert a constant pointer back to a non-constant pointer to a member function. */
|
||||
static void EmscriptenLoop(void *self) { ((VideoDriver_SDL *)self)->LoopOnce(); }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled.
|
||||
*/
|
||||
bool edit_box_focused;
|
||||
|
||||
uint32 cur_ticks;
|
||||
uint32 last_cur_ticks;
|
||||
uint32 next_tick;
|
||||
|
||||
std::thread draw_thread;
|
||||
std::unique_lock<std::recursive_mutex> draw_lock;
|
||||
};
|
||||
|
||||
/** Factory for the SDL video driver. */
|
||||
|
||||
@@ -816,8 +816,7 @@ static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y,
|
||||
{
|
||||
assert((image & SPRITE_MASK) < MAX_SPRITES);
|
||||
|
||||
/*C++17: TileSpriteToDraw &ts = */ _vd.tile_sprites_to_draw.emplace_back();
|
||||
TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.back();
|
||||
TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.emplace_back();
|
||||
ts.image = image;
|
||||
ts.pal = pal;
|
||||
ts.sub = sub;
|
||||
@@ -1038,8 +1037,7 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
|
||||
return;
|
||||
}
|
||||
|
||||
/*C++17: ParentSpriteToDraw &ps = */ _vd.parent_sprites_to_draw.emplace_back();
|
||||
ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.back();
|
||||
ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.emplace_back();
|
||||
ps.x = tmp_x;
|
||||
ps.y = tmp_y;
|
||||
|
||||
@@ -1180,8 +1178,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran
|
||||
|
||||
*_vd.last_child = (uint)_vd.child_screen_sprites_to_draw.size();
|
||||
|
||||
/*C++17: ChildScreenSpriteToDraw &cs = */ _vd.child_screen_sprites_to_draw.emplace_back();
|
||||
ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.back();
|
||||
ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.emplace_back();
|
||||
cs.image = image;
|
||||
cs.pal = pal;
|
||||
cs.sub = sub;
|
||||
@@ -1201,8 +1198,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran
|
||||
static void AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2, Colours colour, uint16 width)
|
||||
{
|
||||
assert(width != 0);
|
||||
/*C++17: StringSpriteToDraw &ss = */ _vd.string_sprites_to_draw.emplace_back();
|
||||
StringSpriteToDraw &ss = _vd.string_sprites_to_draw.back();
|
||||
StringSpriteToDraw &ss = _vd.string_sprites_to_draw.emplace_back();
|
||||
ss.string = string;
|
||||
ss.x = x;
|
||||
ss.y = y;
|
||||
|
||||
Reference in New Issue
Block a user