コード例 #1
0
ファイル: th_lua_strings.cpp プロジェクト: tobylane/CorsixTH
// Generic string method handler
// The name of the method is stored at upvalue 1
static int l_str_func(lua_State *L)
{
    int iArgCount = lua_gettop(L);
    lua_checkstack(L, iArgCount + 10);

    int iUserdataCount = 0;

    // Construct the resulting value
    aux_push_weak_table(L, 0);
    for(int i = 1; i <= iArgCount; ++i)
    {
        lua_pushvalue(L, i);
        if(lua_type(L, i) == LUA_TUSERDATA)
        {
            lua_rawget(L, iArgCount + 1);
            ++iUserdataCount;
        }
    }
    lua_pushvalue(L, luaT_upvalueindex(1));
    lua_gettable(L, iArgCount + 2);
    lua_replace(L, iArgCount + 1);
    lua_call(L, iArgCount, 1);

    // Trivial case of result not depending upon any proxies
    if(iUserdataCount == 0)
        return 1;

    // Wrap result in a proxy
    l_str_new_aux(L);

    // Create and save reconstruction information
    lua_createtable(L, iArgCount + 1, 0);
    lua_pushvalue(L, luaT_upvalueindex(1));
    lua_rawseti(L, -2, 1);
    for(int i = 1; i <= iArgCount; ++i)
    {
        lua_pushvalue(L, i);
        lua_rawseti(L, -2, i + 1);
    }
    lua_setfenv(L, -2);

    return 1;
}
コード例 #2
0
static int l_mk_cache(lua_State *L)
{
    lua_newtable(L);
    lua_pushvalue(L, luaT_upvalueindex(1));
    lua_setmetatable(L, -2);
    lua_pushvalue(L, 2);
    lua_pushvalue(L, 3);
    lua_settable(L, 1);
    return 1;
}
コード例 #3
0
ファイル: th_lua_map.cpp プロジェクト: Alberth289346/CorsixTH
static int l_map_hittest(lua_State *L)
{
    level_map* pMap = luaT_testuserdata<level_map>(L);
    drawable* pObject = pMap->hit_test(static_cast<int>(luaL_checkinteger(L, 2)), static_cast<int>(luaL_checkinteger(L, 3)));
    if(pObject == nullptr)
        return 0;
    lua_rawgeti(L, luaT_upvalueindex(1), 1);
    lua_pushlightuserdata(L, pObject);
    lua_gettable(L, -2);
    return 1;
}
コード例 #4
0
ファイル: persist_lua.cpp プロジェクト: jamesblunt/CorsixTH
    void setErrorObject(int iStackObject)
    {
        if(m_bHadError)
            return;
        lua_State *L = m_L;

        lua_pushvalue(L, iStackObject);
        lua_getmetatable(L, luaT_upvalueindex(2));
        lua_insert(L, -2);
        lua_setfield(L, -2, "err");
        lua_pop(L, 1);
    }
コード例 #5
0
ファイル: sdl_core.cpp プロジェクト: admdly/CorsixTH
static int l_get_fps(lua_State *L)
{
    fps_ctrl *ctrl = (fps_ctrl*)lua_touserdata(L, luaT_upvalueindex(1));
    if(ctrl->track_fps)
    {
        lua_pushinteger(L, ctrl->frame_count);
    }
    else
    {
        lua_pushnil(L);
    }
    return 1;
}
コード例 #6
0
ファイル: persist_lua.cpp プロジェクト: jamesblunt/CorsixTH
 void init(const uint8_t *pData, size_t iLength)
 {
     lua_State *L = m_L;
     m_pData = pData;
     m_iDataBufferLength = iLength;
     m_iNextIndex = 1;
     m_bHadError = false;
     lua_createtable(L, 32, 0); // Environment
     lua_pushvalue(L, 2);
     lua_rawseti(L, -2, 0);
     lua_pushvalue(L, luaT_upvalueindex(1));
     lua_rawseti(L, -2, -1);
     lua_pushvalue(L, luaT_upvalueindex(2));
     lua_rawseti(L, -2, -2);
     lua_pushvalue(L, 1);
     lua_rawseti(L, -2, -3);
     lua_setfenv(L, 1);
     lua_createtable(L, 0, 1); // Metatable
     lua_pushcclosure(L, l_crude_gc<LuaPersistBasicReader>, 0);
     lua_setfield(L, -2, "__gc");
     lua_setmetatable(L, 1);
 }
