Added files via upload

master
Aftermoth 2016-04-25 12:32:33 +12:00
parent d2afc92956
commit db0ca60e64
8 changed files with 517 additions and 2 deletions

192
HOWTO_nuafan.txt Normal file
View File

@ -0,0 +1,192 @@
Nuafan adapts nodes from other mods to add nua functionality.
Using nuafan is all about telling it which nodes to adapt from other mods, and what changes to make.
This is acheived using filter files, which are essentially just lists.
--------------------------
Contents:
Filter files
Mod filtering
Node filtering
Basic syntax
Optional
Globbing syntax
Precedence
Exclusion patterns
Editing tips
Footnote
--------------------------
====== Filter files ======
The README.md for nua outlines the code that nuafan produces.
** Mod Filtering **
"depends.txt" is the main filter, consisting of one mod name per line.
"nua" is nuafan's only real dependency, and must not be removed.
Otherwise, all and only those mods to be adapted should be listed.
With no other filters, nuafan will add event signalling to all nodes from those mods.
Optional dependencies ("name?") will be used if loaded, and are recommended so you don't have to edit it when you disable mods.
Nuafan will not adapt any nodes from mods not listed here.
** Node Filtering **
The remaining filters all deal with individual node types.
They may include unused node specifications without problems, so there's no need to edit it every time you change mods.
"f_xconstruct.txt", "f_xdestruct.txt"
These prevent listed nodes from signalling an event on construction or destruction, respectively.
By default they contain "@safemode:" which is a directive that avoids editing any callbacks that have already been defined. This is because nuafan cannot yet cooperate with existing definitions without hurting their original functionality.
No editing is required unless you wish to exclude additional nodes, or disable safemode and do everything manually.
Manual entries in "f_xconstruct.txt" can have "X" as a second field to also block definitions in "f_callbacks."
"f_callbacks.txt"
This defines callbacks for nodes, allowing them to respond to alerts as well as cause them. It has the same syntax as the other "f_" files, plus an additional function name on each line. Function names given here shall be called with two arguments, (receiverpos,eventpos) to receive update alerts.
Mods that supply only functions need not be in "depends.txt," as long as those you need are loaded by the game. In fact, if the mod has a nua-compatible callback function, its nodes are probably already nua aware anyway.
====== Basic syntax ======
All filters have one entry per line; a node descriptor, and in "callbacks" a function name.
Different parts of an entry are separated by space(s), and no spaces are allowed within each part.
Space or tab indented lines are comments, and ignored by nuafan.
-----------------------------------
default:cobble mymod.monsterize
-----------------------------------
Duplicate node descriptors replace earlier entries. In "callbacks," this redefines the function, or removes it if none is given.
Everything can be done explicitly with the basic syntax above. The following simply reduces the file size a bit.
====== Optional ======
Nuafan does not, and will not, support general regular expressions, but some conveniences may prove indispensable with larger variety of nodes.
Note: Safemode can be enabled selectively, but it's very unlikely you won't want it on all mods.
@safemode: applies to all mods
@safemode:mod1,mod2 applies only to named mods
Because safemode handles essential filtering automatically, and you would likely want update events to work for as many nodes as possible, usually only "f_callbacks" would be worth editing.
** Globbing syntax **
Multiple node names can be referenced on one line:
m:a,b,c expands to separate entries m:a m:b m:c (INclusion)
m:-a,b,c all names from m except m:a m:b m:c (EXclusion)
m: all names from m
* all names from all mods
Related specifiers can also be referenced within a single specifier pattern:
The "*" can only occur once, at one end, where a "_" might be
a_b*, a*, *a_b, *b all match a_b
for example:
"stone*" matches:
stone
stone_with_iron
but not:
stonebrick
REMEMBER: Each line shares any additional fields, such as the "X" in f_xconstruct, or function name in f_callbacks.
default:-*flowing,furnace*,wood oddmod.allbut_flowoodfurn
** Precedence **
1) Test classes are ordered from most to least restrictive.
m:a > m:-a > m: > *
2) Inclusion tests prioritise by first '*'-pattern to match, under the ordering:
plain; on the right, leftwards; on the left, rightwards.
e.g. a_b_c > a_b_c* > a_b* > a* > *a_b_c > *b_c > *c
3) Exclusion tests prioritise by entry order.
4) If duplicate node identifiers occur later in the list, they will replace any definitions of the earlier entry, but in the list position of the original. With the exception of "X," which is protected against overwriting.
Comparison occurs after
- inclusion lists are expanded to separate entries
- exclusion lists are put in canonical form, e.g.
m:-b,a = m:-b,a,b = m:-a,b,a = m:-a,a,b --> m:-a,b
Note that '*' is treated literally, without interpretation.
Tip: Use precedence to make exceptions, e.g.
* mymod.everyone_does_it
yourmod:exception
wins the match and returns no function.
** Exclusion patterns ** (extra)
Precedence ensures that they only apply to the leftovers, after inclusion patterns take what they want.
Patterns with more EXclusions and therefore fewer INclusions should have higher priority.
Usually, you should list wider exclusion patterns earlier, so their inclusions are not blocked.
e.g.
m:-a n.f <-- m:b and m:the_rest
m:-a,b n.g useless
but,
m:-a,b n.g <-- m:the_rest
m:-a n.f <-- m:b
but also,
m:-a,b n.g gets redefined in place
m:-a n.f <-- m:b
m:-b,a n.h <-- m:the_rest
====== Editing tips ======
Make your filter files easy to read and understand so you know what to expect.
Group entries by mod.
Use blank lines if it helps.
Remember, if you need them, comments are on separate lines.
It's usually easier and clearer when temporarily disabling entries to indent them in place rather than move or remove them.
When using globs:
List entries from high to low precedence.
"mod: " finishes a mod group, "* " finishes the list, if used.

