在 Lua 中创建动态数组

Creating a dynamic array in Lua

提问人:C Kolkman 提问时间:8/12/2023 最后编辑:OkaC Kolkman 更新时间:8/13/2023 访问量:135

问:

我是使用 Lua 编程的新手,所以请原谅我的愚蠢。 我正在尝试使用 Lua for QBcore (FiveM) 创建一个动态数组,但是当我创建数组时,我总是以索引 (?) 结尾。

Code with index

这使得游戏中的菜单不起作用(我认为..)。

我的代码是:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    local menuItems = createRadialJobExtrasMenu(myJob.onduty)
    
    if myJob.name == "ems" or myJob.name == "police" then
        mdtMenu = exports['qb-radialmenu']:AddOption({
            menuItems
        }, mdtMenu)
    end
    
    print(QBCore.Debug(mdtMenu))
    --print(mdtMenu)
end)

上面代码中使用的函数:

function createRadialJobExtrasMenu(onduty)
    local extra_menuItems = {}
    local mdtMenu = {
        id = 'job_extras',
        title = 'Job Extras',
        icon = "square-plus",
        items = {
            open_mdt = {
                title = 'Open MDT menu',
                icon = "tablet-screen-button",
                type = 'command',
                event = "mdt",
                shouldClose = true
            },
            my_data = {
                title = 'My Data',
                icon = "person",
                type = 'command',
                event = "myaddons-myinfo",
                shouldClose = true
            },
            mdt_signonoff = {},
        }
    }
    
    if onduty then
        mdt_signonoff = {
            title = 'Sign Off (Duty)',
            icon = "circle-xmark",
            type = 'command',
            event = 'myaddons-toggleduty',
            shouldClose = true
        }
    else
        mdt_signonoff = {
            title = 'Sign On (Duty)',
            icon = "check-to-slot",
            type = 'command',
            event = 'myaddons-toggleduty',
            shouldClose = true
        }
    end
    
    table.insert(mdtMenu.items.mdt_signonoff, mdt_signonoff)
    
    return mdtMenu
end

期望值班时的菜单(注意第三个条目):items:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
            mdtMenu = exports['qb-radialmenu']:AddOption({
                id = 'job_extras',
                title = 'Job Extras',
                icon = "square-plus",
                items = {
                    {
                        id = 'open_mdt',
                        title = 'Open MDT menu',
                        icon = "tablet-screen-button",
                        type = 'command',
                        event = "mdt",
                        shouldClose = true
                    },
                    {
                        id = 'my_data',
                        title = 'My Data',
                        icon = "person",
                        type = 'command',
                        event = "myaddons-myinfo",
                        shouldClose = true
                    },
                    {
                        id = 'mdt_signoff',
                        title = 'Sign Off (Duty)',
                        icon = "circle-xmark",
                        type = 'command',
                        event = 'myaddons-toggleduty',
                        shouldClose = true
                    },
                }
            }, mdtMenu)
    end
end)

下班时(注意第三个条目):items:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
            mdtMenu = exports['qb-radialmenu']:AddOption({
                id = 'job_extras',
                title = 'Job Extras',
                icon = "square-plus",
                items = {
                    {
                        id = 'open_mdt',
                        title = 'Open MDT menu',
                        icon = "tablet-screen-button",
                        type = 'command',
                        event = "mdt",
                        shouldClose = true
                    },
                    {
                        id = 'my_data',
                        title = 'My Data',
                        icon = "person",
                        type = 'command',
                        event = "myaddons-myinfo",
                        shouldClose = true
                    },
                    {
                        id = 'mdt_signon',
                        title = 'Sign On (Duty)',
                        icon = "check-to-slot",
                        type = 'command',
                        event = 'myaddons-toggleduty',
                        shouldClose = true
                    },
                }
            }, mdtMenu)
    end
end)

我希望我的问题能引起任何意义。

编辑:更改了代码,因为我认为@Vlad意味着,但这仍然给我留下了 1 个索引 (?) 数字。

编辑2:唯一正确的结构如下所示:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
        mdtMenu = exports['qb-radialmenu']:AddOption({
            id = 'job_extras',
            title = 'Job Extras',
            icon = "square-plus",
            items = {
                {
                    id = 'open_mdt',
                    title = 'Open MDT menu',
                    icon = "tablet-screen-button",
                    type = 'command',
                    event = "mdt",
                    shouldClose = true
                },
                {
                    id = 'my_data',
                    title = 'My Data',
                    icon = "person",
                    type = 'command',
                    event = "myaddons-myinfo",
                    shouldClose = true
                },
            }
        }, mdtMenu)
    end
