饥荒联机版mod制作[保存与加载]

当我们为一个可以长时间存在预制体写完基本的逻辑代码后,可能会发现,在我们关闭服务器后下一次进入游戏,这个实体原本的属性会消失,比如,我在关闭服务器之前将一个可以升级的武器费尽心思升到了99级,但一觉醒来,兴高采烈地打开了电脑,想象着自己拿着99级的武器玩着饥荒暖暖,但拿起武器后瞬间石化。

这是因为饥荒在每次服务器加载时,都会将世界中的所有预制体重新加载一遍,相当于初始化,原本保存在预制体及其组件中的数据也就被清空了。这时就需要我们对需要保存的数据进行保存与加载。

一、预制体数据的保存与加载

对于预制体数据的保存与加载,官方给出了函数接口,保存函数与加载函数通常在一起出现,函数接口如下:

-- 这两行一般加在预制体fn()的末尾
inst.OnSave = onsave    -- inst.OnLoad为保存函数接口,onload为自定义的保存函数
inst.OnLoad = onload    -- inst.OnLoad为加载函数接口,onload为自定义的加载函数

注意:lua语言是区分大小写的。

在onsave和onload中,分别用data来保存与加载数据。data会被保存在世界数据中而不会被清除或是初始化,所以在下次加载世界的时候,我们需要保存的数据被初始化后,通过把data中保存的值赋值给实体inst,就可以实现数据的保存与加载。

具体函数示例如下:

保存:

inst.OnSave会在每次世界保存(即右上角出现科学机器时)调用

-- 这里用stage作为示例,实际上data可以保存更多的数据
local function onsave(inst,data)
    data.stage = inst.stage
end

加载:

inst.OnLoad会在每次世界加载时调用

local function onload(inst,data)
    inst.stage = data and data.stage or 1  -- 注意如果是第一次加载,data为空,所以必须先判断是否为空
    update(inst)  -- 这里是用来更新网络同步数据的,在[网络同步数据]中会详细讲解
end

此时便完成了预制体数据的保存与加载。

二、组件数据的保存与加载

若组件不是纯方法,而是同样保存了数据,则组件中的数据也需要被保存,组件中保存的数据会被自动绑定到对应的预制体上。

关于组件的保存与加载,官方也给出了接口,即OnSave()与OnLoad()方法。原理同预制体的保存与加载相同,这两个方法分别会在世界保存时与世界加载时自动调用,不用人为干预。

具体代码示例如下:

保存:

只需要参考前三行即可,下面只是因组件需要,对需要保存的数据进行了判断。

function Pickable:OnLoad(data)
    self.transplanted     = data.transplanted or false
    self.cycles_left      = data.cycles_left or self.cycles_left
    self.max_cycles       = data.max_cycles or self.max_cycles

    if data.picked or data.time ~= nil then
        if self:IsBarren() and self.makebarrenfn ~= nil then
            self.makebarrenfn(self.inst, true)
        elseif self.makeemptyfn ~= nil then
            self.makeemptyfn(self.inst)
        end
        self.canbepicked = false
    else
        if self.makefullfn ~= nil then
            self.makefullfn(self.inst)
        end
        self.canbepicked = true
    end

    if data.caninteractwith then
        self.caninteractwith = data.caninteractwith
    end

    if not self.useexternaltimer then
        if data.paused then
            self.paused = true
            self.pause_time = data.pause_time
            if self.task ~= nil then
                self.task:Cancel()
                self.task = nil
            end
        elseif data.time ~= nil then
            if self.task ~= nil then
                self.task:Cancel()
            end
            self.task = self.inst:DoTaskInTime(data.time, OnRegen)
            self.targettime = GetTime() + data.time
        end
    end

    if data.makealwaysbarren == 1 and self.makebarrenfn ~= nil then
        self:MakeBarren()
    end

    self.protected_cycles = data.protected_cycles ~= nil and data.protected_cycles > 0 and data.protected_cycles or nil
    if self.inst.components.witherable ~= nil then
        self.inst.components.witherable:Enable(self.protected_cycles == nil)
    end
end

加载:

同样也是只需要看前几行:

function Pickable:OnSave()
    local data =
    {
        protected_cycles   = self.protected_cycles,
        picked             = not self.canbepicked and true or nil,
        transplanted       = self.transplanted and true or nil,
        paused             = self.paused and true or nil,
        caninteractwith    = self.caninteractwith and true or nil,
    }

    if self.cycles_left ~= self.max_cycles then
        data.cycles_left = self.cycles_left
        data.max_cycles = self.max_cycles
    end

    if not self.useexternaltimer then
        if self.pause_time ~= nil and self.pause_time > 0 then
            data.pause_time = self.pause_time
        end

        if self.targettime ~= nil then
            local time = GetTime()
            if self.targettime > time then
                data.time = math.floor(self.targettime - time)
            end
        end
    end

    return next(data) ~= nil and data or nil
end

最后将data表返回,插入到世界数据中加以保存。

return next(data) ~= nil and data or nil意为,若data表为空,则不进行操作;若有数据则保存

三、总结

原理很简单:

保存即为将需要保存的inst数据全部赋值给data表,此外不需要做任何处理。

加载即为将需要恢复的inst数据从data表中读取出来,此外不需要做任何处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值