View File

@ -1,2 +1,40 @@
# nuafan
NUA For Aganostic Nodes adds nua functionality to nodes from nua-ignorant mods
Minetest mod: nuafan
==== NUA For Agnostic Nodes ====
Nuafan adds nua functionality to nodes from nua-ignorant mods.
Specifically, on_construct and after_destruct node update alerts,
and user-defined callbacks allowing them to receive and respond
to alerts as well.
A demo is enabled by default so you can play around with it in-game before deciding whether to use it seriously.
It reports nearby updates via chat.
requires: nua
https://github.com/Aftermoth/nua
Limitations:
1) Some node types already use on_construct or after_destruct to provide special functionality.
Nuafan cannot yet cooperate with existing definitions without breaking them, and so avoids altering them by default.
2) Some node types repeatedly and ceaselessly destruct/construct without changing type.
Nuafan cannot yet distinguish between real and fake changes, so its best option is not to signal events from those nodes at all, although they may still receive them.
Additionally, large numbers of those nodes spam the event queue quite heavily however they are handled, and could impact performance, especially if extra tests are required.
3) Map-generated nodes and trees do not receive extra functionality upon creation, although nodes in (2) and some plants aquire it without player intervention. This is generally desirable, although it can be difficult to remember which nodes of the same type are aware and which are not, e.g. between generated and user-placed stone.
----
Copyright (C) 2016 Aftermoth, Zolan Davis
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License,
or (at your option) version 3 of the License.
http://www.gnu.org/licenses/lgpl-2.1.html

13
depends.txt Normal file
View File

@ -0,0 +1,13 @@
nua
bones?
default?
doors?
farming?
fire?
flowers?
stairs?
tnt?
vessels?
wool?
xpanes?

5
f_callbacks.txt Normal file
View File

@ -0,0 +1,5 @@
* nuafan.demo
nuafan.demo allows blocks to report alerts they receive to nearby players via chat.
You can use this to test your filters.

6
f_xconstruct.txt Normal file
View File

@ -0,0 +1,6 @@
@safemode:
No-change destruct/construct spammers.
default:dirt
default:dirt_with_grass
default:desert_sand

6
f_xdestruct.txt Normal file
View File

@ -0,0 +1,6 @@
@safemode:
No-change destruct/construct spammers.
default:dirt
default:dirt_with_grass
default:desert_sand

101
init.lua Normal file
View File

@ -0,0 +1,101 @@
--[[
Copyright (C) 2016 Aftermoth, Zolan Davis
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License,
or (at your option) version 3 of the License.
http://www.gnu.org/licenses/lgpl-2.1.html
--]]
nuafan = {}
nuafan.demo = function(ip,ep)
local players, near, pp = {}, 8
for _,player in ipairs(minetest.get_connected_players()) do
pp = player:getpos()
if math.abs(pp.x-ip.x) + math.abs(pp.y-ip.y) + math.abs(pp.z-ip.z) < near then
table.insert(players,player)
end
end
if players[1] then
local m, p = minetest, '('..ep.x..','..ep.y..','..ep.z..')'
local i, e = m.get_node_or_nil(ip).name, m.get_node_or_nil(ep).name
local j, f = m.registered_nodes[i].description, (e=="air" and "Nothing") or m.registered_nodes[e].description
j, f =(j=="" and '['..i..']') or j, (f=="" and '['..e..']') or f
for _,pp in ipairs(players) do
m.chat_send_player(pp:get_player_name(),j..' sees '..f..' at '..p)
end
end
end
-- Local --
local this = minetest.get_current_modname()
local here = minetest.get_modpath(this)..'/'
local lookup, mlist, xclist, xdlist, cblist = dofile(here..'mkfilters.lua')
local function shallow(t)
local d = {}
for a,b in pairs(t) do
d[a] = b
end
return d
end
local function upgrade()
local mod,c,d,s
for nn,dfn in pairs(minetest.registered_nodes) do
mod,c = string.match(nn,'^([^:]+):([^:]+)$')
if mod and mlist[mod] then
d = nil
if not (lookup(xdlist,'@safemode:'..mod) and type(dfn.after_destruct) == "function") then
s = lookup(xdlist,nn)
if not s then
d=shallow(dfn)
d.after_destruct = function (pos, old)
nua.event(pos)
end
end
end
if not (lookup(xclist,'@safemode:'..mod) and type(dfn.on_construct) == "function") then
s = lookup(xclist,nn)
if s~="X" then
local s2 = lookup(cblist,nn)
if not s or (s2 and s2~="") then
if not d then d=shallow(dfn) end
if s2 and s2~="" then
if s then
d.on_construct = function (pos)
minetest.get_meta(pos):set_string('on_nbr_update',s2)
end
else
d.on_construct = function (pos)
minetest.get_meta(pos):set_string('on_nbr_update',s2)
nua.event(pos)
end
end
else
d.on_construct = function (pos)
nua.event(pos)
end
end
end
end
end
if d then
minetest.register_node(':'..nn,d)
end
end
end
end
upgrade()

