Update cleaner mod to Git commit 9230e0c...

https://github.com/AntumMT/mod-cleaner/tree/9230e0c
This commit is contained in:
Jordan Irwin 2021-07-14 03:24:21 -07:00
parent 196afb015a
commit e7c9b61c25
18 changed files with 869 additions and 120 deletions

View File

@ -11,7 +11,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
* admin/
* [alternode][] ([MIT][lic.alternode]) -- version: [1.3][ver.alternode] *2021-05-18*
* [cleaner][] ([MIT][lic.cleaner]) -- version: [1.1][ver.cleaner] *2021-05-27*
* [cleaner][] ([MIT][lic.cleaner]) -- version: [9230e0c Git][ver.cleaner] *2021-07-12*
* [no_fall_damage][] ([MIT][lic.no_fall_damage]) -- version [1.0.0][ver.no_fall_damage] *2020-12-19*
* [privs][] ([CC0][lic.cc0])
* [spectator_mode][] ([WTFPL][lic.spectator_mode]) -- version: [3648371 Git][ver.spectator_mode] *2020-07-15*
@ -527,7 +527,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
[ver.castle_weapons]: https://github.com/minetest-mods/castle_weapons/tree/d3cf095
[ver.chatlog]: https://github.com/AntumMT/mod-chatlog/tree/v1.1
[ver.christmas]: https://github.com/TheZenKitteh/minetest-christmas/tree/d3bd872
[ver.cleaner]: https://github.com/AntumMT/mod-cleaner/releases/tag/v1.1
[ver.cleaner]: https://github.com/AntumMT/mod-cleaner/tree/9230e0c
[ver.cmer]: https://github.com/AntumMT/mod-cmer/tree/2843875
[ver.cmer_chicken]: http://github.com/AntumMT/mod-cmer/tree/085706f
[ver.cmer_ghost]: https://github.com/AntumMT/mod-cmer/tree/2f70906

View File

@ -964,6 +964,14 @@ inventory = sfinv
## ADMIN ##
###########
# *** cleaner ***
## Enables unsafe methods.
# type: bool
# default: false
#cleaner.unsafe = false
# *** whitelist ***
## Enables/Disables whitelist feature.

View File

