Skip to content

Instantly share code, notes, and snippets.

@warmist
Created January 3, 2014 17:56
Show Gist options
  • Save warmist/8242853 to your computer and use it in GitHub Desktop.
Save warmist/8242853 to your computer and use it in GitHub Desktop.
--installs a modpack
-- args: modpack_name [-i|install|-if] [-u|uninstall] [entity_to_patch]
args={...}
if args[1]==nil or #args<2 then
print("Usage: modpack_name [-i|install|-if] [-u|uninstall] [entity_to_patch]")
end
local modPath=dfhack.getDFPath()..'/mods/'..args[1]..'/'
local dfMod=dofile(modPath..'init.lua')
local name=dfMod.name
local guard={">>"..name.." patch","<<End "..name.." patch"}
local guard_init={"--"..guard[1],"--"..guard[2]}
local entity_file=dfhack.getDFPath().."/raw/objects/entity_default.txt"
local init_file=dfhack.getDFPath().."/raw/init.lua"
function fileExists(filename)
local file=io.open(filename,"rb")
if file==nil then
return
else
file:close()
end
end
function copyFile(from,to) --oh so primitive
local filefrom=io.open(from,"rb")
local fileto=io.open(to,"w+b")
local buf=filefrom:read("*a")
printall(buf)
fileto:write(buf)
filefrom:close()
fileto:close()
end
function patchInit(initFileName,patch_guard,code)
local initFile=io.open(initFileName,"a")
initFile:write(string.format("%s\n%s\n%s",patch_guard[1],
code,patch_guard[2]))
initFile:close()
end
function patchEntity(file_name,patch_guard,entity_name,code)
local input_lines=patch_guard[1].."\n"..code.."\n"..patch_guard[2]
local badchars="[%:%[%]]"
local find_string=entity_name:gsub(badchars,"%%%1") --escape some bad chars
local entityFile=io.open(file_name,"r")
local buf=entityFile:read("*all")
entityFile:close()
local entityFile=io.open(file_name,"w+")
print("Patching:"..entity_name)
buf=string.gsub(buf,find_string,entity_name.."\n"..input_lines)
entityFile:write(buf)
entityFile:close()
end
function findGuards(str,start,patch_guard)
local pStart=string.find(str,patch_guard[1],start)
if pStart==nil then return nil end
local pEnd=string.find(str,patch_guard[2],pStart)
if pEnd==nil then error("Start guard token found, but end was not found") end
return pStart-1,pEnd+#patch_guard[2]+1
end
function findGuardsFile(filename,patch_guard)
local file=io.open(filename,"r")
local buf=file:read("*all")
return findGuards(buf,1,patch_guard)
end
function unPatchFile(filename,patch_guard)
local file=io.open(filename,"r")
local buf=file:read("*all")
file:close()
local newBuf=""
local pos=1
local lastPos=1
repeat
local endPos
pos,endPos=findGuards(buf,lastPos,patch_guard)
newBuf=newBuf..string.sub(buf,lastPos,pos)
if endPos~=nil then
lastPos=endPos
end
until pos==nil
local file=io.open(filename,"w+")
file:write(newBuf)
file:close()
end
function checkInstalled() --try to figure out if installed
if dfMod.checkInstalled then
return dfMod.checkInstalled()
else
if dfMod.raws_list then
for k,v in pairs(dfMod.raws_list) do
if fileExists(dfhack.getDFPath().."/raw/objects/"..v) then
return true
end
end
end
if dfMod.patch_entity then
if findGuardsFile(entity_file,guard)~=nil then
return true
end
end
if dfMod.patch_init then
if findGuardsFile(init_file,guard_init)~=nil then
return true
end
end
end
end
if args[2]=="install" or args[2]=="-i" or args[2]=="-if" then
if args[2]~='-if' and checkInstalled() then
qerror("Mod already installed.")
return
end
if dfMod.pre_install then
dfMod.pre_install(args)
end
if dfMod.raws_list then
for k,v in pairs(dfMod.raws_list) do
copyFile(modPath..v,dfhack.getDFPath().."/raw/objects/"..v)
end
end
if dfMod.patch_entity then
local entity_target
if args[3]==nil then
entity_target="[ENTITY:MOUNTAIN]"
else
entity_target="[ENTITY:"..args[3].."]" -- todo multiple entities
end
patchEntity(entity_file,guard,entity_target,dfMod.patch_entity)
end
if dfMod.patch_init then
patchInit(init_file,guard_init,dfMod.patch_init)
end
if dfMod.post_install then
dfMod.post_install(args)
end
return
elseif args[2]=="uninstall" or args[2]=="-u" then
if dfMod.pre_uninstall then
dfMod.pre_uninstall(args)
end
if dfMod.raws_list then
for k,v in pairs(dfMod.raws_list) do
os.remove(dfhack.getDFPath().."/raw/objects/"..v)
end
end
if dfMod.patch_entity then
unPatchFile(entity_file,guard)
end
if dfMod.patch_init then
unPatchFile(init_file,guard_init)
end
if dfMod.post_uninstall then
dfMod.post_uninstall(args)
end
return
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment