Organize Lua API into multiple TUs

This commit is contained in:
Tamás Bálint Misius 2024-01-22 21:43:57 +01:00
parent 2a43e8aef0
commit 1cb8f0378f
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
49 changed files with 6272 additions and 6320 deletions

View File

@ -1,5 +1,6 @@
#pragma once
#include "common/String.h"
#include <cstdint>
#include <string>
#include <vector>
#include <optional>

View File

@ -10,12 +10,12 @@
CommandInterface *commandInterface = nullptr;
CommandInterface::CommandInterface(GameController * c, GameModel * m)
CommandInterface::CommandInterface(GameController *newGameController, GameModel *newGameModel)
{
assert(!commandInterface);
commandInterface = this;
this->m = m;
this->c = c;
this->m = newGameModel;
this->c = newGameController;
}
CommandInterface::~CommandInterface()

View File

@ -12,7 +12,7 @@ protected:
String lastError;
GameModel * m;
GameController * c;
CommandInterface(GameController * c, GameModel * m);
CommandInterface(GameController *newGameController, GameModel *newGameModel);
public:
enum LogType { LogError, LogWarning, LogNotice };
@ -35,7 +35,7 @@ public:
String GetLastError();
virtual ~CommandInterface();
static CommandInterface *Create(GameController * c, GameModel * m);
static CommandInterface *Create(GameController *newGameController, GameModel *newGameModel);
};
extern CommandInterface *commandInterface;

View File

@ -15,53 +15,53 @@ Luna<LuaButton>::RegType LuaButton::methods[] = {
{0, 0}
};
LuaButton::LuaButton(lua_State * l) :
LuaComponent(l)
LuaButton::LuaButton(lua_State *L) :
LuaComponent(L)
{
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
String text = tpt_lua_optString(l, 5, "");
String toolTip = tpt_lua_optString(l, 6, "");
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
String text = tpt_lua_optString(L, 5, "");
String toolTip = tpt_lua_optString(L, 6, "");
button = new ui::Button(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, toolTip);
component = button;
button->SetActionCallback({ [this] { triggerAction(); } });
}
int LuaButton::enabled(lua_State * l)
int LuaButton::enabled(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TBOOLEAN);
button->Enabled = lua_toboolean(l, 1);
luaL_checktype(L, 1, LUA_TBOOLEAN);
button->Enabled = lua_toboolean(L, 1);
return 0;
}
else
{
lua_pushboolean(l, button->Enabled);
lua_pushboolean(L, button->Enabled);
return 1;
}
}
int LuaButton::action(lua_State * l)
int LuaButton::action(lua_State *L)
{
return actionFunction.CheckAndAssignArg1(l);
return actionFunction.CheckAndAssignArg1(L);
}
int LuaButton::text(lua_State * l)
int LuaButton::text(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
button->SetText(tpt_lua_checkString(l, 1));
button->SetText(tpt_lua_checkString(L, 1));
return 0;
}
else
{
tpt_lua_pushString(l, button->GetText());
tpt_lua_pushString(L, button->GetText());
return 1;
}
}
@ -70,11 +70,11 @@ void LuaButton::triggerAction()
{
if(actionFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, actionFunction);
lua_rawgeti(l, LUA_REGISTRYINDEX, owner_ref);
if (tpt_lua_pcall(l, 1, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, actionFunction);
lua_rawgeti(L, LUA_REGISTRYINDEX, owner_ref);
if (tpt_lua_pcall(L, 1, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}

View File

@ -15,13 +15,13 @@ class LuaButton: public LuaComponent
ui::Button * button;
LuaComponentCallback actionFunction;
void triggerAction();
int action(lua_State * l);
int text(lua_State * l);
int enabled(lua_State * l);
int action(lua_State *L);
int text(lua_State *L);
int enabled(lua_State *L);
public:
static const char className[];
static Luna<LuaButton>::RegType methods[];
LuaButton(lua_State * l);
LuaButton(lua_State *L);
~LuaButton();
};

64
src/lua/LuaBz2.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "LuaScriptInterface.h"
#include "bzip2/bz2wrap.h"
static int compress(lua_State *L)
{
auto src = tpt_lua_checkByteString(L, 1);
auto maxSize = size_t(luaL_optinteger(L, 2, 0));
std::vector<char> dest;
auto result = BZ2WCompress(dest, src.data(), src.size(), maxSize);
#define RETURN_ERR(str) lua_pushnil(L); lua_pushinteger(L, int(result)); lua_pushliteral(L, str); return 3
switch (result)
{
case BZ2WCompressOk: break;
case BZ2WCompressNomem: RETURN_ERR("out of memory");
case BZ2WCompressLimit: RETURN_ERR("size limit exceeded");
}
#undef RETURN_ERR
tpt_lua_pushByteString(L, ByteString(dest.begin(), dest.end()));
return 1;
}
static int decompress(lua_State *L)
{
auto src = tpt_lua_checkByteString(L, 1);
auto maxSize = size_t(luaL_optinteger(L, 2, 0));
std::vector<char> dest;
auto result = BZ2WDecompress(dest, src.data(), src.size(), maxSize);
#define RETURN_ERR(str) lua_pushnil(L); lua_pushinteger(L, int(result)); lua_pushliteral(L, str); return 3
switch (result)
{
case BZ2WDecompressOk: break;
case BZ2WDecompressNomem: RETURN_ERR("out of memory");
case BZ2WDecompressLimit: RETURN_ERR("size limit exceeded");
case BZ2WDecompressType:
case BZ2WDecompressBad:
case BZ2WDecompressEof: RETURN_ERR("corrupted stream");
}
#undef RETURN_ERR
tpt_lua_pushByteString(L, ByteString(dest.begin(), dest.end()));
return 1;
}
void LuaBz2::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(compress),
LFUNC(decompress),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONSTAS(k, v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, k)
LCONSTAS("COMPRESS_NOMEM" , BZ2WCompressNomem );
LCONSTAS("COMPRESS_LIMIT" , BZ2WCompressLimit );
LCONSTAS("DECOMPRESS_NOMEM", BZ2WDecompressNomem);
LCONSTAS("DECOMPRESS_LIMIT", BZ2WDecompressLimit);
LCONSTAS("DECOMPRESS_TYPE" , BZ2WDecompressType );
LCONSTAS("DECOMPRESS_BAD" , BZ2WDecompressBad );
LCONSTAS("DECOMPRESS_EOF" , BZ2WDecompressEof );
#undef LCONSTAS
lua_setglobal(L, "bz2");
}

View File

@ -15,51 +15,51 @@ Luna<LuaCheckbox>::RegType LuaCheckbox::methods[] = {
{0, 0}
};
LuaCheckbox::LuaCheckbox(lua_State * l) :
LuaComponent(l)
LuaCheckbox::LuaCheckbox(lua_State *L) :
LuaComponent(L)
{
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
String text = tpt_lua_optString(l, 5, "");
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
String text = tpt_lua_optString(L, 5, "");
checkbox = new ui::Checkbox(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, "");
component = checkbox;
checkbox->SetActionCallback({ [this] { triggerAction(); } });
}
int LuaCheckbox::checked(lua_State * l)
int LuaCheckbox::checked(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
checkbox->SetChecked(lua_toboolean(l, 1));
checkbox->SetChecked(lua_toboolean(L, 1));
return 0;
}
else
{
lua_pushboolean(l, checkbox->GetChecked());
lua_pushboolean(L, checkbox->GetChecked());
return 1;
}
}
int LuaCheckbox::action(lua_State * l)
int LuaCheckbox::action(lua_State *L)
{
return actionFunction.CheckAndAssignArg1(l);
return actionFunction.CheckAndAssignArg1(L);
}
int LuaCheckbox::text(lua_State * l)
int LuaCheckbox::text(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
checkbox->SetText(tpt_lua_checkString(l, 1));
checkbox->SetText(tpt_lua_checkString(L, 1));
return 0;
}
else
{
tpt_lua_pushString(l, checkbox->GetText());
tpt_lua_pushString(L, checkbox->GetText());
return 1;
}
}
@ -68,12 +68,12 @@ void LuaCheckbox::triggerAction()
{
if(actionFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, actionFunction);
lua_rawgeti(l, LUA_REGISTRYINDEX, owner_ref);
lua_pushboolean(l, checkbox->GetChecked());
if (tpt_lua_pcall(l, 2, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, actionFunction);
lua_rawgeti(L, LUA_REGISTRYINDEX, owner_ref);
lua_pushboolean(L, checkbox->GetChecked());
if (tpt_lua_pcall(L, 2, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}

View File

@ -15,13 +15,13 @@ class LuaCheckbox: public LuaComponent
ui::Checkbox * checkbox;
LuaComponentCallback actionFunction;
void triggerAction();
int action(lua_State * l);
int checked(lua_State * l);
int text(lua_State * l);
int action(lua_State *L);
int checked(lua_State *L);
int text(lua_State *L);
public:
static const char className[];
static Luna<LuaCheckbox>::RegType methods[];
LuaCheckbox(lua_State * l);
LuaCheckbox(lua_State *L);
~LuaCheckbox();
};

View File

@ -2,15 +2,13 @@
#if LUA_VERSION_NUM >= 502
// Implement missing luaL_typerror function
int luaL_typerror (lua_State *L, int narg, const char *tname)
int luaL_typerror(lua_State *L, int narg, const char *tname)
{
const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
void luaL_register (lua_State *L,
const char *libname,
const luaL_Reg *l)
void luaL_register(lua_State *L, const char *libname, const luaL_Reg *l)
{
if (libname)
{
@ -20,18 +18,7 @@ void luaL_register (lua_State *L,
}
luaL_setfuncs(L, l, 0);
}
void tpt_lua_setmainthread(lua_State *L)
{
}
void tpt_lua_getmainthread(lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
}
#else
# ifndef lua_pushglobaltable // * Thank you moonjit
// Implement function added in lua 5.2 that we now use
void lua_pushglobaltable(lua_State *L)
@ -39,42 +26,4 @@ void lua_pushglobaltable(lua_State *L)
lua_pushvalue(L, LUA_GLOBALSINDEX);
}
# endif
void tpt_lua_setmainthread(lua_State *L)
{
lua_pushthread(L);
lua_setfield(L, LUA_REGISTRYINDEX, "tpt_lua_mainthread");
}
void tpt_lua_getmainthread(lua_State *L)
{
lua_getfield(L, LUA_REGISTRYINDEX, "tpt_lua_mainthread");
}
#endif
// Useful helper function, mainly used for logging
int luaL_tostring(lua_State *L, int n)
{
luaL_checkany(L, n);
switch (lua_type(L, n))
{
case LUA_TNUMBER:
lua_tostring(L, n);
lua_pushvalue(L, n);
break;
case LUA_TSTRING:
lua_pushvalue(L, n);
break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, n) ? "true" : "false"));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
break;
default:
lua_pushfstring(L, "%s: %p", luaL_typename(L, n), lua_topointer(L, n));
break;
}
return 1;
}

View File

@ -9,9 +9,6 @@ extern "C"
#include <lauxlib.h>
#include <lualib.h>
LUALIB_API void tpt_lua_setmainthread(lua_State *L);
LUALIB_API void tpt_lua_getmainthread(lua_State *L);
#if LUA_VERSION_NUM >= 502
void luaL_register(lua_State *L, const char *libname, const luaL_Reg *l);
#define lua_strlen(L,i) lua_rawlen(L, (i))
@ -25,7 +22,6 @@ LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
LUALIB_API void (lua_pushglobaltable) (lua_State *L);
# endif
#endif
int luaL_tostring(lua_State *L, int n);
#ifdef __cplusplus
}

View File

@ -4,72 +4,72 @@
#include "gui/interface/Component.h"
#include "gui/interface/Window.h"
int LuaComponentCallback::CheckAndAssignArg1(lua_State *l)
int LuaComponentCallback::CheckAndAssignArg1(lua_State *L)
{
if (lua_type(l, 1) != LUA_TNIL)
if (lua_type(L, 1) != LUA_TNIL)
{
luaL_checktype(l, 1, LUA_TFUNCTION);
luaL_checktype(L, 1, LUA_TFUNCTION);
}
LuaSmartRef::Assign(l, 1);
LuaSmartRef::Assign(L, 1);
return 0;
}
LuaComponent::LuaComponent(lua_State * l) : component(nullptr), owner_ref(LUA_REFNIL)
LuaComponent::LuaComponent(lua_State *L) : component(nullptr), owner_ref(LUA_REFNIL)
{
this->l = l; // I don't get how this doesn't cause crashes later on
this->L = L; // I don't get how this doesn't cause crashes later on
ci = static_cast<LuaScriptInterface *>(commandInterface);
}
int LuaComponent::position(lua_State * l)
int LuaComponent::position(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TNUMBER);
luaL_checktype(l, 2, LUA_TNUMBER);
component->Position = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2));
luaL_checktype(L, 1, LUA_TNUMBER);
luaL_checktype(L, 2, LUA_TNUMBER);
component->Position = ui::Point(lua_tointeger(L, 1), lua_tointeger(L, 2));
return 0;
}
else
{
lua_pushinteger(l, component->Position.X);
lua_pushinteger(l, component->Position.Y);
lua_pushinteger(L, component->Position.X);
lua_pushinteger(L, component->Position.Y);
return 2;
}
}
int LuaComponent::size(lua_State * l)
int LuaComponent::size(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TNUMBER);
luaL_checktype(l, 2, LUA_TNUMBER);
component->Size = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2));
luaL_checktype(L, 1, LUA_TNUMBER);
luaL_checktype(L, 2, LUA_TNUMBER);
component->Size = ui::Point(lua_tointeger(L, 1), lua_tointeger(L, 2));
component->Invalidate();
return 0;
}
else
{
lua_pushinteger(l, component->Size.X);
lua_pushinteger(l, component->Size.Y);
lua_pushinteger(L, component->Size.X);
lua_pushinteger(L, component->Size.Y);
return 2;
}
}
int LuaComponent::visible(lua_State * l)
int LuaComponent::visible(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TBOOLEAN);
component->Visible = lua_toboolean(l, 1);
luaL_checktype(L, 1, LUA_TBOOLEAN);
component->Visible = lua_toboolean(L, 1);
return 0;
}
else
{
lua_pushboolean(l, component->Visible);
lua_pushboolean(L, component->Visible);
return 1;
}
}

View File

@ -15,25 +15,25 @@ class LuaComponentCallback : public LuaSmartRef
{
public:
using LuaSmartRef::LuaSmartRef;
int CheckAndAssignArg1(lua_State *l);
int CheckAndAssignArg1(lua_State *L);
};
class LuaComponent
{
protected:
ui::Component * component;
lua_State * l;
lua_State *L;
LuaWindow * parent = nullptr;
int position(lua_State * l);
int size(lua_State * l);
int visible(lua_State * l);
int position(lua_State *L);
int size(lua_State *L);
int visible(lua_State *L);
public:
LuaScriptInterface * ci;
int owner_ref;
ui::Component * GetComponent() { return component; }
void SetParentWindow(LuaWindow *parent) { this->parent = parent; }
LuaComponent(lua_State * l);
LuaComponent(lua_State *L);
~LuaComponent();
};

900
src/lua/LuaElements.cpp Normal file
View File