end)

但是当我动态尝试添加带有以下代码的菜单项时,我收到错误。

if myJob.onduty then
        table.insert(mdtMenu.items, {id = 'mdt_signoff', title = 'Sign Off (Duty)', icon = "circle-xmark", type = 'command', event = 'myaddons-toggleduty', shouldClose = true})
    else
        table.insert(mdtMenu.items, {id = 'mdt_signon', title = 'Sign On (Duty)', icon = "check-to-slot", type = 'command', event = 'myaddons-toggleduty', shouldClose = true})
    end

完整的代码块:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
        mdtMenu = exports['qb-radialmenu']:AddOption({
            id = 'job_extras',
            title = 'Job Extras',
            icon = "square-plus",
            items = {
                {
                    id = 'open_mdt',
                    title = 'Open MDT menu',
                    icon = "tablet-screen-button",
                    type = 'command',
                    event = "mdt",
                    shouldClose = true
                },
                {
                    id = 'my_data',
                    title = 'My Data',
                    icon = "person",
                    type = 'command',
                    event = "myaddons-myinfo",
                    shouldClose = true
                },
            }
        }, mdtMenu)
    end
    
    if myJob.onduty then
        table.insert(mdtMenu.items, {id = 'mdt_signoff', title = 'Sign Off (Duty)', icon = "circle-xmark", type = 'command', event = 'myaddons-toggleduty', shouldClose = true})
    else
        table.insert(mdtMenu.items, {id = 'mdt_signon', title = 'Sign On (Duty)', icon = "check-to-slot", type = 'command', event = 'myaddons-toggleduty', shouldClose = true})
    end
end)

我收到的错误:

Error

它正在使用以下代码,但这意味着我必须为每个动态菜单项重新创建完整的菜单,使菜单不那么动态:

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
        if myJob.onduty then
            mdtMenu = exports['qb-radialmenu']:AddOption({
                id = 'job_extras',
                title = 'Job Extras',
                icon = "square-plus",
                items = {
                    {
                        id = 'open_mdt',
                        title = 'Open MDT menu',
                        icon = "tablet-screen-button",
                        type = 'command',
                        event = "mdt",
                        shouldClose = true
                    },
                    {
                        id = 'my_data',
                        title = 'My Data',
                        icon = "person",
                        type = 'command',
                        event = "myaddons-myinfo",
                        shouldClose = true
                    },
                    {
                        id = 'mdt_signoff',
                        title = 'Sign Off (Duty)',
                        icon = "circle-xmark",
                        type = 'command',
                        event = 'myaddons-toggleduty',
                        shouldClose = true
                    },
                }
            }, mdtMenu)
        else
            mdtMenu = exports['qb-radialmenu']:AddOption({
                id = 'job_extras',
                title = 'Job Extras',
                icon = "square-plus",
                items = {
                    {
                        id = 'open_mdt',
                        title = 'Open MDT menu',
                        icon = "tablet-screen-button",
                        type = 'command',
                        event = "mdt",
                        shouldClose = true
                    },
                    {
                        id = 'my_data',
                        title = 'My Data',
                        icon = "person",
                        type = 'command',
                        event = "myaddons-myinfo",
                        shouldClose = true
                    },
                    {
                        id = 'mdt_signon',
                        title = 'Sign On (Duty)',
                        icon = "check-to-slot",
                        type = 'command',
                        event = 'myaddons-toggleduty',
                        shouldClose = true
                    },
                }
            }, mdtMenu)
        end
    end
end)

编辑3:下面的代码似乎可以工作(感谢@dt192!!):

local mdtMenu = nil
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
    
    local myData = QBCore.Functions.GetPlayerData()
    local myJob = myData.job
    
    if myJob.name == "ems" or myJob.name == "police" then
        local myTable = createRadialJobExtrasMenu(myJob.onduty)
        
        mdtMenu = exports['qb-radialmenu']:AddOption(myTable, mdtMenu)
    end
end)

AddEventHandler('onResourceStop', function(resource)
    if mdtMenu ~= nil then
        exports['qb-radialmenu']:RemoveOption(mdtMenu)
        mdtMenu = nil
    end
end)

使用以下功能:

