1508 lines
37 KiB
C++
1508 lines
37 KiB
C++
#ifdef LUACONSOLE
|
|
#include <iomanip>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <locale>
|
|
|
|
#include "client/http/Request.h"
|
|
#include "client/Client.h"
|
|
|
|
#include "Format.h"
|
|
#include "LuaScriptInterface.h"
|
|
#include "LuaScriptHelper.h"
|
|
#include "LuaSmartRef.h"
|
|
#include "Platform.h"
|
|
#include "PowderToy.h"
|
|
|
|
#include "gui/dialogues/ErrorMessage.h"
|
|
#include "gui/dialogues/InformationMessage.h"
|
|
#include "gui/dialogues/TextPrompt.h"
|
|
#include "gui/dialogues/ConfirmPrompt.h"
|
|
#include "gui/game/GameModel.h"
|
|
#include "gui/game/GameController.h"
|
|
#include "gui/interface/Keys.h"
|
|
#include "gui/interface/Engine.h"
|
|
|
|
#include "simulation/Simulation.h"
|
|
#include "simulation/Gravity.h"
|
|
#include "simulation/SimulationData.h"
|
|
#include "simulation/ElementCommon.h"
|
|
|
|
#include "graphics/Graphics.h"
|
|
#include "graphics/Renderer.h"
|
|
|
|
std::map<ByteString, StructProperty> legacyPropNames;
|
|
std::map<ByteString, StructProperty> legacyTransitionNames;
|
|
void initLegacyProps()
|
|
{
|
|
std::vector<StructProperty> properties = Element::GetProperties();
|
|
for (auto prop : properties)
|
|
{
|
|
if (prop.Name == "MenuVisible")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("menu", prop));
|
|
else if (prop.Name == "PhotonReflectWavelengths")
|
|
continue;
|
|
else if (prop.Name == "Temperature")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("heat", prop));
|
|
else if (prop.Name == "HeatConduct")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("hconduct", prop));
|
|
|
|
// Put all transition stuff into separate map
|
|
else if (prop.Name == "LowPressure")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presLowValue", prop));
|
|
else if (prop.Name == "LowPressureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presLowType", prop));
|
|
else if (prop.Name == "HighPressure")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presHighValue", prop));
|
|
else if (prop.Name == "HighPressureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presHighType", prop));
|
|
else if (prop.Name == "LowTemperature")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempLowValue", prop));
|
|
else if (prop.Name == "LowTemperatureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempLowType", prop));
|
|
else if (prop.Name == "HighTemperature")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempHighValue", prop));
|
|
else if (prop.Name == "HighTemperatureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempHighType", prop));
|
|
|
|
else
|
|
{
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>(prop.Name.ToLower(), prop));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef FFI
|
|
int luacon_partread(lua_State* l)
|
|
{
|
|
int tempinteger, i = cIndex;
|
|
float tempfloat;
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(key, format);
|
|
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Out of range");
|
|
if (offset == -1)
|
|
{
|
|
if (!key.compare("id"))
|
|
{
|
|
lua_pushnumber(l, i);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Invalid property");
|
|
}
|
|
|
|
switch(format)
|
|
{
|
|
case CommandInterface::FormatInt:
|
|
case CommandInterface::FormatElement:
|
|
tempinteger = *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempinteger);
|
|
break;
|
|
case CommandInterface::FormatFloat:
|
|
tempfloat = *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempfloat);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int luacon_partwrite(lua_State* l)
|
|
{
|
|
int i = cIndex;
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(key, format);
|
|
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Out of range");
|
|
if (!luacon_sim->parts[i].type)
|
|
return luaL_error(l, "Dead particle");
|
|
if (offset == -1)
|
|
return luaL_error(l, "Invalid property");
|
|
|
|
switch(format)
|
|
{
|
|
case CommandInterface::FormatInt:
|
|
*((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optinteger(l, 3, 0);
|
|
break;
|
|
case CommandInterface::FormatFloat:
|
|
*((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optnumber(l, 3, 0);
|
|
break;
|
|
case CommandInterface::FormatElement:
|
|
luacon_sim->part_change_type(i, luacon_sim->parts[i].x, luacon_sim->parts[i].y, luaL_optinteger(l, 3, 0));
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luacon_partsread(lua_State* l)
|
|
{
|
|
int i = luaL_optinteger(l, 2, 0);
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "array index out of bounds");
|
|
|
|
lua_rawgeti(l, LUA_REGISTRYINDEX, *tptPart);
|
|
cIndex = i;
|
|
return 1;
|
|
}
|
|
|
|
int luacon_partswrite(lua_State* l)
|
|
{
|
|
return luaL_error(l, "table readonly");
|
|
}
|
|
#endif
|
|
|
|
int luacon_transitionread(lua_State* l)
|
|
{
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyTransitionNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushstring(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsValidElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int luacon_transitionwrite(lua_State* l)
|
|
{
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyTransitionNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushstring(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsValidElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
if (prop.Type == StructProperty::TransitionType)
|
|
{
|
|
int type = luaL_checkinteger(l, 3);
|
|
if (!luacon_sim->IsValidElement(type) && type != NT && type != ST)
|
|
{
|
|
return luaL_error(l, "Invalid element");
|
|
}
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int luacon_elementread(lua_State* l)
|
|
{
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
if (legacyPropNames.find(key) == legacyPropNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyPropNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushstring(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsValidElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int luacon_elementwrite(lua_State* l)
|
|
{
|
|
ByteString key = luaL_optstring(l, 2, "");
|
|
if (legacyPropNames.find(key) == legacyPropNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyPropNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushstring(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsValidElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
if (prop.Name == "type") // i.e. it's .type
|
|
{
|
|
luacon_sim->part_change_type(i, luacon_sim->parts[i].x+0.5f, luacon_sim->parts[i].y+0.5f, luaL_checkinteger(l, 3));
|
|
}
|
|
else
|
|
{
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
|
}
|
|
|
|
luacon_model->BuildMenus();
|
|
luacon_sim->init_can_move();
|
|
std::fill(&luacon_ren->graphicscache[0], &luacon_ren->graphicscache[PT_NUM], gcache_item());
|
|
|
|
return 0;
|
|
}
|
|
|
|
int luacon_eval(const char *command)
|
|
{
|
|
ui::Engine::Ref().LastTick(Platform::GetTime());
|
|
return luaL_dostring (luacon_ci->l, command);
|
|
}
|
|
|
|
void luacon_hook(lua_State * l, lua_Debug * ar)
|
|
{
|
|
if(ar->event == LUA_HOOKCOUNT && Platform::GetTime()-ui::Engine::Ref().LastTick() > 3000)
|
|
{
|
|
if(ConfirmPrompt::Blocking("Script not responding"_i18n, "The Lua script may have stopped responding. There might be an infinite loop. Press \"Stop\" to stop it"_i18n, "Stop"_i18n))
|
|
luaL_error(l, "Error: Script not responding");
|
|
ui::Engine::Ref().LastTick(Platform::GetTime());
|
|
}
|
|
}
|
|
|
|
ByteString luacon_geterror()
|
|
{
|
|
luaL_tostring(luacon_ci->l, -1);
|
|
ByteString err = luaL_optstring(luacon_ci->l, -1, "failed to execute");
|
|
lua_pop(luacon_ci->l, 1);
|
|
return err;
|
|
}
|
|
|
|
//tpt. api methods
|
|
int luatpt_getelement(lua_State *l)
|
|
{
|
|
int t;
|
|
if (lua_isnumber(l, 1))
|
|
{
|
|
t = luaL_optint(l, 1, 1);
|
|
if (!luacon_sim->IsValidElement(t))
|
|
{
|
|
return luaL_error(l, "Unrecognised element number '%d'", t);
|
|
}
|
|
lua_pushstring(l, luacon_sim->elements[t].Name.ToUtf8().c_str());
|
|
}
|
|
else
|
|
{
|
|
luaL_checktype(l, 1, LUA_TSTRING);
|
|
const char* name = luaL_optstring(l, 1, "");
|
|
if ((t = luacon_sim->GetParticleType(name))==-1)
|
|
return luaL_error(l, "Unrecognised element '%s'", name);
|
|
lua_pushinteger(l, t);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int luacon_elementReplacement(UPDATE_FUNC_ARGS)
|
|
{
|
|
int retval = 0, callret;
|
|
if (lua_el_func[parts[i].type])
|
|
{
|
|
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_el_func[parts[i].type]);
|
|
lua_pushinteger(luacon_ci->l, i);
|
|
lua_pushinteger(luacon_ci->l, x);
|
|
lua_pushinteger(luacon_ci->l, y);
|
|
lua_pushinteger(luacon_ci->l, surround_space);
|
|
lua_pushinteger(luacon_ci->l, nt);
|
|
callret = lua_pcall(luacon_ci->l, 5, 1, 0);
|
|
if (callret)
|
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror().FromUtf8());
|
|
if(lua_isboolean(luacon_ci->l, -1)){
|
|
retval = lua_toboolean(luacon_ci->l, -1);
|
|
}
|
|
lua_pop(luacon_ci->l, 1);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
int luatpt_element_func(lua_State *l)
|
|
{
|
|
if(lua_isfunction(l, 1))
|
|
{
|
|
int element = luaL_optint(l, 2, 0);
|
|
int replace = luaL_optint(l, 3, 0);
|
|
if (luacon_sim->IsValidElement(element))
|
|
{
|
|
lua_el_func[element].Assign(1);
|
|
if (replace == 2)
|
|
lua_el_mode[element] = 3; //update before
|
|
else if (replace)
|
|
lua_el_mode[element] = 2; //replace
|
|
else
|
|
lua_el_mode[element] = 1; //update after
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return luaL_error(l, "Invalid element");
|
|
}
|
|
}
|
|
else if(lua_isnil(l, 1))
|
|
{
|
|
int element = luaL_optint(l, 2, 0);
|
|
if (luacon_sim->IsValidElement(element))
|
|
{
|
|
lua_el_func[element].Clear();
|
|
lua_el_mode[element] = 0;
|
|
}
|
|
else
|
|
{
|
|
return luaL_error(l, "Invalid element");
|
|
}
|
|
}
|
|
else
|
|
return luaL_error(l, "Not a function");
|
|
return 0;
|
|
}
|
|
|
|
int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS, int i)
|
|
{
|
|
int cache = 0, callret;
|
|
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_gr_func[cpart->type]);
|
|
lua_pushinteger(luacon_ci->l, i);
|
|
lua_pushinteger(luacon_ci->l, *colr);
|
|
lua_pushinteger(luacon_ci->l, *colg);
|
|
lua_pushinteger(luacon_ci->l, *colb);
|
|
callret = lua_pcall(luacon_ci->l, 4, 10, 0);
|
|
if (callret)
|
|
{
|
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror().FromUtf8());
|
|
lua_pop(luacon_ci->l, 1);
|
|
}
|
|
else
|
|
{
|
|
bool valid = true;
|
|
for (int i = -10; i < 0; i++)
|
|
if (!lua_isnumber(luacon_ci->l, i) && !lua_isnil(luacon_ci->l, i))
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
if (valid)
|
|
{
|
|
cache = luaL_optint(luacon_ci->l, -10, 0);
|
|
*pixel_mode = luaL_optint(luacon_ci->l, -9, *pixel_mode);
|
|
*cola = luaL_optint(luacon_ci->l, -8, *cola);
|
|
*colr = luaL_optint(luacon_ci->l, -7, *colr);
|
|
*colg = luaL_optint(luacon_ci->l, -6, *colg);
|
|
*colb = luaL_optint(luacon_ci->l, -5, *colb);
|
|
*firea = luaL_optint(luacon_ci->l, -4, *firea);
|
|
*firer = luaL_optint(luacon_ci->l, -3, *firer);
|
|
*fireg = luaL_optint(luacon_ci->l, -2, *fireg);
|
|
*fireb = luaL_optint(luacon_ci->l, -1, *fireb);
|
|
}
|
|
lua_pop(luacon_ci->l, 10);
|
|
}
|
|
return cache;
|
|
}
|
|
|
|
int luatpt_graphics_func(lua_State *l)
|
|
{
|
|
if(lua_isfunction(l, 1))
|
|
{
|
|
int element = luaL_optint(l, 2, 0);
|
|
if (luacon_sim->IsValidElement(element))
|
|
{
|
|
lua_gr_func[element].Assign(1);
|
|
luacon_ren->graphicscache[element].isready = 0;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return luaL_error(l, "Invalid element");
|
|
}
|
|
}
|
|
else if (lua_isnil(l, 1))
|
|
{
|
|
int element = luaL_optint(l, 2, 0);
|
|
if (luacon_sim->IsValidElement(element))
|
|
{
|
|
lua_gr_func[element].Clear();
|
|
luacon_ren->graphicscache[element].isready = 0;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return luaL_error(l, "Invalid element");
|
|
}
|
|
}
|
|
else
|
|
return luaL_error(l, "Not a function");
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_error(lua_State* l)
|
|
{
|
|
String errorMessage = ByteString(luaL_optstring(l, 1, "Error text")).FromUtf8();
|
|
ErrorMessage::Blocking("Error"_i18n, errorMessage);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_drawtext(lua_State* l)
|
|
{
|
|
const char *string;
|
|
int textx, texty, textred, textgreen, textblue, textalpha;
|
|
textx = luaL_optint(l, 1, 0);
|
|
texty = luaL_optint(l, 2, 0);
|
|
string = luaL_optstring(l, 3, "");
|
|
textred = luaL_optint(l, 4, 255);
|
|
textgreen = luaL_optint(l, 5, 255);
|
|
textblue = luaL_optint(l, 6, 255);
|
|
textalpha = luaL_optint(l, 7, 255);
|
|
if (textx<0 || texty<0 || textx>=WINDOWW || texty>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", textx, texty);
|
|
if (textred<0) textred = 0;
|
|
if (textred>255) textred = 255;
|
|
if (textgreen<0) textgreen = 0;
|
|
if (textgreen>255) textgreen = 255;
|
|
if (textblue<0) textblue = 0;
|
|
if (textblue>255) textblue = 255;
|
|
if (textalpha<0) textalpha = 0;
|
|
if (textalpha>255) textalpha = 255;
|
|
|
|
luacon_g->drawtext(textx, texty, ByteString(string).FromUtf8(), textred, textgreen, textblue, textalpha);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_create(lua_State* l)
|
|
{
|
|
int x, y, retid, t = -1;
|
|
x = abs(luaL_optint(l, 1, 0));
|
|
y = abs(luaL_optint(l, 2, 0));
|
|
if(x < XRES && y < YRES)
|
|
{
|
|
if(lua_isnumber(l, 3))
|
|
{
|
|
t = luaL_optint(l, 3, 0);
|
|
if (!luacon_sim->IsValidElement(t))
|
|
{
|
|
return luaL_error(l, "Unrecognised element number '%d'", t);
|
|
}
|
|
} else {
|
|
const char* name = luaL_optstring(l, 3, "dust");
|
|
if ((t = luacon_sim->GetParticleType(ByteString(name))) == -1)
|
|
return luaL_error(l,"Unrecognised element '%s'", name);
|
|
}
|
|
retid = luacon_sim->create_part(-1, x, y, t);
|
|
// failing to create a particle often happens (e.g. if space is already occupied) and isn't usually important, so don't raise an error
|
|
lua_pushinteger(l, retid);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", x, y);
|
|
}
|
|
|
|
int luatpt_setpause(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushnumber(l, luacon_model->GetPaused());
|
|
return 1;
|
|
}
|
|
int pausestate = luaL_checkinteger(l, 1);
|
|
luacon_model->SetPaused(pausestate==0?0:1);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_togglepause(lua_State* l)
|
|
{
|
|
luacon_model->SetPaused(!luacon_model->GetPaused());
|
|
lua_pushnumber(l, luacon_model->GetPaused());
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_togglewater(lua_State* l)
|
|
{
|
|
luacon_sim->water_equal_test=!luacon_sim->water_equal_test;
|
|
lua_pushnumber(l, luacon_sim->water_equal_test);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_setconsole(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushnumber(l, luacon_ci->Window != ui::Engine::Ref().GetWindow());
|
|
return 1;
|
|
}
|
|
if (luaL_checkinteger(l, 1))
|
|
luacon_controller->ShowConsole();
|
|
else
|
|
luacon_controller->HideConsole();
|
|
return 0;
|
|
}
|
|
int luatpt_log(lua_State* l)
|
|
{
|
|
int args = lua_gettop(l);
|
|
String text = "";
|
|
for(int i = 1; i <= args; i++)
|
|
{
|
|
luaL_tostring(l, -1);
|
|
if(text.length())
|
|
text=ByteString(luaL_optstring(l, -1, "")).FromUtf8() + ", " + text;
|
|
else
|
|
text=ByteString(luaL_optstring(l, -1, "")).FromUtf8();
|
|
lua_pop(l, 2);
|
|
}
|
|
if((*luacon_currentCommand))
|
|
{
|
|
if(luacon_lastError->length())
|
|
*luacon_lastError += "; ";
|
|
*luacon_lastError += text;
|
|
}
|
|
else
|
|
luacon_ci->Log(CommandInterface::LogNotice, text.c_str());
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_pressure(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
float value;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
value = (float)luaL_optint(l, 5, 0.0f);
|
|
if(value > 256.0f)
|
|
value = 256.0f;
|
|
else if(value < -256.0f)
|
|
value = -256.0f;
|
|
|
|
if(x1 > (XRES/CELL)-1)
|
|
x1 = (XRES/CELL)-1;
|
|
if(y1 > (YRES/CELL)-1)
|
|
y1 = (YRES/CELL)-1;
|
|
if(x1+width > (XRES/CELL)-1)
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL)-1)
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->pv[ny][nx] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_gravity(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
float value;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
value = (float)luaL_optint(l, 5, 0.0f);
|
|
if(value > 256.0f)
|
|
value = 256.0f;
|
|
else if(value < -256.0f)
|
|
value = -256.0f;
|
|
|
|
if(x1 > (XRES/CELL)-1)
|
|
x1 = (XRES/CELL)-1;
|
|
if(y1 > (YRES/CELL)-1)
|
|
y1 = (YRES/CELL)-1;
|
|
if(x1+width > (XRES/CELL)-1)
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL)-1)
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->gravmap[ny*(XRES/CELL)+nx] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_gravity_field(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
if(x1 > (XRES/CELL)-1)
|
|
x1 = (XRES/CELL)-1;
|
|
if(y1 > (YRES/CELL)-1)
|
|
y1 = (YRES/CELL)-1;
|
|
if(x1+width > (XRES/CELL)-1)
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL)-1)
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->gravx[ny*(XRES/CELL)+nx] = 0;
|
|
luacon_sim->gravy[ny*(XRES/CELL)+nx] = 0;
|
|
luacon_sim->gravp[ny*(XRES/CELL)+nx] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_velocity(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
if(x1 > (XRES/CELL)-1)
|
|
x1 = (XRES/CELL)-1;
|
|
if(y1 > (YRES/CELL)-1)
|
|
y1 = (YRES/CELL)-1;
|
|
if(x1+width > (XRES/CELL)-1)
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL)-1)
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->vx[ny][nx] = 0;
|
|
luacon_sim->vy[ny][nx] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_spark(lua_State* l)
|
|
{
|
|
luacon_controller->ResetSpark();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_property(lua_State* l)
|
|
{
|
|
const char *name;
|
|
int r, i, x, y, w, h, t = 0, nx, ny, partsel = 0;
|
|
float f = 0;
|
|
int acount = lua_gettop(l);
|
|
const char* prop = luaL_optstring(l, 1, "");
|
|
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(prop, format);
|
|
if (offset == -1)
|
|
return luaL_error(l, "Invalid property '%s'", prop);
|
|
|
|
if (acount > 2)
|
|
{
|
|
if(!lua_isnumber(l, acount) && lua_isstring(l, acount))
|
|
{
|
|
name = luaL_optstring(l, acount, "none");
|
|
if ((partsel = luacon_sim->GetParticleType(ByteString(name))) == -1)
|
|
return luaL_error(l, "Unrecognised element '%s'", name);
|
|
}
|
|
}
|
|
if (lua_isnumber(l, 2))
|
|
{
|
|
if (format == CommandInterface::FormatFloat)
|
|
f = luaL_optnumber(l, 2, 0);
|
|
else
|
|
t = luaL_optint(l, 2, 0);
|
|
|
|
if (!strcmp(prop, "type") && !luacon_sim->IsValidElement(t))
|
|
return luaL_error(l, "Unrecognised element number '%d'", t);
|
|
}
|
|
else if (lua_isstring(l, 2))
|
|
{
|
|
name = luaL_checklstring(l, 2, NULL);
|
|
if ((t = luacon_sim->GetParticleType(ByteString(name)))==-1)
|
|
return luaL_error(l, "Unrecognised element '%s'", name);
|
|
}
|
|
else
|
|
luaL_error(l, "Expected number or element name as argument 2");
|
|
|
|
if (!lua_isnumber(l, 3) || acount >= 6)
|
|
{
|
|
// Got a region
|
|
if (acount < 6)
|
|
{
|
|
i = 0;
|
|
y = 0;
|
|
w = XRES;
|
|
h = YRES;
|
|
}
|
|
else
|
|
{
|
|
i = abs(luaL_checkint(l, 3));
|
|
y = abs(luaL_checkint(l, 4));
|
|
w = abs(luaL_checkint(l, 5));
|
|
h = abs(luaL_checkint(l, 6));
|
|
}
|
|
if (i>=XRES || y>=YRES)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
x = i;
|
|
if(x+w > XRES)
|
|
w = XRES-x;
|
|
if(y+h > YRES)
|
|
h = YRES-y;
|
|
Particle * parts = luacon_sim->parts;
|
|
for (i = 0; i < NPART; i++)
|
|
{
|
|
if (parts[i].type)
|
|
{
|
|
nx = (int)(parts[i].x + .5f);
|
|
ny = (int)(parts[i].y + .5f);
|
|
if (nx >= x && nx < x+w && ny >= y && ny < y+h && (!partsel || partsel == parts[i].type))
|
|
{
|
|
if (format == CommandInterface::FormatElement)
|
|
luacon_sim->part_change_type(i, nx, ny, t);
|
|
else if(format == CommandInterface::FormatFloat)
|
|
*((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f;
|
|
else
|
|
*((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = abs(luaL_checkint(l, 3));
|
|
// Got coords or particle index
|
|
if (lua_isnumber(l, 4))
|
|
{
|
|
y = abs(luaL_checkint(l, 4));
|
|
if (i>=XRES || y>=YRES)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
r = luacon_sim->pmap[y][i];
|
|
if (!r || (partsel && partsel != TYP(r)))
|
|
r = luacon_sim->photons[y][i];
|
|
if (!r || (partsel && partsel != TYP(r)))
|
|
return 0;
|
|
i = ID(r);
|
|
}
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Invalid particle ID '%d'", i);
|
|
if (!luacon_sim->parts[i].type)
|
|
return 0;
|
|
if (partsel && partsel != luacon_sim->parts[i].type)
|
|
return 0;
|
|
|
|
if (format == CommandInterface::FormatElement)
|
|
luacon_sim->part_change_type(i, luacon_sim->parts[i].x, luacon_sim->parts[i].y, t);
|
|
else if (format == CommandInterface::FormatFloat)
|
|
*((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f;
|
|
else
|
|
*((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_wallmap(lua_State* l)
|
|
{
|
|
int nx, ny, acount;
|
|
int x1, y1, width, height, wallType;
|
|
acount = lua_gettop(l);
|
|
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
wallType = luaL_optint(l, acount, 0);
|
|
if (wallType < 0 || wallType >= UI_WALLCOUNT)
|
|
return luaL_error(l, "Unrecognised wall number %d", wallType);
|
|
|
|
if (acount == 5) //Draw rect
|
|
{
|
|
if(x1 > (XRES/CELL))
|
|
x1 = (XRES/CELL);
|
|
if(y1 > (YRES/CELL))
|
|
y1 = (YRES/CELL);
|
|
if(x1+width > (XRES/CELL))
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL))
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->bmap[ny][nx] = wallType;
|
|
}
|
|
}
|
|
else //Set point
|
|
{
|
|
if(x1 > (XRES/CELL))
|
|
x1 = (XRES/CELL);
|
|
if(y1 > (YRES/CELL))
|
|
y1 = (YRES/CELL);
|
|
luacon_sim->bmap[y1][x1] = wallType;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_get_wallmap(lua_State* l)
|
|
{
|
|
int x1 = abs(luaL_optint(l, 1, 0));
|
|
int y1 = abs(luaL_optint(l, 2, 0));
|
|
|
|
if(x1 > (XRES/CELL) || y1 > (YRES/CELL))
|
|
return luaL_error(l, "Out of range");
|
|
|
|
lua_pushinteger(l, luacon_sim->bmap[y1][x1]);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_set_elecmap(lua_State* l)
|
|
{
|
|
int nx, ny, acount;
|
|
int x1, y1, width, height;
|
|
float value;
|
|
acount = lua_gettop(l);
|
|
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XRES/CELL));
|
|
height = abs(luaL_optint(l, 4, YRES/CELL));
|
|
value = (float)luaL_optint(l, acount, 0);
|
|
|
|
if(acount==5) //Draw rect
|
|
{
|
|
if(x1 > (XRES/CELL))
|
|
x1 = (XRES/CELL);
|
|
if(y1 > (YRES/CELL))
|
|
y1 = (YRES/CELL);
|
|
if(x1+width > (XRES/CELL))
|
|
width = (XRES/CELL)-x1;
|
|
if(y1+height > (YRES/CELL))
|
|
height = (YRES/CELL)-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->emap[ny][nx] = value;
|
|
}
|
|
}
|
|
else //Set point
|
|
{
|
|
if(x1 > (XRES/CELL))
|
|
x1 = (XRES/CELL);
|
|
if(y1 > (YRES/CELL))
|
|
y1 = (YRES/CELL);
|
|
luacon_sim->emap[y1][x1] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_get_elecmap(lua_State* l)
|
|
{
|
|
int x1 = abs(luaL_optint(l, 1, 0));
|
|
int y1 = abs(luaL_optint(l, 2, 0));
|
|
|
|
if(x1 > (XRES/CELL) || y1 > (YRES/CELL))
|
|
return luaL_error(l, "Out of range");
|
|
|
|
lua_pushinteger(l, luacon_sim->emap[y1][x1]);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_get_property(lua_State* l)
|
|
{
|
|
ByteString prop = luaL_optstring(l, 1, "");
|
|
int i = luaL_optint(l, 2, 0); //x coord or particle index, depending on arguments
|
|
int y = luaL_optint(l, 3, -1);
|
|
if (y!=-1 && y<YRES && y>=0 && i < XRES && i>=0)
|
|
{
|
|
int r = luacon_sim->pmap[y][i];
|
|
if (!r)
|
|
{
|
|
r = luacon_sim->photons[y][i];
|
|
if (!r)
|
|
{
|
|
if (!prop.compare("type"))
|
|
{
|
|
lua_pushinteger(l, 0);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Particle does not exist");
|
|
}
|
|
}
|
|
i = ID(r);
|
|
}
|
|
else if (y != -1)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Invalid particle ID '%d'", i);
|
|
|
|
if (luacon_sim->parts[i].type)
|
|
{
|
|
int tempinteger;
|
|
float tempfloat;
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(prop, format);
|
|
|
|
if (offset == -1)
|
|
{
|
|
if (!prop.compare("id"))
|
|
{
|
|
lua_pushnumber(l, i);
|
|
return 1;
|
|
}
|
|
else
|
|
return luaL_error(l, "Invalid property");
|
|
}
|
|
switch(format)
|
|
{
|
|
case CommandInterface::FormatInt:
|
|
case CommandInterface::FormatElement:
|
|
tempinteger = *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempinteger);
|
|
break;
|
|
case CommandInterface::FormatFloat:
|
|
tempfloat = *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempfloat);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
else if (!prop.compare("type"))
|
|
{
|
|
lua_pushinteger(l, 0);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Particle does not exist");
|
|
}
|
|
|
|
int luatpt_drawpixel(lua_State* l)
|
|
{
|
|
int x, y, r, g, b, a;
|
|
x = luaL_optint(l, 1, 0);
|
|
y = luaL_optint(l, 2, 0);
|
|
r = luaL_optint(l, 3, 255);
|
|
g = luaL_optint(l, 4, 255);
|
|
b = luaL_optint(l, 5, 255);
|
|
a = luaL_optint(l, 6, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
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;
|
|
luacon_g->blendpixel(x, y, r, g, b, a);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_drawrect(lua_State* l)
|
|
{
|
|
int x, y, w, h, r, g, b, a;
|
|
x = luaL_optint(l, 1, 0);
|
|
y = luaL_optint(l, 2, 0);
|
|
w = luaL_optint(l, 3, 10)+1;
|
|
h = luaL_optint(l, 4, 10)+1;
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
if(x+w > WINDOWW)
|
|
w = WINDOWW-x;
|
|
if(y+h > WINDOWH)
|
|
h = WINDOWH-y;
|
|
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;
|
|
luacon_g->drawrect(x, y, w, h, r, g, b, a);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_fillrect(lua_State* l)
|
|
{
|
|
int x,y,w,h,r,g,b,a;
|
|
x = luaL_optint(l, 1, 0)+1;
|
|
y = luaL_optint(l, 2, 0)+1;
|
|
w = luaL_optint(l, 3, 10)-1;
|
|
h = luaL_optint(l, 4, 10)-1;
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
if(x+w > WINDOWW)
|
|
w = WINDOWW-x;
|
|
if(y+h > WINDOWH)
|
|
h = WINDOWH-y;
|
|
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;
|
|
luacon_g->fillrect(x, y, w, h, r, g, b, a);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_drawline(lua_State* l)
|
|
{
|
|
int x1,y1,x2,y2,r,g,b,a;
|
|
x1 = luaL_optint(l, 1, 0);
|
|
y1 = luaL_optint(l, 2, 0);
|
|
x2 = luaL_optint(l, 3, 10);
|
|
y2 = luaL_optint(l, 4, 10);
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
//Don't need to check coordinates, as they are checked in blendpixel
|
|
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;
|
|
luacon_g->draw_line(x1, y1, x2, y2, r, g, b, a);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_textwidth(lua_State* l)
|
|
{
|
|
int strwidth = 0;
|
|
const char* string = luaL_optstring(l, 1, "");
|
|
strwidth = Graphics::textwidth(ByteString(string).FromUtf8());
|
|
lua_pushinteger(l, strwidth);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_get_name(lua_State* l)
|
|
{
|
|
if (luacon_model->GetUser().UserID)
|
|
{
|
|
lua_pushstring(l, luacon_model->GetUser().Username.c_str());
|
|
return 1;
|
|
}
|
|
lua_pushstring(l, "");
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_delete(lua_State* l)
|
|
{
|
|
int arg1, arg2;
|
|
arg1 = abs(luaL_optint(l, 1, 0));
|
|
arg2 = luaL_optint(l, 2, -1);
|
|
if (arg2 == -1 && arg1 < NPART)
|
|
{
|
|
luacon_sim->kill_part(arg1);
|
|
return 0;
|
|
}
|
|
arg2 = abs(arg2);
|
|
if(arg2 < YRES && arg1 < XRES)
|
|
{
|
|
luacon_sim->delete_part(arg1, arg2);
|
|
return 0;
|
|
}
|
|
return luaL_error(l,"Invalid coordinates or particle ID");
|
|
}
|
|
|
|
int luatpt_input(lua_State* l)
|
|
{
|
|
String prompt, title, result, shadow, text;
|
|
title = ByteString(luaL_optstring(l, 1, "Title")).FromUtf8();
|
|
prompt = ByteString(luaL_optstring(l, 2, "Enter some text:")).FromUtf8();
|
|
text = ByteString(luaL_optstring(l, 3, "")).FromUtf8();
|
|
shadow = ByteString(luaL_optstring(l, 4, "")).FromUtf8();
|
|
|
|
result = TextPrompt::Blocking(title, prompt, text, shadow, false);
|
|
|
|
lua_pushstring(l, result.ToUtf8().c_str());
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_message_box(lua_State* l)
|
|
{
|
|
String title = ByteString(luaL_optstring(l, 1, "Title")).FromUtf8();
|
|
String message = ByteString(luaL_optstring(l, 2, "Message")).FromUtf8();
|
|
int large = lua_toboolean(l, 3);
|
|
new InformationMessage(title, message, large);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_confirm(lua_State *l)
|
|
{
|
|
String title = ByteString(luaL_optstring(l, 1, "Title")).FromUtf8();
|
|
String message = ByteString(luaL_optstring(l, 2, "Message")).FromUtf8();
|
|
String buttonText = ByteString(luaL_optstring(l, 3, "Confirm")).FromUtf8();
|
|
bool ret = ConfirmPrompt::Blocking(title, message, buttonText);
|
|
lua_pushboolean(l, ret ? 1 : 0);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_get_numOfParts(lua_State* l)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->NUM_PARTS);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_start_getPartIndex(lua_State* l)
|
|
{
|
|
getPartIndex_curIdx = -1;
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_next_getPartIndex(lua_State* l)
|
|
{
|
|
while(1)
|
|
{
|
|
getPartIndex_curIdx++;
|
|
if (getPartIndex_curIdx >= NPART)
|
|
{
|
|
getPartIndex_curIdx = -1;
|
|
lua_pushboolean(l, 0);
|
|
return 1;
|
|
}
|
|
if (luacon_sim->parts[getPartIndex_curIdx].type)
|
|
break;
|
|
|
|
}
|
|
|
|
lua_pushboolean(l, 1);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_getPartIndex(lua_State* l)
|
|
{
|
|
if(getPartIndex_curIdx < 0)
|
|
{
|
|
lua_pushinteger(l, -1);
|
|
return 1;
|
|
}
|
|
lua_pushinteger(l, getPartIndex_curIdx);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_hud(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_controller->GetHudEnable());
|
|
return 1;
|
|
}
|
|
int hudstate = luaL_checkint(l, 1);
|
|
if (hudstate)
|
|
luacon_controller->SetHudEnable(1);
|
|
else
|
|
luacon_controller->SetHudEnable(0);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_gravity(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->grav->IsEnabled() ? 1 : 0);
|
|
return 1;
|
|
}
|
|
int gravstate = luaL_checkint(l, 1);
|
|
if(gravstate)
|
|
luacon_sim->grav->start_grav_async();
|
|
else
|
|
luacon_sim->grav->stop_grav_async();
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_airheat(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->aheat_enable);
|
|
return 1;
|
|
}
|
|
int aheatstate = luaL_checkint(l, 1);
|
|
luacon_sim->aheat_enable = (aheatstate==0?0:1);
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_active_menu(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_model->GetActiveMenu());
|
|
return 1;
|
|
}
|
|
int menuid = luaL_checkint(l, 1);
|
|
if (menuid >= 0 && menuid < SC_TOTAL)
|
|
luacon_controller->SetActiveMenu(menuid);
|
|
else
|
|
return luaL_error(l, "Invalid menu");
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_menu_enabled(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, luacon_sim->msections[menusection].doshow);
|
|
return 1;
|
|
}
|
|
luaL_checktype(l, 2, LUA_TBOOLEAN);
|
|
int enabled = lua_toboolean(l, 2);
|
|
luacon_sim->msections[menusection].doshow = enabled;
|
|
luacon_model->BuildMenus();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_num_menus(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);
|
|
}
|
|
lua_pushinteger(l, luacon_controller->GetNumMenus(onlyEnabled));
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_decorations_enable(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_model->GetDecoration());
|
|
return 1;
|
|
}
|
|
int decostate = luaL_checkint(l, 1);
|
|
luacon_model->SetDecoration(decostate==0?false:true);
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_heat(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, !luacon_sim->legacy_enable);
|
|
return 1;
|
|
}
|
|
int heatstate = luaL_checkint(l, 1);
|
|
luacon_sim->legacy_enable = (heatstate==1?0:1);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_cmode_set(lua_State* l)
|
|
{
|
|
int cmode = luaL_optint(l, 1, 3)+1;
|
|
if (cmode == 11)
|
|
cmode = 0;
|
|
if (cmode >= 0 && cmode <= 10)
|
|
luacon_controller->LoadRenderPreset(cmode);
|
|
else
|
|
return luaL_error(l, "Invalid display mode");
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setfire(lua_State* l)
|
|
{
|
|
int firesize = luaL_optint(l, 2, 4);
|
|
float fireintensity = (float)luaL_optnumber(l, 1, 1.0f);
|
|
luacon_model->GetRenderer()->prepare_alpha(firesize, fireintensity);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setdebug(lua_State* l)
|
|
{
|
|
int debugFlags = luaL_optint(l, 1, 0);
|
|
luacon_controller->SetDebugFlags(debugFlags);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setfpscap(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, ui::Engine::Ref().FpsLimit);
|
|
return 1;
|
|
}
|
|
int fpscap = luaL_checkint(l, 1);
|
|
if (fpscap < 2)
|
|
return luaL_error(l, "fps cap too small");
|
|
ui::Engine::Ref().FpsLimit = fpscap;
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_getscript(lua_State* l)
|
|
{
|
|
int scriptID = luaL_checkinteger(l, 1);
|
|
const char *filename = luaL_checkstring(l, 2);
|
|
int runScript = luaL_optint(l, 3, 0);
|
|
int confirmPrompt = luaL_optint(l, 4, 1);
|
|
|
|
ByteString url = ByteString::Build(SCHEME "starcatcher.us/scripts/main.lua?get=", scriptID);
|
|
if (confirmPrompt && !ConfirmPrompt::Blocking("Do you want to install script?"_i18n, url.FromUtf8(), "Install"_i18n))
|
|
return 0;
|
|
|
|
int ret;
|
|
ByteString scriptData = http::Request::Simple(url, &ret);
|
|
if (!scriptData.size() || !filename)
|
|
{
|
|
return luaL_error(l, "Server did not return data");
|
|
}
|
|
if (ret != 200)
|
|
{
|
|
return luaL_error(l, http::StatusText(ret).ToUtf8().c_str());
|
|
}
|
|
|
|
if (scriptData.Contains("Invalid script ID"))
|
|
{
|
|
return luaL_error(l, "Invalid Script ID");
|
|
}
|
|
|
|
FILE *outputfile = fopen(filename, "r");
|
|
if (outputfile)
|
|
{
|
|
fclose(outputfile);
|
|
outputfile = NULL;
|
|
if (!confirmPrompt || ConfirmPrompt::Blocking("File already exists, overwrite?"_i18n, ByteString(filename).FromUtf8(), "Overwrite"_i18n))
|
|
{
|
|
outputfile = fopen(filename, "wb");
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
outputfile = fopen(filename, "wb");
|
|
}
|
|
if (!outputfile)
|
|
{
|
|
return luaL_error(l, "Unable to write to file");
|
|
}
|
|
|
|
fputs(scriptData.c_str(), outputfile);
|
|
fclose(outputfile);
|
|
outputfile = NULL;
|
|
if (runScript)
|
|
{
|
|
luaL_dostring(l, ByteString::Build("dofile('", filename, "')").c_str());
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setwindowsize(lua_State* l)
|
|
{
|
|
int scale = luaL_optint(l,1,1);
|
|
int kiosk = luaL_optint(l,2,0);
|
|
// 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;
|
|
if (kiosk!=1) kiosk = 0;
|
|
ui::Engine::Ref().SetScale(scale);
|
|
ui::Engine::Ref().SetFullscreen(kiosk);
|
|
return 0;
|
|
}
|
|
|
|
int screenshotIndex = 0;
|
|
|
|
int luatpt_screenshot(lua_State* l)
|
|
{
|
|
int captureUI = luaL_optint(l, 1, 0);
|
|
int fileType = luaL_optint(l, 2, 0);
|
|
std::vector<char> data;
|
|
if(captureUI)
|
|
{
|
|
VideoBuffer screenshot(ui::Engine::Ref().g->DumpFrame());
|
|
if(fileType == 1) {
|
|
data = format::VideoBufferToBMP(screenshot);
|
|
} else if(fileType == 2) {
|
|
data = format::VideoBufferToPPM(screenshot);
|
|
} else {
|
|
data = format::VideoBufferToPNG(screenshot);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VideoBuffer screenshot(luacon_ren->DumpFrame());
|
|
if(fileType == 1) {
|
|
data = format::VideoBufferToBMP(screenshot);
|
|
} else if(fileType == 2) {
|
|
data = format::VideoBufferToPPM(screenshot);
|
|
} else {
|
|
data = format::VideoBufferToPNG(screenshot);
|
|
}
|
|
}
|
|
ByteString filename = ByteString::Build("screenshot_", Format::Width(screenshotIndex++, 6));
|
|
if(fileType == 1) {
|
|
filename += ".bmp";
|
|
} else if(fileType == 2) {
|
|
filename += ".ppm";
|
|
} else {
|
|
filename += ".png";
|
|
}
|
|
Client::Ref().WriteFile(data, filename);
|
|
lua_pushstring(l, filename.c_str());
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_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);
|
|
int recordingFolder = luacon_controller->Record(record);
|
|
lua_pushinteger(l, recordingFolder);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|