コード例 #7
0
ファイル: th_lua_anims.cpp プロジェクト: AtlasRedux/CorsixTH
static int l_anims_draw(lua_State *L)
{
    THAnimationManager* pAnims = luaT_testuserdata<THAnimationManager>(L);
    THRenderTarget* pCanvas = luaT_testuserdata<THRenderTarget>(L, 2);
    int iFrame = luaL_checkint(L, 3);
    THLayers_t* pLayers = luaT_testuserdata<THLayers_t>(L, 4, luaT_upvalueindex(2));
    int iX = luaL_checkint(L, 5);
    int iY = luaL_checkint(L, 6);
    int iFlags = luaL_optint(L, 7, 0);

    pAnims->drawFrame(pCanvas, (unsigned int)iFrame, *pLayers, iX, iY, iFlags);

    lua_settop(L, 1);
    return 1;
}
コード例 #8
0
ファイル: th_lua_gfx.cpp プロジェクト: mounirlamouri/CorsixTH
static int l_rawbitmap_load(lua_State *L)
{
    THRawBitmap* pBitmap = luaT_testuserdata<THRawBitmap>(L);
    size_t iDataLen;
    const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen);
    int iWidth = static_cast<int>(luaL_checkinteger(L, 3));
    THRenderTarget* pSurface = luaT_testuserdata<THRenderTarget>(L, 4, luaT_upvalueindex(1), false);

    if(pBitmap->loadFromTHFile(pData, iDataLen, iWidth, pSurface))
        lua_pushboolean(L, 1);
    else
        lua_pushboolean(L, 0);

    return 1;
}
コード例 #9
0
ファイル: th_lua_gfx.cpp プロジェクト: mounirlamouri/CorsixTH
static int l_spritesheet_load(lua_State *L)
{
    THSpriteSheet* pSheet = luaT_testuserdata<THSpriteSheet>(L);
    size_t iDataLenTable, iDataLenChunk;
    const uint8_t* pDataTable = luaT_checkfile(L, 2, &iDataLenTable);
    const uint8_t* pDataChunk = luaT_checkfile(L, 3, &iDataLenChunk);
    bool bComplex = lua_toboolean(L, 4) != 0;
    THRenderTarget* pSurface = luaT_testuserdata<THRenderTarget>(L, 5, luaT_upvalueindex(1), false);

    if(pSheet->loadFromTHFile(pDataTable, iDataLenTable, pDataChunk, iDataLenChunk, bComplex, pSurface))
        lua_pushboolean(L, 1);
    else
        lua_pushboolean(L, 0);

    return 1;
}
コード例 #10
0
ファイル: persist_lua.cpp プロジェクト: jamesblunt/CorsixTH
    void init()
    {
        lua_State *L = m_L;
        lua_createtable(L, 1, 8); // Environment
        lua_pushvalue(L, 2); // Permanent objects
        lua_rawseti(L, -2, 1);
        lua_createtable(L, 1, 0); // Environment metatable
        lua_pushvalue(L, 2); // Permanent objects
        lua_pushvalue(L, 1); // self
        lua_pushcclosure(L, l_writer_mt_index, 2);
        lua_setfield(L, -2, "__index");
        lua_setmetatable(L, -2);
        lua_setfenv(L, 1);
        lua_createtable(L, 1, 4); // Metatable
        lua_pushcclosure(L, l_crude_gc<LuaPersistBasicWriter>, 0);
        lua_setfield(L, -2, "__gc");
        lua_pushvalue(L, luaT_upvalueindex(1)); // Prototype persistance names
        lua_rawseti(L, -2, 1);
        lua_setmetatable(L, 1);

        m_iNextIndex = 1;
        m_iDataLength = 0;
        m_bHadError = false;
    }
