Basically, this changes "SaveLoad *" to either:
1) "SaveLoadTable" if a list of SaveLoads was meant
2) "SaveLoad &" if a single entry was meant
As added bonus, this removes SL_END / SLE_END / SLEG_END. This
also adds core/span.hpp, a "std::span"-lite.
This is mostly done as there are now constraints on settings.ini you might not
expected. For example, conditional settings always have to come last, as otherwise
they would influence the index.
YAPF could end up in a situation where it sets the best intermediate node
to a node whose construction is never finalized (i.e. it is never added to
the open list). The content of the node would be overwritten in the next
round, potentially sending the vehicle to an unwanted location.
When you buy-out a company, you got your shares back. This is
based on company-value, which includes values for the vehicles etc.
In other words, you not only got the vehicles, but you also got
paid to get them back.
Additionally, you also got the loan of the company, but not the
money for the loan (as that is subtracted from the company-value).
Solve this by changing the rules of a buy-out: don't sell your
shares, get the loan AND the balance and get the infrastructure.
The comments for SettingDescType; it is a byte, so not 4 bytes and since it is not a flag there are about 250 other possibilities left instead of 9.
SettingGuiFlag is uint16 so has 2 bytes allocated.
SettingDescGlobVarList and related comments imply that global vars cannot be used elsewhere, but they are used for settings just fine. Even then the type is not used anywhere else but the definition of the table.
This to prevent the default copy-assignment getting used when during the assignment also some other memory needs to be allocated as that would otherwise be freed.
Division by resize_y is already yielding an unsigned number, so when clicking in the WD_FRAMERECT_TOP you would already get a huge value, so sel would never be negative. So, leave sel an unsigned number and remove the <= check.
Due to 47a99bb the order of elements in the garbage collection chain has
changed causing the class to be finalised before the instances of that class.
Since the instance's array of member values depends on the size of the values
in the class, the class finalisation resetting that size to 0 causes not all
finalisations to run, which subsequently causes a heap use after free. So,
just set the SQObjectPtrs to 'null' during the finalisation of the SQClass
so the SQInstance can release all instance variables during its finalisation.
Practically the length of the handlers not being equal to the number of
features is the problem as it means something was forgotten when adding
a new feature, so static assert to that and let the existing check on
the feature number take care of invalid data from the NewGRFs.
Functions like localtime, gmtime and asctime are not thread safe as they (might) reuse the same buffer. So use the safer _s/_r variant for localtime and gmtime, and use strftime in favour of asctime.
This ensures that default vehicles can transport any NewGRF defined cargos, albeit with weird graphics and vehicle names.
This also changes the refittability of default vehicles with default industries.
Default vehicles now behave as if they had a cargo translation table. This fixes default vehicles carrying seemingly random cargos, if NewGRF industry sets are present.
This behavior is disabled, when a NewGRF touches any of the cargo-type or refitting properties. In that case it's up to the NewGRF to define its own cargo translation table.
* Codechange: [Network] split CloseSocket and CloseConnection more clearly
- CloseSocket now closes the actual OS socket.
- CloseConnection frees up the resources to just before CloseSocket.
- dtors call CloseSocket / CloseConnection where needed.
Susz is masculine, not neuter, so it should result in "Susz Mazowiecki",
"Susz Morski", and not "Susz Mazowieckie" or "Susz Morskie". However,
because order of the names whould not be changed, it was replaced with
Leszno, which is neuter.
In the destructors of many of the network related classes Close() is called, just like the
top class in that hierarchy. However, due to virtual functions getting resolved statically
in the destructor it would always call the empty Close() of the top class.
Document the other cases where a virtual call is resolved statically.
This as during construction the sub class has not been initialized yet, and
during destruction the sub class has already been destroyed, so the overriding
virtual function would be accessing uninitialized data.
This also changes ScriptEventVehicleAutoReplaced when replacing wagons:
The event is now only spawned, if the head engine changes, so only if the VehicleID of the consist changes.
Previously replacing wagons spawned an event with OldVehicleID==NewVehicleID.
This means that random tree generation density is higher on small maps and lower on large maps. This difference is enough to make the Lumber Mill impractical to use on large maps.
This change skips ticks on maps smaller than 256x256 and increases iterations or shortens the interval on maps larger than 256x256.
It now follows very simple rules:
0 - Fatal, user should know about this
1 - Error, but we are recovering
2 - Warning, wrong but okay if you don't know
3 - Info, information you might care about
4 -
5 - Debug #1 - High level debug messages
6 - Debug #2 - Low level debug messages
7 - Trace information
The code mixed up "client has quit but we already told everyone"
with "client lost connection, handle this".
Split up those two signals:
- CLIENT_QUIT means we told everyone and the connection is now dead
- CONNECTION_LIST means we should tell everyone we lost a client
The function fluid_player_join in the library is broken beyond compare for the
usecases it was used for (see their #872). It does not wait until it is safe
to delete the player, so it is up to the end user to ensure that.
For OpenTTD we acquire a lock before fluid_synth_write_s16 and we acquire the
same lock in the stop function. So, only one of the functions can be doing its
thing, meaning we do not need to wait for the player to be stopped as it
cannot be doing anything as we prevent that by the lock.
Since pixel dimensions in SetPadding() are scaled by GUI size, padding for inset viewports was excessive.
Instead, automatically apply padding for WWT_INSET at widget level. This applies to all widgets inside a WWT_INSET, which in all instances is a NWID_VIEWPORT.
This meant that on opening the Multiplayer window, if you had more
than one server configured, it would one by one cancel all pending
queries and send a new. Result: only the last server was updated.
The most common case never needs access to it anymore. Make the
one exception to this explicit. This means the fact that we
store it is now an implementation detail.
If the highscore/news window panel size, which is now scaled by GUI zoom, is larger than the screen size, a loop will be entered where the window is repeatedly resized.
This is resolved by removing the minimal size from the panel, as the window is always resized to cover the screen anyway. This means the screen size can never be too small.
Hostnames like "content.openttd.org" resolve into multiple IPv4 and IPv6.
It is possible that either of the IPs is not working, either due to
a poorly configured OS (having IPv6 but no valid route), broken network
paths, or a service that is temporary unavailable.
Instead of trying the IPs one by one, waiting for a 3s timeout between
each, be a bit more like browsers, and stack attempts on top of each
other with slight delays. This is called Happy Eyebells.
Initially, try the first IPv6 address. If within 250ms there is no
connection yet, try the first IPv4 address. 250ms later, try the
second IPv6 address, etc, till all addresses are tried.
If any connection is created, abort all the other (pending) connections
and use the one that is created. If all fail 3s after the last connect(),
trigger a timeout for all.
We now resolve the connection_string to a NetworkAddress in a much
later state. This means there are fewer places constructing a NetworkAddress.
The main benefit of this is in later PRs that introduce different types
of NetworkAddresses. Storing this in things like NetworkGameList is
rather complex, especially as NetworkAddress has to be mutable at all
times.
Additionally, the NetworkAddress is a complex object to store simple
information: how to connect to this server.
Split the updating in a "static" version that only needs to be called when a new map is loaded or some settings are changed, and a "dynamic" version that updates everything that changes regularly such as the current game date or the number of spectators.