@ -0,0 +1,900 @@
#include "LuaScriptInterface.h"
#include "gui/game/GameModel.h"
#include "simulation/ElementClasses.h"
#include "simulation/ElementCommon.h"
#include "simulation/SimulationData.h"
#include <mutex>
static void getDefaultProperties(lua_State *L, int id)
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
lua_newtable(L);
for (auto &prop : Particle::GetProperties())
{
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<const unsigned char*>(&elements[id].DefaultProperties)) + prop.Offset);
tpt_lua_pushByteString(L, prop.Name);
LuaGetProperty(L, prop, propertyAddress);
lua_settable(L, -3);
}
for (auto &alias : Particle::GetPropertyAliases())
{
tpt_lua_pushByteString(L, alias.from);
tpt_lua_pushByteString(L, alias.to);
lua_gettable(L, -3);
lua_settable(L, -3);
}
}
static void setDefaultProperties(lua_State *L, int id, int stackPos)
{
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
if (lua_type(L, stackPos) == LUA_TTABLE)
{
for (auto &prop : Particle::GetProperties())
{
tpt_lua_pushByteString(L, prop.Name);
lua_gettable(L, stackPos);
if (lua_type(L, -1) == LUA_TNIL)
{
for (auto &alias : Particle::GetPropertyAliases())
{
if (alias.to == prop.Name)
{
lua_pop(L, 1);
tpt_lua_pushByteString(L, alias.from);
lua_gettable(L, stackPos);
}
}
}
if (lua_type(L, -1) != LUA_TNIL)
{
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<unsigned char*>(&elements[id].DefaultProperties)) + prop.Offset);
LuaSetProperty(L, prop, propertyAddress, -1);
}
lua_pop(L, 1);
}
}
}
static void manageElementIdentifier(lua_State *L, int id, bool add)
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
if (elements[id].Enabled)
{
lua_getglobal(L, "elements");
tpt_lua_pushByteString(L, elements[id].Identifier);
if (add)
{
lua_pushinteger(L, id);
}
else
{
lua_pushnil(L);
}
lua_settable(L, -3);
if (elements[id].Identifier.BeginsWith("DEFAULT_PT_"))
{
ByteString realIdentifier = ByteString::Build("DEFAULT_PT_", elements[id].Name.ToUtf8());
if (id != 0 && id != PT_NBHL && id != PT_NWHL && elements[id].Identifier != realIdentifier)
{
tpt_lua_pushByteString(L, realIdentifier);
if (add)
{
lua_pushinteger(L, id);
}
else
{
lua_pushnil(L);
}
lua_settable(L, -3);
}
}
lua_pop(L, 1);
}
}
static int luaUpdateWrapper(UPDATE_FUNC_ARGS)
{
if (!sim->useLuaCallbacks)
{
return 0;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &builtinElements = GetElements();
auto *builtinUpdate = builtinElements[parts[i].type].Update;
auto &customElements = lsi->customElements;
if (builtinUpdate && customElements[parts[i].type].updateMode == UPDATE_AFTER)
{
if (builtinUpdate(UPDATE_FUNC_SUBCALL_ARGS))
return 1;
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
if (customElements[parts[i].type].update)
{
int retval = 0, callret;
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[parts[i].type].update);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, x);
lua_pushinteger(lsi->L, y);
lua_pushinteger(lsi->L, surround_space);
lua_pushinteger(lsi->L, nt);
callret = tpt_lua_pcall(lsi->L, 5, 1, 0, eventTraitSimRng);
if (callret)
lsi->Log(CommandInterface::LogError, LuaGetError());
if(lua_isboolean(lsi->L, -1)){
retval = lua_toboolean(lsi->L, -1);
}
lua_pop(lsi->L, 1);
if (retval)
{
return 1;
}
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
if (builtinUpdate && customElements[parts[i].type].updateMode == UPDATE_BEFORE)
{
if (builtinUpdate(UPDATE_FUNC_SUBCALL_ARGS))
return 1;
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
return 0;
}
static int luaGraphicsWrapper(GRAPHICS_FUNC_ARGS)
{
if (!gfctx.sim->useLuaCallbacks)
{
return Element::defaultGraphics(GRAPHICS_FUNC_SUBCALL_ARGS);
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
auto *sim = lsi->sim;
if (customElements[cpart->type].graphics)
{
auto *pipeSubcallWcpart = gfctx.pipeSubcallCpart ? sim->parts + (gfctx.pipeSubcallCpart - gfctx.sim->parts) : nullptr;
if (pipeSubcallWcpart)
{
std::swap(*pipeSubcallWcpart, *gfctx.pipeSubcallTpart);
cpart = pipeSubcallWcpart;
}
int cache = 0, callret;
int i = cpart - gfctx.sim->parts; // pointer arithmetic be like
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[cpart->type].graphics);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, *colr);
lua_pushinteger(lsi->L, *colg);
lua_pushinteger(lsi->L, *colb);
callret = tpt_lua_pcall(lsi->L, 4, 10, 0, eventTraitSimGraphics);
if (callret)
{
lsi->Log(CommandInterface::LogError, LuaGetError());
lua_pop(lsi->L, 1);
}
else
{
bool valid = true;
for (int i = -10; i < 0; i++)
if (!lua_isnumber(lsi->L, i) && !lua_isnil(lsi->L, i))
{
valid = false;
break;
}
if (valid)
{
cache = luaL_optint(lsi->L, -10, 0);
*pixel_mode = luaL_optint(lsi->L, -9, *pixel_mode);
*cola = luaL_optint(lsi->L, -8, *cola);
*colr = luaL_optint(lsi->L, -7, *colr);
*colg = luaL_optint(lsi->L, -6, *colg);
*colb = luaL_optint(lsi->L, -5, *colb);
*firea = luaL_optint(lsi->L, -4, *firea);
*firer = luaL_optint(lsi->L, -3, *firer);
*fireg = luaL_optint(lsi->L, -2, *fireg);
*fireb = luaL_optint(lsi->L, -1, *fireb);
}
lua_pop(lsi->L, 10);
}
if (pipeSubcallWcpart)
{
std::swap(*pipeSubcallWcpart, *gfctx.pipeSubcallTpart);
}
return cache;
}
return 0;
}
static void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS)
{
if (!sim->useLuaCallbacks)
{
return;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
if (customElements[sim->parts[i].type].create)
{
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[sim->parts[i].type].create);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, x);
lua_pushinteger(lsi->L, y);
lua_pushinteger(lsi->L, t);
lua_pushinteger(lsi->L, v);
if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng))
{
lsi->Log(CommandInterface::LogError, "In create func: " + LuaGetError());
lua_pop(lsi->L, 1);
}
}
}
static bool luaCreateAllowedWrapper(ELEMENT_CREATE_ALLOWED_FUNC_ARGS)
{
if (!sim->useLuaCallbacks)
{
// Nothing really bad can happen, no callbacks are allowed anyway. The worst thing that can happen
// is that a well-crafted save looks odd in previews because it has multiple Element::defaultGraphics-rendered
// instances of something that should be limited to one instance.
return 1;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
bool ret = false;
if (customElements[t].createAllowed)
{
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[t].createAllowed);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, x);
lua_pushinteger(lsi->L, y);
lua_pushinteger(lsi->L, t);
if (tpt_lua_pcall(lsi->L, 4, 1, 0, eventTraitSimRng))
{
lsi->Log(CommandInterface::LogError, "In create allowed: " + LuaGetError());
lua_pop(lsi->L, 1);
}
else
{
if (lua_isboolean(lsi->L, -1))
ret = lua_toboolean(lsi->L, -1);
lua_pop(lsi->L, 1);
}
}
return ret;
}
static void luaChangeTypeWrapper(ELEMENT_CHANGETYPE_FUNC_ARGS)
{
if (!sim->useLuaCallbacks)
{
return;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
if (customElements[sim->parts[i].type].changeType)
{
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[sim->parts[i].type].changeType);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, x);
lua_pushinteger(lsi->L, y);
lua_pushinteger(lsi->L, from);
lua_pushinteger(lsi->L, to);
if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng))
{
lsi->Log(CommandInterface::LogError, "In change type: " + LuaGetError());
lua_pop(lsi->L, 1);
}
}
}
static bool luaCtypeDrawWrapper(CTYPEDRAW_FUNC_ARGS)
{
if (!sim->useLuaCallbacks)
{
return false;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
bool ret = false;
if (customElements[sim->parts[i].type].ctypeDraw)
{
lua_rawgeti(lsi->L, LUA_REGISTRYINDEX, customElements[sim->parts[i].type].ctypeDraw);
lua_pushinteger(lsi->L, i);
lua_pushinteger(lsi->L, t);
lua_pushinteger(lsi->L, v);
if (tpt_lua_pcall(lsi->L, 3, 1, 0, eventTraitSimRng))
{
lsi->Log(CommandInterface::LogError, LuaGetError());
lua_pop(lsi->L, 1);
}
else
{
if (lua_isboolean(lsi->L, -1))
ret = lua_toboolean(lsi->L, -1);
lua_pop(lsi->L, 1);
}
}
return ret;
}
static int allocate(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TSTRING);
auto group = tpt_lua_toByteString(L, 1).ToUpper();
auto id = tpt_lua_toByteString(L, 2).ToUpper();
if (id.Contains("_"))
{
return luaL_error(L, "The element name may not contain '_'.");
}
if (group.Contains("_"))
{
return luaL_error(L, "The group name may not contain '_'.");
}
if (group == "DEFAULT")
{
return luaL_error(L, "You cannot create elements in the 'DEFAULT' group.");
}
auto identifier = group + "_PT_" + id;
int newID = -1;
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
for(int i = 0; i < PT_NUM; i++)
{
if(elements[i].Enabled && ByteString(elements[i].Identifier) == identifier)
return luaL_error(L, "Element identifier already in use");
}
// Start out at 255 so that lua element IDs are still one byte (better save compatibility)
for (int i = PT_NUM >= 255 ? 255 : PT_NUM; i >= 0; i--)
{
if (!elements[i].Enabled)
{
newID = i;
break;
}
}
// If not enough space, then we start with the new maimum ID
if (newID == -1)
{
for (int i = PT_NUM-1; i >= 255; i--)
{
if (!elements[i].Enabled)
{
newID = i;
break;
}
}
}
}
if (newID != -1)
{
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
auto &elements = sd.elements;
elements[newID] = Element();
elements[newID].Enabled = true;
elements[newID].Identifier = identifier;
}
lua_getglobal(L, "elements");
tpt_lua_pushByteString(L, identifier);
lua_pushinteger(L, newID);
lua_settable(L, -3);
lua_pop(L, 1);
for (auto elem = 0; elem < PT_NUM; ++elem)
{
lsi->customCanMove[elem][newID] = 0;
lsi->customCanMove[newID][elem] = 0;
}
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
}
lua_pushinteger(L, newID);
return 1;
}
static int element(lua_State *L)
{
auto &builtinElements = GetElements();
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
int id = luaL_checkinteger(L, 1);
if (!SimulationData::CRef().IsElementOrNone(id))
{
return luaL_error(L, "Invalid element");
}
if (lua_gettop(L) > 1)
{
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
auto &elements = sd.elements;
luaL_checktype(L, 2, LUA_TTABLE);
//Write values from native data to a table
for (auto &prop : Element::GetProperties())
{
tpt_lua_pushByteString(L, prop.Name);
lua_gettable(L, -2);
if (lua_type(L, -1) != LUA_TNIL)
{
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop.Offset);
LuaSetProperty(L, prop, propertyAddress, -1);
}
lua_pop(L, 1);
}
lua_getfield(L, -1, "Update");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].update.Assign(L, -1);
customElements[id].updateMode = UPDATE_AFTER;
elements[id].Update = luaUpdateWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].update.Clear();
customElements[id].updateMode = UPDATE_AFTER;
elements[id].Update = builtinElements[id].Update;
}
lua_pop(L, 1);
lua_getfield(L, -1, "Graphics");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].graphics.Assign(L, -1);
elements[id].Graphics = luaGraphicsWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].graphics.Clear();
elements[id].Graphics = builtinElements[id].Graphics;
}
lua_pop(L, 1);
lua_getfield(L, -1, "Create");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].create.Assign(L, -1);
elements[id].Create = luaCreateWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].create.Clear();
elements[id].Create = builtinElements[id].Create;
}
lua_pop(L, 1);
lua_getfield(L, -1, "CreateAllowed");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].createAllowed.Assign(L, -1);
elements[id].CreateAllowed = luaCreateAllowedWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].createAllowed.Clear();
elements[id].CreateAllowed = builtinElements[id].CreateAllowed;
}
lua_pop(L, 1);
lua_getfield(L, -1, "ChangeType");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].changeType.Assign(L, -1);
elements[id].ChangeType = luaChangeTypeWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].changeType.Clear();
elements[id].ChangeType = builtinElements[id].ChangeType;
}
lua_pop(L, 1);
lua_getfield(L, -1, "CtypeDraw");
if (lua_type(L, -1) == LUA_TFUNCTION)
{
customElements[id].ctypeDraw.Assign(L, -1);
elements[id].CtypeDraw = luaCtypeDrawWrapper;
}
else if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1))
{
customElements[id].ctypeDraw.Clear();
elements[id].CtypeDraw = builtinElements[id].CtypeDraw;
}
lua_pop(L, 1);
lua_getfield(L, -1, "DefaultProperties");
setDefaultProperties(L, id, lua_gettop(L));
lua_pop(L, 1);
sd.graphicscache[id].isready = 0;
}
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
return 0;
}
else
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
//Write values from native data to a table
lua_newtable(L);
for (auto &prop : Element::GetProperties())
{
tpt_lua_pushByteString(L, prop.Name);
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop.Offset);
LuaGetProperty(L, prop, propertyAddress);
lua_settable(L, -3);
}
tpt_lua_pushByteString(L, elements[id].Identifier);
lua_setfield(L, -2, "Identifier");
getDefaultProperties(L, id);
lua_setfield(L, -2, "DefaultProperties");
return 1;
}
}
static int property(lua_State *L)
{
auto &builtinElements = GetElements();
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto &customElements = lsi->customElements;
int id = luaL_checkinteger(L, 1);
if (!SimulationData::CRef().IsElementOrNone(id))
{
return luaL_error(L, "Invalid element");
}
ByteString propertyName = tpt_lua_checkByteString(L, 2);
auto &properties = Element::GetProperties();
auto prop = std::find_if(properties.begin(), properties.end(), [&propertyName](StructProperty const &p) {
return p.Name == propertyName;
});
if (lua_gettop(L) > 2)
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
auto &elements = sd.elements;
if (prop != properties.end())
{
if (lua_type(L, 3) != LUA_TNIL)
{
if (prop->Type == StructProperty::TransitionType)
{
int type = luaL_checkinteger(L, 3);
if (!SimulationData::CRef().IsElementOrNone(type) && type != NT && type != ST)
{
return luaL_error(L, "Invalid element");
}
}
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop->Offset);
manageElementIdentifier(L, id, false);
LuaSetProperty(L, *prop, propertyAddress, 3);
manageElementIdentifier(L, id, true);
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
sd.graphicscache[id].isready = 0;
}
}
else if (propertyName == "Update")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
switch (luaL_optint(L, 4, 0))
{
case 2:
customElements[id].updateMode = UPDATE_BEFORE;
break;
case 1:
customElements[id].updateMode = UPDATE_REPLACE;
break;
default:
customElements[id].updateMode = UPDATE_AFTER;
break;
}
customElements[id].update.Assign(L, 3);
elements[id].Update = luaUpdateWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].update.Clear();
customElements[id].updateMode = UPDATE_AFTER;
elements[id].Update = builtinElements[id].Update;
}
}
else if (propertyName == "Graphics")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
customElements[id].graphics.Assign(L, 3);
elements[id].Graphics = luaGraphicsWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].graphics.Clear();
elements[id].Graphics = builtinElements[id].Graphics;
}
sd.graphicscache[id].isready = 0;
}
else if (propertyName == "Create")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
customElements[id].create.Assign(L, 3);
elements[id].Create = luaCreateWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].create.Clear();
elements[id].Create = builtinElements[id].Create;
}
}
else if (propertyName == "CreateAllowed")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
customElements[id].createAllowed.Assign(L, 3);
elements[id].CreateAllowed = luaCreateAllowedWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].createAllowed.Clear();
elements[id].CreateAllowed = builtinElements[id].CreateAllowed;
}
}
else if (propertyName == "ChangeType")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
customElements[id].changeType.Assign(L, 3);
elements[id].ChangeType = luaChangeTypeWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].changeType.Clear();
elements[id].ChangeType = builtinElements[id].ChangeType;
}
}
else if (propertyName == "CtypeDraw")
{
if (lua_type(L, 3) == LUA_TFUNCTION)
{
customElements[id].ctypeDraw.Assign(L, 3);
elements[id].CtypeDraw = luaCtypeDrawWrapper;
}
else if (lua_type(L, 3) == LUA_TBOOLEAN && !lua_toboolean(L, 3))
{
customElements[id].ctypeDraw.Clear();
elements[id].CtypeDraw = builtinElements[id].CtypeDraw;
}
}
else if (propertyName == "DefaultProperties")
{
setDefaultProperties(L, id, 3);
}
else
{
return luaL_error(L, "Invalid element property");
}
return 0;
}
else
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
if (prop != properties.end())
{
intptr_t propertyAddress = (intptr_t)(((const unsigned char*)&elements[id]) + prop->Offset);
LuaGetProperty(L, *prop, propertyAddress);
return 1;
}
else if (propertyName == "Identifier")
{
tpt_lua_pushByteString(L, elements[id].Identifier);
return 1;
}
else if (propertyName == "DefaultProperties")
{
getDefaultProperties(L, id);
return 1;
}
else
{
return luaL_error(L, "Invalid element property");
}
}
}
static int ffree(lua_State *L)
{
int id = luaL_checkinteger(L, 1);
ByteString identifier;
{
auto &sd = SimulationData::CRef();
if (!sd.IsElement(id))
{
return luaL_error(L, "Invalid element");
}
identifier = sd.elements[id].Identifier;
if (identifier.BeginsWith("DEFAULT_PT_"))
{
return luaL_error(L, "Cannot free default elements");
}
}
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
sd.elements[id].Enabled = false;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lsi->gameModel->BuildMenus();
lua_getglobal(L, "elements");
tpt_lua_pushByteString(L, identifier);
lua_pushnil(L);
lua_settable(L, -3);
lua_pop(L, 1);
return 0;
}
static int exists(lua_State *L)
{
auto &sd = SimulationData::CRef();
lua_pushboolean(L, sd.IsElement(luaL_checkinteger(L, 1)));
return 1;
}
static int loadDefault(lua_State *L)
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
auto &elements = sd.elements;
auto &builtinElements = GetElements();
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
{
auto loadDefaultOne = [L, &elements, &builtinElements](int id) {
lua_getglobal(L, "elements");
ByteString identifier = elements[id].Identifier;
tpt_lua_pushByteString(L, identifier);
lua_pushnil(L);
lua_settable(L, -3);
manageElementIdentifier(L, id, false);
if (id < (int)builtinElements.size())
elements[id] = builtinElements[id];
else
elements[id] = Element();
manageElementIdentifier(L, id, true);
tpt_lua_pushByteString(L, identifier);
lua_pushinteger(L, id);
lua_settable(L, -3);
lua_pop(L, 1);
};
int args = lua_gettop(L);
if (args)
{
luaL_checktype(L, 1, LUA_TNUMBER);
int id = lua_tointeger(L, 1);
if (id < 0 || id >= PT_NUM)
return luaL_error(L, "Invalid element");
loadDefaultOne(id);
}
else
{
for (int i = 0; i < PT_NUM; i++)
{
loadDefaultOne(i);
}
}
}
lsi->gameModel->BuildMenus();
for (auto moving = 0; moving < PT_NUM; ++moving)
{
for (auto into = 0; into < PT_NUM; ++into)
{
lsi->customCanMove[moving][into] = 0;
}
}
lsi->InitCustomCanMove();
sd.graphicscache = std::array<gcache_item, PT_NUM>();
return 0;
}
static int getByName(lua_State *L)
{
lua_pushinteger(L, SimulationData::CRef().GetParticleType(tpt_lua_checkByteString(L, 1)));
return 1;
}
void LuaElements::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(allocate),
LFUNC(element),
LFUNC(property),
LFUNC(exists),
LFUNC(loadDefault),
LFUNC(getByName),
#undef LFUNC
{ "free", ffree },
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONST(v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, #v)
LCONST(TYPE_PART);
LCONST(TYPE_LIQUID);
LCONST(TYPE_SOLID);
LCONST(TYPE_GAS);
LCONST(TYPE_ENERGY);
LCONST(PROP_CONDUCTS);
LCONST(PROP_BLACK);
LCONST(PROP_NEUTPENETRATE);
LCONST(PROP_NEUTABSORB);
LCONST(PROP_NEUTPASS);
LCONST(PROP_DEADLY);
LCONST(PROP_HOT_GLOW);
LCONST(PROP_LIFE);
LCONST(PROP_RADIOACTIVE);
LCONST(PROP_LIFE_DEC);
LCONST(PROP_LIFE_KILL);
LCONST(PROP_LIFE_KILL_DEC);
LCONST(PROP_SPARKSETTLE);
LCONST(PROP_NOAMBHEAT);
LCONST(PROP_NOCTYPEDRAW);
LCONST(SC_WALL);
LCONST(SC_ELEC);
LCONST(SC_POWERED);
LCONST(SC_SENSOR);
LCONST(SC_FORCE);
LCONST(SC_EXPLOSIVE);
LCONST(SC_GAS);
LCONST(SC_LIQUID);
LCONST(SC_POWDERS);
LCONST(SC_SOLIDS);
LCONST(SC_NUCLEAR);
LCONST(SC_SPECIAL);
LCONST(SC_LIFE);
LCONST(SC_TOOL);
LCONST(SC_DECO);
LCONST(UPDATE_AFTER);
LCONST(UPDATE_REPLACE);
LCONST(UPDATE_BEFORE);
LCONST(NUM_UPDATEMODES);
#undef LCONST
lua_pushvalue(L, -1);
lua_setglobal(L, "elements");
lua_setglobal(L, "elem");
for (int i = 0; i < PT_NUM; i++)
{
manageElementIdentifier(L, i, true);
}
}