コード例 #11
0
ファイル: th_lua_map.cpp プロジェクト: sadger/CorsixTH
static int l_map_updateblueprint(lua_State *L)
{
    // NB: This function can be implemented in Lua, but is implemented in C for
    // efficiency.
    const unsigned short iFloorTileGood = 24 + (THDF_Alpha50 << 8);
    const unsigned short iFloorTileGoodCenter = 37 + (THDF_Alpha50 << 8);
    const unsigned short iFloorTileBad  = 67 + (THDF_Alpha50 << 8);
    const unsigned int iWallAnimTopCorner = 124;
    const unsigned int iWallAnim = 120;

    THMap* pMap = luaT_testuserdata<THMap>(L);
    int iOldX = static_cast<int>(luaL_checkinteger(L, 2)) - 1;
    int iOldY = static_cast<int>(luaL_checkinteger(L, 3)) - 1;
    int iOldW = static_cast<int>(luaL_checkinteger(L, 4));
    int iOldH = static_cast<int>(luaL_checkinteger(L, 5));
    int iNewX = static_cast<int>(luaL_checkinteger(L, 6)) - 1;
    int iNewY = static_cast<int>(luaL_checkinteger(L, 7)) - 1;
    int iNewW = static_cast<int>(luaL_checkinteger(L, 8));
    int iNewH = static_cast<int>(luaL_checkinteger(L, 9));
    luaL_checktype(L, 10, LUA_TTABLE); // Animation list
    THAnimationManager* pAnims = luaT_testuserdata<THAnimationManager>(L, 11, luaT_upvalueindex(1));
    bool entire_invalid = lua_toboolean(L, 12) != 0;
    bool valid = !entire_invalid;

    if(iOldX < 0 || iOldY < 0 || (iOldX + iOldW) > pMap->getWidth() || (iOldY + iOldH) > pMap->getHeight())
        luaL_argerror(L, 2, "Old rectangle is out of bounds");
    if(iNewX < 0 || iNewY < 0 || (iNewX + iNewW) >= pMap->getWidth() || (iNewY + iNewH) >= pMap->getHeight())
        luaL_argerror(L, 6, "New rectangle is out of bounds");

    // Clear blueprint flag from previous selected floor tiles (copying it to the passable flag).
    for(int iY = iOldY; iY < iOldY + iOldH; ++iY)
    {
        for(int iX = iOldX; iX < iOldX + iOldW; ++iX)
        {
            THMapNode *pNode = pMap->getNodeUnchecked(iX, iY);
            pNode->iBlock[3] = 0;
            uint32_t iFlags = pNode->iFlags;
            iFlags |= ((iFlags & THMN_PassableIfNotForBlueprint) != 0) ? THMN_Passable : 0;
            iFlags &= ~THMN_PassableIfNotForBlueprint;
            pNode->iFlags = iFlags;
        }
    }

    // Add blueprint flag to new floor tiles.
    for(int iY = iNewY; iY < iNewY + iNewH; ++iY)
    {
        for(int iX = iNewX; iX < iNewX + iNewW; ++iX)
        {
            THMapNode *pNode = pMap->getNodeUnchecked(iX, iY);
            if(is_valid(entire_invalid, pNode))
                pNode->iBlock[3] = iFloorTileGood;
            else
            {
                pNode->iBlock[3] = iFloorTileBad;
                valid = false;
            }
            pNode->iFlags |= ((pNode->iFlags & THMN_Passable) != 0) ? THMN_PassableIfNotForBlueprint : 0;
        }
    }

    // Set center floor tiles
    if(iNewW >= 2 && iNewH >= 2)
    {
        int iCenterX = iNewX + (iNewW - 2) / 2;
        int iCenterY = iNewY + (iNewH - 2) / 2;

        THMapNode *pNode = pMap->getNodeUnchecked(iCenterX, iCenterY);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 2;

        pNode = pMap->getNodeUnchecked(iCenterX + 1, iCenterY);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 1;

        pNode = pMap->getNodeUnchecked(iCenterX, iCenterY + 1);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 0;

        pNode = pMap->getNodeUnchecked(iCenterX + 1, iCenterY + 1);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 3;
    }

    // Set wall animations
    int iNextAnim = 1;
    THAnimation *pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
    THMapNode *pNode = pMap->getNodeUnchecked(iNewX, iNewY);
    pAnim->setAnimation(pAnims, iWallAnimTopCorner);
    pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode) ? 0 : THDF_AltPalette));
    pAnim->attachToTile(pNode, 0);

    for(int iX = iNewX; iX < iNewX + iNewW; ++iX)
    {
        if(iX != iNewX)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pNode = pMap->getNodeUnchecked(iX, iNewY);
            pAnim->setAnimation(pAnims, iWallAnim);
            pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode) ? 0 : THDF_AltPalette));
            pAnim->attachToTile(pNode, 0);
            pAnim->setPosition(0, 0);
        }
        pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
        pNode = pMap->getNodeUnchecked(iX, iNewY + iNewH - 1);
        pAnim->setAnimation(pAnims, iWallAnim);
        pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode) ? 0 : THDF_AltPalette));
        pNode = pMap->getNodeUnchecked(iX, iNewY + iNewH);
        pAnim->attachToTile(pNode, 0);
        pAnim->setPosition(0, -1);
    }
    for(int iY = iNewY; iY < iNewY + iNewH; ++iY)
    {
        if(iY != iNewY)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pNode = pMap->getNodeUnchecked(iNewX, iY);
            pAnim->setAnimation(pAnims, iWallAnim);
            pAnim->setFlags(THDF_ListBottom | THDF_FlipHorizontal | (is_valid(entire_invalid, pNode) ? 0 : THDF_AltPalette));
            pAnim->attachToTile(pNode, 0);
            pAnim->setPosition(2, 0);
        }
        pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
        pNode = pMap->getNodeUnchecked(iNewX + iNewW - 1, iY);
        pAnim->setAnimation(pAnims, iWallAnim);
        pAnim->setFlags(THDF_ListBottom | THDF_FlipHorizontal | (is_valid(entire_invalid, pNode) ? 0 : THDF_AltPalette));
        pNode = pMap->getNodeUnchecked(iNewX + iNewW, iY);
        pAnim->attachToTile(pNode, 0);
        pAnim->setPosition(2, -1);
    }

    // Clear away extra animations
    int iAnimCount = (int)lua_objlen(L, 10);
    if(iAnimCount >= iNextAnim)
    {
        for(int i = iNextAnim; i <= iAnimCount; ++i)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pAnim->removeFromTile();
            lua_pushnil(L);
            lua_rawseti(L, 10, i);
        }
    }

    lua_pushboolean(L, valid ? 1 : 0);
    return 1;
}
コード例 #12
0
ファイル: sdl_core.cpp プロジェクト: admdly/CorsixTH
static int l_mainloop(lua_State *L)
{
    luaL_checktype(L, 1, LUA_TTHREAD);
    lua_State *dispatcher = lua_tothread(L, 1);

    fps_ctrl *fps_control = (fps_ctrl*)lua_touserdata(L, luaT_upvalueindex(1));
    SDL_TimerID timer = SDL_AddTimer(30, timer_frame_callback, nullptr);
    SDL_Event e;

    while(SDL_WaitEvent(&e) != 0)
    {
        bool do_frame = false;
        bool do_timer = false;
        do
        {
            int nargs;
            switch(e.type)
            {
            case SDL_QUIT:
                goto leave_loop;
            case SDL_KEYDOWN:
                lua_pushliteral(dispatcher, "keydown");
                lua_pushstring(dispatcher, SDL_GetKeyName(e.key.keysym.sym));
                l_push_modifiers_table(dispatcher, e.key.keysym.mod);
                lua_pushboolean(dispatcher, e.key.repeat != 0);
                nargs = 4;
                break;
            case SDL_KEYUP:
                lua_pushliteral(dispatcher, "keyup");
                lua_pushstring(dispatcher, SDL_GetKeyName(e.key.keysym.sym));
                nargs = 2;
                break;
            case SDL_TEXTINPUT:
                lua_pushliteral(dispatcher, "textinput");
                lua_pushstring(dispatcher, e.text.text);
                nargs = 2;
                break;
            case SDL_TEXTEDITING:
                lua_pushliteral(dispatcher, "textediting");
                lua_pushstring(dispatcher, e.edit.text);
                lua_pushinteger(dispatcher, e.edit.start);
                lua_pushinteger(dispatcher, e.edit.length);
                nargs = 4;
                break;
            case SDL_MOUSEBUTTONDOWN:
                lua_pushliteral(dispatcher, "buttondown");
                lua_pushinteger(dispatcher, e.button.button);
                lua_pushinteger(dispatcher, e.button.x);
                lua_pushinteger(dispatcher, e.button.y);
                nargs = 4;
                break;
            case SDL_MOUSEBUTTONUP:
                lua_pushliteral(dispatcher, "buttonup");
                lua_pushinteger(dispatcher, e.button.button);
                lua_pushinteger(dispatcher, e.button.x);
                lua_pushinteger(dispatcher, e.button.y);
                nargs = 4;
                break;
            case SDL_MOUSEWHEEL:
                lua_pushliteral(dispatcher, "mousewheel");
                lua_pushinteger(dispatcher, e.wheel.x);
                lua_pushinteger(dispatcher, e.wheel.y);
                nargs = 3;
                break;
            case SDL_MOUSEMOTION:
                lua_pushliteral(dispatcher, "motion");
                lua_pushinteger(dispatcher, e.motion.x);
                lua_pushinteger(dispatcher, e.motion.y);
                lua_pushinteger(dispatcher, e.motion.xrel);
                lua_pushinteger(dispatcher, e.motion.yrel);
                nargs = 5;
                break;
            case SDL_WINDOWEVENT:
                switch (e.window.event) {
                    case SDL_WINDOWEVENT_FOCUS_GAINED:
                        lua_pushliteral(dispatcher, "active");
                        lua_pushinteger(dispatcher, 1);
                        nargs = 2;
                        break;
                    case SDL_WINDOWEVENT_FOCUS_LOST:
                        lua_pushliteral(dispatcher, "active");
                        lua_pushinteger(dispatcher, 0);
                        nargs = 2;
                        break;
                    default:
                        nargs = 0;
                        break;
                }
                break;
            case SDL_USEREVENT_MUSIC_OVER:
                lua_pushliteral(dispatcher, "music_over");
                nargs = 1;
                break;
            case SDL_USEREVENT_CPCALL:
                if(luaT_cpcall(L, (lua_CFunction)e.user.data1, e.user.data2))
                {
                    SDL_RemoveTimer(timer);
                    lua_pushliteral(L, "callback");
                    return 2;
                }
                nargs = 0;
                break;
            case SDL_USEREVENT_TICK:
                do_timer = true;
                nargs = 0;
                break;
            case SDL_USEREVENT_MOVIE_OVER:
                lua_pushliteral(dispatcher, "movie_over");
                nargs = 1;
                break;
            case SDL_USEREVENT_SOUND_OVER:
                lua_pushliteral(dispatcher, "sound_over");
                lua_pushinteger(dispatcher, *(static_cast<int*>(e.user.data1)));
                nargs = 2;
                break;
            default:
                nargs = 0;
                break;
            }
            if(nargs != 0)
            {
                if(luaT_resume(dispatcher, dispatcher, nargs) != LUA_YIELD)
                {
                    goto leave_loop;
                }
                do_frame = do_frame || (lua_toboolean(dispatcher, 1) != 0);
                lua_settop(dispatcher, 0);
            }
        } while(SDL_PollEvent(&e) != 0);
        if(do_timer)
        {
            lua_pushliteral(dispatcher, "timer");
            if(luaT_resume(dispatcher, dispatcher, 1) != LUA_YIELD)
            {
                break;
            }
            do_frame = do_frame || (lua_toboolean(dispatcher, 1) != 0);
            lua_settop(dispatcher, 0);
        }
        if(do_frame || !fps_control->limit_fps)
        {
            do
            {
                if(fps_control->track_fps)
                {
                    fps_control->count_frame();
                }
                lua_pushliteral(dispatcher, "frame");
                if(luaT_resume(dispatcher, dispatcher, 1) != LUA_YIELD)
                {
                    goto leave_loop;
                }
                lua_settop(dispatcher, 0);
            } while(fps_control->limit_fps == false && SDL_PollEvent(nullptr) == 0);
        }

        // No events pending - a good time to do a bit of garbage collection
        lua_gc(L, LUA_GCSTEP, 2);
    }

leave_loop:
    SDL_RemoveTimer(timer);
    int n = lua_gettop(dispatcher);
    if(lua_status(dispatcher) >= LUA_ERRRUN)
    {
        n = 1;
    }
    lua_checkstack(L, n);
    lua_xmove(dispatcher, L, n);
    return n;
}
コード例 #13
0
ファイル: persist_lua.cpp プロジェクト: jamesblunt/CorsixTH
static int l_writer_mt_index(lua_State *L)
{
    return reinterpret_cast<LuaPersistBasicWriter*>(
        lua_touserdata(L, luaT_upvalueindex(2)))->writeObjectRaw();
}
コード例 #14
0
ファイル: sdl_core.cpp プロジェクト: admdly/CorsixTH
static int l_limit_fps(lua_State *L)
{
    fps_ctrl *ctrl = (fps_ctrl*)lua_touserdata(L, luaT_upvalueindex(1));
    ctrl->limit_fps = lua_isnone(L, 1) ? true : (lua_toboolean(L, 1) != 0);
    return 0;
}
コード例 #15
0
ファイル: persist_lua.cpp プロジェクト: jamesblunt/CorsixTH
    int writeObjectRaw()
    {
        lua_State *L = m_L;
        uint8_t iType;

        // Save the index to the cache
        lua_pushvalue(L, 2);
        lua_pushnumber(L, (lua_Number)(m_iNextIndex++));
        lua_settable(L, 1);

        // Lookup the object in the permanents table
        lua_pushvalue(L, 2);
        lua_gettable(L, luaT_upvalueindex(1));
        if(lua_type(L, -1) != LUA_TNIL)
        {
            // Object is in the permanents table.

            uint8_t iType = PERSIST_TPERMANENT;
            writeByteStream(&iType, 1);

            // Replace self's environment with self (for call to writeStackObject)
            lua_pushvalue(L, luaT_upvalueindex(2));
            lua_replace(L, 1);

            // Write the key corresponding to the permanent object
            writeStackObject(-1);
        }
        else
        {
            // Object is not in the permanents table.
            lua_pop(L, 1);

            switch(lua_type(L, 2))
            {
            // LUA_TNIL handled in writeStackObject
            // LUA_TBOOLEAN handled in writeStackObject
            // LUA_TNUMBER handled in writeStackObject

            case LUA_TSTRING: {
                iType = LUA_TSTRING;
                writeByteStream(&iType, 1);
                // Strings are simple: length and then bytes (not null terminated)
                size_t iLength;
                const char *sString = lua_tolstring(L, 2, &iLength);
                writeVUInt(iLength);
                writeByteStream(reinterpret_cast<const uint8_t*>(sString), iLength);
                break; }

            case LUA_TTABLE: {
                // Replace self's environment with self (for calls to writeStackObject)
                lua_pushvalue(L, luaT_upvalueindex(2));
                lua_replace(L, 1);

                // Save env and insert prior to table
                lua_getfenv(L, 1);
                lua_insert(L, 2);

                int iTable = 3; table_reentry:

                // Handle the metatable
                if(lua_getmetatable(L, iTable))
                {
                    iType = PERSIST_TTABLE_WITH_META;
                    writeByteStream(&iType, 1);
                    writeStackObject(-1);
                    lua_pop(L, 1);
                }
                else
                {
                    iType = LUA_TTABLE;
                    writeByteStream(&iType, 1);
                }

                // Write the children as key, value pairs
                lua_pushnil(L);
                while(lua_next(L, iTable))
                {
                    writeStackObject(-2);
                    // The naive thing to do now would be writeStackObject(-1)
                    // but this can easily lead to Lua's C call stack limit
                    // being hit. To reduce the likelyhood of this happening,
                    // we check to see if about to write another table.
                    if(lua_type(L, -1) == LUA_TTABLE)
                    {
                        lua_pushvalue(L, -1);
                        lua_rawget(L, 2);
                        lua_pushvalue(L, -2);
                        lua_gettable(L, luaT_upvalueindex(1));
                        if(lua_isnil(L, -1) && lua_isnil(L, -2))
                        {
                            lua_pop(L, 2);
                            lua_checkstack(L, 10);
                            iTable += 2;
                            lua_pushvalue(L, iTable);
                            lua_pushnumber(L, (lua_Number)(m_iNextIndex++));
                            lua_settable(L, 2);
                            goto table_reentry; table_resume:
                            iTable -= 2;
                        }
                        else
                        {
                            lua_pop(L, 2);
                            writeStackObject(-1);
                        }
                    }
                    else
                        writeStackObject(-1);
                    lua_pop(L, 1);
                }

                // Write a nil to mark the end of the children (as nil is the
                // only value which cannot be used as a key in a table).
                iType = LUA_TNIL;
                writeByteStream(&iType, 1);
                if(iTable != 3)
                    goto table_resume;
                break; }

            case LUA_TFUNCTION:
                if(lua_iscfunction(L, 2))
                {
                    setErrorObject(2);
                    setError("Cannot persist C functions");
                }
                else
                {
                    iType = LUA_TFUNCTION;
                    writeByteStream(&iType, 1);

                    // Replace self's environment with self (for calls to writeStackObject)
                    lua_pushvalue(L, luaT_upvalueindex(2));
                    lua_replace(L, 1);

                    // Write the prototype (the part of a function which is common across
                    // multiple closures - see LClosure / Proto in Lua's lobject.h).
                    lua_Debug proto_info;
                    lua_pushvalue(L, 2);
                    lua_getinfo(L, ">Su", &proto_info);
                    writePrototype(&proto_info, 2);

                    // Write the values of the upvalues
                    // If available, also write the upvalue IDs (so that in
                    // the future, we could hypothetically rejoin shared
                    // upvalues). An ID is just an opaque sequence of bytes.
                    writeVUInt(proto_info.nups);
#if LUA_VERSION_NUM >= 502
                    writeVUInt(sizeof(void*));
#else
                    writeVUInt(0);
#endif
                    for(int i = 1; i <= proto_info.nups; ++i)
                    {
                        lua_getupvalue(L, 2, i);
                        writeStackObject(-1);
#if LUA_VERSION_NUM >= 502
                        void *pUpvalueID = lua_upvalueid(L, 2, i);
                        writeByteStream((uint8_t*)&pUpvalueID, sizeof(void*));
#endif
                    }

                    // Write the environment table
                    lua_getfenv(L, 2);
                    writeStackObject(-1);
                    lua_pop(L, 1);
                }
                break;

            case LUA_TUSERDATA:
                if(!_checkThatUserdataCanBeDepersisted(2))
                    break;

                // Replace self's environment with self (for calls to writeStackObject)
                lua_pushvalue(L, luaT_upvalueindex(2));
                lua_replace(L, 1);

                // Write type, metatable, and then environment
                iType = LUA_TUSERDATA;
                writeByteStream(&iType, 1);
                writeStackObject(-1);
                lua_getfenv(L, 2);
                writeStackObject(-1);
                lua_pop(L, 1);

                // Write the raw data
                if(lua_type(L, -1) == LUA_TTABLE)
                {
                    lua_getfield(L, -1, "__persist");
                    if(lua_isnil(L, -1))
                        lua_pop(L, 1);
                    else
                    {
                        lua_pushvalue(L, 2);
                        lua_pushvalue(L, luaT_upvalueindex(2));
                        lua_call(L, 2, 0);
                    }
                }
                writeVUInt((uint64_t)0x42); // sync marker
                break;

            default:
                setError(lua_pushfstring(L, "Cannot persist %s values", luaL_typename(L, 2)));
                break;
            }
        }
        lua_pushnumber(L, 0);
        return 1;
    }
