That is, rather than XRES pixels wide. Broken since f52e047037, where RendererFrame started being dumped directly rather than via Renderer::DumpFrame, which took care of the required cropping.
This should and indeed mostly does not have any observable effect because any particle created with create_part for being loaded from a save is overwritten with data from the save anyway. However, if pretty powders is on, create_part uses Simulation::rng to make powders pretty, and that just gets in the way of debugging when relying on determinism.
Returning true is meant to consume the event, thereby preventing remaining event handlers and the rest of the game from handling it, but the check that implements this was accidentally removed in 87b81ceb45, oops.
Without the change the build fails on upcoming `gcc-16` as:
../src/lua/LuaSocketDefault.cpp: In function 'void LuaSocket::Timeout(double)':
../src/lua/LuaSocketDefault.cpp:21:31: error: 'INT_MAX' was not declared in this scope
21 | if (timeout > INT_MAX) timeout = INT_MAX;
| ^~~~~~~
../src/lua/LuaSocketDefault.cpp:6:1: note: 'INT_MAX' is defined in header '<climits>'; this is probably fixable by adding '#include <climits>'
5 | #include <sys/time.h>
+++ |+#include <climits>
6 | #include <time.h>
Specifically for lists of element and tool numbers, and clipboard implementations. These higher-level macros allow lower-level macros meant to be applied to each item in a list to be defined at the application site of the higher-level macro, slightly increasing readability. See https://en.wikipedia.org/wiki/X_macro
This ensures that the API is used correctly (i.e. without relying on blocking loops) by guaranteeing that blocking behaviour freezes the game.
Blocking until requests finish has always been bad practice and could/would freeze the game until the request manager finished handling the request, which could take as much as 30 seconds in some cases, or however much of your time the network felt like wasting, or it could even be guaranteed to permanently freeze the game on e.g. emscripten, where the request manager runs on the same thread as the rest of the game. It's just "luck" that in the vast majority of cases this was imperceptible because of good connectivity and because nobody uses the emscripten port.
Invoke with:
ninja serve-locally
Also fix emscripten builds on some systems where emscripten suddenly needs USE_PTHREADS (?????). Also fix JS-unsafe app_exe values breaking builds.
I'm not sure why we weren't using static_libraries to begin with; most likely because the object files (as opposed to the sources) were not possible to share due to different sets of macros being defined in cpp_args, see 3a591b8539 to 4f0c365e05.
I forgot to adjust the pattern build.sh looked for in 49991b5915 so this commit started out as a simple fix that did that, but then I realized that the project call in meson.build had grown too complicated to be tractable with grep so I moved version number enforcement to prepare.py.
Namely, in Create and ChangeType callbacks, which are themselves called by such lifetime management functions. Lifetime management includes explicit actions via partCreate and partKill, but also implicit ones such as changing the type property or changing x or y properties to values that move the particle beyond the edges and causes it to be killed.
Namely, in Select and Click tool callbacks, which are otherwise interface contexts and allow changing tools. This may cause use-after-free but it's much more likely to cause stack overflows. Importantly, the setter usage of ui.activeTool is considered to change tool state because it invokes Select callbacks.
CtypeDraw is already not an interface event, so to prevent parts of the call stack from being upgraded back to interface event status is not why this change is necessary. Rather, it is necessary because some Lua functions that are allowed to be called from non-interface events may indirectly invoke CtypeDraw, which is most likely unintended. Ctype-drawing is intended to be an interface feature, not something that e.g. an Update function creating a circle of particles should invoke.
Also make the flags parameter mandatory across all relevant functions because it's too easy to add a millionth int parameter and forget to update all call sites.
Semantics are mostly the same:
- event.register pushes a handler at the end of the handler chain, such that it has the lowest priority
- event.unregister removes at most one handler, which is the first one that matches
- a handler failing causes it to be removed from the chain
But removing handlers from the chain doesn't mess up handler order for the frame anymore: until this commit, removing a handler from the chain would shift all handlers in the chain while it was being traversed, which meant that some handlers were always skipped whenever any were removed.
Validate this with the following script:
local t = {}
for i = 1, 10 do
table.insert(t, i)
end
for i = #t - 1, 1, -1 do
local j = math.random(1, i)
t[i], t[j] = t[j], t[i]
end
print(table.concat(t, " "))
event.register(event.MOUSEDOWN, function()
print("=====")
end)
for i = 1, #t do
local c = t[i]
local function f()
print(i)
c = c - 1
if c == 0 then
event.unregister(event.MOUSEDOWN, f)
end
end
event.register(event.MOUSEDOWN, f)
end
The expected behaviour is that numbered event handlers are removed once they've been run as many times as the correspondingly numbered entry in t dictates. This, among other things, means that exactly one event handler is removed every MOUSEDOWN. This was absolutely not the case until now; removals were all over the place.
The idea behind not calling GameModel::Log in tpt.log is that that would not only print the message to stdout but also add it to GameView's list of log entries, which the console doesn't want. Sadly, this meant that messages also didn't make it to stdout when the console was open.
This opens a console window on Windows but does nothing anywhere else. Overrides 'redirect'.
Useful on Windows because the only way to access standard streams there is by tail -f'ing stdout/err.txt.