86
src/lua/LuaEvent.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "LuaScriptInterface.h"
#include "common/VariantIndex.h"
#include "PowderToySDL.h"
static int fregister(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int eventType = luaL_checkinteger(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
if (eventType < 0 || eventType >= int(lsi->gameControllerEventHandlers.size()))
{
luaL_error(L, "Invalid event type: %i", lua_tointeger(L, 1));
}
lsi->gameControllerEventHandlers[eventType].Push(L);
auto length = lua_objlen(L, -1);
lua_pushvalue(L, 2);
lua_rawseti(L, -2, length + 1);
lua_pushvalue(L, 2);
return 1;
}
static int unregister(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int eventType = luaL_checkinteger(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
if (eventType < 0 || eventType >= int(lsi->gameControllerEventHandlers.size()))
{
luaL_error(L, "Invalid event type: %i", lua_tointeger(L, 1));
}
lsi->gameControllerEventHandlers[eventType].Push(L);
auto length = lua_objlen(L, -1);
int skip = 0;
for (auto i = 1U; i <= length; ++i)
{
lua_rawgeti(L, -1, i);
if (!skip && lua_equal(L, -1, 2))
{
skip = 1;
}
lua_pop(L, 1);
lua_rawgeti(L, -1, i + skip);
lua_rawseti(L, -2, i);
}
return 0;
}
static int getModifiers(lua_State *L)
{
lua_pushnumber(L, GetModifiers());
return 1;
}
void LuaEvent::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(unregister),
LFUNC(getModifiers),
#undef LFUNC
{ "register", fregister },
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LVICONST(id, v) lua_pushinteger(L, VariantIndex<GameControllerEvent, id>()); lua_setfield(L, -2, v)
LVICONST(TextInputEvent , "TEXTINPUT" );
LVICONST(TextEditingEvent , "TEXTEDITING" );
LVICONST(KeyPressEvent , "KEYPRESS" );
LVICONST(KeyReleaseEvent , "KEYRELEASE" );
LVICONST(MouseDownEvent , "MOUSEDOWN" );
LVICONST(MouseUpEvent , "MOUSEUP" );
LVICONST(MouseMoveEvent , "MOUSEMOVE" );
LVICONST(MouseWheelEvent , "MOUSEWHEEL" );
LVICONST(TickEvent , "TICK" );
LVICONST(BlurEvent , "BLUR" );
LVICONST(CloseEvent , "CLOSE" );
LVICONST(BeforeSimEvent , "BEFORESIM" );
LVICONST(AfterSimEvent , "AFTERSIM" );
LVICONST(BeforeSimDrawEvent, "BEFORESIMDRAW");
LVICONST(AfterSimDrawEvent , "AFTERSIMDRAW" );
#undef LVICONST
lua_pushvalue(L, -1);
lua_setglobal(L, "event");
lua_setglobal(L, "evt");
}

119
src/lua/LuaFileSystem.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "LuaScriptInterface.h"
#include "common/platform/Platform.h"
static int list(lua_State *L)
{
auto directoryName = tpt_lua_checkByteString(L, 1);
lua_newtable(L);
int index = 0;
for (auto &name : Platform::DirectorySearch(directoryName, "", {}))
{
if (name != "." && name != "..")
{
index += 1;
tpt_lua_pushByteString(L, name);
lua_rawseti(L, -2, index);
}
}
return 1;
}
static int exists(lua_State *L)
{
auto filename = tpt_lua_checkByteString(L, 1);
bool ret = Platform::Stat(filename);
lua_pushboolean(L, ret);
return 1;
}
static int isFile(lua_State *L)
{
auto filename = tpt_lua_checkByteString(L, 1);
bool ret = Platform::FileExists(filename);
lua_pushboolean(L, ret);
return 1;
}
static int isDirectory(lua_State *L)
{
auto dirname = tpt_lua_checkByteString(L, 1);
bool ret = Platform::DirectoryExists(dirname);
lua_pushboolean(L, ret);
return 1;
}
static int isLink(lua_State *L)
{
auto dirname = tpt_lua_checkByteString(L, 1);
bool ret = Platform::IsLink(dirname);
lua_pushboolean(L, ret);
return 1;
}
static int makeDirectory(lua_State *L)
{
auto dirname = tpt_lua_checkByteString(L, 1);
int ret = 0;
ret = Platform::MakeDirectory(dirname);
lua_pushboolean(L, ret);
return 1;
}
static int removeDirectory(lua_State *L)
{
auto directory = tpt_lua_checkByteString(L, 1);
bool ret = Platform::DeleteDirectory(directory);
lua_pushboolean(L, ret);
return 1;
}
static int removeFile(lua_State *L)
{
auto filename = tpt_lua_checkByteString(L, 1);
lua_pushboolean(L, Platform::RemoveFile(filename));
return 1;
}
static int move(lua_State *L)
{
auto filename = tpt_lua_checkByteString(L, 1);
auto newFilename = tpt_lua_checkByteString(L, 2);
bool replace = lua_toboolean(L, 3);
lua_pushboolean(L, Platform::RenameFile(filename, newFilename, replace));
return 1;
}
static int copy(lua_State *L)
{
auto filename = tpt_lua_checkByteString(L, 1);
auto newFilename = tpt_lua_checkByteString(L, 2);
std::vector<char> fileData;
lua_pushboolean(L, Platform::ReadFile(fileData, filename) && Platform::WriteFile(fileData, newFilename));
return 1;
}
void LuaFileSystem::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(list),
LFUNC(exists),
LFUNC(isFile),
LFUNC(isDirectory),
LFUNC(isLink),
LFUNC(makeDirectory),
LFUNC(removeDirectory),
LFUNC(removeFile),
LFUNC(move),
LFUNC(copy),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
lua_pushvalue(L, -1);
lua_setglobal(L, "fileSystem");
lua_setglobal(L, "fs");
}

307
src/lua/LuaGraphics.cpp Normal file
View File

@ -0,0 +1,307 @@
#include "LuaScriptInterface.h"
#include "graphics/Graphics.h"
#include "graphics/Renderer.h"
static int32_t int32Truncate(double n)
{
if (n >= 0x1p31)
{
n -= 0x1p32;
}
return int32_t(n);
}
static std::variant<Graphics *, Renderer *> currentGraphics()
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi->eventTraits & eventTraitSimGraphics)
{
return lsi->ren;
}
return lsi->g;
}
static int textSize(lua_State *L)
{
auto text = tpt_lua_optString(L, 1, "");
auto size = Graphics::TextSize(text);
lua_pushinteger(L, size.X);
lua_pushinteger(L, size.Y);
return 2;
}
static int drawText(lua_State *L)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
auto text = tpt_lua_optString(L, 3, "");
int r = luaL_optint(L, 4, 255);
int g = luaL_optint(L, 5, 255);
int b = luaL_optint(L, 6, 255);
int a = luaL_optint(L, 7, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x, y, r, g, b, a, &text](auto p) {
p->BlendText({ x, y }, text, RGBA<uint8_t>(r, g, b, a));
}, currentGraphics());
return 0;
}
static int drawPixel(lua_State *L)
{
auto x = luaL_optint(L, 1, 0);
auto y = luaL_optint(L, 2, 0);
auto r = luaL_optint(L, 3, 255);
auto g = luaL_optint(L, 4, 255);
auto b = luaL_optint(L, 5, 255);
auto a = luaL_optint(L, 6, 255);
if (r < 0 ) r = 0 ;
else if (r > 255) r = 255;
if (g < 0 ) g = 0 ;
else if (g > 255) g = 255;
if (b < 0 ) b = 0 ;
else if (b > 255) b = 255;
if (a < 0 ) a = 0 ;
else if (a > 255) a = 255;
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lsi->g->BlendPixel({ x, y }, RGBA<uint8_t>(r, g, b, a));
return 0;
}
static int drawLine(lua_State *L)
{
int x1 = lua_tointeger(L, 1);
int y1 = lua_tointeger(L, 2);
int x2 = lua_tointeger(L, 3);
int y2 = lua_tointeger(L, 4);
int r = luaL_optint(L, 5, 255);
int g = luaL_optint(L, 6, 255);
int b = luaL_optint(L, 7, 255);
int a = luaL_optint(L, 8, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x1, y1, x2, y2, r, g, b, a](auto p) {
if (a == 255)
{
p->DrawLine({ x1, y1 }, { x2, y2 }, RGB<uint8_t>(r, g, b));
}
else
{
p->BlendLine({ x1, y1 }, { x2, y2 }, RGBA<uint8_t>(r, g, b, a));
}
}, currentGraphics());
return 0;
}
static int drawRect(lua_State *L)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
int width = lua_tointeger(L, 3);
int height = lua_tointeger(L, 4);
int r = luaL_optint(L, 5, 255);
int g = luaL_optint(L, 6, 255);
int b = luaL_optint(L, 7, 255);
int a = luaL_optint(L, 8, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x, y, width, height, r, g, b, a](auto p) {
if (a == 255)
{
p->DrawRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGB<uint8_t>(r, g, b));
}
else
{
p->BlendRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
}
}, currentGraphics());
return 0;
}
static int fillRect(lua_State *L)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
int width = lua_tointeger(L, 3);
int height = lua_tointeger(L, 4);
int r = luaL_optint(L, 5, 255);
int g = luaL_optint(L, 6, 255);
int b = luaL_optint(L, 7, 255);
int a = luaL_optint(L, 8, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x, y, width, height, r, g, b, a](auto p) {
if (a == 255)
{
p->DrawFilledRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGB<uint8_t>(r, g, b));
}
else
{
p->BlendFilledRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
}
}, currentGraphics());
return 0;
}
static int drawCircle(lua_State *L)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
int rx = lua_tointeger(L, 3);
int ry = lua_tointeger(L, 4);
int r = luaL_optint(L, 5, 255);
int g = luaL_optint(L, 6, 255);
int b = luaL_optint(L, 7, 255);
int a = luaL_optint(L, 8, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
p->BlendEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
}, currentGraphics());
return 0;
}
static int fillCircle(lua_State *L)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
int rx = lua_tointeger(L, 3);
int ry = lua_tointeger(L, 4);
int r = luaL_optint(L, 5, 255);
int g = luaL_optint(L, 6, 255);
int b = luaL_optint(L, 7, 255);
int a = luaL_optint(L, 8, 255);
if (r<0) r = 0;
else if (r>255) r = 255;
if (g<0) g = 0;
else if (g>255) g = 255;
if (b<0) b = 0;
else if (b>255) b = 255;
if (a<0) a = 0;
else if (a>255) a = 255;
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
p->BlendFilledEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
}, currentGraphics());
return 0;
}
static int getColors(lua_State *L)
{
unsigned int color = int32Truncate(lua_tonumber(L, 1));
int a = color >> 24;
int r = (color >> 16)&0xFF;
int g = (color >> 8)&0xFF;
int b = color&0xFF;
lua_pushinteger(L, r);
lua_pushinteger(L, g);
lua_pushinteger(L, b);
lua_pushinteger(L, a);
return 4;
}
static int getHexColor(lua_State *L)
{
int r = lua_tointeger(L, 1);
int g = lua_tointeger(L, 2);
int b = lua_tointeger(L, 3);
int a = 0;
if (lua_gettop(L) >= 4)
a = lua_tointeger(L, 4);
unsigned int color = (a<<24) + (r<<16) + (g<<8) + b;
lua_pushinteger(L, color);
return 1;
}
static int setClipRect(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi->eventTraits & eventTraitSimGraphics)
{
return luaL_error(L, "simulation graphics do not support clip rects");
}
int x = luaL_optinteger(L, 1, 0);
int y = luaL_optinteger(L, 2, 0);
int w = luaL_optinteger(L, 3, WINDOWW);
int h = luaL_optinteger(L, 4, WINDOWH);
auto rect = RectSized(Vec2(x, y), Vec2(w, h));
lsi->g->SwapClipRect(rect);
lua_pushinteger(L, rect.TopLeft.X);
lua_pushinteger(L, rect.TopLeft.Y);
lua_pushinteger(L, rect.Size().X);
lua_pushinteger(L, rect.Size().Y);
return 4;
}
void LuaGraphics::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(textSize),
LFUNC(drawText),
LFUNC(drawPixel),
LFUNC(drawLine),
LFUNC(drawRect),
LFUNC(fillRect),
LFUNC(drawCircle),
LFUNC(fillCircle),
LFUNC(getColors),
LFUNC(getHexColor),
LFUNC(setClipRect),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONSTAS(k, v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, k)
LCONSTAS("WIDTH", WINDOWW);
LCONSTAS("HEIGHT", WINDOWH);
#undef LCONSTAS
lua_pushvalue(L, -1);
lua_setglobal(L, "graphics");
lua_setglobal(L, "gfx");
}

View File