@ -1,58 +1,79 @@
## Cleaner mod for Minetest
---
### Description:
A [Minetest][] mod that can be used to remove/replace unknown entities, nodes, & items. Originally forked from [PilzAdam's ***clean*** mod][f.pilzadam].
---
### Licensing:
[MIT](LICENSE.txt)
---
### Requirements:
- Minetest 0.4.16 or newer
- Minetest minimum version: 5.0
- Depends: none
---
### Usage:
There are three files in the world path that can be edited: `clean_entities.json`, `clean_nodes.json`, & `clean_items.json`. If they do not already exist with the server is started they will be created automatically.
Registering items, entities, etc. for cleaning can be done in `cleaner.json` in the world directory. If it does not exist it will be created automatically when the server is started.
They are formatted as follows:
It is formatted as follows:
```json
{
"remove":
[
"creatures:ghost",
"creatures:chicken",
"creatures:sheep",
"creatures:skeleton",
"creatures:zombie",
"creatures:oerkki",
"creatures:shark",
],
"replace":
"entities" :
{
"biofuel:biofuel":"default:leaves",
"helicopter:heli":"default:copper_lump",
"spawneggs:ghost":"alternode:key",
"spawneggs:oerkki":"default:mese_crystal",
"unifieddyes:airbrush":"default:coal_lump",
"remove" : []
},
"items" :
{
"replace" : {}
},
"nodes" :
{
"remove" : [],
"replace" : {}
},
"ores" :
{
"remove" : []
}
}
```
Cleaning nodes example:
```json
{
"nodes" :
{
"remove" : [
"old:node_1",
"old:node_2",
],
"replace" : {
"old:node_3" : "new:node_1",
"old:node_4" : "new:node_2",
}
},
}
```
`remove` key works for nodes & entities. `replace` key works for nodes & items. Their functions are self-explanatory.
`remove` key works for nodes, entities, & ores. `replace` key works for nodes & items. Their functions are self-explanatory.
#### Settings:
```
cleaner.unsafe
- Enables unsafe methods & commands (remove_ore).
- type: bool
- default: false
```
---
### Links:
- [![ContentDB](https://content.minetest.net/packages/AntumDeluge/cleaner/shields/title/)][ContentDB]
- [Forum](https://forum.minetest.net/viewtopic.php?t=18381)
- [Git repo](https://github.com/AntumMT/mod-cleaner)
- [API](https://antummt.github.io/mod-cleaner/docs/reference)
- [Changelog](changelog.txt)
- [TODO](TODO.txt)

View File

@ -1,2 +1,7 @@
TODO:
- update world file when chat commands are used
- update inventories when items are replaced:
- creative
- storage (chests, etc.)
- fix top nodes disappearing with /replace_node command

193
mods/admin/cleaner/api.lua Normal file
View File

@ -0,0 +1,193 @@
--- Cleaner API
--
-- @topic api
local replace_items = {}
local replace_nodes = {}
--- Retrieves list of items to be replaced.
--
-- @treturn table Items to be replaced.
function cleaner.get_replace_items()
return replace_items
end
--- Retrieves list of nodes to be replaced.
--
-- @treturn table Nodes to be replaced.
function cleaner.get_replace_nodes()
return replace_nodes
end
--- Registers an entity to be removed.
--
-- @tparam string src Entity technical name.
function cleaner.register_entity_removal(src)
core.register_entity(":" .. src, {
on_activate = function(self, ...)
self.object:remove()
end,
})
end
--- Registers a node to be removed.
--
-- @tparam string src Node technical name.
function cleaner.register_node_removal(src)
core.register_node(":" .. src, {
groups = {to_remove=1},
})
end
local function update_list(inv, listname, src, tgt)
if not inv then
cleaner.log("error", "cannot update list of unknown inventory")
return
end
local list = inv:get_list(listname)
if not list then
cleaner.log("warning", "unknown inventory list: " .. listname)
return
end
for idx, stack in pairs(list) do
if stack:get_name() == src then
local new_stack = ItemStack(tgt)
new_stack:set_count(stack:get_count())
inv:set_stack(listname, idx, new_stack)
end
end
end
--- Replaces an item with another registered item.
--
-- @tparam string src Technical name of item to be replaced.
-- @tparam string tgt Technical name of item to be used in place.
-- @tparam[opt] bool update_players `true` updates inventory lists associated with players (default: `false`).
function cleaner.replace_item(src, tgt, update_players)
update_players = not (update_players ~= true)
if not core.registered_items[tgt] then
return false, S('Cannot use unknown item "@1" as replacement.', tgt)
end
if not core.registered_items[src] then
cleaner.log("info", "\"" .. src .. "\" not registered, not unregistering")
else
cleaner.log("warning", "overriding registered item \"" .. src .. "\"")
core.unregister_item(src)
if core.registered_items[src] then
cleaner.log("error", "could not unregister \"" .. src .. "\"")
end
end
core.register_alias(src, tgt)
if core.registered_aliases[src] == tgt then
cleaner.log("info", "registered alias \"" .. src .. "\" for \"" .. tgt .. "\"")
else
cleaner.log("error", "could not register alias \"" .. src .. "\" for \"" .. tgt .. "\"")
end
local bags = core.get_modpath("bags") ~= nil
local armor = core.get_modpath("3d_armor") ~= nil
-- update player inventories
if update_players then
for _, player in ipairs(core.get_connected_players()) do
local pinv = player:get_inventory()
update_list(pinv, "main", src, tgt)
if bags then
for i = 1, 4 do
update_list(pinv, "bag" .. i .. "contents", src, tgt)
end
end
if armor then
local armor_inv = core.get_inventory({type="detached", name=player:get_player_name() .. "_armor"})
update_list(armor_inv, "armor", src, tgt)
end
end
end
return true
end
--- Registeres an item to be replaced.
--
-- @tparam string src Technical name of item to be replaced.
-- @tparam string tgt Technical name of item to be used in place.
function cleaner.register_item_replacement(src, tgt)
replace_items[src] = tgt
end
--- Registers a node to be replaced.
--
-- @tparam string src Technical name of node to be replaced.
-- @tparam string tgt Technical name of node to be used in place.
function cleaner.register_node_replacement(src, tgt)
core.register_node(":" .. src, {
groups = {to_replace=1},
})
replace_nodes[src] = tgt
end
--- Unsafe methods.
--
-- Enabled with `cleaner.unsafe` setting.
--
-- @section unsafe
if cleaner.unsafe then
local remove_ores = {}
--- Retrieves list of ores to be removed.
--
-- @treturn table Ores to be replaced.
function cleaner.get_remove_ores()
return remove_ores
end
--- Registers an ore to be removed after server startup.
--
-- @tparam string src Ore technical name.
function cleaner.register_ore_removal(src)
table.insert(remove_ores, src)
end
--- Removes an ore definition.
--
-- @tparam string src Ore technical name.
function cleaner.remove_ore(src)
local remove_ids = {}
local total_removed = 0
local registered = false
for id, def in pairs(core.registered_ores) do
if def.ore == src then
table.insert(remove_ids, id)
registered = true
end
end
for _, id in ipairs(remove_ids) do
core.registered_ores[id] = nil
if core.registered_ores[id] then
cleaner.log("error", "unable to unregister ore " .. id)
else
total_removed = total_removed + 1
end
end
return registered, total_removed
end
end

View File

@ -1,4 +1,18 @@
v1.2
----
- added API
- added chat commands:
- remove_entity
- remove_node
- replace_item
- replace_node
- find_unknown_nodes
- added setting for enabling "unsafe" methods & commands
- added support for unregistering ores
- all types are loaded from <world_path>/cleaner.json file
- added localization support
v1.1
----
- uses "register_lbm" with "run_at_every_load" instead of "register_abm" to save resources

357
mods/admin/cleaner/chat.lua Normal file
View File

@ -0,0 +1,357 @@
--- Cleaner Chat Commands
--
-- @topic commands
local S = core.get_translator(cleaner.modname)
local function pos_list(ppos, radius)
local plist = {}
for x = ppos.x - radius, ppos.x + radius, 1 do
for y = ppos.y - radius, ppos.y + radius, 1 do
for z = ppos.z - radius, ppos.z + radius, 1 do
table.insert(plist, {x=x, y=y, z=z})
end
end
end
return plist
end
local param_desc = {
["radius"] = S("Search radius."),
["entity"] = S("Entity technical name."),
["node"] = S("Node technical name."),
["old_node"] = S("Technical name of node to be replaced."),
["new_node"] = S("Technical name of node to be used in place."),
["old_item"] = S("Technical name of item to be replaced."),
["new_item"] = S("Technical name of item to be used in place."),
["ore"] = S("Ore technical name."),
}
local function format_help(cmd, param_string, params)
local retval = S("Usage:") .. "\n /" .. cmd .. " " .. param_string
.. "\n"
local p_count = 0
for _, p in ipairs(params) do
if p_count == 0 then
retval = retval .. "\n" .. S("Params:")
end
retval = retval .. "\n " .. S(p) .. ": " .. param_desc[p]
p_count = p_count + 1
end
return retval
end
local cmd_repo = {
entity = {
cmd = "remove_entity",
params = "<" .. S("entity") .. "> [" .. S("radius") .. "]",
},
node = {
cmd_rem = "remove_node",
cmd_rep = "replace_node",
cmd_find = "find_unknown_nodes",
params_rem = "<" .. S("node") .. "> [" .. S("radius") .. "]",
params_rep = "<" .. S("old_node") .. "> <" .. S("new_node") .. "> [" .. S("radius") .. "]",
params_find = "[" .. S("radius") .. "]",
},
item = {
cmd = "replace_item",
params = "<" .. S("old_item") .. "> <" .. S("new_item") .. ">",
},
ore = {
cmd = "remove_ore",
params = "<" .. S("ore") .. ">",
},
param = {
missing = S("Missing parameter."),
excess = S("Too many parameters."),
mal_radius = S("Radius must be a number."),
},
}
--- Removes nearby entities.
--
-- @chatcmd remove_entity
-- @param entity Entity technical name.
-- @tparam[opt] int radius
core.register_chatcommand(cmd_repo.entity.cmd, {
privs = {server=true},
description = S("Remove an entity from game."),
params = cmd_repo.entity.params,
func = function(name, param)
local entity
local radius = 100
if param:find(" ") then
entity = param:split(" ")
radius = tonumber(entity[2])
entity = entity[1]
else
entity = param
end
local err
if not entity or entity:trim() == "" then
err = cmd_repo.param.missing
elseif not radius then
err = cmd_repo.param.mal_radius
end
if err then
return false, err .. "\n\n"
.. format_help(cmd_repo.entity.cmd, cmd_repo.entity.params, {"entity", "radius"})
end
local player = core.get_player_by_name(name)
local total_removed = 0
for _, object in ipairs(core.get_objects_inside_radius(player:get_pos(), radius)) do
local lent = object:get_luaentity()
if lent then
if lent.name == entity then
object:remove()
total_removed = total_removed + 1
end
else
if object:get_properties().infotext == entity then
object:remove()
total_removed = total_removed + 1
end
end
end
return true, S("Removed @1 entities.", total_removed)
end,
})
--- Removes nearby nodes.
--
-- @chatcmd remove_node
-- @param node Node technical name.
-- @tparam[opt] int radius
core.register_chatcommand(cmd_repo.node.cmd_rem, {
privs = {server=true},
description = S("Remove a node from game."),
params = cmd_repo.node.params_rem,
func = function(name, param)
local nname
local radius = 100
if param:find(" ") then
nname = param:split(" ")
radius = tonumber(nname[2])
nname = nname[1]
else
nname = param
end
local err
if not nname or nname:trim() == "" then
err = cmd_repo.param.missing
elseif not radius then
err = cmd_repo.param.mal_radius
end
if err then
return false, err .. "\n\n"
.. format_help(cmd_repo.node.cmd_rem, cmd_repo.node.params_rem, {"node", "radius"})
end
local ppos = core.get_player_by_name(name):get_pos()
local total_removed = 0
for _, npos in ipairs(pos_list(ppos, radius)) do
local node = core.get_node_or_nil(npos)
if node and node.name == nname then
core.remove_node(npos)
total_removed = total_removed + 1
end
end
return true, S("Removed @1 nodes.", total_removed)
end,
})
--- Replaces an item.
--
-- @chatcmd replace_item
-- @param old_item Technical name of item to replace.
-- @param new_item Technical name of item to be used in place.
core.register_chatcommand(cmd_repo.item.cmd, {
privs = {server=true},
description = S("Replace an item in game."),
params = cmd_repo.item.params,
func = function(name, param)
local help = format_help(cmd_repo.item.cmd, cmd_repo.item.params, {"old_item", "new_item"})
if not param:find(" ") then
return false, cmd_repo.param.missing .. "\n\n" .. help
end
local src = param:split(" ")
local tgt = src[2]
src = src[1]
local retval, msg = cleaner.replace_item(src, tgt, true)
if not retval then
return false, msg
end
return true, S("Success!")
end,
})
--- Replaces nearby nodes.
--
-- FIXME: sometimes nodes on top disappear
--
-- @chatcmd replace_node
-- @param old_node Technical name of node to replace.
-- @param new_node Technical name of node to be used in place.
-- @tparam[opt] int radius
core.register_chatcommand(cmd_repo.node.cmd_rep, {
privs = {server=true},
description = S("Replace a node in game."),
params = cmd_repo.node.params_rep,
func = function(name, param)
local help = format_help(cmd_repo.node.cmd_rep, cmd_repo.node.params_rep, {"old_node", "new_node", "radius"})
if not param:find(" ") then
return false, cmd_repo.param.missing .. "\n\n" .. help
end
local radius = 100
local params = param:split(" ")
local src = params[1]
local tgt = tostring(params[2])
if #params > 2 then
radius = tonumber(params[3])
end
if not radius then
return false, cmd_repo.param.mal_radius .. "\n\n" .. help
end
local new_node = core.registered_nodes[tgt]
if not new_node then
return false, S('Cannot use unknown node "@1" as replacement.', tgt)
end
local total_replaced = 0
local ppos = core.get_player_by_name(name):get_pos()
for _, npos in ipairs(pos_list(ppos, radius)) do
local node = core.get_node_or_nil(npos)
if node and node.name == src then
core.remove_node(npos)
core.place_node(npos, new_node)
total_replaced = total_replaced + 1
end
end
return true, S("Replaced @1 nodes.", total_replaced)
end,
})
--- Checks for nearby unknown nodes.
--
-- @chatcmd find_unknown_nodes
-- @tparam[opt] int radius Search radius.
core.register_chatcommand(cmd_repo.node.cmd_find, {
privs = {server=true},
description = S("Find names of unknown nodes."),
params = cmd_repo.node.params_find,
func = function(name, param)
local help = format_help(cmd_repo.node.cmd_find, cmd_repo.node.params_find, {"radius"})
if param:find(" ") then
return false, cmd_repo.param.excess .. "\n\n" .. help
end
local radius = 100
if param and param:trim() ~= "" then
radius = tonumber(param)
end
if not radius then
return false, cmd_repo.param.mal_radius .. "\n\n" .. help
end
local ppos = core.get_player_by_name(name):get_pos()
local checked_nodes = {}
local unknown_nodes = {}
for _, npos in ipairs(pos_list(ppos, radius)) do
local node = core.get_node_or_nil(npos)
if node and not checked_nodes[node.name] then
if not core.registered_nodes[node.name] then
table.insert(unknown_nodes, node.name)
end
checked_nodes[node.name] = true
end
end
local msg
if #unknown_nodes > 0 then
msg = S("Found unknown nodes: @1", table.concat(unknown_nodes, ", "))
else
msg = S("No unknown nodes found.")
end
return true, msg
end,
})
--- Unsafe commands.
--
-- Enabled with `cleaner.unsafe` setting.
--
-- @section unsafe
if cleaner.unsafe then
--- Registers an ore to be removed.
--
-- @chatcmd remove_ore
-- @param ore Ore technical name.
core.register_chatcommand(cmd_repo.ore.cmd, {
privs = {server=true},
description = S("Remove an ore from game."),
params = cmd_repo.ore.params,
func = function(name, param)
local err
if not param or param:trim() == "" then
err = cmd_repo.param.missing
elseif param:find(" ") then
err = cmd_repo.param.excess
end
if err then
return false, err .. "\n\n" .. format_help(cmd_repo.ore.cmd, cmd_repo.ore.params, {"ore"})
end
local success = false
local msg
local registered, total_removed = cleaner.remove_ore(param)
if not registered then
msg = S('Ore "@1" not found, not unregistering.', param)
else
msg = S("Unregistered @1 ores (this will be undone after server restart).", total_removed)
success = true
end
return success, msg
end
})
end

View File

@ -1,20 +1,30 @@
local misc = dofile(cleaner.modpath .. "/misc_functions.lua")
local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-- populate entities list from file in world path
local e_list = {remove={}}
local entities_data = aux.get_world_data().entities
-- START: backward compat
local e_path = core.get_worldpath() .. "/clean_entities.json"
local e_file = io.open(e_path, "r")
if e_file then
cleaner.log("action", "found deprecated clean_entities.json, updating")
local data_in = core.parse_json(e_file:read("*a"))
e_file:close()
if data_in then
e_list = data_in
if data_in and data_in.remove then
for _, r in ipairs(data_in.remove) do
table.insert(entities_data.remove, r)
end
end
-- don't read deprecated file again
os.rename(e_path, e_path .. ".old")
end
-- backward compat
local e_path_old = core.get_worldpath() .. "/clean_entities.txt"
e_file = io.open(e_path_old, "r")
@ -25,7 +35,7 @@ if e_file then
for _, e in ipairs(data_in) do
e = e:trim()
if e ~= "" and e:sub(1, 1) ~= "#" then
table.insert(e_list.remove, e)
table.insert(entities_data.remove, e)
end
end
@ -33,23 +43,17 @@ if e_file then
os.rename(e_path_old, e_path_old .. ".bak") -- don't read deprecated file again
end
e_list.remove = misc.clean_duplicates(e_list.remove)
-- END: backward compat
entities_data.remove = aux.clean_duplicates(entities_data.remove)
-- update json file with any changes
e_file = io.open(e_path, "w")
if e_file then
local data_out = core.write_json(e_list, true):gsub("\"remove\" : null", "\"remove\" : []")
e_file:write(data_out)
e_file:close()
end
aux.update_world_data("entities", entities_data)
for _, e in ipairs(e_list.remove) do
cleaner.log("debug", "Cleaning entity: " .. e)
core.register_entity(":" .. e, {
on_activate = function(self, staticdata)
self.object:remove()
end,
})
end
core.register_on_mods_loaded(function()
for _, e in ipairs(entities_data.remove) do
cleaner.log("action", "registering entity for removal: " .. e)
cleaner.register_entity_removal(e)
end
end)

View File

@ -30,11 +30,20 @@ function cleaner.log(lvl, msg)
end
end
local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-- initialize world file
aux.update_world_data()
local scripts = {
"settings",
"api",
"chat",
"entities",
"nodes",
"items",
"ores",
}
for _, script in ipairs(scripts) do

View File

@ -1,55 +1,49 @@
local misc = dofile(cleaner.modpath .. "/misc_functions.lua")
local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-- populate items list from file in world path
local items_data = aux.get_world_data().items
-- START: backward compat
-- populate nodes list from file in world path
local i_list = {replace={}}
local i_path = core.get_worldpath() .. "/clean_items.json"
local i_file = io.open(i_path, "r")
if i_file then
cleaner.log("action", "found deprecated clean_items.json, updating")
local data_in = core.parse_json(i_file:read("*a"))
i_file:close()
if data_in then
i_list = data_in
if data_in and data_in.replace then
for k, v in pairs(data_in.replace) do
if not items_data.replace[k] then
items_data.replace[k] = v
end
end
end
-- don't read deprecated file again
os.rename(i_path, i_path .. ".old")
end
-- update json file with any changes
i_file = io.open(i_path, "w")
if i_file then
local data_out = core.write_json(i_list, true)
-- END: backward compat
data_out = data_out:gsub("\"replace\" : null", "\"replace\" : {}")
i_file:write(data_out)
i_file:close()
aux.update_world_data("items", items_data)
for i_old, i_new in pairs(items_data.replace) do
cleaner.register_item_replacement(i_old, i_new)
end
-- register actions for after server startup
core.after(0, function()
for i_old, i_new in pairs(i_list.replace) do
cleaner.log("action", "replacing item \"" .. i_old .. "\" with \"" .. i_new .. "\"")
core.register_on_mods_loaded(function()
for i_old, i_new in pairs(cleaner.get_replace_items()) do
cleaner.log("action", "registering item \"" .. i_old .. "\" to be replaced with \"" .. i_new .. "\"")
if not core.registered_items[i_old] then
cleaner.log("info", "\"" .. i_old .. "\" not registered, not unregistering")
else
cleaner.log("warning", "overriding registered item \"" .. i_old .. "\"")
core.unregister_item(i_old)
if core.registered_items[i_old] then
cleaner.log("error", "could not unregister \"" .. i_old .. "\"")
end
end
if not core.registered_items[i_new] then
cleaner.log("warning", "adding alias for unregistered item \"" .. i_new .. "\"")
end
core.register_alias(i_old, i_new)
if core.registered_aliases[i_old] == i_new then
cleaner.log("info", "registered alias \"" .. i_old .. "\" for \"" .. i_new .. "\"")
else
cleaner.log("error", "could not register alias \"" .. i_old .. "\" for \"" .. i_new .. "\"")
local retval, msg = cleaner.replace_item(i_old, i_new)
if not retval then
cleaner.log("warning", msg)
end
end
end)

View File

@ -0,0 +1,41 @@
# Translated by
# chat commands
entity=
node=
radius=
old_item=
new_item=
old_node=
new_node=
ore=
Usage:=
Params:=
Search radius.=
Entity technical name.=
Node technical name.=
Technical name of node to be replaced.=
Technical name of node to be used in place.=
Technical name of item to be replaced.=
Technical name of item to be used in place.=
Ore technical name.=
Remove an entity from game.=
Remove a node from game.=
Replace an item in game.=
Replace a node in game.=
Find names of unknown nodes.=
Remove an ore from game.=
Missing parameter.=
Too many parameters.=
Radius must be a number.=
Cannot use unknown item "@1" as replacement.=
Cannot use unknown node "@1" as replacement.=
Replaced @1 nodes.=
Removed @1 nodes.=
Removed @1 entities.=
Found unknown nodes: @1=
No unknown nodes found.=
Ore "@1" not found, not unregistering.=
Unregistered @1 ores (this will be undone after server restart).=
Success!=

View File

@ -19,7 +19,56 @@ local function clean_duplicates(t)
return t
end
local world_file = core.get_worldpath() .. "/cleaner.json"
local function get_world_data()
local wdata = {}
local buffer = io.open(world_file, "r")
if buffer then
wdata = core.parse_json(buffer:read("*a"))
buffer:close()
end
local rem_types = {"entities", "nodes", "ores",}
local rep_types = {"items", "nodes",}
for _, t in ipairs(rem_types) do
wdata[t] = wdata[t] or {}
wdata[t].remove = wdata[t].remove or {}
end
for _, t in ipairs(rep_types) do
wdata[t] = wdata[t] or {}
wdata[t].replace = wdata[t].replace or {}
end
return wdata
end
local function update_world_data(t, data)
local wdata = get_world_data()
if t and data then
wdata[t].remove = data.remove
wdata[t].replace = data.replace
end
local json_string = core.write_json(wdata, true):gsub("\"remove\" : null", "\"remove\" : []")
:gsub("\"replace\" : null", "\"replace\" : {}")
local buffer = io.open(world_file, "w")
if buffer then
buffer:write(json_string)
buffer:close()
return true
end
return false
end
return {
clean_duplicates = clean_duplicates,
get_world_data = get_world_data,
update_world_data = update_world_data,
}

View File

@ -3,3 +3,4 @@ description = A mod that can be used to remove/replace unknown entities, nodes,
version = 1.1
license = MIT
author = PilzAdam, Jordan Irwin (AntumDeluge)
min_minetest_version = 5.0

View File

@ -1,20 +1,40 @@
local misc = dofile(cleaner.modpath .. "/misc_functions.lua")
local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-- populate nodes list from file in world path
local n_list = {remove={}, replace={}}
local nodes_data = aux.get_world_data().nodes
-- START: backward compat
local n_path = core.get_worldpath() .. "/clean_nodes.json"
local n_file = io.open(n_path, "r")
if n_file then
cleaner.log("action", "found deprecated clean_nodes.json, updating")
local data_in = core.parse_json(n_file:read("*a"))
n_file:close()
if data_in then
n_list = data_in
if data_in.remove then
for _, r in ipairs(data_in.remove) do
table.insert(nodes_data.remove, r)
end
end
if data_in.replace then
for k, v in pairs(data_in.replace) do
if not nodes_data.replace[k] then
nodes_data.replace[k] = v
end
end
end
end
-- don't read deprecated file again
os.rename(n_path, n_path .. ".old")
end
-- backward compat
local n_path_old = core.get_worldpath() .. "/clean_nodes.txt"
n_file = io.open(n_path_old, "r")
@ -25,36 +45,21 @@ if n_file then
for _, e in ipairs(data_in) do
e = e:trim()
if e ~= "" and e:sub(1, 1) ~= "#" then
table.insert(n_list.remove, e)
table.insert(nodes_data.remove, e)
end
end
n_file:close()
os.rename(n_path_old, n_path_old .. ".bak") -- don't read deprecated file again
os.rename(n_path_old, n_path_old .. ".old") -- don't read deprecated file again
end
n_list.remove = misc.clean_duplicates(n_list.remove)
-- END: backward compat
nodes_data.remove = aux.clean_duplicates(nodes_data.remove)
-- update json file with any changes
n_file = io.open(n_path, "w")
if n_file then
local data_out = core.write_json(n_list, true)
-- FIXME: how to do this with a single regex?
data_out = data_out:gsub("\"remove\" : null", "\"remove\" : []")
data_out = data_out:gsub("\"replace\" : null", "\"replace\" : {}")
n_file:write(data_out)
n_file:close()
end
for _, n in ipairs(n_list.remove) do
cleaner.log("debug", "Cleaning node: " .. n)
core.register_node(":" .. n, {
groups = {to_remove=1},
})
end
aux.update_world_data("nodes", nodes_data)
core.register_lbm({
name = "cleaner:remove_nodes",
@ -65,14 +70,6 @@ core.register_lbm({
end,
})
for n_old, n_new in pairs(n_list.replace) do
cleaner.log("debug", "Replacing node \"" .. n_old .. "\" with \"" .. n_new .. "\"")
core.register_node(":" .. n_old, {
groups = {to_replace=1},
})
end
core.register_lbm({
name = "cleaner:replace_nodes",
nodenames = {"group:to_replace"},
@ -80,7 +77,7 @@ core.register_lbm({
action = function(pos, node)
core.remove_node(pos)
local new_node_name = n_list.replace[node.name]
local new_node_name = cleaner.get_replace_nodes()[node.name]
local new_node = core.registered_nodes[new_node_name]
if new_node then
core.place_node(pos, new_node)
@ -89,3 +86,15 @@ core.register_lbm({
end
end,
})
core.register_on_mods_loaded(function()
for _, n in ipairs(nodes_data.remove) do
cleaner.log("action", "registering node for removal: " .. n)
cleaner.register_node_removal(n)
end
for n_old, n_new in pairs(nodes_data.replace) do
cleaner.log("action", "registering node \"" .. n_old .. "\" to be replaced with \"" .. n_new .. "\"")
cleaner.register_node_replacement(n_old, n_new)
end
end)

View File

@ -0,0 +1,17 @@
if not cleaner.unsafe then return end
local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
local ores_data = aux.get_world_data().ores
for _, ore in ipairs(ores_data.remove) do
cleaner.register_ore_removal(ore)
end
core.register_on_mods_loaded(function()
for _, ore in ipairs(cleaner.get_remove_ores()) do
cleaner.log("action", "unregistering ore: " .. ore)
cleaner.remove_ore(ore)
end
end)

View File

@ -0,0 +1,14 @@
--- Cleaner Settings
--
-- @topic settings
--- Enables unsafe methods.
--
-- `cleaner.remove_ore`
--
-- @setting cleaner.unsafe
-- @settype bool
-- @default false
cleaner.unsafe = core.settings:get_bool("cleaner.unsafe", false)

View File

@ -0,0 +1,5 @@
# Enables unsafe methods.
#
# - cleaner.remove_ore
cleaner.unsafe (Enable unsafe methods) bool false

View File

@ -562,6 +562,14 @@ chatlog.single_file (Single file chatlog) bool false
chatlog.disable (Disable chatlog) bool false
[*cleaner]
# Enables unsafe methods.
#
# - cleaner.remove_ore
cleaner.unsafe (Enable unsafe methods) bool false
[*craftguide]
# The progressive mode shows recipes you can craft from items you ever had in your inventory.