154
mkfilters.lua Normal file
View File

@ -0,0 +1,154 @@
--[[
Copyright (C) 2016 Aftermoth, Zolan Davis
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License,
or (at your option) version 3 of the License.
http://www.gnu.org/licenses/lgpl-2.1.html
--]]
local function lookup(t,n)
--[[
returns
nil if invalid
false if not found
string if found
]]
local m , a = string.match(n,'^([^:]+:)([^:]+)$')
if m then
-- pre-generate possible * matches
local ps = {}
table.insert(ps,a)
local s,r = a,""
while s and s~="" do
table.insert(ps,s..'*')
s,r = string.match(s, '^(.*)(_[^_]*'..r..')$')
end
s,r = a,""
while s and s~="" do
table.insert(ps,'*'..s)
r,s = string.match(a,'^('..r..'[^_]*_)(.*)$')
end
-- inclusion -- '*' order
for _,v in ipairs(ps) do
if t[m..v] then
return t[m..v]
end
end
-- exclusion -- entry order
if t[m..'-'] then
local ok
for _,g in ipairs(t[m..'-']) do
ok = true
for _,v in ipairs(ps) do
if g[1][v] then
ok = false
break
end
end
if ok then
return g[2]
end
end
end
-- any in mod
if t[m] then
return t[m]
end
-- any
if t['*'] then
return t['*']
end
-- no match
return false
end
-- invalid
return nil
end
local here = minetest.get_modpath(minetest.get_current_modname())..'/'
local mkmlist = function ()
local list = {}
local s
for ln in io.lines(here.."depends.txt") do
s=string.match(ln,'([^%s:?]+)')
if s then list[s] = 1 end
end
return list
end
local mlist = mkmlist()
local function split(s,pfx,val)
local t={}
for v in string.gmatch(s,'([^,]+)') do t[pfx..v] = val end
return t
end
local function parse(s,s2)
local t,h = {}, {}
local m,e,a,c = string.match(s,'^([^:]+:?(-?))([^,]*(,?).*)$')
if e ~= '' then
t = split(a,'',1)
for n,_ in pairs(t) do
table.insert(h,n)
end
table.sort(h)
return { [0] = m, [1] = { [0]=table.concat(h,","), [1]=t, [2]=s2 }}
elseif c ~= '' then
t = split(a,m,s2)
return t
elseif s ~= '0' then
return { [s] = s2 }
end
return {}
end
local function mkflist(src)
src=here..src
local list = {}
local s1,s2,p,h
local fh = io.open(src)
if fh then
io.close(fh)
for ln in io.lines(src) do
s1,s2=string.match(ln,'^([^%s]+)%s*([^%s]*)')
if s1 then
if s1 == "*" or string.sub(s1,1,1) == "@" or mlist[string.match(s1,'^([^:]+)') or ':'] then -- mod ok
p = parse(s1,s2)
if p[0] then
if not list[p[0] ] then
list[p[0] ] = {}
h=true
else
h=p[1][0]
for _,t in ipairs(list[p[0] ]) do
if h == t[0] then
t[2]=p[1][2]
h=false
break
end
end
end
if h then
table.insert(list[p[0] ],p[1])
end
else
for k,v in pairs(p) do
if not (list[k] and list[k]=='X') then
list[k] = v
end
end
end
end
end
end
end
return list
end
return lookup, mlist, mkflist('f_xconstruct.txt'), mkflist('f_xdestruct.txt'), mkflist('f_callbacks.txt')