@ -1,4 +1,4 @@
#include "LuaHttp.h"
#include "LuaScriptInterface.h"
#include "client/http/Request.h"
#include "client/Client.h"
#include "json/json.h"
@ -46,16 +46,16 @@ private:
}
public:
static int Make(lua_State *l, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const http::PostData &postData, const std::vector<http::Header> &headers)
static int Make(lua_State *L, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const http::PostData &postData, const std::vector<http::Header> &headers)
{
auto authUser = Client::Ref().GetAuthUser();
if (type == getAuthToken && !authUser.UserID)
{
lua_pushnil(l);
lua_pushliteral(l, "not authenticated");
lua_pushnil(L);
lua_pushliteral(L, "not authenticated");
return 2;
}
auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle));
auto *rh = (RequestHandle *)lua_newuserdata(L, sizeof(RequestHandle));
if (!rh)
{
return 0;
@ -80,8 +80,8 @@ public:
rh->request->AuthHeaders(ByteString::Build(authUser.UserID), authUser.SessionID);
}
rh->request->Start();
luaL_newmetatable(l, "HTTPRequest");
lua_setmetatable(l, -2);
luaL_newmetatable(L, "HTTPRequest");
lua_setmetatable(L, -2);
return 1;
}
@ -158,48 +158,48 @@ public:
}
};
static int http_request_gc(lua_State *l)
static int HTTPRequest_gc(lua_State *L)
{
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
auto *rh = (RequestHandle *)luaL_checkudata(L, 1, "HTTPRequest");
rh->~RequestHandle();
return 0;
}
static int http_request_status(lua_State *l)
static int HTTPRequest_status(lua_State *L)
{
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
auto *rh = (RequestHandle *)luaL_checkudata(L, 1, "HTTPRequest");
if (rh->Dead())
{
lua_pushliteral(l, "dead");
lua_pushliteral(L, "dead");
}
else if (rh->Done())
{
lua_pushliteral(l, "done");
lua_pushliteral(L, "done");
}
else
{
lua_pushliteral(l, "running");
lua_pushliteral(L, "running");
}
return 1;
}
static int http_request_progress(lua_State *l)
static int HTTPRequest_progress(lua_State *L)
{
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
auto *rh = (RequestHandle *)luaL_checkudata(L, 1, "HTTPRequest");
if (!rh->Dead())
{
int64_t total, done;
rh->Progress(&total, &done);
lua_pushinteger(l, total);
lua_pushinteger(l, done);
lua_pushinteger(L, total);
lua_pushinteger(L, done);
return 2;
}
return 0;
}
static int http_request_cancel(lua_State *l)
static int HTTPRequest_cancel(lua_State *L)
{
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
auto *rh = (RequestHandle *)luaL_checkudata(L, 1, "HTTPRequest");
if (!rh->Dead())
{
rh->Cancel();
@ -207,33 +207,33 @@ static int http_request_cancel(lua_State *l)
return 0;
}
static int http_request_finish(lua_State *l)
static int HTTPRequest_finish(lua_State *L)
{
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
auto *rh = (RequestHandle *)luaL_checkudata(L, 1, "HTTPRequest");
if (!rh->Dead())
{
std::vector<http::Header> headers;
auto [ status, data ] = rh->Finish(headers);
tpt_lua_pushByteString(l, data);
lua_pushinteger(l, status);
lua_newtable(l);
tpt_lua_pushByteString(L, data);
lua_pushinteger(L, status);
lua_newtable(L);
for (auto i = 0; i < int(headers.size()); ++i)
{
lua_newtable(l);
lua_pushlstring(l, headers[i].name.data(), headers[i].name.size());
lua_rawseti(l, -2, 1);
lua_pushlstring(l, headers[i].value.data(), headers[i].value.size());
lua_rawseti(l, -2, 2);
lua_rawseti(l, -2, i + 1);
lua_newtable(L);
lua_pushlstring(L, headers[i].name.data(), headers[i].name.size());
lua_rawseti(L, -2, 1);
lua_pushlstring(L, headers[i].value.data(), headers[i].value.size());
lua_rawseti(L, -2, 2);
lua_rawseti(L, -2, i + 1);
}
return 3;
}
return 0;
}
static int http_request(lua_State *l, bool isPost)
static int request(lua_State *L, bool isPost)
{
ByteString uri = tpt_lua_checkByteString(l, 1);
ByteString uri = tpt_lua_checkByteString(L, 1);
http::PostData postData;
auto headersIndex = 2;
auto verbIndex = 3;
@ -242,152 +242,160 @@ static int http_request(lua_State *l, bool isPost)
{
headersIndex += 1;
verbIndex += 1;
if (lua_isstring(l, 2))
if (lua_isstring(L, 2))
{
postData = tpt_lua_toByteString(l, 2);
postData = tpt_lua_toByteString(L, 2);
}
else if (lua_istable(l, 2))
else if (lua_istable(L, 2))
{
postData = http::FormData{};
auto &formData = std::get<http::FormData>(postData);
auto size = lua_objlen(l, 2);
auto size = lua_objlen(L, 2);
if (size)
{
for (auto i = 0U; i < size; ++i)
{
lua_rawgeti(l, 2, i + 1);
if (!lua_istable(l, -1))
lua_rawgeti(L, 2, i + 1);
if (!lua_istable(L, -1))
{
luaL_error(l, "form item %i is not a table", i + 1);
luaL_error(L, "form item %i is not a table", i + 1);
}
lua_rawgeti(l, -1, 1);
if (!lua_isstring(l, -1))
lua_rawgeti(L, -1, 1);
if (!lua_isstring(L, -1))
{
luaL_error(l, "name of form item %i is not a string", i + 1);
luaL_error(L, "name of form item %i is not a string", i + 1);
}
auto name = tpt_lua_toByteString(l, -1);
lua_pop(l, 1);
lua_rawgeti(l, -1, 2);
if (!lua_isstring(l, -1))
auto name = tpt_lua_toByteString(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
if (!lua_isstring(L, -1))
{
luaL_error(l, "value of form item %i is not a string", i + 1);
luaL_error(L, "value of form item %i is not a string", i + 1);
}
auto value = tpt_lua_toByteString(l, -1);
lua_pop(l, 1);
auto value = tpt_lua_toByteString(L, -1);
lua_pop(L, 1);
std::optional<ByteString> filename;
lua_rawgeti(l, -1, 3);
if (!lua_isnoneornil(l, -1))
lua_rawgeti(L, -1, 3);
if (!lua_isnoneornil(L, -1))
{
if (!lua_isstring(l, -1))
if (!lua_isstring(L, -1))
{
luaL_error(l, "filename of form item %i is not a string", i + 1);
luaL_error(L, "filename of form item %i is not a string", i + 1);
}
filename = tpt_lua_toByteString(l, -1);
filename = tpt_lua_toByteString(L, -1);
}
lua_pop(l, 1);
lua_pop(L, 1);
formData.push_back({ name, value, filename });
lua_pop(l, 1);
lua_pop(L, 1);
}
}
else
{
lua_pushnil(l);
while (lua_next(l, 2))
lua_pushnil(L);
while (lua_next(L, 2))
{
lua_pushvalue(l, -2);
formData.push_back({ tpt_lua_toByteString(l, -1), tpt_lua_toByteString(l, -2) });
lua_pop(l, 2);
lua_pushvalue(L, -2);
formData.push_back({ tpt_lua_toByteString(L, -1), tpt_lua_toByteString(L, -2) });
lua_pop(L, 2);
}
}
}
}
std::vector<http::Header> headers;
if (lua_istable(l, headersIndex))
if (lua_istable(L, headersIndex))
{
auto size = lua_objlen(l, headersIndex);
auto size = lua_objlen(L, headersIndex);
if (size)
{
for (auto i = 0U; i < size; ++i)
{
lua_rawgeti(l, headersIndex, i + 1);
if (!lua_istable(l, -1))
lua_rawgeti(L, headersIndex, i + 1);
if (!lua_istable(L, -1))
{
luaL_error(l, "header %i is not a table", i + 1);
luaL_error(L, "header %i is not a table", i + 1);
}
lua_rawgeti(l, -1, 1);
if (!lua_isstring(l, -1))
lua_rawgeti(L, -1, 1);
if (!lua_isstring(L, -1))
{
luaL_error(l, "name of header %i is not a string", i + 1);
luaL_error(L, "name of header %i is not a string", i + 1);
}
auto name = tpt_lua_toByteString(l, -1);
lua_pop(l, 1);
lua_rawgeti(l, -1, 2);
if (!lua_isstring(l, -1))
auto name = tpt_lua_toByteString(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
if (!lua_isstring(L, -1))
{
luaL_error(l, "value of header %i is not a string", i + 1);
luaL_error(L, "value of header %i is not a string", i + 1);
}
auto value = tpt_lua_toByteString(l, -1);
lua_pop(l, 1);
auto value = tpt_lua_toByteString(L, -1);
lua_pop(L, 1);
headers.push_back({ name, value });
lua_pop(l, 1);
lua_pop(L, 1);
}
}
else
{
// old dictionary format
lua_pushnil(l);
while (lua_next(l, headersIndex))
lua_pushnil(L);
while (lua_next(L, headersIndex))
{
lua_pushvalue(l, -2);
headers.push_back({ tpt_lua_toByteString(l, -1), tpt_lua_toByteString(l, -2) });
lua_pop(l, 2);
lua_pushvalue(L, -2);
headers.push_back({ tpt_lua_toByteString(L, -1), tpt_lua_toByteString(L, -2) });
lua_pop(L, 2);
}
}
}
auto verb = tpt_lua_optByteString(l, verbIndex, "");
return RequestHandle::Make(l, uri, isPost, verb, RequestHandle::normal, postData, headers);
auto verb = tpt_lua_optByteString(L, verbIndex, "");
return RequestHandle::Make(L, uri, isPost, verb, RequestHandle::normal, postData, headers);
}
static int http_get_auth_token(lua_State *l)
static int getAuthToken(lua_State *L)
{
return RequestHandle::Make(l, ByteString::Build(SCHEME, SERVER, "/ExternalAuth.api?Action=Get&Audience=", format::URLEncode(tpt_lua_checkByteString(l, 1))), false, {}, RequestHandle::getAuthToken, {}, {});
return RequestHandle::Make(L, ByteString::Build(SCHEME, SERVER, "/ExternalAuth.api?Action=Get&Audience=", format::URLEncode(tpt_lua_checkByteString(L, 1))), false, {}, RequestHandle::getAuthToken, {}, {});
}
static int http_get(lua_State * l)
static int get(lua_State *L)
{
return http_request(l, false);
return request(L, false);
}
static int http_post(lua_State * l)
static int post(lua_State *L)
{
return http_request(l, true);
return request(L, true);
}
void LuaHttp::Open(lua_State *l)
void LuaHttp::Open(lua_State *L)
{
luaL_newmetatable(l, "HTTPRequest");
lua_pushcfunction(l, http_request_gc);
lua_setfield(l, -2, "__gc");
lua_newtable(l);
struct luaL_Reg httpRequestIndexMethods[] = {
{ "status", http_request_status },
{ "progress", http_request_progress },
{ "cancel", http_request_cancel },
{ "finish", http_request_finish },
{ NULL, NULL }
};
luaL_register(l, NULL, httpRequestIndexMethods);
lua_setfield(l, -2, "__index");
lua_pop(l, 1);
lua_newtable(l);
struct luaL_Reg httpMethods[] = {
{ "get", http_get },
{ "post", http_post },
{ "getAuthToken", http_get_auth_token },
{ NULL, NULL }
};
luaL_register(l, NULL, httpMethods);
lua_setglobal(l, "http");
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, HTTPRequest_ ## v }
LFUNC(status),
LFUNC(progress),
LFUNC(cancel),
LFUNC(finish),
#undef LFUNC
{ NULL, NULL }
};
luaL_newmetatable(L, "HTTPRequest");
lua_pushcfunction(L, HTTPRequest_gc);
lua_setfield(L, -2, "__gc");
lua_newtable(L);
luaL_register(L, NULL, reg);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
}
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(get),
LFUNC(post),
LFUNC(getAuthToken),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
lua_setglobal(L, "http");
}
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "LuaCompat.h"
namespace LuaHttp
{
void Open(lua_State *l);
}

498
src/lua/LuaInterface.cpp Normal file
View File

@ -0,0 +1,498 @@
#include "LuaScriptInterface.h"
#include "gui/dialogues/ConfirmPrompt.h"
#include "gui/dialogues/ErrorMessage.h"
#include "gui/dialogues/InformationMessage.h"
#include "gui/dialogues/TextPrompt.h"
#include "gui/game/Brush.h"
#include "gui/game/GameController.h"
#include "gui/game/GameModel.h"
#include "gui/game/GameView.h"
#include "gui/game/Tool.h"
#include "gui/interface/Engine.h"
#include "LuaButton.h"
#include "LuaCheckbox.h"
#include "LuaLabel.h"
#include "LuaLuna.h"
#include "LuaProgressBar.h"
#include "LuaSDLKeys.h"
#include "LuaSlider.h"
#include "LuaTextbox.h"
#include "LuaWindow.h"
#include "prefs/GlobalPrefs.h"
#include "simulation/SimulationData.h"
template<class Type>
struct PickIfTypeHelper;
template<>
struct PickIfTypeHelper<String>
{
static constexpr auto LuaType = LUA_TSTRING;
static String Get(lua_State *L, int index) { return tpt_lua_checkString(L, index); }
};
template<>
struct PickIfTypeHelper<bool>
{
static constexpr auto LuaType = LUA_TBOOLEAN;
static bool Get(lua_State *L, int index) { return lua_toboolean(L, index); }
};
template<class Type>
static Type PickIfType(lua_State *L, int index, Type defaultValue)
{
return lua_type(L, index) == PickIfTypeHelper<Type>::LuaType ? PickIfTypeHelper<Type>::Get(L, index) : defaultValue;
}
static int beginMessageBox(lua_State *L)
{
auto title = PickIfType(L, 1, String("Title"));
auto message = PickIfType(L, 2, String("Message"));
auto large = PickIfType(L, 3, false);
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
cb->Assign(L, lua_gettop(L));
new InformationMessage(title, message, large, { [cb]() {
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto L = lsi->L;
cb->Push(L);
if (lua_isfunction(L, -1))
{
if (tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
lsi->Log(CommandInterface::LogError, LuaGetError());
}
}
else
{
lua_pop(L, 1);
}
} });
return 0;
}
static int beginThrowError(lua_State *L)
{
auto errorMessage = PickIfType(L, 1, String("Error text"));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
cb->Assign(L, lua_gettop(L));
new ErrorMessage("Error", errorMessage, { [cb]() {
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto L = lsi->L;
cb->Push(L);
if (lua_isfunction(L, -1))
{
if (tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
lsi->Log(CommandInterface::LogError, LuaGetError());
}
}
else
{
lua_pop(L, 1);
}
} });
return 0;
}
static int beginInput(lua_State *L)
{
auto title = PickIfType(L, 1, String("Title"));
auto prompt = PickIfType(L, 2, String("Enter some text:"));
auto text = PickIfType(L, 3, String(""));
auto shadow = PickIfType(L, 4, String(""));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
cb->Assign(L, lua_gettop(L));
auto handle = [cb](std::optional<String> input) {
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto L = lsi->L;
cb->Push(L);
if (lua_isfunction(L, -1))
{
if (input)
{
tpt_lua_pushString(L, *input);
}
else
{
lua_pushnil(L);
}
if (tpt_lua_pcall(L, 1, 0, 0, eventTraitNone))
{
lsi->Log(CommandInterface::LogError, LuaGetError());
}
}
else
{
lua_pop(L, 1);
}
};
new TextPrompt(title, prompt, text, shadow, false, { [handle](const String &input) {
handle(input);
}, [handle]() {
handle(std::nullopt);
} });
return 0;
}
static int beginConfirm(lua_State *L)
{
auto title = PickIfType(L, 1, String("Title"));
auto message = PickIfType(L, 2, String("Message"));
auto buttonText = PickIfType(L, 3, String("Confirm"));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
cb->Assign(L, lua_gettop(L));
auto handle = [cb](int result) {
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto L = lsi->L;
cb->Push(L);
if (lua_isfunction(L, -1))
{
lua_pushboolean(L, result);
if (tpt_lua_pcall(L, 1, 0, 0, eventTraitNone))
{
lsi->Log(CommandInterface::LogError, LuaGetError());
}
}
else
{
lua_pop(L, 1);
}
};
new ConfirmPrompt(title, message, { [handle]() {
handle(1);
}, [handle]() {
handle(0);
} }, buttonText);
return 0;
}
static int console(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushboolean(L, lsi->window != ui::Engine::Ref().GetWindow());
return 1;
}
if (lua_toboolean(L, 1))
lsi->gameController->ShowConsole();
else
lsi->gameController->HideConsole();
return 0;
}
static int brushID(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lua_gettop(L) < 1)
{
lua_pushnumber(L, lsi->gameModel->GetBrushID());
return 1;
}
auto index = luaL_checkint(L, 1);
if (index < 0 || index >= int(lsi->gameModel->BrushListSize()))
{
return luaL_error(L, "Invalid brush index %i", index);
}
lsi->gameModel->SetBrushID(index);
return 0;
}
static int brushRadius(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lua_gettop(L) < 1)
{
auto radius = lsi->gameModel->GetBrush().GetRadius();
lua_pushnumber(L, radius.X);
lua_pushnumber(L, radius.Y);
return 2;
}
lsi->gameModel->GetBrush().SetRadius({ luaL_checkint(L, 1), luaL_checkint(L, 2) });
return 0;
}
static int mousePosition(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto pos = lsi->gameController->GetView()->GetMousePosition();
lua_pushnumber(L, pos.X);
lua_pushnumber(L, pos.Y);
return 2;
}
static int activeTool(lua_State *L)
{ auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto index = luaL_checkint(L, 1);
if (index < 0 || index >= NUM_TOOLINDICES)
{
return luaL_error(L, "Invalid tool index %i", index);
}
if (lua_gettop(L) < 2)
{
tpt_lua_pushByteString(L, lsi->gameModel->GetActiveTool(index)->Identifier);
return 1;
}
auto identifier = tpt_lua_checkByteString(L, 2);
auto *tool = lsi->gameModel->GetToolFromIdentifier(identifier);
if (!tool)
{
return luaL_error(L, "Invalid tool identifier %s", identifier.c_str());
}
lsi->gameController->SetActiveTool(index, tool);
return 0;
}
static int addComponent(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
void *opaque = nullptr;
LuaComponent *luaComponent = nullptr;
if ((opaque = Luna<LuaButton>::tryGet(L, 1)))
luaComponent = Luna<LuaButton>::get(opaque);
else if ((opaque = Luna<LuaLabel>::tryGet(L, 1)))
luaComponent = Luna<LuaLabel>::get(opaque);
else if ((opaque = Luna<LuaTextbox>::tryGet(L, 1)))
luaComponent = Luna<LuaTextbox>::get(opaque);
else if ((opaque = Luna<LuaCheckbox>::tryGet(L, 1)))
luaComponent = Luna<LuaCheckbox>::get(opaque);
else if ((opaque = Luna<LuaSlider>::tryGet(L, 1)))
luaComponent = Luna<LuaSlider>::get(opaque);
else if ((opaque = Luna<LuaProgressBar>::tryGet(L, 1)))
luaComponent = Luna<LuaProgressBar>::get(opaque);
else
luaL_typerror(L, 1, "Component");
if (lsi->window && luaComponent)
{
auto ok = lsi->grabbedComponents.insert(std::make_pair(luaComponent, LuaSmartRef()));
if (ok.second)
{
auto it = ok.first;
it->second.Assign(L, 1);
it->first->owner_ref = it->second;
}
lsi->window->AddComponent(luaComponent->GetComponent());
}
return 0;
}
static int removeComponent(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
void *opaque = nullptr;
LuaComponent *luaComponent = nullptr;
if ((opaque = Luna<LuaButton>::tryGet(L, 1)))
luaComponent = Luna<LuaButton>::get(opaque);
else if ((opaque = Luna<LuaLabel>::tryGet(L, 1)))
luaComponent = Luna<LuaLabel>::get(opaque);
else if ((opaque = Luna<LuaTextbox>::tryGet(L, 1)))
luaComponent = Luna<LuaTextbox>::get(opaque);
else if ((opaque = Luna<LuaCheckbox>::tryGet(L, 1)))
luaComponent = Luna<LuaCheckbox>::get(opaque);
else if ((opaque = Luna<LuaSlider>::tryGet(L, 1)))
luaComponent = Luna<LuaSlider>::get(opaque);
else if ((opaque = Luna<LuaProgressBar>::tryGet(L, 1)))
luaComponent = Luna<LuaProgressBar>::get(opaque);
else
luaL_typerror(L, 1, "Component");
if(lsi->window && luaComponent)
{
ui::Component *component = luaComponent->GetComponent();
lsi->window->RemoveComponent(component);
auto it = lsi->grabbedComponents.find(luaComponent);
if (it != lsi->grabbedComponents.end())
{
it->second.Clear();
it->first->owner_ref = it->second;
lsi->grabbedComponents.erase(it);
}
}
return 0;
}
static int grabTextInput(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lsi->textInputRefcount += 1;
lsi->gameController->GetView()->DoesTextInput = lsi->textInputRefcount > 0;
return 0;
}
static int dropTextInput(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lsi->textInputRefcount -= 1;
lsi->gameController->GetView()->DoesTextInput = lsi->textInputRefcount > 0;
return 0;
}
static int textInputRect(lua_State *L)
{
int x = luaL_checkint(L, 1);
int y = luaL_checkint(L, 2);
int w = luaL_checkint(L, 3);
int h = luaL_checkint(L, 4);
ui::Engine::Ref().TextInputRect(ui::Point{ x, y }, ui::Point{ w, h });
return 0;
}
static int showWindow(lua_State *L)
{
LuaWindow * window = Luna<LuaWindow>::check(L, 1);
if(window && ui::Engine::Ref().GetWindow()!=window->GetWindow())
ui::Engine::Ref().ShowWindow(window->GetWindow());
return 0;
}
static int closeWindow(lua_State *L)
{
LuaWindow * window = Luna<LuaWindow>::check(L, 1);
if (window)
window->GetWindow()->CloseActiveWindow();
return 0;
}
static int perfectCircleBrush(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (!lua_gettop(L))
{
lua_pushboolean(L, lsi->gameModel->GetPerfectCircle());
return 1;
}
luaL_checktype(L, 1, LUA_TBOOLEAN);
lsi->gameModel->SetPerfectCircle(lua_toboolean(L, 1));
return 0;
}
static int activeMenu(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushinteger(L, lsi->gameModel->GetActiveMenu());
return 1;
}
int menuid = luaL_checkint(L, 1);
if (menuid >= 0 && menuid < SC_TOTAL)
lsi->gameController->SetActiveMenu(menuid);
else
return luaL_error(L, "Invalid menu");
return 0;
}
static int menuEnabled(lua_State *L)
{
int menusection = luaL_checkint(L, 1);
if (menusection < 0 || menusection >= SC_TOTAL)
return luaL_error(L, "Invalid menu");
int acount = lua_gettop(L);
if (acount == 1)
{
lua_pushboolean(L, SimulationData::CRef().msections[menusection].doshow);
return 1;
}
luaL_checktype(L, 2, LUA_TBOOLEAN);
int enabled = lua_toboolean(L, 2);
{
auto &sd = SimulationData::Ref();
sd.msections[menusection].doshow = enabled;
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lsi->gameModel->BuildMenus();
return 0;
}
static int numMenus(lua_State *L)
{
int acount = lua_gettop(L);
bool onlyEnabled = true;
if (acount > 0)
{
luaL_checktype(L, 1, LUA_TBOOLEAN);
onlyEnabled = lua_toboolean(L, 1);
}
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
lua_pushinteger(L, lsi->gameController->GetNumMenus(onlyEnabled));
return 1;
}
static int windowSize(lua_State *L)
{
auto &g = ui::Engine::Ref();
if (lua_gettop(L) < 1)
{
lua_pushinteger(L, g.GetScale());
lua_pushboolean(L, g.GetFullscreen());
return 2;
}
int scale = luaL_optint(L,1,1);
auto kiosk = lua_toboolean(L,2);
// TODO: handle this the same way as it's handled in PowderToySDL.cpp
// > maybe bind the maximum allowed scale to screen size somehow
if (scale < 1 || scale > 10)
{
scale = 1;
}
{
auto &prefs = GlobalPrefs::Ref();
Prefs::DeferWrite dw(prefs);
prefs.Set("Scale", scale);
prefs.Set("Fullscreen", kiosk);
}
g.SetScale(scale);
g.SetFullscreen(kiosk);
return 0;
}
void LuaInterface::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(showWindow),
LFUNC(closeWindow),
LFUNC(addComponent),
LFUNC(removeComponent),
LFUNC(grabTextInput),
LFUNC(dropTextInput),
LFUNC(textInputRect),
LFUNC(beginInput),
LFUNC(beginMessageBox),
LFUNC(beginConfirm),
LFUNC(beginThrowError),
LFUNC(activeMenu),
LFUNC(menuEnabled),
LFUNC(numMenus),
LFUNC(perfectCircleBrush),
LFUNC(console),
LFUNC(windowSize),
LFUNC(brushID),
LFUNC(brushRadius),
LFUNC(mousePosition),
LFUNC(activeTool),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONSTAS(k, v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, k)
LCONSTAS("MOUSEUP_NORMAL" , GameController::mouseUpNormal);
LCONSTAS("MOUSEUP_BLUR" , GameController::mouseUpBlur);
LCONSTAS("MOUSEUP_DRAWEND", GameController::mouseUpDrawEnd);
LCONSTAS("NUM_TOOLINDICES", NUM_TOOLINDICES);
#undef LCONSTAS
initLuaSDLKeys(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "interface");
lua_setglobal(L, "ui");
Luna<LuaWindow >::Register(L);
Luna<LuaButton >::Register(L);
Luna<LuaLabel >::Register(L);
Luna<LuaTextbox >::Register(L);
Luna<LuaCheckbox >::Register(L);
Luna<LuaSlider >::Register(L);
Luna<LuaProgressBar>::Register(L);
}

View File

@ -13,31 +13,31 @@ Luna<LuaLabel>::RegType LuaLabel::methods[] = {
{0, 0}
};
LuaLabel::LuaLabel(lua_State * l) :
LuaComponent(l)
LuaLabel::LuaLabel(lua_State *L) :
LuaComponent(L)
{
this->l = l;
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
String text = tpt_lua_optString(l, 5, "");
this->L = L;
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
String text = tpt_lua_optString(L, 5, "");
label = new ui::Label(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text);
component = label;
}
int LuaLabel::text(lua_State * l)
int LuaLabel::text(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
label->SetText(tpt_lua_checkString(l, 1));
label->SetText(tpt_lua_checkString(L, 1));
return 0;
}
else
{
tpt_lua_pushString(l, label->GetText());
tpt_lua_pushString(L, label->GetText());
return 1;
}
}

View File

