1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-25 22:25:46 +00:00

Really fix variadic calls (including self). Also fix avatar_setPullTarget() failing because entities are userdata now.

This does now allow constructs like this, in an entity script:

  function msg(me, a)
      if a > 1 then
          a = a * entity_msg(me, a - 1)
      end
      return a
  end

So that entity_msg(thing, 5) == 120 is true.
This commit is contained in:
fgenesis 2012-03-14 20:11:14 +01:00
parent 0cdbc66c02
commit e94de627eb
5 changed files with 31 additions and 42 deletions

View file

@ -234,7 +234,7 @@ public:
bool canSetState(int state); bool canSetState(int state);
virtual void message(const std::string &msg, int v) {} virtual void message(const std::string &msg, int v) {}
virtual void messageVariadic(lua_State *L, int nparams) {} virtual int messageVariadic(lua_State *L, int nparams) { return 0; }
bool isUnderWater(const Vector &o=Vector()); bool isUnderWater(const Vector &o=Vector());

View file

@ -2889,8 +2889,8 @@ luaFunc(entity_isBeingPulled)
luaFunc(avatar_setPullTarget) luaFunc(avatar_setPullTarget)
{ {
Entity *e = 0; Entity *e = 0;
if (lua_tonumber(L, 1) != 0) if (lua_isuserdata(L, 1))
e = entity(L); e = entity(L, 1);
if (dsq->game->avatar->pullTarget != 0) if (dsq->game->avatar->pullTarget != 0)
dsq->game->avatar->pullTarget->stopPull(); dsq->game->avatar->pullTarget->stopPull();
@ -4202,10 +4202,10 @@ luaFunc(entity_msg)
Entity *e = entity(L); Entity *e = entity(L);
if (e) if (e)
{ {
int top = lua_gettop(L);
// pass everything on the stack except the entity pointer // pass everything on the stack except the entity pointer
e->messageVariadic(L, top - 1); int res = e->messageVariadic(L, lua_gettop(L) - 1);
return lua_gettop(L) - top; // return everything that was pushed on our stack if (res >= 0)
return res;
} }
luaReturnNil(); luaReturnNil();
} }
@ -9177,42 +9177,27 @@ bool Script::call(const char *name, void *param1, void *param2, void *param3, fl
return true; return true;
} }
bool Script::callVariadic(const char *name, lua_State *fromL, int nparams, void *param) int Script::callVariadic(const char *name, lua_State *fromL, int nparams, void *param)
{ {
lookupFunc(name); // [f] int oldtop = lua_gettop(L);
luaPushPointer(L, param); // [f, p]
if (L != fromL) lookupFunc(name);
{ luaPushPointer(L, param);
// clone topmost nparams elements, they will be popped by xmove
// If both stacks are the same, we already pushed 2 more entries to the stack.
int pos = (L == fromL) ? -(nparams+2) : -nparams;
for (int i = 0; i < nparams; ++i) for (int i = 0; i < nparams; ++i)
lua_pushvalue(fromL, -nparams); lua_pushvalue(fromL, pos);
// Move them to the other stack // Move them to the other stack. Ignored if L == fromL.
lua_xmove(fromL, L, nparams); // [f, p, ...] lua_xmove(fromL, L, nparams);
}
else
{
// Same stack, insert pointer param below the parameters which are already there
lua_insert(L, -(nparams + 2));
// and the function, now below the pointer param
lua_insert(L, -(nparams + 2));
}
// Do the call // Do the call
bool success = doCall(nparams + 1, LUA_MULTRET); if (!doCall(nparams + 1, LUA_MULTRET))
return -1;
// after returning from the call, push everything that is left on the stack nparams = lua_gettop(L) - oldtop;
// (= what the function returned) back onto the caller's stack, if not already there. lua_xmove(L, fromL, nparams);
if (success && L != fromL)
{
// clone elements again
int count = lua_gettop(L);
for (int i = 0; i < count; ++i)
lua_pushvalue(L, -count);
lua_xmove(L, fromL, count); return nparams;
}
return success;
} }

View file

@ -60,7 +60,8 @@ public:
// boolean = function(pointer, pointer, pointer, number, number, number, number, pointer) // boolean = function(pointer, pointer, pointer, number, number, number, number, pointer)
bool call(const char *name, void *param1, void *param2, void *param3, float param4, float param5, float param6, float param7, void *param8, bool *ret1); bool call(const char *name, void *param1, void *param2, void *param3, float param4, float param5, float param6, float param7, void *param8, bool *ret1);
// function(pointer, ...) - anything that is already on the stack is forwarded. Results are left on the stack. // function(pointer, ...) - anything that is already on the stack is forwarded. Results are left on the stack.
bool callVariadic(const char *name, lua_State *L, int nparams, void *param); // Returns how many values the called function returned, or -1 in case of error.
int callVariadic(const char *name, lua_State *L, int nparams, void *param);
lua_State *getLuaState() {return L;} lua_State *getLuaState() {return L;}
const std::string &getFile() {return file;} const std::string &getFile() {return file;}

View file

@ -96,14 +96,17 @@ void ScriptedEntity::message(const std::string &msg, int v)
Entity::message(msg, v); Entity::message(msg, v);
} }
void ScriptedEntity::messageVariadic(lua_State *L, int nparams) int ScriptedEntity::messageVariadic(lua_State *L, int nparams)
{ {
if (script) if (script)
{ {
if (!script->callVariadic("msg", L, nparams, this)) int res = script->callVariadic("msg", L, nparams, this);
if (res < 0)
luaDebugMsg("msg", script->getLastError()); luaDebugMsg("msg", script->getLastError());
else
return res;
} }
Entity::messageVariadic(L, nparams); return Entity::messageVariadic(L, nparams);
} }
void ScriptedEntity::warpSegments() void ScriptedEntity::warpSegments()

View file

@ -47,7 +47,7 @@ public:
void lightFlare(); void lightFlare();
void entityDied(Entity *e); void entityDied(Entity *e);
void message(const std::string &msg, int v); void message(const std::string &msg, int v);
void messageVariadic(lua_State *L, int nparams); int messageVariadic(lua_State *L, int nparams);
static bool runningActivation; static bool runningActivation;