Update cleaner mod to Git commit 9230e0c...
https://github.com/AntumMT/mod-cleaner/tree/9230e0c
This commit is contained in:
parent
196afb015a
commit
e7c9b61c25
@ -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
|
||||
|
@ -964,6 +964,14 @@ inventory = sfinv
|
||||
## ADMIN ##
|
||||
###########
|
||||
|
||||
# *** cleaner ***
|
||||
|
||||
## Enables unsafe methods.
|
||||
# type: bool
|
||||
# default: false
|
||||
#cleaner.unsafe = false
|
||||
|
||||
|
||||
# *** whitelist ***
|
||||
|
||||
## Enables/Disables whitelist feature.
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
193
mods/admin/cleaner/api.lua
Normal 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
|
@ -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
357
mods/admin/cleaner/chat.lua
Normal 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
|
@ -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
|
||||
|
||||
-- backward compat
|
||||
-- don't read deprecated file again
|
||||
os.rename(e_path, e_path .. ".old")
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
|
||||
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,
|
||||
})
|
||||
aux.update_world_data("entities", entities_data)
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
-- 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)
|
||||
-- don't read deprecated file again
|
||||
os.rename(i_path, i_path .. ".old")
|
||||
end
|
||||
|
||||
data_out = data_out:gsub("\"replace\" : null", "\"replace\" : {}")
|
||||
-- END: backward compat
|
||||
|
||||
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)
|
||||
|
41
mods/admin/cleaner/locale/template.txt
Normal file
41
mods/admin/cleaner/locale/template.txt
Normal 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!=
|
@ -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,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
-- backward compat
|
||||
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
|
||||
|
||||
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)
|
||||
|
17
mods/admin/cleaner/ores.lua
Normal file
17
mods/admin/cleaner/ores.lua
Normal 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)
|
14
mods/admin/cleaner/settings.lua
Normal file
14
mods/admin/cleaner/settings.lua
Normal 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)
|
5
mods/admin/cleaner/settingtypes.txt
Normal file
5
mods/admin/cleaner/settingtypes.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
# Enables unsafe methods.
|
||||
#
|
||||
# - cleaner.remove_ore
|
||||
cleaner.unsafe (Enable unsafe methods) bool false
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user