Add mods: technic, moreores, paintings, Nyancat (Pbj_pup). Small fix: sandwiches
21
mods/.cleaner/LICENSE.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
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.
|
86
mods/.cleaner/README.md
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
|
||||||
|
[Luanti]: https://luanti.org/
|
||||||
|
[f.pilzadam]: https://forum.luanti.org/viewtopic.php?t=2777
|
||||||
|
[ContentDB]: https://content.luanti.org/packages/AntumDeluge/cleaner/
|
14
mods/.cleaner/TODO.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
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
|
194
mods/.cleaner/api.lua
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
|
||||||
|
--- 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
|
63
mods/.cleaner/changelog.txt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
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 <world_path>/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 (<world_path>/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"
|
660
mods/.cleaner/chat.lua
Normal file
|
@ -0,0 +1,660 @@
|
||||||
|
|
||||||
|
--- 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).
|
||||||
|
--
|
||||||
|
-- <h3>Required Privileges:</h3>
|
||||||
|
--
|
||||||
|
-- - 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,
|
||||||
|
})
|
59
mods/.cleaner/entities.lua
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
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)
|
48
mods/.cleaner/init.lua
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
cleaner = {}
|
||||||
|
cleaner.modname = core.get_current_modname()
|
||||||
|
cleaner.modpath = core.get_modpath(cleaner.modname)
|
||||||
|
|
||||||
|
local cleaner_debug = core.settings:get_bool("enable_debug_mods", false)
|
||||||
|
|
||||||
|
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
|
||||||
|
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")
|
||||||
|
end
|
49
mods/.cleaner/items.lua
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
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)
|
66
mods/.cleaner/locale/cleaner.es.tr
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# 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
|
66
mods/.cleaner/locale/template.txt
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# 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=
|
258
mods/.cleaner/misc_functions.lua
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
9
mods/.cleaner/mod.conf
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
name = cleaner
|
||||||
|
description = A mod that can be used to remove/replace unknown entities, nodes, & items.
|
||||||
|
version = 2025-01-18
|
||||||
|
license = MIT
|
||||||
|
author = AntumDeluge
|
||||||
|
min_minetest_version = 5.0
|
||||||
|
optional_depends = sounds
|
||||||
|
release = 29398
|
||||||
|
title = Cleaner
|
97
mods/.cleaner/nodes.lua
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
|
||||||
|
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)
|
17
mods/.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)
|
BIN
mods/.cleaner/screenshot.png
Normal file
After Width: | Height: | Size: 183 KiB |
15
mods/.cleaner/settings.lua
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
--- 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)
|
6
mods/.cleaner/settingtypes.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
# Enables unsafe methods & chat commands.
|
||||||
|
#
|
||||||
|
# - cleaner.remove_ore
|
||||||
|
# - /remove_ores
|
||||||
|
cleaner.unsafe (Enable unsafe methods) bool false
|
BIN
mods/.cleaner/textures/cleaner_pencil.png
Normal file
After Width: | Height: | Size: 255 B |
44
mods/.cleaner/tools.lua
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
--- 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,
|
||||||
|
})
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 624 B After Width: | Height: | Size: 624 B |
|
@ -1,127 +0,0 @@
|
||||||
-- mod check and sound settings
|
|
||||||
|
|
||||||
local def = core.get_modpath("default")
|
|
||||||
local mcl = core.get_modpath("mcl_core")
|
|
||||||
local snd = mcl and mcl_sounds.node_sound_glass_defaults() or default.node_sound_glass_defaults()
|
|
||||||
|
|
||||||
-- Nyan Cat node
|
|
||||||
|
|
||||||
core.register_node(":nyancat:nyancat", {
|
|
||||||
description = "Nyan Cat",
|
|
||||||
tiles = {
|
|
||||||
"nyancat_side.png",
|
|
||||||
"nyancat_side.png",
|
|
||||||
"nyancat_side.png",
|
|
||||||
"nyancat_side.png",
|
|
||||||
"nyancat_back.png",
|
|
||||||
"nyancat_front.png",
|
|
||||||
},
|
|
||||||
paramtype = "light",
|
|
||||||
light_source = 15,
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
groups = { cracky = 2, handy = 1 },
|
|
||||||
is_ground_content = false,
|
|
||||||
sounds = snd,
|
|
||||||
_mcl_hardness = 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Rainbow node
|
|
||||||
|
|
||||||
core.register_node(":nyancat:nyancat_rainbow", {
|
|
||||||
description = "Rainbow",
|
|
||||||
tiles = {
|
|
||||||
"nyancat_rainbow.png^[transformR90",
|
|
||||||
"nyancat_rainbow.png^[transformR90",
|
|
||||||
"nyancat_rainbow.png",
|
|
||||||
},
|
|
||||||
paramtype = "light",
|
|
||||||
light_source = 15,
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
groups = { cracky = 2, handy = 1 },
|
|
||||||
is_ground_content = false,
|
|
||||||
sounds = snd,
|
|
||||||
_mcl_hardness = 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Fuels
|
|
||||||
|
|
||||||
core.register_craft({
|
|
||||||
type = "fuel",
|
|
||||||
recipe = "nyancat:nyancat",
|
|
||||||
burntime = 10,
|
|
||||||
})
|
|
||||||
|
|
||||||
core.register_craft({
|
|
||||||
type = "fuel",
|
|
||||||
recipe = "nyancat:nyancat_rainbow",
|
|
||||||
burntime = 10,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- helper function to place Nyan/Pup/Moo with rainbow tail
|
|
||||||
|
|
||||||
local types = { "nyancat:nyancat" }
|
|
||||||
|
|
||||||
local function place(pos, facedir, length)
|
|
||||||
if facedir > 3 then
|
|
||||||
facedir = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local tailvec = core.facedir_to_dir(facedir)
|
|
||||||
local p = { x = pos.x, y = pos.y, z = pos.z }
|
|
||||||
local num = math.random(#types)
|
|
||||||
|
|
||||||
core.swap_node(p, { name = types[num], param2 = facedir })
|
|
||||||
|
|
||||||
for i = 1, length do
|
|
||||||
p.x = p.x + tailvec.x
|
|
||||||
p.z = p.z + tailvec.z
|
|
||||||
|
|
||||||
core.swap_node(p, { name = "nyancat:nyancat_rainbow", param2 = facedir })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Do we generate PB&J Pup and Nyan Cat's in world?
|
|
||||||
|
|
||||||
local function generate(minp, maxp, seed)
|
|
||||||
local height_min = -31000
|
|
||||||
local height_max = -32
|
|
||||||
local chance = 1000
|
|
||||||
|
|
||||||
if maxp.y < height_min or minp.y > height_max then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local y_min = math.max(minp.y, height_min)
|
|
||||||
local y_max = math.min(maxp.y, height_max)
|
|
||||||
local volume = (maxp.x - minp.x + 1) * (y_max - y_min + 1) * (maxp.z - minp.z + 1)
|
|
||||||
local pr = PseudoRandom(seed + 9324342)
|
|
||||||
local max_num_nyancats = math.floor(volume / (16 * 16 * 16))
|
|
||||||
|
|
||||||
for i = 1, max_num_nyancats do
|
|
||||||
if pr:next(0, 1000) == 0 then
|
|
||||||
local x0 = pr:next(minp.x, maxp.x)
|
|
||||||
local y0 = pr:next(minp.y, maxp.y)
|
|
||||||
local z0 = pr:next(minp.z, maxp.z)
|
|
||||||
local p0 = {x = x0, y = y0, z = z0}
|
|
||||||
nyancat.place(p0, pr:next(0, 3), pr:next(3, 15))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
core.register_on_generated(generate)
|
|
||||||
|
|
||||||
if def then
|
|
||||||
default.generate_nyancats = generate
|
|
||||||
end --Legacy
|
|
||||||
|
|
||||||
-- Legacy
|
|
||||||
|
|
||||||
core.register_alias("default:nyancat", "nyancat:nyancat")
|
|
||||||
core.register_alias("default:nyancat_rainbow", "nyancat:nyancat_rainbow")
|
|
||||||
|
|
||||||
if def then
|
|
||||||
default.make_nyancat = place
|
|
||||||
end
|
|
||||||
|
|
||||||
print("[MOD] PB&J Pup loaded")
|
|
|
@ -4,15 +4,22 @@
|
||||||
local S = airutils.S
|
local S = airutils.S
|
||||||
local module_name = "airutils"
|
local module_name = "airutils"
|
||||||
|
|
||||||
|
--[[
|
||||||
if core.get_modpath("technic") then
|
if core.get_modpath("technic") then
|
||||||
if technic then
|
if technic then
|
||||||
technic.register_extractor_recipe({input = {"farming:wheat 33"}, output = "biofuel:biofuel 1"})
|
local extractor_recipes = {
|
||||||
technic.register_extractor_recipe({input = {"farming:corn 33"}, output = "biofuel:biofuel 1"})
|
{ "farming:wheat 33", "biofuel:biofuel" },
|
||||||
technic.register_extractor_recipe({input = {"farming:potato 33"}, output = "biofuel:biofuel 1"})
|
{ "farming:corn 33", "biofuel:biofuel" },
|
||||||
technic.register_extractor_recipe({input = {"default:papyrus 99"}, output = "biofuel:biofuel 1"})
|
{ "farming:potato 33", "biofuel:biofuel" },
|
||||||
end
|
{ "default:papyrus 99", "biofuel:biofuel" },
|
||||||
end
|
}
|
||||||
|
|
||||||
|
for _, data in ipairs(extractor_recipes) do
|
||||||
|
technic.register_extractor_recipe({ input = { data[1] }, output = data[2] })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
|
||||||
if core.get_modpath("basic_machines") then
|
if core.get_modpath("basic_machines") then
|
||||||
if basic_machines then
|
if basic_machines then
|
||||||
|
@ -44,7 +51,6 @@ if core.get_modpath("mcl_core") then
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- biofuel
|
-- biofuel
|
||||||
local new_gallon_id = "airutils:biofuel"
|
local new_gallon_id = "airutils:biofuel"
|
||||||
core.register_craftitem(new_gallon_id, {
|
core.register_craftitem(new_gallon_id, {
|
||||||
|
@ -65,17 +71,33 @@ local ferment = {
|
||||||
{ "farming:wheat", new_gallon_id },
|
{ "farming:wheat", new_gallon_id },
|
||||||
{ "farming:corn", new_gallon_id },
|
{ "farming:corn", new_gallon_id },
|
||||||
{ "farming:baked_potato", new_gallon_id },
|
{ "farming:baked_potato", new_gallon_id },
|
||||||
{"farming:potato", new_gallon_id}
|
{ "farming:potato", new_gallon_id },
|
||||||
}
|
}
|
||||||
|
|
||||||
local ferment_groups = {'flora', 'leaves', 'flower', 'sapling', 'tree', 'wood', 'stick', 'plant', 'seed',
|
local ferment_groups = {
|
||||||
'leafdecay', 'leafdecay_drop', 'mushroom', 'vines' }
|
"flora",
|
||||||
|
"leaves",
|
||||||
|
"flower",
|
||||||
|
"sapling",
|
||||||
|
"tree",
|
||||||
|
"wood",
|
||||||
|
"stick",
|
||||||
|
"plant",
|
||||||
|
"seed",
|
||||||
|
"leafdecay",
|
||||||
|
"leafdecay_drop",
|
||||||
|
"mushroom",
|
||||||
|
"vines",
|
||||||
|
}
|
||||||
|
|
||||||
-- distiller
|
-- distiller
|
||||||
local biofueldistiller_formspec = "size[8,9]"
|
local biofueldistiller_formspec = "size[8,9]"
|
||||||
.. "list[current_name;src;2,1;1,1;]" .. airutils.get_itemslot_bg(2, 1, 1, 1)
|
.. "list[current_name;src;2,1;1,1;]"
|
||||||
.. "list[current_name;dst;5,1;1,1;]" .. airutils.get_itemslot_bg(5, 1, 1, 1)
|
.. airutils.get_itemslot_bg(2, 1, 1, 1)
|
||||||
.. "list[current_player;main;0,5;8,4;]" .. airutils.get_itemslot_bg(0, 5, 8, 4)
|
.. "list[current_name;dst;5,1;1,1;]"
|
||||||
|
.. airutils.get_itemslot_bg(5, 1, 1, 1)
|
||||||
|
.. "list[current_player;main;0,5;8,4;]"
|
||||||
|
.. airutils.get_itemslot_bg(0, 5, 8, 4)
|
||||||
.. "listring[current_name;dst]"
|
.. "listring[current_name;dst]"
|
||||||
.. "listring[current_player;main]"
|
.. "listring[current_player;main]"
|
||||||
.. "listring[current_name;src]"
|
.. "listring[current_name;src]"
|
||||||
|
@ -90,14 +112,15 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
groups = {
|
groups = {
|
||||||
choppy = 2, oddly_breakable_by_hand = 1, flammable = 2
|
choppy = 2,
|
||||||
|
oddly_breakable_by_hand = 1,
|
||||||
|
flammable = 2,
|
||||||
},
|
},
|
||||||
legacy_facedir_simple = true,
|
legacy_facedir_simple = true,
|
||||||
|
|
||||||
on_place = core.rotate_node,
|
on_place = core.rotate_node,
|
||||||
|
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
|
|
||||||
local meta = core.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
|
|
||||||
meta:set_string("formspec", biofueldistiller_formspec)
|
meta:set_string("formspec", biofueldistiller_formspec)
|
||||||
|
@ -111,12 +134,10 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
can_dig = function(pos, player)
|
can_dig = function(pos, player)
|
||||||
|
|
||||||
local meta = core.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
|
|
||||||
if not inv:is_empty("dst")
|
if not inv:is_empty("dst") or not inv:is_empty("src") then
|
||||||
or not inv:is_empty("src") then
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -124,7 +145,6 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
|
|
||||||
if core.is_protected(pos, player:get_player_name()) then
|
if core.is_protected(pos, player:get_player_name()) then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
@ -133,7 +153,6 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
|
||||||
if core.is_protected(pos, player:get_player_name()) then
|
if core.is_protected(pos, player:get_player_name()) then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
@ -146,7 +165,6 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
|
||||||
if core.is_protected(pos, player:get_player_name()) then
|
if core.is_protected(pos, player:get_player_name()) then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
@ -159,20 +177,20 @@ core.register_node( module_name .. ":biofuel_distiller", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_metadata_inventory_put = function(pos)
|
on_metadata_inventory_put = function(pos)
|
||||||
|
|
||||||
local timer = core.get_node_timer(pos)
|
local timer = core.get_node_timer(pos)
|
||||||
|
|
||||||
timer:start(5)
|
timer:start(5)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_timer = function(pos)
|
on_timer = function(pos)
|
||||||
|
local meta = core.get_meta(pos)
|
||||||
local meta = core.get_meta(pos) ; if not meta then return end
|
if not meta then
|
||||||
|
return
|
||||||
|
end
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
|
|
||||||
-- is barrel empty?
|
-- is barrel empty?
|
||||||
if not inv or inv:is_empty("src") then
|
if not inv or inv:is_empty("src") then
|
||||||
|
|
||||||
meta:set_float("status", 0.0)
|
meta:set_float("status", 0.0)
|
||||||
meta:set_string("infotext", S("Fuel Distiller"))
|
meta:set_string("infotext", S("Fuel Distiller"))
|
||||||
|
|
||||||
|
|
13
mods/basic_materials/.github/workflows/luacheck.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
name: luacheck
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: apt
|
||||||
|
run: sudo apt-get install -y luarocks
|
||||||
|
- name: luacheck install
|
||||||
|
run: luarocks install --local luacheck
|
||||||
|
- name: luacheck run
|
||||||
|
run: $HOME/.luarocks/bin/luacheck ./
|
7
mods/basic_materials/.luacheckrc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
globals = {
|
||||||
|
"minetest", "basic_materials", "crafting",
|
||||||
|
}
|
||||||
|
|
||||||
|
read_globals = {
|
||||||
|
"default", "xcompat",
|
||||||
|
}
|
600
mods/basic_materials/LICENSE
Normal file
|
@ -0,0 +1,600 @@
|
||||||
|
License for code: LGPL 3.0
|
||||||
|
License for media and all other assets: CC-by-SA 4.0
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Attribution-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution-ShareAlike 4.0 International Public
|
||||||
|
License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-ShareAlike 4.0 International Public License ("Public
|
||||||
|
License"). To the extent this Public License may be interpreted as a
|
||||||
|
contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. License Elements means the license attributes listed in the name
|
||||||
|
of a Creative Commons Public License. The License Elements of this
|
||||||
|
Public License are Attribution and ShareAlike.
|
||||||
|
|
||||||
|
h. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
i. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
k. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
l. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
m. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material.
|
||||||
|
Every recipient of Adapted Material from You
|
||||||
|
automatically receives an offer from the Licensor to
|
||||||
|
exercise the Licensed Rights in the Adapted Material
|
||||||
|
under the conditions of the Adapter's License You apply.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
b. ShareAlike.
|
||||||
|
|
||||||
|
In addition to the conditions in Section 3(a), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply.
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a Creative Commons
|
||||||
|
license with the same License Elements, this version or
|
||||||
|
later, or a BY-SA Compatible License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition
|
||||||
|
in any reasonable manner based on the medium, means, and
|
||||||
|
context in which You Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms
|
||||||
|
or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, Adapted Material that restrict exercise of the
|
||||||
|
rights granted under the Adapter's License You apply.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material,
|
||||||
|
|
||||||
|
including for purposes of Section 3(b); and
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public
|
||||||
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
|
its public licenses to material it publishes and in those instances
|
||||||
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
|
material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
|
public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
23
mods/basic_materials/README.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Basic Materials mod
|
||||||
|
|
||||||
|
mod that adds basic material nodes and items
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
### Option 1: use content tab in minetest
|
||||||
|
|
||||||
|
* click the content tab
|
||||||
|
* search for basic materials
|
||||||
|
* click install on basic materials
|
||||||
|
|
||||||
|
### Option 2: download from [ContentDB](https://content.minetest.net/packages/VanessaE/basic_materials/)
|
||||||
|
|
||||||
|
* click the above link or search for basic materials on ContentDB
|
||||||
|
* select the download button on the basic materials page
|
||||||
|
* extract the zip downloaded from the previous step
|
||||||
|
* place in your mods folder
|
||||||
|
|
||||||
|
### Option 3: use git
|
||||||
|
|
||||||
|
* `git clone https://github.com/mt-mods/basic_materials.git`
|
||||||
|
* `cd basic_materials`
|
34
mods/basic_materials/aliases.lua
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
minetest.register_alias("homedecor:plastic_sheeting", "basic_materials:plastic_sheet")
|
||||||
|
minetest.register_alias("homedecor:plastic_strips", "basic_materials:plastic_strip")
|
||||||
|
minetest.register_alias("homedecor:empty_spool", "basic_materials:empty_spool")
|
||||||
|
minetest.register_alias("homedecor:oil_extract", "basic_materials:oil_extract")
|
||||||
|
minetest.register_alias("homedecor:paraffin", "basic_materials:paraffin")
|
||||||
|
minetest.register_alias("homedecor:plastic_base", "basic_materials:paraffin")
|
||||||
|
minetest.register_alias("homedecor:terracotta_base", "basic_materials:terracotta_base")
|
||||||
|
minetest.register_alias("gloopblocks:wet_cement", "basic_materials:wet_cement")
|
||||||
|
minetest.register_alias("gloopblocks:cement", "basic_materials:cement_block")
|
||||||
|
minetest.register_alias("technic:concrete", "basic_materials:concrete_block")
|
||||||
|
minetest.register_alias("homedecor:ic", "basic_materials:ic")
|
||||||
|
minetest.register_alias("homedecor:motor", "basic_materials:motor")
|
||||||
|
minetest.register_alias("technic:motor", "basic_materials:motor")
|
||||||
|
minetest.register_alias("homedecor:heating_element", "basic_materials:heating_element")
|
||||||
|
minetest.register_alias("homedecor:power_crystal", "basic_materials:energy_crystal_simple")
|
||||||
|
minetest.register_alias("homedecor:copper_wire", "basic_materials:copper_wire")
|
||||||
|
minetest.register_alias("technic:fine_copper_wire", "basic_materials:copper_wire")
|
||||||
|
minetest.register_alias("technic:fine_silver_wire", "basic_materials:silver_wire")
|
||||||
|
minetest.register_alias("technic:fine_gold_wire", "basic_materials:gold_wire")
|
||||||
|
minetest.register_alias("homedecor:steel_wire", "basic_materials:steel_wire")
|
||||||
|
minetest.register_alias("homedecor:brass_ingot", "basic_materials:brass_ingot")
|
||||||
|
minetest.register_alias("technic:brass_ingot", "basic_materials:brass_ingot")
|
||||||
|
minetest.register_alias("technic:brass_block", "basic_materials:brass_block")
|
||||||
|
minetest.register_alias("homedecor:copper_strip", "basic_materials:copper_strip")
|
||||||
|
minetest.register_alias("homedecor:steel_strip", "basic_materials:steel_strip")
|
||||||
|
minetest.register_alias("homedecor:chainlink_brass", "basic_materials:chainlink_brass")
|
||||||
|
minetest.register_alias("chains:chain", "basic_materials:chain_steel")
|
||||||
|
minetest.register_alias("chains:chain_brass", "basic_materials:chain_brass")
|
||||||
|
minetest.register_alias("pipeworks:gear", "basic_materials:gear_steel")
|
||||||
|
minetest.register_alias("technic:rebar", "basic_materials:steel_bar")
|
||||||
|
|
||||||
|
minetest.register_alias_force("mesecons_materials:silicon", "basic_materials:silicon")
|
||||||
|
minetest.register_alias_force("glooptest:chainlink", "basic_materials:chainlink_steel")
|
||||||
|
minetest.register_alias_force("homedecor:chainlink_steel", "basic_materials:chainlink_steel")
|
188
mods/basic_materials/craftitems.lua
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
local S = minetest.get_translator("basic_materials")
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:plastic_sheet", {
|
||||||
|
description = S("Plastic sheet"),
|
||||||
|
inventory_image = "basic_materials_plastic_sheet.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:plastic_strip", {
|
||||||
|
description = S("Plastic strips"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_plastic_strip.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:empty_spool", {
|
||||||
|
description = S("Empty wire spool"),
|
||||||
|
inventory_image = "basic_materials_empty_spool.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:oil_extract", {
|
||||||
|
description = S("Oil extract"),
|
||||||
|
inventory_image = "basic_materials_oil_extract.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:paraffin", {
|
||||||
|
description = S("Unprocessed paraffin"),
|
||||||
|
inventory_image = "basic_materials_paraffin.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:terracotta_base", {
|
||||||
|
description = S("Uncooked Terracotta Base"),
|
||||||
|
inventory_image = "basic_materials_terracotta_base.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:wet_cement", {
|
||||||
|
description = S("Wet Cement"),
|
||||||
|
inventory_image = "basic_materials_wet_cement.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:silicon", {
|
||||||
|
description = S("Silicon lump"),
|
||||||
|
inventory_image = "basic_materials_silicon.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:ic", {
|
||||||
|
description = S("Simple Integrated Circuit"),
|
||||||
|
inventory_image = "basic_materials_ic.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:motor", {
|
||||||
|
description = S("Simple Motor"),
|
||||||
|
inventory_image = "basic_materials_motor.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:heating_element", {
|
||||||
|
description = S("Heating element"),
|
||||||
|
inventory_image = "basic_materials_heating_element.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:energy_crystal_simple", {
|
||||||
|
description = S("Simple energy crystal"),
|
||||||
|
inventory_image = "basic_materials_energy_crystal.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:steel_wire", {
|
||||||
|
description = S("Spool of steel wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_steel_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:copper_wire", {
|
||||||
|
description = S("Spool of copper wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_copper_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:silver_wire", {
|
||||||
|
description = S("Spool of silver wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_silver_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:gold_wire", {
|
||||||
|
description = S("Spool of gold wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_gold_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:stainless_steel_wire", {
|
||||||
|
description = S("Spool of stainless steel wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_stainless_steel_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:aluminum_wire", {
|
||||||
|
description = S("Spool of aluminum wire"),
|
||||||
|
groups = { wire = 1 },
|
||||||
|
inventory_image = "basic_materials_aluminum_wire.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:steel_strip", {
|
||||||
|
description = S("Steel Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_steel_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:copper_strip", {
|
||||||
|
description = S("Copper Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_copper_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:lead_strip", {
|
||||||
|
description = S("Lead Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_lead_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:gold_strip", {
|
||||||
|
description = S("Gold Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_gold_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:stainless_steel_strip", {
|
||||||
|
description = S("Stainless Steel Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_stainless_steel_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:aluminum_strip", {
|
||||||
|
description = S("Aluminum Strip"),
|
||||||
|
groups = { strip = 1 },
|
||||||
|
inventory_image = "basic_materials_aluminum_strip.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:steel_bar", {
|
||||||
|
description = S("Steel Bar"),
|
||||||
|
inventory_image = "basic_materials_steel_bar.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:carbon_steel_bar", {
|
||||||
|
description = S("Carbon Steel Bar"),
|
||||||
|
inventory_image = "basic_materials_carbon_steel_bar.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:stainless_steel_bar", {
|
||||||
|
description = S("Stainless Steel Bar"),
|
||||||
|
inventory_image = "basic_materials_stainless_steel_bar.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:aluminum_bar", {
|
||||||
|
description = S("Aluminum Bar"),
|
||||||
|
inventory_image = "basic_materials_aluminum_bar.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:chainlink_brass", {
|
||||||
|
description = S("Chainlinks (brass)"),
|
||||||
|
groups = { chainlinks = 1 },
|
||||||
|
inventory_image = "basic_materials_chainlink_brass.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:chainlink_steel", {
|
||||||
|
description = S("Chainlinks (steel)"),
|
||||||
|
groups = { chainlinks = 1 },
|
||||||
|
inventory_image = "basic_materials_chainlink_steel.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:brass_ingot", {
|
||||||
|
description = S("Brass Ingot"),
|
||||||
|
inventory_image = "basic_materials_brass_ingot.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:gear_steel", {
|
||||||
|
description = S("Steel gear"),
|
||||||
|
inventory_image = "basic_materials_gear_steel.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("basic_materials:padlock", {
|
||||||
|
description = S("Padlock"),
|
||||||
|
inventory_image = "basic_materials_padlock.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
if minetest.get_modpath("hades_materials") then
|
||||||
|
minetest.register_alias_force("basic_materials:plastic_sheet", "hades_materials:plastic_sheeting")
|
||||||
|
minetest.register_alias_force("basic_materials:paraffin", "hades_materials:plastic_base")
|
||||||
|
minetest.register_alias_force("basic_materials:silicon", "hades_materials:silicon")
|
||||||
|
end
|
||||||
|
|
441
mods/basic_materials/crafts.lua
Normal file
|
@ -0,0 +1,441 @@
|
||||||
|
local materials = xcompat.materials
|
||||||
|
|
||||||
|
local have_hades_materials = minetest.get_modpath("hades_materials")
|
||||||
|
|
||||||
|
local function compress_craft(input)
|
||||||
|
local buffer = {}
|
||||||
|
for _, item in pairs(input) do
|
||||||
|
if type(item)=="table" then
|
||||||
|
for _, inneritem in pairs(item) do
|
||||||
|
buffer[inneritem] = (buffer[inneritem] or 0) + 1
|
||||||
|
end
|
||||||
|
elseif item ~= "" then
|
||||||
|
buffer[item] = (buffer[item] or 0) + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local output = {}
|
||||||
|
for item, count in pairs(buffer) do
|
||||||
|
output[#output + 1] = item .. " " .. count
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
local function register_craft(input)
|
||||||
|
if minetest.get_modpath("rp_crafting") then
|
||||||
|
local rp_craft = compress_craft(input.recipe)
|
||||||
|
if #rp_craft > crafting.MAX_INPUTS then
|
||||||
|
minetest.log("error", "[basic_materials] unable to register craft for " .. input.output)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
crafting.register_craft({
|
||||||
|
output = input.output,
|
||||||
|
items = rp_craft
|
||||||
|
})
|
||||||
|
else
|
||||||
|
minetest.register_craft(input)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Craft recipes
|
||||||
|
register_craft({
|
||||||
|
output = "basic_materials:chainlink_brass 12",
|
||||||
|
recipe = {
|
||||||
|
{"", "basic_materials:brass_ingot", "basic_materials:brass_ingot"},
|
||||||
|
{"basic_materials:brass_ingot", "", "basic_materials:brass_ingot"},
|
||||||
|
{"basic_materials:brass_ingot", "basic_materials:brass_ingot", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
output = "basic_materials:chain_steel 2",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:chainlink_steel"},
|
||||||
|
{"basic_materials:chainlink_steel"},
|
||||||
|
{"basic_materials:chainlink_steel"}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
output = "basic_materials:chain_brass 2",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:chainlink_brass"},
|
||||||
|
{"basic_materials:chainlink_brass"},
|
||||||
|
{"basic_materials:chainlink_brass"}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
type = "shapeless",
|
||||||
|
output = "basic_materials:brass_ingot 9",
|
||||||
|
recipe = {"basic_materials:brass_block"},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:brass_block",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot"},
|
||||||
|
{"basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot"},
|
||||||
|
{"basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:plastic_strip 9",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:empty_spool 3",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"},
|
||||||
|
{"", "basic_materials:plastic_sheet", ""},
|
||||||
|
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if have_hades_materials then
|
||||||
|
minetest.clear_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {"group:leaves", "group:leaves", "group:leaves", "group:leaves", "group:leaves", "group:leaves"}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "basic_materials:oil_extract 2",
|
||||||
|
recipe = {"group:leaves", "group:leaves", "group:leaves", "group:leaves", "group:leaves", "group:leaves"}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Cooking recipes
|
||||||
|
if not have_hades_materials then
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "basic_materials:plastic_sheet",
|
||||||
|
recipe = "basic_materials:paraffin",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "basic_materials:paraffin",
|
||||||
|
recipe = "basic_materials:oil_extract",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "basic_materials:cement_block",
|
||||||
|
recipe = "basic_materials:wet_cement",
|
||||||
|
cooktime = 8
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Fuel recipes
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "basic_materials:plastic_sheet",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "basic_materials:oil_extract",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "basic_materials:paraffin",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
output = "basic_materials:concrete_block 6",
|
||||||
|
recipe = {
|
||||||
|
{"group:sand", "basic_materials:wet_cement", materials.gravel},
|
||||||
|
{"basic_materials:steel_bar", "basic_materials:wet_cement", "basic_materials:steel_bar"},
|
||||||
|
{materials.gravel, "basic_materials:wet_cement", "group:sand"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:motor 2",
|
||||||
|
recipe = {
|
||||||
|
{materials.mese_crystal_fragment, "basic_materials:copper_wire", "basic_materials:plastic_sheet"},
|
||||||
|
{materials.copper_ingot, materials.steel_ingot, materials.steel_ingot},
|
||||||
|
{materials.mese_crystal_fragment, "basic_materials:copper_wire", "basic_materials:plastic_sheet"}
|
||||||
|
},
|
||||||
|
replacements = {
|
||||||
|
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||||
|
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:heating_element 2",
|
||||||
|
recipe = {
|
||||||
|
{materials.copper_ingot, materials.mese_crystal_fragment, materials.copper_ingot}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
--type = "shapeless",
|
||||||
|
output = "basic_materials:energy_crystal_simple 2",
|
||||||
|
recipe = {
|
||||||
|
{materials.mese_crystal_fragment, materials.torch, materials.mese_crystal_fragment},
|
||||||
|
{materials.diamond, materials.gold_ingot, materials.diamond}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:copper_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.copper_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:gold_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.gold_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:steel_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.steel_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if materials.stainless_steel_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:stainless_steel_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.stainless_steel_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if materials.aluminum_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:aluminum_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.aluminum_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:steel_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.steel_ingot, ""},
|
||||||
|
{materials.steel_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:copper_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.copper_ingot, ""},
|
||||||
|
{materials.copper_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:gold_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.gold_ingot, ""},
|
||||||
|
{materials.gold_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if materials.lead_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:lead_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.lead_ingot, ""},
|
||||||
|
{materials.lead_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if materials.stainless_steel_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:stainless_steel_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.stainless_steel_ingot, ""},
|
||||||
|
{materials.stainless_steel_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if materials.aluminum_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:aluminum_strip 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.aluminum_ingot, ""},
|
||||||
|
{materials.aluminum_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:steel_bar 6",
|
||||||
|
recipe = {
|
||||||
|
{"", "", materials.steel_ingot},
|
||||||
|
{"", materials.steel_ingot, ""},
|
||||||
|
{materials.steel_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if materials.carbon_steel_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:carbon_steel_bar 6",
|
||||||
|
recipe = {
|
||||||
|
{"", "", materials.carbon_steel_ingot},
|
||||||
|
{"", materials.carbon_steel_ingot, ""},
|
||||||
|
{materials.carbon_steel_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if materials.stainless_steel_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:stainless_steel_bar 6",
|
||||||
|
recipe = {
|
||||||
|
{"", "", materials.stainless_steel_ingot},
|
||||||
|
{"", materials.stainless_steel_ingot, ""},
|
||||||
|
{materials.stainless_steel_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if materials.aluminum_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:aluminum_bar 6",
|
||||||
|
recipe = {
|
||||||
|
{"", "", materials.aluminum_ingot},
|
||||||
|
{"", materials.aluminum_ingot, ""},
|
||||||
|
{materials.aluminum_ingot, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:padlock 2",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:steel_bar"},
|
||||||
|
{materials.steel_ingot},
|
||||||
|
{materials.steel_ingot},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
output = "basic_materials:chainlink_steel 12",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.steel_ingot, materials.steel_ingot},
|
||||||
|
{materials.steel_ingot, "", materials.steel_ingot},
|
||||||
|
{materials.steel_ingot, materials.steel_ingot, ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:gear_steel 6",
|
||||||
|
recipe = {
|
||||||
|
{"", materials.steel_ingot, ""},
|
||||||
|
{materials.steel_ingot,"basic_materials:chainlink_steel", materials.steel_ingot},
|
||||||
|
{"", materials.steel_ingot, ""}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
type = "shapeless",
|
||||||
|
output = "basic_materials:terracotta_base 8",
|
||||||
|
recipe = {
|
||||||
|
materials.water_bucket,
|
||||||
|
materials.clay_lump,
|
||||||
|
materials.gravel,
|
||||||
|
},
|
||||||
|
replacements = {{materials.water_bucket, materials.empty_bucket}},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "basic_materials:wet_cement 3",
|
||||||
|
recipe = {
|
||||||
|
materials.dirt,
|
||||||
|
materials.dye_dark_grey,
|
||||||
|
materials.dye_dark_grey,
|
||||||
|
materials.dye_dark_grey,
|
||||||
|
materials.water_bucket
|
||||||
|
},
|
||||||
|
replacements = {{materials.water_bucket, materials.empty_bucket}},
|
||||||
|
})
|
||||||
|
|
||||||
|
if not have_hades_materials then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:silicon 4",
|
||||||
|
recipe = {
|
||||||
|
{materials.sand, materials.sand},
|
||||||
|
{materials.sand, materials.steel_ingot},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:ic 4",
|
||||||
|
recipe = {
|
||||||
|
{"basic_materials:silicon", "basic_materials:silicon"},
|
||||||
|
{"basic_materials:silicon", materials.copper_ingot},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Without moreores, there still should be a way to create brass.
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:brass_ingot 9",
|
||||||
|
recipe = {
|
||||||
|
{materials.copper_ingot, materials.tin_ingot, materials.copper_ingot},
|
||||||
|
{materials.gold_ingot, materials.copper_ingot, materials.tin_ingot},
|
||||||
|
{materials.copper_ingot, materials.tin_ingot, materials.copper_ingot},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if materials.silver_ingot then
|
||||||
|
register_craft( {
|
||||||
|
output = "basic_materials:silver_wire 2",
|
||||||
|
type = "shapeless",
|
||||||
|
recipe = {
|
||||||
|
materials.silver_ingot,
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
"basic_materials:empty_spool",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
register_craft( {
|
||||||
|
type = "shapeless",
|
||||||
|
output = "basic_materials:brass_ingot 3",
|
||||||
|
recipe = {
|
||||||
|
materials.copper_ingot,
|
||||||
|
materials.copper_ingot,
|
||||||
|
materials.silver_ingot,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
14
mods/basic_materials/init.lua
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- Basic materials mod
|
||||||
|
-- by Vanessa Dannenberg
|
||||||
|
|
||||||
|
-- This mod supplies all those little random craft items that everyone always
|
||||||
|
-- seems to need, such as metal bars (ala rebar), plastic, wire, and so on.
|
||||||
|
|
||||||
|
basic_materials = {}
|
||||||
|
basic_materials.mod = { author = "Vanessa Dannenberg" }
|
||||||
|
basic_materials.modpath = minetest.get_modpath("basic_materials")
|
||||||
|
|
||||||
|
dofile(basic_materials.modpath .. "/nodes.lua")
|
||||||
|
dofile(basic_materials.modpath .. "/craftitems.lua")
|
||||||
|
dofile(basic_materials.modpath .. "/crafts.lua")
|
||||||
|
dofile(basic_materials.modpath .. "/aliases.lua")
|
33
mods/basic_materials/locale/basic_materials.de.tr
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# textdomain: basic_materials
|
||||||
|
Silicon lump=Siliziumklumpen
|
||||||
|
Simple Integrated Circuit=Einfacher Integrierter Schaltkreis
|
||||||
|
Simple Motor=Einfacher Motor
|
||||||
|
Heating element=Heizelement
|
||||||
|
Simple energy crystal=Einfacher Energiekristall
|
||||||
|
|
||||||
|
Spool of steel wire=Spule mit Stahldraht
|
||||||
|
Spool of copper wire=Spule mit Kupferdraht
|
||||||
|
Spool of silver wire=Spule mit Silberdraht
|
||||||
|
Spool of gold wire=Spule mit Golddraht
|
||||||
|
Steel Strip=Stahlstreifen
|
||||||
|
Copper Strip=Kupferstreifen
|
||||||
|
Steel Bar=Stahlstab
|
||||||
|
Chainlinks (brass)=Messingkettenglieder
|
||||||
|
Chainlinks (steel)=Stahlkettenglieder
|
||||||
|
Brass Ingot=Messingbarren
|
||||||
|
Steel gear=Stahlzahnrad
|
||||||
|
Padlock=Vorhängeschloss
|
||||||
|
Chain (steel, hanging)=Hängende Stahlkette
|
||||||
|
Chain (brass, hanging)=Hängende Messingkette
|
||||||
|
Brass Block=Messingblock
|
||||||
|
|
||||||
|
Oil extract=Ölextrakt
|
||||||
|
Unprocessed paraffin=Unverarbeitetes Paraffin
|
||||||
|
Uncooked Terracotta Base=Ungebranntes Terrakotta
|
||||||
|
Wet Cement=Nasser Zement
|
||||||
|
Cement=Zement
|
||||||
|
Concrete Block=Betonblock
|
||||||
|
|
||||||
|
Plastic sheet=Kunststoffplatte
|
||||||
|
Plastic strips=Kunststoffstreifen
|
||||||
|
Empty wire spool=Leere Drahtspule
|
33
mods/basic_materials/locale/basic_materials.fr.tr
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# textdomain: basic_materials
|
||||||
|
Silicon lump=Morceau de silicium
|
||||||
|
Simple Integrated Circuit=Circuit intégré simple
|
||||||
|
Simple Motor=Moteur simple
|
||||||
|
Heating element=Élément chauffant
|
||||||
|
Simple energy crystal=Cristal d’énergie simple
|
||||||
|
|
||||||
|
Spool of steel wire=Bobine de fil d’acier
|
||||||
|
Spool of copper wire=Bobine de fil de cuivre
|
||||||
|
Spool of silver wire=Bobine de fil d’argent
|
||||||
|
Spool of gold wire=Bobine de fil d’or
|
||||||
|
Steel Strip=Bande de acier
|
||||||
|
Copper Strip=Bande de cuivre
|
||||||
|
Steel Bar=Barre d’acier
|
||||||
|
Chainlinks (brass)=Maillon en laiton
|
||||||
|
Chainlinks (steel)=Maillon en acier
|
||||||
|
Brass Ingot=Lingot de laiton
|
||||||
|
Steel gear=Rouage en acier
|
||||||
|
Padlock=Cadenas
|
||||||
|
Chain (steel, hanging)=Chaine en acier
|
||||||
|
Chain (brass, hanging)=Chaine en laiton
|
||||||
|
Brass Block=Bloc de laiton
|
||||||
|
|
||||||
|
Oil extract=Extrait d’huile
|
||||||
|
Unprocessed paraffin=Paraffine non transformée
|
||||||
|
Uncooked Terracotta Base=Argile crue
|
||||||
|
Wet Cement=Ciment humide
|
||||||
|
Cement=Ciment
|
||||||
|
Concrete Block=Bloc de béton
|
||||||
|
|
||||||
|
Plastic sheet=Morceau de plastique
|
||||||
|
Plastic strips=Bande de plastique
|
||||||
|
Empty wire spool=Bobine de fil vide
|
34
mods/basic_materials/locale/basic_materials.it.tr
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# textdomain: basic_materials
|
||||||
|
# Author: Salvo 'LtWorf' Tomaselli <tiposchi@tiscali.it>
|
||||||
|
Silicon lump=Grumo di silicio
|
||||||
|
Simple Integrated Circuit=Circuito integrato semplice
|
||||||
|
Simple Motor=Motore semplice
|
||||||
|
Heating element=Elemento riscaldante
|
||||||
|
Simple energy crystal=Cristallo di energia semplice
|
||||||
|
|
||||||
|
Spool of steel wire=Bobina di filo d'acciaio
|
||||||
|
Spool of copper wire=Bobina di filo di rame
|
||||||
|
Spool of silver wire=Bobina di filo d'argento
|
||||||
|
Spool of gold wire=Bobina di filo d'oro
|
||||||
|
Steel Strip=Striscia d'acciaio
|
||||||
|
Copper Strip=Striscia di rame
|
||||||
|
Steel Bar=Barra d'acciaio
|
||||||
|
Chainlinks (brass)=Catena (ottone)
|
||||||
|
Chainlinks (steel)=Catena (acciaio)
|
||||||
|
Brass Ingot=Lingotto di ottone
|
||||||
|
Steel gear=Ingranaggio d'acciaio
|
||||||
|
Padlock=Catenaccio
|
||||||
|
Chain (steel, hanging)=Catena (acciaio, pendente)
|
||||||
|
Chain (brass, hanging)=Catena (ottone, pendente)
|
||||||
|
Brass Block=Blocco di ottone
|
||||||
|
|
||||||
|
Oil extract=Estratto d'olio
|
||||||
|
Unprocessed paraffin=Paraffina grezza
|
||||||
|
Uncooked Terracotta Base=Argilla cruda
|
||||||
|
Wet Cement=Cemento umido
|
||||||
|
Cement=Cemento
|
||||||
|
Concrete Block=Blocco di calcestruzzo
|
||||||
|
|
||||||
|
Plastic sheet=Foglio di plastica
|
||||||
|
Plastic strips=Striscia di plastica
|
||||||
|
Empty wire spool=Rocchetto vuoto
|
33
mods/basic_materials/locale/basic_materials.ru.tr
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# textdomain: basic_materials
|
||||||
|
Silicon lump=Кусок Кремния
|
||||||
|
Simple Integrated Circuit=Микросхема
|
||||||
|
Simple Motor=Мотор
|
||||||
|
Heating element=Нить Накала
|
||||||
|
Simple energy crystal=Энергетический Кристалл
|
||||||
|
|
||||||
|
Spool of steel wire=Катушка Стальной Проволоки
|
||||||
|
Spool of copper wire=Катушка Медной Проволоки
|
||||||
|
Spool of silver wire=Катушка Серебрянной Проволоки
|
||||||
|
Spool of gold wire=Катушка Золотой Проволоки
|
||||||
|
Steel Strip=Стальная Полоса
|
||||||
|
Copper Strip=Медная Полоса
|
||||||
|
Steel Bar=Стальной Прут
|
||||||
|
Chainlinks (brass)=Латунные Звенья
|
||||||
|
Chainlinks (steel)=Стальные Звенья
|
||||||
|
Brass Ingot=Латунный Брусок
|
||||||
|
Steel gear=Стальная Шестерня
|
||||||
|
Padlock=Навесной Замок
|
||||||
|
Chain (steel, hanging)=Стальная Цепь
|
||||||
|
Chain (brass, hanging)=Латунная Цепь
|
||||||
|
Brass Block=Латунный Блок
|
||||||
|
|
||||||
|
Oil extract=Масляный Экстракт
|
||||||
|
Unprocessed paraffin=Необработанный Парафин
|
||||||
|
Uncooked Terracotta Base=Ком Мокрого Терракота
|
||||||
|
Wet Cement=Ком Мокрого Цемента
|
||||||
|
Cement=Цемент
|
||||||
|
Concrete Block=Железобетон
|
||||||
|
|
||||||
|
Plastic sheet=Пластиковый Лист
|
||||||
|
Plastic strips=Пластиковая Полоса
|
||||||
|
Empty wire spool=Пустая Катушка
|
8
mods/basic_materials/mod.conf
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
name = basic_materials
|
||||||
|
depends = xcompat
|
||||||
|
optional_depends = moreores, default, mesecons_materials, dye, bucket, fl_stone, fl_trees, mcl_sounds, hades_core, hades_sounds, hades_materials, hades_dye, hades_bucket, hades_extraores, hades_mesecons_materials, aloz, rp_crafting, mcl_core, mcl_copper
|
||||||
|
min_minetest_version = 5.2.0
|
||||||
|
release = 23751
|
||||||
|
author = mt-mods
|
||||||
|
description = Provides a small selection of "basic" materials and items that other mods should use when possible -- things like steel bars and chains, wire, plastic strips and sheets, and more.
|
||||||
|
title = Basic Materials and items
|
881
mods/basic_materials/models/basic_materials_chains.obj
Normal file
|
@ -0,0 +1,881 @@
|
||||||
|
# Blender v2.73 (sub 0) OBJ File: 'chains.blend'
|
||||||
|
# www.blender.org
|
||||||
|
o Torus.016_Torus
|
||||||
|
v 0.000000 -0.429978 0.000002
|
||||||
|
v 0.000000 -0.401109 0.055211
|
||||||
|
v -0.014044 -0.391975 0.048870
|
||||||
|
v -0.014044 -0.423304 0.000002
|
||||||
|
v -0.009826 -0.379748 0.040970
|
||||||
|
v -0.009826 -0.406012 0.000002
|
||||||
|
v 0.009826 -0.379748 0.040970
|
||||||
|
v 0.009826 -0.406012 0.000002
|
||||||
|
v 0.014044 -0.391975 0.048870
|
||||||
|
v 0.014044 -0.423304 0.000002
|
||||||
|
v 0.000000 -0.316336 0.080195
|
||||||
|
v -0.014044 -0.316336 0.069112
|
||||||
|
v -0.009826 -0.316336 0.057941
|
||||||
|
v 0.009826 -0.316336 0.057941
|
||||||
|
v 0.014044 -0.316336 0.069112
|
||||||
|
v 0.000000 -0.231564 0.055211
|
||||||
|
v -0.014044 -0.240700 0.048870
|
||||||
|
v -0.009826 -0.252925 0.040970
|
||||||
|
v 0.009826 -0.252925 0.040970
|
||||||
|
v 0.014044 -0.240700 0.048870
|
||||||
|
v 0.000000 -0.202695 0.000002
|
||||||
|
v -0.014044 -0.209368 0.000002
|
||||||
|
v -0.009826 -0.226661 0.000002
|
||||||
|
v 0.009826 -0.226661 0.000002
|
||||||
|
v 0.014044 -0.209368 0.000002
|
||||||
|
v 0.000000 -0.231564 -0.055206
|
||||||
|
v -0.014044 -0.240700 -0.048868
|
||||||
|
v -0.009826 -0.252925 -0.040967
|
||||||
|
v 0.009826 -0.252925 -0.040967
|
||||||
|
v 0.014044 -0.240700 -0.048865
|
||||||
|
v 0.000000 -0.316336 -0.080190
|
||||||
|
v -0.014044 -0.316336 -0.069108
|
||||||
|
v -0.009826 -0.316336 -0.057936
|
||||||
|
v 0.009826 -0.316336 -0.057936
|
||||||
|
v 0.014044 -0.316336 -0.069108
|
||||||
|
v 0.000000 -0.400361 -0.055206
|
||||||
|
v -0.014044 -0.391975 -0.048868
|
||||||
|
v -0.009826 -0.379748 -0.040967
|
||||||
|
v 0.009826 -0.379748 -0.040967
|
||||||
|
v 0.014044 -0.391975 -0.048868
|
||||||
|
v 0.000000 -0.262249 0.000002
|
||||||
|
v -0.061672 -0.233381 0.000002
|
||||||
|
v -0.054590 -0.224245 -0.012569
|
||||||
|
v 0.000000 -0.255577 -0.012569
|
||||||
|
v -0.045765 -0.212018 -0.008794
|
||||||
|
v 0.000000 -0.238285 -0.008794
|
||||||
|
v -0.045765 -0.212018 0.008798
|
||||||
|
v 0.000000 -0.238285 0.008798
|
||||||
|
v -0.054590 -0.224245 0.012574
|
||||||
|
v 0.000000 -0.255577 0.012574
|
||||||
|
v -0.089582 -0.148609 0.000002
|
||||||
|
v -0.077200 -0.148609 -0.012569
|
||||||
|
v -0.064722 -0.148609 -0.008794
|
||||||
|
v -0.064722 -0.148609 0.008799
|
||||||
|
v -0.077200 -0.148609 0.012574
|
||||||
|
v -0.061672 -0.063837 0.000002
|
||||||
|
v -0.054590 -0.072971 -0.012569
|
||||||
|
v -0.045765 -0.085198 -0.008794
|
||||||
|
v -0.045765 -0.085198 0.008799
|
||||||
|
v -0.054590 -0.072971 0.012574
|
||||||
|
v 0.000000 -0.034967 0.000002
|
||||||
|
v 0.000000 -0.041641 -0.012569
|
||||||
|
v 0.000000 -0.058933 -0.008794
|
||||||
|
v 0.000000 -0.058933 0.008799
|
||||||
|
v 0.000000 -0.041641 0.012574
|
||||||
|
v 0.061672 -0.063837 0.000002
|
||||||
|
v 0.054590 -0.072971 -0.012569
|
||||||
|
v 0.045765 -0.085198 -0.008794
|
||||||
|
v 0.045765 -0.085198 0.008799
|
||||||
|
v 0.054590 -0.072971 0.012574
|
||||||
|
v 0.089582 -0.148609 0.000002
|
||||||
|
v 0.077200 -0.148609 -0.012569
|
||||||
|
v 0.064722 -0.148609 -0.008794
|
||||||
|
v 0.064722 -0.148609 0.008799
|
||||||
|
v 0.077200 -0.148609 0.012574
|
||||||
|
v 0.061672 -0.232631 0.000002
|
||||||
|
v 0.054590 -0.224245 -0.012569
|
||||||
|
v 0.045765 -0.212018 -0.008794
|
||||||
|
v 0.045765 -0.212018 0.008798
|
||||||
|
v 0.054590 -0.224245 0.012574
|
||||||
|
v 0.000000 0.073316 0.000002
|
||||||
|
v 0.061672 0.102183 0.000002
|
||||||
|
v 0.054590 0.111319 0.012574
|
||||||
|
v 0.000000 0.079988 0.012574
|
||||||
|
v 0.045765 0.123546 0.008799
|
||||||
|
v 0.000000 0.097280 0.008799
|
||||||
|
v 0.045765 0.123546 -0.008794
|
||||||
|
v 0.000000 0.097280 -0.008794
|
||||||
|
v 0.054590 0.111319 -0.012569
|
||||||
|
v 0.000000 0.079988 -0.012569
|
||||||
|
v 0.089582 0.186956 0.000002
|
||||||
|
v 0.077200 0.186956 0.012574
|
||||||
|
v 0.064722 0.186956 0.008799
|
||||||
|
v 0.064722 0.186956 -0.008794
|
||||||
|
v 0.077200 0.186956 -0.012569
|
||||||
|
v 0.061672 0.271728 0.000002
|
||||||
|
v 0.054590 0.262594 0.012574
|
||||||
|
v 0.045765 0.250367 0.008799
|
||||||
|
v 0.045765 0.250367 -0.008794
|
||||||
|
v 0.054590 0.262594 -0.012569
|
||||||
|
v 0.000000 0.300597 0.000002
|
||||||
|
v 0.000000 0.293923 0.012574
|
||||||
|
v 0.000000 0.276631 0.008799
|
||||||
|
v 0.000000 0.276631 -0.008794
|
||||||
|
v 0.000000 0.293923 -0.012569
|
||||||
|
v -0.061672 0.271728 0.000002
|
||||||
|
v -0.054590 0.262594 0.012574
|
||||||
|
v -0.045765 0.250367 0.008799
|
||||||
|
v -0.045765 0.250367 -0.008794
|
||||||
|
v -0.054590 0.262594 -0.012569
|
||||||
|
v -0.089582 0.186956 0.000002
|
||||||
|
v -0.077200 0.186956 0.012574
|
||||||
|
v -0.064722 0.186956 0.008799
|
||||||
|
v -0.064722 0.186956 -0.008794
|
||||||
|
v -0.077200 0.186956 -0.012569
|
||||||
|
v -0.061672 0.102931 0.000002
|
||||||
|
v -0.054590 0.111319 0.012574
|
||||||
|
v -0.045765 0.123546 0.008799
|
||||||
|
v -0.045765 0.123546 -0.008794
|
||||||
|
v -0.054590 0.111319 -0.012569
|
||||||
|
v 0.000000 -0.095037 0.000002
|
||||||
|
v 0.000000 -0.066168 -0.055206
|
||||||
|
v 0.014044 -0.057034 -0.048868
|
||||||
|
v 0.014044 -0.088363 0.000002
|
||||||
|
v 0.009826 -0.044807 -0.040967
|
||||||
|
v 0.009826 -0.071071 0.000002
|
||||||
|
v -0.009826 -0.044807 -0.040967
|
||||||
|
v -0.009826 -0.071071 0.000002
|
||||||
|
v -0.014044 -0.057034 -0.048868
|
||||||
|
v -0.014044 -0.088363 0.000002
|
||||||
|
v 0.000000 0.018605 -0.080190
|
||||||
|
v 0.014044 0.018605 -0.069108
|
||||||
|
v 0.009826 0.018605 -0.057936
|
||||||
|
v -0.009826 0.018605 -0.057936
|
||||||
|
v -0.014044 0.018605 -0.069108
|
||||||
|
v 0.000000 0.103377 -0.055206
|
||||||
|
v 0.014044 0.094243 -0.048868
|
||||||
|
v 0.009826 0.082016 -0.040967
|
||||||
|
v -0.009826 0.082016 -0.040967
|
||||||
|
v -0.014044 0.094243 -0.048868
|
||||||
|
v 0.000000 0.132246 0.000002
|
||||||
|
v 0.014044 0.125572 0.000002
|
||||||
|
v 0.009826 0.108280 0.000002
|
||||||
|
v -0.009826 0.108280 0.000002
|
||||||
|
v -0.014044 0.125572 0.000002
|
||||||
|
v 0.000000 0.103377 0.055211
|
||||||
|
v 0.014044 0.094243 0.048870
|
||||||
|
v 0.009826 0.082016 0.040970
|
||||||
|
v -0.009826 0.082016 0.040970
|
||||||
|
v -0.014044 0.094243 0.048870
|
||||||
|
v 0.000000 0.018605 0.080195
|
||||||
|
v 0.014044 0.018605 0.069112
|
||||||
|
v 0.009826 0.018605 0.057941
|
||||||
|
v -0.009826 0.018605 0.057941
|
||||||
|
v -0.014044 0.018605 0.069112
|
||||||
|
v 0.000000 -0.065420 0.055211
|
||||||
|
v 0.014044 -0.057032 0.048870
|
||||||
|
v 0.009826 -0.044807 0.040970
|
||||||
|
v -0.009826 -0.044807 0.040970
|
||||||
|
v -0.014044 -0.057032 0.048870
|
||||||
|
v 0.000000 -0.598329 0.000002
|
||||||
|
v 0.061672 -0.569460 0.000002
|
||||||
|
v 0.054590 -0.560326 0.012574
|
||||||
|
v 0.000000 -0.591655 0.012574
|
||||||
|
v 0.045765 -0.548099 0.008798
|
||||||
|
v 0.000000 -0.574363 0.008798
|
||||||
|
v 0.045765 -0.548099 -0.008794
|
||||||
|
v 0.000000 -0.574363 -0.008794
|
||||||
|
v 0.054590 -0.560326 -0.012569
|
||||||
|
v 0.000000 -0.591655 -0.012569
|
||||||
|
v 0.089582 -0.484687 0.000002
|
||||||
|
v 0.077200 -0.484687 0.012574
|
||||||
|
v 0.064722 -0.484687 0.008798
|
||||||
|
v 0.064722 -0.484687 -0.008794
|
||||||
|
v 0.077200 -0.484687 -0.012569
|
||||||
|
v 0.061672 -0.399915 0.000002
|
||||||
|
v 0.054590 -0.409051 0.012574
|
||||||
|
v 0.045765 -0.421278 0.008798
|
||||||
|
v 0.045765 -0.421278 -0.008794
|
||||||
|
v 0.054590 -0.409051 -0.012569
|
||||||
|
v 0.000000 -0.371048 0.000002
|
||||||
|
v 0.000000 -0.377719 0.012574
|
||||||
|
v 0.000000 -0.395012 0.008798
|
||||||
|
v 0.000000 -0.395012 -0.008794
|
||||||
|
v 0.000000 -0.377719 -0.012569
|
||||||
|
v -0.061672 -0.399915 0.000002
|
||||||
|
v -0.054590 -0.409051 0.012574
|
||||||
|
v -0.045765 -0.421278 0.008798
|
||||||
|
v -0.045765 -0.421278 -0.008794
|
||||||
|
v -0.054590 -0.409051 -0.012569
|
||||||
|
v -0.089582 -0.484687 0.000002
|
||||||
|
v -0.077200 -0.484687 0.012574
|
||||||
|
v -0.064722 -0.484687 0.008798
|
||||||
|
v -0.064722 -0.484687 -0.008794
|
||||||
|
v -0.077200 -0.484687 -0.012569
|
||||||
|
v -0.061672 -0.568712 0.000002
|
||||||
|
v -0.054590 -0.560326 0.012574
|
||||||
|
v -0.045765 -0.548099 0.008798
|
||||||
|
v -0.045765 -0.548099 -0.008794
|
||||||
|
v -0.054590 -0.560326 -0.012569
|
||||||
|
v 0.000000 0.241043 0.000002
|
||||||
|
v 0.000000 0.269910 0.055211
|
||||||
|
v -0.014044 0.279047 0.048870
|
||||||
|
v -0.014044 0.247717 0.000002
|
||||||
|
v -0.009826 0.291274 0.040970
|
||||||
|
v -0.009826 0.265007 0.000002
|
||||||
|
v 0.009826 0.291274 0.040970
|
||||||
|
v 0.009826 0.265007 0.000002
|
||||||
|
v 0.014044 0.279047 0.048870
|
||||||
|
v 0.014044 0.247717 0.000002
|
||||||
|
v 0.000000 0.354683 0.080195
|
||||||
|
v -0.014044 0.354683 0.069112
|
||||||
|
v -0.009826 0.354683 0.057941
|
||||||
|
v 0.009826 0.354683 0.057941
|
||||||
|
v 0.014044 0.354683 0.069112
|
||||||
|
v 0.000000 0.439455 0.055211
|
||||||
|
v -0.014044 0.430321 0.048870
|
||||||
|
v -0.009826 0.418094 0.040970
|
||||||
|
v 0.009826 0.418094 0.040970
|
||||||
|
v 0.014044 0.430321 0.048870
|
||||||
|
v 0.000000 0.468325 0.000002
|
||||||
|
v -0.014044 0.461651 0.000002
|
||||||
|
v -0.009826 0.444361 0.000002
|
||||||
|
v 0.009826 0.444361 0.000002
|
||||||
|
v 0.014044 0.461651 0.000002
|
||||||
|
v 0.000000 0.439455 -0.055206
|
||||||
|
v -0.014044 0.430321 -0.048868
|
||||||
|
v -0.009826 0.418094 -0.040967
|
||||||
|
v 0.009826 0.418094 -0.040967
|
||||||
|
v 0.014044 0.430321 -0.048868
|
||||||
|
v 0.000000 0.354683 -0.080190
|
||||||
|
v -0.014044 0.354683 -0.069108
|
||||||
|
v -0.009826 0.354683 -0.057936
|
||||||
|
v 0.009826 0.354683 -0.057936
|
||||||
|
v 0.014044 0.354683 -0.069108
|
||||||
|
v 0.000000 0.270661 -0.055206
|
||||||
|
v -0.014044 0.279047 -0.048868
|
||||||
|
v -0.009826 0.291274 -0.040967
|
||||||
|
v 0.009826 0.291274 -0.040967
|
||||||
|
v 0.014044 0.279047 -0.048868
|
||||||
|
vt 0.187500 0.125000
|
||||||
|
vt 0.250000 0.125000
|
||||||
|
vt 0.250000 0.187500
|
||||||
|
vt 0.187500 0.187500
|
||||||
|
vt 0.250000 0.250000
|
||||||
|
vt 0.187500 0.250000
|
||||||
|
vt 0.250000 0.312500
|
||||||
|
vt 0.187500 0.312500
|
||||||
|
vt 0.250000 0.375000
|
||||||
|
vt 0.187500 0.375000
|
||||||
|
vt 0.187500 0.062500
|
||||||
|
vt 0.250000 0.062500
|
||||||
|
vt 0.312500 0.125000
|
||||||
|
vt 0.312500 0.187500
|
||||||
|
vt 0.312500 0.250000
|
||||||
|
vt 0.312500 0.312500
|
||||||
|
vt 0.312500 0.375000
|
||||||
|
vt 0.312500 0.062500
|
||||||
|
vt 0.375000 0.125000
|
||||||
|
vt 0.375000 0.187500
|
||||||
|
vt 0.375000 0.250000
|
||||||
|
vt 0.375000 0.312500
|
||||||
|
vt 0.375000 0.375000
|
||||||
|
vt 0.375000 0.062500
|
||||||
|
vt 0.437500 0.125000
|
||||||
|
vt 0.437500 0.187500
|
||||||
|
vt 0.437500 0.250000
|
||||||
|
vt 0.437500 0.312500
|
||||||
|
vt 0.437500 0.375000
|
||||||
|
vt 0.437500 0.062500
|
||||||
|
vt 0.500000 0.125000
|
||||||
|
vt 0.500000 0.187500
|
||||||
|
vt 0.500000 0.250000
|
||||||
|
vt 0.500000 0.312500
|
||||||
|
vt 0.500000 0.375000
|
||||||
|
vt 0.500000 0.062500
|
||||||
|
vt -0.000000 0.125000
|
||||||
|
vt 0.062500 0.125000
|
||||||
|
vt 0.062500 0.187500
|
||||||
|
vt -0.000000 0.187500
|
||||||
|
vt 0.062500 0.250000
|
||||||
|
vt -0.000000 0.250000
|
||||||
|
vt 0.062500 0.312500
|
||||||
|
vt -0.000000 0.312500
|
||||||
|
vt 0.062500 0.375000
|
||||||
|
vt -0.000000 0.375000
|
||||||
|
vt -0.000000 0.062500
|
||||||
|
vt 0.062500 0.062500
|
||||||
|
vt 0.125000 0.125000
|
||||||
|
vt 0.125000 0.187500
|
||||||
|
vt 0.125000 0.250000
|
||||||
|
vt 0.125000 0.312500
|
||||||
|
vt 0.125000 0.375000
|
||||||
|
vt 0.125000 0.062500
|
||||||
|
vt 0.750000 0.625000
|
||||||
|
vt 0.812500 0.625000
|
||||||
|
vt 0.812500 0.687500
|
||||||
|
vt 0.750000 0.687500
|
||||||
|
vt 0.750000 0.375000
|
||||||
|
vt 0.812500 0.375000
|
||||||
|
vt 0.812500 0.437500
|
||||||
|
vt 0.750000 0.437500
|
||||||
|
vt 0.812500 0.500000
|
||||||
|
vt 0.750000 0.500000
|
||||||
|
vt 0.812500 0.562500
|
||||||
|
vt 0.750000 0.562500
|
||||||
|
vt 0.875000 0.625000
|
||||||
|
vt 0.875000 0.687500
|
||||||
|
vt 0.875000 0.375000
|
||||||
|
vt 0.875000 0.437500
|
||||||
|
vt 0.875000 0.500000
|
||||||
|
vt 0.875000 0.562500
|
||||||
|
vt 0.937500 0.625000
|
||||||
|
vt 0.937500 0.687500
|
||||||
|
vt 0.937500 0.375000
|
||||||
|
vt 0.937500 0.437500
|
||||||
|
vt 0.937500 0.500000
|
||||||
|
vt 0.937500 0.562500
|
||||||
|
vt 1.000000 0.625000
|
||||||
|
vt 1.000000 0.687500
|
||||||
|
vt 1.000000 0.375000
|
||||||
|
vt 1.000000 0.437500
|
||||||
|
vt 1.000000 0.500000
|
||||||
|
vt 1.000000 0.562500
|
||||||
|
vt 0.500000 0.625000
|
||||||
|
vt 0.562500 0.625000
|
||||||
|
vt 0.562500 0.687500
|
||||||
|
vt 0.500000 0.687500
|
||||||
|
vt 0.562500 0.375000
|
||||||
|
vt 0.562500 0.437500
|
||||||
|
vt 0.500000 0.437500
|
||||||
|
vt 0.562500 0.500000
|
||||||
|
vt 0.500000 0.500000
|
||||||
|
vt 0.562500 0.562500
|
||||||
|
vt 0.500000 0.562500
|
||||||
|
vt 0.625000 0.625000
|
||||||
|
vt 0.625000 0.687500
|
||||||
|
vt 0.625000 0.375000
|
||||||
|
vt 0.625000 0.437500
|
||||||
|
vt 0.625000 0.500000
|
||||||
|
vt 0.625000 0.562500
|
||||||
|
vt 0.687500 0.625000
|
||||||
|
vt 0.687500 0.687500
|
||||||
|
vt 0.687500 0.375000
|
||||||
|
vt 0.687500 0.437500
|
||||||
|
vt 0.687500 0.500000
|
||||||
|
vt 0.687500 0.562500
|
||||||
|
vt 0.250000 0.625000
|
||||||
|
vt 0.312500 0.625000
|
||||||
|
vt 0.312500 0.687500
|
||||||
|
vt 0.250000 0.687500
|
||||||
|
vt 0.312500 0.437500
|
||||||
|
vt 0.250000 0.437500
|
||||||
|
vt 0.312500 0.500000
|
||||||
|
vt 0.250000 0.500000
|
||||||
|
vt 0.312500 0.562500
|
||||||
|
vt 0.250000 0.562500
|
||||||
|
vt 0.375000 0.625000
|
||||||
|
vt 0.375000 0.687500
|
||||||
|
vt 0.375000 0.437500
|
||||||
|
vt 0.375000 0.500000
|
||||||
|
vt 0.375000 0.562500
|
||||||
|
vt 0.437500 0.625000
|
||||||
|
vt 0.437500 0.687500
|
||||||
|
vt 0.437500 0.437500
|
||||||
|
vt 0.437500 0.500000
|
||||||
|
vt 0.437500 0.562500
|
||||||
|
vt -0.000000 0.625000
|
||||||
|
vt 0.062500 0.625000
|
||||||
|
vt 0.062500 0.687500
|
||||||
|
vt -0.000000 0.687500
|
||||||
|
vt 0.062500 0.437500
|
||||||
|
vt -0.000000 0.437500
|
||||||
|
vt 0.062500 0.500000
|
||||||
|
vt -0.000000 0.500000
|
||||||
|
vt 0.062500 0.562500
|
||||||
|
vt -0.000000 0.562500
|
||||||
|
vt 0.125000 0.625000
|
||||||
|
vt 0.125000 0.687500
|
||||||
|
vt 0.125000 0.437500
|
||||||
|
vt 0.125000 0.500000
|
||||||
|
vt 0.125000 0.562500
|
||||||
|
vt 0.187500 0.625000
|
||||||
|
vt 0.187500 0.687500
|
||||||
|
vt 0.187500 0.437500
|
||||||
|
vt 0.187500 0.500000
|
||||||
|
vt 0.187500 0.562500
|
||||||
|
vt 0.687500 0.750000
|
||||||
|
vt 0.750000 0.750000
|
||||||
|
vt 0.750000 0.812500
|
||||||
|
vt 0.687500 0.812500
|
||||||
|
vt 0.750000 0.875000
|
||||||
|
vt 0.687500 0.875000
|
||||||
|
vt 0.750000 0.937500
|
||||||
|
vt 0.687500 0.937500
|
||||||
|
vt 0.750000 1.000000
|
||||||
|
vt 0.687500 1.000000
|
||||||
|
vt 0.812500 0.750000
|
||||||
|
vt 0.812500 0.812500
|
||||||
|
vt 0.812500 0.875000
|
||||||
|
vt 0.812500 0.937500
|
||||||
|
vt 0.812500 1.000000
|
||||||
|
vt 0.875000 0.750000
|
||||||
|
vt 0.875000 0.812500
|
||||||
|
vt 0.875000 0.875000
|
||||||
|
vt 0.875000 0.937500
|
||||||
|
vt 0.875000 1.000000
|
||||||
|
vt 0.937500 0.750000
|
||||||
|
vt 0.937500 0.812500
|
||||||
|
vt 0.937500 0.875000
|
||||||
|
vt 0.937500 0.937500
|
||||||
|
vt 0.937500 1.000000
|
||||||
|
vt 1.000000 0.750000
|
||||||
|
vt 1.000000 0.812500
|
||||||
|
vt 1.000000 0.875000
|
||||||
|
vt 1.000000 0.937500
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.500000 0.750000
|
||||||
|
vt 0.562500 0.750000
|
||||||
|
vt 0.562500 0.812500
|
||||||
|
vt 0.500000 0.812500
|
||||||
|
vt 0.562500 0.875000
|
||||||
|
vt 0.500000 0.875000
|
||||||
|
vt 0.562500 0.937500
|
||||||
|
vt 0.500000 0.937500
|
||||||
|
vt 0.562500 1.000000
|
||||||
|
vt 0.500000 1.000000
|
||||||
|
vt 0.625000 0.750000
|
||||||
|
vt 0.625000 0.812500
|
||||||
|
vt 0.625000 0.875000
|
||||||
|
vt 0.625000 0.937500
|
||||||
|
vt 0.625000 1.000000
|
||||||
|
vt 0.750000 0.312500
|
||||||
|
vt 0.812500 0.312500
|
||||||
|
vt 0.750000 0.062500
|
||||||
|
vt 0.812500 0.062500
|
||||||
|
vt 0.812500 0.125000
|
||||||
|
vt 0.750000 0.125000
|
||||||
|
vt 0.812500 0.187500
|
||||||
|
vt 0.750000 0.187500
|
||||||
|
vt 0.812500 0.250000
|
||||||
|
vt 0.750000 0.250000
|
||||||
|
vt 0.875000 0.312500
|
||||||
|
vt 0.875000 0.062500
|
||||||
|
vt 0.875000 0.125000
|
||||||
|
vt 0.875000 0.187500
|
||||||
|
vt 0.875000 0.250000
|
||||||
|
vt 0.937500 0.312500
|
||||||
|
vt 0.937500 0.062500
|
||||||
|
vt 0.937500 0.125000
|
||||||
|
vt 0.937500 0.187500
|
||||||
|
vt 0.937500 0.250000
|
||||||
|
vt 1.000000 0.312500
|
||||||
|
vt 1.000000 0.062500
|
||||||
|
vt 1.000000 0.125000
|
||||||
|
vt 1.000000 0.187500
|
||||||
|
vt 1.000000 0.250000
|
||||||
|
vt 0.562500 0.312500
|
||||||
|
vt 0.562500 0.062500
|
||||||
|
vt 0.562500 0.125000
|
||||||
|
vt 0.562500 0.187500
|
||||||
|
vt 0.562500 0.250000
|
||||||
|
vt 0.625000 0.312500
|
||||||
|
vt 0.625000 0.062500
|
||||||
|
vt 0.625000 0.125000
|
||||||
|
vt 0.625000 0.187500
|
||||||
|
vt 0.625000 0.250000
|
||||||
|
vt 0.687500 0.312500
|
||||||
|
vt 0.687500 0.062500
|
||||||
|
vt 0.687500 0.125000
|
||||||
|
vt 0.687500 0.187500
|
||||||
|
vt 0.687500 0.250000
|
||||||
|
vt 0.250000 0.937500
|
||||||
|
vt 0.312500 0.937500
|
||||||
|
vt 0.312500 1.000000
|
||||||
|
vt 0.250000 1.000000
|
||||||
|
vt 0.312500 0.750000
|
||||||
|
vt 0.250000 0.750000
|
||||||
|
vt 0.312500 0.812500
|
||||||
|
vt 0.250000 0.812500
|
||||||
|
vt 0.312500 0.875000
|
||||||
|
vt 0.250000 0.875000
|
||||||
|
vt 0.375000 0.937500
|
||||||
|
vt 0.375000 1.000000
|
||||||
|
vt 0.375000 0.750000
|
||||||
|
vt 0.375000 0.812500
|
||||||
|
vt 0.375000 0.875000
|
||||||
|
vt 0.437500 0.937500
|
||||||
|
vt 0.437500 1.000000
|
||||||
|
vt 0.437500 0.750000
|
||||||
|
vt 0.437500 0.812500
|
||||||
|
vt 0.437500 0.875000
|
||||||
|
vt 0.000000 0.937500
|
||||||
|
vt 0.062500 0.937500
|
||||||
|
vt 0.062500 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.062500 0.750000
|
||||||
|
vt 0.000000 0.750000
|
||||||
|
vt 0.062500 0.812500
|
||||||
|
vt 0.000000 0.812500
|
||||||
|
vt 0.062500 0.875000
|
||||||
|
vt 0.000000 0.875000
|
||||||
|
vt 0.125000 0.937500
|
||||||
|
vt 0.125000 1.000000
|
||||||
|
vt 0.125000 0.750000
|
||||||
|
vt 0.125000 0.812500
|
||||||
|
vt 0.125000 0.875000
|
||||||
|
vt 0.187500 0.937500
|
||||||
|
vt 0.187500 1.000000
|
||||||
|
vt 0.187500 0.750000
|
||||||
|
vt 0.187500 0.812500
|
||||||
|
vt 0.187500 0.875000
|
||||||
|
vn 0.000000 -1.000000 -0.004800
|
||||||
|
vn 0.000000 -0.657400 0.753500
|
||||||
|
vn -0.898300 -0.248500 0.362300
|
||||||
|
vn -0.863600 -0.504100 -0.003400
|
||||||
|
vn -0.661500 0.421500 -0.620200
|
||||||
|
vn -0.746000 0.665900 0.000000
|
||||||
|
vn 0.661500 0.421500 -0.620200
|
||||||
|
vn 0.746000 0.665900 0.000000
|
||||||
|
vn 0.898300 -0.248500 0.362300
|
||||||
|
vn 0.863600 -0.504100 -0.003400
|
||||||
|
vn 0.000000 0.000000 1.000000
|
||||||
|
vn -0.925200 0.000000 0.379500
|
||||||
|
vn -0.617100 0.000000 -0.786900
|
||||||
|
vn 0.617100 0.000000 -0.786900
|
||||||
|
vn 0.925200 0.000000 0.379500
|
||||||
|
vn 0.000000 0.657400 0.753500
|
||||||
|
vn -0.898300 0.248400 0.362300
|
||||||
|
vn -0.661500 -0.421500 -0.620200
|
||||||
|
vn 0.661500 -0.421500 -0.620200
|
||||||
|
vn 0.898300 0.248400 0.362300
|
||||||
|
vn 0.000000 1.000000 0.000000
|
||||||
|
vn -0.866100 0.499800 0.000000
|
||||||
|
vn -0.746000 -0.665900 0.000000
|
||||||
|
vn 0.746000 -0.665900 0.000000
|
||||||
|
vn 0.866100 0.499800 0.000000
|
||||||
|
vn 0.000000 0.657400 -0.753500
|
||||||
|
vn -0.898300 0.248400 -0.362400
|
||||||
|
vn -0.661600 -0.421500 0.620200
|
||||||
|
vn 0.661500 -0.421500 0.620200
|
||||||
|
vn 0.898300 0.248400 -0.362300
|
||||||
|
vn 0.000000 -0.000900 -1.000000
|
||||||
|
vn -0.924600 -0.000600 -0.380700
|
||||||
|
vn -0.617100 0.000000 0.786900
|
||||||
|
vn 0.617100 0.000000 0.786900
|
||||||
|
vn 0.924700 -0.000600 -0.380700
|
||||||
|
vn 0.000000 -0.650300 -0.759600
|
||||||
|
vn -0.895600 -0.254600 -0.364800
|
||||||
|
vn -0.661600 0.421500 0.620200
|
||||||
|
vn 0.661600 0.421500 0.620200
|
||||||
|
vn 0.895600 -0.254600 -0.364800
|
||||||
|
vn 0.004900 -1.000000 0.000000
|
||||||
|
vn -0.729700 -0.683800 0.000000
|
||||||
|
vn -0.324500 -0.256300 -0.910500
|
||||||
|
vn 0.003300 -0.475500 -0.879700
|
||||||
|
vn 0.578700 0.436200 -0.689100
|
||||||
|
vn 0.000000 0.666600 -0.745400
|
||||||
|
vn 0.578700 0.436200 0.689100
|
||||||
|
vn 0.000000 0.666600 0.745400
|
||||||
|
vn -0.324500 -0.256300 0.910500
|
||||||
|
vn 0.003300 -0.475500 0.879700
|
||||||
|
vn -1.000000 0.000000 0.000000
|
||||||
|
vn -0.359600 0.000000 -0.933100
|
||||||
|
vn 0.756400 0.000000 -0.654100
|
||||||
|
vn 0.756400 0.000000 0.654100
|
||||||
|
vn -0.359600 0.000000 0.933100
|
||||||
|
vn -0.729700 0.683700 0.000000
|
||||||
|
vn -0.324500 0.256300 -0.910500
|
||||||
|
vn 0.578700 -0.436200 -0.689100
|
||||||
|
vn 0.578700 -0.436200 0.689100
|
||||||
|
vn -0.324500 0.256300 0.910500
|
||||||
|
vn 0.000000 0.470900 -0.882200
|
||||||
|
vn 0.000000 -0.666600 -0.745400
|
||||||
|
vn 0.000000 -0.666600 0.745400
|
||||||
|
vn 0.000000 0.470900 0.882200
|
||||||
|
vn 0.729700 0.683700 0.000000
|
||||||
|
vn 0.324500 0.256300 -0.910500
|
||||||
|
vn -0.578700 -0.436200 -0.689100
|
||||||
|
vn -0.578700 -0.436200 0.689100
|
||||||
|
vn 0.324500 0.256300 0.910500
|
||||||
|
vn 1.000000 -0.001100 0.000000
|
||||||
|
vn 0.361000 -0.000700 -0.932600
|
||||||
|
vn -0.756400 0.000000 -0.654100
|
||||||
|
vn -0.756400 0.000000 0.654100
|
||||||
|
vn 0.361000 -0.000700 0.932600
|
||||||
|
vn 0.736100 -0.676800 0.000000
|
||||||
|
vn 0.327100 -0.263100 -0.907600
|
||||||
|
vn -0.578700 0.436200 -0.689100
|
||||||
|
vn -0.578700 0.436200 0.689100
|
||||||
|
vn 0.327100 -0.263100 0.907600
|
||||||
|
vn -0.004900 -1.000000 0.000000
|
||||||
|
vn 0.729700 -0.683800 0.000000
|
||||||
|
vn 0.324500 -0.256300 0.910500
|
||||||
|
vn -0.003300 -0.475400 0.879700
|
||||||
|
vn 0.324500 -0.256300 -0.910500
|
||||||
|
vn -0.003300 -0.475400 -0.879700
|
||||||
|
vn 1.000000 0.000000 0.000000
|
||||||
|
vn 0.359600 0.000000 0.933100
|
||||||
|
vn 0.359600 0.000000 -0.933100
|
||||||
|
vn -1.000000 -0.001100 0.000000
|
||||||
|
vn -0.361000 -0.000700 0.932600
|
||||||
|
vn -0.361000 -0.000700 -0.932600
|
||||||
|
vn -0.736100 -0.676800 0.000000
|
||||||
|
vn -0.327100 -0.263100 0.907600
|
||||||
|
vn -0.327100 -0.263100 -0.907600
|
||||||
|
vn 0.000000 -1.000000 0.004800
|
||||||
|
vn 0.000000 -0.657400 -0.753500
|
||||||
|
vn 0.898300 -0.248500 -0.362400
|
||||||
|
vn 0.863600 -0.504100 0.003400
|
||||||
|
vn -0.898300 -0.248500 -0.362400
|
||||||
|
vn -0.863600 -0.504100 0.003400
|
||||||
|
vn 0.000000 0.000000 -1.000000
|
||||||
|
vn 0.925200 0.000000 -0.379500
|
||||||
|
vn -0.925200 0.000000 -0.379500
|
||||||
|
vn 0.898300 0.248500 -0.362400
|
||||||
|
vn 0.661600 -0.421500 0.620200
|
||||||
|
vn -0.898300 0.248500 -0.362400
|
||||||
|
vn 0.898300 0.248500 0.362300
|
||||||
|
vn -0.898300 0.248500 0.362300
|
||||||
|
vn 0.000000 -0.000900 1.000000
|
||||||
|
vn 0.924700 -0.000600 0.380700
|
||||||
|
vn -0.924700 -0.000600 0.380700
|
||||||
|
vn 0.000000 -0.650300 0.759600
|
||||||
|
vn 0.895600 -0.254600 0.364700
|
||||||
|
vn -0.895600 -0.254600 0.364700
|
||||||
|
vn 0.729700 -0.683700 0.000000
|
||||||
|
vn 0.729700 0.683800 0.000000
|
||||||
|
vn -0.729700 0.683800 0.000000
|
||||||
|
vn -0.898300 -0.248400 0.362300
|
||||||
|
vn -0.863600 -0.504100 -0.003500
|
||||||
|
vn 0.898300 -0.248400 0.362300
|
||||||
|
vn 0.863600 -0.504100 -0.003500
|
||||||
|
vn -0.661500 -0.421500 0.620200
|
||||||
|
vn 0.924600 -0.000600 -0.380700
|
||||||
|
vn -0.661500 0.421500 0.620200
|
||||||
|
vn 0.661500 0.421500 0.620200
|
||||||
|
s 1
|
||||||
|
f 1/1/1 2/2/2 3/3/3 4/4/4
|
||||||
|
f 4/4/4 3/3/3 5/5/5 6/6/6
|
||||||
|
f 6/6/6 5/5/5 7/7/7 8/8/8
|
||||||
|
f 8/8/8 7/7/7 9/9/9 10/10/10
|
||||||
|
f 1/1/1 10/11/10 9/12/9 2/2/2
|
||||||
|
f 2/2/2 11/13/11 12/14/12 3/3/3
|
||||||
|
f 3/3/3 12/14/12 13/15/13 5/5/5
|
||||||
|
f 5/5/5 13/15/13 14/16/14 7/7/7
|
||||||
|
f 7/7/7 14/16/14 15/17/15 9/9/9
|
||||||
|
f 9/12/9 15/18/15 11/13/11 2/2/2
|
||||||
|
f 11/13/11 16/19/16 17/20/17 12/14/12
|
||||||
|
f 12/14/12 17/20/17 18/21/18 13/15/13
|
||||||
|
f 13/15/13 18/21/18 19/22/19 14/16/14
|
||||||
|
f 14/16/14 19/22/19 20/23/20 15/17/15
|
||||||
|
f 15/18/15 20/24/20 16/19/16 11/13/11
|
||||||
|
f 16/19/16 21/25/21 22/26/22 17/20/17
|
||||||
|
f 17/20/17 22/26/22 23/27/23 18/21/18
|
||||||
|
f 18/21/18 23/27/23 24/28/24 19/22/19
|
||||||
|
f 19/22/19 24/28/24 25/29/25 20/23/20
|
||||||
|
f 20/24/20 25/30/25 21/25/21 16/19/16
|
||||||
|
f 21/25/21 26/31/26 27/32/27 22/26/22
|
||||||
|
f 22/26/22 27/32/27 28/33/28 23/27/23
|
||||||
|
f 23/27/23 28/33/28 29/34/29 24/28/24
|
||||||
|
f 24/28/24 29/34/29 30/35/30 25/29/25
|
||||||
|
f 25/30/25 30/36/30 26/31/26 21/25/21
|
||||||
|
f 26/37/26 31/38/31 32/39/32 27/40/27
|
||||||
|
f 27/40/27 32/39/32 33/41/33 28/42/28
|
||||||
|
f 28/42/28 33/41/33 34/43/34 29/44/29
|
||||||
|
f 29/44/29 34/43/34 35/45/35 30/46/30
|
||||||
|
f 30/47/30 35/48/35 31/38/31 26/37/26
|
||||||
|
f 31/38/31 36/49/36 37/50/37 32/39/32
|
||||||
|
f 32/39/32 37/50/37 38/51/38 33/41/33
|
||||||
|
f 33/41/33 38/51/38 39/52/39 34/43/34
|
||||||
|
f 34/43/34 39/52/39 40/53/40 35/45/35
|
||||||
|
f 35/48/35 40/54/40 36/49/36 31/38/31
|
||||||
|
f 36/49/36 1/1/1 4/4/4 37/50/37
|
||||||
|
f 37/50/37 4/4/4 6/6/6 38/51/38
|
||||||
|
f 38/51/38 6/6/6 8/8/8 39/52/39
|
||||||
|
f 39/52/39 8/8/8 10/10/10 40/53/40
|
||||||
|
f 1/1/1 36/49/36 40/54/40 10/11/10
|
||||||
|
f 41/55/41 42/56/42 43/57/43 44/58/44
|
||||||
|
f 44/59/44 43/60/43 45/61/45 46/62/46
|
||||||
|
f 46/62/46 45/61/45 47/63/47 48/64/48
|
||||||
|
f 48/64/48 47/63/47 49/65/49 50/66/50
|
||||||
|
f 41/55/41 50/66/50 49/65/49 42/56/42
|
||||||
|
f 42/56/42 51/67/51 52/68/52 43/57/43
|
||||||
|
f 43/60/43 52/69/52 53/70/53 45/61/45
|
||||||
|
f 45/61/45 53/70/53 54/71/54 47/63/47
|
||||||
|
f 47/63/47 54/71/54 55/72/55 49/65/49
|
||||||
|
f 49/65/49 55/72/55 51/67/51 42/56/42
|
||||||
|
f 51/67/51 56/73/56 57/74/57 52/68/52
|
||||||
|
f 52/69/52 57/75/57 58/76/58 53/70/53
|
||||||
|
f 53/70/53 58/76/58 59/77/59 54/71/54
|
||||||
|
f 54/71/54 59/77/59 60/78/60 55/72/55
|
||||||
|
f 55/72/55 60/78/60 56/73/56 51/67/51
|
||||||
|
f 56/73/56 61/79/21 62/80/61 57/74/57
|
||||||
|
f 57/75/57 62/81/61 63/82/62 58/76/58
|
||||||
|
f 58/76/58 63/82/62 64/83/63 59/77/59
|
||||||
|
f 59/77/59 64/83/63 65/84/64 60/78/60
|
||||||
|
f 60/78/60 65/84/64 61/79/21 56/73/56
|
||||||
|
f 61/85/21 66/86/65 67/87/66 62/88/61
|
||||||
|
f 62/35/61 67/89/66 68/90/67 63/91/62
|
||||||
|
f 63/91/62 68/90/67 69/92/68 64/93/63
|
||||||
|
f 64/93/63 69/92/68 70/94/69 65/95/64
|
||||||
|
f 65/95/64 70/94/69 66/86/65 61/85/21
|
||||||
|
f 66/86/65 71/96/70 72/97/71 67/87/66
|
||||||
|
f 67/89/66 72/98/71 73/99/72 68/90/67
|
||||||
|
f 68/90/67 73/99/72 74/100/73 69/92/68
|
||||||
|
f 69/92/68 74/100/73 75/101/74 70/94/69
|
||||||
|
f 70/94/69 75/101/74 71/96/70 66/86/65
|
||||||
|
f 71/96/70 76/102/75 77/103/76 72/97/71
|
||||||
|
f 72/98/71 77/104/76 78/105/77 73/99/72
|
||||||
|
f 73/99/72 78/105/77 79/106/78 74/100/73
|
||||||
|
f 74/100/73 79/106/78 80/107/79 75/101/74
|
||||||
|
f 75/101/74 80/107/79 76/102/75 71/96/70
|
||||||
|
f 76/102/75 41/55/41 44/58/44 77/103/76
|
||||||
|
f 77/104/76 44/59/44 46/62/46 78/105/77
|
||||||
|
f 78/105/77 46/62/46 48/64/48 79/106/78
|
||||||
|
f 79/106/78 48/64/48 50/66/50 80/107/79
|
||||||
|
f 41/55/41 76/102/75 80/107/79 50/66/50
|
||||||
|
f 81/108/80 82/109/81 83/110/82 84/111/83
|
||||||
|
f 84/9/83 83/17/82 85/112/78 86/113/48
|
||||||
|
f 86/113/48 85/112/78 87/114/77 88/115/46
|
||||||
|
f 88/115/46 87/114/77 89/116/84 90/117/85
|
||||||
|
f 81/108/80 90/117/85 89/116/84 82/109/81
|
||||||
|
f 82/109/81 91/118/86 92/119/87 83/110/82
|
||||||
|
f 83/17/82 92/23/87 93/120/73 85/112/78
|
||||||
|
f 85/112/78 93/120/73 94/121/72 87/114/77
|
||||||
|
f 87/114/77 94/121/72 95/122/88 89/116/84
|
||||||
|
f 89/116/84 95/122/88 91/118/86 82/109/81
|
||||||
|
f 91/118/86 96/123/65 97/124/69 92/119/87
|
||||||
|
f 92/23/87 97/29/69 98/125/68 93/120/73
|
||||||
|
f 93/120/73 98/125/68 99/126/67 94/121/72
|
||||||
|
f 94/121/72 99/126/67 100/127/66 95/122/88
|
||||||
|
f 95/122/88 100/127/66 96/123/65 91/118/86
|
||||||
|
f 96/123/65 101/85/21 102/88/64 97/124/69
|
||||||
|
f 97/29/69 102/35/64 103/91/63 98/125/68
|
||||||
|
f 98/125/68 103/91/63 104/93/62 99/126/67
|
||||||
|
f 99/126/67 104/93/62 105/95/61 100/127/66
|
||||||
|
f 100/127/66 105/95/61 101/85/21 96/123/65
|
||||||
|
f 101/128/21 106/129/56 107/130/60 102/131/64
|
||||||
|
f 102/46/64 107/45/60 108/132/59 103/133/63
|
||||||
|
f 103/133/63 108/132/59 109/134/58 104/135/62
|
||||||
|
f 104/135/62 109/134/58 110/136/57 105/137/61
|
||||||
|
f 105/137/61 110/136/57 106/129/56 101/128/21
|
||||||
|
f 106/129/56 111/138/89 112/139/90 107/130/60
|
||||||
|
f 107/45/60 112/53/90 113/140/54 108/132/59
|
||||||
|
f 108/132/59 113/140/54 114/141/53 109/134/58
|
||||||
|
f 109/134/58 114/141/53 115/142/91 110/136/57
|
||||||
|
f 110/136/57 115/142/91 111/138/89 106/129/56
|
||||||
|
f 111/138/89 116/143/92 117/144/93 112/139/90
|
||||||
|
f 112/53/90 117/10/93 118/145/47 113/140/54
|
||||||
|
f 113/140/54 118/145/47 119/146/45 114/141/53
|
||||||
|
f 114/141/53 119/146/45 120/147/94 115/142/91
|
||||||
|
f 115/142/91 120/147/94 116/143/92 111/138/89
|
||||||
|
f 116/143/92 81/108/80 84/111/83 117/144/93
|
||||||
|
f 117/10/93 84/9/83 86/113/48 118/145/47
|
||||||
|
f 118/145/47 86/113/48 88/115/46 119/146/45
|
||||||
|
f 119/146/45 88/115/46 90/117/85 120/147/94
|
||||||
|
f 81/108/80 116/143/92 120/147/94 90/117/85
|
||||||
|
f 121/148/95 122/149/96 123/150/97 124/151/98
|
||||||
|
f 124/151/98 123/150/97 125/152/39 126/153/8
|
||||||
|
f 126/153/8 125/152/39 127/154/38 128/155/6
|
||||||
|
f 128/155/6 127/154/38 129/156/99 130/157/100
|
||||||
|
f 121/148/95 130/103/100 129/58/99 122/149/96
|
||||||
|
f 122/149/96 131/158/101 132/159/102 123/150/97
|
||||||
|
f 123/150/97 132/159/102 133/160/34 125/152/39
|
||||||
|
f 125/152/39 133/160/34 134/161/33 127/154/38
|
||||||
|
f 127/154/38 134/161/33 135/162/103 129/156/99
|
||||||
|
f 129/58/99 135/57/103 131/158/101 122/149/96
|
||||||
|
f 131/158/101 136/163/26 137/164/104 132/159/102
|
||||||
|
f 132/159/102 137/164/104 138/165/105 133/160/34
|
||||||
|
f 133/160/34 138/165/105 139/166/28 134/161/33
|
||||||
|
f 134/161/33 139/166/28 140/167/106 135/162/103
|
||||||
|
f 135/57/103 140/68/106 136/163/26 131/158/101
|
||||||
|
f 136/163/26 141/168/21 142/169/25 137/164/104
|
||||||
|
f 137/164/104 142/169/25 143/170/24 138/165/105
|
||||||
|
f 138/165/105 143/170/24 144/171/23 139/166/28
|
||||||
|
f 139/166/28 144/171/23 145/172/22 140/167/106
|
||||||
|
f 140/68/106 145/74/22 141/168/21 136/163/26
|
||||||
|
f 141/168/21 146/173/16 147/174/107 142/169/25
|
||||||
|
f 142/169/25 147/174/107 148/175/19 143/170/24
|
||||||
|
f 143/170/24 148/175/19 149/176/18 144/171/23
|
||||||
|
f 144/171/23 149/176/18 150/177/108 145/172/22
|
||||||
|
f 145/74/22 150/80/108 146/173/16 141/168/21
|
||||||
|
f 146/178/16 151/179/109 152/180/110 147/181/107
|
||||||
|
f 147/181/107 152/180/110 153/182/14 148/183/19
|
||||||
|
f 148/183/19 153/182/14 154/184/13 149/185/18
|
||||||
|
f 149/185/18 154/184/13 155/186/111 150/187/108
|
||||||
|
f 150/88/108 155/87/111 151/179/109 146/178/16
|
||||||
|
f 151/179/109 156/188/112 157/189/113 152/180/110
|
||||||
|
f 152/180/110 157/189/113 158/190/7 153/182/14
|
||||||
|
f 153/182/14 158/190/7 159/191/5 154/184/13
|
||||||
|
f 154/184/13 159/191/5 160/192/114 155/186/111
|
||||||
|
f 155/87/111 160/97/114 156/188/112 151/179/109
|
||||||
|
f 156/188/112 121/148/95 124/151/98 157/189/113
|
||||||
|
f 157/189/113 124/151/98 126/153/8 158/190/7
|
||||||
|
f 158/190/7 126/153/8 128/155/6 159/191/5
|
||||||
|
f 159/191/5 128/155/6 130/157/100 160/192/114
|
||||||
|
f 121/148/95 156/188/112 160/97/114 130/103/100
|
||||||
|
f 161/193/80 162/194/115 163/60/82 164/59/83
|
||||||
|
f 164/195/83 163/196/82 165/197/78 166/198/48
|
||||||
|
f 166/198/48 165/197/78 167/199/77 168/200/46
|
||||||
|
f 168/200/46 167/199/77 169/201/84 170/202/85
|
||||||
|
f 161/193/80 170/202/85 169/201/84 162/194/115
|
||||||
|
f 162/194/115 171/203/86 172/69/87 163/60/82
|
||||||
|
f 163/196/82 172/204/87 173/205/73 165/197/78
|
||||||
|
f 165/197/78 173/205/73 174/206/72 167/199/77
|
||||||
|
f 167/199/77 174/206/72 175/207/88 169/201/84
|
||||||
|
f 169/201/84 175/207/88 171/203/86 162/194/115
|
||||||
|
f 171/203/86 176/208/116 177/75/69 172/69/87
|
||||||
|
f 172/204/87 177/209/69 178/210/68 173/205/73
|
||||||
|
f 173/205/73 178/210/68 179/211/67 174/206/72
|
||||||
|
f 174/206/72 179/211/67 180/212/66 175/207/88
|
||||||
|
f 175/207/88 180/212/66 176/208/116 171/203/86
|
||||||
|
f 176/208/116 181/213/21 182/81/64 177/75/69
|
||||||
|
f 177/209/69 182/214/64 183/215/63 178/210/68
|
||||||
|
f 178/210/68 183/215/63 184/216/62 179/211/67
|
||||||
|
f 179/211/67 184/216/62 185/217/61 180/212/66
|
||||||
|
f 180/212/66 185/217/61 181/213/21 176/208/116
|
||||||
|
f 181/34/21 186/218/117 187/89/60 182/35/64
|
||||||
|
f 182/36/64 187/219/60 188/220/59 183/31/63
|
||||||
|
f 183/31/63 188/220/59 189/221/58 184/32/62
|
||||||
|
f 184/32/62 189/221/58 190/222/57 185/33/61
|
||||||
|
f 185/33/61 190/222/57 186/218/117 181/34/21
|
||||||
|
f 186/218/117 191/223/89 192/98/90 187/89/60
|
||||||
|
f 187/219/60 192/224/90 193/225/54 188/220/59
|
||||||
|
f 188/220/59 193/225/54 194/226/53 189/221/58
|
||||||
|
f 189/221/58 194/226/53 195/227/91 190/222/57
|
||||||
|
f 190/222/57 195/227/91 191/223/89 186/218/117
|
||||||
|
f 191/223/89 196/228/92 197/104/93 192/98/90
|
||||||
|
f 192/224/90 197/229/93 198/230/47 193/225/54
|
||||||
|
f 193/225/54 198/230/47 199/231/45 194/226/53
|
||||||
|
f 194/226/53 199/231/45 200/232/94 195/227/91
|
||||||
|
f 195/227/91 200/232/94 196/228/92 191/223/89
|
||||||
|
f 196/228/92 161/193/80 164/59/83 197/104/93
|
||||||
|
f 197/229/93 164/195/83 166/198/48 198/230/47
|
||||||
|
f 198/230/47 166/198/48 168/200/46 199/231/45
|
||||||
|
f 199/231/45 168/200/46 170/202/85 200/232/94
|
||||||
|
f 161/193/80 196/228/92 200/232/94 170/202/85
|
||||||
|
f 201/233/1 202/234/2 203/235/118 204/236/119
|
||||||
|
f 204/111/119 203/110/118 205/237/5 206/238/6
|
||||||
|
f 206/238/6 205/237/5 207/239/7 208/240/8
|
||||||
|
f 208/240/8 207/239/7 209/241/120 210/242/121
|
||||||
|
f 201/233/1 210/242/121 209/241/120 202/234/2
|
||||||
|
f 202/234/2 211/243/11 212/244/12 203/235/118
|
||||||
|
f 203/110/118 212/119/12 213/245/13 205/237/5
|
||||||
|
f 205/237/5 213/245/13 214/246/14 207/239/7
|
||||||
|
f 207/239/7 214/246/14 215/247/15 209/241/120
|
||||||
|
f 209/241/120 215/247/15 211/243/11 202/234/2
|
||||||
|
f 211/243/11 216/248/16 217/249/108 212/244/12
|
||||||
|
f 212/119/12 217/124/108 218/250/18 213/245/13
|
||||||
|
f 213/245/13 218/250/18 219/251/19 214/246/14
|
||||||
|
f 214/246/14 219/251/19 220/252/107 215/247/15
|
||||||
|
f 215/247/15 220/252/107 216/248/16 211/243/11
|
||||||
|
f 216/248/16 221/185/21 222/187/22 217/249/108
|
||||||
|
f 217/124/108 222/88/22 223/178/23 218/250/18
|
||||||
|
f 218/250/18 223/178/23 224/181/24 219/251/19
|
||||||
|
f 219/251/19 224/181/24 225/183/25 220/252/107
|
||||||
|
f 220/252/107 225/183/25 221/185/21 216/248/16
|
||||||
|
f 221/253/21 226/254/26 227/255/106 222/256/22
|
||||||
|
f 222/131/22 227/130/106 228/257/122 223/258/23
|
||||||
|
f 223/258/23 228/257/122 229/259/29 224/260/24
|
||||||
|
f 224/260/24 229/259/29 230/261/104 225/262/25
|
||||||
|
f 225/262/25 230/261/104 226/254/26 221/253/21
|
||||||
|
f 226/254/26 231/263/31 232/264/32 227/255/106
|
||||||
|
f 227/130/106 232/139/32 233/265/33 228/257/122
|
||||||
|
f 228/257/122 233/265/33 234/266/34 229/259/29
|
||||||
|
f 229/259/29 234/266/34 235/267/123 230/261/104
|
||||||
|
f 230/261/104 235/267/123 231/263/31 226/254/26
|
||||||
|
f 231/263/31 236/268/36 237/269/37 232/264/32
|
||||||
|
f 232/139/32 237/144/37 238/270/124 233/265/33
|
||||||
|
f 233/265/33 238/270/124 239/271/125 234/266/34
|
||||||
|
f 234/266/34 239/271/125 240/272/40 235/267/123
|
||||||
|
f 235/267/123 240/272/40 236/268/36 231/263/31
|
||||||
|
f 236/268/36 201/233/1 204/236/119 237/269/37
|
||||||
|
f 237/144/37 204/111/119 206/238/6 238/270/124
|
||||||
|
f 238/270/124 206/238/6 208/240/8 239/271/125
|
||||||
|
f 239/271/125 208/240/8 210/242/121 240/272/40
|
||||||
|
f 201/233/1 236/268/36 240/272/40 210/242/121
|
62
mods/basic_materials/nodes.lua
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
local S = minetest.get_translator("basic_materials")
|
||||||
|
local sound_api = xcompat.sounds
|
||||||
|
local chains_sbox = {type = "fixed",fixed = { -0.1, -0.5, -0.1, 0.1, 0.5, 0.1 }}
|
||||||
|
|
||||||
|
minetest.register_node("basic_materials:cement_block", {
|
||||||
|
description = S("Cement"),
|
||||||
|
tiles = {"basic_materials_cement_block.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky=2, dig_stone = 1, pickaxey=5},
|
||||||
|
_mcl_hardness=1.6,
|
||||||
|
sounds = sound_api.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("basic_materials:concrete_block", {
|
||||||
|
description = S("Concrete Block"),
|
||||||
|
tiles = {"basic_materials_concrete_block.png",},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky=1, concrete=1, dig_stone = 1, pickaxey=5},
|
||||||
|
_mcl_hardness=1.6,
|
||||||
|
sounds = sound_api.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("basic_materials:chain_steel", {
|
||||||
|
description = S("Chain (steel, hanging)"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "basic_materials_chains.obj",
|
||||||
|
tiles = {"basic_materials_chain_steel.png"},
|
||||||
|
walkable = false,
|
||||||
|
climbable = true,
|
||||||
|
sunlight_propagates = true,
|
||||||
|
paramtype = "light",
|
||||||
|
inventory_image = "basic_materials_chain_steel_inv.png",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky=3, dig_stone = 1, pickaxey=5},
|
||||||
|
_mcl_hardness=1.6,
|
||||||
|
selection_box = chains_sbox,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("basic_materials:chain_brass", {
|
||||||
|
description = S("Chain (brass, hanging)"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "basic_materials_chains.obj",
|
||||||
|
tiles = {"basic_materials_chain_brass.png"},
|
||||||
|
walkable = false,
|
||||||
|
climbable = true,
|
||||||
|
sunlight_propagates = true,
|
||||||
|
paramtype = "light",
|
||||||
|
inventory_image = "basic_materials_chain_brass_inv.png",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky=3, dig_stone = 1, pickaxey=5},
|
||||||
|
_mcl_hardness=1.6,
|
||||||
|
selection_box = chains_sbox,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("basic_materials:brass_block", {
|
||||||
|
description = S("Brass Block"),
|
||||||
|
tiles = { "basic_materials_brass_block.png" },
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky=1, dig_stone = 1, pickaxey=5},
|
||||||
|
_mcl_hardness=1.6,
|
||||||
|
sounds = sound_api.node_sound_metal_defaults()
|
||||||
|
})
|
BIN
mods/basic_materials/textures/basic_materials_aluminum_bar.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
mods/basic_materials/textures/basic_materials_aluminum_strip.png
Normal file
After Width: | Height: | Size: 383 B |
BIN
mods/basic_materials/textures/basic_materials_aluminum_wire.png
Normal file
After Width: | Height: | Size: 258 B |
BIN
mods/basic_materials/textures/basic_materials_brass_block.png
Normal file
After Width: | Height: | Size: 272 B |
BIN
mods/basic_materials/textures/basic_materials_brass_ingot.png
Normal file
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 292 B |
BIN
mods/basic_materials/textures/basic_materials_cement_block.png
Normal file
After Width: | Height: | Size: 243 B |
BIN
mods/basic_materials/textures/basic_materials_chain_brass.png
Normal file
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 1.8 KiB |
BIN
mods/basic_materials/textures/basic_materials_chain_steel.png
Normal file
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 178 B |
After Width: | Height: | Size: 175 B |
BIN
mods/basic_materials/textures/basic_materials_concrete_block.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
mods/basic_materials/textures/basic_materials_copper_strip.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
mods/basic_materials/textures/basic_materials_copper_wire.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
mods/basic_materials/textures/basic_materials_empty_spool.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
mods/basic_materials/textures/basic_materials_energy_crystal.png
Normal file
After Width: | Height: | Size: 817 B |
BIN
mods/basic_materials/textures/basic_materials_gear_steel.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
mods/basic_materials/textures/basic_materials_gold_strip.png
Normal file
After Width: | Height: | Size: 358 B |
BIN
mods/basic_materials/textures/basic_materials_gold_wire.png
Normal file
After Width: | Height: | Size: 286 B |
After Width: | Height: | Size: 369 B |
BIN
mods/basic_materials/textures/basic_materials_ic.png
Normal file
After Width: | Height: | Size: 293 B |
BIN
mods/basic_materials/textures/basic_materials_lead_strip.png
Normal file
After Width: | Height: | Size: 366 B |
BIN
mods/basic_materials/textures/basic_materials_motor.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
mods/basic_materials/textures/basic_materials_oil_extract.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
mods/basic_materials/textures/basic_materials_padlock.png
Normal file
After Width: | Height: | Size: 215 B |
BIN
mods/basic_materials/textures/basic_materials_paraffin.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
mods/basic_materials/textures/basic_materials_plastic_sheet.png
Normal file
After Width: | Height: | Size: 293 B |
BIN
mods/basic_materials/textures/basic_materials_plastic_strip.png
Normal file
After Width: | Height: | Size: 160 B |
BIN
mods/basic_materials/textures/basic_materials_silicon.png
Normal file
After Width: | Height: | Size: 769 B |
BIN
mods/basic_materials/textures/basic_materials_silver_wire.png
Normal file
After Width: | Height: | Size: 251 B |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 280 B |
BIN
mods/basic_materials/textures/basic_materials_steel_bar.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
mods/basic_materials/textures/basic_materials_steel_strip.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
mods/basic_materials/textures/basic_materials_steel_wire.png
Normal file
After Width: | Height: | Size: 284 B |
After Width: | Height: | Size: 775 B |
BIN
mods/basic_materials/textures/basic_materials_wet_cement.png
Normal file
After Width: | Height: | Size: 366 B |
137
mods/fakelib/API.md
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
# API Documentation
|
||||||
|
|
||||||
|
## Quick Links
|
||||||
|
|
||||||
|
- [`fakelib.is_player(x)`](#fakelibis_playerx)
|
||||||
|
- [`fakelib.is_metadata(x)`](#fakelibis_metadatax)
|
||||||
|
- [`fakelib.is_inventory(x)`](#fakelibis_inventoryx)
|
||||||
|
- [`fakelib.is_vector(x, [add_metatable])`](#fakelibis_vectorx-add_metatable)
|
||||||
|
- [`fakelib.create_player([options])`](#fakelibcreate_playeroptions)
|
||||||
|
- [`fakelib.create_inventory([sizes])`](#fakelibcreate_inventorysizes)
|
||||||
|
- [`fakelib.create_metadata([data])`](#fakelibcreate_metadatadata)
|
||||||
|
|
||||||
|
|
||||||
|
## Type checks
|
||||||
|
|
||||||
|
#### **`fakelib.is_player(x)`**
|
||||||
|
|
||||||
|
Checks if a value is a player. Only returns true for real players and `fakelib`'s fake players.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `x` - Any value. The value to be checked.
|
||||||
|
|
||||||
|
#### **`fakelib.is_inventory(x)`**
|
||||||
|
|
||||||
|
Checks if a value is an inventory. Only returns true for real inventories and `fakelib`'s fake inventories.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `x` - Any value. The value to be checked.
|
||||||
|
|
||||||
|
#### **`fakelib.is_metadata(x)`**
|
||||||
|
|
||||||
|
Checks if a value is metadata. Only returns true for real metadata and `fakelib`'s fake metadata.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `x` - Any value. The value to be checked.
|
||||||
|
|
||||||
|
#### **`fakelib.is_vector(x, [add_metatable])`**
|
||||||
|
|
||||||
|
Checks if a value is a vector. Returns true for any table with `x`, `y`, and `z` values that are numbers.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `x` - Any value. The value to be checked.
|
||||||
|
- `add_metatable` - Boolean, optional. Add the vector metatable to basic vectors.
|
||||||
|
|
||||||
|
|
||||||
|
## Creation
|
||||||
|
|
||||||
|
#### **`fakelib.create_player([options])`**
|
||||||
|
|
||||||
|
Creates a new fake player.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `options` - Definition table, optional. Specifies player data. See [`options`](#options) below. Can also be a string as shorthand to set the player name only.
|
||||||
|
|
||||||
|
#### **`fakelib.create_inventory([sizes])`**
|
||||||
|
|
||||||
|
Creates a new fake player.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `sizes` - Definition table, optional. Specifies list names and sizes. See [`sizes`](#sizes) below.
|
||||||
|
|
||||||
|
#### **`fakelib.create_metadata([data])`**
|
||||||
|
|
||||||
|
Creates a new fake player.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- `data` - Definition table, optional. Specifies metadata keys and values. See [`data`](#data) below.
|
||||||
|
|
||||||
|
|
||||||
|
## Definition tables.
|
||||||
|
|
||||||
|
|
||||||
|
#### **`options`**
|
||||||
|
|
||||||
|
Specifies player data. Used by [`fakelib.create_player([options])`](#fakelibcreate_playeroptions).
|
||||||
|
|
||||||
|
All values are optional.
|
||||||
|
|
||||||
|
- `name` - String. Player name. Unlike real player names, this can contain any characters.
|
||||||
|
- `position` - Vector. Player position.
|
||||||
|
- `direction` - Vector. Player look direction.
|
||||||
|
- `controls` - Table. Player controls. Uses the same format returned by `player:get_player_controls()`.
|
||||||
|
- `metadata` - Metadata. Player metadata. Can be fake metadata or a reference to real metadata.
|
||||||
|
- `inventory` - Inventory. Player inventory. Can be a fake inventory or a reference to a real inventory.
|
||||||
|
- `wield_list` - String. Selected inventory list. Must be a list that exists in the player's inventory.
|
||||||
|
- `wield_index` - Number. Selected list index. Must be an index that exists in the selected list.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
local options = {
|
||||||
|
name = "sam",
|
||||||
|
position = vector.new(1, 5, 3),
|
||||||
|
direction = vector(1, 0, 0),
|
||||||
|
controls = {sneak = true},
|
||||||
|
}
|
||||||
|
local player = fakelib.create_player(options)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **`sizes`**
|
||||||
|
|
||||||
|
Specifies list names and sizes. Used by [`fakelib.create_inventory([sizes])`](#fakelibcreate_inventorysizes).
|
||||||
|
|
||||||
|
List names must be strings, and list sizes must be numbers greater than zero.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
local sizes = {
|
||||||
|
main = 32,
|
||||||
|
craft = 9,
|
||||||
|
craftpreview = 1,
|
||||||
|
craftresult = 1,
|
||||||
|
}
|
||||||
|
local inv = fakelib.create_inventory(sizes)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **`data`**
|
||||||
|
|
||||||
|
Specifies metadata keys and values. Used by [`fakelib.create_metadata([data])`](#fakelibcreate_metadatadata).
|
||||||
|
|
||||||
|
Keys must be strings, and values must be strings or numbers.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
local data = {
|
||||||
|
enabled = "true",
|
||||||
|
energy = 300,
|
||||||
|
}
|
||||||
|
local meta = fakelib.create_metadata(data)
|
||||||
|
```
|
21
mods/fakelib/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 OgelGames
|
||||||
|
|
||||||
|
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.
|
26
mods/fakelib/README.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Minetest fake userdata library [fakelib]
|
||||||
|
|
||||||
|
[](https://github.com/OgelGames/fakelib/actions)
|
||||||
|
[](LICENSE.md)
|
||||||
|
[](https://www.minetest.net)
|
||||||
|
[](https://content.minetest.net/packages/OgelGames/fakelib/)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This mod is a code library for creating fake userdata (players, inventories and metadata), replicating their functionality as closely as possible.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Simply add `fakelib` to your mod's dependencies, and call any of the API functions from your code.
|
||||||
|
|
||||||
|
See [API.md](API.md) for detailed documentation.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Download the [master branch](https://github.com/OgelGames/fakelib/archive/master.zip) or the [latest release](https://github.com/OgelGames/fakelib/releases), and follow [the usual installation steps](https://wiki.minetest.net/Installing_Mods).
|
||||||
|
|
||||||
|
Alternatively, you can download and install the mod from [ContentDB](https://content.minetest.net/packages/OgelGames/fakelib) or the online content tab in Minetest.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
All code is licensed under the [MIT License](LICENSE).
|
53
mods/fakelib/init.lua
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
fakelib = {}
|
||||||
|
|
||||||
|
local function check(n, v, a, b)
|
||||||
|
local t = type(v)
|
||||||
|
if t == a or t == b then
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
local info = debug.getinfo(2, "n")
|
||||||
|
local f = info.name or "?"
|
||||||
|
if info.namewhat ~= "method" then
|
||||||
|
-- Offset argument number when called using '.' instead of ':'
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
error(string.format("bad argument #%i to '%s' (%s expected, got %s)", n, f, a, t), 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function secure_table(t, index, id)
|
||||||
|
setmetatable(t, {
|
||||||
|
__index = index,
|
||||||
|
__newindex = {},
|
||||||
|
__metatable = id,
|
||||||
|
})
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = minetest.get_modpath("fakelib")
|
||||||
|
|
||||||
|
for _,file in pairs({"metadata", "inventory", "player"}) do
|
||||||
|
loadfile(path.."/"..file..".lua")(check, secure_table)
|
||||||
|
end
|
||||||
|
|
||||||
|
dofile(path.."/misc.lua")
|
||||||
|
|
||||||
|
-- Tests are not included in releases, so check for them before registering the command.
|
||||||
|
|
||||||
|
local tests = loadfile(path.."/tests.lua")
|
||||||
|
|
||||||
|
if tests and minetest.is_singleplayer() then
|
||||||
|
minetest.register_chatcommand("fakelib_test", {
|
||||||
|
description = "Test fakelib's API.",
|
||||||
|
params = "[<run error tests>]",
|
||||||
|
func = function(_, param)
|
||||||
|
local start_time = minetest.get_us_time()
|
||||||
|
local success = tests(param == "true")
|
||||||
|
local end_time = minetest.get_us_time()
|
||||||
|
if success then
|
||||||
|
return true, string.format("Testing completed in %i us", end_time - start_time)
|
||||||
|
end
|
||||||
|
return true, "Testing failed. See console for errors."
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
302
mods/fakelib/inventory.lua
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
|
||||||
|
local fake_inventory = {}
|
||||||
|
local identifier = "fakelib:inventory"
|
||||||
|
local check, secure_table = ...
|
||||||
|
|
||||||
|
-- API functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
function fakelib.is_inventory(x)
|
||||||
|
if type(x) == "userdata" and x.get_lists then
|
||||||
|
return true
|
||||||
|
elseif type(x) == "table" and getmetatable(x) == identifier then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function fakelib.create_inventory(sizes)
|
||||||
|
local lists = {}
|
||||||
|
if type(sizes) == "table" then
|
||||||
|
for listname, size in pairs(sizes) do
|
||||||
|
if type(listname) == "string" and type(size) == "number" and size > 0 then
|
||||||
|
local list = {}
|
||||||
|
for i=1, size do
|
||||||
|
list[i] = ItemStack()
|
||||||
|
end
|
||||||
|
lists[listname] = list
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return secure_table({lists = lists}, fake_inventory, identifier)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
local function copy_list(list)
|
||||||
|
local copy = {}
|
||||||
|
for i=1, #list do
|
||||||
|
copy[i] = ItemStack(list[i])
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
local function stack_matches(a, b, match_meta)
|
||||||
|
if a:get_name() ~= b:get_name() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if match_meta then
|
||||||
|
if a:get_wear() ~= b:get_wear() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return a:get_meta():equals(b:get_meta())
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inventory functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
function fake_inventory:is_empty(listname)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or #list == 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
for _,stack in ipairs(list) do
|
||||||
|
if not stack:is_empty() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:get_size(listname)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
return list and #list or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:set_size(listname, size)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
check(2, size, "number")
|
||||||
|
listname = tostring(listname)
|
||||||
|
if size ~= size or size < 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
size = math.floor(size)
|
||||||
|
if size == 0 then
|
||||||
|
self.lists[listname] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local list = self.lists[listname] or {}
|
||||||
|
if #list < size then
|
||||||
|
for i=#list+1, size do
|
||||||
|
list[i] = ItemStack()
|
||||||
|
end
|
||||||
|
elseif #list > size then
|
||||||
|
for i=size+1, #list do
|
||||||
|
list[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.lists[listname] = list
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:get_width(listname)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
return list and list.width or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:set_width(listname, width)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
check(2, width, "number")
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or width ~= width or width < 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
width = math.floor(width)
|
||||||
|
list.width = width > 0 and width or nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:get_stack(listname, i)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
check(2, i, "number")
|
||||||
|
i = math.floor(i)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or not list[i] then
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
return ItemStack(list[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:set_stack(listname, i, stack)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
check(2, i, "number")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
i = math.floor(i)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or not list[i] or stack:is_empty() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
list[i] = stack
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:get_list(listname)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
return list and copy_list(list) or nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:set_list(listname, list)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
listname = tostring(listname)
|
||||||
|
if list == nil then
|
||||||
|
self.lists[listname] = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
check(2, list, "table")
|
||||||
|
local new_list, size = {}, 0
|
||||||
|
for i,s in pairs(list) do
|
||||||
|
check(4, i, "number")
|
||||||
|
if i > size then
|
||||||
|
size = i
|
||||||
|
end
|
||||||
|
new_list[i] = ItemStack(s)
|
||||||
|
end
|
||||||
|
for i=1, size do
|
||||||
|
if not new_list[i] then
|
||||||
|
new_list[i] = ItemStack()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.lists[listname] = new_list
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:get_lists()
|
||||||
|
local lists = {}
|
||||||
|
for listname, list in pairs(self.lists) do
|
||||||
|
lists[listname] = copy_list(list)
|
||||||
|
end
|
||||||
|
return lists
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:set_lists(lists)
|
||||||
|
check(1, lists, "table")
|
||||||
|
local new_lists = {}
|
||||||
|
for listname, list in pairs(lists) do
|
||||||
|
check(3, listname, "string", "number")
|
||||||
|
check(3, list, "table")
|
||||||
|
listname = tostring(listname)
|
||||||
|
local new_list, size = {}, 0
|
||||||
|
for i,s in pairs(list) do
|
||||||
|
check(5, i, "number")
|
||||||
|
if i > size then
|
||||||
|
size = i
|
||||||
|
end
|
||||||
|
new_list[i] = ItemStack(s)
|
||||||
|
end
|
||||||
|
for i=1, size do
|
||||||
|
if not new_list[i] then
|
||||||
|
new_list[i] = ItemStack()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
new_lists[listname] = new_list
|
||||||
|
end
|
||||||
|
self.lists = new_lists
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:add_item(listname, stack)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or #list == 0 or stack:is_empty() then
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
local empty = {}
|
||||||
|
for _,s in ipairs(list) do
|
||||||
|
if s:is_empty() then
|
||||||
|
table.insert(empty, s)
|
||||||
|
else
|
||||||
|
stack = s:add_item(stack)
|
||||||
|
if stack:is_empty() then
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _,s in ipairs(empty) do
|
||||||
|
stack = s:add_item(stack)
|
||||||
|
if stack:is_empty() then
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:room_for_item(listname, stack)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or #list == 0 or stack:is_empty() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for _,s in ipairs(copy_list(list)) do
|
||||||
|
stack = s:add_item(stack)
|
||||||
|
if stack:is_empty() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:contains_item(listname, stack, match_meta)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or stack:is_empty() or stack:is_empty() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local count = stack:get_count()
|
||||||
|
for _,s in ipairs(list) do
|
||||||
|
if stack_matches(stack, s, match_meta) then
|
||||||
|
count = count - s:get_count()
|
||||||
|
if count <= 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory:remove_item(listname, stack)
|
||||||
|
check(1, listname, "string", "number")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
local list = self.lists[tostring(listname)]
|
||||||
|
if not list or #list == 0 or stack:is_empty() then
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local name, remaining, removed = stack:get_name(), stack:get_count()
|
||||||
|
for i=#list, 1, -1 do
|
||||||
|
local s = list[i]
|
||||||
|
if s:get_name() == name then
|
||||||
|
s = s:take_item(remaining)
|
||||||
|
remaining = remaining - s:get_count()
|
||||||
|
if not removed then
|
||||||
|
removed = s
|
||||||
|
else
|
||||||
|
removed:set_count(removed:get_count() + s:get_count())
|
||||||
|
end
|
||||||
|
if remaining == 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return removed or ItemStack()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_inventory.get_location()
|
||||||
|
return {type = "undefined"}
|
||||||
|
end
|
134
mods/fakelib/metadata.lua
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
local fake_metadata = {}
|
||||||
|
local identifier = "fakelib:metadata"
|
||||||
|
local check, secure_table = ...
|
||||||
|
|
||||||
|
-- API functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
function fakelib.is_metadata(x)
|
||||||
|
if type(x) == "userdata" and x.get_keys then
|
||||||
|
return true
|
||||||
|
elseif type(x) == "table" and getmetatable(x) == identifier then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function fakelib.create_metadata(data)
|
||||||
|
local fields = {}
|
||||||
|
if type(data) == "table" then
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
if type(k) == "string" and type(v) == "string" then
|
||||||
|
fields[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return secure_table({fields = fields}, fake_metadata, identifier)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Metadata functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
function fake_metadata:contains(key)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
return self.fields[key] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:get(key)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
return self.fields[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:set_string(key, value)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
check(2, value, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
value = tostring(value)
|
||||||
|
if value == "" then
|
||||||
|
self.fields[key] = nil
|
||||||
|
end
|
||||||
|
self.fields[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:get_string(key)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
return self.fields[key] or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:set_int(key, value)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
check(2, value, "number")
|
||||||
|
key = tostring(key)
|
||||||
|
if value >= 2^31 then
|
||||||
|
value = 0
|
||||||
|
end
|
||||||
|
self.fields[key] = string.format("%i", value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:get_int(key)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
return tonumber(self.fields[key]) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:set_float(key, value)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
check(2, value, "number")
|
||||||
|
key = tostring(key)
|
||||||
|
self.fields[key] = string.format("%s", value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:get_float(key)
|
||||||
|
check(1, key, "string", "number")
|
||||||
|
key = tostring(key)
|
||||||
|
return tonumber(self.fields[key]) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:get_keys()
|
||||||
|
local keys = {}
|
||||||
|
for key in pairs(self.fields) do
|
||||||
|
table.insert(keys, key)
|
||||||
|
end
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:to_table()
|
||||||
|
return {fields = table.copy(self.fields)}
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:from_table(data)
|
||||||
|
if type(data) ~= "table" or type(data.fields) ~= "table" then
|
||||||
|
self.fields = {}
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local fields = {}
|
||||||
|
for k,v in pairs(data.fields) do
|
||||||
|
check(4, k, "string")
|
||||||
|
check(5, v, "string", "number")
|
||||||
|
fields[k] = tostring(v)
|
||||||
|
end
|
||||||
|
self.fields = fields
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function fake_metadata:equals(other)
|
||||||
|
if not fakelib.is_metadata(other) then
|
||||||
|
check(1, other, "MetaDataRef")
|
||||||
|
end
|
||||||
|
local fields = other:to_table().fields
|
||||||
|
for k,v in pairs(self.fields) do
|
||||||
|
if fields[k] == v then
|
||||||
|
fields[k] = nil
|
||||||
|
elseif fields[k] ~= nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if next(fields) == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|