From 2929264885ccbd6447fe076a24cf2f402757edfc Mon Sep 17 00:00:00 2001 From: jacob1 Date: Sat, 17 Nov 2018 00:09:48 -0500 Subject: [PATCH] embed event api compatibility lua script probably temporary, can't deprecate and remove an extremely common api in the same version. lua script embed code mostly copied from my mod --- SConscript | 2 +- resources/powder-res.rc | 5 +- resources/resource.h | 7 + src/Platform.cpp | 12 ++ src/Platform.h | 2 + src/lua/LuaScriptHelper.h | 1 + src/lua/LuaScriptInterface.cpp | 3 + src/lua/luascripts/eventcompat.lua | 174 ++++++++++++++++++++++++ src/lua/luascripts/eventcompat.lua.cpp | 27 ++++ src/lua/luascripts/eventcompat.lua.orig | 27 ++++ src/lua/luascripts/file2c.py | 27 ++++ 11 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 resources/resource.h create mode 100644 src/lua/luascripts/eventcompat.lua create mode 100644 src/lua/luascripts/eventcompat.lua.cpp create mode 100644 src/lua/luascripts/eventcompat.lua.orig create mode 100644 src/lua/luascripts/file2c.py diff --git a/SConscript b/SConscript index d6fe4b216..d7893db7b 100644 --- a/SConscript +++ b/SConscript @@ -180,7 +180,7 @@ if GetOption("msvc"): env.Append(LIBPATH=['StaticLibs/']) else: env.Append(LIBPATH=['Libraries/']) - env.Append(CPPPATH=['includes/']) + env.Append(CPPPATH=['includes/', 'resources/']) #Check 32/64 bit def CheckBit(context): diff --git a/resources/powder-res.rc b/resources/powder-res.rc index 46208e21c..66c3ae80c 100644 --- a/resources/powder-res.rc +++ b/resources/powder-res.rc @@ -1,4 +1,5 @@ -#define IDI_ICON1 101 -#define IDI_ICON2 102 +#include "resource.h" + IDI_ICON1 ICON DISCARDABLE "powder.ico" IDI_ICON2 ICON DISCARDABLE "document.ico" +IDI_EVENTCOMPAT LUASCRIPT "../src/lua/luascripts/eventcompat.lua" diff --git a/resources/resource.h b/resources/resource.h new file mode 100644 index 000000000..b95856d51 --- /dev/null +++ b/resources/resource.h @@ -0,0 +1,7 @@ +#define LUASCRIPT 256 + +#define IDI_ICON1 101 +#define IDI_ICON2 102 +#define IDI_TPTMP 103 +#define IDI_SCRIPTMANAGER 104 +#define IDI_EVENTCOMPAT 105 diff --git a/src/Platform.cpp b/src/Platform.cpp index fde137304..62939f4fe 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -132,4 +132,16 @@ long unsigned int GetTime() #endif } + +void LoadFileInResource(int name, int type, unsigned int& size, const char*& data) +{ +#ifdef _MSC_VER + HMODULE handle = ::GetModuleHandle(NULL); + HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name), MAKEINTRESOURCE(type)); + HGLOBAL rcData = ::LoadResource(handle, rc); + size = ::SizeofResource(handle, rc); + data = static_cast(::LockResource(rcData)); +#endif +} + } diff --git a/src/Platform.h b/src/Platform.h index 3bceb1438..9a2ad8ab5 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -12,6 +12,8 @@ namespace Platform void Millisleep(long int t); long unsigned int GetTime(); + + void LoadFileInResource(int name, int type, unsigned int& size, const char*& data); } #endif diff --git a/src/lua/LuaScriptHelper.h b/src/lua/LuaScriptHelper.h index f56bfc2bf..b7b36b727 100644 --- a/src/lua/LuaScriptHelper.h +++ b/src/lua/LuaScriptHelper.h @@ -19,6 +19,7 @@ extern int tptPropertiesVersion; extern int tptElements; //Table for TPT element names extern int tptParts, tptPartsMeta, tptElementTransitions, tptPartsCData, tptPartMeta, tptPart, cIndex; +void luaopen_eventcompat(lua_State *l); void luacon_hook(lua_State *L, lua_Debug *ar); int luacon_eval(const char *command); String luacon_geterror(); diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 62a15dd05..cf1272ea2 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -335,6 +335,9 @@ tpt.partsdata = nil"); lua_setmetatable(l, -2); initLegacyProps(); + + ui::Engine::Ref().LastTick(Platform::GetTime()); + luaopen_eventcompat(l); } void LuaScriptInterface::Init() diff --git a/src/lua/luascripts/eventcompat.lua b/src/lua/luascripts/eventcompat.lua new file mode 100644 index 000000000..f044a0e5f --- /dev/null +++ b/src/lua/luascripts/eventcompat.lua @@ -0,0 +1,174 @@ +if not event then + return +end + +local deprecated_scripts = {} +local timer = nil +local function print_deprecation_warnings() + if not timer or timer <= 0 then + event.unregister(event.tick, print_deprecation_warnings) + else + timer = timer - 1 + return + end + + local deprecated = {} + for k,v in pairs(deprecated_scripts) do + table.insert(deprecated, k) + end + local start_message = #deprecated == 1 and "This script is" or "These scripts are" + print(start_message.." using a legacy event api and should be updated: ") + print("\""..table.concat(deprecated, "\", \"").."\"") +end + +local function deprecationwarning() + -- no warning for now + --[[local calling_file_info = debug.getinfo(3, "S") + if calling_file_info then + calling_file_info = calling_file_info["short_src"] + + if calling_file_info then + deprecated_scripts[calling_file_info] = true + if not timer then + timer = 5 + event.register(event.tick, print_deprecation_warnings) + end + end + end]] +end + + +function tpt.register_step(f) + deprecationwarning() + + event.register(event.tick, f) +end + +function tpt.unregister_step(f) + deprecationwarning() + + event.unregister(event.tick, f) +end + +local registered_mouseclicks = {} +function tpt.register_mouseclick(f) + deprecationwarning() + + local mousex = -1 + local mousey = -1 + local mousedown = -1 + local function mousedownfunc(x, y, button) + --replicate hack in original function + if button == 3 then + button = 4 + end + mousex = x + mousey = y + mousedown = button + return f(x, y, button, 1, 0) + end + local function mouseupfunc(x, y, button, evt) + --ignore automatic mouseup event sent when switching windows + if mousedown == -1 and evt == 1 then + return + end + --replicate hack in original function + if button == 3 then + button = 4 + end + local evtType = 2 + if evt == 1 then + evtType = 4 + elseif evt == 2 then + evtType = 5 + end + --zoom window cancel + --Original function would have started returning 0 for mousetick events + --(until the actual mousedown), but we don't replicate that here + if evt ~= 2 then + mousedown = -1 + end + return f(x, y, button, evtType, 0) + end + local function mousemovefunc(x, y, dx, dy) + mousex = x + mousey = y + end + local function mousewheelfunc(x, y, d) + return f(x, y, 0, 0, d) + end + local function tickfunc() + if mousedown ~= -1 then + return f(mousex, mousey, mousedown, 3, 0) + end + end + + event.register(event.mousedown, mousedownfunc) + event.register(event.mouseup, mouseupfunc) + event.register(event.mousemove, mousemovefunc) + event.register(event.mousewheel, mousewheelfunc) + event.register(event.tick, tickfunc) + + local funcs = {mousedownfunc, mouseupfunc, mousemovefunc, mousewheelfunc, tickfunc} + registered_mouseclicks[f] = funcs +end +tpt.register_mouseevent = tpt.register_mouseclick + +function tpt.unregister_mouseclick(f) + if not registered_mouseclicks[f] then return end + + local funcs = registered_mouseclicks[f] + event.unregister(event.mousedown, funcs[1]) + event.unregister(event.mouseup, funcs[2]) + event.unregister(event.mousemove, funcs[3]) + event.unregister(event.mousewheel, funcs[4]) + event.unregister(event.tick, funcs[5]) +end +tpt.unregister_mouseevent = tpt.unregister_mouseclick + +function tpt.register_keypress(f) + deprecationwarning() + + local keyMapping = {} + + -- lctrl, rctlr, lshift, rshift, lalt, ralt + keyMapping[225] = 304 + keyMapping[229] = 303 + keyMapping[224] = 306 + keyMapping[228] = 305 + keyMapping[226] = 308 + keyMapping[230] = 307 + + --up, down, right, left + keyMapping[82] = 273 + keyMapping[81] = 274 + keyMapping[79] = 275 + keyMapping[80] = 276 + + event.register(event.keypress, function(key, scan, rep, shift, ctrl, alt) + if rep then return end + local mod = event.getmodifiers() + + -- attempt to convert to string representation + err, keyStr = pcall(string.char, key) + if not err then keyStr = "" end + if keyStr ~= "" and shift then keyStr = string.upper(keyStr) end + + -- key mapping for common keys, extremely incomplete + if keyMapping[scan] then key = keyMapping[scan] end + return f(keyStr, key, mod, 1) + end) + + event.register(event.keyrelease, function(key, scan, rep, shift, ctrl, alt) + local mod = event.getmodifiers() + + -- attempt to convert to string representation + err, keyStr = pcall(string.char, key) + if not err then keyStr = "" end + + -- key mapping for common keys, extremely incomplete + if keyMapping[scan] then key = keyMapping[scan] end + return f(keyStr, key, mod, 2) + end) +end +tpt.register_keyevent = tpt.register_keypress diff --git a/src/lua/luascripts/eventcompat.lua.cpp b/src/lua/luascripts/eventcompat.lua.cpp new file mode 100644 index 000000000..7d3dd75ae --- /dev/null +++ b/src/lua/luascripts/eventcompat.lua.cpp @@ -0,0 +1,27 @@ +#ifdef LUACONSOLE +#ifdef _MSC_VER +#include "Platform.h" +#include "resource.h" +#endif +#include "lua/LuaCompat.h" + +void luaopen_eventcompat(lua_State *l) +{ +#ifndef _MSC_VER + int eventcompat_luac_sz = 4458; + const char* eventcompat_luac = "if not event then\n\011return\nend\n\nlocal deprecated_scripts = {}\nlocal timer = nil\nlocal function print_deprecation_warnings()\n\011if not timer or timer <= 0 then\n\011\011event.unregister(event.tick, print_deprecation_warnings)\n\011else\n\011\011timer = timer - 1\n\011\011return\n\011end\n\n\011local deprecated = {}\n\011for k,v in pairs(deprecated_scripts) do\n\011\011table.insert(deprecated, k)\n\011end\n\011local start_message = #deprecated == 1 and \"This script is\" or \"These scripts are\"\n\011print(start_message..\" using a legacy event api and should be updated: \")\n\011print(\"\\\"\"..table.concat(deprecated, \"\\\", \\\"\")..\"\\\"\")\nend\n\nlocal function deprecationwarning()\n\011-- no warning for now\n\011--[[local calling_file_info = debug.getinfo(3, \"S\")\n\011if calling_file_info then\n\011\011calling_file_info = calling_file_info[\"short_src\"]\n\n\011\011if calling_file_info then\n\011\011\011deprecated_scripts[calling_file_info] = true\n\011\011\011if not timer then\n\011\011\011\011timer = 5\n\011\011\011\011event.register(event.tick, print_deprecation_warnings)\n\011\011\011end\n\011\011end\n\011end]]\nend\n\n\nfunction tpt.register_step(f)\n\011deprecationwarning()\n\n\011event.register(event.tick, f)\nend\n\nfunction tpt.unregister_step(f)\n\011deprecationwarning()\n\n\011event.unregister(event.tick, f)\nend\n\nlocal registered_mouseclicks = {}\nfunction tpt.register_mouseclick(f)\n\011deprecationwarning()\n\n\011local mousex = -1\n\011local mousey = -1\n\011local mousedown = -1\n\011local function mousedownfunc(x, y, button)\n\011\011--replicate hack in original function\n\011\011if button == 3 then\n\011\011\011button = 4\n\011\011end\n\011\011mousex = x\n\011\011mousey = y\n\011\011mousedown = button\n\011\011return f(x, y, button, 1, 0)\n\011end\n\011local function mouseupfunc(x, y, button, evt)\n\011\011--ignore automatic mouseup event sent when switching windows\n\011\011if mousedown == -1 and evt == 1 then\n\011\011\011return\n\011\011end\n\011\011--replicate hack in original function\n\011\011if button == 3 then\n\011\011\011button = 4\n\011\011end\n\011\011local evtType = 2\n\011\011if evt == 1 then\n\011\011\011evtType = 4\n\011\011elseif evt == 2 then\n\011\011\011evtType = 5\n\011\011end\n\011\011--zoom window cancel\n\011\011--Original function would have started returning 0 for mousetick events\n\011\011--(until the actual mousedown), but we don't replicate that here\n\011\011if evt ~= 2 then\n\011\011\011mousedown = -1\n\011\011end\n\011\011return f(x, y, button, evtType, 0)\n\011end\n\011local function mousemovefunc(x, y, dx, dy)\n\011\011mousex = x\n\011\011mousey = y\n\011end\n\011local function mousewheelfunc(x, y, d)\n\011\011return f(x, y, 0, 0, d)\n\011end\n\011local function tickfunc()\n\011\011if mousedown ~= -1 then\n\011\011\011return f(mousex, mousey, mousedown, 3, 0)\n\011\011end\n\011end\n\n\011event.register(event.mousedown, mousedownfunc)\n\011event.register(event.mouseup, mouseupfunc)\n\011event.register(event.mousemove, mousemovefunc)\n\011event.register(event.mousewheel, mousewheelfunc)\n\011event.register(event.tick, tickfunc)\n\011\n\011local funcs = {mousedownfunc, mouseupfunc, mousemovefunc, mousewheelfunc, tickfunc}\n\011registered_mouseclicks[f] = funcs\nend\ntpt.register_mouseevent = tpt.register_mouseclick\n\nfunction tpt.unregister_mouseclick(f)\n\011if not registered_mouseclicks[f] then return end\n\n\011local funcs = registered_mouseclicks[f]\n\011event.unregister(event.mousedown, funcs[1])\n\011event.unregister(event.mouseup, funcs[2])\n\011event.unregister(event.mousemove, funcs[3])\n\011event.unregister(event.mousewheel, funcs[4])\n\011event.unregister(event.tick, funcs[5])\nend\ntpt.unregister_mouseevent = tpt.unregister_mouseclick\n\nfunction tpt.register_keypress(f)\n\011deprecationwarning()\n\n\011local keyMapping = {}\n\n\011-- lctrl, rctlr, lshift, rshift, lalt, ralt\n\011keyMapping[225] = 304\n\011keyMapping[229] = 303\n\011keyMapping[224] = 306\n\011keyMapping[228] = 305\n\011keyMapping[226] = 308\n\011keyMapping[230] = 307\n\n\011--up, down, right, left\n\011keyMapping[82] = 273\n\011keyMapping[81] = 274\n\011keyMapping[79] = 275\n\011keyMapping[80] = 276\n\n\011event.register(event.keypress, function(key, scan, rep, shift, ctrl, alt)\n\011\011if rep then return end\n\011\011local mod = event.getmodifiers()\n\n\011\011-- attempt to convert to string representation\n\011\011err, keyStr = pcall(string.char, key)\n\011\011if not err then keyStr = \"\" end\n\011\011if keyStr ~= \"\" and shift then keyStr = string.upper(keyStr) end\n\n\011\011-- key mapping for common keys, extremely incomplete\n\011\011if keyMapping[scan] then key = keyMapping[scan] end\n\011\011return f(keyStr, key, mod, 1)\n\011end)\n\n\011event.register(event.keyrelease, function(key, scan, rep, shift, ctrl, alt)\n\011\011local mod = event.getmodifiers()\n\n\011\011-- attempt to convert to string representation\n\011\011err, keyStr = pcall(string.char, key)\n\011\011if not err then keyStr = \"\" end\n\n\011\011-- key mapping for common keys, extremely incomplete\n\011\011if keyMapping[scan] then key = keyMapping[scan] end\n\011\011return f(keyStr, key, mod, 2)\n\011end)\nend\ntpt.register_keyevent = tpt.register_keypress\n"; + luaL_loadbuffer(l, eventcompat_luac, eventcompat_luac_sz, "@eventcompat.lua"); + lua_pcall(l, 0, 0, 0); +#else + unsigned int size = 0; + const char* data = NULL; + Platform::LoadFileInResource(IDI_EVENTCOMPAT, LUASCRIPT, size, data); + char *buffer = new char[size+1]; + ::memcpy(buffer, data, size); + buffer[size] = 0; + luaL_loadbuffer(l, buffer, size, "@eventcompat.lua"); + lua_pcall(l, 0, 0, 0); + delete[] buffer; +#endif +} +#endif diff --git a/src/lua/luascripts/eventcompat.lua.orig b/src/lua/luascripts/eventcompat.lua.orig new file mode 100644 index 000000000..8a47adee5 --- /dev/null +++ b/src/lua/luascripts/eventcompat.lua.orig @@ -0,0 +1,27 @@ +#ifdef LUACONSOLE +#ifdef _MSC_VER +#include "Platform.h" +#include "resource.h" +#endif +#include "lua/LuaCompat.h" + +void luaopen_eventcompat(lua_State *l) +{ +#ifndef _MSC_VER + int eventcompat_luac_sz = /*#SIZE*/; + const char* eventcompat_luac = /*#DATA*/; + luaL_loadbuffer(l, eventcompat_luac, eventcompat_luac_sz, "@eventcompat.lua"); + lua_pcall(l, 0, 0, 0); +#else + unsigned int size = 0; + const char* data = NULL; + Platform::LoadFileInResource(IDI_EVENTCOMPAT, LUASCRIPT, size, data); + char *buffer = new char[size+1]; + ::memcpy(buffer, data, size); + buffer[size] = 0; + luaL_loadbuffer(l, buffer, size, "@eventcompat.lua"); + lua_pcall(l, 0, 0, 0); + delete[] buffer; +#endif +} +#endif diff --git a/src/lua/luascripts/file2c.py b/src/lua/luascripts/file2c.py new file mode 100644 index 000000000..ae1e31cd7 --- /dev/null +++ b/src/lua/luascripts/file2c.py @@ -0,0 +1,27 @@ +#file from mniip, https://github.com/mniip/The-Powder-Toy/commit/d46d9f3f815d +import sys +import re + +def encode(x): + x = x.group(0) + if x == '\n': + return '\\n'; + if x == '"': + return '\\"'; + if x == '\\': + return '\\\\'; + return '\\{0:03o}'.format(ord(x)) + +f = open(sys.argv[2], 'rb') + +data = f.read().decode('utf-8') +f.close() +size = len(data) +data = '"' + re.sub(r'[^ -~]|"|\\', encode, data) + '"'; + +i = open(sys.argv[3], 'r') +o = open(sys.argv[1], 'w') +o.write(i.read().replace('/*#SIZE*/', str(size)).replace('/*#DATA*/', data)) +i.close() +o.close() +