@ -13,11 +13,11 @@ class LuaScriptInterface;
class LuaLabel: public LuaComponent
{
ui::Label * label;
int text(lua_State * l);
int text(lua_State *L);
public:
static const char className[];
static Luna<LuaLabel>::RegType methods[];
LuaLabel(lua_State * l);
LuaLabel(lua_State *L);
~LuaLabel();
};

View File

@ -54,7 +54,7 @@ public:
}
// get userdata from Lua stack and return pointer to T object
static T * check(lua_State * L, int narg)
static T * check(lua_State *L, int narg)
{
userdataType *ud = static_cast<userdataType*>(luaL_checkudata(L, narg, T::className));
if(!ud)
@ -62,7 +62,7 @@ public:
return ud->pT; // pointer to T object
}
static void * tryGet(lua_State * L, int narg)
static void * tryGet(lua_State *L, int narg)
{
if(checkType(L, narg, T::className))
{
@ -77,7 +77,7 @@ public:
}
}
static bool checkType (lua_State * L, int idx, const char *name)
static bool checkType (lua_State *L, int idx, const char *name)
{
// returns true if a userdata is of a certain type
int res;
@ -98,7 +98,7 @@ private:
Luna(); // hide default constructor
// member function dispatcher
static int thunk(lua_State * L)
static int thunk(lua_State *L)
{
// stack has userdata, followed by method args
T *obj = check(L, 1); // get 'self', or if you prefer, 'this'
@ -110,7 +110,7 @@ private:
// create a new T object and
// push onto the Lua stack a userdata containing a pointer to T object
static int new_T(lua_State * L)
static int new_T(lua_State *L)
{
if (!lua_gettop(L))
return 0;
@ -133,7 +133,7 @@ private:
return 0;
}
static int tostring_T (lua_State * L)
static int tostring_T (lua_State *L)
{
char buff[32];
userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));

300
src/lua/LuaMisc.cpp Normal file
View File

@ -0,0 +1,300 @@
#include "LuaScriptInterface.h"
#include "client/http/Request.h"
#include "common/platform/Platform.h"
#include "compat.lua.h"
#include "Config.h"
#include "gui/dialogues/ErrorMessage.h"
#include "gui/dialogues/InformationMessage.h"
#include "gui/game/GameController.h"
#include "gui/game/GameModel.h"
#include "gui/game/GameView.h"
#include "gui/interface/Engine.h"
static int getUserName(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi->gameModel->GetUser().UserID)
{
tpt_lua_pushByteString(L, lsi->gameModel->GetUser().Username);
return 1;
}
lua_pushliteral(L, "");
return 1;
}
static int installScriptManager(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi->scriptManagerDownload)
{
new ErrorMessage("Script download", "A script download is already pending");
return 0;
}
lsi->gameController->HideConsole();
if (ui::Engine::Ref().GetWindow() != lsi->gameController->GetView())
{
new ErrorMessage("Script download", "You must run this function from the console");
return 0;
}
lsi->scriptManagerDownload = std::make_unique<http::Request>(ByteString::Build(SCHEME, "starcatcher.us/scripts/main.lua?get=1"));
lsi->scriptManagerDownload->Start();
return 0;
}
void LuaMisc::Tick(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi->scriptManagerDownload && lsi->scriptManagerDownload->CheckDone())
{
struct Status
{
struct Ok
{
};
struct GetFailed
{
String error;
};
struct RunFailed
{
String error;
};
using Value = std::variant<
Ok,
GetFailed,
RunFailed
>;
Value value;
};
auto complete = [](Status status) {
if (std::get_if<Status::Ok>(&status.value))
{
new InformationMessage("Install script manager", "Script manager successfully installed", false);
}
if (auto *requestFailed = std::get_if<Status::GetFailed>(&status.value))
{
new ErrorMessage("Install script manager", "Failed to get script manager: " + requestFailed->error);
}
if (auto *runFailed = std::get_if<Status::RunFailed>(&status.value))
{
new ErrorMessage("Install script manager", "Failed to run script manager: " + runFailed->error);
}
};
try
{
auto ret = lsi->scriptManagerDownload->StatusCode();
auto scriptData = lsi->scriptManagerDownload->Finish().second;
if (!scriptData.size())
{
complete({ Status::GetFailed{ "Server did not return data" } });
return;
}
if (ret != 200)
{
complete({ Status::GetFailed{ ByteString(http::StatusText(ret)).FromUtf8() } });
return;
}
ByteString filename = "autorun.lua";
if (!Platform::WriteFile(std::vector<char>(scriptData.begin(), scriptData.end()), filename))
{
complete({ Status::GetFailed{ String::Build("Unable to write to ", filename.FromUtf8()) } });
return;
}
if (tpt_lua_dostring(L, ByteString::Build("dofile('", filename, "')")))
{
complete({ Status::RunFailed{ LuaGetError() } });
return;
}
complete({ Status::Ok{} });
}
catch (const http::RequestError &ex)
{
complete({ Status::GetFailed{ ByteString(ex.what()).FromUtf8() } });
}
lsi->scriptManagerDownload.reset();
}
}
static int flog(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int args = lua_gettop(L);
String text;
bool hasText = false;
for(int i = 1; i <= args; i++)
{
LuaToLoggableString(L, -1);
if (hasText)
{
text = tpt_lua_optString(L, -1, "") + ", " + text;
}
else
{
text = tpt_lua_optString(L, -1, "");
hasText = true;
}
lua_pop(L, 2);
}
if (lsi->currentCommand)
{
auto lastError = lsi->GetLastError();
if (lsi->luacon_hasLastError)
lastError += "; ";
lastError += text;
lsi->SetLastError(lastError);
lsi->luacon_hasLastError = true;
}
else
lsi->Log(CommandInterface::LogNotice, text);
return 0;
}
static int screenshot(lua_State *L)
{
int captureUI = luaL_optint(L, 1, 0);
int fileType = luaL_optint(L, 2, 0);
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
ByteString filename = lsi->gameController->TakeScreenshot(captureUI, fileType);
if (filename.size())
{
tpt_lua_pushByteString(L, filename);
return 1;
}
return 0;
}
static int record(lua_State *L)
{
if (!lua_isboolean(L, -1))
return luaL_typerror(L, 1, lua_typename(L, LUA_TBOOLEAN));
bool record = lua_toboolean(L, -1);
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int recordingFolder = lsi->gameController->Record(record);
lua_pushinteger(L, recordingFolder);
return 1;
}
static int compatChunk(lua_State *L)
{
lua_pushlstring(L, reinterpret_cast<const char *>(compat_lua), compat_lua_size);
return 1;
}
static int debug(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushinteger(L, lsi->gameController->GetDebugFlags());
return 1;
}
int debugFlags = luaL_optint(L, 1, 0);
lsi->gameController->SetDebugFlags(debugFlags);
return 0;
}
static int fpsCap(lua_State *L)
{
int acount = lua_gettop(L);
if (acount == 0)
{
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
if (std::holds_alternative<FpsLimitVsync>(fpsLimit))
{
lua_pushliteral(L, "vsync");
}
else if (std::holds_alternative<FpsLimitNone>(fpsLimit))
{
lua_pushnumber(L, 2);
}
else
{
lua_pushnumber(L, std::get<FpsLimitExplicit>(fpsLimit).value);
}
return 1;
}
if (lua_isstring(L, 1) && byteStringEqualsLiteral(tpt_lua_toByteString(L, 1), "vsync"))
{
ui::Engine::Ref().SetFpsLimit(FpsLimitVsync{});
return 0;
}
float fpscap = luaL_checknumber(L, 1);
if (fpscap < 2)
{
return luaL_error(L, "fps cap too small");
}
if (fpscap == 2)
{
ui::Engine::Ref().SetFpsLimit(FpsLimitNone{});
return 0;
}
ui::Engine::Ref().SetFpsLimit(FpsLimitExplicit{ fpscap });
return 0;
}
static int drawCap(lua_State *L)
{
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushinteger(L, ui::Engine::Ref().GetDrawingFrequencyLimit());
return 1;
}
int drawcap = luaL_checkint(L, 1);
if(drawcap < 0)
return luaL_error(L, "draw cap too small");
ui::Engine::Ref().SetDrawingFrequencyLimit(drawcap);
return 0;
}
void LuaMisc::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(getUserName),
LFUNC(installScriptManager),
LFUNC(screenshot),
LFUNC(record),
LFUNC(debug),
LFUNC(fpsCap),
LFUNC(drawCap),
LFUNC(compatChunk),
#undef LFUNC
{ "log", flog },
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONST(v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, #v)
LCONST(DEBUG_PARTS);
LCONST(DEBUG_ELEMENTPOP);
LCONST(DEBUG_LINES);
LCONST(DEBUG_PARTICLE);
LCONST(DEBUG_SURFNORM);
#undef LCONST
{
lua_newtable(L);
#define LCONSTAS(k, v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, k)
LCONSTAS("major" , DISPLAY_VERSION[0]);
LCONSTAS("minor" , DISPLAY_VERSION[1]);
LCONSTAS("build" , APP_VERSION.build);
LCONSTAS("upstreamMajor", UPSTREAM_VERSION.displayVersion[0]);
LCONSTAS("upstreamMinor", UPSTREAM_VERSION.displayVersion[1]);
LCONSTAS("upstreamBuild", UPSTREAM_VERSION.build);
LCONSTAS("modid" , MOD_ID);
#undef LCONSTAS
lua_pushboolean(L, SNAPSHOT);
lua_setfield(L, -2, "snapshot");
lua_pushboolean(L, BETA);
lua_setfield(L, -2, "beta");
auto vcsTag = ByteString(VCS_TAG);
if (vcsTag.size())
{
tpt_lua_pushByteString(L, vcsTag);
lua_setfield(L, -2, "vcstag");
}
lua_setfield(L, -2, "version");
}
lua_setglobal(L, "tpt");
}

80
src/lua/LuaPlatform.cpp Normal file
View File

@ -0,0 +1,80 @@
#include "LuaScriptInterface.h"
#include "common/platform/Platform.h"
#include "Config.h"
#include "PowderToySDL.h"
static int platform(lua_State *L)
{
tpt_lua_pushByteString(L, IDENT_PLATFORM);
return 1;
}
static int ident(lua_State *L)
{
tpt_lua_pushByteString(L, IDENT);
return 1;
}
static int releaseType(lua_State *L)
{
tpt_lua_pushByteString(L, ByteString(1, IDENT_RELTYPE));
return 1;
}
static int exeName(lua_State *L)
{
ByteString name = Platform::ExecutableName();
if (name.length())
tpt_lua_pushByteString(L, name);
else
luaL_error(L, "Error, could not get executable name");
return 1;
}
static int restart(lua_State *L)
{
Platform::DoRestart();
return 0;
}
static int openLink(lua_State *L)
{
auto uri = tpt_lua_checkByteString(L, 1);
Platform::OpenURI(uri);
return 0;
}
static int clipboardCopy(lua_State *L)
{
tpt_lua_pushByteString(L, ClipboardPull());
return 1;
}
static int clipboardPaste(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
ClipboardPush(tpt_lua_optByteString(L, 1, ""));
return 0;
}
void LuaPlatform::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(platform),
LFUNC(ident),
LFUNC(releaseType),
LFUNC(exeName),
LFUNC(restart),
LFUNC(openLink),
LFUNC(clipboardCopy),
LFUNC(clipboardPaste),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
lua_pushvalue(L, -1);
lua_setglobal(L, "platform");
lua_setglobal(L, "plat");
}

View File

@ -14,46 +14,46 @@ Luna<LuaProgressBar>::RegType LuaProgressBar::methods[] = {
{0, 0}
};
LuaProgressBar::LuaProgressBar(lua_State * l) :
LuaComponent(l)
LuaProgressBar::LuaProgressBar(lua_State *L) :
LuaComponent(L)
{
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
int value = luaL_optinteger(l, 5, 0);
String status = tpt_lua_optString(l, 6, "");
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
int value = luaL_optinteger(L, 5, 0);
String status = tpt_lua_optString(L, 6, "");
progressBar = new ui::ProgressBar(ui::Point(posX, posY), ui::Point(sizeX, sizeY), value, status);
component = progressBar;
}
int LuaProgressBar::progress(lua_State * l)
int LuaProgressBar::progress(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
progressBar->SetProgress(lua_tointeger(l, 1));
progressBar->SetProgress(lua_tointeger(L, 1));
return 0;
}
else
{
lua_pushinteger(l, progressBar->GetProgress());
lua_pushinteger(L, progressBar->GetProgress());
return 1;
}
}
int LuaProgressBar::status(lua_State * l)
int LuaProgressBar::status(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
progressBar->SetStatus(tpt_lua_checkString(l, 1));
progressBar->SetStatus(tpt_lua_checkString(L, 1));
return 0;
}
else
{
tpt_lua_pushString(l, progressBar->GetStatus());
tpt_lua_pushString(L, progressBar->GetStatus());
return 1;
}
}

View File

@ -13,12 +13,12 @@ class LuaScriptInterface;
class LuaProgressBar: public LuaComponent
{
ui::ProgressBar * progressBar;
int progress(lua_State * l);
int status(lua_State * l);
int progress(lua_State *L);
int status(lua_State *L);
public:
static const char className[];
static Luna<LuaProgressBar>::RegType methods[];
LuaProgressBar(lua_State * l);
LuaProgressBar(lua_State *L);
~LuaProgressBar();
};

341
src/lua/LuaRenderer.cpp Normal file
View File