function createRadialJobExtrasMenu(onduty)
    local tbl = {
        id = 'job_extras',
        title = 'Job Extras',
        icon = "square-plus",
        items = {
            {
                id = 'open_mdt',
                title = 'Open MDT menu',
                icon = "tablet-screen-button",
                type = 'command',
                event = "mdt",
                shouldClose = true
            },
            {
                id = 'my_data',
                title = 'My Data',
                icon = "person",
                type = 'command',
                event = "myaddons-myinfo",
                shouldClose = true
            },
            {
                id = 'mdt_signon',
                title = 'Sign On (Duty)',
                icon = "check-to-slot",
                type = 'command',
                event = 'myaddons-toggleduty',
                shouldClose = true
            },
        }
    }

    if onduty then
        tbl.items[3].id = 'mdt_signoff'
        tbl.items[3].title = 'Sign Off (Duty)'
        tbl.items[3].icon = 'circle-xmark'
    end
    
    return tbl
end
lua lua-table

评论

0赞 dt192 8/12/2023
似乎你应该这样做而不是mdtMenu.items.mdt_signonoff = mdt_signonofftable.insert(mdtMenu.items.mdt_signonoff, mdt_signonoff)
0赞 C Kolkman 8/12/2023
@dt192 我似乎对这个评论越来越近了(例如,数字现在不再显示),但数组的结构似乎不正确,因为菜单没有显示在游戏中。在我问题的底部,您会看到 2 个正确的结构(值班和非值班代码)。

答:

0赞 Vlad 8/12/2023 #1

您正在创建数组数组。但是,在将保存集合值的数组存储在保存所有集合的顶级数组中时,您没有提供键值。您刚刚将密钥存储为集合本身中的项。

它应该是什么样子:

items = {
  open_mdt = {
    collection1
  },
  my_data = {
    collection2
  }
}

此格式仅适用于没有空格的字符串,处理数字和任意字符串的一般语法为:

items = {
  ["open mdt with spaces"] = {
    collection1
  },
  [37] = {
    collection2
  }
}

评论

0赞 C Kolkman 8/12/2023
您好弗拉德,感谢您的快速回复!对不起,我仍然不完全理解。您能否使用我需要的代码给出一个完整的示例?
1赞 dt192 8/12/2023 #2

你可能会做这样的事情

    local tbl = {
        id = 'job_extras',
        title = 'Job Extras',
        icon = "square-plus",
        items = {
            {
                id = 'open_mdt',
                title = 'Open MDT menu',
                icon = "tablet-screen-button",
                type = 'command',
                event = "mdt",
                shouldClose = true
            },
            {
                id = 'my_data',
                title = 'My Data',
                icon = "person",
                type = 'command',
                event = "myaddons-myinfo",
                shouldClose = true
            },
            {
                id = 'mdt_signon',
                title = 'Sign On (Duty)',
                icon = "check-to-slot",
                type = 'command',
                event = 'myaddons-toggleduty',
                shouldClose = true
            },
        }
    }

    if myJob.onduty then
        tbl.items[3].id = 'mdt_signoff'
        tbl.items[3].title = 'Sign Off (Duty)'
        tbl.items[3].icon = 'circle-xmark'
    end

    mdtMenu = exports['qb-radialmenu']:AddOption(tbl, mdtMenu)

您也可以像这样内联检查

    mdtMenu = exports['qb-radialmenu']:AddOption({
        id = 'job_extras',
        title = 'Job Extras',
        icon = "square-plus",
        items = {
            {
                id = 'open_mdt',
                title = 'Open MDT menu',
                icon = "tablet-screen-button",
                type = 'command',
                event = "mdt",
                shouldClose = true
            },
            {
                id = 'my_data',
                title = 'My Data',
                icon = "person",
                type = 'command',
                event = "myaddons-myinfo",
                shouldClose = true
            },
            {
                id = myJob.onduty and 'mdt_signoff' or 'mdt_signon',
                title = myJob.onduty and 'Sign Off (Duty)' or 'Sign On (Duty)',
                icon = myJob.onduty and 'circle-xmark' or 'check-to-slot',
                type = 'command',
                event = 'myaddons-toggleduty',
                shouldClose = true
            },
        }
    }, mdtMenu)

或(不确定此时使用的是哪个版本)

        mdtMenu.item.mdt_signonoff = {
            title = myJob.onduty and 'Sign Off (Duty)' or 'Sign On (Duty)',
            icon = myJob.onduty and 'circle-xmark' or 'check-to-slot',
            type = 'command',
            event = 'myaddons-toggleduty',
            shouldClose = true
        }

评论

0赞 C Kolkman 8/12/2023
你是天才!这似乎工作正常!我已将其标记为答案,并在我的原始帖子中添加了我的新代码!Edit3