在论坛上看到了许多大佬编写的动作mod,对于一个正在学习开发mod的菜鸟来说受益良多,最开始注意到这个问题是在阅读Wiai大佬的超灵活大剑mod[1]时在这个mod中Wiai大佬修改了toolkits的原始脚本,这导致这个mod与其他几个修改武器动作的mod产生了不兼容。我对比了原始脚本和修改的脚本,发现Wiai大佬在修改脚本时删去了其他mod可能会使用的onTerminateVM方法,这导致了与红龙之箭Mod[2]、虫棍派生优化Mod[3]等需要保存设置的mod的不兼容,另外还添加了一些方便自己使用的新方法(虽然这并不会造成兼容问题)以及重写了部分方法。这给了我思考了一个问题,如果要每个mod作者都会重写或添加新的toolkit方法,便会产生巨量的分支,很难保证mod之间的兼容,对mod合并产生很大的困难,因此我设计了两种思路,将新的方法独立到新的脚本中,保护toolkits的完整性。
继承模式
使用面向对象的继承模式,即编写一个新的module继承toolkits,在此module中添加新的方法及重写父类中的方法,为此需要在toolkits中添加一个新的方法用于生成子类。
function module:new(o)
o = o or {}
self.__index = self
setmetatable(o,self)
return o
end
如此,任何module只要在初始化时使用上述方法继承toolkits,就可以继承其所有公有方法和成员变量,例如如下的toolkits_added.lua
moudel_added={}
function moudel_added:setAllConditions_SpecificState_FieldName()
--使用了toolkits的公有方法
local tree = getTreeComponentCore()
end
--重写toolkits存在的方法
function moudel_added:getTreeComponentCore()
---填写自己的实现
end
在修改动作的脚本中添加如下代码,便可以使用自己编写的新方法
local toolkits_origin = require("treeToolkit/toolkits")
local toolkits = require("toolkits_added")
toolkits=toolkits_origin:new()
这种方法只在toolkits文件中添加了一个new方法,不会影响toolkits的兼容性,添加和重写的方法放在toolkits_added文件中,实现了与库的分离。需要注意的是你无法访问toolkits的local方法,如果要使用local方法,需要在toolkits中为其添加公有引用,例如local function getTreeComponentCore()
module.getTreeComponentCore=getTreeComponentCore
类扩展函数
这个方法仍在测试和改良中
受到kotlin的class extend特性启发,即向toolkits添加扩展的成员变量、成员函数,这些函数可以在module外实现并正常访问module的私有资源,我试图在lua实现这一特性。
首先为toolkits提供扩展函数的接口
function module:extend(class)
class.__index=class
setmetatable(self, class)
end
扩展module的编写与上一种方法一致,只是在调用toolkits方法时需要加上self.(你应当用“:”而非“.”声明函数,否则无法使用self标识符)
而在最终实现动作修改的模组中,只需要加入
toolkits:extend(toolkits_added)
即可为toolkits添加你实现的方法,这使你几乎不需要修改已经完成的脚本
这个方法应当是更优的解,但目前问题很多,比如无法实现重写(toolkits永远会先从自己的list中寻找所需的函数然后再搜索元组),无法访问local方法(仍然需要像上一种方法那样添加公有引用才能使用local方法)等等。
这两种方式本质上都是对lua中元组和__index函数的选择性实现,相关的内容可以见lua-users wiki:元组和lua类,我个人非常喜欢类扩展函数这一特性,尽管有lua源码的支持,但苦于技术低微难以实现,所以发上来请各位大佬点评,顺便集思广益,把各位的火花借给我。
另外取得Wiai大佬的同意后我也会将我修改好的与红龙之箭Mod、虫棍派生优化Mod兼容的toolkits脚本发上来
提及的mod链接