@ -0,0 +1,341 @@
#include "LuaScriptInterface.h"
#include "gui/game/GameController.h"
#include "gui/game/GameModel.h"
#include "graphics/Renderer.h"
#include "simulation/ElementGraphics.h"
static int renderModes(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int args = lua_gettop(L);
if(args)
{
int size = 0;
luaL_checktype(L, 1, LUA_TTABLE);
size = lua_objlen(L, 1);
std::vector<unsigned int> renderModes;
for(int i = 1; i <= size; i++)
{
lua_rawgeti(L, 1, i);
renderModes.push_back(lua_tointeger(L, -1));
lua_pop(L, 1);
}
lsi->ren->SetRenderMode(renderModes);
return 0;
}
else
{
lua_newtable(L);
std::vector<unsigned int> renderModes = lsi->ren->GetRenderMode();
int i = 1;
for(std::vector<unsigned int>::iterator iter = renderModes.begin(), end = renderModes.end(); iter != end; ++iter)
{
lua_pushinteger(L, *iter);
lua_rawseti(L, -2, i++);
}
return 1;
}
}
static int hud(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushboolean(L, lsi->gameController->GetHudEnable());
return 1;
}
auto hudstate = lua_toboolean(L, 1);
lsi->gameController->SetHudEnable(hudstate);
return 0;
}
static int debugHud(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushboolean(L, lsi->gameController->GetDebugHUD());
return 1;
}
auto debug = lua_toboolean(L, 1);
lsi->gameController->SetDebugHUD(debug);
return 0;
}
static int useDisplayPreset(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int cmode = luaL_optint(L, 1, 3)+1;
if (cmode == 11)
cmode = 0;
if (cmode >= 0 && cmode <= 10)
lsi->gameController->LoadRenderPreset(cmode);
else
return luaL_error(L, "Invalid display mode");
return 0;
}
static int fireSize(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lua_gettop(L) < 1)
{
lua_pushnumber(L, lsi->gameModel->GetRenderer()->GetFireIntensity());
return 1;
}
float fireintensity = float(luaL_checknumber(L, 1));
lsi->gameModel->GetRenderer()->prepare_alpha(CELL, fireintensity);
return 0;
}
static int displayModes(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int args = lua_gettop(L);
if(args)
{
int size = 0;
luaL_checktype(L, 1, LUA_TTABLE);
size = lua_objlen(L, 1);
std::vector<unsigned int> displayModes;
for(int i = 1; i <= size; i++)
{
lua_rawgeti(L, 1, i);
displayModes.push_back(lua_tointeger(L, -1));
lua_pop(L, 1);
}
lsi->ren->SetDisplayMode(displayModes);
return 0;
}
else
{
lua_newtable(L);
std::vector<unsigned int> displayModes = lsi->ren->GetDisplayMode();
int i = 1;
for(std::vector<unsigned int>::iterator iter = displayModes.begin(), end = displayModes.end(); iter != end; ++iter)
{
lua_pushinteger(L, *iter);
lua_rawseti(L, -2, i++);
}
return 1;
}
}
static int colorMode(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(L, 1, LUA_TNUMBER);
lsi->ren->SetColourMode(lua_tointeger(L, 1));
return 0;
}
else
{
lua_pushinteger(L, lsi->ren->GetColourMode());
return 1;
}
}
static int decorations(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushboolean(L, lsi->gameModel->GetDecoration());
return 1;
}
int decostate = lua_toboolean(L, 1);
lsi->gameModel->SetDecoration(decostate);
lsi->gameModel->UpdateQuickOptions();
return 0;
}
static int grid(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushnumber(L, lsi->ren->GetGridSize());
return 1;
}
int grid = luaL_optint(L, 1, -1);
lsi->ren->SetGridSize(grid);
return 0;
}
static int showBrush(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
int acount = lua_gettop(L);
if (acount == 0)
{
lua_pushnumber(L, lsi->gameController->GetBrushEnable());
return 1;
}
int brush = luaL_optint(L, 1, -1);
lsi->gameController->SetBrushEnable(brush);
return 0;
}
static int depth3d(lua_State *L)
{
return luaL_error(L, "This feature is no longer supported");
}
static int zoomEnabled(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lua_gettop(L) == 0)
{
lua_pushboolean(L, lsi->ren->zoomEnabled);
return 1;
}
else
{
luaL_checktype(L, -1, LUA_TBOOLEAN);
lsi->ren->zoomEnabled = lua_toboolean(L, -1);
return 0;
}
}
static int zoomWindow(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto *ren = lsi->ren;
if (lua_gettop(L) == 0)
{
ui::Point location = ren->zoomWindowPosition;
lua_pushnumber(L, location.X);
lua_pushnumber(L, location.Y);
lua_pushnumber(L, ren->ZFACTOR);
lua_pushnumber(L, ren->zoomScopeSize * ren->ZFACTOR);
return 4;
}
int x = luaL_optint(L, 1, 0);
int y = luaL_optint(L, 2, 0);
int f = luaL_optint(L, 3, 0);
if (f <= 0)
return luaL_error(L, "Zoom factor must be greater than 0");
// To prevent crash when zoom window is outside screen
if (x < 0 || y < 0 || ren->zoomScopeSize * f + x > XRES || ren->zoomScopeSize * f + y > YRES)
return luaL_error(L, "Zoom window outside of bounds");
ren->zoomWindowPosition = ui::Point(x, y);
ren->ZFACTOR = f;
return 0;
}
static int zoomScope(lua_State *L)
{
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
auto *ren = lsi->ren;
if (lua_gettop(L) == 0)
{
ui::Point location = ren->zoomScopePosition;
lua_pushnumber(L, location.X);
lua_pushnumber(L, location.Y);
lua_pushnumber(L, ren->zoomScopeSize);
return 3;
}
int x = luaL_optint(L, 1, 0);
int y = luaL_optint(L, 2, 0);
int s = luaL_optint(L, 3, 0);
if (s <= 0)
return luaL_error(L, "Zoom scope size must be greater than 0");
// To prevent crash when zoom or scope window is outside screen
int windowEdgeRight = ren->ZFACTOR * s + ren->zoomWindowPosition.X;
int windowEdgeBottom = ren->ZFACTOR * s + ren->zoomWindowPosition.Y;
if (x < 0 || y < 0 || x + s > XRES || y + s > YRES)
return luaL_error(L, "Zoom scope outside of bounds");
if (windowEdgeRight > XRES || windowEdgeBottom > YRES)
return luaL_error(L, "Zoom window outside of bounds");
ren->zoomScopePosition = ui::Point(x, y);
ren->zoomScopeSize = s;
return 0;
}
void LuaRenderer::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
#define LFUNC(v) { #v, v }
LFUNC(renderModes),
LFUNC(displayModes),
LFUNC(colorMode),
LFUNC(decorations),
LFUNC(grid),
LFUNC(debugHud),
LFUNC(hud),
LFUNC(showBrush),
LFUNC(depth3d),
LFUNC(zoomEnabled),
LFUNC(zoomWindow),
LFUNC(zoomScope),
LFUNC(fireSize),
LFUNC(useDisplayPreset),
#undef LFUNC
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONST(v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, #v)
LCONST(PMODE);
LCONST(PMODE_NONE);
LCONST(PMODE_FLAT);
LCONST(PMODE_BLOB);
LCONST(PMODE_BLUR);
LCONST(PMODE_GLOW);
LCONST(PMODE_SPARK);
LCONST(PMODE_FLARE);
LCONST(PMODE_LFLARE);
LCONST(PMODE_ADD);
LCONST(PMODE_BLEND);
LCONST(PSPEC_STICKMAN);
LCONST(OPTIONS);
LCONST(NO_DECO);
LCONST(DECO_FIRE);
LCONST(FIREMODE);
LCONST(FIRE_ADD);
LCONST(FIRE_BLEND);
LCONST(FIRE_SPARK);
LCONST(EFFECT);
LCONST(EFFECT_GRAVIN);
LCONST(EFFECT_GRAVOUT);
LCONST(EFFECT_LINES);
LCONST(EFFECT_DBGLINES);
LCONST(RENDER_EFFE);
LCONST(RENDER_FIRE);
LCONST(RENDER_GLOW);
LCONST(RENDER_BLUR);
LCONST(RENDER_BLOB);
LCONST(RENDER_BASC);
LCONST(RENDER_NONE);
LCONST(COLOUR_HEAT);
LCONST(COLOUR_LIFE);
LCONST(COLOUR_GRAD);
LCONST(COLOUR_BASC);
LCONST(COLOUR_DEFAULT);
LCONST(DISPLAY_AIRC);
LCONST(DISPLAY_AIRP);
LCONST(DISPLAY_AIRV);
LCONST(DISPLAY_AIRH);
LCONST(DISPLAY_AIR);
LCONST(DISPLAY_WARP);
LCONST(DISPLAY_PERS);
LCONST(DISPLAY_EFFE);
#undef LCONST
lua_pushvalue(L, -1);
lua_setglobal(L, "renderer");
lua_setglobal(L, "ren");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
#include "TPTScriptInterface.h"
#include "simulation/StructProperty.h"
#include "simulation/ElementDefs.h"
#include <cstdint>
#include <map>
#include <memory>
@ -19,201 +20,88 @@ namespace ui
class Window;
}
class Tool;
//Because lua only has bindings for C, we're going to have to go outside "outside" the LuaScriptInterface, this means we can only have one instance :(
class Graphics;
class Renderer;
class Simulation;
class LuaComponent;
class LuaScriptInterface: public TPTScriptInterface
int LuaToLoggableString(lua_State *L, int n);
String LuaGetError();
void LuaGetProperty(lua_State *L, StructProperty property, intptr_t propertyAddress);
void LuaSetProperty(lua_State *L, StructProperty property, intptr_t propertyAddress, int stackPos);
void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty property, intptr_t propertyAddress, int stackPos);
struct LuaStateDeleter
{
std::unique_ptr<http::Request> scriptManagerDownload;
void operator ()(lua_State *L) const
{
lua_close(L);
}
};
using LuaStatePtr = std::unique_ptr<lua_State, LuaStateDeleter>;
int luacon_mousex, luacon_mousey, luacon_mousebutton;
ByteString luacon_selectedl, luacon_selectedr, luacon_selectedalt, luacon_selectedreplace;
bool luacon_mousedown;
bool currentCommand;
int textInputRefcount;
enum UpdateMode
{
UPDATE_AFTER,
UPDATE_REPLACE,
UPDATE_BEFORE,
NUM_UPDATEMODES,
};
// signs
static int simulation_signIndex(lua_State *l);
static int simulation_signNewIndex(lua_State *l);
static int simulation_newsign(lua_State *l);
struct CustomElement
{
UpdateMode updateMode = UPDATE_AFTER;
LuaSmartRef update;
LuaSmartRef graphics;
LuaSmartRef ctypeDraw;
LuaSmartRef create;
LuaSmartRef createAllowed;
LuaSmartRef changeType;
};
//Simulation
void initSimulationAPI();
static int simulation_partNeighbours(lua_State * l);
static int simulation_partChangeType(lua_State * l);
static int simulation_partCreate(lua_State * l);
static int simulation_partProperty(lua_State * l);
static int simulation_partPosition(lua_State * l);
static int simulation_partID(lua_State * l);
static int simulation_partKill(lua_State * l);
static int simulation_partExists(lua_State * l);
static int simulation_createParts(lua_State * l);
static int simulation_createLine(lua_State * l);
static int simulation_createBox(lua_State * l);
static int simulation_floodParts(lua_State * l);
static int simulation_createWalls(lua_State * l);
static int simulation_createWallLine(lua_State * l);
static int simulation_createWallBox(lua_State * l);
static int simulation_floodWalls(lua_State * l);
static int simulation_toolBrush(lua_State * l);
static int simulation_toolLine(lua_State * l);
static int simulation_toolBox(lua_State * l);
static int simulation_floodProp(lua_State * l);
static int simulation_decoBrush(lua_State * l);
static int simulation_decoLine(lua_State * l);
static int simulation_decoBox(lua_State * l);
static int simulation_decoColor(lua_State * l);
static int simulation_floodDeco(lua_State * l);
static int simulation_clearSim(lua_State * l);
static int simulation_clearRect(lua_State * l);
static int simulation_resetTemp(lua_State * l);
static int simulation_resetPressure(lua_State * l);
static int simulation_saveStamp(lua_State * l);
static int simulation_loadStamp(lua_State * l);
static int simulation_deleteStamp(lua_State * l);
static int simulation_loadSave(lua_State * l);
static int simulation_reloadSave(lua_State * l);
static int simulation_getSaveID(lua_State * l);
static int simulation_adjustCoords(lua_State * l);
static int simulation_prettyPowders(lua_State * l);
static int simulation_gravityGrid(lua_State * l);
static int simulation_edgeMode(lua_State * l);
static int simulation_gravityMode(lua_State * l);
static int simulation_customGravity(lua_State * l);
static int simulation_airMode(lua_State * l);
static int simulation_waterEqualisation(lua_State * l);
static int simulation_ambientAirTemp(lua_State * l);
static int simulation_elementCount(lua_State * l);
static int simulation_canMove(lua_State * l);
static int simulation_parts(lua_State * l);
static int simulation_brush(lua_State * l);
static int simulation_pmap(lua_State * l);
static int simulation_photons(lua_State * l);
static int simulation_neighbours(lua_State * l);
static int simulation_framerender(lua_State * l);
static int simulation_gspeed(lua_State * l);
static int simulation_takeSnapshot(lua_State *l);
static int simulation_historyRestore(lua_State *l);
static int simulation_historyForward(lua_State *l);
static int simulation_replaceModeFlags(lua_State *l);
static int simulation_listCustomGol(lua_State *l);
static int simulation_addCustomGol(lua_State *l);
static int simulation_removeCustomGol(lua_State *l);
static int simulation_lastUpdatedID(lua_State *l);
static int simulation_updateUpTo(lua_State *l);
static int simulation_temperatureScale(lua_State *l);
//Renderer
void initRendererAPI();
static int renderer_renderModes(lua_State * l);
static int renderer_displayModes(lua_State * l);
static int renderer_colourMode(lua_State * l);
static int renderer_decorations(lua_State * l);
static int renderer_grid(lua_State * l);
static int renderer_showBrush(lua_State * l);
static int renderer_depth3d(lua_State * l);
static int renderer_zoomEnabled(lua_State *l);
static int renderer_zoomWindowInfo(lua_State *l);
static int renderer_zoomScopeInfo(lua_State *l);
//Elements
void initElementsAPI();
static int elements_allocate(lua_State * l);
static int elements_element(lua_State * l);
static int elements_property(lua_State * l);
static int elements_loadDefault(lua_State * l);
static int elements_free(lua_State * l);
static int elements_exists(lua_State * l);
static void GetDefaultProperties(lua_State * l, int id);
static void SetDefaultProperties(lua_State * l, int id, int stackPos);
//Interface
void initInterfaceAPI();
static int interface_showWindow(lua_State * l);
static int interface_closeWindow(lua_State * l);
static int interface_addComponent(lua_State * l);
static int interface_removeComponent(lua_State * l);
static int interface_grabTextInput(lua_State * l);
static int interface_dropTextInput(lua_State * l);
static int interface_textInputRect(lua_State * l);
void initGraphicsAPI();
static int graphics_textSize(lua_State * l);
static int graphics_drawText(lua_State * l);
static int graphics_drawLine(lua_State * l);
static int graphics_drawRect(lua_State * l);
static int graphics_fillRect(lua_State * l);
static int graphics_drawCircle(lua_State * l);
static int graphics_fillCircle(lua_State * l);
static int graphics_getColors(lua_State * l);
static int graphics_getHexColor(lua_State * l);
static int graphics_setClipRect(lua_State * l);
void initFileSystemAPI();
static int fileSystem_list(lua_State * l);
static int fileSystem_exists(lua_State * l);
static int fileSystem_isFile(lua_State * l);
static int fileSystem_isDirectory(lua_State * l);
static int fileSystem_makeDirectory(lua_State * l);
static int fileSystem_removeDirectory(lua_State * l);
static int fileSystem_removeFile(lua_State * l);
static int fileSystem_move(lua_State * l);
static int fileSystem_copy(lua_State * l);
void initPlatformAPI();
static int platform_platform(lua_State * l);
static int platform_ident(lua_State * l);
static int platform_releaseType(lua_State * l);
static int platform_exeName(lua_State * l);
static int platform_restart(lua_State * l);
static int platform_openLink(lua_State * l);
static int platform_clipboardCopy(lua_State * l);
static int platform_clipboardPaste(lua_State * l);
void initEventAPI();
static int event_register(lua_State * l);
static int event_unregister(lua_State * l);
static int event_getmodifiers(lua_State * l);
static int installScriptManager(lua_State * l);
void initHttpAPI();
void initSocketAPI();
std::vector<LuaSmartRef> lua_el_func_v, lua_gr_func_v, lua_cd_func_v;
std::vector<int> lua_el_mode_v;
std::vector<LuaSmartRef> gameControllerEventHandlers;
class LuaScriptInterface : public TPTScriptInterface
{
LuaStatePtr luaState;
public:
static void LuaGetProperty(lua_State* l, StructProperty property, intptr_t propertyAddress);
static void LuaSetProperty(lua_State* l, StructProperty property, intptr_t propertyAddress, int stackPos);
static void LuaSetParticleProperty(lua_State* l, int particleID, StructProperty property, intptr_t propertyAddress, int stackPos);
lua_State *L{};
int luaHookTimeout;
ui::Window * Window;
lua_State *l;
GameModel *gameModel;
GameController *gameController;
ui::Window *window;
Simulation *sim;
Graphics *g;
Renderer *ren;
std::vector<CustomElement> customElements; // must come after luaState
EventTraits eventTraits = eventTraitNone;
bool luacon_hasLastError = false;
String lastCode;
bool currentCommand = false;
int textInputRefcount = 0;
long unsigned int luaExecutionStart = 0;
std::map<LuaComponent *, LuaSmartRef> grabbed_components;
LuaScriptInterface(GameController * c, GameModel * m);
char custom_can_move[PT_NUM][PT_NUM];
void custom_init_can_move();
std::vector<LuaSmartRef> gameControllerEventHandlers; // must come after luaState
std::unique_ptr<http::Request> scriptManagerDownload;
int luaHookTimeout;
std::map<LuaComponent *, LuaSmartRef> grabbedComponents; // must come after luaState
LuaScriptInterface(GameController *newGameController, GameModel *newGameModel);
~LuaScriptInterface();
char customCanMove[PT_NUM][PT_NUM];
void InitCustomCanMove();
void OnTick() override;
bool HandleEvent(const GameControllerEvent &event) override;
void Init() override;
void SetWindow(ui::Window * window);
int Command(String command) override;
String FormatCommand(String command) override;
virtual ~LuaScriptInterface();
};
void tpt_lua_pushByteString(lua_State *L, const ByteString &str);
@ -235,11 +123,78 @@ int tpt_lua_loadstring(lua_State *L, const ByteString &str);
int tpt_lua_dostring(lua_State *L, const ByteString &str);
bool tpt_lua_equalsString(lua_State *L, int index, const char *data, size_t size);
template<size_t N>
// TODO: use std::literals::string_literals::operator""s if we get rid of ByteString
template<size_t N>
bool tpt_lua_equalsLiteral(lua_State *L, int index, const char (&lit)[N])
{
return tpt_lua_equalsString(L, index, lit, N - 1U);
}
int tpt_lua_pcall(lua_State *L, int numArgs, int numResults, int errorFunc, EventTraits eventTraits);
namespace LuaHttp
{
void Open(lua_State *L);
}
namespace LuaBz2
{
void Open(lua_State *L);
}
namespace LuaElements
{
void Open(lua_State *L);
}
namespace LuaEvent
{
void Open(lua_State *L);
}
namespace LuaFileSystem
{
void Open(lua_State *L);
}
namespace LuaGraphics
{
void Open(lua_State *L);
}
namespace LuaInterface
{
void Open(lua_State *L);
}
namespace LuaMisc
{
void Open(lua_State *L);
void Tick(lua_State *L);
}
namespace LuaPlatform
{
void Open(lua_State *L);
}
namespace LuaRenderer
{
void Open(lua_State *L);
}
namespace LuaSimulation
{
void Open(lua_State *L);
}
namespace LuaSocket
{
int GetTime(lua_State *L);
int Sleep(lua_State *L);
double Now();
void Timeout(double timeout);
void Open(lua_State *L);
void OpenTCP(lua_State *L);
}

2091
src/lua/LuaSimulation.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,51 +15,51 @@ Luna<LuaSlider>::RegType LuaSlider::methods[] = {
{0, 0}
};
LuaSlider::LuaSlider(lua_State * l) :
LuaComponent(l)
LuaSlider::LuaSlider(lua_State *L) :
LuaComponent(L)
{
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
int steps = luaL_optinteger(l, 5, 10);
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
int steps = luaL_optinteger(L, 5, 10);
slider = new ui::Slider(ui::Point(posX, posY), ui::Point(sizeX, sizeY), steps);
component = slider;
slider->SetActionCallback({ [this] { triggerOnValueChanged(); } });
}
int LuaSlider::steps(lua_State * l)
int LuaSlider::steps(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
slider->SetSteps(lua_tointeger(l, 1));
slider->SetSteps(lua_tointeger(L, 1));
return 0;
}
else
{
lua_pushinteger(l, slider->GetSteps());
lua_pushinteger(L, slider->GetSteps());
return 1;
}
}
int LuaSlider::onValueChanged(lua_State * l)
int LuaSlider::onValueChanged(lua_State *L)
{
return onValueChangedFunction.CheckAndAssignArg1(l);
return onValueChangedFunction.CheckAndAssignArg1(L);
}
int LuaSlider::value(lua_State * l)
int LuaSlider::value(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
slider->SetValue(lua_tointeger(l, 1));
slider->SetValue(lua_tointeger(L, 1));
return 0;
}
else
{
lua_pushinteger(l, slider->GetValue());
lua_pushinteger(L, slider->GetValue());
return 1;
}
}
@ -68,12 +68,12 @@ void LuaSlider::triggerOnValueChanged()
{
if(onValueChangedFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onValueChangedFunction);
lua_rawgeti(l, LUA_REGISTRYINDEX, owner_ref);
lua_pushinteger(l, slider->GetValue());
if (tpt_lua_pcall(l, 2, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onValueChangedFunction);
lua_rawgeti(L, LUA_REGISTRYINDEX, owner_ref);
lua_pushinteger(L, slider->GetValue());
if (tpt_lua_pcall(L, 2, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}

View File

@ -15,13 +15,13 @@ class LuaSlider: public LuaComponent
ui::Slider * slider;
LuaComponentCallback onValueChangedFunction;
void triggerOnValueChanged();
int onValueChanged(lua_State * l);
int steps(lua_State * l);
int value(lua_State * l);
int onValueChanged(lua_State *L);
int steps(lua_State *L);
int value(lua_State *L);
public:
static const char className[];
static Luna<LuaSlider>::RegType methods[];
LuaSlider(lua_State * l);
LuaSlider(lua_State *L);
~LuaSlider();
};

View File

@ -3,10 +3,10 @@
void LuaSmartRef::Clear()
{
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
if (luacon_ci)
auto *lsi = static_cast<LuaScriptInterface *>(commandInterface);
if (lsi)
{
luaL_unref(luacon_ci->l, LUA_REGISTRYINDEX, ref);
luaL_unref(lsi->L, LUA_REGISTRYINDEX, ref);
ref = LUA_REFNIL;
}
}
@ -16,19 +16,19 @@ LuaSmartRef::~LuaSmartRef()
Clear();
}
void LuaSmartRef::Assign(lua_State *l, int index)
void LuaSmartRef::Assign(lua_State *L, int index)
{
if (index < 0)
{
index = lua_gettop(l) + index + 1;
index = lua_gettop(L) + index + 1;
}
Clear();
lua_pushvalue(l, index);
ref = luaL_ref(l, LUA_REGISTRYINDEX);
lua_pushvalue(L, index);
ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
int LuaSmartRef::Push(lua_State *l)
int LuaSmartRef::Push(lua_State *L)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, ref);
return lua_type(l, -1);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
return lua_type(L, -1);
}

View File