コード例 #16
0
ファイル: th_lua_map.cpp プロジェクト: Alberth289346/CorsixTH
static int l_map_updateblueprint(lua_State *L)
{
    // NB: This function can be implemented in Lua, but is implemented in C for
    // efficiency.
    const unsigned short iFloorTileGood = 24 + (thdf_alpha_50 << 8);
    const unsigned short iFloorTileGoodCenter = 37 + (thdf_alpha_50 << 8);
    const unsigned short iFloorTileBad  = 67 + (thdf_alpha_50 << 8);
    const unsigned int iWallAnimTopCorner = 124;
    const unsigned int iWallAnim = 120;

    level_map* pMap = luaT_testuserdata<level_map>(L);
    int iOldX = static_cast<int>(luaL_checkinteger(L, 2)) - 1;
    int iOldY = static_cast<int>(luaL_checkinteger(L, 3)) - 1;
    int iOldW = static_cast<int>(luaL_checkinteger(L, 4));
    int iOldH = static_cast<int>(luaL_checkinteger(L, 5));
    int iNewX = static_cast<int>(luaL_checkinteger(L, 6)) - 1;
    int iNewY = static_cast<int>(luaL_checkinteger(L, 7)) - 1;
    int iNewW = static_cast<int>(luaL_checkinteger(L, 8));
    int iNewH = static_cast<int>(luaL_checkinteger(L, 9));
    int player_id = static_cast<int>(luaL_checkinteger(L, 10));

    luaL_checktype(L, 11, LUA_TTABLE); // Animation list
    animation_manager* pAnims = luaT_testuserdata<animation_manager>(L, 12, luaT_upvalueindex(1));
    bool entire_invalid = lua_toboolean(L, 13) != 0;
    bool valid = !entire_invalid;

    if(iOldX < 0 || iOldY < 0 || (iOldX + iOldW) > pMap->get_width() || (iOldY + iOldH) > pMap->get_height())
        luaL_argerror(L, 2, "Old rectangle is out of bounds");
    if(iNewX < 0 || iNewY < 0 || (iNewX + iNewW) >= pMap->get_width() || (iNewY + iNewH) >= pMap->get_height())
        luaL_argerror(L, 6, "New rectangle is out of bounds");

    // Clear blueprint flag from previous selected floor tiles (copying it to the passable flag).
    for(int iY = iOldY; iY < iOldY + iOldH; ++iY)
    {
        for(int iX = iOldX; iX < iOldX + iOldW; ++iX)
        {
            map_tile *pNode = pMap->get_tile_unchecked(iX, iY);
            pNode->iBlock[3] = 0;
            pNode->flags.passable |= pNode->flags.passable_if_not_for_blueprint;
            pNode->flags.passable_if_not_for_blueprint = false;
        }
    }

    // Add blueprint flag to new floor tiles.
    for(int iY = iNewY; iY < iNewY + iNewH; ++iY)
    {
        for(int iX = iNewX; iX < iNewX + iNewW; ++iX)
        {
            map_tile *pNode = pMap->get_tile_unchecked(iX, iY);
            if(is_valid(entire_invalid, pNode, pMap, player_id))
                pNode->iBlock[3] = iFloorTileGood;
            else
            {
                pNode->iBlock[3] = iFloorTileBad;
                valid = false;
            }
            pNode->flags.passable_if_not_for_blueprint = pNode->flags.passable;
        }
    }

    // Set center floor tiles
    if(iNewW >= 2 && iNewH >= 2)
    {
        int iCenterX = iNewX + (iNewW - 2) / 2;
        int iCenterY = iNewY + (iNewH - 2) / 2;

        map_tile *pNode = pMap->get_tile_unchecked(iCenterX, iCenterY);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 2;

        pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 1;

        pNode = pMap->get_tile_unchecked(iCenterX, iCenterY + 1);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 0;

        pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY + 1);
        if(pNode->iBlock[3] == iFloorTileGood)
            pNode->iBlock[3] = iFloorTileGoodCenter + 3;
    }

    // Set wall animations
    int iNextAnim = 1;
    animation *pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
    map_tile *pNode = pMap->get_tile_unchecked(iNewX, iNewY);
    pAnim->set_animation(pAnims, iWallAnimTopCorner);
    pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette));
    pAnim->attach_to_tile(pNode, 0);

    for(int iX = iNewX; iX < iNewX + iNewW; ++iX)
    {
        if(iX != iNewX)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pNode = pMap->get_tile_unchecked(iX, iNewY);
            pAnim->set_animation(pAnims, iWallAnim);
            pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette));
            pAnim->attach_to_tile(pNode, 0);
            pAnim->set_position(0, 0);
        }
        pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
        pNode = pMap->get_tile_unchecked(iX, iNewY + iNewH - 1);
        pAnim->set_animation(pAnims, iWallAnim);
        pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette));
        pNode = pMap->get_tile_unchecked(iX, iNewY + iNewH);
        pAnim->attach_to_tile(pNode, 0);
        pAnim->set_position(0, -1);
    }
    for(int iY = iNewY; iY < iNewY + iNewH; ++iY)
    {
        if(iY != iNewY)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pNode = pMap->get_tile_unchecked(iNewX, iY);
            pAnim->set_animation(pAnims, iWallAnim);
            pAnim->set_flags(thdf_list_bottom | thdf_flip_horizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette));
            pAnim->attach_to_tile(pNode, 0);
            pAnim->set_position(2, 0);
        }
        pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
        pNode = pMap->get_tile_unchecked(iNewX + iNewW - 1, iY);
        pAnim->set_animation(pAnims, iWallAnim);
        pAnim->set_flags(thdf_list_bottom | thdf_flip_horizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette));
        pNode = pMap->get_tile_unchecked(iNewX + iNewW, iY);
        pAnim->attach_to_tile(pNode, 0);
        pAnim->set_position(2, -1);
    }

    // Clear away extra animations
    int iAnimCount = (int)lua_objlen(L, 11);
    if(iAnimCount >= iNextAnim)
    {
        for(int i = iNextAnim; i <= iAnimCount; ++i)
        {
            pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim);
            pAnim->remove_from_tile();
            lua_pushnil(L);
            lua_rawseti(L, 11, i);
        }
    }

    lua_pushboolean(L, valid ? 1 : 0);
    return 1;
}
コード例 #17
0
ファイル: th_lua_gfx.cpp プロジェクト: mounirlamouri/CorsixTH
static int l_cursor_position(lua_State *L)
{
    THRenderTarget* pCanvas = luaT_testuserdata<THRenderTarget>(L, 1, luaT_upvalueindex(1));
    lua_pushboolean(L, THCursor::setPosition(pCanvas, static_cast<int>(luaL_checkinteger(L, 2)), static_cast<int>(luaL_checkinteger(L, 3))) ? 1 : 0);
    return 1;
}