diff --git a/.cdb.json b/.cdb.json
deleted file mode 100644
index ada3089..0000000
--- a/.cdb.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "type": "MOD",
- "title": "Cleaner",
- "short_description": "Remove/Replace unknown entities, nodes, & items.",
- "license": "MIT",
- "media_license": "CC0-1.0",
- "tags": ["world_tools"],
- "repo": "https://codeberg.org/AntumLuanti/mod-cleaner",
- "issue_tracker": "https://codeberg.org/AntumLuanti/mod-cleaner/issues",
- "forums": 18381
-}
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 62c4b62..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-.* export-ignore
-*.py export-ignore
diff --git a/.github/workflows/reference.yml b/.github/workflows/reference.yml
deleted file mode 100644
index 29dec4c..0000000
--- a/.github/workflows/reference.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-name: Build Reference
-on:
- push:
- tags:
- - 'v[0-9]*'
- workflow_dispatch:
-
-jobs:
- build:
- name: Build Reference
- runs-on: ubuntu-latest
- steps:
- - name: Setup Lua
- uses: leafo/gh-actions-lua@v8
- with:
- luaVersion: 5.4
- - name: Setup Lua Rocks
- uses: leafo/gh-actions-luarocks@v4
- - name: Setup dependencies
- run: luarocks install --only-deps https://raw.githubusercontent.com/lunarmodules/LDoc/master/ldoc-scm-3.rockspec
- - name: Setup LDoc
- run: git clone --single-branch --branch=custom https://github.com/AntumDeluge/LDoc.git ldoc
- - name: Checkout & Build Docs
- run: git clone https://github.com/AntumMT/mod-cleaner.git cleaner && cd cleaner && chmod +x .ldoc/build_versioned_docs.sh && ./.ldoc/build_versioned_docs.sh
- - name: Deploy
- uses: peaceiris/actions-gh-pages@v3
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: cleaner/docs/
diff --git a/.ldoc/build_versioned_docs.sh b/.ldoc/build_versioned_docs.sh
deleted file mode 100755
index 728103f..0000000
--- a/.ldoc/build_versioned_docs.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env bash
-
-# place this file in mod ".ldoc" directory
-
-
-d_config="$(dirname $(readlink -f $0))"
-
-cd "${d_config}/.."
-
-d_root="$(pwd)"
-d_export="${d_export:-${d_root}/docs/reference}"
-
-cmd_ldoc="${d_root}/../ldoc/ldoc.lua"
-if test -f "${cmd_ldoc}"; then
- if test ! -x "${cmd_ldoc}"; then
- chmod +x "${cmd_ldoc}"
- fi
-else
- cmd_ldoc="ldoc"
-fi
-
-# clean old files
-rm -rf "${d_export}"
-
-# store current branch
-main_branch="$(git branch --show-current)"
-
-html_out="\n
\n\n\n\n\n"
-
-# generate new doc files
-mkdir -p "${d_export}"
-for vinfo in $(git tag -l --sort=-v:refname | grep "^v[0-9]"); do
- echo -e "\nbuilding ${vinfo} docs ..."
- git checkout ${vinfo}
- d_temp="${d_config}/temp"
- mkdir -p "${d_temp}"
-
- # backward compat
- f_config="${d_root}/docs/config.ld"
- if test ! -f "${f_config}"; then
- f_config="${d_config}/config.ld"
- fi
-
- if test ! -f "${f_config}"; then
- echo -e "\nLDoc config not available for ${vinfo}, skipping build ..."
- continue
- fi
-
- "${cmd_ldoc}" --UNSAFE_NO_SANDBOX --multimodule -c "${f_config}" -d "${d_temp}" "${d_root}"; retval=$?
- if test ${retval} -ne 0; then
- echo -e "\nERROR: doc build for ${vinfo} failed!"
- rm -rf "${d_temp}"
- continue
- fi
-
- # show version info
- for html in $(find "${d_temp}" -type f -name "*.html"); do
- sed -i -e "s|^[cC]leaner
$|Cleaner (${vinfo})
|" \
- "${html}"
- done
-
- if test -d "${d_root}/textures"; then
- # copy textures to data directory
- echo -e "\ncopying textures ..."
- d_data="${d_temp}/data"
- mkdir -p "${d_data}"
- texture_count=0
- for png in $(find "${d_root}/textures" -maxdepth 1 -type f -name "*.png"); do
- t_png="${d_data}/$(basename ${png})"
- if test -f "${t_png}"; then
- echo "WARNING: not overwriting existing file: ${t_png}"
- else
- cp "${png}" "${d_data}"
- texture_count=$((texture_count + 1))
- printf "\rcopied ${texture_count} textures"
- fi
- done
- fi
-
- mv "${d_temp}" "${d_export}/${vinfo}"
- if test -z ${vcur+x}; then
- vcur="${vinfo}"
- ln -s "${d_export}/${vinfo}" "${d_export}/current"
- ln -s "${d_export}/${vinfo}" "${d_export}/latest"
- html_out="${html_out} - current
\n"
- html_out="${html_out} - latest
\n"
- fi
- html_out="${html_out} - ${vinfo}
\n"
-done
-
-html_out="${html_out}
\n\n"
-
-cd "${d_root}"
-git checkout ${main_branch}
-
-echo -e "${html_out}" > "${d_export}/index.html"
-
-echo -e "\nDone!"
diff --git a/.ldoc/config.ld b/.ldoc/config.ld
deleted file mode 100644
index 10e46db..0000000
--- a/.ldoc/config.ld
+++ /dev/null
@@ -1,201 +0,0 @@
-
-local dofile, print, error, type, table, ipairs, string, tostring
-if import then
- dofile = import("dofile")
- print = import("print")
- error = import("error")
- type = import("type")
- table = import("table")
- ipairs = import("ipairs")
- string = import("string")
- tostring = import("tostring")
-end
-
-
-project = "Cleaner"
-title = "Cleaner mod for Luanti"
-format = "markdown"
-not_luadoc=true
-boilerplate = false
-icon = "textures/cleaner_pencil.png"
-favicon = "https://www.luanti.org/media/icon.svg"
-
-file = {
- "settings.lua",
- "api.lua",
- "chat.lua",
- "tools.lua",
- ".ldoc/config.luadoc",
-}
-
-new_type("chatcmd", "Chat Commands")
-new_type("setting", "Settings")
-new_type("tool", "Tools")
-new_type("json", "JSON Configurations")
-
-
-local function video_frame(src)
- return ''
-end
-
-
-local tags
-tags, custom_tags = dofile(".ldoc/tags.ld")
-
-
--- START: handling items to prevent re-parsing
-
-local registered_items = {}
-
-local function is_registered(item)
- if not registered_items[item.type] then return false end
-
- for _, tbl in ipairs(registered_items[item.type]) do
- if item == tbl then
- return true
- end
- end
-
- return false
-end
-
-local function register(item)
- if not registered_items[item.type] then
- registered_items[item.type] = {}
- end
-
- if not is_registered(item) then
- table.insert(registered_items[item.type], item)
- end
-end
-
--- END:
-
-
-local function format_setting_tag(desc, value)
- return "\n- `" .. desc .. ":` `" .. value .. "`"
-end
-
-local function setting_handler(item)
- if not ipairs or not type then
- return item
- end
-
- local tags = {
- {"settype", "type"},
- {"default"},
- {"min", "minimum value"},
- {"max", "maximum value"},
- }
-
- local def = {
- ["settype"] = format_setting_tag("type", "string"),
- }
-
- for _, t in ipairs(tags) do
- local name = t[1]
- local desc = t[2]
- if not desc then desc = name end
-
- local value = item.tags[name]
- if type(value) == "table" then
- if #value > 1 then
- local msg = item.file.filename .. " (line " .. item.lineno
- .. "): multiple instances of tag \"" .. name .. "\" found"
- if error then
- error(msg)
- elseif print then
- print("WARNING: " .. msg)
- end
- end
-
- if value[1] then
- def[name] = format_setting_tag(desc, value[1])
- end
- end
- end
-
- item.description = item.description .. "\n\n**Definition:**\n" .. def.settype
- for _, t in ipairs({def.default, def.min, def.max}) do
- if t then
- item.description = item.description .. t
- end
- end
-
- return item
-end
-
-local function chatcmd_handler(item)
- for _, p in ipairs(item.params) do
- if item.modifiers.param[p].opt then
- item.name = item.name .. " [" .. p .. "]"
- else
- item.name = item.name .. " <" .. p .. ">"
- end
- end
-
- if #item.params > 0 then
- local pstring = "### Parameters:\n"
- for k, param in pairs(item.params) do
- if type(k) == "number" then
- local value = item.params.map[param]
-
- pstring = pstring .. '\n- '
- .. param .. ''
-
- local modifiers = item.modifiers.param[param]
- if modifiers and modifiers.type then
- pstring = pstring .. ' `' .. modifiers.type .. '`'
- end
-
- if value then
- pstring = pstring .. value
- end
-
- if modifiers and modifiers.opt then
- pstring = pstring .. " *(optional)*"
- end
- end
- end
-
- item.description = item.description .. "\n\n" .. pstring
- -- clear parameter list
- item.params = {}
- end
-
- return item
-end
-
-function custom_display_name_handler(item, default_handler)
- if not is_registered(item) then
- if item.type == "setting" then
- item = setting_handler(item)
- elseif item.type == "chatcmd" then
- item = chatcmd_handler(item)
- end
-
- local parse_tags = {"priv", "note"}
- for _, pt in ipairs(parse_tags) do
- local tvalues = item.tags[pt]
- if tvalues then
- local tstring = ""
-
- local title = tags.get_title(pt)
- if title then
- tstring = tstring .. "\n\n### " .. title .. ":\n"
- end
-
- for _, tv in ipairs(tvalues) do
- tstring = tstring .. "\n- " .. tags.format(pt, tv)
- end
-
- item.description = item.description .. tstring
- end
- end
- end
-
- register(item)
- return default_handler(item)
-end
diff --git a/.ldoc/config.luadoc b/.ldoc/config.luadoc
deleted file mode 100644
index 7cb0044..0000000
--- a/.ldoc/config.luadoc
+++ /dev/null
@@ -1,55 +0,0 @@
-
---- World Path Configuration
---
--- @topic config
-
-
---- Main configuration file.
---
--- Registering items, entities, etc. for cleaning can be done in ***cleaner.json***
--- in the world directory (`/cleaner.json`). If it does not exist
--- it will be created automatically when the server is started.
---
--- It is formatted as follows:
---
--- {
--- "entities" :
--- {
--- "remove" : []
--- },
--- "items" :
--- {
--- "replace" : {}
--- },
--- "nodes" :
--- {
--- "remove" : [],
--- "replace" : {}
--- },
--- "ores" :
--- {
--- "remove" : []
--- }
--- }
---
--- `remove` key works for nodes, entities, & ores. `replace` key works for
--- nodes & items. Their functions are self-explanatory.
---
--- @json cleaner.json
--- @usage
--- Cleaning nodes example:
--- {
--- "nodes" :
--- {
--- "remove" :
--- [
--- "old:node_1",
--- "old:node_2",
--- ],
--- "replace" :
--- {
--- "old:node_3" : "new:node_1",
--- "old:node_4" : "new:node_2",
--- },
--- },
--- }
diff --git a/.ldoc/gendoc.sh b/.ldoc/gendoc.sh
deleted file mode 100755
index 75ef2c3..0000000
--- a/.ldoc/gendoc.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-
-# place this file in mod ".ldoc" directory
-
-
-d_ldoc="$(dirname $(readlink -f $0))"
-f_config="${d_ldoc}/config.ld"
-
-cd "${d_ldoc}/.."
-
-d_root="$(pwd)"
-d_export="${d_export:-${d_root}/docs/reference}"
-
-cmd_ldoc="${d_ldoc}/ldoc/ldoc.lua"
-if test ! -x "${cmd_ldoc}"; then
- cmd_ldoc="ldoc"
-fi
-
-# clean old files
-rm -rf "${d_export}"
-
-vinfo="v$(grep "^version = " "${d_root}/mod.conf" | head -1 | sed -e 's/version = //')"
-d_data="${d_export}/${vinfo}/data"
-
-# generate new doc files
-"${cmd_ldoc}" --UNSAFE_NO_SANDBOX --multimodule -c "${f_config}" -d "${d_export}/${vinfo}" "${d_root}"; retval=$?
-
-# check exit status
-if test ${retval} -ne 0; then
- echo -e "\nan error occurred (ldoc return code: ${retval})"
- exit ${retval}
-fi
-
-# show version info
-for html in $(find "${d_export}/${vinfo}" -type f -name "*.html"); do
- sed -i -e "s|^[cC]leaner
$|Cleaner (${vinfo})
|" "${html}"
-done
-
-# copy textures to data directory
-echo -e "\ncopying textures ..."
-mkdir -p "${d_data}"
-texture_count=0
-for png in $(find "${d_root}/textures" -maxdepth 1 -type f -name "*.png"); do
- t_png="${d_data}/$(basename ${png})"
- if test -f "${t_png}"; then
- echo "WARNING: not overwriting existing file: ${t_png}"
- else
- cp "${png}" "${d_data}"
- texture_count=$((texture_count + 1))
- printf "\rcopied ${texture_count} textures"
- fi
-done
-
-echo -e "\n\nDone!"
diff --git a/.ldoc/tags.ld b/.ldoc/tags.ld
deleted file mode 100644
index 91ab6dd..0000000
--- a/.ldoc/tags.ld
+++ /dev/null
@@ -1,81 +0,0 @@
-
-local tags = {}
-local tag_list = {}
-local custom_tags = {}
-
-local register_tag = function(name, tag)
- local new_tag = {name, title=tag.title, hidden=tag.hidden, format=tag.format}
- table.insert(custom_tags, new_tag)
- tag_list[name] = {title=tag.title, format=tag.format}
-end
-
-tags.get_title = function(tname)
- local t = tag_list[tname]
- if t then
- return t.title
- end
-end
-
-tags.format = function(tname, value)
- local t = tag_list[tname]
- if t then
- if type(t.format) == "function" then
- value = t.format(value)
- end
- end
-
- return value
-end
-
-
-local new_tags = {
- ["priv"] = {
- title = "Required Privileges",
- hidden = true,
- },
- ["note"] = {
- title = "Notes",
- hidden = true,
- format = function(value)
- return "*" .. value .. "*"
- end,
- },
- ["video"] = {
- title = "Video",
- format = video_frame,
- },
- ["youtube"] = {
- title = "Video",
- format = function(value)
- return video_frame("https://www.youtube.com/embed/" .. value)
- end,
- },
- -- settings
- ["settype"] = {
- title = "Setting Type",
- hidden = true,
- },
- ["default"] = {
- title = "Default Value",
- hidden = true,
- },
- -- craft items/tools
- ["img"] = {
- title = "Image",
- format = function(value)
- return "
"
- end,
- },
- -- chat commands
- ["chatparam"] = {
- title = "Parameters",
- hidden = true,
- },
-}
-
-for k, v in pairs(new_tags) do
- register_tag(k, v)
-end
-
-
-return tags, custom_tags
diff --git a/LICENSE.txt b/LICENSE.txt
index 357bcd0..9042c25 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,21 +1,13 @@
-The MIT License (MIT)
-
-Copyright © 2021 Jordan Irwin (AntumDeluge)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/README.md b/README.md
index 70253ef..77b9f63 100644
--- a/README.md
+++ b/README.md
@@ -1,86 +1,18 @@
-## Cleaner mod for Luanti
-
-### Description:
-
-A [Luanti (Minetest)][Luanti] mod that can be used to remove/replace unknown entities, nodes, & items. Originally forked from [PilzAdam's ***clean*** mod][f.pilzadam].
-
-
-
-### Licensing:
-
-- Code: [MIT](LICENSE.txt)
-- Textures: CC0
-
-### Requirements:
-
-- Luanti minimum version: 5.0
-- Depends: none
-
-### Usage:
-
-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.
-
-It is formatted as follows:
-```json
-{
- "entities" :
- {
- "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, & 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]
-- [Forum](https://forum.luanti.org/viewtopic.php?t=18381)
-- [Git repo](https://github.com/AntumMT/mod-cleaner)
-- [Reference](https://antummt.github.io/mod-cleaner/reference/latest/)
-- [Changelog](changelog.txt)
-- [TODO](TODO.txt)
+## Clean mod for [Minetest][]
-[Luanti]: https://luanti.org/
-[f.pilzadam]: https://forum.luanti.org/viewtopic.php?t=2777
-[ContentDB]: https://content.luanti.org/packages/AntumDeluge/cleaner/
+---
+### **Description:**
+
+Fork of [PilzAdam's ***clean*** mod][f.pilzadam] for Minetest.
+
+
+---
+### **Licensing:**
+
+[WTFPL](LICENSE.txt)
+
+
+[Minetest]: http://www.minetest.net/
+
+[f.pilzadam]: https://forum.minetest.net/viewtopic.php?t=2777
diff --git a/TODO.txt b/TODO.txt
deleted file mode 100644
index b800544..0000000
--- a/TODO.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-TODO:
-- update world file when chat commands are used
-- update inventories when items are replaced:
- - creative
- - storage (chests, etc.)
-- add LBM when removing an item if it is a node
-- add "radius" option for pencil or "xlen", "ylen", & "zlen" options
-- add "xrotate" & "zrorate" modes for pencil
-- don't require "server" priv for "find_unknown_nodes" & "find_neaby_nodes" commands
-- add chat command to find nodes with specified attributes
-- may be better to update player inventories on login than add aliases for items
-- use aliases for unknown nodes instead of LBM
-- only use LBM when a node to replace is still registered
diff --git a/api.lua b/api.lua
deleted file mode 100644
index a894148..0000000
--- a/api.lua
+++ /dev/null
@@ -1,194 +0,0 @@
-
---- 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
- cleaner.register_item_replacement(src, tgt)
-end
-
-
---- Unsafe Methods.
---
--- Enabled with [cleaner.unsafe](settings.html#cleaner.unsafe) setting.
---
--- @section unsafe
-
-
-if cleaner.unsafe then
- local remove_ores = {}
-
- --- Retrieves list of ores to be removed.
- --
- -- @treturn table Ores to be removed.
- 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
diff --git a/changelog.txt b/changelog.txt
deleted file mode 100644
index 0214081..0000000
--- a/changelog.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-
-2025-01-18
-----------
-- fix undeclared global
-- added nil check after reading world data file
-
-
-v1.2.1
-----
-- use sounds mod for sounds
-- added nil check after reading world data file
-
-
-v1.2
-----
-- added API
-- added support for unregistering ores (unsafe)
-- added setting for enabling "unsafe" methods & commands
-- all types are loaded from /cleaner.json file
-- added localization support
-- added Spanish localization
-- added pencil tool for erasing, adding, & swapping nodes
-- added chat commands:
- - remove_entities
- - remove_nodes
- - replace_items
- - replace_nodes
- - find_unknown_nodes
- - find_nearby_nodes
- - remove_ores (unsafe)
- - ctool (manages wielded cleaner tool settings)
-
-v1.1
-----
-- uses "register_lbm" with "run_at_every_load" instead of "register_abm" to save resources
- - suggested by bell07 ( https://forum.luanti.org/viewtopic.php?p=325519#p325519 )
-
-v1.0
-----
-- changed license to MIT
-- "clean_entities" & "clean_nodes" files now use json format
-- nodes can be replaced with other nodes
-- items can be replaced with other items (/clean_items.json file)
-
-v0.4
-----
-- changed technical name to "cleaner"
-- re-added functionality to clean nodes
-
-v0.3
-----
-- removed functionality for cleaning anything other than entities
-
-v0.2
-----
-- changed license to CC0
-- added some log output
-- entities to be cleaned can be configured & loaded from world directory
-
-v0.1
-----
-- forked from PilzAdam's "clean" mod @ forum post updated: 2013-06-08
-- replaced deprecated call to "minetest.env"
diff --git a/chat.lua b/chat.lua
deleted file mode 100644
index 3f7cf43..0000000
--- a/chat.lua
+++ /dev/null
@@ -1,660 +0,0 @@
-
---- Cleaner Chat Commands
---
--- @topic commands
-
-
-local S = core.get_translator(cleaner.modname)
-
-
-local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-
-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_def = {
- radius = {name=S("radius"), desc=S("Search radius.")},
- entity = {name=S("entity"), desc=S("Entity technical name.")},
- node = {name=S("node"), desc=S("Node technical name.")},
- old_node = {name=S("old_node"), desc=S("Technical name of node to be replaced.")},
- new_node = {name=S("new_node"), desc=S("Technical name of node to be used in place.")},
- old_item = {name=S("old_item"), desc=S("Technical name of item to be replaced.")},
- new_item = {name=S("new_item"), desc=S("Technical name of item to be used in place.")},
- ore = {name=S("ore"), desc=S("Ore technical name.")},
- action = {name=S("action"),
- desc=S('Action to execute. Can be one of "@1", "@2", or "@3".', "status", "setmode", "setnode")},
- value = {name=S("value"), desc=S('Mode or node to be set for tool (not required for "@1" action).', "status")},
-}
-
-local cmd_repo = {
- entity = {
- cmd = "remove_entities",
- params = {"entity"},
- oparams = {radius=100},
- },
- rem_node = {
- cmd = "remove_nodes",
- params = {"node"},
- oparams = {radius=5},
- },
- rep_node = {
- cmd = "replace_nodes",
- params = {"old_node", "new_node"},
- oparams = {radius=5},
- },
- find_node = {
- cmd = "find_unknown_nodes",
- oparams = {radius=100},
- },
- near_node = {
- cmd = "find_nearby_nodes",
- oparams = {radius=5},
- },
- item = {
- cmd = "replace_items",
- params = {"old_item", "new_item"},
- },
- ore = {
- cmd = "remove_ores",
- params = {"ore"},
- },
- tool = {
- cmd = "ctool",
- params = {"action", "value"},
- },
- param = {
- missing = S("Missing parameter."),
- excess = S("Too many parameters."),
- mal_radius = S("Radius must be a number."),
- },
-}
-
-for k, def in pairs(cmd_repo) do
- if k ~= "param" then
- local cmd_help = {
- param_string = "",
- usage_string = "/" .. def.cmd,
- }
-
- if def.params or def.oparams then
- if def.params then
- local params = {}
- for _, p in ipairs(def.params) do
- -- translate
- table.insert(params, S(p))
- end
-
- cmd_help.param_string = "<" .. table.concat(params, "> <") .. ">"
- end
- end
-
- if def.oparams then
- for k, v in pairs(def.oparams) do
- local op = k
- if type(op) == "number" then
- op = v
- end
-
- cmd_help.param_string = cmd_help.param_string .. " [" .. S(op) .. "]"
- end
- end
-
- if cmd_help.param_string ~= "" then
- cmd_help.usage_string = cmd_help.usage_string .. " " .. cmd_help.param_string
- end
-
- cmd_repo[k].help = cmd_help
- end
-end
-
-local function get_cmd_def(cmd)
- for k, v in pairs(cmd_repo) do
- if v.cmd == cmd then return v end
- end
-end
-
-local function format_usage(cmd)
- local def = get_cmd_def(cmd)
- if def then
- return S("Usage:") .. "\n " .. def.help.usage_string
- end
-end
-
-local function format_params(cmd)
- local def = get_cmd_def(cmd)
-
- local param_count
- -- FIXME: unused?
- local all_params = {}
- if def.params then
- for _, p in ipairs(def.params) do
- table.insert(all_params, p)
- end
- end
- if def.oparams then
- for k, v in pairs(def.oparams) do
-
- end
- end
-
- local retval = ""
- local p_count = 0
-
- if def.params then
- for _, p in ipairs(def.params) do
- if p_count == 0 then
- retval = retval .. S("Params:")
- end
-
- retval = retval .. "\n " .. S(p) .. ": " .. param_def[p].desc
-
- p_count = p_count + 1
- end
- end
-
- if def.oparams then
- for k, v in pairs(def.oparams) do
- if p_count == 0 then
- retval = retval .. S("Params:")
- end
-
- local p = k
- local dvalue = v
- if type(p) == "number" then
- p = v
- dvalue = nil
- end
-
- retval = retval .. "\n " .. S(p) .. ": " .. param_def[p].desc
- if dvalue then
- retval = retval .. " (" .. S("default: @1", dvalue) .. ")"
- end
-
- p_count = p_count + 1
- end
- end
-
- return retval
-end
-
-local function format_help(cmd)
- return format_usage(cmd) .. "\n\n" .. format_params(cmd)
-end
-
-
-local function check_radius(radius, pname)
- local is_admin = core.check_player_privs(pname, {server=true})
-
- if not is_admin and radius > 10 then
- radius = 10
- return radius, S("You do not have permission to set radius that high. Reduced to @1.", radius)
- end
-
- if radius > 100 then
- radius = 100
- return radius, S("Radius is too high. Reduced to @1.", radius)
- end
-
- return radius
-end
-
-
---- Removes nearby entities.
---
--- @chatcmd remove_entities
--- @param entity Entity technical name.
--- @tparam[opt] int radius Search radius (default: 100).
--- @priv server
--- @usage
--- # remove all mobs:horse entities within a radius of 10 nodes
--- /remove_entities mobs:horse 10
-core.register_chatcommand(cmd_repo.entity.cmd, {
- privs = {server=true},
- description = S("Remove an entity from game.") .. "\n\n"
- .. format_params(cmd_repo.entity.cmd),
- params = cmd_repo.entity.help.param_string,
- func = function(name, param)
- local entity
- local radius = cmd_repo.entity.oparams.radius
- 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
-
- local radius, msg = check_radius(radius, name)
- if msg then
- core.chat_send_player(name, msg)
- end
-
- if err then
- return false, err .. "\n\n" .. format_help(cmd_repo.entity.cmd)
- 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_nodes
--- @param node Node technical name.
--- @tparam[opt] int radius Search radius (default: 5).
--- @priv server
--- @usage
--- # remove all default:dirt nodes within a radius of 10
--- /remove_nodes default:dirt 10
-core.register_chatcommand(cmd_repo.rem_node.cmd, {
- privs = {server=true},
- description = S("Remove a node from game.") .. "\n\n"
- .. format_params(cmd_repo.rem_node.cmd),
- params = cmd_repo.rem_node.help.param_string,
- func = function(name, param)
- local nname
- local radius = cmd_repo.rem_node.oparams.radius
- 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
-
- local radius, msg = check_radius(radius, name)
- if msg then
- core.chat_send_player(name, msg)
- end
-
- if err then
- return false, err .. "\n\n" .. format_help(cmd_repo.rem_node.cmd)
- 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_items
--- @param old_item Technical name of item to replace.
--- @param new_item Technical name of item to be used in place.
--- @priv server
--- @usage
--- # replace default:sword_wood with default:sword_mese
--- /replace_items default:sword_wood default:sword_mese
-core.register_chatcommand(cmd_repo.item.cmd, {
- privs = {server=true},
- description = S("Replace an item in game.") .. "\n\n"
- .. format_params(cmd_repo.item.cmd),
- params = cmd_repo.item.help.param_string,
- func = function(name, param)
- if not param:find(" ") then
- return false, cmd_repo.param.missing .. "\n\n" .. format_help(cmd_repo.item.cmd)
- 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.
---
--- @chatcmd replace_nodes
--- @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 Search radius (default: 5).
--- @priv server
--- @usage
--- # replace all default:dirt nodes with default:cobble within a radius of 10
--- /replace_nodes default:dirt default:cobble 10
-core.register_chatcommand(cmd_repo.rep_node.cmd, {
- privs = {server=true},
- description = S("Replace a node in game.") .. "\n\n"
- .. format_params(cmd_repo.rep_node.cmd),
- params = cmd_repo.rep_node.help.param_string,
- func = function(name, param)
- local help = format_help(cmd_repo.rep_node.cmd)
-
- if not param:find(" ") then
- return false, cmd_repo.param.missing .. "\n\n" .. help
- end
-
- local radius = cmd_repo.rep_node.oparams.radius
- 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 radius, msg = check_radius(radius, name)
- if msg then
- core.chat_send_player(name, msg)
- end
-
- if not core.registered_nodes[tgt] 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
- if core.swap_node(npos, {name=tgt}) then
- total_replaced = total_replaced + 1
- else
- cleaner.log("error", "could not replace node at " .. core.pos_to_string(npos, 0))
- end
- 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 (default: 100).
--- @priv server
--- @usage
--- # print names of all unknown nodes within radius of 10
--- /find_unknown_nodes 10
-core.register_chatcommand(cmd_repo.find_node.cmd, {
- privs = {server=true},
- description = S("Find names of unknown nodes.") .. "\n\n"
- .. format_params(cmd_repo.find_node.cmd),
- params = cmd_repo.find_node.help.param_string,
- func = function(name, param)
- local help = format_help(cmd_repo.find_node.cmd)
-
- if param:find(" ") then
- return false, cmd_repo.param.excess .. "\n\n" .. help
- end
-
- local radius = cmd_repo.find_node.oparams.radius
- 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 radius, msg = check_radius(radius, name)
- if msg then
- core.chat_send_player(name, msg)
- 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 node_count = #unknown_nodes
- if node_count > 0 then
- msg = S("Found unknown nodes: @1", node_count) .. "\n " .. table.concat(unknown_nodes, ", ")
- else
- msg = S("No unknown nodes found.")
- end
-
- return true, msg
- end,
-})
-
---- Finds names of nearby nodes.
---
--- @chatcmd find_nearby_nodes
--- @tparam[opt] int radius Search radius (default: 5).
--- @priv server
--- @usage
--- # print names of all node types found within radius of 10
--- /find_nearby_nodes 10
-core.register_chatcommand(cmd_repo.near_node.cmd, {
- privs = {server=true},
- description = S("Find names of nearby nodes.") .. "\n\n"
- .. format_params(cmd_repo.near_node.cmd),
- params = cmd_repo.near_node.help.param_string,
- func = function(name, param)
- local help = format_help(cmd_repo.near_node.cmd)
-
- if param:find(" ") then
- return false, cmd_repo.param.excess .. "\n\n" .. help
- end
-
- local radius = cmd_repo.near_node.oparams.radius
- 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 radius, msg = check_radius(radius, name)
- if msg then
- core.chat_send_player(name, msg)
- end
-
- local ppos = core.get_player_by_name(name):get_pos()
-
- local node_names = {}
- for _, npos in ipairs(pos_list(ppos, radius)) do
- local node = core.get_node_or_nil(npos)
- if node and not node_names[node.name] then
- node_names[node.name] = true
- end
- end
-
- local found_nodes = {}
- for k, _ in pairs(node_names) do
- table.insert(found_nodes, k)
- end
-
- local msg
- local node_count = #found_nodes
- if node_count > 0 then
- msg = S("Nearby nodes: @1", node_count) .. "\n " .. table.concat(found_nodes, ", ")
- else
- msg = S("No nearby nodes found.")
- end
-
- return true, msg
- end,
-})
-
-
---- Unsafe Commands.
---
--- Enabled with [cleaner.unsafe](settings.html#cleaner.unsafe) setting.
---
--- @section unsafe
-
-
-if cleaner.unsafe then
- --- Registers an ore to be removed.
- --
- -- @chatcmd remove_ores
- -- @param ore Ore technical name.
- -- @priv server
- -- @note This action is reverted after server restart. To make changes permanent,
- -- use the [cleaner.json](config.html#cleaner.json) config.
- -- @usage
- -- # remove all registered ores that add default:stone_with_iron to world
- -- /remove_ores default:stone_with_iron
- core.register_chatcommand(cmd_repo.ore.cmd, {
- privs = {server=true},
- description = S("Remove an ore from game.") .. "\n\n"
- .. format_params(cmd_repo.ore.cmd),
- params = cmd_repo.ore.help.param_string,
- 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)
- 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
-
---- @section end
-
-
---- Manages settings for wielded [cleaner tool](tools.html).
---
--- Required Privileges:
---
--- - server
---
--- @chatcmd ctool
--- @param action Action to execute. Can be "status", "setmode", or "setnode".
--- @param value Mode or node to be set for tool (not required for "status" action).
--- @usage
--- # while cleaner:pencil is wielded, configure to place default:dirt node when used
--- /ctool setmode write
--- /ctool setnode default:dirt
-core.register_chatcommand(cmd_repo.tool.cmd, {
- privs = {server=true},
- description = S("Manage settings for wielded cleaner tool.") .. "\n\n"
- .. format_params(cmd_repo.tool.cmd),
- params = cmd_repo.tool.help.param_string,
- func = function(name, param)
- local action, value = param
- local idx = param:find(" ")
- if idx then
- param = string.split(param, " ")
- action = param[1]
- value = param[2]
- end
-
- local help = format_help(cmd_repo.tool.cmd)
-
- local player = core.get_player_by_name(name)
- local stack = player:get_wielded_item()
- local iname = aux.tool:format_name(stack)
- local imeta = stack:get_meta()
-
- if iname ~= "cleaner:pencil" then
- return false, S("Unrecognized wielded item: @1", iname) .. "\n\n" .. help
- end
-
- if action == "status" then
- core.chat_send_player(name, iname .. ": " .. S("mode") .. "=" .. imeta:get_string("mode")
- .. ", " .. S("node") .. "=" .. imeta:get_string("node"))
- return true
- end
-
- if not action or not value then
- return false, S("Missing parameter.") .. "\n\n" .. help
- end
-
- if action == "setmode" then
- stack = aux.tool:set_mode(stack, value, name)
- elseif action == "setnode" then
- stack = aux.tool:set_node(stack, value, name)
- else
- return false, S("Unrecognized action: @1", action) .. "\n\n" .. help
- end
-
- return player:set_wielded_item(stack)
- end,
-})
diff --git a/description.txt b/description.txt
new file mode 100644
index 0000000..f04ad33
--- /dev/null
+++ b/description.txt
@@ -0,0 +1 @@
+A very simple mod that deletes unknown blocks and removes unknown entities.
diff --git a/entities.lua b/entities.lua
deleted file mode 100644
index 7b9da53..0000000
--- a/entities.lua
+++ /dev/null
@@ -1,59 +0,0 @@
-
-local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-
--- populate entities list from file in world path
-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 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
-
-local e_path_old = core.get_worldpath() .. "/clean_entities.txt"
-e_file = io.open(e_path_old, "r")
-
-if e_file then
- cleaner.log("action", "found deprecated clean_entities.txt, converting to json")
-
- local data_in = string.split(e_file:read("*a"), "\n")
- for _, e in ipairs(data_in) do
- e = e:trim()
- if e ~= "" and e:sub(1, 1) ~= "#" then
- table.insert(entities_data.remove, e)
- end
- end
-
- e_file:close()
- os.rename(e_path_old, e_path_old .. ".bak") -- don't read deprecated file again
-end
-
--- END: backward compat
-
-
-entities_data.remove = aux.clean_duplicates(entities_data.remove)
-
--- update json file with any changes
-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)
diff --git a/init.lua b/init.lua
index 71d9ef2..bbdbca2 100644
--- a/init.lua
+++ b/init.lua
@@ -1,48 +1,43 @@
+-- clean by PilzAdam
+-- LICENSE: WTFPL
-cleaner = {}
-cleaner.modname = core.get_current_modname()
-cleaner.modpath = core.get_modpath(cleaner.modname)
+local old_nodes = {}
+local old_entities = {}
-local cleaner_debug = core.settings:get_bool("enable_debug_mods", false)
+-- Old/Missing nodes that should be replaced with something currently in game
+local replace_nodes = {}
-function cleaner.log(lvl, msg)
- if lvl == "debug" and not cleaner_debug then return end
- if lvl and not msg then
- msg = lvl
- lvl = nil
- end
-
- msg = "[" .. cleaner.modname .. "] " .. msg
- if lvl == "debug" then
- msg = "[DEBUG] " .. msg
- lvl = nil
- end
-
- if not lvl then
- core.log(msg)
- else
- core.log(lvl, msg)
- end
+-- "Replaces" an old/non-existent node
+local function replace_node(old_node, new_node)
+ minetest.register_alias(old_node, new_node)
end
-local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
--- initialize world file
-aux.update_world_data()
-
-
-local scripts = {
- "settings",
- "api",
- "chat",
- "tools",
- "entities",
- "nodes",
- "items",
- "ores",
-}
-
-for _, script in ipairs(scripts) do
- dofile(cleaner.modpath .. "/" .. script .. ".lua")
+for _,node_name in ipairs(old_nodes) do
+ minetest.register_node(':'..node_name, {
+ groups = {old=1},
+ })
+end
+
+minetest.register_abm({
+ nodenames = {'group:old'},
+ interval = 1,
+ chance = 1,
+ action = function(pos, node)
+ minetest.remove_node(pos)
+ end,
+})
+
+for _,entity_name in ipairs(old_entities) do
+ minetest.register_entity(':'..entity_name, {
+ on_activate = function(self, staticdata)
+ self.object:remove()
+ end,
+ })
+end
+
+-- Replace old nodes
+for _, node_group in pairs(replace_nodes) do
+ replace_node(node_group[1], node_group[2])
end
diff --git a/items.lua b/items.lua
deleted file mode 100644
index 02cde65..0000000
--- a/items.lua
+++ /dev/null
@@ -1,49 +0,0 @@
-
-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
-
-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 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
-
--- END: backward compat
-
-
-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.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 .. "\"")
-
- local retval, msg = cleaner.replace_item(i_old, i_new)
- if not retval then
- cleaner.log("warning", msg)
- end
- end
-end)
diff --git a/locale/cleaner.es.tr b/locale/cleaner.es.tr
deleted file mode 100644
index bbc0007..0000000
--- a/locale/cleaner.es.tr
+++ /dev/null
@@ -1,66 +0,0 @@
-# textdomain:cleaner
-
-# Translators: Jordan Irwin (AntumDeluge)
-
-
-# chat commands
-entity=entidad
-mode=modo
-node=nodo
-radius=radio
-old_item=objeto_antiguo
-new_item=objeto_nuevo
-old_node=nodo_antiguo
-new_node=nodo_nuevo
-ore=mineral
-action=acción
-value=valor
-Usage:=Uso:
-Params:=Parámetros:
-default: @1=por defecto: @1
-Search radius.=Radio de búsqueda.
-Entity technical name.=Nombre técnico de entidad.
-Node technical name.=Nombre técnico de nodo.
-Technical name of node to be replaced.=Nombre técnico del nodo reemplazado.
-Technical name of node to be used in place.=Nombre técnico del nodo de reemplazo.
-Technical name of item to be replaced.=Nombre técnico del objeto reemplazado.
-Technical name of item to be used in place.=Nombre técnico del objeto de reemplazo.
-Ore technical name.=Nombre técnico de mineral.
-Action to execute. Can be one of "@1", "@2", or "@3".=La acción para ejecutar. Puede ser "@1", "@2", o "@3".
-Mode or node to be set for tool (not required for "@1" action).=Modo o nodo para configurar a la herramienta (no se requiere para la acción de "@1").
-Remove an entity from game.=Eliminar una entidad del juego.
-Remove a node from game.=Eliminar un nodo del juego.
-Replace an item in game.=Sustituir un objecto del juego.
-Replace a node in game.=Sustituir un nodo del juego.
-Find names of unknown nodes.=Descubrir los nombres de nodos desconocidos.
-Find names of nearby nodes.=Descubrir los nombres de nodos cercanos.
-Remove an ore from game.=Eliminar un mineral del juego.
-Missing parameter.=Parámetro extraviado.
-Too many parameters.=Demasiados parámetros.
-Radius must be a number.=El radio debe ser un número.
-Cannot use unknown item "@1" as replacement.=El objeto "@1" es desonocido, no se puede utilizar como sustitución.
-Cannot use unknown node "@1" as replacement.=El nodo "@1" es desonocido, no se puede utilizar como sustitución.
-Replaced @1 nodes.=Nodos sustituidos: @1
-Removed @1 nodes.=Se eliminaron @1 nodos.
-Removed @1 entities.=Se eliminaron @1 entidades.
-Found unknown nodes: @1=Se encontraron @1 nodos desconocidos.
-No unknown nodes found.=No se encontraron nodos desconocidos.
-Nearby nodes: @1=Nodos cercanos: @1
-No nearby nodes found.=No se encontraron nodos cercanos.
-Ore "@1" not found, not unregistering.=No se encontró el mineral "@1", se mantiene registrado.
-Unregistered @1 ores (this will be undone after server restart).=Se anuló @1 minerales del registro.
-Success!=¡Éxito!
-Manage settings for wielded cleaner tool.=Administrar a los ajustes de la herramienta cleaner empuñada.
-Unrecognized wielded item: @1=Objeto empuñado desconocido: @1
-Unrecognized action: @1=Acción desconocido: @1
-You do not have permission to set radius that high. Reduced to @1.=No tienes permiso para poner al radio tan alto. Se reduce a @1.
-Radius is too high. Reduced to @1.=El radio es demasiado alto. Se reduce a @1.
-
-# tools:
-@1: mode set to: @2=@1: modo configurado para: @2
-@1: node set to: @2=@1: nodo configurado para: @2
-Modes for tool "@1" not available.=Modos para herramienta "@1" no disponibles.
-You do not have permission to use this item. Missing privs: @1=No tienes permiso para usar este objeto. Privs que faltan: @1
-Unknown mode: @1=Modo desconocido: @1
-Can't place node there.=No se puede poner nodo allí.
-Cannot place unknown node: @1=No se puede poner nodo desconocido: @1
diff --git a/locale/template.txt b/locale/template.txt
deleted file mode 100644
index 5373fb7..0000000
--- a/locale/template.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-# textdomain:cleaner
-
-# Translators:
-
-
-# chat commands
-entity=
-mode=
-node=
-radius=
-old_item=
-new_item=
-old_node=
-new_node=
-ore=
-action=
-value=
-Usage:=
-Params:=
-default: @1=
-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.=
-Action to execute. Can be one of "@1", "@2", or "@3".=
-Mode or node to be set for tool (not required for "@1" action).=
-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.=
-Find names of nearby 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.=
-Nearby nodes: @1=
-No nearby nodes found.=
-Ore "@1" not found, not unregistering.=
-Unregistered @1 ores (this will be undone after server restart).=
-Success!=
-Manage settings for wielded cleaner tool.=
-Unrecognized wielded item: @1=
-Unrecognized action: @1=
-You do not have permission to set radius that high. Reduced to @1.=
-Radius is too high. Reduced to @1.=
-
-# tools:
-@1: mode set to: @2=
-Modes for tool "@1" not available.=
-@1: node set to: @2=
-You do not have permission to use this item. Missing privs: @1=
-Can't place node there.=
-Unknown mode: @1=
-Cannot place unknown node: @1=
diff --git a/misc_functions.lua b/misc_functions.lua
deleted file mode 100644
index 27c8654..0000000
--- a/misc_functions.lua
+++ /dev/null
@@ -1,258 +0,0 @@
-
-local S = core.get_translator(cleaner.modname)
-
-
---- Cleans duplicate entries from indexed table.
---
--- @local
--- @function clean_duplicates
--- @tparam table t
--- @treturn table
-local function clean_duplicates(t)
- local tmp = {}
- for _, v in ipairs(t) do
- tmp[v] = true
- end
-
- t = {}
- for k in pairs(tmp) do
- table.insert(t, k)
- end
-
- 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
- local err
- wdata, err = core.parse_json(buffer:read("*a"), nil, true)
- buffer:close()
- if wdata == nil then
- cleaner.log("warning", "reading world data file failed: " .. world_file)
- wdata = {}
- end
- 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
-
-local tool = {
- modes = {
- ["cleaner:pencil"] = {"erase", "write", "swap"},
- },
-
- format_name = function(self, stack)
- local iname = stack:get_name()
- if iname == "cleaner:pencil_1" then
- iname = "cleaner:pencil"
- end
-
- return iname
- end,
-
- set_mode = function(self, stack, mode, pname)
- local iname = self:format_name(stack)
-
- if not self.modes[iname] then
- if pname then
- core.chat_send_player(pname, iname .. ": " .. S("unknown mode: @1", mode))
- end
- cleaner.log("warning", iname .. ": unknown mode: " .. mode)
- return stack
- end
-
- local imeta = stack:get_meta()
- imeta:set_string("mode", mode)
-
- if pname then
- core.chat_send_player(pname, S("@1: mode set to: @2", iname, imeta:get_string("mode")))
- end
-
- local new_stack
- if mode == "erase" then
- new_stack = ItemStack("cleaner:pencil_1")
- else
- new_stack = ItemStack("cleaner:pencil")
- end
-
- local new_meta = new_stack:get_meta()
- new_meta:from_table(imeta:to_table())
-
- return new_stack
- end,
-
- next_mode = function(self, stack, pname)
- local iname = self:format_name(stack)
- local modes = self.modes[iname]
-
- if not modes then
- return false, stack, S('Modes for tool "@1" not available.', stack:get_name())
- end
-
- local imeta = stack:get_meta()
- local current_mode = imeta:get_string("mode")
- if not current_mode or current_mode:trim() == "" then
- return true, self:set_mode(stack, modes[1], pname)
- end
-
- local idx = 1
- for _, m in ipairs(modes) do
- if current_mode == m then
- break
- end
- idx = idx + 1
- end
-
- return true, self:set_mode(stack, modes[idx+1] or modes[1], pname)
- end,
-
- set_node = function(self, stack, node, pname)
- local imeta = stack:get_meta()
- imeta:set_string("node", node)
-
- if pname then
- core.chat_send_player(pname, S("@1: node set to: @2", stack:get_name(), imeta:get_string("node")))
- end
-
- return stack
- end,
-}
-
-local use_sounds = core.global_exists("sounds")
-local sound_handle
-
-tool.on_use = function(stack, user, pointed_thing)
- if not user:is_player() then return end
-
- local pname = user:get_player_name()
- if not core.get_player_privs(pname).server then
- core.chat_send_player(pname, S("You do not have permission to use this item. Missing privs: @1", "server"))
- return stack
- end
-
- if sound_handle then
- core.sound_stop(sound_handle)
- sound_handle = nil
- end
-
- if pointed_thing.type == "node" then
- local npos = core.get_pointed_thing_position(pointed_thing)
- local imeta = stack:get_meta()
- local mode = imeta:get_string("mode")
- local new_node_name = imeta:get_string("node")
-
- if mode == "erase" then
- core.remove_node(npos)
- if use_sounds then
- local sound_handle = sounds.pencil_erase({object=user})
- end
- return stack
- elseif core.registered_nodes[new_node_name] then
- if mode == "swap" then
- core.swap_node(npos, {name=new_node_name})
- if use_sounds then
- local sound_handle = sounds.pencil_write({object=user})
- end
- elseif mode == "write" then
- local node_above = core.get_node_or_nil(pointed_thing.above)
- if not node_above or node_above.name == "air" then
- core.set_node(pointed_thing.above, {name=new_node_name})
- if use_sounds then
- local sound_handle = sounds.pencil_write({object=user})
- end
- else
- core.chat_send_player(pname, S("Can't place node there."))
- end
- else
- core.chat_send_player(pname, S("Unknown mode: @1", mode))
- end
-
- return stack
- end
-
- core.chat_send_player(pname, S("Cannot place unknown node: @1", new_node_name))
- return stack
- end
-end
-
-tool.on_secondary_use = function(stack, user, pointed_thing)
- if not user:is_player() then return end
-
- local pname = user:get_player_name()
- if not core.get_player_privs(pname).server then
- core.chat_send_player(pname, S("You do not have permission to use this item. Missing privs: @1", "server"))
- return stack
- end
-
- local success, stack, msg = tool.next_mode(tool, stack, pname)
- if not success then
- core.chat_send_player(pname, msg)
- end
-
- return stack
-end
-
-tool.on_place = function(stack, placer, pointed_thing)
- if not placer:is_player() then return end
-
- local pname = placer:get_player_name()
- if not core.get_player_privs(pname).server then
- core.chat_send_player(pname, S("You do not have permission to use this item. Missing privs: @1", "server"))
- return stack
- end
-
- if pointed_thing.type == "node" then
- local node = core.get_node_or_nil(core.get_pointed_thing_position(pointed_thing))
- if node then
- stack = tool:set_node(stack, node.name, pname)
- end
- end
-
- return stack
-end
-
-
-return {
- clean_duplicates = clean_duplicates,
- get_world_data = get_world_data,
- update_world_data = update_world_data,
- tool = tool,
-}
diff --git a/mod.conf b/mod.conf
index 03b84d4..a2e790c 100644
--- a/mod.conf
+++ b/mod.conf
@@ -1,7 +1,4 @@
-name = cleaner
-description = A mod that can be used to remove/replace unknown entities, nodes, & items.
-version = 2025-01-18
-license = MIT
-author = PilzAdam, Jordan Irwin (AntumDeluge)
-min_minetest_version = 5.0
-optional_depends = sounds
+name = clean
+author = PilzAdam
+license = WTFPL
+version = 0.1
diff --git a/nodes.lua b/nodes.lua
deleted file mode 100644
index f3878ab..0000000
--- a/nodes.lua
+++ /dev/null
@@ -1,97 +0,0 @@
-
-local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-
--- populate nodes list from file in world path
-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
- 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
-
-local n_path_old = core.get_worldpath() .. "/clean_nodes.txt"
-n_file = io.open(n_path_old, "r")
-
-if n_file then
- cleaner.log("action", "found deprecated clean_nodes.txt, converting to json")
-
- local data_in = string.split(n_file:read("*a"), "\n")
- for _, e in ipairs(data_in) do
- e = e:trim()
- if e ~= "" and e:sub(1, 1) ~= "#" then
- table.insert(nodes_data.remove, e)
- end
- end
-
- n_file:close()
- os.rename(n_path_old, n_path_old .. ".old") -- don't read deprecated file again
-end
-
--- END: backward compat
-
-
-nodes_data.remove = aux.clean_duplicates(nodes_data.remove)
-
--- update json file with any changes
-aux.update_world_data("nodes", nodes_data)
-
-core.register_lbm({
- name = "cleaner:remove_nodes",
- nodenames = {"group:to_remove"},
- run_at_every_load = true,
- action = function(pos, node)
- core.remove_node(pos)
- end,
-})
-
-core.register_lbm({
- name = "cleaner:replace_nodes",
- nodenames = {"group:to_replace"},
- run_at_every_load = true,
- action = function(pos, node)
- local new_node_name = cleaner.get_replace_nodes()[node.name]
- if core.registered_nodes[new_node_name] then
- core.swap_node(pos, {name=new_node_name})
- else
- cleaner.log("error", "cannot replace with unregistered node \"" .. tostring(new_node_name) .. "\"")
- 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)
diff --git a/ores.lua b/ores.lua
deleted file mode 100644
index 517f60a..0000000
--- a/ores.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-
-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)
diff --git a/screenshot.png b/screenshot.png
deleted file mode 100644
index 639655d..0000000
Binary files a/screenshot.png and /dev/null differ
diff --git a/set_version.py b/set_version.py
deleted file mode 100755
index 8c40217..0000000
--- a/set_version.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-
-import sys, os, codecs
-
-
-f_script = os.path.realpath(__file__)
-d_root = os.path.dirname(f_script)
-
-os.chdir(d_root)
-
-args = sys.argv[1:]
-if len(args) < 1:
- print("ERROR: must supply version as parameter")
- sys.exit(1)
-
-new_version = args[0]
-
-to_update = {
- "mod.conf": "version =",
- "changelog.txt": "next",
- os.path.normpath(".ldoc/config.ld"): "local version =",
-}
-
-for f in to_update:
- f_path = os.path.join(d_root, f)
- if not os.path.isfile(f_path):
- print("WARNING: {} not found, skipping ...".format(f))
- continue
-
- print("\nsetting version to {} in {}".format(new_version, f_path))
-
- buffer = codecs.open(f_path, "r", "utf-8")
- if not buffer:
- print("WARNING: could not open {} for reading, skipping ...".format(f))
- continue
-
- read_in = buffer.read()
- buffer.close()
-
- read_in = read_in.replace("\r\n", "\n").replace("\r", "\n")
- replacement = to_update[f]
- new_lines = []
-
- version_set = False
- for li in read_in.split("\n"):
- if not version_set:
- if "=" in replacement and li.startswith(replacement):
- key = li.split(" = ")[0]
- li = "{} = {}".format(key, new_version)
- version_set = True
- elif li == replacement:
- li = "v{}".format(new_version)
- version_set = True
-
- new_lines.append(li)
-
- write_out = "\n".join(new_lines)
- if write_out == read_in:
- print("no changes for {}, skipping ...".format(f))
- continue
-
- buffer = codecs.open(f_path, "w", "utf-8")
- if not buffer:
- print("WARNING: could not open {} for writing, skipping ...".format(f))
- continue
-
- buffer.write("\n".join(new_lines))
- buffer.close()
-
- print("done")
diff --git a/settings.lua b/settings.lua
deleted file mode 100644
index 16c2f42..0000000
--- a/settings.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-
---- Cleaner Settings
---
--- @topic settings
-
-
---- Enables unsafe methods & chat commands.
---
--- - `cleaner.remove_ore`
--- - `/remove_ores`
---
--- @setting cleaner.unsafe
--- @settype bool
--- @default false
-cleaner.unsafe = core.settings:get_bool("cleaner.unsafe", false)
diff --git a/settingtypes.txt b/settingtypes.txt
deleted file mode 100644
index b5debc7..0000000
--- a/settingtypes.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# Enables unsafe methods & chat commands.
-#
-# - cleaner.remove_ore
-# - /remove_ores
-cleaner.unsafe (Enable unsafe methods) bool false
diff --git a/textures/cleaner_pencil.png b/textures/cleaner_pencil.png
deleted file mode 100644
index 3582687..0000000
Binary files a/textures/cleaner_pencil.png and /dev/null differ
diff --git a/tools.lua b/tools.lua
deleted file mode 100644
index cc1c405..0000000
--- a/tools.lua
+++ /dev/null
@@ -1,44 +0,0 @@
-
---- Cleaner Tools
---
--- @topic tools
-
-
-local S = core.get_translator(cleaner.modname)
-
-
-local aux = dofile(cleaner.modpath .. "/misc_functions.lua")
-
---- Master Pencil
---
--- @tool cleaner:pencil
--- @img cleaner_pencil.png
--- @priv server
--- @usage
--- place (right-click):
--- - when not pointing at a node, changes modes
--- - when pointing at a node, sets node to be used
---
--- use (left-click):
--- - executes action for current mode:
--- - erase: erases pointed node
--- - write: adds node
--- - swap: replaces pointed node
-core.register_tool(cleaner.modname .. ":pencil", {
- description = S("Master Pencil"),
- inventory_image = "cleaner_pencil.png",
- liquids_pointable = true,
- on_use = aux.tool.on_use,
- on_secondary_use = aux.tool.on_secondary_use,
- on_place = aux.tool.on_place,
-})
-
-core.register_tool(cleaner.modname .. ":pencil_1", {
- description = S("Master Pencil"),
- inventory_image = "cleaner_pencil.png^[transformFXFY",
- liquids_pointable = true,
- groups = {not_in_creative_inventory=1},
- on_use = aux.tool.on_use,
- on_secondary_use = aux.tool.on_secondary_use,
- on_place = aux.tool.on_place,
-})