From 3d8468b26490c039d2cd004287a84b56aad2adf3 Mon Sep 17 00:00:00 2001 From: liuzujun <307836273@qq.com> Date: Thu, 18 Mar 2021 17:47:46 +0800 Subject: [PATCH] 火花系统 --- src/GlobalVar.lua | 1 + src/ProtocolCode.lua | 5 +++++ src/RedisKeys.lua | 2 ++ src/actions/CarAction.lua | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/actions/GmAction.lua | 16 ++++++++++++++++ src/actions/HeroAction.lua | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/actions/RoleAction.lua | 30 +++++++++++++++++++++++++++++- src/csvdata | 2 +- src/models/Hero.lua | 8 +++++--- src/models/HeroPlugin.lua | 15 +++++++++++++++ src/models/Role.lua | 1 + src/models/RoleLog.lua | 6 ++++++ src/models/RolePlugin.lua | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/models/Spark.lua | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 435 insertions(+), 6 deletions(-) create mode 100644 src/models/Spark.lua diff --git a/src/GlobalVar.lua b/src/GlobalVar.lua index 54af52d..d121048 100644 --- a/src/GlobalVar.lua +++ b/src/GlobalVar.lua @@ -81,6 +81,7 @@ ItemType = { SelectItemBox = 17, -- 自选箱子 CommonPaster = 18, -- 万能贴纸 BossTicket = 20, -- boss挑战门票 + Spark = 21, -- 火花 } --在这个里面的会记录的是功能开放 对应类型open 而不是 ID diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index ca8a513..7756669 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -51,6 +51,8 @@ actionCodes = { Role_broadGetSSR = 135, -- 全服广播 获得ssr英雄 Role_renameTeamRpc = 136, -- 编队改名 Role_accuseRpc = 137, -- 举报 + Role_loadSparks = 138, + Role_updateSpark = 139, -- 更新火花 Adv_startAdvRpc = 151, Adv_startHangRpc = 152, @@ -102,6 +104,7 @@ actionCodes = { Hero_drawHeroExtraRewardNtf = 224, Hero_itemComposeRpc = 225, Hero_setWishPoolRpc = 226, + Hero_changeSparkRpc = 227, Hang_startRpc = 251, Hang_checkRpc = 252, @@ -152,6 +155,8 @@ actionCodes = { Car_runeUpRpc = 402, Car_saleEquipRpc = 403, Car_saleRuneRpc = 404, + Car_sparkLvlUpRpc = 405, + Car_sparkQualityUpRpc = 406, Friend_searchRpc = 450, diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index 3a5660d..068340a 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -14,6 +14,8 @@ R_EMAIL_ITEM = "email:%d:%d" --邮件 R_STORE = "role:%d:store" -- 商店 R_ORDERS = "role:%d:orders" -- 订单 R_ORDER = "order:%d:%d" +R_SPARKIDS = "role:%d:sparkIds" -- 玩家拥有火花自增id +R_SPARK = "role:%d:spark:%d" -- 火花详细信息 -- 通用排行榜 RANK_COMMON = "rank:common:" diff --git a/src/actions/CarAction.lua b/src/actions/CarAction.lua index 6685f4f..d72ec5d 100644 --- a/src/actions/CarAction.lua +++ b/src/actions/CarAction.lua @@ -211,4 +211,92 @@ function _M.saleRuneRpc(agent, data ) return true end +function _M.sparkQualityUpRpc( agent, data ) + local role = agent.role + local msg = MsgPack.unpack(data) + local uid = msg.uid + local ownSpark = role.sparkBag[uid] + if not ownSpark then return 1 end + + + local cfg_id = ownSpark:getProperty("cfg_id") + local level = ownSpark:getProperty("level") + + local sparkSet = csvdb["sparkCsv"][cfg_id] + if not sparkSet then return 4 end + local sparkData = sparkSet[level] + if not sparkData then return 5 end + + if sparkData.star_up == 0 then return 6 end + local cost = sparkData.star_item:toNumMap() + if not role:checkItemEnough(cost) then + return 7 + end + + role:costItems(cost, {log = {desc = "sparkQualityUp", int1 = uid, int2 = level}}) + + local newSet = csvdb["sparkCsv"][sparkData.star_up] + if not newSet then return 8 end + local newSparkData = newSet[0] + if not newSparkData then return 9 end + local attrs = newSparkData.attr:toNumMap() + ownSpark:addAttr(attrs) + ownSpark:updateProperty({field = "level",value = 0}) + ownSpark:updateProperty({field = "cfg_id",value = sparkData.star_up}) + --role:checkTaskEnter("SparkQualityUp") + + + ownSpark:mylog({desc = "sparkQualityUp", int1 = sparkData.id , int2 = sparkData.star_up}) + + SendPacket(actionCodes.Car_sparkQualityUpRpc, '') + return true +end + +function _M.sparkLvlUpRpc( agent, data ) + local role = agent.role + local msg = MsgPack.unpack(data) + local uid = msg.uid + local ownSpark = role.sparkBag[uid] + if not ownSpark then return 1 end + + + local cfg_id = ownSpark:getProperty("cfg_id") + local level = ownSpark:getProperty("level") + + local sparkSet = csvdb["sparkCsv"][cfg_id] + if not sparkSet then return 4 end + local sparkData = sparkSet[level] + if not sparkData then return 5 end + + if level >= #sparkSet then return 6 end + local cost = sparkData.lv_up_item:toNumMap() + if not role:checkItemEnough(cost) then + return 7 + end + local weight = math.random(0, 100) + local addLvl = 1 + if weight < sparkData.probability then + addLvl = 2 + end + + role:costItems(cost, {log = {desc = "sparkLvlUp", int1 = uid, int2 = level}}) + local attrs = {} + for i = 1, addLvl do + local cfg = sparkSet[level + i] + if not cfg then break end + for k, v in pairs(cfg.attr:toNumMap()) do + attrs[k] = (attrs[k] or 0) + v + end + end + ownSpark:addAttr(attrs) + ownSpark:updateProperty({field = "level",value = level+addLvl}) + --role:checkTaskEnter("SparkLvlUp") + + + ownSpark:mylog({desc = "sparkLvlUp", int1 = level + addLvl}) + + SendPacket(actionCodes.Car_sparkLvlUpRpc, MsgPack.pack({big = (addLvl == 2)})) + return true +end + return _M \ No newline at end of file diff --git a/src/actions/GmAction.lua b/src/actions/GmAction.lua index 263b691..799cf79 100644 --- a/src/actions/GmAction.lua +++ b/src/actions/GmAction.lua @@ -166,6 +166,15 @@ function _M.rune(role, pms) return result end +table.insert(helpDes, {"获得火花" , "spark", "零件id"}) +function _M.spark(role, pms) + local id = tonum(pms.pm1) + local result = role:addSpark({id = id, log = {desc = "gm"}}) + role:mylog("gm_action", {desc = "spark", int1 = id, key1 = pms.sender}) + + return result == 0 and "成功" or "失败" +end + table.insert(helpDes, {"通关挂机副本", "fb", "挂卡id"}) function _M.fb(role, pms) -- 直接通关 local carbonId = tonum(pms.pm1) @@ -594,6 +603,13 @@ function _M.clearbag(role, pms) end role:delRunes(uids, {log = {desc = "gm"}}) + -- 火花 + uids = {} + for uid, _ in pairs(role.sparkBag) do + table.insert(uids, uid) + end + role:delSparks(uids, {log = {desc = "gm"}}) + return "成功" end diff --git a/src/actions/HeroAction.lua b/src/actions/HeroAction.lua index 0685c14..489c393 100644 --- a/src/actions/HeroAction.lua +++ b/src/actions/HeroAction.lua @@ -105,6 +105,25 @@ function _M.wakeRpc(agent, data) if not role:checkItemEnough(cost) then return 4 end + local curLevel = hero:getProperty("wakeL") + local sparkInfo = hero:getProperty("spark") + -- 大于等于7的时候需要装备火花才能升 + if curLevel >= 7 then + if #sparkInfo == 0 then + return 5 + end + local ok = false + for _, info in ipairs(sparkInfo) do + local cfg = csvdb["sparkCsv"][info.cfg_id][info.level or 0] + if not cfg then return 6 end + if cfg.star == curLevel then + ok = true + break + end + end + if not ok then return 7 end + end + role:costItems(cost, {log = {desc = "heroWake", int1 = msg.id, int2 = hero:getProperty("type")}}) @@ -112,7 +131,6 @@ function _M.wakeRpc(agent, data) local oldBattleV = hero:getProperty("battleV") hero:updateProperty({field = "wakeL", delta = 1}) - local curLevel = hero:getProperty("wakeL") role:checkTaskEnter("Wake", {heroType = typ, wakeL = curLevel}) if curLevel == 3 then -- 解锁cg role:checkTaskEnter("WakeCG", {heroType = typ}) @@ -1193,4 +1211,55 @@ function _M.setWishPoolRpc(agent, data) return true end +function _M.changeSparkRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + + local idx = msg.index + local sparkId = msg.spark_id + local heroId = msg.hero_id + local hero = role.heros[heroId] + if not hero then return 1 end + + local spark = role.sparkBag[sparkId] + if not spark then return 2 end + + local lvl = spark:getProperty("level") + local cfgId = spark:getProperty("cfg_id") + + local dataSet = csvdb["sparkCsv"][cfgId] + if not dataSet then return 3 end + local cfg = dataSet[lvl] + if not cfg then return 4 end + + if hero:getProperty("wakeL") < cfg.star then return 5 end + + local itemCfg = csvdb["itemCsv"][cfgId] + if not itemCfg then return 6 end + if itemCfg.quality ~= hero:getRare() then return 6 end + + local sparkList = hero:getProperty("spark") or {} + local oldSparkInfo = sparkList[idx] or {} + sparkList[idx] = spark:data() + hero:updateProperty({field="spark", value=sparkList}) + + role:delSparks({sparkId}, {log = {desc = "changeSpark"}}) + local oldId = oldSparkInfo["cfg_id"] or 0 + local oldLevel = oldSparkInfo["level"] or 0 + local oldSparkSet = csvdb["sparkCsv"][oldId] + print(oldId, oldLevel) + local reward = {} + if oldSparkSet then + local oldSparkCfg = oldSparkSet[oldLevel] + dump(oldSparkCfg) + if oldSparkSet then + reward = oldSparkCfg.back:toNumMap() + end + end + dump(reward) + + SendPacket(actionCodes.Hero_changeSparkRpc, MsgPack.pack({reward = reward})) + return true +end + return _M diff --git a/src/actions/RoleAction.lua b/src/actions/RoleAction.lua index 6840508..00b1d52 100644 --- a/src/actions/RoleAction.lua +++ b/src/actions/RoleAction.lua @@ -16,6 +16,7 @@ local httpc = require("http.httpc") local WAVE_HERO_NUMS = 150 local WAVE_RUNE_NUMS = 150 +local WAVE_SPARK_NUMS = 150 local function validName(name) name = string.upper(name) @@ -204,6 +205,16 @@ function _M.loginRpc( agent, data ) table_insert(modules, "runeBag") end + local sparkIds = {} + for id ,_ in pairs(role.sparkBag) do + table.insert(sparkIds, id) + end + local sparkWave = math.ceil(#sparkIds / WAVE_SPARK_NUMS) + if #sparkIds <= 50 then + sparkWave = 0 + table_insert(modules, "sparkBag") + end + for _, name in ipairs(modules) do response[name] = {} for id, unit in pairs(role[name]) do @@ -211,12 +222,29 @@ function _M.loginRpc( agent, data ) end end - response.wave = 1 + heroWave + runeWave + 1 + response.wave = 1 + heroWave + runeWave + sparkWave + 1 SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response)) local curWave = 1 + local sparkIndex = 1 + for index = curWave + 1, curWave + sparkWave do + local sparkResponse = {sparkBag = {}} + for i = sparkIndex, sparkIndex + WAVE_SPARK_NUMS do + local sparkId = sparkIds[i] + if not sparkId then + break + end + local spark = role.sparkBag[sparkId] + table.insert(sparkResponse.sparkBag, spark:data()) + sparkIndex = sparkIndex + 1 + end + sparkResponse.sparkWave = index + SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(sparkResponse)) + end + curWave = curWave + sparkWave + local runeIndex = 1 for index = curWave + 1, curWave + runeWave do local runeResponse = {runeBag = {}} diff --git a/src/csvdata b/src/csvdata index 686b192..ec92ed5 160000 --- a/src/csvdata +++ b/src/csvdata @@ -1 +1 @@ -Subproject commit 686b192263f5cc221e472e1b9a41d059d581da2d +Subproject commit ec92ed50d3d5ff9655b1715239e7fda48f8ef5cb diff --git a/src/models/Hero.lua b/src/models/Hero.lua index 5be87e8..2daed35 100644 --- a/src/models/Hero.lua +++ b/src/models/Hero.lua @@ -16,6 +16,7 @@ Hero.schema = { equip = {"string",""}, --装备 type=level rune = {"string",""}, --零件 type=id faith = {"number", 0}, -- 信赖 + spark = {"table", {}}, -- 火花属性 } function Hero:ctor( properties ) @@ -47,7 +48,7 @@ end function Hero:updateProperties(params, notNotify) self:setProperties(params) - local check = {level = true, breakL = true, wakeL = true, talent = true, loveL = true, equip = true, rune = true} + local check = {level = true, breakL = true, wakeL = true, talent = true, loveL = true, equip = true, rune = true, spark = true} local datas = {} local updateBV = false for k , v in pairs(params) do @@ -78,7 +79,7 @@ function Hero:updateProperty(params) local datas = {} table.insert(datas, {key = params.field, newValue = self:getProperty(params.field)}) - local check = {level = true, breakL = true, wakeL = true, talent = true, loveL = true, equip = true, rune = true} + local check = {level = true, breakL = true, wakeL = true, talent = true, loveL = true, equip = true, rune = true, spark = true} if check[params.field] then local orginValue = self:getProperty("battleV") local curValue = self:saveBattleValue() @@ -103,7 +104,8 @@ function Hero:data() -- loveL = self:getProperty("loveL"), equip = self:getProperty("equip"), rune = self:getProperty("rune"), - faith = self:getProperty("faith") + faith = self:getProperty("faith"), + spark = self:getProperty("spark"), } end diff --git a/src/models/HeroPlugin.lua b/src/models/HeroPlugin.lua index 876a4e5..aefd200 100644 --- a/src/models/HeroPlugin.lua +++ b/src/models/HeroPlugin.lua @@ -121,11 +121,13 @@ function HeroPlugin.bind(Hero) local attrs = self:getBaseAttrs() -- 装备零件 local equipAttrs = self:getRuneEquipAttrs() + local sparkAttrs = self:getSparkAttrs() for _, attName in pairs(AttsEnumEx) do attrs[attName] = attrs[attName] or 0 attrs[attName] = attrs[attName] + addAttr(attrs[attName], equipAttrs.percent[attName], 1, attName) attrs[attName] = attrs[attName] + addAttr(attrs[attName], equipAttrs.value[attName], 0, attName) + attrs[attName] = attrs[attName] + addAttr(attrs[attName], sparkAttrs[attName], 0, attName) end -- 羁绊加成 @@ -225,6 +227,19 @@ function HeroPlugin.bind(Hero) return attrs end + function Hero:getSparkAttrs() + local attrs = {} + for _, attName in pairs(AttsEnumEx) do + attrs[attName] = 0 + end + for _, data in pairs(self.spark or {}) do + for k, v in pairs(data.attrs:toNumMap()) do + attrs[AttsEnumEx[k]] = attrs[AttsEnumEx[k]] + v + end + end + return attrs + end + -- 战斗力(当前属性)= POWER[(生命 + 防御 * 7 + 闪避 * 4)*(攻击*4 + 命中 * 2)*(1 + 暴击几率/100 * 暴击伤害/100)* 攻击速度 / 60000 ,0.8 ] -- function Hero:getBattleValue(activeRelation) -- isReal包括队伍加成 diff --git a/src/models/Role.lua b/src/models/Role.lua index 1483493..eb1b92b 100644 --- a/src/models/Role.lua +++ b/src/models/Role.lua @@ -25,6 +25,7 @@ function Role:ctor( properties ) self.storeData = nil self.heros = {} self.runeBag = {} + self.sparkBag = {} self.advData = nil self.activity = nil self._pushToken = nil diff --git a/src/models/RoleLog.lua b/src/models/RoleLog.lua index 5c19ac5..b3159ad 100644 --- a/src/models/RoleLog.lua +++ b/src/models/RoleLog.lua @@ -127,6 +127,9 @@ local ItemReason = { refer = 1210, -- 穿戴 itemCompose = 1211, -- 天赋道具合成 radioQuest = 1212, -- 电台任务奖励 + changeSpark = 1213, -- 穿戴火花 + sparkLvlUp = 1214, -- 火花强化 + sparkQualityUp = 1215, -- 火花升华 -- pvp pvpCHead = 1301, -- pvp 跨服竞技场头像 @@ -622,6 +625,8 @@ local LogType = { in_adv = "common", out_adv = "common", in_artifact = "common", + in_spark = "common", + out_spark = "common", mail_action = "common", role_action = "common", @@ -634,6 +639,7 @@ local LogType = { tower_action = "common", gm_action = "common", act_action = "common", + spark_action = "common", } -- 如要修改 要提前修改 _template mapping -- 对应 mapping 为 gamelog-* diff --git a/src/models/RolePlugin.lua b/src/models/RolePlugin.lua index 6b110ee..fbf6318 100644 --- a/src/models/RolePlugin.lua +++ b/src/models/RolePlugin.lua @@ -12,6 +12,7 @@ function RolePlugin.bind(Role) self:loadDiner() self:loadActivity() self:loadStoreInfo() + self:loadSparks() end function Role:reloadWhenLogin() @@ -96,6 +97,11 @@ function RolePlugin.bind(Role) self:addRune({type = typ,id = itemId, notNotify = pms.notNotify, log = pms.log}) end end, + [ItemType.Spark] = function() + for _= 1, count do + self:addSpark({id = itemId, notNotify = pms.notNotify, log = pms.log}) + end + end, [ItemType.AdvItem] = function() --冒险道具不会进入 玩家仓库 count = 0 end, @@ -748,6 +754,23 @@ function RolePlugin.bind(Role) end end + function Role:loadSparks() + local roleId = self:getProperty("id") + local sparkIds = redisproxy:smembers(string.format(R_SPARKIDS, roleId)) + local redret = redisproxy:pipelining(function (red) + for _, sparkId in ipairs(sparkIds) do + red:hgetall(string.format(R_SPARK, roleId, sparkId)) + end + end) + for index, sparkId in ipairs(sparkIds) do + local spark = require("models.Spark").new({key = string.format(R_SPARK, roleId, sparkId)}) + if spark:load(table.array2Table(redret[index])) then + spark.owner = self + self.sparkBag[tonumber(sparkId)] = spark + end + end + end + -- 0 为操作成功 function Role:addRune(params) if params.type and params.id then @@ -802,6 +825,101 @@ function RolePlugin.bind(Role) end end + -- 0 为操作成功 + function Role:addSpark(params) + if params.id then + local set = csvdb["sparkCsv"][params.id] + if not set then return 2 end + local data = set[0] + if not data then return 3 end + + local roleId = self:getProperty("id") + local sparkUid = tonum(redisproxy:hincrby(string.format(R_INCR, roleId), "spark", 1)) + + redisproxy:sadd(string.format(R_SPARKIDS, roleId), sparkUid) + + local sparkInfo = { + key = string.format(R_SPARK, roleId, sparkUid), + id = sparkUid, + cfg_id = params.id, + } + + local newSpark = require("models.Spark").new(sparkInfo) + newSpark:create() + newSpark:addAttr(data.attr:toNumMap()) + newSpark.owner = self + self.sparkBag[sparkUid] = newSpark + if not params.notNotify then + local response = {} + table.insert(response, newSpark:data()) + dump(response) + SendPacket(actionCodes.Role_loadSparks, MsgPack.pack(response)) + end + --self:checkTaskEnter("AddRune", {id = params.id, type = params.type, rarity = data.rarity}, params.notNotify) + + self:logItems(params.id, 0, 1, params.log) + if params.log then + local log = clone(params.log) + if log["cint1"] or log["cint2"] or log["cint3"] then + print("addRune error log have cint1 or cint2 or cint3 ", debug.traceback()) + end + + log["cint1"] = sparkUid + log["cint2"] = params.cfg_id + + self:mylog("in_spark", log) + else + print("addSpark no log ", debug.traceback()) + end + + return 0, newSpark + else + return 1 + end + end + + function Role:delSparks(sparkIds, params) -- 批量删除 {id, } + params = params or {} + local roleId = self:getProperty('id') + local bDel = {} + for _, sparkId in pairs(sparkIds) do + local spark = self.sparkBag[sparkId] + if spark then + + self:logItems(spark:getProperty("id"), 1, 0, params.log) + if params.log then + local log = clone(params.log) + if log["cint1"] or log["cint2"] then + print("delSpark error log have cint1 or cint2 ", debug.traceback()) + end + + log["cint1"] = sparkId + log["cint2"] = spark:getProperty("cfg_id") + + self:mylog("out_spark", log) + else + print("delSparks no log ", debug.traceback()) + end + + self.sparkBag[sparkId] = nil + table.insert(bDel, sparkId) + end + end + + redisproxy:pipelining(function (red) + for _, sparkId in pairs(bDel) do + red:del(string.format(R_SPARK, roleId, sparkId)) + red:srem(string.format(R_SPARKIDS, roleId), sparkId) + end + end) + local response = {} + for _, sparkId in pairs(bDel) do + table.insert(response, {id = sparkId, bDel = true}) + end + + SendPacket(actionCodes.Role_loadSparks, MsgPack.pack(response)) + end + function Role:delRunes(runeIds, params) -- 批量删除 {id, } params = params or {} local roleId = self:getProperty('id') diff --git a/src/models/Spark.lua b/src/models/Spark.lua new file mode 100644 index 0000000..04bd803 --- /dev/null +++ b/src/models/Spark.lua @@ -0,0 +1,78 @@ +local Spark = class("Spark", require("shared.ModelBase")) +Spark.schema = { + id = {"number"}, -- 唯一自增id + cfg_id = {"number"}, + level = {"number", 0}, -- 等级 + attrs = {"table", {}} -- 基础属性值 id=value +} + +function Spark:ctor( properties ) + Spark.super.ctor(self, properties) +end + +function Spark:notifyUpdateProperty(field, newValue, oldValue) + local datas = { + id = self:getProperty("id"), + datas = { + { + key = field, + newValue = newValue, + oldValue = oldValue, + } + } + } + self:notifyUpdateProperties(datas) +end + +function Spark:mylog(contents) + contents = contents or {} + if contents["cint1"] or contents["cint2"] then + print("sparkLog error log have cint1 or cint2 ", debug.traceback()) + end + contents["cint1"] = self:getProperty("id") + contents["cint2"] = self:getProperty("cfg_id") + + self.owner:mylog("spark_action", contents) +end + +function Spark:notifyUpdateProperties(params) + local updateData = { + id = self:getProperty("id"), + datas = params + } + SendPacket(actionCodes.Role_updateSpark, MsgPack.pack(updateData)) +end + +function Spark:updateProperty(params) + if not params.field or (not params.delta and not params.value) then + return + end + if params.delta then + self:incrProperty(params.field, params.delta) + elseif params.value then + self:setProperty(params.field, params.value) + end + local datas = {} + table.insert(datas, {key = params.field, newValue = self:getProperty(params.field)}) + + self:notifyUpdateProperties(datas) +end + +function Spark:addAttr(attrs) + local curAttrs = clone(self:getProperty("attrs")) + for k, v in pairs(attrs) do + curAttrs[k] = (curAttrs[k] or 0) + v + end + self:updateProperty({field = "attrs", value = curAttrs}) +end + +function Spark:data() + return { + id = self:getProperty("id"), + cfg_id = self:getProperty("cfg_id"), + level = self:getProperty("level"), + attrs = self:getProperty("attrs"), + } +end + +return Spark \ No newline at end of file -- libgit2 0.21.2