@ -7,9 +7,9 @@ class LuaSmartRef
public:
~LuaSmartRef();
void Assign(lua_State *l, int index); // Copies the value before getting reference, stack unchanged.
void Assign(lua_State *L, int index); // Copies the value before getting reference, stack unchanged.
void Clear();
int Push(lua_State *l); // Always pushes exactly one value, possibly nil.
int Push(lua_State *L); // Always pushes exactly one value, possibly nil.
inline operator int() const
{

View File

@ -1,33 +1,27 @@
#include "LuaSocket.h"
#include "LuaScriptInterface.h"
#include "Misc.h"
#include <stdint.h>
#include <algorithm>
namespace LuaSocket
int LuaSocket::GetTime(lua_State *L)
{
static int GetTime(lua_State *l)
{
lua_pushnumber(l, Now());
return 1;
}
static int Sleep(lua_State *l)
{
Timeout(luaL_checknumber(l, 1));
return 0;
}
void Open(lua_State *l)
{
lua_newtable(l);
struct luaL_Reg socketMethods[] = {
{ "sleep", LuaSocket::Sleep },
{ "getTime", LuaSocket::GetTime },
{ NULL, NULL },
};
luaL_register(l, NULL, socketMethods);
lua_setglobal(l, "socket");
OpenTCP(l);
}
lua_pushnumber(L, LuaSocket::Now());
return 1;
}
int LuaSocket::Sleep(lua_State *L)
{
LuaSocket::Timeout(luaL_checknumber(L, 1));
return 0;
}
void LuaSocket::Open(lua_State *L)
{
static const luaL_Reg reg[] = {
{ "sleep", LuaSocket::Sleep },
{ "getTime", LuaSocket::GetTime },
{ NULL, NULL }
};
lua_newtable(L);
luaL_register(L, NULL, reg);
lua_setglobal(L, "socket");
OpenTCP(L);
}

View File

@ -1,10 +0,0 @@
#pragma once
#include "LuaCompat.h"
namespace LuaSocket
{
double Now();
void Timeout(double timeout);
void Open(lua_State *l);
void OpenTCP(lua_State *l);
}

View File

@ -1,4 +1,3 @@
#include "LuaSocket.h"
#include "LuaScriptInterface.h"
#include "Misc.h"
#include <stdint.h>

View File

@ -1,5 +1,7 @@
#include "LuaSocket.h"
#include "LuaScriptInterface.h"
#include "client/http/requestmanager/CurlError.h"
#include "client/http/requestmanager/RequestManager.h"
#include "Misc.h"
#include "common/String.h"
#include <curl/curl.h>
#include <vector>
@ -8,11 +10,6 @@
#include <stdint.h>
#include <algorithm>
#include "LuaScriptInterface.h"
#include "client/http/requestmanager/RequestManager.h"
#include "client/http/requestmanager/CurlError.h"
#include "Misc.h"
namespace LuaSocket
{
enum Status
@ -80,14 +77,14 @@ namespace LuaSocket
return false;
}
static int New(lua_State *l)
static int New(lua_State *L)
{
using http::HandleCURLMcode;
if (http::RequestManager::Ref().DisableNetwork())
{
return luaL_error(l, "network disabled");
return luaL_error(L, "network disabled");
}
auto *tcps = (TCPSocket *)lua_newuserdata(l, sizeof(TCPSocket));
auto *tcps = (TCPSocket *)lua_newuserdata(L, sizeof(TCPSocket));
new(tcps) TCPSocket;
tcps->errorBuf[0] = 0;
tcps->easy = curl_easy_init();
@ -100,47 +97,47 @@ namespace LuaSocket
if (!tcps->easy)
{
Reset(tcps);
return luaL_error(l, "curl_easy_init failed");
return luaL_error(L, "curl_easy_init failed");
}
tcps->multi = curl_multi_init();
if (!tcps->multi)
{
Reset(tcps);
return luaL_error(l, "curl_multi_init failed");
return luaL_error(L, "curl_multi_init failed");
}
HandleCURLMcode(curl_multi_add_handle(tcps->multi, tcps->easy));
luaL_newmetatable(l, "TCPSocket");
lua_setmetatable(l, -2);
luaL_newmetatable(L, "TCPSocket");
lua_setmetatable(L, -2);
return 1;
}
static int GC(lua_State *l)
static int GC(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
Reset(tcps);
tcps->~TCPSocket();
return 0;
}
static int Close(lua_State *l)
static int Close(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
Reset(tcps);
return 0;
}
static int Send(lua_State *l)
static int Send(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
if (tcps->status != StatusConnected)
{
return luaL_error(l, "attempt to send on socket while not connected");
return luaL_error(L, "attempt to send on socket while not connected");
}
size_t dlenu;
auto *data = luaL_checklstring(l, 2, &dlenu);
auto *data = luaL_checklstring(L, 2, &dlenu);
auto dlen = int(dlenu);
auto first = luaL_optinteger(l, 3, 1);
auto last = luaL_optinteger(l, 4, -1);
auto first = luaL_optinteger(L, 3, 1);
auto last = luaL_optinteger(L, 4, -1);
if (first < 0) first += dlen + 1;
if (last < 0) last += dlen + 1;
if (first < 1) first = 1;
@ -179,9 +176,9 @@ namespace LuaSocket
if (tcps->writeClosed)
{
Reset(tcps);
lua_pushnil(l);
lua_pushliteral(l, "closed");
lua_pushinteger(l, writtenTotal + begin);
lua_pushnil(L);
lua_pushliteral(L, "closed");
lua_pushinteger(L, writtenTotal + begin);
return 3;
}
if (res == CURLE_AGAIN)
@ -194,22 +191,22 @@ namespace LuaSocket
Timeout(0.01);
continue;
}
lua_pushnil(l);
lua_pushliteral(l, "timeout");
lua_pushinteger(l, writtenTotal + begin);
lua_pushnil(L);
lua_pushliteral(L, "timeout");
lua_pushinteger(L, writtenTotal + begin);
return 3;
}
}
lua_pushinteger(l, writtenTotal + begin);
lua_pushinteger(L, writtenTotal + begin);
return 1;
}
static int ReceiveNoPrefix(lua_State *l)
static int ReceiveNoPrefix(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
if (tcps->status != StatusConnected)
{
return luaL_error(l, "attempt to receive on socket while not connected");
return luaL_error(L, "attempt to receive on socket while not connected");
}
enum
{
@ -218,17 +215,17 @@ namespace LuaSocket
readLine,
} pattern = readN;
size_t len = 4096;
if (tpt_lua_equalsLiteral(l, 2, "*a"))
if (tpt_lua_equalsLiteral(L, 2, "*a"))
{
pattern = readAll;
}
else if (tpt_lua_equalsLiteral(l, 2, "*l"))
else if (tpt_lua_equalsLiteral(L, 2, "*L"))
{
pattern = readLine;
}
else
{
len = size_t(luaL_checkinteger(l, 2));
len = size_t(luaL_checkinteger(L, 2));
}
if (pattern == readAll || pattern == readLine)
{
@ -303,11 +300,11 @@ namespace LuaSocket
// * Closed "*a" patterns don't return an error.
break;
}
lua_pushnil(l);
lua_pushliteral(l, "closed");
lua_pushnil(L);
lua_pushliteral(L, "closed");
if (pattern == readLine)
{
// * Closed "*l" patterns don't return partial lines.
// * Closed "*L" patterns don't return partial lines.
returning = 0;
}
retn = 3;
@ -331,11 +328,11 @@ namespace LuaSocket
Timeout(0.01);
continue;
}
lua_pushnil(l);
lua_pushliteral(l, "timeout");
lua_pushnil(L);
lua_pushliteral(L, "timeout");
if (pattern == readLine)
{
// * Timed-out "*l" patterns don't return partial lines.
// * Timed-out "*L" patterns don't return partial lines.
returning = 0;
}
retn = 3;
@ -356,12 +353,12 @@ namespace LuaSocket
}
returning = curOut;
}
lua_pushlstring(l, &tcps->recvBuf[0], returning);
lua_pushlstring(L, &tcps->recvBuf[0], returning);
// * This copy makes ReceiveNoPrefix quadratic if there's a lot of stuff in
// the stash (as a result of a *very* long line being returned by an "*l"
// the stash (as a result of a *very* long line being returned by an "*L"
// pattern and then whatever was left being stashed) and it's all *very*
// short lines (compared to the previous *very* long one, from the point
// of view of an "*l" pattern). Handling this edge case in a special,
// of view of an "*L" pattern). Handling this edge case in a special,
// sub-quadratic way isn't worth the effort.
std::copy(
&tcps->recvBuf[0] + readTotal - tcps->stashedLen,
@ -371,35 +368,35 @@ namespace LuaSocket
return retn;
}
static int Receive(lua_State *l)
static int Receive(lua_State *L)
{
bool prefix = false;
if (lua_gettop(l) >= 3)
if (lua_gettop(L) >= 3)
{
prefix = true;
lua_tostring(l, 3);
lua_tostring(L, 3);
}
int ret = ReceiveNoPrefix(l);
int ret = ReceiveNoPrefix(L);
if (prefix)
{
lua_pushvalue(l, 3);
lua_insert(l, -2);
lua_concat(l, 2);
lua_pushvalue(L, 3);
lua_insert(L, -2);
lua_concat(L, 2);
}
return ret;
}
static int Connect(lua_State *l)
static int Connect(lua_State *L)
{
using http::HandleCURLcode;
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
if (tcps->status == StatusDead)
{
return luaL_error(l, "attempt to connect dead socket");
return luaL_error(L, "attempt to connect dead socket");
}
if (tcps->status == StatusConnected)
{
return luaL_error(l, "attempt to connect connected socket");
return luaL_error(L, "attempt to connect connected socket");
}
auto startedAt = Now();
while (true)
@ -416,11 +413,11 @@ namespace LuaSocket
// the hostnames.
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_ERRORBUFFER, tcps->errorBuf));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_CONNECT_ONLY, 1L));
ByteString address = tpt_lua_checkByteString(l, 2);
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_PORT, long(luaL_checkinteger(l, 3))));
ByteString address = tpt_lua_checkByteString(L, 2);
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_PORT, long(luaL_checkinteger(L, 3))));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_NOSIGNAL, 1L));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0));
if (lua_toboolean(l, 4))
if (lua_toboolean(L, 4))
{
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 85, 0)
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_PROTOCOLS_STR, "https"));
@ -447,7 +444,7 @@ namespace LuaSocket
}
catch (const http::CurlError &ex)
{
return luaL_error(l, ex.what());
return luaL_error(L, ex.what());
}
}
@ -462,73 +459,73 @@ namespace LuaSocket
Timeout(0.01);
continue;
}
lua_pushnil(l);
lua_pushliteral(l, "timeout");
lua_pushnil(L);
lua_pushliteral(L, "timeout");
return 2;
}
if (res != CURLE_OK)
{
Reset(tcps);
lua_pushnil(l);
lua_pushstring(l, tcps->errorBuf);
lua_pushnil(L);
lua_pushstring(L, tcps->errorBuf);
return 2;
}
break;
}
tcps->status = StatusConnected;
lua_pushinteger(l, 1);
lua_pushinteger(L, 1);
return 1;
}
static int LastError(lua_State *l)
static int LastError(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
lua_pushstring(l, tcps->errorBuf);
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
lua_pushstring(L, tcps->errorBuf);
return 1;
}
static int GetStatus(lua_State *l)
static int GetStatus(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
switch (tcps->status)
{
case StatusReady: lua_pushliteral(l, "ready"); break;
case StatusConnecting: lua_pushliteral(l, "connecting"); break;
case StatusConnected: lua_pushliteral(l, "connected"); break;
case StatusDead: lua_pushliteral(l, "dead"); break;
case StatusReady: lua_pushliteral(L, "ready"); break;
case StatusConnecting: lua_pushliteral(L, "connecting"); break;
case StatusConnected: lua_pushliteral(L, "connected"); break;
case StatusDead: lua_pushliteral(L, "dead"); break;
}
return 1;
}
static int GetPeerName(lua_State *l)
static int GetPeerName(lua_State *L)
{
using http::HandleCURLcode;
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
if (tcps->status != StatusConnected)
{
return luaL_error(l, "attempt to get remote socket info while not connected");
return luaL_error(L, "attempt to get remote socket info while not connected");
}
char *address;
HandleCURLcode(curl_easy_getinfo(tcps->easy, CURLINFO_PRIMARY_IP, &address));
lua_pushstring(l, address);
lua_pushstring(L, address);
long port;
HandleCURLcode(curl_easy_getinfo(tcps->easy, CURLINFO_PRIMARY_PORT, &port));
lua_pushinteger(l, port);
lua_pushinteger(L, port);
return 2;
}
static int SetTimeout(lua_State *l)
static int SetTimeout(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
tcps->blocking = true;
if (lua_isnoneornil(l, 2))
if (lua_isnoneornil(L, 2))
{
tcps->timeoutIndefinite = true;
}
else
{
tcps->timeoutIndefinite = false;
tcps->timeout = luaL_checknumber(l, 2);
tcps->timeout = luaL_checknumber(L, 2);
if (int(tcps->timeout) == 0)
{
tcps->blocking = false;
@ -537,57 +534,57 @@ namespace LuaSocket
return 0;
}
static int GetSockName(lua_State *l)
static int GetSockName(lua_State *L)
{
using http::HandleCURLcode;
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
if (tcps->status != StatusConnected)
{
return luaL_error(l, "attempt to get local socket info while not connected");
return luaL_error(L, "attempt to get local socket info while not connected");
}
char *address;
HandleCURLcode(curl_easy_getinfo(tcps->easy, CURLINFO_LOCAL_IP, &address));
lua_pushstring(l, address);
lua_pushstring(L, address);
long port;
HandleCURLcode(curl_easy_getinfo(tcps->easy, CURLINFO_LOCAL_PORT, &port));
lua_pushinteger(l, port);
lua_pushinteger(L, port);
return 2;
}
static int SetOption(lua_State *l)
static int SetOption(lua_State *L)
{
using http::HandleCURLcode;
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto option = tpt_lua_checkByteString(l, 2);
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
auto option = tpt_lua_checkByteString(L, 2);
try
{
if (byteStringEqualsLiteral(option, "keepalive"))
{
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_TCP_KEEPALIVE, long(lua_toboolean(l, 3))));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_TCP_KEEPALIVE, long(lua_toboolean(L, 3))));
return 0;
}
else if (byteStringEqualsLiteral(option, "tcp-nodelay"))
{
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_TCP_NODELAY, long(lua_toboolean(l, 3))));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_TCP_NODELAY, long(lua_toboolean(L, 3))));
return 0;
}
else if (byteStringEqualsLiteral(option, "verify-peer"))
{
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_SSL_VERIFYPEER, long(lua_toboolean(l, 3))));
HandleCURLcode(curl_easy_setopt(tcps->easy, CURLOPT_SSL_VERIFYPEER, long(lua_toboolean(L, 3))));
return 0;
}
}
catch (const http::CurlError &ex)
{
return luaL_error(l, ex.what());
return luaL_error(L, ex.what());
}
return luaL_error(l, "unknown option");
return luaL_error(L, "unknown option");
}
static int Shutdown(lua_State *l)
static int Shutdown(lua_State *L)
{
auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket");
auto direction = tpt_lua_optByteString(l, 2, "both");
auto *tcps = (TCPSocket *)luaL_checkudata(L, 1, "TCPSocket");
auto direction = tpt_lua_optByteString(L, 2, "both");
if (byteStringEqualsLiteral(direction, "receive"))
{
tcps->readClosed = true;
@ -604,15 +601,15 @@ namespace LuaSocket
tcps->writeClosed = true;
return 0;
}
return luaL_error(l, "unknown direction");
return luaL_error(L, "unknown direction");
}
void OpenTCP(lua_State *l)
void OpenTCP(lua_State *L)
{
luaL_newmetatable(l, "TCPSocket");
lua_pushcfunction(l, LuaSocket::GC);
lua_setfield(l, -2, "__gc");
lua_newtable(l);
luaL_newmetatable(L, "TCPSocket");
lua_pushcfunction(L, LuaSocket::GC);
lua_setfield(L, -2, "__gc");
lua_newtable(L);
struct luaL_Reg tcpSocketIndexMethods[] = {
{ "connect", LuaSocket::Connect },
{ "close", LuaSocket::Close },
@ -627,12 +624,12 @@ namespace LuaSocket
{ "shutdown", LuaSocket::Shutdown },
{ NULL, NULL },
};
luaL_register(l, NULL, tcpSocketIndexMethods);
lua_setfield(l, -2, "__index");
lua_pop(l, 1);
lua_getglobal(l, "socket");
lua_pushcfunction(l, LuaSocket::New);
lua_setfield(l, -2, "tcp");
lua_pop(l, 1);
luaL_register(L, NULL, tcpSocketIndexMethods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
lua_getglobal(L, "socket");
lua_pushcfunction(L, LuaSocket::New);
lua_setfield(L, -2, "tcp");
lua_pop(L, 1);
}
}

View File

@ -1,8 +1,8 @@
#include "LuaSocket.h"
#include "LuaScriptInterface.h"
namespace LuaSocket
{
void OpenTCP(lua_State *l)
void OpenTCP(lua_State *L)
{
}
}

View File

@ -1,4 +1,3 @@
#include "LuaSocket.h"
#include "LuaScriptInterface.h"
#include "Misc.h"
#include <stdint.h>

View File

@ -15,16 +15,16 @@ Luna<LuaTextbox>::RegType LuaTextbox::methods[] = {
{0, 0}
};
LuaTextbox::LuaTextbox(lua_State * l) :
LuaComponent(l)
LuaTextbox::LuaTextbox(lua_State *L) :
LuaComponent(L)
{
this->l = l;
int posX = luaL_optinteger(l, 1, 0);
int posY = luaL_optinteger(l, 2, 0);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
String text = tpt_lua_optString(l, 5, "");
String placeholder = tpt_lua_optString(l, 6, "");
this->L = L;
int posX = luaL_optinteger(L, 1, 0);
int posY = luaL_optinteger(L, 2, 0);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
String text = tpt_lua_optString(L, 5, "");
String placeholder = tpt_lua_optString(L, 6, "");
textbox = new ui::Textbox(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, placeholder);
textbox->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
@ -32,51 +32,51 @@ LuaTextbox::LuaTextbox(lua_State * l) :
component = textbox;
}
int LuaTextbox::readonly(lua_State * l)
int LuaTextbox::readonly(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TBOOLEAN);
textbox->ReadOnly = lua_toboolean(l, 1);
luaL_checktype(L, 1, LUA_TBOOLEAN);
textbox->ReadOnly = lua_toboolean(L, 1);
return 0;
}
else
{
lua_pushboolean(l, textbox->ReadOnly);
lua_pushboolean(L, textbox->ReadOnly);
return 1;
}
}
int LuaTextbox::onTextChanged(lua_State * l)
int LuaTextbox::onTextChanged(lua_State *L)
{
return onTextChangedFunction.CheckAndAssignArg1(l);
return onTextChangedFunction.CheckAndAssignArg1(L);
}
void LuaTextbox::triggerOnTextChanged()
{
if(onTextChangedFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onTextChangedFunction);
lua_rawgeti(l, LUA_REGISTRYINDEX, owner_ref);
if (tpt_lua_pcall(l, 1, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onTextChangedFunction);
lua_rawgeti(L, LUA_REGISTRYINDEX, owner_ref);
if (tpt_lua_pcall(L, 1, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_optString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_optString(L, -1));
}
}
}
int LuaTextbox::text(lua_State * l)
int LuaTextbox::text(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
textbox->SetText(tpt_lua_checkString(l, 1));
textbox->SetText(tpt_lua_checkString(L, 1));
return 0;
}
else
{
tpt_lua_pushString(l, textbox->GetText());
tpt_lua_pushString(L, textbox->GetText());
return 1;
}
}

View File

@ -14,14 +14,14 @@ class LuaTextbox: public LuaComponent
{
LuaComponentCallback onTextChangedFunction;
ui::Textbox * textbox;
int text(lua_State * l);
int readonly(lua_State * l);
int onTextChanged(lua_State * l);
int text(lua_State *L);
int readonly(lua_State *L);
int onTextChanged(lua_State *L);
void triggerOnTextChanged();
public:
static const char className[];
static Luna<LuaTextbox>::RegType methods[];
LuaTextbox(lua_State * l);
LuaTextbox(lua_State *L);
~LuaTextbox();
};

