diff --git a/functions.php b/functions.php index ee0f9d51..0f502790 100755 --- a/functions.php +++ b/functions.php @@ -155,6 +155,7 @@ function settingsForm() { Server Desc:
Server Website:
Server MOTD:
+ Default Privs:
Spawnpoint (Format example: '32, 20, -140')

Player Transfer Distance (Value in chunks, 0 = unlimited)

diff --git a/index.php b/index.php index 75a269ec..9bb49735 100755 --- a/index.php +++ b/index.php @@ -304,6 +304,11 @@ else if(isset($_GET['do'])) file_put_contents("mtm_db/worlds/$userid/minetest.conf", "player_transfer_distance = " . $_POST['playertransferdistance'] . "\n", FILE_APPEND); } + // default_privs + if(isset($_POST['defaultprivs']) && $_POST['defaultprivs']!="") { + file_put_contents("mtm_db/worlds/$userid/minetest.conf", "default_privs = " . $_POST['defaultprivs'] . "\n", FILE_APPEND); + } + header("Location: index.php?do=manage"); } else { echo "Shut down server before configuration..."; diff --git a/mods/areas/README.md b/mods/areas/README.md new file mode 100644 index 00000000..2a69ac93 --- /dev/null +++ b/mods/areas/README.md @@ -0,0 +1,63 @@ +simple_protection +================= + +A Minetest area protection mod, based on a fixed claim grid, +like seen in [landrush](https://github.com/Bremaweb/landrush). + +You can claim areas by punching those with a claim stick. + +![Screenshot](https://raw.githubusercontent.com/SmallJoker/simple_protection/master/screenshot.png) + + +License: CC0 + +**Dependencies** +- Minetest 5.0.0+ +- default: Crafting recipes + +**Optional dependencies** +- [areas](https://github.com/ShadowNinja/areas): HUD compatibility + + +Features +-------- + +- Easy, single-click protection +- Fixed claim grid: 16x80x16 by default + - To configure: see `default_settings.lua` header text +- Minimap-like radar to see areas nearby +- Visual area border feedback, as seen in the [protector](https://github.com/tenplus1/protector) mod +- List of claimed areas +- Shared Chest for exchanging items +- Translation support +- Optional setting to require an area before digging + + +Chat command(s) +-------------- + +``` +/area [ ...] + show -> Provides information about the current area + radar -> Displays a minimap-like area overview + share -> Shares the current area with + unshare -> Unshares the current area with + shareall -> Shares all your areas with + unshareall -> Unshares all your areas with + list [] -> Lists all areas (optional ) + unclaim -> Unclaims the current area + delete -> Removes all areas of (requires "server" privilege) +``` + + +About "/area show" +------------------ + +Area status: Not claimable +- Shown when the area can not be claimed +- Happens (by default) in the underground + +Players with access: foo, bar*, leprechaun, *all +- foo, leprechaun: Regular single area share +- bar*: Has access to all areas with the same owner +- *all: Everybody can build and dig in the area diff --git a/mods/areas/chest.lua b/mods/areas/chest.lua new file mode 100644 index 00000000..d295b853 --- /dev/null +++ b/mods/areas/chest.lua @@ -0,0 +1,80 @@ +local S = s_protect.translator + +-- A shared chest for simple_protection but works with other protection mods too + +local function get_item_count(pos, player, count) + local name = player and player:get_player_name() + if not name or minetest.is_protected(pos, name) then + return 0 + end + return count +end + +local tex_mod = "^[colorize:#FF2:50" +minetest.register_node("simple_protection:chest", { + description = S("Shared Chest") .. " " .. S("(by protection)"), + tiles = { + "default_chest_top.png" .. tex_mod, + "default_chest_top.png" .. tex_mod, + "default_chest_side.png" .. tex_mod, + "default_chest_side.png" .. tex_mod, + "default_chest_side.png" .. tex_mod, + "default_chest_lock.png" .. tex_mod + }, + paramtype2 = "facedir", + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 2, oddly_breakable_by_hand = 2}, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Shared Chest")) + meta:set_string("formspec", + "size[8,9]" .. + default.gui_bg .. + default.gui_bg_img .. + "list[context;main;0,0.3;8,4;]" .. + "list[current_player;main;0,5;8,4;]" .. + "listring[context;main]" .. + "listring[current_player;main]" + ) + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + end, + can_dig = function(pos, player) + return minetest.get_meta(pos):get_inventory():is_empty("main") + end, + on_blast = function() end, + + allow_metadata_inventory_put = function(pos, fl, fi, stack, player) + return get_item_count(pos, player, stack:get_count()) + end, + allow_metadata_inventory_take = function(pos, fl, fi, stack, player) + return get_item_count(pos, player, stack:get_count()) + end, + allow_metadata_inventory_move = function(pos, fl, fi, tl, ti, count, player) + return get_item_count(pos, player, count) + end, + on_metadata_inventory_put = function(pos, fl, fi, stack, player) + minetest.log("action", player:get_player_name() + .. " moves " .. stack:get_name() .. " to shared chest at " + .. minetest.pos_to_string(pos)) + end, + on_metadata_inventory_take = function(pos, fl, fi, stack, player) + minetest.log("action", player:get_player_name() + .. " takes " .. stack:get_name() .. " from shared chest at " + .. minetest.pos_to_string(pos)) + end, + -- on_metadata_inventory_move logging is redundant: Same chest contents +}) + +minetest.register_craft({ + type = "shapeless", + output = "simple_protection:shared_chest", + recipe = { "simple_protection:claim", "default:chest_locked" } +}) + +minetest.register_craft({ + type = "shapeless", + output = "simple_protection:shared_chest", + recipe = { "simple_protection:claim", "default:chest" } +}) \ No newline at end of file diff --git a/mods/areas/command_mgr.lua b/mods/areas/command_mgr.lua new file mode 100644 index 00000000..7df9a70c --- /dev/null +++ b/mods/areas/command_mgr.lua @@ -0,0 +1,293 @@ +local S = s_protect.translator + +local commands = {} + +function s_protect.register_subcommand(name, func) + if commands[name] then + minetest.log("info", "[simple_protection] Overwriting chat command " .. name) + end + + assert(#name:split(" ") == 1, "Invalid name") + assert(type(func) == "function") + + commands[name] = func +end + +minetest.register_chatcommand("area", { + description = S("Manages all of your areas."), + privs = {interact = true}, + func = function(name, param) + if param == "" or param == "help" then + local function chat_send(desc, cmd) + minetest.chat_send_player(name, S(desc) .. ": " + .. minetest.colorize("#0FF", cmd)) + end + local privs = minetest.get_player_privs(name) + minetest.chat_send_player(name, minetest.colorize("#0F0", + "=> " .. S("Available area commands"))) + + chat_send("Information about this area", "/area show") + chat_send("View of surrounding areas", "/area radar") + chat_send("(Un)share one area", "/area (un)share ") + chat_send("(Un)share all areas", "/area (un)shareall ") + if s_protect.area_list or privs.simple_protection then + chat_send("List claimed areas", "/area list []") + end + chat_send("Unclaim this area", "/area unclaim") + if privs.server then + chat_send("Delete all areas of a player", "/area delete ") + end + return + end + + local args = param:split(" ", 2) + local func = commands[args[1]] + if not func then + return false, S("Unknown command parameter: @1. Check '/area' for correct usage.", args[1]) + end + + return func(name, args[2]) + end, +}) + +s_protect.register_subcommand("show", function(name, param) + local player = minetest.get_player_by_name(name) + local player_pos = player:get_pos() + local data = s_protect.get_claim(player_pos) + + minetest.add_entity(s_protect.get_center(player_pos), "simple_protection:marker") + local minp, maxp = s_protect.get_area_bounds(player_pos) + minetest.chat_send_player(name, S("Vertical from Y @1 to @2", + tostring(minp.y), tostring(maxp.y))) + + if not data then + if s_protect.underground_limit and minp.y < s_protect.underground_limit then + return true, S("Area status: @1", S("Not claimable")) + end + return true, S("Area status: @1", S("Unowned (!)")) + end + + minetest.chat_send_player(name, S("Area status: @1", S("Owned by @1", data.owner))) + local text = "" + for i, player in ipairs(data.shared) do + text = text..player..", " + end + local shared = s_protect.share[data.owner] + if shared then + for i, player in ipairs(shared) do + text = text..player.."*, " + end + end + + if text ~= "" then + return true, S("Players with access: @1", text) + end +end) + +local function check_ownership(name) + local player = minetest.get_player_by_name(name) + local data, index = s_protect.get_claim(player:get_pos()) + if not data then + return false, S("This area is not claimed yet.") + end + local priv = minetest.check_player_privs(name, {simple_protection=true}) + if name ~= data.owner and not priv then + return false, S("You do not own this area.") + end + return true, data, index +end + +local function table_erase(t, e) + if not t or not e then + return false + end + local removed = false + for i, v in ipairs(t) do + if v == e then + table.remove(t, i) + removed = true + end + end + return removed +end + +s_protect.register_subcommand("share", function(name, param) + if not param or name == param then + return false, S("No player name given.") + end + if not minetest.builtin_auth_handler.get_auth(param) and param ~= "*all" then + return false, S("Unknown player.") + end + local success, data, index = check_ownership(name) + if not success then + return success, data + end + + if s_protect.is_shared(name, param) then + return true, S("@1 already has access to all your areas.", param) + end + + if s_protect.is_shared(data, param) then + return true, S("@1 already has access to this area.", param) + end + table.insert(data.shared, param) + s_protect.set_claim(data, index) + + if minetest.get_player_by_name(param) then + minetest.chat_send_player(param, S("@1 shared an area with you.", name)) + end + return true, S("@1 has now access to this area.", param) +end) + +s_protect.register_subcommand("unshare", function(name, param) + if not param or name == param or param == "" then + return false, S("No player name given.") + end + local success, data, index = check_ownership(name) + if not success then + return success, data + end + if not s_protect.is_shared(data, param) then + return true, S("That player has no access to this area.") + end + table_erase(data.shared, param) + s_protect.set_claim(data, index) + + if minetest.get_player_by_name(param) then + minetest.chat_send_player(param, S("@1 unshared an area with you.", name)) + end + return true, S("@1 has no longer access to this area.", param) +end) + +s_protect.register_subcommand("shareall", function(name, param) + if not param or name == param or param == "" then + return false, S("No player name given.") + end + if not minetest.builtin_auth_handler.get_auth(param) then + if param == "*all" then + return false, S("You can not share all your areas with everybody.") + end + return false, S("Unknown player.") + end + + if s_protect.is_shared(name, param) then + return true, S("@1 already has now access to all your areas.", param) + end + if not shared then + s_protect.share[name] = {} + end + table.insert(s_protect.share[name], param) + s_protect.save_share_db() + + if minetest.get_player_by_name(param) then + minetest.chat_send_player(param, S("@1 shared all areas with you.", name)) + end + return true, S("@1 has now access to all your areas.", param) +end) + +s_protect.register_subcommand("unshareall", function(name, param) + if not param or name == param or param == "" then + return false, S("No player name given.") + end + local removed = false + local shared = s_protect.share[name] + if table_erase(shared, param) then + removed = true + s_protect.save_share_db() + end + + -- Unshare each single claim + local claims = s_protect.get_player_claims(name) + for index, data in pairs(claims) do + if table_erase(data.shared, param) then + removed = true + end + end + if not removed then + return false, S("@1 does not have access to any of your areas.", param) + end + s_protect.update_claims(claims) + if minetest.get_player_by_name(param) then + minetest.chat_send_player(param, S("@1 unshared all areas with you.", name)) + end + return true, S("@1 has no longer access to your areas.", param) +end) + +s_protect.register_subcommand("unclaim", function(name) + local success, data, index = check_ownership(name) + if not success then + return success, data + end + if s_protect.claim_return and name == data.owner then + local player = minetest.get_player_by_name(name) + local inv = player:get_inventory() + if inv:room_for_item("main", "simple_protection:claim") then + inv:add_item("main", "simple_protection:claim") + end + end + s_protect.set_claim(nil, index) + return true, S("This area is unowned now.") +end) + +s_protect.register_subcommand("delete", function(name, param) + if not param or name == param or param == "" then + return false, S("No player name given.") + end + if not minetest.check_player_privs(name, {server=true}) then + return false, S("Missing privilege: @1", "server") + end + + local removed = {} + if s_protect.share[param] then + s_protect.share[param] = nil + table.insert(removed, S("Globally shared areas")) + s_protect.save_share_db() + end + + -- Delete all claims + local claims, count = s_protect.get_player_claims(param) + for index in pairs(claims) do + claims[index] = false + end + s_protect.update_claims(claims) + + if count > 0 then + table.insert(removed, S("@1 claimed area(s)", tostring(count))) + end + + if #removed == 0 then + return false, S("@1 does not own any claimed areas.", param) + end + return true, S("Removed")..": "..table.concat(removed, ", ") +end) + +s_protect.register_subcommand("list", function(name, param) + local has_sp_priv = minetest.check_player_privs(name, {simple_protection=true}) + if not s_protect.area_list and not has_sp_priv then + return false, S("This command is not available.") + end + if not param or param == "" then + param = name + end + if not has_sp_priv and param ~= name then + return false, S("Missing privilege: @1", "simple_protection") + end + + local list = {} + local width = s_protect.claim_size + local height = s_protect.claim_height + + local claims = s_protect.get_player_claims(param) + for index in pairs(claims) do + -- TODO: Add database-specific function to convert the index to a position + local abs_pos = minetest.string_to_pos(index) + table.insert(list, string.format("%5i,%5i,%5i", + abs_pos.x * width + (width / 2), + abs_pos.y * height - s_protect.start_underground + (height / 2), + abs_pos.z * width + (width / 2) + )) + end + + local text = S("Listing all areas of @1. Amount: @2", param, tostring(#list)) + return true, text.."\n"..table.concat(list, "\n") +end) diff --git a/mods/areas/database_lsqlite.lua b/mods/areas/database_lsqlite.lua new file mode 100644 index 00000000..a7382bb0 --- /dev/null +++ b/mods/areas/database_lsqlite.lua @@ -0,0 +1,130 @@ +--[[ +File: database_raw.lua + +lSQLite database functions: + load_db() + save_share_db() + get_claim(, direct access) + set_claim(data, index) + get_player_claims(player name) + update_claims(claims table) +]] + +local worldpath = minetest.get_worldpath() + +local ie = minetest.request_insecure_environment() +if not ie then + error("Cannot access insecure environment!") +end + +local sql = ie.require("lsqlite3") +-- Remove public table +if sqlite3 then + sqlite3 = nil +end + +local db = sql.open(worldpath .. "/s_protect.sqlite3") + +local function sql_exec(q) + if db:exec(q) ~= sql.OK then + minetest.log("info", "[simple_protection] lSQLite: " .. db:errmsg()) + end +end + +local function sql_row(q) + q = q .. " LIMIT 1;" + for row in db:nrows(q) do + return row + end +end + +sql_exec([[ +CREATE TABLE IF NOT EXISTS claims ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + x INTEGER, + y INTEGER, + z INTEGER, + owner TEXT, + shared TEXT, + data TEXT +); +CREATE TABLE IF NOT EXISTS shares ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + owner TEXT, + shared TEXT, + data TEXT +); +]]) + +function s_protect.load_db() end +function s_protect.load_shareall() end +function s_protect.save_share_db() end + +function s_protect.set_claim(cpos, claim) + local id, row = s_protect.get_claim(cpos) + + if not claim then + if not id then + -- Claim never existed + return + end + + -- Remove claim + sql_exec( + ("DELETE FROM claims WHERE id = %i LIMIT 1;"):format(id) + ) + end + + if id then + local vals = {} + for k, v in pairs(claim) do + if row[k] ~= v and type(v) == "string" then + vals[#vals + 1] = ("%s = `%s`"):format(k, v) + end + end + if #vals == 0 then + return + end + sql_exec( + ("UPDATE claims SET %s WHERE id = %i LIMIT 1;") + :format(table.concat(vals, ","), id) + ) + else + sql_exec( + ("INSERT INTO claims VALUES (%i, %i, %i, %s, %s, %s);") + :format(pos.x, pos.y, pos.z, claim.owner, + claim.shared or "", claim.data or "") + ) + end +end + +function s_protect.get_claim(cpos) + local q + if type(pos) == "number" then + -- Direct index + q = "id = " .. cpos + else + q = ("x = %i AND y = %i AND z = %z"):format(cpos.x, cpos.y, cpos.z) + end + local row = sql_row("SELECT id, owner, shared, data FROM claims WHERE " .. q) + if not row then + return + end + + local id = row.id + row.id = nil + return id, row +end + +function s_protect.get_player_claims(owner) + local q = ("SELECT * FROM claims WHERE owner = %s;"):format(owner) + local vals = {} + for row in db:nrows(q) do + vals[#vals + 1] = row + end + return vals +end + +function s_protect.update_claims(updated) + error("Inefficient. To be removed.") +end diff --git a/mods/areas/database_raw.lua b/mods/areas/database_raw.lua new file mode 100644 index 00000000..26308168 --- /dev/null +++ b/mods/areas/database_raw.lua @@ -0,0 +1,167 @@ +--[[ +File: database_raw.lua + +Raw text format database functions: + load_db() + save_share_db() + get_claim(, direct access) + set_claim(data, index) + get_player_claims(player name) + update_claims(claims table) +]] + +local claim_data = {} +local claim_db = { time = os.time(), dirty = false } +local share_db = { time = os.time(), dirty = false } + +function s_protect.load_db() + -- Don't forget the "parties" + s_protect.load_shareall() + + local file = io.open(s_protect.file, "r") + if not file then + return + end + for line in file:lines() do + local data = line:split(" ") + if #data >= 2 then + -- Line format: pos, owner, shared_player, shared_player2, .. + local _shared = {} + for index = 3, #data do + if data[index] ~= "" then + table.insert(_shared, data[index]) + end + end + claim_data[data[1]] = {owner=data[2], shared=_shared} + end + end + io.close(file) + minetest.log("action", "[simple_protection] Loaded claim data") +end + +function s_protect.load_shareall() + local file = io.open(s_protect.sharefile, "r") + if not file then + return + end + for line in file:lines() do + if line ~= "" then + local data = line:split(" ") + -- Line format: owner, shared_player, shared_player2, .. + local _shared = {} + if #data > 1 then + for index = 2, #data do + if data[index] ~= "" then + table.insert(_shared, data[index]) + end + end + s_protect.share[data[1]] = _shared + end + end + end + io.close(file) + minetest.log("action", "[simple_protection] Loaded shared claims") +end + +local function delay(db_info, func) + local dtime = os.time() - db_info.time + if dtime < 6 then + -- Excessive save requests. Delay them. + if not db_info.dirty then + minetest.after(6 - dtime, func) + end + db_info.dirty = true + return true + end + db_info.time = os.time() + db_info.dirty = false +end + +local function save_claims() + if delay(claim_db, save_claims) then + return + end + + local contents = {} + for pos, data in pairs(claim_data) do + if data.owner and data.owner ~= "" then + contents[#contents + 1] = + pos .. " ".. data.owner .. " " .. + table.concat(data.shared, " ") + end + end + minetest.safe_file_write(s_protect.file, table.concat(contents, "\n")) +end + +function s_protect.save_share_db() + if delay(share_db, s_protect.save_share_db) then + return + end + + -- Save globally shared areas + local contents = {} + for name, players in pairs(s_protect.share) do + if #players > 0 then + contents[#contents + 1] = name .. " " .. + table.concat(players, " ") + end + end + minetest.safe_file_write(s_protect.sharefile, table.concat(contents, "\n")) +end + +-- Speed up the function access +local get_location = s_protect.get_location +function s_protect.get_claim(pos, direct_access) + if direct_access then + return claim_data[pos], pos + end + local pos = get_location(pos) + local index = pos.x..","..pos.y..","..pos.z + return claim_data[index], index +end + +function s_protect.set_claim(data, index) + claim_data[index] = data + save_claims() +end + +function s_protect.get_player_claims(owner) + local count = 0 + local claims = {} + for index, data in pairs(claim_data) do + if data.owner == owner then + claims[index] = data + count = count + 1 + end + end + return claims, count +end + +function s_protect.update_claims(updated) + for index, data in pairs(updated) do + if not data then + claim_data[index] = nil + else + claim_data[index] = data + end + end + save_claims() +end + +local function table_contains(t, to_find) + for i, v in pairs(t) do + if v == to_find then + return true + end + end + return false +end +function s_protect.is_shared(id, player_name) + if type(id) == "table" and id.shared then + -- by area + return table_contains(id.shared, player_name) + end + assert(type(id) == "string", "is_shared(): Either ClaimData or string expected") + -- by owner + return table_contains(s_protect.share[id] or {}, player_name) +end \ No newline at end of file diff --git a/mods/areas/default_settings.lua b/mods/areas/default_settings.lua new file mode 100644 index 00000000..b950c93b --- /dev/null +++ b/mods/areas/default_settings.lua @@ -0,0 +1,53 @@ +--[[ + SETTINGS FILE + +simple_protection/default_settings.lua + Contains the default settings for freshly created worlds. + Please do not modify in order to not get any configuration-related errors + after updating all other files but this + +[world_path]/s_protect.conf + Contains the per-world specific settings. + You may modify this one but pay attention, as some settings may cause + unwanted side effects when claims were made. +]] + + +-- Width and length of claims in nodes +-- !! Distorts the claim locations along the X and Z axis !! +-- Type: Integer, positive, even number +s_protect.claim_size = 16 + +-- Height of claims in nodes +-- !! Distorts the claim locations along the Y axis !! +-- Type: Integer, positive +s_protect.claim_height = 150 + +-- Defines the Y offset where the 0th claim should start in the underground +-- Example of claim (0,0,0): Ymin = -(50) = -50, Ymax = 150 - (50) - 1 = 99 +-- Type: Integer +s_protect.start_underground = 50 + +-- Only allows claiming above this Y value +-- To disable this limit, set the value to 'nil' +-- Type: Integer or nil +s_protect.underground_limit = -300 + +-- Returns the claim stick when unclaiming the area +-- Type: Boolean +s_protect.claim_return = true + +-- Players will need to claim the area (or have access to it) to dig +-- Digging will be still allowed in the underground, +-- as defined by the setting 's_protect.underground_limit' +-- Type: Boolean +s_protect.claim_to_dig = false + +-- Allows players to list their areas using '/area list' +-- Type: Boolean +s_protect.area_list = true + +-- Limits the amount of claims per player +-- Doubled limit for players with the 'simple_protection' privilege +-- Type: Integer +s_protect.max_claims = 200 diff --git a/mods/areas/doc/mod_api.txt b/mods/areas/doc/mod_api.txt new file mode 100644 index 00000000..78cd25a3 --- /dev/null +++ b/mods/areas/doc/mod_api.txt @@ -0,0 +1,108 @@ +# simple_protection API + +This file provides information about the API of simple_protection for the use in +custom mods. The API might change slightly when the development goes on, so avoid +using internal tables or functions which are not documented here. + +### Table of contents + +* Types: Custom tables or values +* Helper functions: General purpose functions +* Protection management: Claim-specific API functions +* Callbacks: Registrable callbacks + +### Notation + +* `function_name(arg1, arg2, ...)` -> `returned data type` + * Function description + + +## Types + +* `ClaimData` -> `table` +``` + { + owner = "foobar", -- string, owner of the area + shared = { "covfefe", "leprechaun" }, + -- ^ table, list of players who explicitly have access to this area + } +``` +* `ClaimIndex` -> `?` + * This might be any value, depending on the database backend. + * Can be obtained with `get_claim` and is used for `set_claim` + + +## Helper functions + +These functions are grouped so that they make sense and then sorted alphabetically. + +* `s_protect.can_access(pos, player_name)` -> `boolean` + * Returns whether the player may modify the given position + * `pos`: Position as a `vector` + * `player_name`: Is a `string` for the player to check + * `nil`: Always returns `false` + * `""`: Returns `true`. Warning: `get_player_name()` returns this value on + objects which are not players, such as Lua entities. +* `s_protect.get_area_bounds(pos)` -> `vector, vector` + * Returns the minimal node position (1st value) and maximal node position + (2nd value) of the current claim. The coordinate values are inside the claim. + * `pos`: Position as a `vector` +* `s_protect.get_center(pos)` -> `vector` + * Returns the center node position of the current claim near to `pos.y`. + * `pos`: Position as a `vector` +* `s_protect.get_location(pos)` -> `vector` + * Returns the location of the given claim (whole numbers) in claim-coordinates + * `pos`: Position as a `vector` + * This function is only helpful to iterate through multiple claims. +* `s_protect.load_config()` + * Causes simple_protection to (initialize and) reload the configuration. + + +## Protection management + +* `s_protect.get_claim(pos)` -> `ClaimData, ClaimIndex` + * Returns the area information or `nil` when no area was found at the given + position. + * `pos`: Position as a `vector` +* `s_protect.get_player_claims(owner)` -> `table, count` + * Returns a table of claims which the player owns, whereas `ClaimIndex` is the + key and `ClaimData` the value of the resulting table. The second argument + describes how many entries the table has (i.e. how many claims). + * `owner`: Player name as `string` +* `s_protect.set_claim(data, index)` + * Updates the area data for the given index. It will be saved automatically. + * `data`: Area information as `ClaimData` + * `index`: `ClaimIndex` provided by `get_claim` +* `s_protect.update_claims(update_table)` + * Updates multiple areas according to the supplied table + * `update_table`: `table` of areas to update, whereas the key is `ClaimIndex` + and the value `ClaimData`. Set the value to `nil` to remove the claim. +* `s_protect.is_shared(id, player_name)` -> `boolean` + * Returns whether the owner shared an area (or multiple) with `player_name` + * `id`: Can be either `ClaimData` or the owner name as `string`: + * Type `ClaimData`: Checks whether `player_name` is contained in + the given area's share list. + * Type `string`: Checks whether all areas of the given owner are + shared with `player_name` + * `player_name`: `string`, the player to check + + +## Callbacks + +* `s_protect.registered_on_access(func)` + * Override or extend access to a certain claim. Depending on the returned + value of the registered function. + * `func`: `function(pos, player_name, owner_name)` called in `s_protect.can_access`. + * Is only called on protected areas. Use settings to control unclaimed areas. + * Must return a boolean or `nil` + * `pos`: `vector` position of the interaction + * `player_name`: `string` name of the interacting player + * `owner_name`: `string` name of the claim owner (player) + * If `func() -> false`: Access is denied instantly regardless of shared areas. + * If `func() -> true`: Access is granted if no other callback returns `false`. + * If `func() -> nil`: Normal protection handling +* `s_protect.register_subcommand(name, func)` + * Registers a new subcommand for `/area`; throws errors on failure + * `name`: `string` name of the new command + * `func`: `function` to call when the command is executed + * See "Chat command definition" in the Minetest core Lua API. diff --git a/mods/areas/hud.lua b/mods/areas/hud.lua new file mode 100644 index 00000000..7a478672 --- /dev/null +++ b/mods/areas/hud.lua @@ -0,0 +1,91 @@ +--[[ +File: hud.lua + +areas HUD overlap compatibility +HUD display and refreshing +]] + + +local S = s_protect.translator + +s_protect.player_huds = {} + +local hud_time = 0 +local prefix = "" +local align_x = 1 +local pos_x = 0.02 + +-- If areas is installed: Move the HUD to th opposite side +if minetest.get_modpath("areas") then + prefix = "Simple Protection:\n" + align_x = -1 + pos_x = 0.95 +end + +local function generate_hud(player, current_owner, has_access) + -- green if access + local color = 0xFFFFFF + if has_access then + color = 0x00CC00 + end + s_protect.player_huds[player:get_player_name()] = { + hud_id = player:hud_add({ + hud_elem_type = "text", + name = "area_hud", + number = color, + position = {x=pos_x, y=0.98}, + text = prefix + .. S("Area owner: @1", current_owner), + scale = {x=100, y=25}, + alignment = {x=align_x, y=-1}, + }), + owner = current_owner, + had_access = has_access + } +end + +minetest.register_globalstep(function(dtime) + hud_time = hud_time + dtime + if hud_time < 2.9 then + return + end + hud_time = 0 + + local is_shared = s_protect.is_shared + for _, player in ipairs(minetest.get_connected_players()) do + local player_name = player:get_player_name() + + local current_owner = "" + local data = s_protect.get_claim(player:get_pos()) + if data then + current_owner = data.owner + end + + local has_access = (current_owner == player_name) + if not has_access and data then + -- Check if this area is shared with this player + has_access = is_shared(data, player_name) + end + if not has_access then + -- Check if all areas are shared with this player + has_access = is_shared(current_owner, player_name) + end + local changed = true + + local hud_table = s_protect.player_huds[player_name] + if hud_table and hud_table.owner == current_owner + and hud_table.had_access == has_access then + -- still the same hud + changed = false + end + + if changed and hud_table then + player:hud_remove(hud_table.hud_id) + s_protect.player_huds[player_name] = nil + end + + if changed and current_owner ~= "" then + generate_hud(player, current_owner, has_access) + end + end +end) diff --git a/mods/areas/init.lua b/mods/areas/init.lua new file mode 100644 index 00000000..8632958c --- /dev/null +++ b/mods/areas/init.lua @@ -0,0 +1,35 @@ +-- simple_protection initialization + +if not minetest.get_translator then + error("[simple_protection] Your Minetest version is no longer supported." + .. " (version < 5.0.0)") +end + + +local world_path = minetest.get_worldpath() +s_protect = {} +s_protect.translator = minetest.get_translator("simple_protection") +s_protect.share = {} +s_protect.mod_path = minetest.get_modpath("simple_protection") +s_protect.conf = world_path.."/s_protect.conf" +s_protect.file = world_path.."/s_protect.data" +s_protect.sharefile = world_path.."/s_protect_share.data" + +minetest.register_privilege("simple_protection", + s_protect.translator("Allows to modify and delete protected areas")) + +-- Load helper functions and configuration +dofile(s_protect.mod_path.."/misc_functions.lua") +s_protect.load_config() + +-- Load database functions +dofile(s_protect.mod_path.."/command_mgr.lua") +dofile(s_protect.mod_path.."/database_raw.lua") +-- Spread the load a bit +minetest.after(0.5, s_protect.load_db) + +-- General things to make this mod friendlier +dofile(s_protect.mod_path.."/protection.lua") +dofile(s_protect.mod_path.."/hud.lua") +dofile(s_protect.mod_path.."/radar.lua") +dofile(s_protect.mod_path.."/chest.lua") diff --git a/mods/areas/locale/simple_protection.de.tr b/mods/areas/locale/simple_protection.de.tr new file mode 100644 index 00000000..07def45d --- /dev/null +++ b/mods/areas/locale/simple_protection.de.tr @@ -0,0 +1,108 @@ +# textdomain: simple_protection +# Translated by: Krock/SmallJoker + + +# Privilege description +Allows to modify and delete protected areas=Erlaubt das Abändern und Entfernen von geschützten Gebieten + +#### AREA COMMAND #### + +# Command description +Manages all of your areas.=Verwaltet alle deine geschützten Gebiete + +# /area +Available area commands=Verfügbare 'area' Befehle +Information about this area=Informationen über dieses Gebiet +View of surrounding areas=Übersicht von allen Gebieten +(Un)share one area=Zugriffs-Berechtigung eines Gebietes hinzufügen/entfernen +(Un)share all areas=Zugriffs-Berechtigung für alle Gebiete hinzufügen/entfernen +List claimed areas=Geschützte Gebiete auflisten +Delete all areas of a player=Alle Gebiete eines Spielers löschen +Unclaim this area=Den Schutz für dieses Gebiet aufheben + +# Errors of /area +Unknown command parameter: @1. Check '/area' for correct usage.=Unbekannter Befehls-Parameter: @1. Siehe '/area' für die korrekte Anwendung. +No player name given.=Kein Spielernahme gegeben. +Unknown player.=Unbekannter Spieler. +This area is not claimed yet.=Dieses Gebiet ist noch nicht geschützt. +You do not own this area.=Du besitzt dieses Gebiet nicht. + +# /area show +Vertical from Y @1 to @2=Senkrecht von Y @1 bis @2 +Area status: @1=Gebiets-Status: @1 +Not claimable=Nicht schützbar +Unowned (!)=Nicht geschützt (!) +Owned by @1=Von @1 geschützt +Players with access: @1=Spieler mit Zugriff: @1 + +# /area radar +North @1=Nord @1 +East @1=Ost @1 +South @1=Süd @1 +West @1=West @1 +Your position=Deine Position +Your area=Dein Gebiet +Area claimed\nNo access for you=Gebiet geschützt\nKeine Berechtigung +Access for everybody=Zugriff für jeden +One area unit (@1m) up/down\n-> no claims on this Y level=Ein Gebiet (@1m) ober-/unterhalb +square \= 1 area \= @1x@2x@3 nodes (X,Y,Z)=1 Quadrat \= 1 Gebiet \= @1x@2x@3 Blöcke (X,Y,Z) + +# /area share +@1 already has access to all your areas.=@1 hat bereits Zugriff auf alle deine Gebiete. +@1 already has access to this area.=@1 hat bereits Zugriff auf dieses Gebiet. +@1 shared an area with you.=Du hast jetzt Zugriff auf ein Gebiet von @1. +@1 has now access to this area.=@1 kann jetzt dieses Gebiet abändern. + +# /area unshare +That player has no access to this area.=Dieser Spieler hat keinen Zugriff auf dieses Gebiet. +@1 unshared an area with you.=Du hast nun keinen Zugriff auf ein Gebiet von @1 mehr. +@1 has no longer access to this area.=@1 kann jetzt dieses Gebiet nicht mehr abändern. + +# /area shareall +You can not share all your areas with everybody.=Du kannst nicht alle Gebiete mit jedem teilen. +@1 already has now access to all your areas.=@1 hat bereits Zugriff auf alle deine Gebiete +@1 shared all areas with you.=@1 hat dir Zufriff auf alle die Gebiete erlaubt. +@1 has now access to all your areas.=@1 kann jetzt alle deine Gebiete abändern. + +# /area unshareall +@1 does not have access to any of your areas.=@1 hat keinen Zugriff auf deine Gebiete. +@1 unshared all areas with you.=@1 hat dir den Zugriff auf die Gebiete verwehrt. +@1 has no longer access to your areas.=@1 kann keines deiner Gebiete mehr abändern. + +# /area unclaim +This area is unowned now.=Dieses Gebiet ist nun nicht mehr geschützt. + +# /area delete +Missing privilege: @1=Fehlendes Privileg: @1 +Removed=Entfernt +Globally shared areas=Globale Gebietszugiffe +@1 claimed area(s)=@1 geschützte(s) Gebiet(e) +@1 does not own any claimed areas.=@1 besitzt keine geschützten Gebiete. + +# /area list [name] +This command is not available.=Dieser Befehl ist nicht verfügbar. +Listing all areas of @1. Amount: @2=Auslistung der Gebiete von @1. Anzahl: @2 + + +#### Protection #### + +# Item place information +Area owned by: @1=Gebiet geschützt durch: @1 +# Hud text +Area owner: @1=Gebiets-Besitzer: @1 + +# Item: Claim stick +Claim Stick=Gebietsschutz +#(click to protect)=(kicken zum schützen) +This area is already protected by an other protection mod.=Dieses Gebiet ist bereits durch eine andere Mod geschützt. +You can not claim areas below @1.=Du kannst keine Gebiete unterhalb von @1 schützen. +This area is already owned by: @1=@1 besitzt dieses Gebiet bereits. +Congratulations! You now own this area.=Glückwunsch! Du besitzt dieses Gebiet jetzt. +You can not claim any further areas: Limit (@1) reached.=Du kannst keine weiteren Gebiete schützen lassen: Limit (@1) erreicht. +Please claim this area to modify it.=Bitte schütze das Gebiet um dieses abändern zu können. + + +#### Shared Chest #### + +Shared Chest=Geteilte Truhe +(by protection)=(durch Gebietsschutz) diff --git a/mods/areas/locale/simple_protection.fr.tr b/mods/areas/locale/simple_protection.fr.tr new file mode 100644 index 00000000..e2164096 --- /dev/null +++ b/mods/areas/locale/simple_protection.fr.tr @@ -0,0 +1,107 @@ +# textdomain: simple_protection +# Translated by: d-stephane + + +# Privilege description +Allows to modify and delete protected areas=Permet de modifier et supprimer des zones protégées + +#### AREA COMMAND #### + +# Command description +Manages all of your areas.=Gestion de toutes vos zones. + +# /area +Available area commands=Commandes de zone disponibles +Information about this area=Informations sur cette zone +(Un)share one area=Partager (ou pas) une zone +(Un)share all areas=Partager (ou pas) toutes les zones +List claimed areas=Liste des zones revendiquées +Delete all areas of a player=Supprimer toutes les zones d'un joueur +Unclaim this area=Libérer cette zone + +# Errors of /area +Unknown command parameter: @1. Check '/area' for correct usage.=Paramètre de commande inconnu : @1. Tappez '/area' pour voir les paramètres possible. +No player name given.=Aucun nom de joueur donné. +Unknown player.=Joueur inconnu. +This area is not claimed yet.=Cette zone n'est pas encore revendiquée. +You do not own this area.=Vous ne possédez pas cette zone. + +# /area show +Vertical from Y @1 to @2=Verticale de Y @1 à @2 +Area status: @1=Statut de la zone : @1 +Not claimable=Non revendiquable +Unowned (!)=Pas de propriétaire (!) +Owned by @1=Possédée par @1 +Players with access: @1=Joueurs avec accès : @1 + +# /area radar +North @1=Nord @1 +East @1=Est @1 +South @1=Sud @1 +West @1=Ouest @1 +Your position=Votre position +Your area=Votre zone +Area claimed\nNo access for you=Zone revendiquée\nNon accessible pour vous +Access for everybody=Accès pour tout le monde +One area unit (@1m) up/down\n-> no claims on this Y level=Une unité de zone (@1m) haut/bas\n-> Rien de revendiqué à ce niveau Y +square \= 1 area \= @1x@2x@3 nodes (X,Y,Z)=carré \= 1 zone \= @1x@2x@3 blocs (X,Y,Z) + +# /area share +@1 already has access to all your areas.=@1 a déjà accès à toutes vos zones. +@1 already has access to this area.=@1 a déjà accès à cette zone. +@1 shared an area with you.=@1 a partagé une zone avec vous. +@1 has now access to this area.=@1 a maintenant accès à cette zone. + +# /area unshare +That player has no access to this area.=Ce joueur n'a pas accès à cette zone. +@1 unshared an area with you.=@1 a enlevé le partage de la zone avec vous. +@1 has no longer access to this area.=@1 n'a plus accès à cette zone. + +# /area shareall +You can not share all your areas with everybody.=Vous ne pouvez pas partager toutes vos zones avec tout le monde. +@1 already has now access to all your areas.=@1 a déjà accès à toutes vos zones. +@1 shared all areas with you.=@1 a partagé toutes les zones avec vous. +@1 has now access to all your areas.=@1 a maintenant accès à toutes vos zones. + +# /area unshareall +@1 does not have access to any of your areas.=@1 n'a accès à aucune de vos zones. +@1 unshared all areas with you.=@1 a enlevé le partage de toutes les zones avec vous. +@1 has no longer access to your areas.=@1 n'a plus accès à vos zones. + +# /area unclaim +This area is unowned now.=Cette zone n'est plus revendiquée. + +# /area delete +Missing privilege: @1=Privilège manquant : @1 +Removed=Supprimé +Globally shared areas=Zones partagées globalement +@1 claimed area(s)=@1 a revendiqué des zones +@1 does not own any claimed areas.=@1 ne possède aucune zone revendiquée. + +# /area list [name] +This command is not available.=Cette commande n'est pas disponible. +Listing all areas of @1. Amount: @2=Liste de tous les zones de @1. Total : @2 + + +#### Protection #### + +# Item place information +Area owned by: @1=Zone appartenant à : @1 +# Hud text +Area owner: @1=Propriétaire de la zone : @1 + +# Item: Claim stick +Claim Stick=Bâton de protection +(click to protect)=(cliquez pour protéger) +This area is already protected by an other protection mod.=Cette zone est déjà protégée par un autre mod de protection. +You can not claim areas below @1.=Vous ne pouvez pas revendiquer les zones ci-dessous @1. +This area is already owned by: @1=Cette zone est déjà détenue par : @1. +Congratulations! You now own this area.=Félicitations ! Vous possédez maintenant cette zone. +You can not claim any further areas: Limit (@1) reached.=Vous ne pouvez pas revendiquer d'autres zones : La limite de @1 a été atteinte. +Please claim this area to modify it.=Veuillez revendiquer cette zone pour la modifier. + + +#### Shared Chest #### + +Shared Chest=Coffre partagé +(by protection)=(par protection) diff --git a/mods/areas/locale/simple_protection.pt.tr b/mods/areas/locale/simple_protection.pt.tr new file mode 100644 index 00000000..a6e0c3c8 --- /dev/null +++ b/mods/areas/locale/simple_protection.pt.tr @@ -0,0 +1,105 @@ +# textdomain: simple_protection +# Translated by: BrunoMine + + +# Privilege description +Allows to modify and delete protected areas=Permitir modificar e deletar areas protegidas + +#### AREA COMMAND #### + +# Command description +Manages all of your areas.=Gerencia todas as suas areas. + +# /area +Available area commands=Comandos disponiveis +Information about this area=Dados sobre essa area +(Un)share one area=(Des)compartilha uma area +(Un)share all areas=(Des)compartilha todas areas +#List claimed areas = +#Delete all areas of a player = +Unclaim this area=Desfazer-se dessa area + +# Errors of /area +Unknown command parameter: @1. Check '/area' for correct usage.=Parametro de comando desconhecido: @1. Use '/area' para o uso correto. +No player name given.=Nenhum nome de jogador dado. +Unknown player.=Jogador desconhecido. +This area is not claimed yet.=Essa area nao foi reivindicada ainda. +You do not own this area.=Voce nao pode possuir essa area. + +# /area show +Vertical from Y @1 to @2=Vertical em Y @1 a @2 +Area status: @1=Status da area: @1 +Not claimable=Nao reivindicada +Unowned (!)=Sem dono (!) +Owned by @1=Reivindicada por @1 +Players with access: @1=Jogadores com acesso: @1 + +# /area radar +#North @1 = +#East @1 = +#South @1 = +#West @1 = +#Your position = +#Your area = +#Area claimed\nNo access for you = +#Access for everybody = + +# /area share +@1 already has access to all your areas.=@1 ja possui acesso a todas suas areas. +@1 already has access to this area.=@1 ja possui acesso a essa area. +@1 shared an area with you.=@1 compartilhou uma area contigo. +@1 has now access to this area.=@1 agora tem acesso nessa area. + +# /area unshare +That player has no access to this area.=Esse jogador nao tem acesso a essa area. +@1 unshared an area with you.=@1 descompartilhou uma area contigo. +@1 has no longer access to this area.=@1 deixou de ter acesso a essa area. + +# /area shareall +You can not share all your areas with everybody.=Nao podes compartilhar todas as suas areas com todos. +@1 already has now access to all your areas.=@1 ja possui agora acesso a todas suas areas. +@1 shared all areas with you.=@1 compartilhou todas as areas contigo. +@1 has now access to all your areas.=@1 agora tem acesso a todas suas areas. + +# /area unshareall +@1 does not have access to any of your areas.=@1 nao tem acesso a nenhuma de suas areas. +@1 unshared all areas with you.=@1 descompartilhou todas areas contigo. +@1 has no longer access to your areas.=@1 deixou de ter acesso a todas suas areas. + +# /area unclaim +This area is unowned now.=Essa area deixou de ser reivindicada agora. + +# /area delete +Missing privilege: @1=Perderam o privilegio: @1 +Removed=Removido +Globally shared areas=Areas compartilhadas globalmente +@1 claimed area(s)=@1 area(s) reivindicada(s) +@1 does not own any claimed areas.=@1 nao possui nenhuma area reivindicada. + +# /area list [name] +#This command is not available. = +#Listing all areas of @1. Amount: @2 = + + +#### Protection #### + +# Item place information +Area owned by: @1=Area possuida por: @1 +# Hud text +Area owner: @1=Area de: @1 + +# Item: Claim stick +Claim Stick=Graveto Reivindicador +#(click to protect) = +This area is already protected by an other protection mod.=Essa area ja foi protegida por um outro mod protetor. +You can not claim areas below @1.=Nao podes reivindicar areas abaixo @1. +This area is already owned by: @1=Essa area ja foi reivindicada por: @1. +Congratulations! You now own this area.=Parabens! Agora reivindicaste essa area. +#You can not claim any further areas: Limit (@1) reached. = +#Please claim this area to modify it. = + + +#### Shared Chest #### + +#Shared Chest = +#(by protection) = diff --git a/mods/areas/locale/template.txt b/mods/areas/locale/template.txt new file mode 100644 index 00000000..bf589766 --- /dev/null +++ b/mods/areas/locale/template.txt @@ -0,0 +1,108 @@ +# textdomain: simple_protection +# Translated by: YOURNAME + + +# Privilege description +Allows to modify and delete protected areas= + +#### AREA COMMAND #### + +# Command description +Manages all of your areas.= + +# /area +Available area commands= +Information about this area= +View of surrounding areas= +(Un)share one area= +(Un)share all areas= +List claimed areas= +Delete all areas of a player= +Unclaim this area= + +# Errors of /area +Unknown command parameter: @1. Check '/area' for correct usage.= +No player name given.= +Unknown player.= +This area is not claimed yet.= +You do not own this area.= + +# /area show +Vertical from Y @1 to @2= +Area status: @1= +Not claimable= +Unowned (!)= +Owned by @1= +Players with access: @1= + +# /area radar +North @1= +East @1= +South @1= +West @1= +Your position= +Your area= +Area claimed\nNo access for you= +Access for everybody= +One area unit (@1m) up/down\n-> no claims on this Y level= +square \= 1 area \= @1x@2x@3 nodes (X,Y,Z)= + +# /area share +@1 already has access to all your areas.= +@1 already has access to this area.= +@1 shared an area with you.= +@1 has now access to this area.= + +# /area unshare +That player has no access to this area.= +@1 unshared an area with you.= +@1 has no longer access to this area.= + +# /area shareall +You can not share all your areas with everybody.= +@1 already has now access to all your areas.= +@1 shared all areas with you.= +@1 has now access to all your areas.= + +# /area unshareall +@1 does not have access to any of your areas.= +@1 unshared all areas with you.= +@1 has no longer access to your areas.= + +# /area unclaim +This area is unowned now.= + +# /area delete +Missing privilege: @1= +Removed= +Globally shared areas= +@1 claimed area(s)= +@1 does not own any claimed areas.= + +# /area list [name] +This command is not available.= +Listing all areas of @1. Amount: @2= + + +#### Protection #### + +# Item place information +Area owned by: @1= +# Hud text +Area owner: @1= + +# Item: Claim stick +Claim Stick= +(click to protect)= +This area is already protected by an other protection mod.= +You can not claim areas below @1.= +This area is already owned by: @1= +Congratulations! You now own this area.= +You can not claim any further areas: Limit (@1) reached.= +Please claim this area to modify it.= + + +#### Shared Chest #### + +Shared Chest= +(by protection)= diff --git a/mods/areas/misc_functions.lua b/mods/areas/misc_functions.lua new file mode 100644 index 00000000..4dcdca70 --- /dev/null +++ b/mods/areas/misc_functions.lua @@ -0,0 +1,184 @@ +--[[ +File: functions.lua + +Protection helper functions +Configuration loading +]] + +-- Helper functions + +-- Cache for performance +local get_player_privs = minetest.get_player_privs +local registered_on_access = {} + +s_protect.can_access = function(pos, player_name) + if not player_name then + return false + end + -- Allow access for pipeworks and unidentified mods + if player_name == ":pipeworks" + or player_name == "" then + return true + end + + -- Admin power, handle privileges + local privs = get_player_privs(player_name) + if privs.simple_protection or privs.protection_bypass then + return true + end + + -- Data of current area + local data = s_protect.get_claim(pos) + + -- Area is not claimed + if not data then + -- Allow digging when claiming is not forced + if not s_protect.claim_to_dig then + return true + end + + -- Must claim everywhere? Disallow everywhere. + if not s_protect.underground_limit then + return false + end + -- Is it in claimable area? Yes? Disallow. + if pos.y >= s_protect.underground_limit then + return false + end + return true + end + if player_name == data.owner then + return true + end + + -- Complicated-looking return value handling: + -- false: Forbid access instantly + -- true: Access granted if none returns false + -- nil: Do nothing + local override_access = false + for i = 1, #registered_on_access do + local ret = registered_on_access[i]( + vector.new(pos), player_name, data.owner) + + if ret == false then + return false + end + if ret == true then + override_access = true + end + end + if override_access then + return true + end + + -- Owner shared the area with the player + if s_protect.is_shared(data.owner, player_name) then + return true + end + -- Globally shared area + if s_protect.is_shared(data, player_name) then + return true + end + if s_protect.is_shared(data, "*all") then + return true + end + return false +end + +s_protect.register_on_access = function(func) + registered_on_access[#registered_on_access + 1] = func +end + +s_protect.get_location = function(pos_) + local pos = vector.round(pos_) + return vector.floor({ + x = pos.x / s_protect.claim_size, + y = (pos.y + s_protect.start_underground) / s_protect.claim_height, + z = pos.z / s_protect.claim_size + }) +end + +local get_location = s_protect.get_location +s_protect.get_area_bounds = function(pos_) + local cs = s_protect.claim_size + local cy = s_protect.claim_height + + local p = get_location(pos_) + + local minp = { + x = p.x * cs, + y = p.y * cy - s_protect.start_underground, + z = p.z * cs + } + local maxp = { + x = minp.x + cs - 1, + y = minp.y + cy - 1, + z = minp.z + cs - 1 + } + + return minp, maxp +end + +s_protect.get_center = function(pos1) + local size = s_protect.claim_size + local pos = { + x = pos1.x / size, + y = pos1.y + 1.5, + z = pos1.z / size + } + pos = vector.floor(pos) + -- Get the middle of the area + pos.x = pos.x * size + (size / 2) + pos.z = pos.z * size + (size / 2) + return pos +end + +s_protect.load_config = function() + -- Load defaults + dofile(s_protect.mod_path.."/default_settings.lua") + local file = io.open(s_protect.conf, "r") + if not file then + -- Duplicate configuration file on first time + local src = io.open(s_protect.mod_path.."/default_settings.lua", "r") + file = io.open(s_protect.conf, "w") + + while true do + local block = src:read(128) -- 128B at once + if not block then + io.close(src) + io.close(file) + break + end + file:write(block) + end + return + end + + io.close(file) + + -- Load existing config + simple_protection = {} + dofile(s_protect.conf) + + -- Backwards compatibility + for k, v in pairs(simple_protection) do + s_protect[k] = v + end + simple_protection = nil + + -- Sanity check individual settings + assert((s_protect.claim_size % 2) == 0 and s_protect.claim_size >= 4, + "claim_size must be even and >= 4") + assert(s_protect.claim_height >= 4, "claim_height must be >= 4") + + if s_protect.claim_heigh then + minetest.log("warning", "[simple_protection] " + .. "Deprecated setting: claim_heigh") + s_protect.claim_height = s_protect.claim_heigh + end + if s_protect.underground_claim then + minetest.log("warning", "[simple_protection] " + .. "Deprecated setting: underground_claim") + s_protect.underground_limit = nil + end +end diff --git a/mods/areas/mod.conf b/mods/areas/mod.conf new file mode 100644 index 00000000..153a2a33 --- /dev/null +++ b/mods/areas/mod.conf @@ -0,0 +1,4 @@ +name = simple_protection +description = Easy to use fixed-grid quadratic area protection mod with graphical area "minimap" +depends = default +optional_depends = areas diff --git a/mods/areas/protection.lua b/mods/areas/protection.lua new file mode 100644 index 00000000..fc57233e --- /dev/null +++ b/mods/areas/protection.lua @@ -0,0 +1,148 @@ +--[[ +File: protection.lua + +Protection callback handler +Node placement checks +Claim Stick item definition +]] + +local S = s_protect.translator + +local function notify_player(pos, player_name) + local data = s_protect.get_claim(pos) + if not data and s_protect.claim_to_dig then + minetest.chat_send_player(player_name, S("Please claim this area to modify it.")) + elseif not data then + -- Access restricted by another protection mod. Not my job. + return + else + minetest.chat_send_player(player_name, S("Area owned by: @1", data.owner)) + end +end + +s_protect.old_is_protected = minetest.is_protected +minetest.is_protected = function(pos, player_name) + if s_protect.can_access(pos, player_name) then + return s_protect.old_is_protected(pos, player_name) + end + return true +end + +local old_item_place = minetest.item_place +minetest.item_place = function(itemstack, placer, pointed_thing) + local player_name = placer and placer:get_player_name() or "" + + if s_protect.can_access(pointed_thing.above, player_name) + or not minetest.registered_nodes[itemstack:get_name()] then + return old_item_place(itemstack, placer, pointed_thing) + end + + notify_player(pointed_thing.above, player_name) + return itemstack +end + +minetest.register_on_protection_violation(notify_player) + + +minetest.register_craftitem("simple_protection:claim", { + description = S("Claim Stick") .. " " .. S("(click to protect)"), + inventory_image = "simple_protection_claim.png", + stack_max = 10, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "node" then + return + end + local player_name = user:get_player_name() + local pos = pointed_thing.under + if s_protect.old_is_protected(pos, player_name) then + minetest.chat_send_player(player_name, + S("This area is already protected by an other protection mod.")) + return + end + if s_protect.underground_limit then + local minp, maxp = s_protect.get_area_bounds(pos) + if minp.y < s_protect.underground_limit then + minetest.chat_send_player(player_name, + S("You can not claim areas below @1.", + s_protect.underground_limit .. "m")) + return + end + end + local data, index = s_protect.get_claim(pos) + if data then + minetest.chat_send_player(player_name, + S("This area is already owned by: @1", data.owner)) + return + end + -- Count number of claims for this user + local claims_max = s_protect.max_claims + + if minetest.check_player_privs(player_name, {simple_protection=true}) then + claims_max = claims_max * 2 + end + + local claims, count = s_protect.get_player_claims(player_name) + if count >= claims_max then + minetest.chat_send_player(player_name, + S("You can not claim any further areas: Limit (@1) reached.", + tostring(claims_max))) + return + end + + itemstack:take_item(1) + s_protect.update_claims({ + [index] = {owner=player_name, shared={}} + }) + + minetest.add_entity(s_protect.get_center(pos), "simple_protection:marker") + minetest.chat_send_player(player_name, S("Congratulations! You now own this area.")) + return itemstack + end, +}) +minetest.register_alias("simple_protection:claim_stick", "simple_protection:claim") +minetest.register_alias("claim_stick", "simple_protection:claim") + +minetest.register_craft({ + output = "simple_protection:claim", + recipe = { + {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"}, + {"default:steel_ingot", "default:stonebrick", "default:steel_ingot"}, + {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"}, + } +}) + +minetest.register_entity("simple_protection:marker",{ + initial_properties = { + hp_max = 1, + visual = "wielditem", + visual_size = {x=1.0/1.5,y=1.0/1.5}, + physical = false, + textures = {"simple_protection:mark"}, + }, + on_activate = function(self, staticdata, dtime_s) + minetest.after(10, function() + self.object:remove() + end) + end, +}) + +-- hacky - I'm not a regular node! +local size = s_protect.claim_size / 2 +minetest.register_node("simple_protection:mark", { + tiles = {"simple_protection_marker.png"}, + groups = {dig_immediate=3, not_in_creative_inventory=1}, + drop = "", + use_texture_alpha = true, + walkable = false, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + -- sides + {-size-.5, -size-.5, -size-.5, -size-.5, size+.5, size-.5}, + {-size-.5, -size-.5, size-.5, size-.5, size+.5, size-.5}, + { size-.5, -size-.5, -size-.5, size-.5, size+.5, size-.5}, + {-size-.5, -size-.5, -size-.5, size-.5, size+.5, -size-.5}, + }, + }, +}) diff --git a/mods/areas/radar.lua b/mods/areas/radar.lua new file mode 100644 index 00000000..b916764e --- /dev/null +++ b/mods/areas/radar.lua @@ -0,0 +1,128 @@ +-- /area radar +local S = s_protect.translator +local data_cache + +local function colorize_area(name, force) + if force == "unclaimed" or not force and + not data_cache then + -- Area not claimed + return "[colorize:#FFF:50" + end + if force == "owner" or not force and + data_cache.owner == name then + return "[colorize:#0F0:180" + end + local is_shared = s_protect.is_shared + if force == "shared" or not force and ( + is_shared(data_cache, name) + or is_shared(data_cache.owner, name)) then + return "[colorize:#0F0:80" + end + if force == "*all" or not force and + is_shared(data_cache, "*all") then + return "[colorize:#00F:180" + end + -- Claimed but not shared + return "[colorize:#000:180" +end + +local function combine_escape(str) + return str:gsub("%^%[", "\\%^\\%["):gsub(":", "\\:") +end + +s_protect.register_subcommand("radar", function(name) + local player = minetest.get_player_by_name(name) + local player_pos = player:get_pos() + local pos = s_protect.get_location(player_pos) + local map_w = 15 - 1 + local map_wh = map_w / 2 + local img_w = 20 + + local get_single = s_protect.get_claim + local function getter(x, ymod, z) + data_cache = get_single(x .."," .. (pos.y + ymod) .. "," .. z, true) + return data_cache + end + + local parts = "" + for z = 0, map_w do + for x = 0, map_w do + local ax = pos.x + x - map_wh + local az = pos.z + z - map_wh + local img = "simple_protection_radar.png" + + if getter(ax, 0, az) then + -- Using default "img" value + elseif getter(ax, -1, az) then + -- Check for claim below first + img = "simple_protection_radar_down.png" + elseif getter(ax, 1, az) then + -- Last, check upper area + img = "simple_protection_radar_up.png" + end + parts = parts .. string.format(":%i,%i=%s", + x * img_w, (map_w - z) * img_w, + combine_escape(img .. "^" .. colorize_area(name))) + -- Somewhat dirty hack for [combine. Escape everything + -- to get the whole text passed into TextureSource::generateImage() + end + end + + -- Player's position marker (8x8 px) + local pp_x = player_pos.x / s_protect.claim_size + local pp_z = player_pos.z / s_protect.claim_size + -- Get relative position to the map, add map center offset, center image + pp_x = math.floor((pp_x - pos.x + map_wh) * img_w + 0.5) - 4 + pp_z = math.floor((pos.z - pp_z + map_wh + 1) * img_w + 0.5) - 4 + local marker_str = string.format(":%i,%i=%s", pp_x, pp_z, + combine_escape("object_marker_red.png^[resize:8x8")) + + -- Rotation calculation + local dir_label = S("North @1", "(Z+)") + local dir_mod = "" + local look_angle = player.get_look_horizontal and player:get_look_horizontal() + if not look_angle then + look_angle = player:get_look_yaw() - math.pi / 2 + end + look_angle = look_angle * 180 / math.pi + + if look_angle >= 45 and look_angle < 135 then + dir_label = S("West @1", "(X-)") + dir_mod = "^[transformR270" + elseif look_angle >= 135 and look_angle < 225 then + dir_label = S("South @1", "(Z-)") + dir_mod = "^[transformR180" + elseif look_angle >= 225 and look_angle < 315 then + dir_label = S("East @1", "(X+)") + dir_mod = "^[transformR90" + end + + minetest.show_formspec(name, "covfefe", + "size[10.5,7]" .. + "button_exit[9.5,0;1,1;exit;X]" .. + "label[2,0;"..dir_label.."]" .. + "image[0,0.5;7,7;" .. + minetest.formspec_escape("[combine:300x300" + .. parts .. marker_str) + .. dir_mod .. "]" .. + "label[0,6.8;1 " .. S("square = 1 area = @1x@2x@3 nodes (X,Y,Z)", + s_protect.claim_size, + s_protect.claim_height, + s_protect.claim_size) .. "]" .. + "image[6.25,1.25;0.5,0.5;object_marker_red.png]" .. + "label[7,1.25;" .. S("Your position") .. "]" .. + "image[6,2;1,1;simple_protection_radar.png^" + .. colorize_area(nil, "owner") .. "]" .. + "label[7,2.25;" .. S("Your area") .. "]" .. + "image[6,3;1,1;simple_protection_radar.png^" + .. colorize_area(nil, "other") .. "]" .. + "label[7,3;" .. S("Area claimed\nNo access for you") .. "]" .. + "image[6,4;1,1;simple_protection_radar.png^" + .. colorize_area(nil, "*all") .. "]" .. + "label[7,4.25;" .. S("Access for everybody") .. "]" .. + "image[6,5;1,1;simple_protection_radar_down.png]" .. + "image[7,5;1,1;simple_protection_radar_up.png]" .. + "label[6,6;" .. S("One area unit (@1m) up/down\n-> no claims on this Y level", + s_protect.claim_height) .. "]" + ) +end) diff --git a/mods/areas/screenshot.png b/mods/areas/screenshot.png new file mode 100644 index 00000000..f2885ecc Binary files /dev/null and b/mods/areas/screenshot.png differ diff --git a/mods/areas/textures/simple_protection_claim.png b/mods/areas/textures/simple_protection_claim.png new file mode 100644 index 00000000..41dbd8bf Binary files /dev/null and b/mods/areas/textures/simple_protection_claim.png differ diff --git a/mods/areas/textures/simple_protection_marker.png b/mods/areas/textures/simple_protection_marker.png new file mode 100644 index 00000000..950609c8 Binary files /dev/null and b/mods/areas/textures/simple_protection_marker.png differ diff --git a/mods/areas/textures/simple_protection_radar.png b/mods/areas/textures/simple_protection_radar.png new file mode 100644 index 00000000..75bbbe1a Binary files /dev/null and b/mods/areas/textures/simple_protection_radar.png differ diff --git a/mods/areas/textures/simple_protection_radar_down.png b/mods/areas/textures/simple_protection_radar_down.png new file mode 100644 index 00000000..aee9c442 Binary files /dev/null and b/mods/areas/textures/simple_protection_radar_down.png differ diff --git a/mods/areas/textures/simple_protection_radar_up.png b/mods/areas/textures/simple_protection_radar_up.png new file mode 100644 index 00000000..2d51762a Binary files /dev/null and b/mods/areas/textures/simple_protection_radar_up.png differ diff --git a/mods/basic_materials/.luacheckrc b/mods/basic_materials/.luacheckrc new file mode 100644 index 00000000..55879b03 --- /dev/null +++ b/mods/basic_materials/.luacheckrc @@ -0,0 +1,30 @@ +std = "lua51+minetest" +unused_args = false +allow_defined_top = true +max_line_length = 999 + +stds.minetest = { + read_globals = { + "DIR_DELIM", + "minetest", + "core", + "dump", + "vector", + "nodeupdate", + "VoxelManip", + "VoxelArea", + "PseudoRandom", + "ItemStack", + "default", + table = { + fields = { + "copy", + }, + }, + } +} + +read_globals = { + "default", + "moreores", +} diff --git a/mods/basic_materials/LICENSE b/mods/basic_materials/LICENSE new file mode 100644 index 00000000..c5885ae9 --- /dev/null +++ b/mods/basic_materials/LICENSE @@ -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. + 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. diff --git a/mods/basic_materials/electrical-electronic.lua b/mods/basic_materials/electrical-electronic.lua new file mode 100644 index 00000000..91fac4e3 --- /dev/null +++ b/mods/basic_materials/electrical-electronic.lua @@ -0,0 +1,86 @@ +-- Translation support +local S = minetest.get_translator("basic_materials") + +-- items + +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", +}) + +-- crafts + +minetest.register_craft( { + output = "mesecons_materials:silicon 4", + recipe = { + { "default:sand", "default:sand" }, + { "default:sand", "default:steel_ingot" }, + }, +}) + +minetest.register_craft( { + output = "basic_materials:ic 4", + recipe = { + { "mesecons_materials:silicon", "mesecons_materials:silicon" }, + { "mesecons_materials:silicon", "default:copper_ingot" }, + }, +}) + +minetest.register_craft( { + output = "basic_materials:motor 2", + recipe = { + { "default:mese_crystal_fragment", "basic_materials:copper_wire", "basic_materials:plastic_sheet" }, + { "default:copper_ingot", "default:steel_ingot", "default:steel_ingot" }, + { "default: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" }, + } +}) + +minetest.register_craft( { + output = "basic_materials:heating_element 2", + recipe = { + { "default:copper_ingot", "default:mese_crystal_fragment", "default:copper_ingot" } + }, +}) + +minetest.register_craft({ + --type = "shapeless", + output = "basic_materials:energy_crystal_simple 2", + recipe = { + { "default:mese_crystal_fragment", "default:torch", "default:mese_crystal_fragment" }, + { "default:diamond", "default:gold_ingot", "default:diamond" } + }, +}) + +-- aliases + +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_force("mesecons_materials:silicon", "basic_materials:silicon") diff --git a/mods/basic_materials/init.lua b/mods/basic_materials/init.lua new file mode 100644 index 00000000..348c0598 --- /dev/null +++ b/mods/basic_materials/init.lua @@ -0,0 +1,15 @@ +-- 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. + +local modpath = minetest.get_modpath("basic_materials") + +basic_materials = {} +basic_materials.mod = { author = "Vanessa Dannenberg" } + +dofile(modpath.."/metals.lua") +dofile(modpath.."/plastics.lua") +dofile(modpath.."/electrical-electronic.lua") +dofile(modpath.."/misc.lua") diff --git a/mods/basic_materials/locale/basic_materials.de.tr b/mods/basic_materials/locale/basic_materials.de.tr new file mode 100644 index 00000000..8fddd8a7 --- /dev/null +++ b/mods/basic_materials/locale/basic_materials.de.tr @@ -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 diff --git a/mods/basic_materials/locale/basic_materials.fr.tr b/mods/basic_materials/locale/basic_materials.fr.tr new file mode 100644 index 00000000..0bebf79d --- /dev/null +++ b/mods/basic_materials/locale/basic_materials.fr.tr @@ -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 diff --git a/mods/basic_materials/locale/basic_materials.it.tr b/mods/basic_materials/locale/basic_materials.it.tr new file mode 100644 index 00000000..aae0b3be --- /dev/null +++ b/mods/basic_materials/locale/basic_materials.it.tr @@ -0,0 +1,34 @@ +# textdomain: basic_materials +# Author: Salvo 'LtWorf' Tomaselli +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 diff --git a/mods/basic_materials/locale/basic_materials.ru.tr b/mods/basic_materials/locale/basic_materials.ru.tr new file mode 100644 index 00000000..85e9c0cf --- /dev/null +++ b/mods/basic_materials/locale/basic_materials.ru.tr @@ -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=Пустая Катушка diff --git a/mods/basic_materials/metals.lua b/mods/basic_materials/metals.lua new file mode 100644 index 00000000..0a3243b0 --- /dev/null +++ b/mods/basic_materials/metals.lua @@ -0,0 +1,300 @@ +-- Translation support +local S = minetest.get_translator("basic_materials") + +-- items + +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: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:steel_bar", { + description = S("Steel Bar"), + inventory_image = "basic_materials_steel_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" +}) + +-- nodes + +local chains_sbox = { + type = "fixed", + fixed = { -0.1, -0.5, -0.1, 0.1, 0.5, 0.1 } +} + +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", + groups = {cracky=3}, + 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", + groups = {cracky=3}, + 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, level=2}, + sounds = default.node_sound_metal_defaults() +}) + +-- crafts + +minetest.register_craft( { + output = "basic_materials:copper_wire 2", + type = "shapeless", + recipe = { + "default:copper_ingot", + "basic_materials:empty_spool", + "basic_materials:empty_spool", + }, +}) + +minetest.register_craft( { + output = "basic_materials:silver_wire 2", + type = "shapeless", + recipe = { + "moreores:silver_ingot", + "basic_materials:empty_spool", + "basic_materials:empty_spool", + }, +}) + +minetest.register_craft( { + output = "basic_materials:gold_wire 2", + type = "shapeless", + recipe = { + "default:gold_ingot", + "basic_materials:empty_spool", + "basic_materials:empty_spool", + }, +}) + +minetest.register_craft( { + output = "basic_materials:steel_wire 2", + type = "shapeless", + recipe = { + "default:steel_ingot", + "basic_materials:empty_spool", + "basic_materials:empty_spool", + }, +}) + +minetest.register_craft( { + output = "basic_materials:steel_strip 12", + recipe = { + { "", "default:steel_ingot", "" }, + { "default:steel_ingot", "", "" }, + }, +}) + +minetest.register_craft( { + output = "basic_materials:copper_strip 12", + recipe = { + { "", "default:copper_ingot", "" }, + { "default:copper_ingot", "", "" }, + }, +}) + +minetest.register_craft( { + output = "basic_materials:steel_bar 6", + recipe = { + { "", "", "default:steel_ingot" }, + { "", "default:steel_ingot", "" }, + { "default:steel_ingot", "", "" }, + }, +}) + +minetest.register_craft( { + output = "basic_materials:padlock 2", + recipe = { + { "basic_materials:steel_bar" }, + { "default:steel_ingot" }, + { "default:steel_ingot" }, + }, +}) + +minetest.register_craft({ + output = "basic_materials:chainlink_steel 12", + recipe = { + {"", "default:steel_ingot", "default:steel_ingot"}, + { "default:steel_ingot", "", "default:steel_ingot" }, + { "default:steel_ingot", "default:steel_ingot", "" }, + }, +}) + +minetest.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", "" }, + }, +}) + +minetest.register_craft({ + output = 'basic_materials:chain_steel 2', + recipe = { + {"basic_materials:chainlink_steel"}, + {"basic_materials:chainlink_steel"}, + {"basic_materials:chainlink_steel"} + } +}) + +minetest.register_craft({ + output = 'basic_materials:chain_brass 2', + recipe = { + {"basic_materials:chainlink_brass"}, + {"basic_materials:chainlink_brass"}, + {"basic_materials:chainlink_brass"} + } +}) + +minetest.register_craft( { + output = "basic_materials:gear_steel 6", + recipe = { + { "", "default:steel_ingot", "" }, + { "default:steel_ingot","basic_materials:chainlink_steel", "default:steel_ingot" }, + { "", "default:steel_ingot", "" } + }, +}) + +minetest.register_craft( { + type = "shapeless", + output = "basic_materials:brass_ingot 3", + recipe = { + "default:copper_ingot", + "default:copper_ingot", + "moreores:silver_ingot", + }, +}) + +if not minetest.get_modpath("moreores") then + -- Without moreores, there still should be a way to create brass. + minetest.register_craft( { + output = "basic_materials:brass_ingot 9", + recipe = { + {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"}, + {"default:gold_ingot", "default:copper_ingot", "default:gold_ingot"}, + {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"}, + }, + }) +end + +minetest.register_craft( { + type = "shapeless", + output = "basic_materials:brass_ingot 9", + recipe = { "basic_materials:brass_block" }, +}) + +minetest.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" }, + }, +}) + +-- aliases + +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_force("glooptest:chainlink", "basic_materials:chainlink_steel") +minetest.register_alias_force("homedecor:chainlink_steel", "basic_materials:chainlink_steel") +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") + diff --git a/mods/basic_materials/misc.lua b/mods/basic_materials/misc.lua new file mode 100644 index 00000000..00128972 --- /dev/null +++ b/mods/basic_materials/misc.lua @@ -0,0 +1,126 @@ +-- Translation support +local S = minetest.get_translator("basic_materials") + +-- items + +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", +}) + +-- nodes + +minetest.register_node("basic_materials:cement_block", { + description = S("Cement"), + tiles = {"basic_materials_cement_block.png"}, + is_ground_content = true, + groups = {cracky=2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("basic_materials:concrete_block", { + description = S("Concrete Block"), + tiles = {"basic_materials_concrete_block.png",}, + groups = {cracky=1, level=2, concrete=1}, + sounds = default.node_sound_stone_defaults(), +}) + +-- crafts + +minetest.register_craft({ + type = "shapeless", + output = "basic_materials:oil_extract 2", + recipe = { + "group:leaves", + "group:leaves", + "group:leaves", + "group:leaves", + "group:leaves", + "group:leaves" + } +}) + +minetest.register_craft({ + type = "cooking", + output = "basic_materials:paraffin", + recipe = "basic_materials:oil_extract", +}) + +minetest.register_craft({ + type = "fuel", + recipe = "basic_materials:oil_extract", + burntime = 30, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "basic_materials:paraffin", + burntime = 30, +}) + +minetest.register_craft( { + type = "shapeless", + output = "basic_materials:terracotta_base 8", + recipe = { + "bucket:bucket_water", + "default:clay_lump", + "default:gravel", + }, + replacements = { {"bucket:bucket_water", "bucket:bucket_empty"}, }, +}) + +minetest.register_craft({ + type = "shapeless", + output = "basic_materials:wet_cement 3", + recipe = { + "default:dirt", + "dye:dark_grey", + "dye:dark_grey", + "dye:dark_grey", + "bucket:bucket_water" + }, + replacements = {{'bucket:bucket_water', 'bucket:bucket_empty'},}, +}) + +minetest.register_craft({ + type = "cooking", + output = "basic_materials:cement_block", + recipe = "basic_materials:wet_cement", + cooktime = 8 +}) + +minetest.register_craft({ + output = 'basic_materials:concrete_block 6', + recipe = { + {'group:sand', 'basic_materials:wet_cement', 'default:gravel'}, + {'basic_materials:steel_bar', 'basic_materials:wet_cement', 'basic_materials:steel_bar'}, + {'default:gravel', 'basic_materials:wet_cement', 'group:sand'}, + } +}) + +-- aliases + +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") diff --git a/mods/basic_materials/mod.conf b/mods/basic_materials/mod.conf new file mode 100644 index 00000000..7234bfe9 --- /dev/null +++ b/mods/basic_materials/mod.conf @@ -0,0 +1,4 @@ +name = basic_materials +depends = default +optional_depends = moreores +min_minetest_version = 5.2.0 diff --git a/mods/basic_materials/models/basic_materials_chains.obj b/mods/basic_materials/models/basic_materials_chains.obj new file mode 100644 index 00000000..78724c98 --- /dev/null +++ b/mods/basic_materials/models/basic_materials_chains.obj @@ -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 diff --git a/mods/basic_materials/plastics.lua b/mods/basic_materials/plastics.lua new file mode 100644 index 00000000..e29af53e --- /dev/null +++ b/mods/basic_materials/plastics.lua @@ -0,0 +1,56 @@ +-- Translation support +local S = minetest.get_translator("basic_materials") + +-- items + +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" +}) + +-- crafts + +minetest.register_craft({ + type = "cooking", + output = "basic_materials:plastic_sheet", + recipe = "basic_materials:paraffin", +}) + +minetest.register_craft({ + type = "fuel", + recipe = "basic_materials:plastic_sheet", + burntime = 30, +}) + +minetest.register_craft( { + output = "basic_materials:plastic_strip 9", + recipe = { + { "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" } + }, +}) + +minetest.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" } + }, +}) + +-- aliases + +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") diff --git a/mods/basic_materials/textures/basic_materials_brass_block.png b/mods/basic_materials/textures/basic_materials_brass_block.png new file mode 100644 index 00000000..c9378000 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_brass_block.png differ diff --git a/mods/basic_materials/textures/basic_materials_brass_ingot.png b/mods/basic_materials/textures/basic_materials_brass_ingot.png new file mode 100644 index 00000000..0bd030a3 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_brass_ingot.png differ diff --git a/mods/basic_materials/textures/basic_materials_cement_block.png b/mods/basic_materials/textures/basic_materials_cement_block.png new file mode 100644 index 00000000..6d30f477 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_cement_block.png differ diff --git a/mods/basic_materials/textures/basic_materials_chain_brass.png b/mods/basic_materials/textures/basic_materials_chain_brass.png new file mode 100644 index 00000000..e2fb20db Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chain_brass.png differ diff --git a/mods/basic_materials/textures/basic_materials_chain_brass_inv.png b/mods/basic_materials/textures/basic_materials_chain_brass_inv.png new file mode 100644 index 00000000..8c2d554d Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chain_brass_inv.png differ diff --git a/mods/basic_materials/textures/basic_materials_chain_steel.png b/mods/basic_materials/textures/basic_materials_chain_steel.png new file mode 100644 index 00000000..29af8dbd Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chain_steel.png differ diff --git a/mods/basic_materials/textures/basic_materials_chain_steel_inv.png b/mods/basic_materials/textures/basic_materials_chain_steel_inv.png new file mode 100644 index 00000000..c552f7b4 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chain_steel_inv.png differ diff --git a/mods/basic_materials/textures/basic_materials_chainlink_brass.png b/mods/basic_materials/textures/basic_materials_chainlink_brass.png new file mode 100644 index 00000000..9a1ad87e Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chainlink_brass.png differ diff --git a/mods/basic_materials/textures/basic_materials_chainlink_steel.png b/mods/basic_materials/textures/basic_materials_chainlink_steel.png new file mode 100644 index 00000000..d7132c32 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_chainlink_steel.png differ diff --git a/mods/basic_materials/textures/basic_materials_concrete_block.png b/mods/basic_materials/textures/basic_materials_concrete_block.png new file mode 100644 index 00000000..5dd0d660 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_concrete_block.png differ diff --git a/mods/basic_materials/textures/basic_materials_copper_strip.png b/mods/basic_materials/textures/basic_materials_copper_strip.png new file mode 100644 index 00000000..22e572a1 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_copper_strip.png differ diff --git a/mods/basic_materials/textures/basic_materials_copper_wire.png b/mods/basic_materials/textures/basic_materials_copper_wire.png new file mode 100644 index 00000000..9df9f366 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_copper_wire.png differ diff --git a/mods/basic_materials/textures/basic_materials_empty_spool.png b/mods/basic_materials/textures/basic_materials_empty_spool.png new file mode 100644 index 00000000..017a94fd Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_empty_spool.png differ diff --git a/mods/basic_materials/textures/basic_materials_energy_crystal.png b/mods/basic_materials/textures/basic_materials_energy_crystal.png new file mode 100644 index 00000000..f1c28e80 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_energy_crystal.png differ diff --git a/mods/basic_materials/textures/basic_materials_gear_steel.png b/mods/basic_materials/textures/basic_materials_gear_steel.png new file mode 100644 index 00000000..584f9a51 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_gear_steel.png differ diff --git a/mods/basic_materials/textures/basic_materials_gold_wire.png b/mods/basic_materials/textures/basic_materials_gold_wire.png new file mode 100644 index 00000000..781de7b1 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_gold_wire.png differ diff --git a/mods/basic_materials/textures/basic_materials_heating_element.png b/mods/basic_materials/textures/basic_materials_heating_element.png new file mode 100644 index 00000000..42e00b7a Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_heating_element.png differ diff --git a/mods/basic_materials/textures/basic_materials_ic.png b/mods/basic_materials/textures/basic_materials_ic.png new file mode 100644 index 00000000..4c888945 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_ic.png differ diff --git a/mods/basic_materials/textures/basic_materials_motor.png b/mods/basic_materials/textures/basic_materials_motor.png new file mode 100644 index 00000000..f19ec0a0 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_motor.png differ diff --git a/mods/basic_materials/textures/basic_materials_oil_extract.png b/mods/basic_materials/textures/basic_materials_oil_extract.png new file mode 100644 index 00000000..e34623d0 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_oil_extract.png differ diff --git a/mods/basic_materials/textures/basic_materials_padlock.png b/mods/basic_materials/textures/basic_materials_padlock.png new file mode 100644 index 00000000..b05b7ef7 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_padlock.png differ diff --git a/mods/basic_materials/textures/basic_materials_paraffin.png b/mods/basic_materials/textures/basic_materials_paraffin.png new file mode 100644 index 00000000..77d2bbd1 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_paraffin.png differ diff --git a/mods/basic_materials/textures/basic_materials_plastic_sheet.png b/mods/basic_materials/textures/basic_materials_plastic_sheet.png new file mode 100644 index 00000000..034dcc2f Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_plastic_sheet.png differ diff --git a/mods/basic_materials/textures/basic_materials_plastic_strip.png b/mods/basic_materials/textures/basic_materials_plastic_strip.png new file mode 100644 index 00000000..1318dfc0 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_plastic_strip.png differ diff --git a/mods/basic_materials/textures/basic_materials_silicon.png b/mods/basic_materials/textures/basic_materials_silicon.png new file mode 100644 index 00000000..847b366c Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_silicon.png differ diff --git a/mods/basic_materials/textures/basic_materials_silver_wire.png b/mods/basic_materials/textures/basic_materials_silver_wire.png new file mode 100644 index 00000000..a38a45ea Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_silver_wire.png differ diff --git a/mods/basic_materials/textures/basic_materials_steel_bar.png b/mods/basic_materials/textures/basic_materials_steel_bar.png new file mode 100644 index 00000000..0673b6ee Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_steel_bar.png differ diff --git a/mods/basic_materials/textures/basic_materials_steel_strip.png b/mods/basic_materials/textures/basic_materials_steel_strip.png new file mode 100644 index 00000000..6384dc83 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_steel_strip.png differ diff --git a/mods/basic_materials/textures/basic_materials_steel_wire.png b/mods/basic_materials/textures/basic_materials_steel_wire.png new file mode 100644 index 00000000..0c96c8f3 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_steel_wire.png differ diff --git a/mods/basic_materials/textures/basic_materials_terracotta_base.png b/mods/basic_materials/textures/basic_materials_terracotta_base.png new file mode 100644 index 00000000..9f04aad5 Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_terracotta_base.png differ diff --git a/mods/basic_materials/textures/basic_materials_wet_cement.png b/mods/basic_materials/textures/basic_materials_wet_cement.png new file mode 100644 index 00000000..6a7fbf1b Binary files /dev/null and b/mods/basic_materials/textures/basic_materials_wet_cement.png differ diff --git a/version.php b/version.php index bbda97d0..bbc1bdff 100644 --- a/version.php +++ b/version.php @@ -1,5 +1,5 @@