View File

@ -35,13 +35,13 @@ Luna<LuaWindow>::RegType LuaWindow::methods[] = {
{0, 0}
};
LuaWindow::LuaWindow(lua_State * l)
LuaWindow::LuaWindow(lua_State *L)
{
this->l = l;
int posX = luaL_optinteger(l, 1, 1);
int posY = luaL_optinteger(l, 2, 1);
int sizeX = luaL_optinteger(l, 3, 10);
int sizeY = luaL_optinteger(l, 4, 10);
this->L = L;
int posX = luaL_optinteger(L, 1, 1);
int posY = luaL_optinteger(L, 2, 1);
int sizeX = luaL_optinteger(L, 3, 10);
int sizeY = luaL_optinteger(L, 4, 10);
// We should replace this with errors
if (posX < 1 && posX != -1)
@ -85,31 +85,31 @@ LuaWindow::LuaWindow(lua_State * l)
window = new DrawnWindow(ui::Point(posX, posY), ui::Point(sizeX, sizeY), this);
}
int LuaWindow::addComponent(lua_State * l)
int LuaWindow::addComponent(lua_State *L)
{
void *opaque = nullptr;
LuaComponent *luaComponent = nullptr;
if ((opaque = Luna<LuaButton>::tryGet(l, 1)))
if ((opaque = Luna<LuaButton>::tryGet(L, 1)))
luaComponent = Luna<LuaButton>::get(opaque);
else if ((opaque = Luna<LuaLabel>::tryGet(l, 1)))
else if ((opaque = Luna<LuaLabel>::tryGet(L, 1)))
luaComponent = Luna<LuaLabel>::get(opaque);
else if ((opaque = Luna<LuaTextbox>::tryGet(l, 1)))
else if ((opaque = Luna<LuaTextbox>::tryGet(L, 1)))
luaComponent = Luna<LuaTextbox>::get(opaque);
else if ((opaque = Luna<LuaCheckbox>::tryGet(l, 1)))
else if ((opaque = Luna<LuaCheckbox>::tryGet(L, 1)))
luaComponent = Luna<LuaCheckbox>::get(opaque);
else if ((opaque = Luna<LuaSlider>::tryGet(l, 1)))
else if ((opaque = Luna<LuaSlider>::tryGet(L, 1)))
luaComponent = Luna<LuaSlider>::get(opaque);
else if ((opaque = Luna<LuaProgressBar>::tryGet(l, 1)))
else if ((opaque = Luna<LuaProgressBar>::tryGet(L, 1)))
luaComponent = Luna<LuaProgressBar>::get(opaque);
else
luaL_typerror(l, 1, "Component");
luaL_typerror(L, 1, "Component");
if (luaComponent)
{
auto ok = grabbed_components.insert(std::make_pair(luaComponent, LuaSmartRef()));
auto ok = grabbedComponents.insert(std::make_pair(luaComponent, LuaSmartRef()));
if (ok.second)
{
auto it = ok.first;
it->second.Assign(l, 1);
it->second.Assign(L, 1);
it->first->owner_ref = it->second;
}
window->AddComponent(luaComponent->GetComponent());
@ -118,86 +118,86 @@ int LuaWindow::addComponent(lua_State * l)
return 0;
}
int LuaWindow::removeComponent(lua_State * l)
int LuaWindow::removeComponent(lua_State *L)
{
void *opaque = nullptr;
LuaComponent *luaComponent = nullptr;
if ((opaque = Luna<LuaButton>::tryGet(l, 1)))
if ((opaque = Luna<LuaButton>::tryGet(L, 1)))
luaComponent = Luna<LuaButton>::get(opaque);
else if ((opaque = Luna<LuaLabel>::tryGet(l, 1)))
else if ((opaque = Luna<LuaLabel>::tryGet(L, 1)))
luaComponent = Luna<LuaLabel>::get(opaque);
else if ((opaque = Luna<LuaTextbox>::tryGet(l, 1)))
else if ((opaque = Luna<LuaTextbox>::tryGet(L, 1)))
luaComponent = Luna<LuaTextbox>::get(opaque);
else if ((opaque = Luna<LuaCheckbox>::tryGet(l, 1)))
else if ((opaque = Luna<LuaCheckbox>::tryGet(L, 1)))
luaComponent = Luna<LuaCheckbox>::get(opaque);
else if ((opaque = Luna<LuaSlider>::tryGet(l, 1)))
else if ((opaque = Luna<LuaSlider>::tryGet(L, 1)))
luaComponent = Luna<LuaSlider>::get(opaque);
else if ((opaque = Luna<LuaProgressBar>::tryGet(l, 1)))
else if ((opaque = Luna<LuaProgressBar>::tryGet(L, 1)))
luaComponent = Luna<LuaProgressBar>::get(opaque);
else
luaL_typerror(l, 1, "Component");
luaL_typerror(L, 1, "Component");
if (luaComponent)
{
ui::Component *component = luaComponent->GetComponent();
window->RemoveComponent(component);
auto it = grabbed_components.find(luaComponent);
if (it != grabbed_components.end())
auto it = grabbedComponents.find(luaComponent);
if (it != grabbedComponents.end())
{
it->second.Clear();
it->first->owner_ref = it->second;
grabbed_components.erase(it);
grabbedComponents.erase(it);
luaComponent->SetParentWindow(nullptr);
}
}
return 0;
}
int LuaWindow::position(lua_State * l)
int LuaWindow::position(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TNUMBER);
luaL_checktype(l, 2, LUA_TNUMBER);
int posX = lua_tointeger(l, 1);
int posY = lua_tointeger(l, 2);
luaL_checktype(L, 1, LUA_TNUMBER);
luaL_checktype(L, 2, LUA_TNUMBER);
int posX = lua_tointeger(L, 1);
int posY = lua_tointeger(L, 2);
if (posX < 1 || posY < 1)
{
return luaL_error(l, "Invalid position: '%d,%d'", posX, posY);
return luaL_error(L, "Invalid position: '%d,%d'", posX, posY);
}
window->Position = ui::Point(posX, posY);
return 0;
}
else
{
lua_pushinteger(l, window->Position.X);
lua_pushinteger(l, window->Position.Y);
lua_pushinteger(L, window->Position.X);
lua_pushinteger(L, window->Position.Y);
return 2;
}
}
int LuaWindow::size(lua_State * l)
int LuaWindow::size(lua_State *L)
{
int args = lua_gettop(l);
int args = lua_gettop(L);
if(args)
{
luaL_checktype(l, 1, LUA_TNUMBER);
luaL_checktype(l, 2, LUA_TNUMBER);
int sizeX = lua_tointeger(l, 1);
int sizeY = lua_tointeger(l, 2);
luaL_checktype(L, 1, LUA_TNUMBER);
luaL_checktype(L, 2, LUA_TNUMBER);
int sizeX = lua_tointeger(L, 1);
int sizeY = lua_tointeger(L, 2);
if (sizeX < 10 || sizeY < 10)
{
return luaL_error(l, "Invalid size: '%d,%d'", sizeX, sizeY);
return luaL_error(L, "Invalid size: '%d,%d'", sizeX, sizeY);
}
window->Size = ui::Point(sizeX, sizeY);
return 0;
}
else
{
lua_pushinteger(l, window->Size.X);
lua_pushinteger(l, window->Size.Y);
lua_pushinteger(L, window->Size.X);
lua_pushinteger(L, window->Size.Y);
return 2;
}
}
@ -206,10 +206,10 @@ void LuaWindow::triggerOnInitialized()
{
if(onInitializedFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onInitializedFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onInitializedFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -218,10 +218,10 @@ void LuaWindow::triggerOnExit()
{
if(onExitFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onExitFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onExitFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -230,11 +230,11 @@ void LuaWindow::triggerOnTick(float dt)
{
if(onTickFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onTickFunction);
lua_pushnumber(l, dt);
if(tpt_lua_pcall(l, 1, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onTickFunction);
lua_pushnumber(L, dt);
if(tpt_lua_pcall(L, 1, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -243,10 +243,10 @@ void LuaWindow::triggerOnDraw()
{
if(onDrawFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onDrawFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onDrawFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -255,10 +255,10 @@ void LuaWindow::triggerOnFocus()
{
if(onFocusFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onFocusFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onFocusFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -267,10 +267,10 @@ void LuaWindow::triggerOnBlur()
{
if(onBlurFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onBlurFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onBlurFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -279,10 +279,10 @@ void LuaWindow::triggerOnTryExit()
{
if(onTryExitFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onTryExitFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onTryExitFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -291,10 +291,10 @@ void LuaWindow::triggerOnTryOkay()
{
if(onTryOkayFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onTryOkayFunction);
if(tpt_lua_pcall(l, 0, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onTryOkayFunction);
if(tpt_lua_pcall(L, 0, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -303,14 +303,14 @@ void LuaWindow::triggerOnMouseMove(int x, int y, int dx, int dy)
{
if(onMouseMoveFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseMoveFunction);
lua_pushinteger(l, x);
lua_pushinteger(l, y);
lua_pushinteger(l, dx);
lua_pushinteger(l, dy);
if(tpt_lua_pcall(l, 4, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onMouseMoveFunction);
lua_pushinteger(L, x);
lua_pushinteger(L, y);
lua_pushinteger(L, dx);
lua_pushinteger(L, dy);
if(tpt_lua_pcall(L, 4, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -319,13 +319,13 @@ void LuaWindow::triggerOnMouseDown(int x, int y, unsigned button)
{
if(onMouseDownFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseDownFunction);
lua_pushinteger(l, x);
lua_pushinteger(l, y);
lua_pushinteger(l, button);
if(tpt_lua_pcall(l, 3, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onMouseDownFunction);
lua_pushinteger(L, x);
lua_pushinteger(L, y);
lua_pushinteger(L, button);
if(tpt_lua_pcall(L, 3, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -334,13 +334,13 @@ void LuaWindow::triggerOnMouseUp(int x, int y, unsigned button)
{
if(onMouseUpFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseUpFunction);
lua_pushinteger(l, x);
lua_pushinteger(l, y);
lua_pushinteger(l, button);
if(tpt_lua_pcall(l, 3, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onMouseUpFunction);
lua_pushinteger(L, x);
lua_pushinteger(L, y);
lua_pushinteger(L, button);
if(tpt_lua_pcall(L, 3, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -349,13 +349,13 @@ void LuaWindow::triggerOnMouseWheel(int x, int y, int d)
{
if(onMouseWheelFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseWheelFunction);
lua_pushinteger(l, x);
lua_pushinteger(l, y);
lua_pushinteger(l, d);
if(tpt_lua_pcall(l, 3, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onMouseWheelFunction);
lua_pushinteger(L, x);
lua_pushinteger(L, y);
lua_pushinteger(L, d);
if(tpt_lua_pcall(L, 3, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -364,15 +364,15 @@ void LuaWindow::triggerOnKeyPress(int key, int scan, bool repeat, bool shift, bo
{
if(onKeyPressFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onKeyPressFunction);
lua_pushinteger(l, key);
lua_pushinteger(l, scan);
lua_pushboolean(l, shift);
lua_pushboolean(l, ctrl);
lua_pushboolean(l, alt);
if(tpt_lua_pcall(l, 5, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onKeyPressFunction);
lua_pushinteger(L, key);
lua_pushinteger(L, scan);
lua_pushboolean(L, shift);
lua_pushboolean(L, ctrl);
lua_pushboolean(L, alt);
if(tpt_lua_pcall(L, 5, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
@ -381,104 +381,104 @@ void LuaWindow::triggerOnKeyRelease(int key, int scan, bool repeat, bool shift,
{
if(onKeyReleaseFunction)
{
lua_rawgeti(l, LUA_REGISTRYINDEX, onKeyReleaseFunction);
lua_pushinteger(l, key);
lua_pushinteger(l, scan);
lua_pushboolean(l, shift);
lua_pushboolean(l, ctrl);
lua_pushboolean(l, alt);
if(tpt_lua_pcall(l, 5, 0, 0, eventTraitNone))
lua_rawgeti(L, LUA_REGISTRYINDEX, onKeyReleaseFunction);
lua_pushinteger(L, key);
lua_pushinteger(L, scan);
lua_pushboolean(L, shift);
lua_pushboolean(L, ctrl);
lua_pushboolean(L, alt);
if(tpt_lua_pcall(L, 5, 0, 0, eventTraitNone))
{
ci->Log(CommandInterface::LogError, tpt_lua_toString(l, -1));
ci->Log(CommandInterface::LogError, tpt_lua_toString(L, -1));
}
}
}
int LuaWindow::onInitialized(lua_State * l)
int LuaWindow::onInitialized(lua_State *L)
{
return onInitializedFunction.CheckAndAssignArg1(l);
return onInitializedFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onExit(lua_State * l)
int LuaWindow::onExit(lua_State *L)
{
return onExitFunction.CheckAndAssignArg1(l);
return onExitFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onTick(lua_State * l)
int LuaWindow::onTick(lua_State *L)
{
return onTickFunction.CheckAndAssignArg1(l);
return onTickFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onDraw(lua_State * l)
int LuaWindow::onDraw(lua_State *L)
{
return onDrawFunction.CheckAndAssignArg1(l);
return onDrawFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onFocus(lua_State * l)
int LuaWindow::onFocus(lua_State *L)
{
return onFocusFunction.CheckAndAssignArg1(l);
return onFocusFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onBlur(lua_State * l)
int LuaWindow::onBlur(lua_State *L)
{
return onBlurFunction.CheckAndAssignArg1(l);
return onBlurFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onTryExit(lua_State * l)
int LuaWindow::onTryExit(lua_State *L)
{
return onTryExitFunction.CheckAndAssignArg1(l);
return onTryExitFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onTryOkay(lua_State * l)
int LuaWindow::onTryOkay(lua_State *L)
{
return onTryOkayFunction.CheckAndAssignArg1(l);
return onTryOkayFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onMouseMove(lua_State * l)
int LuaWindow::onMouseMove(lua_State *L)
{
return onMouseMoveFunction.CheckAndAssignArg1(l);
return onMouseMoveFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onMouseDown(lua_State * l)
int LuaWindow::onMouseDown(lua_State *L)
{
return onMouseDownFunction.CheckAndAssignArg1(l);
return onMouseDownFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onMouseUp(lua_State * l)
int LuaWindow::onMouseUp(lua_State *L)
{
return onMouseUpFunction.CheckAndAssignArg1(l);
return onMouseUpFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onMouseWheel(lua_State * l)
int LuaWindow::onMouseWheel(lua_State *L)
{
return onMouseWheelFunction.CheckAndAssignArg1(l);
return onMouseWheelFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onKeyPress(lua_State * l)
int LuaWindow::onKeyPress(lua_State *L)
{
return onKeyPressFunction.CheckAndAssignArg1(l);
return onKeyPressFunction.CheckAndAssignArg1(L);
}
int LuaWindow::onKeyRelease(lua_State * l)
int LuaWindow::onKeyRelease(lua_State *L)
{
return onKeyReleaseFunction.CheckAndAssignArg1(l);
return onKeyReleaseFunction.CheckAndAssignArg1(L);
}
void LuaWindow::ClearRef(LuaComponent *luaComponent)
{
auto it = grabbed_components.find(luaComponent);
if (it != grabbed_components.end())
auto it = grabbedComponents.find(luaComponent);
if (it != grabbedComponents.end())
{
it->second.Clear();
it->first->owner_ref = it->second;
it->first->SetParentWindow(nullptr);
grabbed_components.erase(it);
grabbedComponents.erase(it);
}
}
LuaWindow::~LuaWindow()
{
for (auto &component_and_ref : grabbed_components)
for (auto &component_and_ref : grabbedComponents)
{
window->RemoveComponent(component_and_ref.first->GetComponent());
component_and_ref.second.Clear();

View File

@ -27,30 +27,30 @@ class LuaWindow
LuaComponentCallback onKeyPressFunction;
LuaComponentCallback onKeyReleaseFunction;
std::map<LuaComponent *, LuaSmartRef> grabbed_components;
std::map<LuaComponent *, LuaSmartRef> grabbedComponents;
ui::Window * window;
lua_State * l;
int position(lua_State * l);
int size(lua_State * l);
int addComponent(lua_State * l);
int removeComponent(lua_State * l);
lua_State *L;
int position(lua_State *L);
int size(lua_State *L);
int addComponent(lua_State *L);
int removeComponent(lua_State *L);
//Set event handlers
int onInitialized(lua_State * l);
int onExit(lua_State * l);
int onTick(lua_State * l);
int onDraw(lua_State * l);
int onFocus(lua_State * l);
int onBlur(lua_State * l);
int onTryExit(lua_State * l);
int onTryOkay(lua_State * l);
int onMouseMove(lua_State * l);
int onMouseDown(lua_State * l);
int onMouseUp(lua_State * l);
int onMouseWheel(lua_State * l);
int onKeyPress(lua_State * l);
int onKeyRelease(lua_State * l);
int onInitialized(lua_State *L);
int onExit(lua_State *L);
int onTick(lua_State *L);
int onDraw(lua_State *L);
int onFocus(lua_State *L);
int onBlur(lua_State *L);
int onTryExit(lua_State *L);
int onTryOkay(lua_State *L);
int onMouseMove(lua_State *L);
int onMouseDown(lua_State *L);
int onMouseUp(lua_State *L);
int onMouseWheel(lua_State *L);
int onKeyPress(lua_State *L);
int onKeyRelease(lua_State *L);
void triggerOnInitialized();
void triggerOnExit();
@ -75,6 +75,6 @@ public:
ui::Window * GetWindow() { return window; }
void ClearRef(LuaComponent *luaComponent);
LuaWindow(lua_State * l);
LuaWindow(lua_State *L);
~LuaWindow();
};

View File

@ -11,10 +11,6 @@
#include <cstdlib>
#include <cmath>
TPTScriptInterface::TPTScriptInterface(GameController * c, GameModel * m): CommandInterface(c, m)
{
}
int TPTScriptInterface::Command(String command)
{
lastError = "";

View File

@ -15,7 +15,8 @@ class TPTScriptInterface: public CommandInterface {
AnyType tptS_quit(std::deque<String> * words);
ValueType testType(String word);
public:
TPTScriptInterface(GameController * c, GameModel * m);
using CommandInterface::CommandInterface;
int Command(String command) override;
String FormatCommand(String command) override;
};

View File

@ -58,6 +58,7 @@ ui.MOUSE_UP_NORMAL = ui.MOUSEUP_NORMAL
if socket then
socket.gettime = socket.getTime
end
print = tpt.log
local function fake_boolean_wrapper(func, true_is_1)
return function(param)

View File

@ -1,12 +1,22 @@
luaconsole_files = files(
'LuaButton.cpp',
'LuaBz2.cpp',
'LuaCheckbox.cpp',
'LuaCompat.c',
'LuaComponent.cpp',
'LuaElements.cpp',
'LuaEvent.cpp',
'LuaFileSystem.cpp',
'LuaGraphics.cpp',
'LuaHttp.cpp',
'LuaInterface.cpp',
'LuaLabel.cpp',
'LuaMisc.cpp',
'LuaPlatform.cpp',
'LuaProgressBar.cpp',
'LuaRenderer.cpp',
'LuaScriptInterface.cpp',
'LuaSimulation.cpp',
'LuaSlider.cpp',
'LuaSocket.cpp',
'LuaSmartRef.cpp',