diff --git a/kingdoms_game/.gitignore b/kingdoms_game/.gitignore new file mode 100644 index 0000000..717f5fe --- /dev/null +++ b/kingdoms_game/.gitignore @@ -0,0 +1,9 @@ +## Generic ignorable patterns and files +*~ +.*.swp +*bak* +tags +*.vim + +## Files related to minetest development cycle +*.patch diff --git a/kingdoms_game/README.txt b/kingdoms_game/README.txt new file mode 100644 index 0000000..b59b7f9 --- /dev/null +++ b/kingdoms_game/README.txt @@ -0,0 +1,53 @@ +Minetest Game [minetest_game] +============================= +The main subgame for the Minetest engine +======================================== + +To use this subgame with the Minetest engine, insert this repository as + /games/minetest_game + +The Minetest engine can be found in: + https://github.com/minetest/minetest/ + +Compatibility +-------------- +The Minetest Game github master HEAD is generally compatible with the github +master HEAD of the Minetest engine. + +Additionally, when the Minetest engine is tagged to be a certain version (eg. +0.4.10), Minetest Game is tagged with the version too. + +When stable releases are made, Minetest Game is packaged and made available in + http://minetest.net/download +and in case the repository has grown too much, it may be reset. In that sense, +this is not a "real" git repository. (Package maintainers please note!) + +License of source code +---------------------- +Copyright (C) 2010-2012 celeron55, Perttu Ahola +See README.txt in each mod directory for information about other authors. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +License of media (textures and sounds) +-------------------------------------- +Copyright (C) 2010-2012 celeron55, Perttu Ahola +See README.txt in each mod directory for information about other authors. + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +http://creativecommons.org/licenses/by-sa/3.0/ + +License of menu/header.png +Copyright (C) 2015 paramat CC BY-SA 3.0 diff --git a/kingdoms_game/game.conf b/kingdoms_game/game.conf new file mode 100644 index 0000000..b854790 --- /dev/null +++ b/kingdoms_game/game.conf @@ -0,0 +1 @@ +name = Minetest Wars \ No newline at end of file diff --git a/kingdoms_game/game_api.txt b/kingdoms_game/game_api.txt new file mode 100644 index 0000000..a32f8d5 --- /dev/null +++ b/kingdoms_game/game_api.txt @@ -0,0 +1,473 @@ +Minetest Game API +================= +GitHub Repo: https://github.com/minetest/minetest_game + +Introduction +------------ + +The Minetest Game subgame offers multiple new possibilities in addition to the Minetest engine's built-in API, +allowing you to add new plants to farming mod, buckets for new liquids, new stairs and custom panes. +For information on the Minetest API, visit https://github.com/minetest/minetest/blob/master/doc/lua_api.txt +Please note: + + * [XYZ] refers to a section the Minetest API + * [#ABC] refers to a section in this document + +Bucket API +---------- + +The bucket API allows registering new types of buckets for non-default liquids. + + + bucket.register_liquid( + "default:lava_source", -- name of the source node + "default:lava_flowing", -- name of the flowing node + "bucket:bucket_lava", -- name of the new bucket item (or nil if liquid is not takeable) + "bucket_lava.png", -- texture of the new bucket item (ignored if itemname == nil) + "Lava Bucket", -- text description of the bucket item + {lava_bucket = 1} -- groups of the bucket item, OPTIONAL + ) + +Beds API +-------- + + beds.register_bed( + "beds:bed", -- Bed name + def -- See [#Bed definition] + ) + + * `beds.read_spawns() ` Returns a table containing players respawn positions + * `beds.kick_players()` Forces all players to leave bed + * `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping + +###Bed definition + + { + description = "Simple Bed", + inventory_image = "beds_bed.png", + wield_image = "beds_bed.png", + tiles = { + bottom = {'Tile definition'}, -- the tiles of the bottom part of the bed. + top = {Tile definition} -- the tiles of the bottom part of the bed. + }, + nodebox = { + bottom = 'regular nodebox', -- bottom part of bed (see [Node boxes]) + top = 'regular nodebox', -- top part of bed (see [Node boxes]) + }, + selectionbox = 'regular nodebox', -- for both nodeboxes (see [Node boxes]) + recipe = { -- Craft recipe + {"group:wool", "group:wool", "group:wool"}, + {"group:wood", "group:wood", "group:wood"} + } + } + +Doors API +--------- + +The doors mod allows modders to register custom doors and trapdoors. + +`doors.register_door(name, def)` + + * Registers new door + * `name` Name for door + * `def` See [#Door definition] + +`doors.register_trapdoor(name, def)` + + * Registers new trapdoor + * `name` Name for trapdoor + * `def` See [#Trapdoor definition] + +`doors.get(pos)` + + * `pos` A position as a table, e.g `{x = 1, y = 1, z = 1}` + * Returns an ObjecRef to a door, or nil if the position does not contain a door + + ###Methods + + :open(player) -- Open the door object, returns if door was opened + :close(player) -- Close the door object, returns if door was closed + :toggle(player) -- Toggle the door state, returns if state was toggled + :state() -- returns the door state, true = open, false = closed + + the "player" parameter can be omitted in all methods. If passed then + the usual permission checks will be performed to make sure the player + has the permissions needed to open this door. If omitted then no + permission checks are performed. + +###Door definition + + description = "Door description", + inventory_image = "mod_door_inv.png", + groups = {choppy = 2}, + tiles = {"mod_door.png"}, -- UV map. + recipe = craftrecipe, + sounds = default.node_sound_wood_defaults(), -- optional + sound_open = sound play for open door, -- optional + sound_close = sound play for close door, -- optional + protected = false, -- If true, only placer can open the door (locked for others) + +###Trapdoor definition + + description = "Trapdoor description", + inventory_image = "mod_trapdoor_inv.png", + groups = {choppy = 2}, + tile_front = "doors_trapdoor.png", -- the texture for the front and back of the trapdoor + tile_side = "doors_trapdoor_side.png", -- the tiles of the four side parts of the trapdoor + sounds = default.node_sound_wood_defaults(), -- optional + sound_open = sound play for open door, -- optional + sound_close = sound play for close door, -- optional + protected = false, -- If true, only placer can open the door (locked for others) + +Fence API +--------- +Allows creation of new fences with "fencelike" drawtype. + +`default.register_fence(name, item definition)` + + Registers a new fence. Custom fields texture and material are required, as + are name and description. The rest is optional. You can pass most normal + nodedef fields here except drawtype. The fence group will always be added + for this node. + +###fence definition + + name = "default:fence_wood", + description = "Wooden Fence", + texture = "default_wood.png", + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + +#Walls API +--------- +The walls API allows easy addition of stone auto-connecting wall nodes. + +walls.register(name, desc, texture, mat, sounds) +^ name = "walls:stone_wall". Node name. +^ desc = "A Stone wall" +^ texture = "default_stone.png" +^ mat = "default:stone". Used to auto-generate crafting recipe. +^ sounds = sounds: see [#Default sounds] + +Farming API +----------- + +The farming API allows you to easily register plants and hoes. + +`farming.register_hoe(name, hoe definition)` + * Register a new hoe, see [#hoe definition] + +`farming.register_plant(name, Plant definition)` + * Register a new growing plant, see [#Plant definition] + +###Hoe Definition + + + { + description = "", -- Description for tooltip + inventory_image = "unknown_item.png", -- Image to be used as wield- and inventory image + max_uses = 30, -- Uses until destroyed + material = "", -- Material for recipes + recipe = { -- Craft recipe, if material isn't used + {"air", "air", "air"}, + {"", "group:stick"}, + {"", "group:stick"}, + } + } + +###Plant definition + + { + description = "", -- Description of seed item + inventory_image = "unknown_item.png", -- Image to be used as seed's wield- and inventory image + steps = 8, -- How many steps the plant has to grow, until it can be harvested + -- ^ Always provide a plant texture for each step, format: modname_plantname_i.png (i = stepnumber) + minlight = 13, -- Minimum light to grow + maxlight = default.LIGHT_MAX -- Maximum light to grow + } + +Fire API +-------- + +`on_burn(pos)` + + * Called when fire attempts to remove a burning node. + * `pos` Position of the burning node. + +Screwdriver API +--------------- + +The screwdriver API allows you to control a node's behaviour when a screwdriver is used on it. +To use it, add the `on_screwdriver` function to the node definition. + +`on_rotate(pos, node, user, mode, new_param2)` + + * `pos` Position of the node that the screwdriver is being used on + * `node` that node + * `user` The player who used the screwdriver + * `mode` screwdriver.ROTATE_FACE or screwdriver.ROTATE_AXIS + * `new_param2` the new value of param2 that would have been set if on_rotate wasn't there + * return value: false to disallow rotation, nil to keep default behaviour, true to allow + it but to indicate that changed have already been made (so the screwdriver will wear out) + * use `on_rotate = screwdriver.disallow` to always disallow rotation + * use `on_rotate = screwdriver.rotate_simple` to allow only face rotation + +Stairs API +---------- + +The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those +delivered with Minetest Game, to keep them compatible with other mods. + +`stairs.register_stair(subname, recipeitem, groups, images, description, sounds)` + + * Registers a stair. + * `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble" + * `groups`: see [Known damage and digging time defining groups] + * `images`: see [Tile definition] + * `description`: used for the description field in the stair's definition + * `sounds`: see [#Default sounds] + +`stairs.register_slab(subname, recipeitem, groups, images, description, sounds)` + + * Registers a slabs + * `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble" + * `groups`: see [Known damage and digging time defining groups] + * `images`: see [Tile definition] + * `description`: used for the description field in the stair's definition + * `sounds`: see [#Default sounds] + +`stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds)` + + * A wrapper for stairs.register_stair and stairs.register_slab + * Uses almost the same arguments as stairs.register_stair + * `desc_stair`: Description for stair node + * `desc_slab`: Description for slab node + +Xpanes API +---------- + +Creates panes that automatically connect to each other + +`xpanes.register_pane(subname, def)` + + * `subname`: used for nodename. Result: "xpanes:subname" and "xpanes:subname_{2..15}" + * `def`: See [#Pane definition] + +###Pane definition + + { + textures = {"texture_Bottom_top", "texture_left_right", "texture_front_back"}, -- More tiles aren't supported + groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups] + sounds = SoundSpec, -- See [#Default sounds] + recipe = {{"","","","","","","","",""}}, -- Recipe field only + } + +Raillike definitions +-------------------- + +The following nodes use the group `connect_to_raillike` and will only connect to +raillike nodes within this group and the same group value. +Use `minetest.raillike_group()` to get the group value. + +| Node type | Raillike group name +|-----------------------|--------------------- +| default:rail | "rail" +| tnt:gunpowder | "gunpowder" +| tnt:gunpowder_burning | "gunpowder" + +Example: +If you want to add a new rail type and want it to connect with default:rail, +add `connect_to_raillike=minetest.raillike_group("rail")` into the `groups` table +of your node. + + +Default sounds +-------------- + +Sounds inside the default table can be used within the sounds field of node definitions. + + * `default.node_sound_defaults()` + * `default.node_sound_stone_defaults()` + * `default.node_sound_dirt_defaults()` + * `default.node_sound_sand_defaults()` + * `default.node_sound_wood_defaults()` + * `default.node_sound_leaves_defaults()` + * `default.node_sound_glass_defaults()` + +Default constants +----------------- + +`default.LIGHT_MAX` The maximum light level (see [Node definition] light_source) + +Player API +---------- + +The player API can register player models and update the player's appearence + +`default.player_register_model(name, def)` + + * Register a new model to be used by players. + * name: model filename such as "character.x", "foo.b3d", etc. + * def: See [#Model definition] + +`default.registered_player_models[name]` + + * Get a model's definition + * see [#Model definition] + +`default.player_set_model(player, model_name)` + + * Change a player's model + * `player`: PlayerRef + * `model_name`: model registered with player_register_model() + +`default.player_set_animation(player, anim_name [, speed])` + + * Applies an animation to a player + * anim_name: name of the animation. + * speed: frames per second. If nil, default from the model is used + +`default.player_set_textures(player, textures)` + + * Sets player textures + * `player`: PlayerRef + * `textures`: array of textures, If `textures` is nil, the default textures from the model def are used + +default.player_get_animation(player) + + * Returns a table containing fields `model`, `textures` and `animation`. + * Any of the fields of the returned table may be nil. + * player: PlayerRef + +###Model Definition + + { + animation_speed = 30, -- Default animation speed, in FPS. + textures = {"character.png", }, -- Default array of textures. + visual_size = {x = 1, y = 1}, -- Used to scale the model. + animations = { + -- = {x = , y = }, + foo = {x = 0, y = 19}, + bar = {x = 20, y = 39}, + -- ... + }, + } + +Leafdecay +--------- + +To enable leaf decay for a node, add it to the `leafdecay` group. + +The rating of the group determines how far from a node in the group `tree` +the node can be without decaying. + +If `param2` of the node is ~= 0, the node will always be preserved. Thus, if +the player places a node of that kind, you will want to set `param2 = 1` or so. + +The function `default.after_place_leaves` can be set as `after_place_node of a node` +to set param2 to 1 if the player places the node (should not be used for nodes +that use param2 otherwise (e.g. facedir)). + +If the node is in the `leafdecay_drop` group then it will always be dropped as an +item. + +Dyes +---- + +To make recipes that will work with any dye ever made by anybody, define +them based on groups. You can select any group of groups, based on your need for +amount of colors. + +###Color groups + +Base color groups: + + * `basecolor_white` + * `basecolor_grey` + * `basecolor_black` + * `basecolor_red` + * `basecolor_yellow` + * `basecolor_green` + * `basecolor_cyan` + * `basecolor_blue` + * `basecolor_magenta` + +Extended color groups ( * means also base color ) + + * `excolor_white` * + * `excolor_lightgrey` + * `excolor_grey` * + * `excolor_darkgrey` + * `excolor_black` * + * `excolor_red` * + * `excolor_orange` + * `excolor_yellow` * + * `excolor_lime` + * `excolor_green` * + * `excolor_aqua` + * `excolor_cyan` * + * `excolor_sky_blue` + * `excolor_blue` * + * `excolor_violet` + * `excolor_magenta` * + * `excolor_red_violet` + +The whole unifieddyes palette as groups: + + * `unicolor_` + +For the following, no white/grey/black is allowed: + + * `unicolor_medium_` + * `unicolor_dark_` + * `unicolor_light_` + * `unicolor__s50` + * `unicolor_medium__s50` + * `unicolor_dark__s50` + +Example of one shapeless recipe using a color group: + + minetest.register_craft({ + type = "shapeless", + output = ':item_yellow', + recipe = {':item_no_color', 'group:basecolor_yellow'}, + }) + +###Color lists + + * `dye.basecolors` are an array containing the names of available base colors + + * `dye.excolors` are an array containing the names of the available extended colors + +Trees +----- + + * `default.grow_tree(pos, is_apple_tree)` + * Grows a mgv6 tree or apple tree at pos + + * `default.grow_jungle_tree(pos)` + * Grows a mgv6 jungletree at pos + + * `default.grow_pine_tree(pos)` + * Grows a mgv6 pinetree at pos + + * `default.grow_new_apple_tree(pos)` + * Grows a new design apple tree at pos + + * `default.grow_new_jungle_tree(pos)` + * Grows a new design jungle tree at pos + + * `default.grow_new_pine_tree(pos)` + * Grows a new design pine tree at pos + + * `default.grow_new_acacia_tree(pos)` + * Grows a new design acacia tree at pos + + * `default.grow_new_aspen_tree(pos)` + * Grows a new design aspen tree at pos + + * `default.grow_new_snowy_pine_tree(pos)` + * Grows a new design snowy pine tree at pos diff --git a/kingdoms_game/menu/header.png b/kingdoms_game/menu/header.png new file mode 100644 index 0000000..2ecda83 Binary files /dev/null and b/kingdoms_game/menu/header.png differ diff --git a/kingdoms_game/menu/icon.png b/kingdoms_game/menu/icon.png new file mode 100644 index 0000000..e6d0645 Binary files /dev/null and b/kingdoms_game/menu/icon.png differ diff --git a/kingdoms_game/minetest.conf b/kingdoms_game/minetest.conf new file mode 100644 index 0000000..e69de29 diff --git a/kingdoms_game/minetest.conf.example b/kingdoms_game/minetest.conf.example new file mode 100644 index 0000000..ac5b8f6 --- /dev/null +++ b/kingdoms_game/minetest.conf.example @@ -0,0 +1,40 @@ +# This file contains settings of Minetest Game that can be changed in minetest.conf +# By default, all the settings are commented and not functional. +# Uncomment settings by removing the preceding #. + +# Whether creative mode (fast digging of all blocks, unlimited resources) should be enabled +#creative_mode = false + +# The time in seconds after which the bones of a dead player can be looted by everyone +# 0 to disable +#share_bones_time = 1200 + +# How much earlier the bones of a dead player can be looted by +# everyone if the player dies in a protected area they don't own. +# 0 to disable. By default it is "share_bones_time" divide by four. +#share_bones_time_early = 300 + +# Whether standard fire should be disabled ('basic flame' nodes will disappear) +# 'permanent flame' nodes will remain with either setting +#disable_fire = false + +# Whether steel tools, torches and cobblestone should be given to new players +#give_initial_stuff = false + +# Whether the TNT mod should be enabled +#enable_tnt = + +# The radius of a TNT explosion +#tnt_radius = 3 + +# Enable the stairs mod ABM that replaces the old 'upside down' +# stair and slab nodes in old maps with the new param2 versions. +#enable_stairs_replace_abm = false + +# Whether you allow respawning in beds +# Default value is true +#enable_bed_respawn = true + +# Whether players can skip night by sleeping +# Default value is true +#enable_bed_night_skip = true diff --git a/kingdoms_game/mods/3d_armor-master/.gitignore b/kingdoms_game/mods/3d_armor-master/.gitignore new file mode 100644 index 0000000..6e4e459 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/.gitignore @@ -0,0 +1,8 @@ +## Generic ignorable patterns and files +*~ +.*.swp +*bak* +tags +*.vim +armor.conf + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/README.txt b/kingdoms_game/mods/3d_armor-master/3d_armor/README.txt new file mode 100644 index 0000000..224f81c --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/README.txt @@ -0,0 +1,24 @@ +[mod] Visible Player Armor [3d_armor] +===================================== + +Depends: default + +Recommends: inventory_plus or unified_inventory (use only one) + +Adds craftable armor that is visible to other players. Each armor item worn contributes to +a player's armor group level making them less vulnerable to weapons. + +Armor takes damage when a player is hurt but also offers a percentage chance of healing. +Overall level is boosted by 10% when wearing a full matching set. + +Fire protection added by TenPlus1 when using crystal armor if Ethereal mod active, level 1 +protects against torches, level 2 for crystal spike, level 3 for fire, level 5 for lava. + +Configuration +------------- + +Armor can be configured by adding a file called armor.conf in 3d_armor mod and/or world directory. +see armor.conf.example for all available options. + +Note: worldpath config settings override any settings made in the mod's directory. + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/admin.lua b/kingdoms_game/mods/3d_armor-master/3d_armor/admin.lua new file mode 100644 index 0000000..485a971 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/admin.lua @@ -0,0 +1,45 @@ +minetest.register_alias("adminboots","3d_armor:boots_admin") +minetest.register_alias("adminhelmet","3d_armor:helmet_admin") +minetest.register_alias("adminchestplate","3d_armor:chestplate_admin") +minetest.register_alias("adminlegginss","3d_armor:leggings_admin") + +minetest.register_tool("3d_armor:helmet_admin", { + description = "Admin Helmet", + inventory_image = "3d_armor_inv_helmet_admin.png", + groups = {armor_head=1000, armor_heal=1000, armor_use=0, not_in_creative_inventory=1}, + wear = 0, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +minetest.register_tool("3d_armor:chestplate_admin", { + description = "Admin Chestplate", + inventory_image = "3d_armor_inv_chestplate_admin.png", + groups = {armor_torso=1000, armor_heal=1000, armor_use=0, not_in_creative_inventory=1}, + wear = 0, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +minetest.register_tool("3d_armor:leggings_admin", { + description = "Admin Leggings", + inventory_image = "3d_armor_inv_leggings_admin.png", + groups = {armor_legs=1000, armor_heal=1000, armor_use=0, not_in_creative_inventory=1}, + wear = 0, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +minetest.register_tool("3d_armor:boots_admin", { + description = "Admin Boots", + inventory_image = "3d_armor_inv_boots_admin.png", + groups = {armor_feet=1000, armor_heal=1000, armor_use=0, not_in_creative_inventory=1}, + wear = 0, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/armor.conf.example b/kingdoms_game/mods/3d_armor-master/3d_armor/armor.conf.example new file mode 100644 index 0000000..15cfe91 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/armor.conf.example @@ -0,0 +1,56 @@ +-- Armor Configuration (defaults) + +-- You can remove any unwanted armor materials from this table. +-- Note that existing armor that is removed will show up as an unknown item. +ARMOR_MATERIALS = { + wood = "group:wood", + cactus = "default:cactus", + steel = "default:steel_ingot", + bronze = "default:bronze_ingot", + diamond = "default:diamond", + gold = "default:gold_ingot", + mithril = "moreores:mithril_ingot", + crystal = "ethereal:crystal_ingot", +} + +-- Enable fire protection (defaults true if using ethereal mod) +ARMOR_FIRE_PROTECT = false + +-- Fire protection nodes, (name, protection level, damage) +ARMOR_FIRE_NODES = { + {"default:lava_source", 5, 4}, + {"default:lava_flowing", 5, 4}, + {"fire:basic_flame", 3, 4}, + {"ethereal:crystal_spike", 2, 1}, + {"bakedclay:safe_fire", 2, 1}, + {"default:torch", 1, 1}, +} + +-- Increase this if you get initialization glitches when a player first joins. +ARMOR_INIT_DELAY = 1 + +-- Number of initialization attempts. +-- Use in conjunction with ARMOR_INIT_DELAY if initialization problems persist. +ARMOR_INIT_TIMES = 1 + +-- Increase this if armor is not getting into bones due to server lag. +ARMOR_BONES_DELAY = 1 + +-- How often player armor/wield items are updated. +ARMOR_UPDATE_TIME = 1 + +-- Drop armor when a player dies. +-- Uses bones mod if present, otherwise items are dropped around the player. +ARMOR_DROP = true + +-- Pulverise armor when a player dies, overrides ARMOR_DROP. +ARMOR_DESTROY = false + +-- You can use this to increase or decrease overall armor effectiveness, +-- eg: ARMOR_LEVEL_MULTIPLIER = 0.5 will reduce armor level by half. +ARMOR_LEVEL_MULTIPLIER = 1 + +-- You can use this to increase or decrease overall armor healing, +-- eg: ARMOR_HEAL_MULTIPLIER = 0 will disable healing altogether. +ARMOR_HEAL_MULTIPLIER = 1 + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/armor.lua b/kingdoms_game/mods/3d_armor-master/3d_armor/armor.lua new file mode 100644 index 0000000..6b62d14 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/armor.lua @@ -0,0 +1,603 @@ +ARMOR_INIT_DELAY = 1 +ARMOR_INIT_TIMES = 1 +ARMOR_BONES_DELAY = 1 +ARMOR_UPDATE_TIME = 1 +ARMOR_DROP = minetest.get_modpath("bones") ~= nil +ARMOR_DESTROY = false +ARMOR_LEVEL_MULTIPLIER = 1 +ARMOR_HEAL_MULTIPLIER = 1 +ARMOR_MATERIALS = { + wood = "group:wood", + --cactus = "default:cactus", + steel = "default:steel_ingot", + bronze = "default:bronze_ingot", + --diamond = "default:diamond", + gold = "default:gold_ingot", + --mithril = "moreores:mithril_ingot", + --crystal = "ethereal:crystal_ingot", +} +ARMOR_FIRE_PROTECT = minetest.get_modpath("ethereal") ~= nil +ARMOR_FIRE_NODES = { + {"default:lava_source", 5, 4}, + {"default:lava_flowing", 5, 4}, + {"fire:basic_flame", 3, 4}, + {"ethereal:crystal_spike", 2, 1}, + {"bakedclay:safe_fire", 2, 1}, + {"default:torch", 1, 1}, +} + +local skin_mod = nil +local inv_mod = nil + +local modpath = minetest.get_modpath(ARMOR_MOD_NAME) +local worldpath = minetest.get_worldpath() +local input = io.open(modpath.."/armor.conf", "r") +if input then + dofile(modpath.."/armor.conf") + input:close() + input = nil +end +input = io.open(worldpath.."/armor.conf", "r") +if input then + dofile(worldpath.."/armor.conf") + input:close() + input = nil +end +if not minetest.get_modpath("moreores") then + ARMOR_MATERIALS.mithril = nil +end +if not minetest.get_modpath("ethereal") then + ARMOR_MATERIALS.crystal = nil +end + +armor = { + timer = 0, + elements = {"head", "torso", "legs", "feet"}, + physics = {"jump","speed","gravity"}, + formspec = "size[8,8.5]image[2,0.75;2,4;armor_preview]" + .."list[current_player;main;0,4.5;8,4;]" + .."list[current_player;craft;4,1;3,3;]" + .."list[current_player;craftpreview;7,2;1,1;]" + .."listring[current_player;main]" + .."listring[current_player;craft]", + textures = {}, + default_skin = "character", + version = "0.4.5", +} + +if minetest.get_modpath("inventory_plus") then + inv_mod = "inventory_plus" + armor.formspec = "size[8,8.5]button[0,0;2,0.5;main;Back]" + .."image[2.5,0.75;2,4;armor_preview]" + .."label[5,1;Level: armor_level]" + .."label[5,1.5;Heal: armor_heal]" + .."label[5,2;Fire: armor_fire]" + .."list[current_player;main;0,4.5;8,4;]" + if minetest.get_modpath("crafting") then + inventory_plus.get_formspec = function(player, page) + end + end +elseif minetest.get_modpath("unified_inventory") then + inv_mod = "unified_inventory" + unified_inventory.register_button("armor", { + type = "image", + image = "inventory_plus_armor.png", + }) + unified_inventory.register_page("armor", { + get_formspec = function(player, perplayer_formspec) + local fy = perplayer_formspec.formspec_y + local name = player:get_player_name() + local formspec = "background[0.06,"..fy..";7.92,7.52;3d_armor_ui_form.png]" + .."label[0,0;Armor]" + .."list[detached:"..name.."_armor;armor;0,"..fy..";2,3;]" + .."image[2.5,"..(fy - 0.25)..";2,4;"..armor.textures[name].preview.."]" + .."label[5.0,"..(fy + 0.0)..";Level: "..armor.def[name].level.."]" + .."label[5.0,"..(fy + 0.5)..";Heal: "..armor.def[name].heal.."]" + .."label[5.0,"..(fy + 1.0)..";Fire: "..armor.def[name].fire.."]" + .."listring[current_player;main]" + .."listring[detached:"..name.."_armor;armor]" + return {formspec=formspec} + end, + }) +elseif minetest.get_modpath("inventory_enhanced") then + inv_mod = "inventory_enhanced" +end + +if minetest.get_modpath("skins") then + skin_mod = "skins" +elseif minetest.get_modpath("simple_skins") then + skin_mod = "simple_skins" +elseif minetest.get_modpath("u_skins") then + skin_mod = "u_skins" +elseif minetest.get_modpath("wardrobe") then + skin_mod = "wardrobe" +end + +armor.def = { + state = 0, + count = 0, +} + +--bloody player code +bloodskin = "blood_0.png" +minetest.register_on_player_hpchange(function(player, hp_change) + local hp = player:get_hp(player) + if hp <= 6 then + bloodskin = "blood_3.png" + elseif hp <= 10 then + bloodskin = "blood_2.png" + elseif hp <= 16 then + bloodskin = "blood_1.png" + elseif hp > 16 then + bloodskin = "blood_0.png" + end + armor:set_player_armor(player) +end)--]] + +armor.update_player_visuals = function(self, player) + if not player then + return + end + local name = player:get_player_name() + if self.textures[name] then + default.player_set_textures(player, { + self.textures[name].skin.."^"..bloodskin, + self.textures[name].armor, + self.textures[name].wielditem, + }) + end +end + +armor.set_player_armor = function(self, player) + local name, player_inv = armor:get_valid_player(player, "[set_player_armor]") + if not name then + return + end + local armor_texture = "3d_armor_trans.png" + local armor_level = 0 + local armor_heal = 0 + local armor_fire = 0 + local state = 0 + local items = 0 + local elements = {} + local textures = {} + local physics_o = {speed=1,gravity=1,jump=1} + local material = {type=nil, count=1} + local preview = armor:get_preview(name) or "character_preview.png" + for _,v in ipairs(self.elements) do + elements[v] = false + end + for i=1, 6 do + local stack = player_inv:get_stack("armor", i) + local item = stack:get_name() + if stack:get_count() == 1 then + local def = stack:get_definition() + for k, v in pairs(elements) do + if v == false then + local level = def.groups["armor_"..k] + if level then + local texture = def.texture or item:gsub("%:", "_") + table.insert(textures, texture..".png") + preview = preview.."^"..texture.."_preview.png" + armor_level = armor_level + level + state = state + stack:get_wear() + items = items + 1 + local heal = def.groups["armor_heal"] or 0 + armor_heal = armor_heal + heal + local fire = def.groups["armor_fire"] or 0 + armor_fire = armor_fire + fire + for kk,vv in ipairs(self.physics) do + local o_value = def.groups["physics_"..vv] + if o_value then + physics_o[vv] = physics_o[vv] + o_value + end + end + local mat = string.match(item, "%:.+_(.+)$") + if material.type then + if material.type == mat then + material.count = material.count + 1 + end + else + material.type = mat + end + elements[k] = true + end + end + end + end + end + if minetest.get_modpath("shields") then + armor_level = armor_level * 0.9 + end + if material.type and material.count == #self.elements then + armor_level = armor_level * 1.1 + end + armor_level = armor_level * ARMOR_LEVEL_MULTIPLIER + armor_heal = armor_heal * ARMOR_HEAL_MULTIPLIER + if #textures > 0 then + armor_texture = table.concat(textures, "^") + end + local armor_groups = {fleshy=100} + if armor_level > 0 then + armor_groups.level = math.floor(armor_level / 20) + armor_groups.fleshy = 100 - armor_level + end + player:set_armor_groups(armor_groups) + player:set_physics_override(physics_o) + self.textures[name].armor = armor_texture + self.textures[name].preview = preview + self.def[name].state = state + self.def[name].count = items + self.def[name].level = armor_level + self.def[name].heal = armor_heal + self.def[name].jump = physics_o.jump + self.def[name].speed = physics_o.speed + self.def[name].gravity = physics_o.gravity + self.def[name].fire = armor_fire + self:update_player_visuals(player) +end + +armor.update_armor = function(self, player) + -- Legacy support: Called when armor levels are changed + -- Other mods can hook on to this function, see hud mod for example +end + +armor.get_player_skin = function(self, name) + local skin = nil + if skin_mod == "skins" or skin_mod == "simple_skins" then + skin = skins.skins[name] + elseif skin_mod == "u_skins" then + skin = u_skins.u_skins[name] + elseif skin_mod == "wardrobe" then + skin = string.gsub(wardrobe.playerSkins[name], "%.png$","") + end + return skin or armor.default_skin +end + +armor.get_preview = function(self, name) + if skin_mod == "skins" then + return armor:get_player_skin(name).."_preview.png" + end +end + +armor.get_armor_formspec = function(self, name) + if not armor.textures[name] then + minetest.log("error", "3d_armor: Player texture["..name.."] is nil [get_armor_formspec]") + return "" + end + if not armor.def[name] then + minetest.log("error", "3d_armor: Armor def["..name.."] is nil [get_armor_formspec]") + return "" + end + local formspec = armor.formspec.."list[detached:"..name.."_armor;armor;0,1;2,3;]" + formspec = formspec:gsub("armor_preview", armor.textures[name].preview) + formspec = formspec:gsub("armor_level", armor.def[name].level) + formspec = formspec:gsub("armor_heal", armor.def[name].heal) + formspec = formspec:gsub("armor_fire", armor.def[name].fire) + return formspec +end + +armor.update_inventory = function(self, player) + local name = armor:get_valid_player(player, "[set_player_armor]") + if not name or inv_mod == "inventory_enhanced" then + return + end + if inv_mod == "unified_inventory" then + if unified_inventory.current_page[name] == "armor" then + unified_inventory.set_inventory_formspec(player, "armor") + end + else + local formspec = armor:get_armor_formspec(name) + if inv_mod == "inventory_plus" then + formspec = formspec.."listring[current_player;main]" + .."listring[detached:"..name.."_armor;armor]" + local page = player:get_inventory_formspec() + if page:find("detached:"..name.."_armor") then + inventory_plus.set_inventory_formspec(player, formspec) + end + else + player:set_inventory_formspec(formspec) + end + end +end + +armor.get_valid_player = function(self, player, msg) + msg = msg or "" + if not player then + minetest.log("error", "3d_armor: Player reference is nil "..msg) + return + end + local name = player:get_player_name() + if not name then + minetest.log("error", "3d_armor: Player name is nil "..msg) + return + end + local pos = player:getpos() + local player_inv = player:get_inventory() + local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"}) + if not pos then + minetest.log("error", "3d_armor: Player position is nil "..msg) + return + elseif not player_inv then + minetest.log("error", "3d_armor: Player inventory is nil "..msg) + return + elseif not armor_inv then + minetest.log("error", "3d_armor: Detached armor inventory is nil "..msg) + return + end + return name, player_inv, armor_inv, pos +end + +-- Register Player Model + +default.player_register_model("3d_armor_character.b3d", { + animation_speed = 30, + textures = { + armor.default_skin..".png", + "3d_armor_trans.png", + "3d_armor_trans.png", + }, + animations = { + stand = {x=0, y=79}, + lay = {x=162, y=166}, + walk = {x=168, y=187}, + mine = {x=189, y=198}, + walk_mine = {x=200, y=219}, + sit = {x=81, y=160}, + }, +}) + +-- Register Callbacks + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local name = armor:get_valid_player(player, "[on_player_receive_fields]") + if not name or inv_mod == "inventory_enhanced" then + return + end + if inv_mod == "inventory_plus" and fields.armor then + local formspec = armor:get_armor_formspec(name) + inventory_plus.set_inventory_formspec(player, formspec) + return + end + for field, _ in pairs(fields) do + if string.find(field, "skins_set") then + minetest.after(0, function(player) + local skin = armor:get_player_skin(name) + armor.textures[name].skin = skin..".png" + armor:set_player_armor(player) + end, player) + end + end +end) + +minetest.register_on_joinplayer(function(player) + default.player_set_model(player, "3d_armor_character.b3d") + local name = player:get_player_name() + local player_inv = player:get_inventory() + local armor_inv = minetest.create_detached_inventory(name.."_armor", { + on_put = function(inv, listname, index, stack, player) + player:get_inventory():set_stack(listname, index, stack) + armor:set_player_armor(player) + armor:update_inventory(player) + end, + on_take = function(inv, listname, index, stack, player) + player:get_inventory():set_stack(listname, index, nil) + armor:set_player_armor(player) + armor:update_inventory(player) + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + local plaver_inv = player:get_inventory() + local stack = inv:get_stack(to_list, to_index) + player_inv:set_stack(to_list, to_index, stack) + player_inv:set_stack(from_list, from_index, nil) + armor:set_player_armor(player) + armor:update_inventory(player) + end, + allow_put = function(inv, listname, index, stack, player) + return 1 + end, + allow_take = function(inv, listname, index, stack, player) + return stack:get_count() + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return count + end, + }) + if inv_mod == "inventory_plus" then + inventory_plus.register_button(player,"armor", "Armor") + end + armor_inv:set_size("armor", 6) + player_inv:set_size("armor", 6) + for i=1, 6 do + local stack = player_inv:get_stack("armor", i) + armor_inv:set_stack("armor", i, stack) + end + armor.def[name] = { + state = 0, + count = 0, + level = 0, + heal = 0, + jump = 1, + speed = 1, + gravity = 1, + fire = 0, + } + armor.textures[name] = { + skin = armor.default_skin..".png", + armor = "3d_armor_trans.png", + wielditem = "3d_armor_trans.png", + preview = armor.default_skin.."_preview.png", + } + if skin_mod == "skins" then + local skin = skins.skins[name] + if skin and skins.get_type(skin) == skins.type.MODEL then + armor.textures[name].skin = skin..".png" + end + elseif skin_mod == "simple_skins" then + local skin = skins.skins[name] + if skin then + armor.textures[name].skin = skin..".png" + end + elseif skin_mod == "u_skins" then + local skin = u_skins.u_skins[name] + if skin and u_skins.get_type(skin) == u_skins.type.MODEL then + armor.textures[name].skin = skin..".png" + end + elseif skin_mod == "wardrobe" then + local skin = wardrobe.playerSkins[name] + if skin then + armor.textures[name].skin = skin + end + end + if minetest.get_modpath("player_textures") then + local filename = minetest.get_modpath("player_textures").."/textures/player_"..name + local f = io.open(filename..".png") + if f then + f:close() + armor.textures[name].skin = "player_"..name..".png" + end + end + for i=1, ARMOR_INIT_TIMES do + minetest.after(ARMOR_INIT_DELAY * i, function(player) + armor:set_player_armor(player) + if not inv_mod then + armor:update_inventory(player) + end + end, player) + end +end) + +if ARMOR_DROP == true or ARMOR_DESTROY == true then + armor.drop_armor = function(pos, stack) + local obj = minetest.add_item(pos, stack) + if obj then + obj:setvelocity({x=math.random(-1, 1), y=5, z=math.random(-1, 1)}) + end + end + minetest.register_on_dieplayer(function(player) + local name, player_inv, armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]") + if not name then + return + end + local drop = {} + for i=1, player_inv:get_size("armor") do + local stack = armor_inv:get_stack("armor", i) + if stack:get_count() > 0 then + table.insert(drop, stack) + armor_inv:set_stack("armor", i, nil) + player_inv:set_stack("armor", i, nil) + end + end + armor:set_player_armor(player) + if inv_mod == "unified_inventory" then + unified_inventory.set_inventory_formspec(player, "craft") + elseif inv_mod == "inventory_plus" then + local formspec = inventory_plus.get_formspec(player,"main") + inventory_plus.set_inventory_formspec(player, formspec) + else + armor:update_inventory(player) + end + if ARMOR_DESTROY == false then + minetest.after(ARMOR_BONES_DELAY, function() + local node = minetest.get_node(vector.round(pos)) + if node then + if node.name == "bones:bones" then + local meta = minetest.get_meta(vector.round(pos)) + local owner = meta:get_string("owner") + local inv = meta:get_inventory() + for _,stack in ipairs(drop) do + if name == owner and inv:room_for_item("main", stack) then + inv:add_item("main", stack) + else + armor.drop_armor(pos, stack) + end + end + end + else + for _,stack in ipairs(drop) do + armor.drop_armor(pos, stack) + end + end + end) + end + end) +end + +minetest.register_on_player_hpchange(function(player, hp_change) + local name, player_inv, armor_inv = armor:get_valid_player(player, "[on_hpchange]") + if name and hp_change < 0 then + local heal_max = 0 + local state = 0 + local items = 0 + for i=1, 6 do + local stack = player_inv:get_stack("armor", i) + if stack:get_count() > 0 then + local use = stack:get_definition().groups["armor_use"] or 0 + local heal = stack:get_definition().groups["armor_heal"] or 0 + local item = stack:get_name() + stack:add_wear(use) + armor_inv:set_stack("armor", i, stack) + player_inv:set_stack("armor", i, stack) + state = state + stack:get_wear() + items = items + 1 + if stack:get_count() == 0 then + local desc = minetest.registered_items[item].description + if desc then + minetest.chat_send_player(name, "Your "..desc.." got destroyed!") + end + armor:set_player_armor(player) + armor:update_inventory(player) + end + heal_max = heal_max + heal + end + end + armor.def[name].state = state + armor.def[name].count = items + heal_max = heal_max * ARMOR_HEAL_MULTIPLIER + if heal_max > math.random(100) then + hp_change = 0 + end + armor:update_armor(player) + end + return hp_change +end, true) + +-- Fire Protection, added by TenPlus1 + +if ARMOR_FIRE_PROTECT == true then + -- override hot nodes so they do not hurt player anywhere but mod + for _, row in ipairs(ARMOR_FIRE_NODES) do + if minetest.registered_nodes[row[1]] then + minetest.override_item(row[1], {damage_per_second = 0}) + end + end + minetest.register_globalstep(function(dtime) + armor.timer = armor.timer + dtime + if armor.timer > ARMOR_UPDATE_TIME then + for _,player in ipairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local pos = player:getpos() + local hp = player:get_hp() + if name and pos and hp then + pos.y = pos.y + 1.4 -- head level + local node_head = minetest.get_node(pos).name + pos.y = pos.y - 1.2 -- feet level + local node_feet = minetest.get_node(pos).name + -- is player inside a hot node? + for _, row in ipairs(ARMOR_FIRE_NODES) do + -- check fire protection, if not enough then get hurt + if row[1] == node_head or row[1] == node_feet then + if hp > 0 and armor.def[name].fire < row[2] then + hp = hp - row[3] * ARMOR_UPDATE_TIME + player:set_hp(hp) + break + end + end + end + end + end + armor.timer = 0 + end + end) +end + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/crafting_guide.txt b/kingdoms_game/mods/3d_armor-master/3d_armor/crafting_guide.txt new file mode 100644 index 0000000..abd1519 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/crafting_guide.txt @@ -0,0 +1,79 @@ +3d_armor -- Crafting Guide +-------------------------- + +Helmets: + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | | X | ++---+---+---+ +| | | | ++---+---+---+ + +[3d_armor:helmet_wood] X = [default:wood] +[3d_armor:helmet_cactus] X = [default:cactus] +[3d_armor:helmet_steel] X = [default:steel_ingot] +[3d_armor:helmet_bronze] X = [default:bronze_ingot] +[3d_armor:helmet_diamond] X = [default:diamond] +[3d_armor:helmet_gold] X = [default:gold_ingot] +[3d_armor:helmet_mithril] X = [moreores:mithril_ingot] * +[3d_armor:helmet_crystal] X = [ethereal:crystal_ingot] ** + +Chestplates: + ++---+---+---+ +| X | | X | ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | X | X | ++---+---+---+ + +[3d_armor:chestplate_wood] X = [default:wood] +[3d_armor:chestplate_cactus] X = [default:cactus] +[3d_armor:chestplate_steel] X = [default:steel_ingot] +[3d_armor:chestplate_bronze] X = [default:bronze_ingot] +[3d_armor:chestplate_diamond] X = [default:diamond] +[3d_armor:chestplate_gold] X = [default:gold_ingot] +[3d_armor:chestplate_mithril] X = [moreores:mithril_ingot] * +[3d_armor:chestplate_crystal] X = [ethereal:crystal_ingot] ** + +Leggings: + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | | X | ++---+---+---+ +| X | | X | ++---+---+---+ + +[3d_armor:leggings_wood] X = [default:wood] +[3d_armor:leggings_cactus] X = [default:cactus] +[3d_armor:leggings_steel] X = [default:steel_ingot] +[3d_armor:leggings_bronze] X = [default:bronze_ingot] +[3d_armor:leggings_diamond] X = [default:diamond] +[3d_armor:leggings_gold] X = [default:gold_ingot] +[3d_armor:leggings_mithril] X = [moreores:mithril_ingot] * +[3d_armor:leggings_crystal] X = [ethereal:crystal_ingot] ** + +Boots: + ++---+---+---+ +| X | | X | ++---+---+---+ +| X | | X | ++---+---+---+ + +[3d_armor:boots_wood] X = [default:wood] +[3d_armor:boots_cactus] X = [default:cactus] +[3d_armor:boots_steel] X = [default:steel_ingot] +[3d_armor:boots_bronze] X = [default:bronze_ingot +[3d_armor:boots_diamond] X = [default:diamond] +[3d_armor:boots_gold] X = [default:gold_ingot] +[3d_armor:boots_mithril] X = [moreores:mithril_ingot] * +[3d_armor:boots_crystal] X = [ethereal:crystal_ingot] ** + + * Requires moreores mod by Calinou - https://forum.minetest.net/viewtopic.php?id=549 +** Requires ethereal mod by Chinchow & TenPlus1 - https://github.com/tenplus1/ethereal diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/depends.txt b/kingdoms_game/mods/3d_armor-master/3d_armor/depends.txt new file mode 100644 index 0000000..3acf737 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/depends.txt @@ -0,0 +1,6 @@ +default +inventory_plus? +unified_inventory? +fire? +ethereal? +bakedclay? diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/init.lua b/kingdoms_game/mods/3d_armor-master/3d_armor/init.lua new file mode 100644 index 0000000..0c8bac8 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor/init.lua @@ -0,0 +1,281 @@ +ARMOR_MOD_NAME = minetest.get_current_modname() +dofile(minetest.get_modpath(ARMOR_MOD_NAME).."/armor.lua") +dofile(minetest.get_modpath(ARMOR_MOD_NAME).."/admin.lua") + +if ARMOR_MATERIALS.wood then + minetest.register_tool("3d_armor:helmet_wood", { + description = "Wood Helmet", + inventory_image = "3d_armor_inv_helmet_wood.png", + groups = {armor_head=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_wood", { + description = "Wood Chestplate", + inventory_image = "3d_armor_inv_chestplate_wood.png", + groups = {armor_torso=10, armor_heal=0, armor_use=2000}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_wood", { + description = "Wood Leggings", + inventory_image = "3d_armor_inv_leggings_wood.png", + groups = {armor_legs=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_wood", { + description = "Wood Boots", + inventory_image = "3d_armor_inv_boots_wood.png", + groups = {armor_feet=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.cactus then + minetest.register_tool("3d_armor:helmet_cactus", { + description = "Cactuc Helmet", + inventory_image = "3d_armor_inv_helmet_cactus.png", + groups = {armor_head=5, armor_heal=0, armor_use=1000}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_cactus", { + description = "Cactus Chestplate", + inventory_image = "3d_armor_inv_chestplate_cactus.png", + groups = {armor_torso=10, armor_heal=0, armor_use=1000}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_cactus", { + description = "Cactus Leggings", + inventory_image = "3d_armor_inv_leggings_cactus.png", + groups = {armor_legs=5, armor_heal=0, armor_use=1000}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_cactus", { + description = "Cactus Boots", + inventory_image = "3d_armor_inv_boots_cactus.png", + groups = {armor_feet=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.steel then + minetest.register_tool("3d_armor:helmet_steel", { + description = "Steel Helmet", + inventory_image = "3d_armor_inv_helmet_steel.png", + groups = {armor_head=10, armor_heal=0, armor_use=500, physics_speed=-0.05}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_steel", { + description = "Steel Chestplate", + inventory_image = "3d_armor_inv_chestplate_steel.png", + groups = {armor_torso=15, armor_heal=0, armor_use=500, physics_speed=-0.1}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_steel", { + description = "Steel Leggings", + inventory_image = "3d_armor_inv_leggings_steel.png", + groups = {armor_legs=15, armor_heal=0, armor_use=500, physics_speed=-0.1}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_steel", { + description = "Steel Boots", + inventory_image = "3d_armor_inv_boots_steel.png", + groups = {armor_feet=10, armor_heal=0, armor_use=500, physics_speed=-0.05}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.bronze then + minetest.register_tool("3d_armor:helmet_bronze", { + description = "Bronze Helmet", + inventory_image = "3d_armor_inv_helmet_bronze.png", + groups = {armor_head=10, armor_heal=2, armor_use=250, physics_speed=-0.06}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_bronze", { + description = "Bronze Chestplate", + inventory_image = "3d_armor_inv_chestplate_bronze.png", + groups = {armor_torso=15, armor_heal=2, armor_use=250, physics_speed=-0.11}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_bronze", { + description = "Bronze Leggings", + inventory_image = "3d_armor_inv_leggings_bronze.png", + groups = {armor_legs=15, armor_heal=2, armor_use=250, physics_speed=-0.11}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_bronze", { + description = "Bronze Boots", + inventory_image = "3d_armor_inv_boots_bronze.png", + groups = {armor_feet=10, armor_heal=2, armor_use=250, physics_speed=-0.06}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.diamond then + minetest.register_tool("3d_armor:helmet_diamond", { + description = "Diamond Helmet", + inventory_image = "3d_armor_inv_helmet_diamond.png", + groups = {armor_head=15, armor_heal=12, armor_use=100}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_diamond", { + description = "Diamond Chestplate", + inventory_image = "3d_armor_inv_chestplate_diamond.png", + groups = {armor_torso=20, armor_heal=12, armor_use=100}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_diamond", { + description = "Diamond Leggings", + inventory_image = "3d_armor_inv_leggings_diamond.png", + groups = {armor_legs=20, armor_heal=12, armor_use=100}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_diamond", { + description = "Diamond Boots", + inventory_image = "3d_armor_inv_boots_diamond.png", + groups = {armor_feet=15, armor_heal=12, armor_use=100}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.gold then + minetest.register_tool("3d_armor:helmet_gold", { + description = "Gold Helmet", + inventory_image = "3d_armor_inv_helmet_gold.png", + groups = {armor_head=10, armor_heal=4, armor_use=250, physics_speed=-0.1}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_gold", { + description = "Gold Chestplate", + inventory_image = "3d_armor_inv_chestplate_gold.png", + groups = {armor_torso=15, armor_heal=4, armor_use=250, physics_speed=-0.15}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_gold", { + description = "Gold Leggings", + inventory_image = "3d_armor_inv_leggings_gold.png", + groups = {armor_legs=15, armor_heal=4, armor_use=250, physics_speed=-0.15}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_gold", { + description = "Gold Boots", + inventory_image = "3d_armor_inv_boots_gold.png", + groups = {armor_feet=10, armor_heal=4, armor_use=250, physics_speed=-0.1}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.mithril then + minetest.register_tool("3d_armor:helmet_mithril", { + description = "Mithril Helmet", + inventory_image = "3d_armor_inv_helmet_mithril.png", + groups = {armor_head=15, armor_heal=12, armor_use=50}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_mithril", { + description = "Mithril Chestplate", + inventory_image = "3d_armor_inv_chestplate_mithril.png", + groups = {armor_torso=20, armor_heal=12, armor_use=50}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_mithril", { + description = "Mithril Leggings", + inventory_image = "3d_armor_inv_leggings_mithril.png", + groups = {armor_legs=20, armor_heal=12, armor_use=50}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_mithril", { + description = "Mithril Boots", + inventory_image = "3d_armor_inv_boots_mithril.png", + groups = {armor_feet=15, armor_heal=12, armor_use=50}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.crystal then + minetest.register_tool("3d_armor:helmet_crystal", { + description = "Crystal Helmet", + inventory_image = "3d_armor_inv_helmet_crystal.png", + groups = {armor_head=15, armor_heal=12, armor_use=50, armor_fire=1}, + wear = 0, + }) + minetest.register_tool("3d_armor:chestplate_crystal", { + description = "Crystal Chestplate", + inventory_image = "3d_armor_inv_chestplate_crystal.png", + groups = {armor_torso=20, armor_heal=12, armor_use=50, armor_fire=1}, + wear = 0, + }) + minetest.register_tool("3d_armor:leggings_crystal", { + description = "Crystal Leggings", + inventory_image = "3d_armor_inv_leggings_crystal.png", + groups = {armor_legs=20, armor_heal=12, armor_use=50, armor_fire=1}, + wear = 0, + }) + minetest.register_tool("3d_armor:boots_crystal", { + description = "Crystal Boots", + inventory_image = "3d_armor_inv_boots_crystal.png", + groups = {armor_feet=15, armor_heal=12, armor_use=50, physics_speed=1, physics_jump=0.5, armor_fire=1}, + wear = 0, + }) +end + +for k, v in pairs(ARMOR_MATERIALS) do + minetest.register_craft({ + output = "3d_armor:helmet_"..k, + recipe = { + {v, v, v}, + {v, "", v}, + {"", "", ""}, + }, + }) + minetest.register_craft({ + output = "3d_armor:chestplate_"..k, + recipe = { + {v, "", v}, + {v, v, v}, + {v, v, v}, + }, + }) + minetest.register_craft({ + output = "3d_armor:leggings_"..k, + recipe = { + {v, v, v}, + {v, "", v}, + {v, "", v}, + }, + }) + minetest.register_craft({ + output = "3d_armor:boots_"..k, + recipe = { + {v, "", v}, + {v, "", v}, + }, + }) +--MELTING DOWN +if v ~= "group:wood" then + minetest.register_craft({ + output = v .. " 5", + type = "cooking", + cooktime = 14, + recipe = "3d_armor:helmet_"..k + }) + minetest.register_craft({ + output = v .. " 8", + type = "cooking", + cooktime = 14, + recipe = "3d_armor:chestplate_"..k + }) + minetest.register_craft({ + output = v .. " 7", + type = "cooking", + cooktime = 14, + recipe = "3d_armor:leggings_"..k + }) + minetest.register_craft({ + output = v .. " 4", + type = "cooking", + cooktime = 14, + recipe = "3d_armor:boots_"..k + }) + end +end + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.b3d b/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.b3d new file mode 100644 index 0000000..278956b Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.b3d differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.blend b/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.blend new file mode 100644 index 0000000..5ded978 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/models/3d_armor_character.blend differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin.png new file mode 100644 index 0000000..a05e4c5 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin_preview.png new file mode 100644 index 0000000..d61ab25 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_admin_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze.png new file mode 100644 index 0000000..7cfe378 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze_preview.png new file mode 100644 index 0000000..6da8019 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_bronze_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold.png new file mode 100644 index 0000000..2de3966 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold_preview.png new file mode 100644 index 0000000..5ca40ac Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_gold_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel.png new file mode 100644 index 0000000..4664be5 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel_preview.png new file mode 100644 index 0000000..25fc47a Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_steel_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood.png new file mode 100644 index 0000000..0ec5d6c Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood_preview.png new file mode 100644 index 0000000..53d6d15 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_boots_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin.png new file mode 100644 index 0000000..404d6e8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin_preview.png new file mode 100644 index 0000000..09325a5 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_admin_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze.png new file mode 100644 index 0000000..d9c7267 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze_preview.png new file mode 100644 index 0000000..90d887a Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_bronze_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold.png new file mode 100644 index 0000000..91b1631 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold_preview.png new file mode 100644 index 0000000..cb11321 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_gold_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel.png new file mode 100644 index 0000000..23cdbda Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel_preview.png new file mode 100644 index 0000000..0e45907 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_steel_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood.png new file mode 100644 index 0000000..ea7a1d7 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood_preview.png new file mode 100644 index 0000000..cdca575 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_chestplate_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin.png new file mode 100644 index 0000000..4d52d4c Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin_preview.png new file mode 100644 index 0000000..51ecb9b Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_admin_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze.png new file mode 100644 index 0000000..438002e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze_preview.png new file mode 100644 index 0000000..61fa1af Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_bronze_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold.png new file mode 100644 index 0000000..6fa3af5 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold_preview.png new file mode 100644 index 0000000..d2e7ac8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_gold_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel.png new file mode 100644 index 0000000..ec5c203 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel_preview.png new file mode 100644 index 0000000..2c8721c Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_steel_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood.png new file mode 100644 index 0000000..0bdb8f7 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood_preview.png new file mode 100644 index 0000000..fe1cead Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_helmet_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_admin.png new file mode 100644 index 0000000..f94c844 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_bronze.png new file mode 100644 index 0000000..7f5f968 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_gold.png new file mode 100644 index 0000000..8598cf9 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_steel.png new file mode 100644 index 0000000..77286b5 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_wood.png new file mode 100644 index 0000000..66993a1 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_boots_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_admin.png new file mode 100644 index 0000000..29f3897 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_bronze.png new file mode 100644 index 0000000..da2f3e0 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_gold.png new file mode 100644 index 0000000..1dddc3d Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_steel.png new file mode 100644 index 0000000..421b3e3 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_wood.png new file mode 100644 index 0000000..434374f Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_chestplate_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_admin.png new file mode 100644 index 0000000..e019702 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_bronze.png new file mode 100644 index 0000000..53cdaf1 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_gold.png new file mode 100644 index 0000000..e8f83d8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_steel.png new file mode 100644 index 0000000..4c636f2 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_wood.png new file mode 100644 index 0000000..e8ee2fe Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_helmet_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_admin.png new file mode 100644 index 0000000..04b64c0 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_bronze.png new file mode 100644 index 0000000..b574108 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_gold.png new file mode 100644 index 0000000..7424833 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_steel.png new file mode 100644 index 0000000..77ee17e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_wood.png new file mode 100644 index 0000000..f162e51 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_inv_leggings_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin.png new file mode 100644 index 0000000..6752256 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin_preview.png new file mode 100644 index 0000000..fe47999 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_admin_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze.png new file mode 100644 index 0000000..3394288 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze_preview.png new file mode 100644 index 0000000..c4aa7b9 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_bronze_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold.png new file mode 100644 index 0000000..d207dff Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold_preview.png new file mode 100644 index 0000000..75e6ca4 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_gold_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel.png new file mode 100644 index 0000000..78d5874 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel_preview.png new file mode 100644 index 0000000..3e3ec85 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_steel_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood.png new file mode 100644 index 0000000..3880fc0 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood_preview.png new file mode 100644 index 0000000..f8ee8e8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_leggings_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_trans.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_trans.png new file mode 100644 index 0000000..4d7beb8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_trans.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_ui_form.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_ui_form.png new file mode 100644 index 0000000..6e5cfee Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/3d_armor_ui_form.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_0.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_0.png new file mode 100644 index 0000000..444cdb8 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_0.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_1.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_1.png new file mode 100644 index 0000000..7345e8e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_1.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_2.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_2.png new file mode 100644 index 0000000..82b8d5c Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_2.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_3.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_3.png new file mode 100644 index 0000000..6f31d0e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/blood_3.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/character_preview.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/character_preview.png new file mode 100644 index 0000000..4ac4602 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/character_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor/textures/inventory_plus_armor.png b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/inventory_plus_armor.png new file mode 100644 index 0000000..6cde640 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor/textures/inventory_plus_armor.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/LICENSE.txt b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/LICENSE.txt new file mode 100644 index 0000000..65f46c8 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/LICENSE.txt @@ -0,0 +1,22 @@ +[mod] 3d Armor Stand [3d_armor_stand] +===================================== + +License Source Code: (C) 2016-2017 Stuart Jones - LGPL v2.1 + +Lecense Models: (C) 2016-2017 Stuart Jones - CC BY-SA 3.0 + +UV model mapping by tobyplowy(aka toby109tt) + +License Textures: + +3d_armor_stand.png +3d_armor_stand_locked.png + +(C) 2017 tobyplowy - CC BY-SA 3.0 + +3d_armor_stand_feet.png +3d_armor_stand_head.png +3d_armor_stand_legs.png +3d_armor_stand_torso.png + +(C) 2016-2017 Stuart Jones - CC BY-SA 3.0 diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/README.txt b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/README.txt new file mode 100644 index 0000000..6a98ab9 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/README.txt @@ -0,0 +1,21 @@ +[mod] 3d Armor Stand [3d_armor_stand] +===================================== + +Depends: 3d_armor + +Adds a chest-like armor stand for armor storage and display. + +Crafting +-------- + +F = Wooden Fence [default:fence_wood] +S = Steel Ingot [default:steel_ingot] + ++---+---+---+ +| | F | | ++---+---+---+ +| | F | | ++---+---+---+ +| S | S | S | ++---+---+---+ + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/depends.txt b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/depends.txt new file mode 100644 index 0000000..fdbb290 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/depends.txt @@ -0,0 +1,2 @@ +3d_armor + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/init.lua b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/init.lua new file mode 100644 index 0000000..48051d8 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/init.lua @@ -0,0 +1,301 @@ +local armor_stand_formspec = "size[8,7]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + default.get_hotbar_bg(0,3) .. + "list[current_name;armor_head;3,0.5;1,1;]" .. + "list[current_name;armor_torso;4,0.5;1,1;]" .. + "list[current_name;armor_legs;3,1.5;1,1;]" .. + "list[current_name;armor_feet;4,1.5;1,1;]" .. + "image[3,0.5;1,1;3d_armor_stand_head.png]" .. + "image[4,0.5;1,1;3d_armor_stand_torso.png]" .. + "image[3,1.5;1,1;3d_armor_stand_legs.png]" .. + "image[4,1.5;1,1;3d_armor_stand_feet.png]" .. + "list[current_player;main;0,3;8,1;]" .. + "list[current_player;main;0,4.25;8,3;8]" + +local elements = {"head", "torso", "legs", "feet"} + +local function get_stand_object(pos) + local object = nil + local objects = minetest.get_objects_inside_radius(pos, 0.5) or {} + for _, obj in pairs(objects) do + local ent = obj:get_luaentity() + if ent then + if ent.name == "3d_armor_stand:armor_entity" then + -- Remove duplicates + if object then + obj:remove() + else + object = obj + end + end + end + end + return object +end + +local function update_entity(pos) + local node = minetest.get_node(pos) + local object = get_stand_object(pos) + if object then + if not string.find(node.name, "3d_armor_stand:") then + object:remove() + return + end + else + object = minetest.add_entity(pos, "3d_armor_stand:armor_entity") + end + if object then + local texture = "3d_armor_trans.png" + local textures = {} + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local yaw = 0 + if inv then + for _, element in pairs(elements) do + local stack = inv:get_stack("armor_"..element, 1) + if stack:get_count() == 1 then + local item = stack:get_name() or "" + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups["armor_"..element] then + local texture = def.texture or item:gsub("%:", "_") + table.insert(textures, texture..".png") + end + end + end + end + if #textures > 0 then + texture = table.concat(textures, "^") + end + if node.param2 then + local rot = node.param2 % 4 + if rot == 1 then + yaw = 3 * math.pi / 2 + elseif rot == 2 then + yaw = math.pi + elseif rot == 3 then + yaw = math.pi / 2 + end + end + object:setyaw(yaw) + object:set_properties({textures={texture}}) + end +end + +local function has_locked_armor_stand_privilege(meta, player) + local name = "" + if player then + if minetest.check_player_privs(player, "protection_bypass") then + return true + end + name = player:get_player_name() + end + if name ~= meta:get_string("owner") then + return false + end + return true +end + +minetest.register_node("3d_armor_stand:armor_stand", { + description = "Armor stand", + drawtype = "mesh", + mesh = "3d_armor_stand.obj", + tiles = {"3d_armor_stand.png"}, + paramtype = "light", + paramtype2 = "facedir", + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.5,-0.5,-0.5, 0.5,1.4,0.5} + }, + groups = {choppy=2, oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", armor_stand_formspec) + meta:set_string("infotext", "Armor Stand") + local inv = meta:get_inventory() + for _, element in pairs(elements) do + inv:set_size("armor_"..element, 1) + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, element in pairs(elements) do + if not inv:is_empty("armor_"..element) then + return false + end + end + return true + end, + after_place_node = function(pos) + minetest.add_entity(pos, "3d_armor_stand:armor_entity") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack) + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups[listname] then + return 1 + end + return 0 + end, + allow_metadata_inventory_move = function(pos) + return 0 + end, + on_metadata_inventory_put = function(pos) + update_entity(pos) + end, + on_metadata_inventory_take = function(pos) + update_entity(pos) + end, + after_destruct = function(pos) + update_entity(pos) + end, + on_blast = function(pos) + local object = get_stand_object(pos) + if object then + object:remove() + end + minetest.after(1, function(pos) + update_entity(pos) + end, pos) + end, +}) + +minetest.register_node("3d_armor_stand:locked_armor_stand", { + description = "Protected Armor stand", + drawtype = "mesh", + mesh = "3d_armor_stand.obj", + tiles = {"3d_armor_stand_locked.png"}, + paramtype = "light", + paramtype2 = "facedir", + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.5,-0.5,-0.5, 0.5,1.4,0.5} + }, + groups = {choppy=2, oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", armor_stand_formspec) + meta:set_string("infotext", "Armor Stand") + meta:set_string("owner", "") + local inv = meta:get_inventory() + for _, element in pairs(elements) do + inv:set_size("armor_"..element, 1) + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, element in pairs(elements) do + if not inv:is_empty("armor_"..element) then + return false + end + end + return true + end, + after_place_node = function(pos, placer) + minetest.add_entity(pos, "3d_armor_stand:armor_entity") + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Protected Armor Stand") + --meta:set_string("owner", placer:get_player_name() or "") + --meta:set_string("infotext", "Armor Stand (owned by " .. + --meta:get_string("owner") .. ")") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups[listname] then + if not minetest.is_protected(pos, player:get_player_name()) then + return 1 + end + end + return 0 + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() + end, + allow_metadata_inventory_move = function(pos) + return 0 + end, + on_metadata_inventory_put = function(pos) + update_entity(pos) + end, + on_metadata_inventory_take = function(pos) + update_entity(pos) + end, + after_destruct = function(pos) + update_entity(pos) + end, + on_blast = function(pos) + local object = get_stand_object(pos) + if object then + object:remove() + end + minetest.after(1, function(pos) + update_entity(pos) + end, pos) + end, +}) + +minetest.register_entity("3d_armor_stand:armor_entity", { + physical = true, + visual = "mesh", + mesh = "3d_armor_entity.obj", + visual_size = {x=1, y=1}, + collisionbox = {-0.1,-0.4,-0.1, 0.1,1.3,0.1}, + textures = {"3d_armor_trans.png"}, + pos = nil, + timer = 0, + on_activate = function(self) + local pos = self.object:getpos() + if pos then + self.pos = vector.round(pos) + update_entity(pos) + end + end, + on_step = function(self, dtime) + if not self.pos then + return + end + self.timer = self.timer + dtime + if self.timer > 1 then + self.timer = 0 + local pos = self.object:getpos() + if pos then + if vector.equals(vector.round(pos), self.pos) then + return + end + end + update_entity(self.pos) + self.object:remove() + end + end, +}) + +minetest.register_craft({ + output = "3d_armor_stand:armor_stand", + recipe = { + {"default:fence_wood"}, + {"default:fence_wood"}, + {"default:cobble"}, + } +}) + +minetest.register_craft({ + output = "3d_armor_stand:locked_armor_stand", + recipe = { + {"3d_armor_stand:armor_stand", "default:steel_ingot"}, + } +}) + diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_entity.obj b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_entity.obj new file mode 100644 index 0000000..052f692 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_entity.obj @@ -0,0 +1,193 @@ +# Blender v2.73 (sub 0) OBJ File: '3d_armor_entity_3.blend' +# www.blender.org +mtllib 3d_armor_entity.mtl +o Player_Cube +v 2.200000 9.763893 1.200000 +v 2.200000 9.763893 -1.200000 +v 2.200000 2.663871 1.200000 +v 2.200000 2.663871 -1.200000 +v -2.200000 9.763893 -1.200000 +v -2.200000 9.763893 1.200000 +v -2.200000 2.663871 -1.200000 +v -2.200000 2.663871 1.200000 +v 2.300000 13.863962 2.300000 +v 2.300000 13.863962 -2.300000 +v 2.300000 9.263885 2.300000 +v 2.300000 9.263885 -2.300000 +v -2.300000 13.863962 -2.300000 +v -2.300000 13.863962 2.300000 +v -2.300000 9.263885 -2.300000 +v -2.300000 9.263885 2.300000 +v -2.322686 2.473175 -1.300000 +v -2.322686 2.473175 1.300000 +v -4.713554 2.682348 1.300000 +v -4.713554 2.682348 -1.300000 +v -1.686446 9.745432 -1.300000 +v -1.686446 9.745432 1.300000 +v -4.077313 9.954605 1.300000 +v -4.077313 9.954605 -1.300000 +v 4.077313 9.954605 -1.300000 +v 4.077313 9.954605 1.300000 +v 1.686446 9.745432 1.300000 +v 1.686446 9.745432 -1.300000 +v 4.713554 2.682348 -1.300000 +v 4.713554 2.682348 1.300000 +v 2.322686 2.473175 1.300000 +v 2.322686 2.473175 -1.300000 +v 0.139099 2.938947 -1.200000 +v 0.139099 2.938947 1.200000 +v 0.261266 -4.059988 1.200000 +v 0.261266 -4.059988 -1.200000 +v 2.660901 -4.018101 1.190000 +v 2.660901 -4.018101 -1.210000 +v 2.538733 2.980834 1.190000 +v 2.538733 2.980834 -1.210000 +v -0.139099 2.938947 -1.200000 +v -0.139099 2.938947 1.200000 +v -0.261266 -4.059988 1.200000 +v -0.261266 -4.059988 -1.200000 +v -2.538734 2.980834 -1.210000 +v -2.538734 2.980834 1.190000 +v -2.660901 -4.018101 -1.210000 +v -2.660901 -4.018101 1.190000 +v -2.799999 -4.387500 1.390000 +v -2.799999 -4.387500 -1.410000 +v -2.800000 -0.812499 1.390000 +v -2.800000 -0.812499 -1.410000 +v -0.000000 -4.387500 -1.400000 +v -0.000000 -4.387500 1.400000 +v -0.000000 -0.812499 1.400000 +v -0.000000 -0.812499 -1.400000 +v 2.800000 -0.812499 -1.410000 +v 2.800000 -0.812499 1.390000 +v 2.799999 -4.387500 -1.410000 +v 2.799999 -4.387500 1.390000 +v 0.000000 -4.387500 -1.400000 +v 0.000000 -4.387500 1.400000 +v 0.000000 -0.812499 1.400000 +v 0.000000 -0.812499 -1.400000 +v 2.267006 13.830965 2.267006 +v 2.267006 13.830965 -2.267006 +v 2.267006 9.296881 2.267006 +v 2.267006 9.296881 -2.267006 +v -2.267006 13.830965 -2.267006 +v -2.267006 13.830965 2.267006 +v -2.267006 9.296881 -2.267006 +v -2.267006 9.296881 2.267006 +vt 0.250000 0.375000 +vt 0.250000 0.000000 +vt 0.312500 0.000000 +vt 0.312500 0.375000 +vt 0.437500 0.375000 +vt 0.437500 0.500000 +vt 0.312500 0.500000 +vt 0.562500 0.375000 +vt 0.562500 0.500000 +vt 0.437500 0.000000 +vt 0.500000 0.000000 +vt 0.500000 0.375000 +vt 0.625000 0.000000 +vt 0.625000 0.375000 +vt 0.500000 0.750000 +vt 0.500000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.750000 +vt 0.750000 0.750000 +vt 0.750000 1.000000 +vt 0.625000 1.000000 +vt 0.875000 0.750000 +vt 0.875000 1.000000 +vt 0.750000 0.500000 +vt 0.875000 0.500000 +vt 1.000000 0.750000 +vt 1.000000 0.500000 +vt 0.750000 0.375000 +vt 0.812500 0.500000 +vt 0.812500 0.375000 +vt 0.687500 0.375000 +vt 0.687500 0.500000 +vt 0.687500 0.000000 +vt 0.750000 0.000000 +vt 0.812500 0.000000 +vt 0.875000 0.375000 +vt 0.875000 0.000000 +vt 0.125000 0.375000 +vt 0.062500 0.375000 +vt 0.062500 0.500000 +vt 0.125000 0.500000 +vt 0.187500 0.375000 +vt 0.187500 0.500000 +vt 0.000000 0.375000 +vt 0.000000 0.000000 +vt 0.062500 0.000000 +vt 0.187500 0.000000 +vt 0.125000 0.000000 +vt 0.437500 0.875000 +vt 0.437500 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.875000 +vt 0.250000 0.875000 +vt 0.312500 0.875000 +vt 0.312500 0.656250 +vt 0.250000 0.656250 +vt 0.500000 0.875000 +vt 0.437500 0.656250 +vt 0.500000 0.656250 +vt 0.375000 0.656250 +vt 0.312500 1.000000 +usemtl Armor +s off +f 1/1 3/2 4/3 2/4 +f 5/5 6/6 1/7 2/4 +f 8/6 7/5 4/8 3/9 +f 5/5 2/4 4/3 7/10 +f 7/10 8/11 6/12 5/5 +f 8/11 3/13 1/14 6/12 +f 9/15 11/16 12/17 10/18 +f 13/19 14/20 9/21 10/18 +f 12/22 11/23 16/20 15/19 +f 13/19 10/18 12/17 15/24 +f 14/22 13/19 15/24 16/25 +f 9/26 14/22 16/25 11/27 +f 17/28 18/24 19/29 20/30 +f 24/31 23/32 22/24 21/28 +f 23/31 24/14 20/13 19/33 +f 24/31 21/28 17/34 20/33 +f 21/28 22/30 18/35 17/34 +f 22/30 23/36 19/37 18/35 +f 27/30 31/35 30/37 26/36 +f 28/28 32/34 31/35 27/30 +f 25/31 29/33 32/34 28/28 +f 26/31 30/33 29/13 25/14 +f 25/31 28/28 27/24 26/32 +f 32/28 29/30 30/29 31/24 +f 40/38 33/39 34/40 39/41 +f 36/42 38/38 37/41 35/43 +f 39/44 37/45 38/46 40/39 +f 34/1 35/2 37/47 39/42 +f 40/38 38/48 36/46 33/39 +f 33/42 36/47 35/48 34/38 +f 45/38 46/41 42/40 41/39 +f 41/42 42/38 43/48 44/47 +f 45/38 41/39 44/46 47/48 +f 42/1 46/42 48/47 43/2 +f 46/44 45/39 47/46 48/45 +f 44/42 43/43 48/41 47/38 +f 53/49 54/50 49/51 50/52 +f 51/53 52/54 50/55 49/56 +f 55/57 51/49 49/58 54/59 +f 52/52 56/54 53/55 50/60 +f 56/49 55/52 54/60 53/58 +f 52/52 51/51 55/61 56/54 +f 64/49 61/58 62/60 63/52 +f 57/52 59/60 61/55 64/54 +f 63/57 62/59 60/58 58/49 +f 58/53 60/56 59/55 57/54 +f 61/49 59/52 60/51 62/50 +f 57/52 64/54 63/61 58/51 +f 65/15 66/18 68/17 67/16 +f 69/19 66/18 65/21 70/20 +f 68/22 71/19 72/20 67/23 +f 69/19 71/24 68/17 66/18 +f 70/22 72/25 71/24 69/19 +f 65/26 67/27 72/25 70/22 diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.obj b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.obj new file mode 100644 index 0000000..0df6dc7 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.obj @@ -0,0 +1,280 @@ +# Blender v2.72 (sub 0) OBJ File: '' +# www.blender.org +mtllib 3d_armor_stand.mtl +o Armor_Stand_Player_Cube_Stand +v 0.062500 0.125002 -0.062500 +v 0.062500 -0.437500 -0.062500 +v 0.062500 -0.437500 0.062500 +v 0.062500 0.125002 0.062500 +v -0.187500 0.250004 0.062500 +v -0.187500 0.250004 -0.062500 +v -0.250000 0.250004 -0.062500 +v -0.250000 0.250004 0.062500 +v -0.062500 -0.437500 -0.062500 +v -0.062500 -0.437500 0.062500 +v -0.187500 -0.437500 0.062500 +v -0.187500 -0.437500 -0.062500 +v -0.187500 0.125002 0.062500 +v -0.187500 0.125002 -0.062500 +v -0.187500 0.937504 0.062500 +v -0.187500 0.937504 -0.062500 +v -0.375000 0.937504 -0.062500 +v -0.375000 0.937504 0.062500 +v -0.062500 0.125002 0.062500 +v 0.187500 0.125002 -0.062500 +v 0.187500 -0.437500 -0.062500 +v -0.062500 0.125002 -0.062500 +v -0.250000 0.125007 -0.062500 +v -0.250000 0.125007 0.062500 +v 0.187500 -0.437500 0.062500 +v 0.187500 0.125002 0.062500 +v -0.062500 0.937504 0.062500 +v -0.187500 0.812504 0.062500 +v -0.062500 0.812504 0.062500 +v -0.062500 0.937504 -0.062500 +v 0.187500 0.250004 -0.062500 +v 0.187500 0.250004 0.062500 +v 0.250000 0.250004 0.062500 +v 0.250000 0.250004 -0.062500 +v 0.250000 0.125007 0.062500 +v 0.250000 0.125007 -0.062500 +v 0.187500 0.812504 0.062500 +v 0.187500 0.812504 -0.062500 +v 0.375000 0.812504 -0.062500 +v 0.375000 0.812504 0.062500 +v 0.187500 0.937504 -0.062500 +v 0.187500 0.937504 0.062500 +v 0.375000 0.937504 0.062500 +v 0.375000 0.937504 -0.062500 +v 0.062500 0.937504 -0.062500 +v 0.062500 0.937504 0.062500 +v -0.062500 0.812504 -0.062500 +v -0.187500 0.812504 -0.062500 +v 0.062500 0.812504 -0.062500 +v 0.062500 0.812504 0.062500 +v -0.375000 0.812504 -0.062500 +v -0.375000 0.812504 0.062500 +v -0.062500 0.250004 0.062500 +v 0.062500 0.250004 0.062500 +v 0.062500 0.250004 -0.062500 +v -0.062500 0.250004 -0.062500 +v -0.062500 1.312504 -0.062500 +v 0.062500 1.312504 -0.062500 +v -0.062500 1.312504 0.062500 +v 0.062500 1.312504 0.062500 +v -0.500000 -0.437500 -0.500000 +v -0.500000 -0.437500 0.500000 +v 0.500000 -0.437500 0.500000 +v 0.500000 -0.437500 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +vt 0.062500 0.140625 +vt 0.062500 0.000000 +vt 0.093750 0.000000 +vt 0.093750 0.140625 +vt 0.140625 0.234375 +vt 0.140625 0.203125 +vt 0.156250 0.203125 +vt 0.156250 0.234375 +vt 0.093750 0.171875 +vt 0.062500 0.171875 +vt 0.218750 0.140625 +vt 0.187500 0.140625 +vt 0.187500 0.000000 +vt 0.218750 0.000000 +vt 0.078125 0.437500 +vt 0.078125 0.468750 +vt 0.031250 0.468750 +vt 0.031250 0.437500 +vt 0.250000 0.140625 +vt 0.250000 0.000000 +vt 0.031250 0.140625 +vt 0.031250 0.000000 +vt 0.156250 0.140625 +vt 0.156250 0.000000 +vt 0.187500 0.203125 +vt 0.156250 0.171875 +vt 0.187500 0.171875 +vt 0.125000 0.000000 +vt 0.125000 0.140625 +vt 0.000000 0.140625 +vt 0.000000 0.000000 +vt 0.328125 0.437500 +vt 0.296875 0.437500 +vt 0.296875 0.406250 +vt 0.328125 0.406250 +vt 0.109375 0.437500 +vt 0.109375 0.468750 +vt 0.046875 0.203125 +vt 0.046875 0.234375 +vt 0.031250 0.234375 +vt 0.031250 0.203125 +vt 0.000000 0.203125 +vt 0.000000 0.171875 +vt 0.031250 0.171875 +vt 0.265625 0.468750 +vt 0.265625 0.437500 +vt 0.218750 0.437500 +vt 0.218750 0.468750 +vt 0.218750 0.171875 +vt 0.171875 0.468750 +vt 0.171875 0.437500 +vt 0.078125 0.406250 +vt 0.031250 0.406250 +vt 0.140625 0.468750 +vt 0.140625 0.437500 +vt 0.140625 0.406250 +vt 0.171875 0.406250 +vt 0.109375 0.406250 +vt 0.359375 0.437500 +vt 0.359375 0.406250 +vt 0.390625 0.406250 +vt 0.390625 0.437500 +vt 0.437500 0.406250 +vt 0.437500 0.437500 +vt 0.000000 0.437500 +vt 0.000000 0.406250 +vt 0.250000 0.437500 +vt 0.218750 0.406250 +vt 0.250000 0.406250 +vt 0.359375 0.468750 +vt 0.406250 0.468750 +vt 0.406250 0.437500 +vt 0.109375 0.234375 +vt 0.078125 0.234375 +vt 0.078125 0.203125 +vt 0.109375 0.203125 +vt 0.062500 0.468750 +vt 0.062500 0.562500 +vt 0.031250 0.562500 +vt 0.328125 0.468750 +vt 0.296875 0.468750 +vt 0.062500 0.593750 +vt 0.031250 0.593750 +vt 0.093750 0.468750 +vt 0.093750 0.562500 +vt 0.125000 0.468750 +vt 0.125000 0.562500 +vt 0.000000 0.562500 +vt 0.000000 0.468750 +vt 0.078125 0.171875 +vt 0.046875 0.171875 +vt 0.265625 0.203125 +vt 0.265625 0.171875 +vt 0.296875 0.171875 +vt 0.296875 0.203125 +vt 0.265625 0.234375 +vt 0.281250 0.234375 +vt 0.281250 0.203125 +vt 0.312500 0.171875 +vt 0.312500 0.203125 +vt 0.140625 0.171875 +vt 0.171875 0.234375 +vt 0.171875 0.203125 +vt 0.109375 0.171875 +vt 0.234375 0.203125 +vt 0.203125 0.203125 +vt 0.203125 0.171875 +vt 0.234375 0.171875 +vt 0.234375 0.234375 +vt 0.203125 0.234375 +vt 0.062500 0.375000 +vt 0.062500 0.234375 +vt 0.093750 0.234375 +vt 0.093750 0.375000 +vt 0.031250 0.375000 +vt 0.125000 0.234375 +vt 0.125000 0.375000 +vt 0.000000 0.375000 +vt 0.000000 0.234375 +vt 0.218750 0.375000 +vt 0.187500 0.375000 +vt 0.187500 0.234375 +vt 0.218750 0.234375 +vt 0.250000 0.375000 +vt 0.250000 0.234375 +vt 0.156250 0.375000 +vt 0.250000 1.000000 +vt 0.250000 0.750000 +vt 0.500000 0.750000 +vt 0.500000 1.000000 +vt 0.750000 0.750000 +vt 0.750000 1.000000 +vt 0.750000 0.734375 +vt 1.000000 0.734375 +vt 1.000000 0.750000 +vt 0.000000 0.750000 +vt 0.000000 0.734375 +vt 0.250000 0.734375 +vt 0.500000 0.734375 +usemtl Stand +s off +f 1/1 2/2 3/3 4/4 +f 5/5 6/6 7/7 8/8 +f 9/1 10/4 11/9 12/10 +f 13/11 14/12 12/13 11/14 +f 15/15 16/16 17/17 18/18 +f 19/19 13/11 11/14 10/20 +f 2/2 1/1 20/21 21/22 +f 14/12 22/23 9/24 12/13 +f 8/25 7/7 23/26 24/27 +f 4/4 3/3 25/28 26/29 +f 22/23 19/29 10/28 9/24 +f 26/30 25/31 21/22 20/21 +f 27/32 15/33 28/34 29/35 +f 16/16 15/15 27/36 30/37 +f 31/38 32/39 33/40 34/41 +f 33/42 35/43 36/44 34/41 +f 37/45 38/46 39/47 40/48 +f 2/49 21/27 25/12 3/11 +f 41/50 42/51 43/47 44/48 +f 38/52 41/15 44/18 39/53 +f 41/50 45/54 46/55 42/51 +f 16/51 30/55 47/56 48/57 +f 41/15 38/52 49/58 45/36 +f 46/59 50/60 37/61 42/62 +f 42/62 37/61 40/63 43/64 +f 43/65 40/66 39/53 44/18 +f 18/67 17/47 51/68 52/69 +f 28/34 15/33 18/67 52/69 +f 16/51 48/57 51/68 17/47 +f 48/59 28/70 52/71 51/72 +f 53/73 54/74 55/75 56/76 +f 30/77 57/78 58/79 45/17 +f 50/60 46/59 27/32 29/35 +f 29/80 47/32 49/33 50/81 +f 47/56 30/55 45/36 49/58 +f 57/78 59/82 60/83 58/79 +f 27/84 59/85 57/78 30/77 +f 46/86 60/87 59/85 27/84 +f 45/17 58/79 60/88 46/89 +f 1/90 55/75 31/38 20/91 +f 54/92 4/93 26/94 32/95 +f 26/92 20/96 36/97 35/98 +f 20/91 31/38 34/41 36/44 +f 32/95 26/94 35/99 33/100 +f 6/6 14/101 23/26 7/7 +f 14/102 13/103 24/7 23/8 +f 6/6 56/76 22/104 14/101 +f 53/105 5/106 13/107 19/108 +f 13/107 5/106 8/25 24/27 +f 1/90 22/104 56/76 55/75 +f 53/105 19/108 4/93 54/92 +f 1/109 4/105 19/106 22/110 +f 49/111 55/112 54/113 50/114 +f 38/115 31/40 55/112 49/111 +f 50/114 54/113 32/116 37/117 +f 37/118 32/119 31/40 38/115 +f 28/120 48/121 6/122 5/123 +f 29/124 28/120 5/123 53/125 +f 48/121 47/126 56/8 6/122 +f 47/126 29/117 53/116 56/8 +usemtl Base +f 61/127 62/128 63/129 64/130 +f 65/129 66/131 67/132 68/130 +f 62/131 68/133 67/134 63/135 +f 63/136 67/137 66/138 64/128 +f 61/129 64/128 66/138 65/139 +f 62/131 61/129 65/139 68/133 diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.png new file mode 100644 index 0000000..aeb26de Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand_locked.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand_locked.png new file mode 100644 index 0000000..3ee08b4 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/models/3d_armor_stand_locked.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_feet.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_feet.png new file mode 100644 index 0000000..d04f9e3 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_feet.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_head.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_head.png new file mode 100644 index 0000000..228c08e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_head.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_legs.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_legs.png new file mode 100644 index 0000000..66ec357 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_legs.png differ diff --git a/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_torso.png b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_torso.png new file mode 100644 index 0000000..af95ec7 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/3d_armor_stand/textures/3d_armor_stand_torso.png differ diff --git a/kingdoms_game/mods/3d_armor-master/LICENSE.md b/kingdoms_game/mods/3d_armor-master/LICENSE.md new file mode 100644 index 0000000..d383270 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/LICENSE.md @@ -0,0 +1,11 @@ +3D Armor - Visible Player Armor +=============================== + +Default Item Textures (C) Cisoun - WTFPL + +Armor Textures: Copyright (C) 2013 Ryan Jones - CC-BY-SA + +Source Code: Copyright (C) 2013 Stuart Jones - LGPL + +Special credit to Jordach and MirceaKitsune for providing the default 3d character model. + diff --git a/kingdoms_game/mods/3d_armor-master/README.md b/kingdoms_game/mods/3d_armor-master/README.md new file mode 100644 index 0000000..16ca0c1 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/README.md @@ -0,0 +1,54 @@ +Modpack - 3d Armor [0.4.5] +========================== + +[mod] Visible Player Armor [3d_armor] +------------------------------------- + +Minetest Version: 0.4.13 + +Game: minetest_game and many derivatives + +Depends: default + +Recommends: inventory_plus or unified_inventory (use only one) + +Adds craftable armor that is visible to other players. Each armor item worn contributes to +a player's armor group level making them less vulnerable to attack. + +Armor takes damage when a player is hurt, however, many armor items offer a 'stackable' +percentage chance of restoring the lost health points. Overall armor level is boosted by 10% +when wearing a full matching set (helmet, chestplate, leggings and boots of the same material) + +Fire protection has been added by TenPlus1 and in use when ethereal mod is found and crystal +armor has been enabled. each piece of armor offers 1 fire protection, level 1 protects +against torches, level 2 against crystal spikes, 3 for fire and 5 protects when in lava. + +Compatible with player skins [skins] by Zeg9 and Player Textures [player_textures] by PilzAdam +and [simple_skins] by TenPlus1. + +Armor can be configured by adding a file called armor.conf in 3d_armor mod or world directory. +see armor.conf.example for all available options. + +[mod] Visible Wielded Items [wieldview] +--------------------------------------- + +Depends: 3d_armor + +Makes hand wielded items visible to other players. + +[mod] Shields [shields] +----------------------- + +Depends: 3d_armor + +Originally a part of 3d_armor, shields have been re-included as an optional extra. +If you do not want shields then simply remove the shields folder from the modpack. + +[mod] Technic Armor [technic_armor] +----------------------------------- + +Depends: 3d_armor + +Adds tin, silver and technic materials to 3d_armor. +Requires technic mod to be installed for craft registration. + diff --git a/kingdoms_game/mods/3d_armor-master/modpack.txt b/kingdoms_game/mods/3d_armor-master/modpack.txt new file mode 100644 index 0000000..e69de29 diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/depends.txt b/kingdoms_game/mods/3d_armor-master/moreclothes/depends.txt new file mode 100644 index 0000000..ac739a4 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/moreclothes/depends.txt @@ -0,0 +1 @@ +3d_armor \ No newline at end of file diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/init.lua b/kingdoms_game/mods/3d_armor-master/moreclothes/init.lua new file mode 100644 index 0000000..01f7adc --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/moreclothes/init.lua @@ -0,0 +1,44 @@ + minetest.register_tool("moreclothes:crown", { + description = "Crown", + inventory_image = "moreclothes_inv_crown.png", + groups = {armor_head=5, armor_heal=0, armor_use=500}, + wear = 0, + }) + minetest.register_tool("moreclothes:cloak_dark_green", { + description = "Cloak", + inventory_image = "moreclothes_inv_cloak_dark_green.png", + groups = {armor_head=5, armor_heal=0, armor_use=500}, + wear = 0, + }) + minetest.register_tool("moreclothes:wrappedcloak_dark_green", { + description = "Wrapped Cloak", + inventory_image = "moreclothes_inv_wrappedcloak_dark_green.png", + groups = {armor_head=5, armor_heal=0, armor_use=500}, + wear = 0, + }) + minetest.register_craft({ + output = "moreclothes:crown", + recipe = { + {"default:gold_ingot", "default:diamond", "default:gold_ingot"}, + }, + }) + + minetest.register_craft({ + output = "moreclothes:cloak_dark_green", + recipe = { + {"group:wool", "group:wool"}, + {"group:wool", "group:wool"}, + }, + }) + minetest.register_craft({ + output = "moreclothes:wrappedcloak_dark_green", + recipe = { + {"moreclothes:cloak_dark_green"}, + }, + }) + minetest.register_craft({ + output = "moreclothes:cloak_dark_green", + recipe = { + {"moreclothes:wrappedcloak_dark_green"}, + }, + }) \ No newline at end of file diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green.png new file mode 100644 index 0000000..ad7e37f Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green_preview.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green_preview.png new file mode 100644 index 0000000..a3b6ba3 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_cloak_dark_green_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown.png new file mode 100644 index 0000000..c432df0 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown_preview.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown_preview.png new file mode 100644 index 0000000..1af0cf2 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_crown_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_cloak_dark_green.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_cloak_dark_green.png new file mode 100644 index 0000000..d0dca66 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_cloak_dark_green.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_crown.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_crown.png new file mode 100644 index 0000000..7de6786 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_crown.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_wrappedcloak_dark_green.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_wrappedcloak_dark_green.png new file mode 100644 index 0000000..cc599e4 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_inv_wrappedcloak_dark_green.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green.png new file mode 100644 index 0000000..06bdf3a Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green.png differ diff --git a/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green_preview.png b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green_preview.png new file mode 100644 index 0000000..54a891e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/moreclothes/textures/moreclothes_wrappedcloak_dark_green_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/README.txt b/kingdoms_game/mods/3d_armor-master/shields/README.txt new file mode 100644 index 0000000..3146bcb --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/shields/README.txt @@ -0,0 +1,6 @@ +Adds shields to 3d_armor + +Depends: 3d_armor + +Originally a part of 3d_armor, shields have been re-included as an optional extra. +If you do not what shields then simply remove the shields folder from the modpack. diff --git a/kingdoms_game/mods/3d_armor-master/shields/crafting_guide.txt b/kingdoms_game/mods/3d_armor-master/shields/crafting_guide.txt new file mode 100644 index 0000000..9b61dde --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/shields/crafting_guide.txt @@ -0,0 +1,36 @@ +Shields -- Crafting Guide +-------------------------- + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | X | X | ++---+---+---+ +| | X | | ++---+---+---+ + +[shields:shield_wood] X = [default:wood] +[shields:shield_cactus] X = [default:cactus] +[shields:shield_steel] X = [default:steel_ingot] +[shields:shield_bronze] X = [default:bronze_ingot] +[shields:shield_diamond] X = [default:diamond] +[shields:shield_gold] X = [default:gold_ingot] +[shields:shield_mithril] X = [moreores:mithril_ingot] +[shields:shield_crystal] X = [ethereal:crystal_ingot] + +Enhanced Shields +---------------- + ++---+ +| S | ++---+ +| X | ++---+ +| S | ++---+ + +[shields:shield_enhanced_wood] X = [shields:shield_wood] +[shields:shield_enhanced_cactus] X = [shields:shield_cactus] + +S = [default:steel_ingot] + diff --git a/kingdoms_game/mods/3d_armor-master/shields/depends.txt b/kingdoms_game/mods/3d_armor-master/shields/depends.txt new file mode 100644 index 0000000..585cc7a --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/shields/depends.txt @@ -0,0 +1,2 @@ +default +3d_armor diff --git a/kingdoms_game/mods/3d_armor-master/shields/init.lua b/kingdoms_game/mods/3d_armor-master/shields/init.lua new file mode 100644 index 0000000..e768e57 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/shields/init.lua @@ -0,0 +1,135 @@ +local use_moreores = minetest.get_modpath("moreores") + +-- Regisiter Shields + +minetest.register_tool("shields:shield_admin", { + description = "Admin Shield", + inventory_image = "shields_inv_shield_admin.png", + groups = {armor_shield=1000, armor_heal=100, armor_use=0, not_in_creative_inventory=1}, + wear = 0, +}) + +if ARMOR_MATERIALS.wood then + minetest.register_tool("shields:shield_wood", { + description = "Wooden Shield", + inventory_image = "shields_inv_shield_wood.png", + groups = {armor_shield=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) + minetest.register_tool("shields:shield_enhanced_wood", { + description = "Enhanced Wood Shield", + inventory_image = "shields_inv_shield_enhanced_wood.png", + groups = {armor_shield=8, armor_heal=0, armor_use=1000}, + wear = 0, + }) + minetest.register_craft({ + output = "shields:shield_enhanced_wood", + recipe = { + {"default:steel_ingot"}, + {"shields:shield_wood"}, + {"default:steel_ingot"}, + }, + }) +end + +if ARMOR_MATERIALS.cactus then + minetest.register_tool("shields:shield_cactus", { + description = "Cactus Shield", + inventory_image = "shields_inv_shield_cactus.png", + groups = {armor_shield=5, armor_heal=0, armor_use=2000}, + wear = 0, + }) + minetest.register_tool("shields:shield_enhanced_cactus", { + description = "Enhanced Cactus Shield", + inventory_image = "shields_inv_shield_enhanced_cactus.png", + groups = {armor_shield=8, armor_heal=0, armor_use=1000}, + wear = 0, + }) + minetest.register_craft({ + output = "shields:shield_enhanced_cactus", + recipe = { + {"default:steel_ingot"}, + {"shields:shield_cactus"}, + {"default:steel_ingot"}, + }, + }) +end + +if ARMOR_MATERIALS.steel then + minetest.register_tool("shields:shield_steel", { + description = "Steel Shield", + inventory_image = "shields_inv_shield_steel.png", + groups = {armor_shield=10, armor_heal=0, armor_use=500}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.bronze then + minetest.register_tool("shields:shield_bronze", { + description = "Bronze Shield", + inventory_image = "shields_inv_shield_bronze.png", + groups = {armor_shield=10, armor_heal=6, armor_use=250}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.diamond then + minetest.register_tool("shields:shield_diamond", { + description = "Diamond Shield", + inventory_image = "shields_inv_shield_diamond.png", + groups = {armor_shield=15, armor_heal=12, armor_use=100}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.gold then + minetest.register_tool("shields:shield_gold", { + description = "Gold Shield", + inventory_image = "shields_inv_shield_gold.png", + groups = {armor_shield=10, armor_heal=6, armor_use=250}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.mithril then + minetest.register_tool("shields:shield_mithril", { + description = "Mithril Shield", + inventory_image = "shields_inv_shield_mithril.png", + groups = {armor_shield=15, armor_heal=12, armor_use=50}, + wear = 0, + }) +end + +if ARMOR_MATERIALS.crystal then + minetest.register_tool("shields:shield_crystal", { + description = "Crystal Shield", + inventory_image = "shields_inv_shield_crystal.png", + groups = {armor_shield=15, armor_heal=12, armor_use=50, armor_fire=1}, + wear = 0, + }) +end + +for k, v in pairs(ARMOR_MATERIALS) do + minetest.register_craft({ + output = "shields:shield_"..k, + recipe = { + {v, v, v}, + {v, v, v}, + {"", v, ""}, + }, + }) + --MELTING + if v ~= "group:wood" then + minetest.register_craft({ + output = v .. " 7", + type = "cooking", + cooktime = 14, + recipe = "shields:shield_"..k + }) + end +end + +minetest.after(0, function() + table.insert(armor.elements, "shield") +end) + diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_admin.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_admin.png new file mode 100644 index 0000000..ae5ab7d Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_bronze.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_bronze.png new file mode 100644 index 0000000..67bac0f Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_enhanced_wood.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_enhanced_wood.png new file mode 100644 index 0000000..058e042 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_enhanced_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_gold.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_gold.png new file mode 100644 index 0000000..8995834 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_steel.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_steel.png new file mode 100644 index 0000000..178b507 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_wood.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_wood.png new file mode 100644 index 0000000..dcbe933 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_inv_shield_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin.png new file mode 100644 index 0000000..c836902 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_old.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_old.png new file mode 100644 index 0000000..430c3e3 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_old.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_preview.png new file mode 100644 index 0000000..762c2d2 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_admin_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze.png new file mode 100644 index 0000000..89d6799 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze_preview.png new file mode 100644 index 0000000..5f9ca7b Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_bronze_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood.png new file mode 100644 index 0000000..14bd057 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood_preview.png new file mode 100644 index 0000000..9298383 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_enhanced_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold.png new file mode 100644 index 0000000..b198d18 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold_preview.png new file mode 100644 index 0000000..66d8f2e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_gold_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel.png new file mode 100644 index 0000000..cfe58a1 Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel_preview.png new file mode 100644 index 0000000..0a3d36a Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_steel_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood.png new file mode 100644 index 0000000..baf092d Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood.png differ diff --git a/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood_preview.png b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood_preview.png new file mode 100644 index 0000000..b446e4e Binary files /dev/null and b/kingdoms_game/mods/3d_armor-master/shields/textures/shields_shield_wood_preview.png differ diff --git a/kingdoms_game/mods/3d_armor-master/wieldview/README.txt b/kingdoms_game/mods/3d_armor-master/wieldview/README.txt new file mode 100644 index 0000000..cffae46 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/wieldview/README.txt @@ -0,0 +1,15 @@ +[mod] visible wielded items [wieldview] +======================================= + +depends: default, 3d_armor + +Makes hand wielded items visible to other players. + +default settings: [minetest.conf] + +# Set number of seconds between visible wielded item updates. +wieldview_update_time = 2 + +# Show nodes as tiles, disabled by default +wieldview_node_tiles = false + diff --git a/kingdoms_game/mods/3d_armor-master/wieldview/depends.txt b/kingdoms_game/mods/3d_armor-master/wieldview/depends.txt new file mode 100644 index 0000000..585cc7a --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/wieldview/depends.txt @@ -0,0 +1,2 @@ +default +3d_armor diff --git a/kingdoms_game/mods/3d_armor-master/wieldview/init.lua b/kingdoms_game/mods/3d_armor-master/wieldview/init.lua new file mode 100644 index 0000000..7a5a619 --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/wieldview/init.lua @@ -0,0 +1,76 @@ +local time = 0 +local update_time = tonumber(minetest.setting_get("wieldview_update_time")) +if not update_time then + update_time = 2 + minetest.setting_set("wieldview_update_time", tostring(update_time)) +end +local node_tiles = minetest.setting_getbool("wieldview_node_tiles") +if not node_tiles then + node_tiles = false + minetest.setting_set("wieldview_node_tiles", "false") +end + +wieldview = { + wielded_item = {}, + transform = {}, +} + +dofile(minetest.get_modpath(minetest.get_current_modname()).."/transform.lua") + +wieldview.get_item_texture = function(self, item) + local texture = "3d_armor_trans.png" + if item ~= "" then + if minetest.registered_items[item] then + if minetest.registered_items[item].inventory_image ~= "" then + texture = minetest.registered_items[item].inventory_image + elseif node_tiles == true and minetest.registered_items[item].tiles + and type(minetest.registered_items[item].tiles[1]) == "string" + and minetest.registered_items[item].tiles[1] ~= "" then + texture = minetest.inventorycube(minetest.registered_items[item].tiles[1]) + end + end + if wieldview.transform[item] then + texture = texture.."^[transform"..wieldview.transform[item] + end + end + return texture +end + +wieldview.update_wielded_item = function(self, player) + if not player then + return + end + local name = player:get_player_name() + local stack = player:get_wielded_item() + local item = stack:get_name() + if not item then + return + end + if self.wielded_item[name] then + if self.wielded_item[name] == item then + return + end + armor.textures[name].wielditem = self:get_item_texture(item) + armor:update_player_visuals(player) + end + self.wielded_item[name] = item +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + wieldview.wielded_item[name] = "" + minetest.after(0, function(player) + wieldview:update_wielded_item(player) + end, player) +end) + +minetest.register_globalstep(function(dtime) + time = time + dtime + if time > update_time then + for _,player in ipairs(minetest.get_connected_players()) do + wieldview:update_wielded_item(player) + end + time = 0 + end +end) + diff --git a/kingdoms_game/mods/3d_armor-master/wieldview/transform.lua b/kingdoms_game/mods/3d_armor-master/wieldview/transform.lua new file mode 100644 index 0000000..4d5133e --- /dev/null +++ b/kingdoms_game/mods/3d_armor-master/wieldview/transform.lua @@ -0,0 +1,24 @@ +-- Wielded Item Transformations - http://dev.minetest.net/texture + +wieldview.transform = { + ["default:torch"]="R270", + ["default:sapling"]="R270", + ["flowers:dandelion_white"]="R270", + ["flowers:dandelion_yellow"]="R270", + ["flowers:geranium"]="R270", + ["flowers:rose"]="R270", + ["flowers:tulip"]="R270", + ["flowers:viola"]="R270", + ["bucket:bucket_empty"]="R270", + ["bucket:bucket_water"]="R270", + ["bucket:bucket_lava"]="R270", + ["screwdriver:screwdriver"]="R270", + ["screwdriver:screwdriver1"]="R270", + ["screwdriver:screwdriver2"]="R270", + ["screwdriver:screwdriver3"]="R270", + ["screwdriver:screwdriver4"]="R270", + ["vessels:glass_bottle"]="R270", + ["vessels:drinking_glass"]="R270", + ["vessels:steel_bottle"]="R270", +} + diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/Chat Commands.md b/kingdoms_game/mods/Minetest-WorldEdit-1.0/Chat Commands.md new file mode 100644 index 0000000..0af2abe --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/Chat Commands.md @@ -0,0 +1,332 @@ +Chat Commands +------------- +For more information, see the [README](README.md). + +### //inspect + +Enable or disable node inspection. + + //inspect on + //inspect off + //inspect 1 + //inspect 0 + //inspect true + //inspect false + //inspect yes + //inspect no + //inspect enable + //inspect disable + +### //reset + +Reset the region so that it is empty. + + //reset + +### //mark + +Show markers at the region positions. + + //mark + +### //unmark + +Hide markers if currently shown. + + //unmark + +### //pos1 + +Set WorldEdit region position 1 to the player's location. + + //pos1 + +### //pos2 + +Set WorldEdit region position 2 to the player's location. + + //pos2 + +### //p set/set1/set2/get + +Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region. + + //p set + //p set1 + //p set2 + //p get + +### //fixedpos set1 x y z + +Set a WorldEdit region position to the position at (, , ). + + //fixedpos set1 0, 0, 0 + //fixedpos set1 -30, 5, 28 + //fixedpos set2 1004, -200, 432 + +### //volume + +Display the volume of the current WorldEdit region. + + //volume + +### //set + +Set the current WorldEdit region to . + + //set air + //set cactus + //set Bronze Block + //set mesecons:wire_00000000_off + +### //replace + +Replace all instances of with in the current WorldEdit region. + + //replace Cobblestone air + //replace lightstone_blue glass + //replace dirt Bronze Block + //replace mesecons:wire_00000000_off flowers:flower_tulip + +### //replaceinverse + +Replace all nodes other than with in the current WorldEdit region. + + //replaceinverse Cobblestone air + //replaceinverse flowers:flower_waterlily glass + //replaceinverse dirt Bronze Block + //replaceinverse mesecons:wire_00000000_off flowers:flower_tulip + +### //hollowsphere + +Add hollow sphere centered at WorldEdit position 1 with radius , composed of . + + //hollowsphere 5 Diamond Block + //hollowsphere 12 glass + //hollowsphere 17 mesecons:wire_00000000_off + +### //sphere + +Add sphere centered at WorldEdit position 1 with radius , composed of . + + //sphere 5 Diamond Block + //sphere 12 glass + //sphere 17 mesecons:wire_00000000_off + +### //hollowdome + +Add hollow dome centered at WorldEdit position 1 with radius , composed of . + + //hollowdome 5 Diamond Block + //hollowdome -12 glass + //hollowdome 17 mesecons:wire_00000000_off + +### //dome + +Add dome centered at WorldEdit position 1 with radius , composed of . + + //dome 5 Diamond Block + //dome -12 glass + //dome 17 mesecons:wire_00000000_off + +### //hollowcylinder x/y/z/? + +Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of . + + //hollowcylinder x +5 8 Bronze Block + //hollowcylinder y 28 10 glass + //hollowcylinder z -12 3 mesecons:wire_00000000_off + //hollowcylinder ? 2 4 default:stone + +### //cylinder x/y/z/? + +Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of . + + //cylinder x +5 8 Bronze Block + //cylinder y 28 10 glass + //cylinder z -12 3 mesecons:wire_00000000_off + //cylinder ? 2 4 default:stone + +### //pyramid x/y/z? + +Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of . + + //pyramid x 8 Diamond Block + //pyramid y -5 glass + //pyramid z 2 mesecons:wire_00000000_off + //pyramid ? 12 mesecons:wire_00000000_off + +### //spiral + +Add spiral centered at WorldEdit position 1 with side length , height , space between walls , composed of . + + //spiral 20 5 3 Diamond Block + //spiral 5 2 1 glass + //spiral 7 1 5 mesecons:wire_00000000_off + +### //copy x/y/z/? + +Copy the current WorldEdit region along the x/y/z/? axis by nodes. + + //copy x 15 + //copy y -7 + //copy z +4 + //copy ? 8 + +### //move x/y/z/? + +Move the current WorldEdit positions and region along the x/y/z/? axis by nodes. + + //move x 15 + //move y -7 + //move z +4 + //move ? -1 + +### //stack x/y/z/? + +Stack the current WorldEdit region along the x/y/z/? axis times. + + //stack x 3 + //stack y -1 + //stack z +5 + //stack ? 12 + +### //scale + +Scale the current WorldEdit positions and region by a factor of positive integer with position 1 as the origin. + + //scale 2 + //scale 1 + //scale 10 + +### //transpose x/y/z/? x/y/z/? + +Transpose the current WorldEdit positions and region along the x/y/z/? and x/y/z/? axes. + + //transpose x y + //transpose x z + //transpose y z + //transpose ? y + +### //flip x/y/z/? + +Flip the current WorldEdit region along the x/y/z/? axis. + + //flip x + //flip y + //flip z + //flip ? + +### //rotate x/y/z/? + +Rotate the current WorldEdit positions and region along the x/y/z/? axis by angle (90 degree increment). + + //rotate x 90 + //rotate y 180 + //rotate z 270 + //rotate ? -90 + +### //orient + +Rotate oriented nodes in the current WorldEdit region around the Y axis by angle (90 degree increment) + + //orient 90 + //orient 180 + //orient 270 + //orient -90 + +### //fixlight + +Fixes the lighting in the current WorldEdit region. + + //fixlight + +### //hide + +Hide all nodes in the current WorldEdit region non-destructively. + + //hide + +### //suppress + +Suppress all in the current WorldEdit region non-destructively. + + //suppress Diamond Block + //suppress glass + //suppress mesecons:wire_00000000_off + +### //highlight + +Highlight in the current WorldEdit region by hiding everything else non-destructively. + + //highlight Diamond Block + //highlight glass + //highlight mesecons:wire_00000000_off + +### //restore + +Restores nodes hidden with WorldEdit in the current WorldEdit region. + + //restore + +### //save + +Save the current WorldEdit region to "(world folder)/schems/.we". + + //save some random filename + //save huge_base + +### //allocate + +Set the region defined by nodes from "(world folder)/schems/.we" as the current WorldEdit region. + + //allocate some random filename + //allocate huge_base + +### //load + +Load nodes from "(world folder)/schems/.we" with position 1 of the current WorldEdit region as the origin. + + //load some random filename + //load huge_base + +### //lua + +Executes as a Lua chunk in the global namespace. + + //lua worldedit.pos1["singleplayer"] = {x=0, y=0, z=0} + //lua worldedit.rotate(worldedit.pos1["singleplayer"], worldedit.pos2["singleplayer"], "y", 90) + +### //luatransform + +Executes as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region. + + //luatransform minetest.add_node(pos, {name="default:stone"}) + //luatransform if minetest.get_node(pos).name == "air" then minetest.add_node(pos, {name="default:water_source"}) + +### //mtschemcreate + +Save the current WorldEdit region using the Minetest Schematic format to "(world folder)/schems/.mts". + + //mtschemcreate some random filename + //mtschemcreate huge_base + +### //mtschemplace + +Load nodes from "(world folder)/schems/.mts" with position 1 of the current WorldEdit region as the origin. + + //mtschemplace some random filename + //mtschemplace huge_base + +### //mtschemprob start/finish/get + +After using //mtschemprob start all nodes punched will bring up a text field where a probablity can be entered. +This mode can be left with //mtschemprob finish. //mtschemprob get will display the probabilities saved for the nodes. + + //mtschemprob get + +### //clearobjects + +Clears all objects within the WorldEdit region. + + //clearobjects diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/LICENSE.txt b/kingdoms_game/mods/Minetest-WorldEdit-1.0/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/README.md b/kingdoms_game/mods/Minetest-WorldEdit-1.0/README.md new file mode 100644 index 0000000..51a6c7a --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/README.md @@ -0,0 +1,110 @@ +WorldEdit v1.0 for MineTest 0.4.8+ +================================== +The ultimate in-game world editing tool for [Minetest](http://minetest.net/)! Tons of functionality to help with building, fixing, and more. + +For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?id=572) at the Minetest forums. + +# New users should see the [tutorial](Tutorial.md). + +Usage +----- +WorldEdit works primarily through chat commands. Depending on your key bindings, you can invoke chat entry with the "t" key, and open the chat console with the "F10" key. + +WorldEdit has a huge potential for abuse by untrusted players. Therefore, users will not be able to use WorldEdit unless they have the "worldedit" privelege. This is available by default in single player, but in multiplayer the permission must be explicitly given by someone with the right credentials, using the follwoing chat command: `/grant worldedit`. This privelege can later be removed using the following chat command: `/revoke worldedit`. + +For in-game information about these commands, type `/help ` in the chat. For example, to learn more about the `//copy` command, simply type `/help /copy` to display information relevant to copying a region. + +Chat Commands +------------- +WorldEdit is accessed in-game through an interface. By default, the mod distribution includes a chat interface for this purpose. It is documented in the [Chat Commands Reference](Chat Commands.md). + +If visual manipulation of nodes is desired, the [WorldEdit GUI](https://forum.minetest.net/viewtopic.php?id=3112) mod provides a simple interface with buttons and text entry fields for this purpose. + +Compatibility +------------- +This mod supports Minetest versions 0.4.8 and newer. Older versions of WorldEdit may work with older versions of Minetest, but are not recommended. + +WorldEdit works quite well with other mods, and does not have any known mod conflicts. + +WorldEdit API +------------- +WorldEdit exposes all significant functionality in a simple Lua interface. Adding WorldEdit to the file "depends.txt" in your mod gives you access to all of the `worldedit` functions. The API is useful for tasks such as high-performance node manipulation, alternative interfaces, and map creation. + +If you don't add WorldEdit to your "depends.txt" file, each file in the WorldEdit mod is also independent. For example, one may import the WorldEdit primitives API using the following code: + + dofile(minetest.get_modpath("worldedit").."/primitives.lua") + +AGPLv3 compatible mods may further include WorldEdit files in their own mods. This may be useful if a modder wishes to completely avoid any dependencies on WorldEdit. Note that it is required to give credit to the authors. + +This API is documented in the [WorldEdit API Reference](WorldEdit API.md). + +Axes +---- +The coordinate system is the same as that used by MineTest; Y is upwards, X is perpendicular, and Z is parallel. + +When an axis is specified in a WorldEdit command, it is specified as one of the following values: x, y, z, or ?. + +The value ? represents the axis the player is currently facing. If the player is facing more than one axis, the axis the player face direction is closest to will be used. + +Nodes +----- +Node names are required for many types of commands that identify or modify specific types of nodes. They can be specified in a number of ways. + +First, by description - the tooltip that appears when hovering over the item in an inventory. This is case insensitive and includes values such as "Cobblestone" and "bronze block". Note that certain commands (namely, `//replace` and `//replaceinverse`) do not support descriptions that contain spaces in the `` field. + +Second, by name - the node name that is defined by code, but without the mod name prefix. This is case sensitive and includes values such as "piston_normal_off" and "cactus". Nodes defined in the `default` mod always take precedence over other nodes when searching for the correct one, and if there are multiple possible nodes (such as "a:celery" and "b:celery"), one is chosen in no particular order. + +Finally, by full name - the unambiguous identifier of the node, prefixes and all. This is case sensitive and includes values such as "default:stone" and "mesecons:wire_00000000_off". + +The node name "air" can be used anywhere a normal node name can, and acts as a blank node. This is useful for clearing or removing nodes. For example, `//set air` would remove all the nodes in the current WorldEdit region. Similarly, `//sphere 10 air`, when WorldEdit position 1 underground, would dig a large sphere out of the ground. + +Regions +------- +Most WorldEdit commands operate on regions. Regions are a set of two positions that define a 3D cuboid. They are local to each player and chat commands affect only the region for the player giving the commands. + +Each positions together define two opposing corners of the cube. With two opposing corners it is possible to determine both the location and dimensions of the region. + +Regions are not saved between server restarts. They start off as empty regions, and cannot be used with most WorldEdit commands until they are set to valid values. + +Markers +------- +Entities are used to mark the location of the WorldEdit regions. They appear as boxes containing the number 1 or 2, and represent position 1 and 2 of the WorldEdit region, respectively. + +To remove the entities, simply punch them. This does not reset the positions themselves. + +Schematics +---------- +WorldEdit supports two different types of schematics. + +The first is the WorldEdit Schematic format, with the file extension ".we", and in some older versions, ".wem". There have been several previous versions of the WorldEdit Schematic format, but WorldEdit is capable of loading any past versions, and will always support them - there is no need to worry about schematics becoming obselete. + +The current version of the WorldEdit Schematic format, internally known as version 4, is essentially an array of node data tables in Lua 5.2 table syntax. Specifically: + + return { + { + ["y"] = , + ["x"] = , + ["name"] = , + ["z"] = , + ["meta"] = , + ["param2"] = , + ["param1"] = , + }, + <...> + } + +Value ordering and minor aspects of the syntax, such as trailing commas or newlines, are not guaranteed. + +The WorldEdit Schematic format is accessed via the WorldEdit API, or WorldEdit serialization chat commands such as `//serialize` and `//deserialize`. + +The second is the Minetest Schematic format (MTS). The details of this format may be found in the Minetest documentation and are out of the scope of this document. Access to this format is done via specialized MTS commands such as `//mtschemcreate` and `//mtschemplace`. + +License +------- +Copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote). + +This mod is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl-3.0.html). + +Basically, this means everyone is free to use, modify, and distribute the files, as long as these modifications are also licensed the same way. + +Most importantly, the Affero variant of the GPL requires you to publish your modifications in source form, even if the mod is run only on the server, and not distributed. diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/Tutorial.md b/kingdoms_game/mods/Minetest-WorldEdit-1.0/Tutorial.md new file mode 100644 index 0000000..f533164 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/Tutorial.md @@ -0,0 +1,55 @@ +WorldEdit Tutorial +================== +This is a step-by-step tutorial outlining the basic usage of WorldEdit. For more information, see the [README](README.md). + +Let's start with a few assumptions: + +* You have a compatible version of Minetest working. + * See the [README](README.md) for compatibility information. +* You have WorldEdit installed as a mod. + * If using Windows, [MODSTER](https://forum.minetest.net/viewtopic.php?pid=101463) makes installing mods totally painless. + * Simply download the file, extract the archive, and move it to the correct mod folder for Minetest. +* You are familiar with the basics of the game. + * How to walk, jump, and climb. + * How to dig, place, and punch blocks. + * How to type into the chat and read text from it. + +Overview +-------- +WorldEdit has a "region", which is simply a cuboid area defined by two markers, both of which the player can move around. Every player can have their own region with their own two markers. + +WorldEdit chat commands can work inside the region selected, or around the first marker. + +Step 1: Selecting a region +-------------------------- +In the chat prompt, enter `//p set`. In the chat, you are prompted to punch two nodes to set the positions of the two markers. + +Punch a nearby node. Be careful of breakable ones such as torches. A black cube reading "1" will appear around the node. This is the marker for WorldEdit position 1. + +Walk away from the node you just punched. Now, punch another node. A black cube reading "2" will appear around the node. This is the marker for WorldEdit position 2. + +Step 2: Region commands +----------------------- +In the chat prompt, enter `//set mese`. In the chat, you will see a message showing the number of nodes set after a small delay. + +Look at the place between the two markers: it is now filled with MESE blocks! + +The `//set ` command fills the region with whatever node you want. It is a region-oriented command, which means it works inside the WorldEdit region only. + +Now, try a few different variations, such as `//set torch`, `//set cobble`, and `//set water`. + +Step 3: Position commands +------------------------- +In the chat prompt, enter `//hollowdome 30 glass`. In the chat, you will see a message showing the number of nodes set after a small delay. + +Look around marker 1: it is now surrounded by a hollow glass dome! + +The `//hollowdome ` command creates a hollow dome centered around marker 1, made of any node you want. It is a position-oriented command, which means it works around marker 1 and can go outside the WorldEdit region. + +Step 4: Other commands +---------------------- +There are many more commands than what is shown here. See the [Chat Commands Reference](Chat Commands.md) for a detailed list of them, along with descriptions and examples for every single one. + +If you're in-game and forgot how a command works, just use the `/help ` command, without the first forward slash. For example, to see some information about the `//set ` command mentioned earlier, simply use `/help /set`. + +A very useful command to check out is the `//save ` command, which can save everything inside the WorldEdit region to a file, stored on the computer hosting the server (the player's computer, in single player mode). You can then later use `//load ` to load the data in a file into a world, even another world on another computer. \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/WorldEdit API.md b/kingdoms_game/mods/Minetest-WorldEdit-1.0/WorldEdit API.md new file mode 100644 index 0000000..70a96bc --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/WorldEdit API.md @@ -0,0 +1,219 @@ +WorldEdit API +============= +The WorldEdit API is composed of multiple modules, each of which is independent and can be used without the other. Each module is contained within a single file. + +If needed, individual modules such as visualization.lua can be removed without affecting the rest of the program. The only file that cannot be removed is init.lua, which is necessary for the mod to run. + +For more information, see the [README](README.md). + +Manipulations +------------- +Contained in manipulations.lua, this module allows several node operations to be applied over a region. + +### count = worldedit.set(pos1, pos2, nodename) + +Sets a region defined by positions `pos1` and `pos2` to `nodename`. To clear to region, use "air" as the value of `nodename`. + +Returns the number of nodes set. + +### count = worldedit.replace(pos1, pos2, searchnode, replacenode) + +Replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`. + +Returns the number of nodes replaced. + +### count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) + +Replaces all nodes other than `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`. + +Returns the number of nodes replaced. + +### count = worldedit.copy(pos1, pos2, axis, amount) + +Copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes. + +Returns the number of nodes copied. + +### count = worldedit.move(pos1, pos2, axis, amount) + +Moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes. + +Returns the number of nodes moved. + +### count = worldedit.stack(pos1, pos2, axis, count) + +Duplicates the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") `count` times. + +Returns the number of nodes stacked. + +### count, newpos1, newpos2 = worldedit.scale(pos1, pos2, factor) + +Scales the region defined by positions `pos1` and `pos2` by an factor of positive integer `factor` with `pos1` as the origin. + +Returns the number of nodes scaled, the new scaled position 1, and the new scaled position 2. + +### count, newpos1, newpos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + +Transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes ("x" or "y" or "z"). + +Returns the number of nodes transposed, the new transposed position 1, and the new transposed position 2. + +### count = worldedit.flip(pos1, pos2, axis) + +Flips a region defined by the positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z"). + +Returns the number of nodes flipped. + +### count, newpos2, newpos2 = worldedit.rotate(pos1, pos2, angle) + +Rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise around the y axis (supporting 90 degree increments only). + +Returns the number of nodes rotated, the new position 1, and the new position 2. + +### count = worldedit.orient(pos1, pos2, angle) + +Rotates all oriented nodes in a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (90 degree increment) around the Y axis. + +Returns the number of nodes oriented. + +### count = worldedit.fixlight(pos1, pos2) + +Fixes the lighting in a region defined by positions `pos1` and `pos2`. + +Returns the number of nodes updated. + +### count = worldedit.clearobjects(pos1, pos2) + +Clears all objects in a region defined by the positions `pos1` and `pos2`. + +Returns the number of objects cleared. + +Primitives +---------- +Contained in primitives.lua, this module allows the creation of several geometric primitives. + +### count = worldedit.hollow_sphere(pos, radius, nodename) + +Adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.sphere(pos, radius, nodename) + +Adds a sphere centered at `pos` with radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.hollow_dome(pos, radius, nodename) + +Adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.dome(pos, radius, nodename) + +Adds a dome centered at `pos` with radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.hollow_cylinder(pos, axis, length, radius, nodename) + +Adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.cylinder(pos, axis, length, radius, nodename) + +Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`. + +Returns the number of nodes added. + +### count = worldedit.pyramid(pos, axis, height, nodename) + +Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`. + +Returns the number of nodes added. + +### count = worldedit.spiral(pos, length, height, spacer, nodename) + +Adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`. + +Returns the number of nodes added. + +Visualization +------------- +Contained in visualization.lua, this module allows nodes to be visualized in different ways. + +### volume = worldedit.volume(pos1, pos2) + +Determines the volume of the region defined by positions `pos1` and `pos2`. + +Returns the volume. + +### count = worldedit.hide(pos1, pos2) + +Hides all nodes in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes. + +Returns the number of nodes hidden. + +### count = worldedit.suppress(pos1, pos2, nodename) + +Suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes. + +Returns the number of nodes suppressed. + +### count = worldedit.highlight(pos1, pos2, nodename) + +Highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes. + +Returns the number of nodes found. + +### count = worldedit.restore(pos1, pos2) + +Restores all nodes hidden with WorldEdit functions in a region defined by positions `pos1` and `pos2`. + +Returns the number of nodes restored. + +Serialization +------------- +Contained in serialization.lua, this module allows regions of nodes to be serialized and deserialized to formats suitable for use outside MineTest. + +### version = worldedit.valueversion(value) + +Determines the version of serialized data `value`. + +Returns the version as a positive integer or 0 for unknown versions. + +### data, count = worldedit.serialize(pos1, pos2) + +Converts the region defined by positions `pos1` and `pos2` into a single string. + +Returns the serialized data and the number of nodes serialized. + +### pos1, pos2, count = worldedit.allocate(originpos, value) + +Determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`. + +Returns the two corner positions and the number of nodes. + +### count = worldedit.deserialize(originpos, value) + +Loads the nodes represented by string `value` at position `originpos`. + +Returns the number of nodes deserialized. + +Code +---- +Contained in code.lua, this module allows arbitrary Lua code to be used with WorldEdit. + +### error = worldedit.lua(code) + +Executes `code` as a Lua chunk in the global namespace. + +Returns an error if the code fails or nil otherwise. + +### error = worldedit.luatransform(pos1, pos2, code) + +Executes `code` as a Lua chunk in the global namespace with the variable `pos` available, for each node in a region defined by positions `pos1` and `pos2`. + +Returns an error if the code fails or nil otherwise. \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/modpack.txt b/kingdoms_game/mods/Minetest-WorldEdit-1.0/modpack.txt new file mode 100644 index 0000000..e69de29 diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/code.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/code.lua new file mode 100644 index 0000000..ca3daa6 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/code.lua @@ -0,0 +1,48 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +--executes `code` as a Lua chunk in the global namespace, returning an error if the code fails or nil otherwise +worldedit.lua = function(code) + local operation, message = loadstring(code) + if operation == nil then --code parsing failed + return message + end + local status, message = pcall(operation) + if status == nil then --operation failed + return message + end + return nil +end + +--executes `code` as a Lua chunk in the global namespace with the variable pos available, for each node in a region defined by positions `pos1` and `pos2`, returning an error if the code fails or nil otherwise +worldedit.luatransform = function(pos1, pos2, code) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + local factory, message = loadstring("return function(pos) " .. code .. " end") + if factory == nil then --code parsing failed + return message + end + local operation = factory() + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos = {x=pos1.x, y=0, z=0} + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local status, message = pcall(operation, pos) + if status == nil then --operation failed + return message + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return nil +end \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/compatibility.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/compatibility.lua new file mode 100644 index 0000000..ca49115 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/compatibility.lua @@ -0,0 +1,20 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +worldedit.allocate_old = worldedit.allocate +worldedit.deserialize_old = worldedit.deserialize +worldedit.metasave = function(pos1, pos2, filename) + local file, err = io.open(filename, "wb") + if err then return 0 end + local data, count = worldedit.serialize(pos1, pos2) + file:write(data) + file:close() + return count +end +worldedit.metaload = function(originpos, filename) + filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem" + local file, err = io.open(filename, "wb") + if err then return 0 end + local data = file:read("*a") + return worldedit.deserialize(originpos, data) +end diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/init.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/init.lua new file mode 100644 index 0000000..6c58bd4 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/init.lua @@ -0,0 +1,19 @@ +assert(minetest.get_voxel_manip, string.rep(">", 300) .. "HEY YOU! YES, YOU OVER THERE. THIS VERSION OF WORLDEDIT REQUIRES MINETEST 0.4.8 OR LATER! YOU HAVE AN OLD VERSION." .. string.rep("<", 300)) + +local path = minetest.get_modpath(minetest.get_current_modname()) + +local loadmodule = function(path) + local file = io.open(path) + if not file then + return + end + file:close() + return dofile(path) +end + +loadmodule(path .. "/manipulations.lua") +loadmodule(path .. "/primitives.lua") +loadmodule(path .. "/visualization.lua") +loadmodule(path .. "/serialization.lua") +loadmodule(path .. "/code.lua") +loadmodule(path .. "/compatibility.lua") diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/manipulations.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/manipulations.lua new file mode 100644 index 0000000..4d0d3d8 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/manipulations.lua @@ -0,0 +1,579 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions +worldedit.sort_pos = function(pos1, pos2) + pos1 = {x=pos1.x, y=pos1.y, z=pos1.z} + pos2 = {x=pos2.x, y=pos2.y, z=pos2.z} + if pos1.x > pos2.x then + pos2.x, pos1.x = pos1.x, pos2.x + end + if pos1.y > pos2.y then + pos2.y, pos1.y = pos1.y, pos2.y + end + if pos1.z > pos2.z then + pos2.z, pos1.z = pos1.z, pos2.z + end + return pos1, pos2 +end + +--determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume +worldedit.volume = function(pos1, pos2) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1) +end + +--sets a region defined by positions `pos1` and `pos2` to `nodename`, returning the number of nodes filled +worldedit.set = function(pos1, pos2, nodename) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + for i in area:iterp(pos1, pos2) do + nodes[i] = node_id + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return worldedit.volume(pos1, pos2) +end + +--replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced +worldedit.replace = function(pos1, pos2, searchnode, replacenode) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + local nodes = manip:get_data() + local searchnode_id = minetest.get_content_id(searchnode) + local replacenode_id = minetest.get_content_id(replacenode) + local count = 0 + for i in area:iterp(pos1, pos2) do --replace searchnode with replacenode + if nodes[i] == searchnode_id then + nodes[i] = replacenode_id + count = count + 1 + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--replaces all nodes other than `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced +worldedit.replaceinverse = function(pos1, pos2, searchnode, replacenode) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + local nodes = manip:get_data() + local searchnode_id = minetest.get_content_id(searchnode) + local replacenode_id = minetest.get_content_id(replacenode) + local count = 0 + for i in area:iterp(pos1, pos2) do --replace anything that is not searchnode with replacenode + if nodes[i] ~= searchnode_id then + nodes[i] = replacenode_id + count = count + 1 + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +worldedit.copy = function(pos1, pos2, axis, amount) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + if amount == 0 then + return + end + + local other1, other2 + if axis == "x" then + other1, other2 = "y", "z" + elseif axis == "y" then + other1, other2 = "x", "z" + else --axis == "z" + other1, other2 = "x", "y" + end + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + --prepare slice along axis + local extent = { + [axis] = 1, + [other1]=pos2[other1] - pos1[other1] + 1, + [other2]=pos2[other2] - pos1[other2] + 1, + } + local nodes = {} + local schematic = {size=extent, data=nodes} + + local currentpos = {x=pos1.x, y=pos1.y, z=pos1.z} + local stride = {x=1, y=extent.x, z=extent.x * extent.y} + local get_node = minetest.get_node + for index1 = 1, extent[axis] do --go through each slice + --copy slice into schematic + local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed + for index2 = 1, extent[other1] do + local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1] + for index3 = 1, extent[other2] do + local i = newindex2 + (index3 + offset[other2]) * stride[other2] + nodes[i] = get_node(pos) + end + end + + --copy schematic to target + currentpos[axis] = currentpos[axis] + amount + place_schematic(currentpos, schematic) + + --wip: copy meta + + currentpos[axis] = currentpos[axis] + 1 + end + return worldedit.volume(pos1, pos2) +end + +--copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes copied +worldedit.copy = function(pos1, pos2, axis, amount) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + if amount < 0 then + local pos = {x=pos1.x, y=0, z=0} + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) --obtain current node + local meta = get_meta(pos):to_table() --get meta of current node + local value = pos[axis] --store current position + pos[axis] = value + amount --move along axis + add_node(pos, node) --copy node to new position + get_meta(pos):from_table(meta) --set metadata of new node + pos[axis] = value --restore old position + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + else + local pos = {x=pos2.x, y=0, z=0} + while pos.x >= pos1.x do + pos.y = pos2.y + while pos.y >= pos1.y do + pos.z = pos2.z + while pos.z >= pos1.z do + local node = get_node(pos) --obtain current node + local meta = get_meta(pos):to_table() --get meta of current node + local value = pos[axis] --store current position + pos[axis] = value + amount --move along axis + add_node(pos, node) --copy node to new position + get_meta(pos):from_table(meta) --set metadata of new node + pos[axis] = value --restore old position + pos.z = pos.z - 1 + end + pos.y = pos.y - 1 + end + pos.x = pos.x - 1 + end + end + return worldedit.volume(pos1, pos2) +end + +--moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes moved +worldedit.move = function(pos1, pos2, axis, amount) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + --wip: move slice by slice using schematic method in the move axis and transfer metadata in separate loop (and if the amount is greater than the length in the axis, copy whole thing at a time and erase original after, using schematic method) + local get_node, get_meta, add_node, remove_node = minetest.get_node, minetest.get_meta, minetest.add_node, minetest.remove_node + if amount < 0 then + local pos = {x=pos1.x, y=0, z=0} + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) --obtain current node + local meta = get_meta(pos):to_table() --get metadata of current node + remove_node(pos) + local value = pos[axis] --store current position + pos[axis] = value + amount --move along axis + add_node(pos, node) --move node to new position + get_meta(pos):from_table(meta) --set metadata of new node + pos[axis] = value --restore old position + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + else + local pos = {x=pos2.x, y=0, z=0} + while pos.x >= pos1.x do + pos.y = pos2.y + while pos.y >= pos1.y do + pos.z = pos2.z + while pos.z >= pos1.z do + local node = get_node(pos) --obtain current node + local meta = get_meta(pos):to_table() --get metadata of current node + remove_node(pos) + local value = pos[axis] --store current position + pos[axis] = value + amount --move along axis + add_node(pos, node) --move node to new position + get_meta(pos):from_table(meta) --set metadata of new node + pos[axis] = value --restore old position + pos.z = pos.z - 1 + end + pos.y = pos.y - 1 + end + pos.x = pos.x - 1 + end + end + return worldedit.volume(pos1, pos2) +end + +--duplicates the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") `count` times, returning the number of nodes stacked +worldedit.stack = function(pos1, pos2, axis, count) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local length = pos2[axis] - pos1[axis] + 1 + if count < 0 then + count = -count + length = -length + end + local amount = 0 + local copy = worldedit.copy + for i = 1, count do + amount = amount + length + copy(pos1, pos2, axis, amount) + end + return worldedit.volume(pos1, pos2) * count +end + +--scales the region defined by positions `pos1` and `pos2` by an factor of positive integer `factor` with `pos1` as the origin, returning the number of nodes scaled, the new scaled position 1, and the new scaled position 2 +worldedit.scale = function(pos1, pos2, factor) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --prepare schematic of large node + local get_node, get_meta, place_schematic = minetest.get_node, minetest.get_meta, minetest.place_schematic + local placeholder_node = {name="", param1=0, param2=0} + local nodes = {} + for i = 1, factor ^ 3 do + nodes[i] = placeholder_node + end + local schematic = {size={x=factor, y=factor, z=factor}, data=nodes} + + local size = factor - 1 + + --make area stay loaded + local manip = minetest.get_voxel_manip() + local new_pos2 = {x=pos1.x + (pos2.x - pos1.x) * factor + size, y=pos1.y + (pos2.y - pos1.y) * factor + size, z=pos1.z + (pos2.z - pos1.z) * factor + size} + manip:read_from_map(pos1, new_pos2) + + local pos = {x=pos2.x, y=0, z=0} + local bigpos = {x=0, y=0, z=0} + while pos.x >= pos1.x do + pos.y = pos2.y + while pos.y >= pos1.y do + pos.z = pos2.z + while pos.z >= pos1.z do + local node = get_node(pos) --obtain current node + local meta = get_meta(pos):to_table() --get meta of current node + + local value = pos[axis] --store current position + local posx, posy, posz = pos1.x + (pos.x - pos1.x) * factor, pos1.y + (pos.y - pos1.y) * factor, pos1.z + (pos.z - pos1.z) * factor + + --create large node + placeholder_node.name = node.name + placeholder_node.param1, placeholder_node.param2 = node.param1, node.param2 + bigpos.x, bigpos.y, bigpos.z = posx, posy, posz + place_schematic(bigpos, schematic) + + --fill in large node meta + if next(meta.fields) ~= nil and next(meta.inventory) ~= nil then --node has meta fields + for x = 0, size do + for y = 0, size do + for z = 0, size do + bigpos.x, bigpos.y, bigpos.z = posx + x, posy + y, posz + z + get_meta(bigpos):from_table(meta) --set metadata of new node + end + end + end + end + pos.z = pos.z - 1 + end + pos.y = pos.y - 1 + end + pos.x = pos.x - 1 + end + return worldedit.volume(pos1, pos2) * (factor ^ 3), pos1, new_pos2 +end + +--transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed, the new transposed position 1, and the new transposed position 2 +worldedit.transpose = function(pos1, pos2, axis1, axis2) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + local compare + local extent1, extent2 = pos2[axis1] - pos1[axis1], pos2[axis2] - pos1[axis2] + + if extent1 > extent2 then + compare = function(extent1, extent2) + return extent1 > extent2 + end + else + compare = function(extent1, extent2) + return extent1 < extent2 + end + end + + --calculate the new position 2 after transposition + local new_pos2 = {x=pos2.x, y=pos2.y, z=pos2.z} + new_pos2[axis1] = pos1[axis1] + extent2 + new_pos2[axis2] = pos1[axis2] + extent1 + + --make area stay loaded + local manip = minetest.get_voxel_manip() + local upperbound = {x=pos2.x, y=pos2.y, z=pos2.z} + if upperbound[axis1] < new_pos2[axis1] then upperbound[axis1] = new_pos2[axis1] end + if upperbound[axis2] < new_pos2[axis2] then upperbound[axis2] = new_pos2[axis2] end + manip:read_from_map(pos1, upperbound) + + local pos = {x=pos1.x, y=0, z=0} + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local extent1, extent2 = pos[axis1] - pos1[axis1], pos[axis2] - pos1[axis2] + if compare(extent1, extent2) then --transpose only if below the diagonal + local node1 = get_node(pos) + local meta1 = get_meta(pos):to_table() + local value1, value2 = pos[axis1], pos[axis2] --save position values + pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1 --swap axis extents + local node2 = get_node(pos) + local meta2 = get_meta(pos):to_table() + add_node(pos, node1) + get_meta(pos):from_table(meta1) + pos[axis1], pos[axis2] = value1, value2 --restore position values + add_node(pos, node2) + get_meta(pos):from_table(meta2) + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return worldedit.volume(pos1, pos2), pos1, new_pos2 +end + +--flips a region defined by the positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z"), returning the number of nodes flipped +worldedit.flip = function(pos1, pos2, axis) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + --wip: flip the region slice by slice along the flip axis using schematic method + local pos = {x=pos1.x, y=0, z=0} + local start = pos1[axis] + pos2[axis] + pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2) + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node1 = get_node(pos) + local meta1 = get_meta(pos):to_table() + local value = pos[axis] + pos[axis] = start - value + local node2 = get_node(pos) + local meta2 = get_meta(pos):to_table() + add_node(pos, node1) + get_meta(pos):from_table(meta1) + pos[axis] = value + add_node(pos, node2) + get_meta(pos):from_table(meta2) + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return worldedit.volume(pos1, pos2) +end + +--rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise around axis `axis` (90 degree increment), returning the number of nodes rotated +worldedit.rotate = function(pos1, pos2, axis, angle) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + local axis1, axis2 + if axis == "x" then + axis1, axis2 = "z", "y" + elseif axis == "y" then + axis1, axis2 = "x", "z" + else --axis == "z" + axis1, axis2 = "y", "x" + end + angle = angle % 360 + + local count + if angle == 90 then + worldedit.flip(pos1, pos2, axis1) + count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + elseif angle == 180 then + worldedit.flip(pos1, pos2, axis1) + count = worldedit.flip(pos1, pos2, axis2) + elseif angle == 270 then + worldedit.flip(pos1, pos2, axis2) + count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + end + return count, pos1, pos2 +end + +--rotates all oriented nodes in a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (90 degree increment) around the Y axis, returning the number of nodes oriented +worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotation along arbitrary axis + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local registered_nodes = minetest.registered_nodes + + local wallmounted = { + [90]={[0]=0, [1]=1, [2]=5, [3]=4, [4]=2, [5]=3}, + [180]={[0]=0, [1]=1, [2]=3, [3]=2, [4]=5, [5]=4}, + [270]={[0]=0, [1]=1, [2]=4, [3]=5, [4]=3, [5]=2} + } + local facedir = { + [90]={[0]=1, [1]=2, [2]=3, [3]=0}, + [180]={[0]=2, [1]=3, [2]=0, [3]=1}, + [270]={[0]=3, [1]=0, [2]=1, [3]=2} + } + + angle = angle % 360 + if angle == 0 then + return 0 + end + local wallmounted_substitution = wallmounted[angle] + local facedir_substitution = facedir[angle] + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local count = 0 + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + local pos = {x=pos1.x, y=0, z=0} + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) + local def = registered_nodes[node.name] + if def then + if def.paramtype2 == "wallmounted" then + node.param2 = wallmounted_substitution[node.param2] + local meta = get_meta(pos):to_table() + add_node(pos, node) + get_meta(pos):from_table(meta) + count = count + 1 + elseif def.paramtype2 == "facedir" then + node.param2 = facedir_substitution[node.param2] + local meta = get_meta(pos):to_table() + add_node(pos, node) + get_meta(pos):from_table(meta) + count = count + 1 + end + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return count +end + +--fixes the lighting in a region defined by positions `pos1` and `pos2`, returning the number of nodes updated +worldedit.fixlight = function(pos1, pos2) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local nodes = minetest.find_nodes_in_area(pos1, pos2, "air") + local dig_node = minetest.dig_node + for _, pos in ipairs(nodes) do + dig_node(pos) + end + return #nodes +end + +--clears all objects in a region defined by the positions `pos1` and `pos2`, returning the number of objects cleared +worldedit.clearobjects = function(pos1, pos2) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1x, pos1y, pos1z = pos1.x, pos1.y, pos1.z + local pos2x, pos2y, pos2z = pos2.x + 1, pos2.y + 1, pos2.z + 1 + local center = {x=(pos1x + pos2x) / 2, y=(pos1y + pos2y) / 2, z=(pos1z + pos2z) / 2} --center of region + local radius = ((center.x - pos1x + 0.5) + (center.y - pos1y + 0.5) + (center.z - pos1z + 0.5)) ^ 0.5 --bounding sphere radius + local count = 0 + for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do --all objects in bounding sphere + local entity = obj:get_luaentity() + if not (entity and entity.name:find("^worldedit:")) then --avoid WorldEdit entities + local pos = obj:getpos() + if pos.x >= pos1x and pos.x <= pos2x + and pos.y >= pos1y and pos.y <= pos2y + and pos.z >= pos1z and pos.z <= pos2z then --inside region + obj:remove() + count = count + 1 + end + end + end + return count +end diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/primitives.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/primitives.lua new file mode 100644 index 0000000..96696a1 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/primitives.lua @@ -0,0 +1,478 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +--adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.hollow_sphere = function(pos, radius, nodename) + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius} + local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius} + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1) + local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z + local zstride, ystride = area.zstride, area.ystride + local count = 0 + for z = -radius, radius do + local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed + for y = -radius, radius do + local newy = newz + (y + offsety) * ystride + for x = -radius, radius do + local squared = x * x + y * y + z * z + if squared >= min_radius and squared <= max_radius then --position is on surface of sphere + local i = newy + (x + offsetx) + nodes[i] = node_id + count = count + 1 + end + end + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.sphere = function(pos, radius, nodename) + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius} + local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius} + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local max_radius = radius * (radius + 1) + local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z + local zstride, ystride = area.zstride, area.ystride + local count = 0 + for z = -radius, radius do + local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed + for y = -radius, radius do + local newy = newz + (y + offsety) * ystride + for x = -radius, radius do + if x * x + y * y + z * z <= max_radius then --position is inside sphere + local i = newy + (x + offsetx) + nodes[i] = node_id + count = count + 1 + end + end + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.hollow_dome = function(pos, radius, nodename) + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius} + local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius} + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + local miny, maxy = 0, radius + if radius < 0 then + radius = -radius + miny, maxy = -radius, 0 + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1) + local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z + local zstride, ystride = area.zstride, area.ystride + local count = 0 + for z = -radius, radius do + local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed + for y = miny, maxy do + local newy = newz + (y + offsety) * ystride + for x = -radius, radius do + local squared = x * x + y * y + z * z + if squared >= min_radius and squared <= max_radius then --position is on surface of sphere + local i = newy + (x + offsetx) + nodes[i] = node_id + count = count + 1 + end + end + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.dome = function(pos, radius, nodename) + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius} + local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius} + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + local miny, maxy = 0, radius + if radius < 0 then + radius = -radius + miny, maxy = -radius, 0 + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local max_radius = radius * (radius + 1) + local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z + local zstride, ystride = area.zstride, area.ystride + local count = 0 + for z = -radius, radius do + local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed + for y = miny, maxy do + local newy = newz + (y + offsety) * ystride + for x = -radius, radius do + if x * x + y * y + z * z <= max_radius then --position is inside sphere + local i = newy + (x + offsetx) + nodes[i] = node_id + count = count + 1 + end + end + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename) --wip: rewrite this using voxelmanip + local other1, other2 + if axis == "x" then + other1, other2 = "y", "z" + elseif axis == "y" then + other1, other2 = "x", "z" + else --axis == "z" + other1, other2 = "x", "y" + end + + --handle negative lengths + local currentpos = {x=pos.x, y=pos.y, z=pos.z} + if length < 0 then + length = -length + currentpos[axis] = currentpos[axis] - length + end + + --make area stay loaded + local manip = minetest.get_voxel_manip() + local pos1 = { + [axis]=currentpos[axis], + [other1]=currentpos[other1] - radius, + [other2]=currentpos[other2] - radius + } + local pos2 = { + [axis]=currentpos[axis] + length - 1, + [other1]=currentpos[other1] + radius, + [other2]=currentpos[other2] + radius + } + manip:read_from_map(pos1, pos2) + + --create schematic for single node column along the axis + local node = {name=nodename, param1=0, param2=0} + local nodes = {} + for i = 1, length do + nodes[i] = node + end + local schematic = {size={[axis]=length, [other1]=1, [other2]=1}, data=nodes} + + --add columns in a circle around axis to form cylinder + local place_schematic = minetest.place_schematic + local count = 0 + local offset1, offset2 = 0, radius + local delta = -radius + while offset1 <= offset2 do + --add node at each octant + local first1, first2 = pos[other1] + offset1, pos[other1] - offset1 + local second1, second2 = pos[other2] + offset2, pos[other2] - offset2 + currentpos[other1], currentpos[other2] = first1, second1 + place_schematic(currentpos, schematic) --octant 1 + currentpos[other1] = first2 + place_schematic(currentpos, schematic) --octant 4 + currentpos[other2] = second2 + place_schematic(currentpos, schematic) --octant 5 + currentpos[other1] = first1 + place_schematic(currentpos, schematic) --octant 8 + local first1, first2 = pos[other1] + offset2, pos[other1] - offset2 + local second1, second2 = pos[other2] + offset1, pos[other2] - offset1 + currentpos[other1], currentpos[other2] = first1, second1 + place_schematic(currentpos, schematic) --octant 2 + currentpos[other1] = first2 + place_schematic(currentpos, schematic) --octant 3 + currentpos[other2] = second2 + place_schematic(currentpos, schematic) --octant 6 + currentpos[other1] = first1 + place_schematic(currentpos, schematic) --octant 7 + + count = count + 8 --wip: broken because sometimes currentpos is repeated + + --move to next location + delta = delta + (offset1 * 2) + 1 + if delta >= 0 then + offset2 = offset2 - 1 + delta = delta - (offset2 * 2) + end + offset1 = offset1 + 1 + end + count = count * length --apply the length to the number of nodes + return count +end + +--adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added +worldedit.cylinder = function(pos, axis, length, radius, nodename) + local other1, other2 + if axis == "x" then + other1, other2 = "y", "z" + elseif axis == "y" then + other1, other2 = "x", "z" + else --axis == "z" + other1, other2 = "x", "y" + end + + --handle negative lengths + local currentpos = {x=pos.x, y=pos.y, z=pos.z} + if length < 0 then + length = -length + currentpos[axis] = currentpos[axis] - length + end + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local pos1 = { + [axis]=currentpos[axis], + [other1]=currentpos[other1] - radius, + [other2]=currentpos[other2] - radius + } + local pos2 = { + [axis]=currentpos[axis] + length - 1, + [other1]=currentpos[other1] + radius, + [other2]=currentpos[other2] + radius + } + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local max_radius = radius * (radius + 1) + local stride = {x=1, y=area.ystride, z=area.zstride} + local offset = {x=currentpos.x - emerged_pos1.x, y=currentpos.y - emerged_pos1.y, z=currentpos.z - emerged_pos1.z} + local min_slice, max_slice = offset[axis], offset[axis] + length - 1 + local count = 0 + for index2 = -radius, radius do + local newindex2 = (index2 + offset[other1]) * stride[other1] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed + for index3 = -radius, radius do + local newindex3 = newindex2 + (index3 + offset[other2]) * stride[other2] + if index2 * index2 + index3 * index3 <= max_radius then + for index1 = min_slice, max_slice do --add column along axis + local i = newindex3 + index1 * stride[axis] + nodes[i] = node_id + end + count = count + length + end + end + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a pyramid centered at `pos` with height `height`, composed of `nodename`, returning the number of nodes added +worldedit.pyramid = function(pos, axis, height, nodename) + local other1, other2 + if axis == "x" then + other1, other2 = "y", "z" + elseif axis == "y" then + other1, other2 = "x", "z" + else --axis == "z" + other1, other2 = "x", "y" + end + + local pos1 = {x=pos.x - height, y=pos.y - height, z=pos.z - height} + local pos2 = {x=pos.x + height, y=pos.y + height, z=pos.z + height} + + --handle inverted pyramids + local startaxis, endaxis, step + if height > 0 then + height = height - 1 + step = 1 + pos1[axis] = pos[axis] --upper half of box + else + height = height + 1 + step = -1 + pos2[axis] = pos[axis] --lower half of box + end + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + --fill selected area with node + local node_id = minetest.get_content_id(nodename) + local stride = {x=1, y=area.ystride, z=area.zstride} + local offset = {x=pos.x - emerged_pos1.x, y=pos.y - emerged_pos1.y, z=pos.z - emerged_pos1.z} + local size = height * step + local count = 0 + for index1 = 0, height, step do --go through each level of the pyramid + local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed + for index2 = -size, size do + local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1] + for index3 = -size, size do + local i = newindex2 + (index3 + offset[other2]) * stride[other2] + nodes[i] = node_id + end + end + count = count + (size * 2 + 1) ^ 2 + size = size - 1 + end + + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end + +--adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`, returning the number of nodes added +worldedit.spiral = function(pos, length, height, spacer, nodename) + local extent = math.ceil(length / 2) + local pos1 = {x=pos.x - extent, y=pos.y, z=pos.z - extent} + local pos2 = {x=pos.x + extent, y=pos.y + height, z=pos.z + extent} + + --set up voxel manipulator + local manip = minetest.get_voxel_manip() + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) + + --fill emerged area with ignore + local nodes = {} + local ignore = minetest.get_content_id("ignore") + for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do + nodes[i] = ignore + end + + -- + local node_id = minetest.get_content_id(nodename) + local stride = {x=1, y=area.ystride, z=area.zstride} + local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z + local i = offsetz * stride.z + offsety * stride.y + offsetx + 1 + + --add first column + local column = i + for y = 1, height do + nodes[column] = node_id + column = column + stride.y + end + + --add spiral segments + local axis, other = "x", "z" + local sign = 1 + local count = height + for segment = 1, length / spacer - 1 do --go through each segment except the last + for index = 1, segment * spacer do --fill segment + i = i + stride[axis] * sign + local column = i + for y = 1, height do --add column + nodes[column] = node_id + column = column + stride.y + end + count = count + height + end + axis, other = other, axis --swap axes + if segment % 2 == 1 then --change sign every other turn + sign = -sign + end + end + + --add shorter final segment + for index = 1, (math.floor(length / spacer) - 2) * spacer do + i = i + stride[axis] * sign + local column = i + for y = 1, height do --add column + nodes[column] = node_id + column = column + stride.y + end + count = count + height + end +print(minetest.serialize(nodes)) + --update map nodes + manip:set_data(nodes) + manip:write_to_map() + manip:update_map() + + return count +end \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/serialization.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/serialization.lua new file mode 100644 index 0000000..737d62d --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/serialization.lua @@ -0,0 +1,273 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions +worldedit.sort_pos = function(pos1, pos2) + pos1 = {x=pos1.x, y=pos1.y, z=pos1.z} + pos2 = {x=pos2.x, y=pos2.y, z=pos2.z} + if pos1.x > pos2.x then + pos2.x, pos1.x = pos1.x, pos2.x + end + if pos1.y > pos2.y then + pos2.y, pos1.y = pos1.y, pos2.y + end + if pos1.z > pos2.z then + pos2.z, pos1.z = pos1.z, pos2.z + end + return pos1, pos2 +end + +--determines the version of serialized data `value`, returning the version as a positive integer or 0 for unknown versions +worldedit.valueversion = function(value) + if value:find("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)") and not value:find("%{") then --previous list format + return 3 + elseif value:find("^[^\"']+%{%d+%}") then + if value:find("%[\"meta\"%]") then --previous meta flat table format + return 2 + end + return 1 --original flat table format + elseif value:find("%{") then --current nested table format + return 4 + end + return 0 --unknown format +end + +--converts the region defined by positions `pos1` and `pos2` into a single string, returning the serialized data and the number of nodes serialized +worldedit.serialize = function(pos1, pos2) + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local pos = {x=pos1.x, y=0, z=0} + local count = 0 + local result = {} + local get_node, get_meta = minetest.get_node, minetest.get_meta + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) + if node.name ~= "air" and node.name ~= "ignore" then + count = count + 1 + local meta = get_meta(pos):to_table() + + --convert metadata itemstacks to itemstrings + for name, inventory in pairs(meta.inventory) do + for index, stack in ipairs(inventory) do + inventory[index] = stack.to_string and stack:to_string() or stack + end + end + + result[count] = { + x = pos.x - pos1.x, + y = pos.y - pos1.y, + z = pos.z - pos1.z, + name = node.name, + param1 = node.param1, + param2 = node.param2, + meta = meta, + } + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + result = minetest.serialize(result) --convert entries to a string + return result, count +end + +--determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes +--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) +worldedit.allocate = function(originpos, value) + local huge = math.huge + local pos1x, pos1y, pos1z = huge, huge, huge + local pos2x, pos2y, pos2z = -huge, -huge, -huge + local originx, originy, originz = originpos.x, originpos.y, originpos.z + local count = 0 + local version = worldedit.valueversion(value) + if version == 1 or version == 2 then --flat table format + --obtain the node table + local get_tables = loadstring(value) + if get_tables then --error loading value + return originpos, originpos, count + end + local tables = get_tables() + + --transform the node table into an array of nodes + for i = 1, #tables do + for j, v in pairs(tables[i]) do + if type(v) == "table" then + tables[i][j] = tables[v[1]] + end + end + end + local nodes = tables[1] + + --check the node array + count = #nodes + if version == 1 then --original flat table format + for index = 1, count do + local entry = nodes[index] + local pos = entry[1] + local x, y, z = originx - pos.x, originy - pos.y, originz - pos.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + else --previous meta flat table format + for index = 1, count do + local entry = nodes[index] + local x, y, z = originx - entry.x, originy - entry.y, originz - entry.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + end + elseif version == 3 then --previous list format + for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries + x, y, z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z) + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + count = count + 1 + end + elseif version == 4 then --current nested table format + --wip: this is a filthy hack that works surprisingly well + value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1) + local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end) + local startpos, startpos1, endpos = 1, 1 + local nodes = {} + while true do + startpos, endpos = escaped:find("},%s*{", startpos) + if not startpos then + break + end + local current = value:sub(startpos1, startpos) + table.insert(nodes, minetest.deserialize("return " .. current)) + startpos, startpos1 = endpos, endpos + end + table.insert(nodes, minetest.deserialize("return " .. value:sub(startpos1))) + + --local nodes = minetest.deserialize(value) --wip: this is broken for larger tables in the current version of LuaJIT + + count = #nodes + for index = 1, count do + local entry = nodes[index] + x, y, z = originx + entry.x, originy + entry.y, originz + entry.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + end + local pos1 = {x=pos1x, y=pos1y, z=pos1z} + local pos2 = {x=pos2x, y=pos2y, z=pos2z} + return pos1, pos2, count +end + +--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized +--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) +worldedit.deserialize = function(originpos, value) + --make area stay loaded --wip: not very performant + local pos1, pos2 = worldedit.allocate(originpos, value) + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local originx, originy, originz = originpos.x, originpos.y, originpos.z + local count = 0 + local add_node, get_meta = minetest.add_node, minetest.get_meta + local version = worldedit.valueversion(value) + if version == 1 or version == 2 then --original flat table format + --obtain the node table + local get_tables = loadstring(value) + if not get_tables then --error loading value + return count + end + local tables = get_tables() + + --transform the node table into an array of nodes + for i = 1, #tables do + for j, v in pairs(tables[i]) do + if type(v) == "table" then + tables[i][j] = tables[v[1]] + end + end + end + local nodes = tables[1] + + --load the node array + count = #nodes + if version == 1 then --original flat table format + for index = 1, count do + local entry = nodes[index] + local pos = entry[1] + pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z + add_node(pos, entry[2]) + end + else --previous meta flat table format + for index = 1, #nodes do + local entry = nodes[index] + entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z + add_node(entry, entry) --entry acts both as position and as node + get_meta(entry):from_table(entry.meta) + end + end + elseif version == 3 then --previous list format + local pos = {x=0, y=0, z=0} + local node = {name="", param1=0, param2=0} + for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries + pos.x, pos.y, pos.z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z) + node.name, node.param1, node.param2 = name, param1, param2 + add_node(pos, node) + count = count + 1 + end + elseif version == 4 then --current nested table format + --wip: this is a filthy hack that works surprisingly well + value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1) + local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end) + local startpos, startpos1, endpos = 1, 1 + local nodes = {} + while true do + startpos, endpos = escaped:find("},%s*{", startpos) + if not startpos then + break + end + local current = value:sub(startpos1, startpos) + table.insert(nodes, minetest.deserialize("return " .. current)) + startpos, startpos1 = endpos, endpos + end + table.insert(nodes, minetest.deserialize("return " .. value:sub(startpos1))) + + --local nodes = minetest.deserialize(value) --wip: this is broken for larger tables in the current version of LuaJIT + + --load the nodes + count = #nodes + for index = 1, count do + local entry = nodes[index] + entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z + add_node(entry, entry) --entry acts both as position and as node + end + + --load the metadata + for index = 1, count do + local entry = nodes[index] + get_meta(entry):from_table(entry.meta) + end + end + return count +end diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/visualization.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/visualization.lua new file mode 100644 index 0000000..a3a4ca3 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit/visualization.lua @@ -0,0 +1,142 @@ +worldedit = worldedit or {} +local minetest = minetest --local copy of global + +--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions +worldedit.sort_pos = function(pos1, pos2) + pos1 = {x=pos1.x, y=pos1.y, z=pos1.z} + pos2 = {x=pos2.x, y=pos2.y, z=pos2.z} + if pos1.x > pos2.x then + pos2.x, pos1.x = pos1.x, pos2.x + end + if pos1.y > pos2.y then + pos2.y, pos1.y = pos1.y, pos2.y + end + if pos1.z > pos2.z then + pos2.z, pos1.z = pos1.z, pos2.z + end + return pos1, pos2 +end + +--determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume +worldedit.volume = function(pos1, pos2) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1) +end + +minetest.register_node("worldedit:placeholder", { + drawtype = "airlike", + paramtype = "light", + sunlight_propagates = true, + diggable = false, + groups = {not_in_creative_inventory=1}, +}) + +--hides all nodes in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes hidden +worldedit.hide = function(pos1, pos2) + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local pos = {x=pos1.x, y=0, z=0} + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) + if node.name ~= "worldedit:placeholder" then + local data = get_meta(pos):to_table() --obtain metadata of original node + data.fields.worldedit_placeholder = node.name --add the node's name + node.name = "worldedit:placeholder" --set node name + add_node(pos, node) --add placeholder node + get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return worldedit.volume(pos1, pos2) +end + +--suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes suppressed +worldedit.suppress = function(pos1, pos2, nodename) + --ignore placeholder supression + if nodename == "worldedit:placeholder" then + return 0 + end + + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local nodes = minetest.find_nodes_in_area(pos1, pos2, nodename) + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + for _, pos in ipairs(nodes) do + local node = get_node(pos) + local data = get_meta(pos):to_table() --obtain metadata of original node + data.fields.worldedit_placeholder = node.name --add the node's name + node.name = "worldedit:placeholder" --set node name + add_node(pos, node) --add placeholder node + get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata + end + return #nodes +end + +--highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes, returning the number of nodes found +worldedit.highlight = function(pos1, pos2, nodename) + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local pos = {x=pos1.x, y=0, z=0} + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + local count = 0 + while pos.x <= pos2.x do + pos.y = pos1.y + while pos.y <= pos2.y do + pos.z = pos1.z + while pos.z <= pos2.z do + local node = get_node(pos) + if node.name == nodename then --node found + count = count + 1 + elseif node.name ~= "worldedit:placeholder" then --hide other nodes + local data = get_meta(pos):to_table() --obtain metadata of original node + data.fields.worldedit_placeholder = node.name --add the node's name + node.name = "worldedit:placeholder" --set node name + add_node(pos, node) --add placeholder node + get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata + end + pos.z = pos.z + 1 + end + pos.y = pos.y + 1 + end + pos.x = pos.x + 1 + end + return count +end + +--restores all nodes hidden with WorldEdit functions in a region defined by positions `pos1` and `pos2`, returning the number of nodes restored +worldedit.restore = function(pos1, pos2) + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local nodes = minetest.find_nodes_in_area(pos1, pos2, "worldedit:placeholder") + local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node + for _, pos in ipairs(nodes) do + local node = get_node(pos) + local data = get_meta(pos):to_table() --obtain node metadata + node.name = data.fields.worldedit_placeholder --set node name + data.fields.worldedit_placeholder = nil --delete old nodename + add_node(pos, node) --add original node + get_meta(pos):from_table(data) --set original node metadata + end + return #nodes +end diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/depends.txt b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/depends.txt new file mode 100644 index 0000000..df8caff --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/depends.txt @@ -0,0 +1 @@ +worldedit \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/init.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/init.lua new file mode 100644 index 0000000..cbb2d31 --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/init.lua @@ -0,0 +1,1163 @@ +minetest.register_privilege("worldedit", "Can use WorldEdit commands") + +worldedit.set_pos = {} +worldedit.inspect = {} + +worldedit.pos1 = {} +worldedit.pos2 = {} +if minetest.place_schematic then + worldedit.prob_pos = {} + worldedit.prob_list = {} +end + +dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua") + +worldedit.player_notify = function(name, message) + minetest.chat_send_player(name, "WorldEdit -!- " .. message, false) +end + +--determines whether `nodename` is a valid node name, returning a boolean +worldedit.normalize_nodename = function(nodename) + local fullname = ItemStack({name=nodename}):get_name() --resolve aliases of node names to full names + if minetest.registered_nodes[fullname] then --directly found node name or alias of nodename + return fullname + end + for key, value in pairs(minetest.registered_nodes) do + if key:find(":" .. nodename, 1, true) then --found in mod + return key + end + end + nodename = nodename:lower() --lowercase both for case insensitive comparison + for key, value in pairs(minetest.registered_nodes) do + if value.description:lower() == nodename then --found in description + return key + end + end + return nil +end + +--determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1) +worldedit.player_axis = function(name) + local dir = minetest.get_player_by_name(name):get_look_dir() + local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z) + if x > y then + if x > z then + return "x", dir.x > 0 and 1 or -1 + end + elseif y > z then + return "y", dir.y > 0 and 1 or -1 + end + return "z", dir.z > 0 and 1 or -1 +end + +minetest.register_chatcommand("/inspect", { + params = "on/off/1/0/true/false/yes/no/enable/disable", + description = "Enable or disable node inspection", + privs = {worldedit=true}, + func = function(name, param) + if param == "on" or param == "1" or param == "true" or param == "yes" or param == "enable" then + worldedit.inspect[name] = true + worldedit.player_notify(name, "node inspection enabled") + elseif param == "off" or param == "0" or param == "false" or param == "no" or param == "disable" then + worldedit.inspect[name] = nil + worldedit.player_notify(name, "node inspection disabled") + else + worldedit.player_notify(name, "invalid usage: " .. param) + end + end, +}) + +minetest.register_on_punchnode(function(pos, node, puncher) + local name = puncher:get_player_name() + if worldedit.inspect[name] then + if minetest.check_player_privs(name, {worldedit=true}) then + message = "inspector: " .. node.name .. " at " .. minetest.pos_to_string(pos) .. " (param1=" .. node.param1 .. ", param2=" .. node.param2 .. ")" + else + message = "inspector: worldedit privileges required" + end + worldedit.player_notify(name, message) + end +end) + +minetest.register_chatcommand("/reset", { + params = "", + description = "Reset the region so that it is empty", + privs = {worldedit=true}, + func = function(name, param) + worldedit.pos1[name] = nil + worldedit.pos2[name] = nil + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.set_pos[name] = nil + worldedit.player_notify(name, "region reset") + end, +}) + +minetest.register_chatcommand("/mark", { + params = "", + description = "Show markers at the region positions", + privs = {worldedit=true}, + func = function(name, param) + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.player_notify(name, "region marked") + end, +}) + +minetest.register_chatcommand("/unmark", { + params = "", + description = "Hide markers if currently shown", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + worldedit.pos1[name] = nil + worldedit.pos2[name] = nil + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.player_notify(name, "region unmarked") + end, +}) + +minetest.register_chatcommand("/pos1", { + params = "", + description = "Set WorldEdit region position 1 to the player's location", + privs = {worldedit=true}, + func = function(name, param) + local pos = minetest.get_player_by_name(name):getpos() + pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) + end, +}) + +minetest.register_chatcommand("/pos2", { + params = "", + description = "Set WorldEdit region position 2 to the player's location", + privs = {worldedit=true}, + func = function(name, param) + local pos = minetest.get_player_by_name(name):getpos() + pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) + worldedit.pos2[name] = pos + worldedit.mark_pos2(name) + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) + end, +}) + +minetest.register_chatcommand("/p", { + params = "set/set1/set2/get", + description = "Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + if param == "set" then --set both WorldEdit positions + worldedit.set_pos[name] = "pos1" + worldedit.player_notify(name, "select positions by punching two nodes") + elseif param == "set1" then --set WorldEdit position 1 + worldedit.set_pos[name] = "pos1only" + worldedit.player_notify(name, "select position 1 by punching a node") + elseif param == "set2" then --set WorldEdit position 2 + worldedit.set_pos[name] = "pos2" + worldedit.player_notify(name, "select position 2 by punching a node") + elseif param == "get" then --display current WorldEdit positions + if worldedit.pos1[name] ~= nil then + worldedit.player_notify(name, "position 1: " .. minetest.pos_to_string(worldedit.pos1[name])) + else + worldedit.player_notify(name, "position 1 not set") + end + if worldedit.pos2[name] ~= nil then + worldedit.player_notify(name, "position 2: " .. minetest.pos_to_string(worldedit.pos2[name])) + else + worldedit.player_notify(name, "position 2 not set") + end + else + worldedit.player_notify(name, "unknown subcommand: " .. param) + end + end, +}) + +minetest.register_chatcommand("/fixedpos", { + params = "set1/set2 x y z", + description = "Set a WorldEdit region position to the position at (, , )", + privs = {worldedit=true}, + func = function(name, param) + local found, _, flag, x, y, z = param:find("^(set[12])%s+([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)} + if flag == "set1" then + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) + else --flag == "set2" + worldedit.pos2[name] = pos + worldedit.mark_pos2(name) + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) + end + end, +}) + +minetest.register_on_punchnode(function(pos, node, puncher) + local name = puncher:get_player_name() + if name ~= "" and worldedit.set_pos[name] ~= nil then --currently setting position + if worldedit.set_pos[name] == "pos1" then --setting position 1 + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + worldedit.set_pos[name] = "pos2" --set position 2 on the next invocation + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) + elseif worldedit.set_pos[name] == "pos1only" then --setting position 1 only + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + worldedit.set_pos[name] = nil --finished setting positions + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) + elseif worldedit.set_pos[name] == "pos2" then --setting position 2 + worldedit.pos2[name] = pos + worldedit.mark_pos2(name) + worldedit.set_pos[name] = nil --finished setting positions + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) + elseif worldedit.set_pos[name] == "prob" then --setting Minetest schematic node probabilities + worldedit.prob_pos[name] = pos + minetest.show_formspec(puncher:get_player_name(), "prob_val_enter", "field[text;;]") + end + end +end) + +minetest.register_chatcommand("/volume", { + params = "", + description = "Display the volume of the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local volume = worldedit.volume(pos1, pos2) + local abs = math.abs + worldedit.player_notify(name, "current region has a volume of " .. volume .. " nodes (" + .. abs(pos2.x - pos1.x) .. "*" + .. abs(pos2.y - pos1.y) .. "*" + .. abs(pos2.z - pos1.z) .. ")") + end, +}) + +minetest.register_chatcommand("/set", { + params = "", + description = "Set the current WorldEdit region to ", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) + return + end + + local count = worldedit.set(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes set") + end, +}) + +minetest.register_chatcommand("/replace", { + params = " ", + description = "Replace all instances of with in the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local newsearchnode = worldedit.normalize_nodename(searchnode) + if not newsearchnode then + worldedit.player_notify(name, "invalid search node name: " .. searchnode) + return + end + local newreplacenode = worldedit.normalize_nodename(replacenode) + if not newreplacenode then + worldedit.player_notify(name, "invalid replace node name: " .. replacenode) + return + end + + local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode) + worldedit.player_notify(name, count .. " nodes replaced") + end, +}) + +minetest.register_chatcommand("/replaceinverse", { + params = " ", + description = "Replace all nodes other than with in the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local newsearchnode = worldedit.normalize_nodename(searchnode) + if not newsearchnode then + worldedit.player_notify(name, "invalid search node name: " .. searchnode) + return + end + local newreplacenode = worldedit.normalize_nodename(replacenode) + if not newreplacenode then + worldedit.player_notify(name, "invalid replace node name: " .. replacenode) + return + end + + local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) + worldedit.player_notify(name, count .. " nodes replaced") + end, +}) + +minetest.register_chatcommand("/hollowsphere", { + params = " ", + description = "Add hollow sphere centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.hollow_sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/sphere", { + params = " ", + description = "Add sphere centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/hollowdome", { + params = " ", + description = "Add hollow dome centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.hollow_dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/dome", { + params = " ", + description = "Add dome centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/hollowcylinder", { + params = "x/y/z/? ", + description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + length, radius = tonumber(length), tonumber(radius) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + length = length * sign + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.hollow_cylinder(pos, axis, length, radius, node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/cylinder", { + params = "x/y/z/? ", + description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + length, radius = tonumber(length), tonumber(radius) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + length = length * sign + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.cylinder(pos, axis, length, radius, node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/pyramid", { + params = "x/y/z/? ", + description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + height = tonumber(height) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + height = height * sign + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.pyramid(pos, axis, height, node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/spiral", { + params = " ", + description = "Add spiral centered at WorldEdit position 1 with side length , height , space between walls , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, length, height, space, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.spiral(pos, tonumber(length), tonumber(height), tonumber(space), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/copy", { + params = "x/y/z/? ", + description = "Copy the current WorldEdit region along the x/y/z/? axis by nodes", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + amount = tonumber(amount) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + amount = amount * sign + end + + local count = worldedit.copy(pos1, pos2, axis, amount) + worldedit.player_notify(name, count .. " nodes copied") + end, +}) + +minetest.register_chatcommand("/move", { + params = "x/y/z/? ", + description = "Move the current WorldEdit region along the x/y/z/? axis by nodes", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + amount = tonumber(amount) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + amount = amount * sign + end + + local count = worldedit.move(pos1, pos2, axis, amount) + + pos1[axis] = pos1[axis] + amount + pos2[axis] = pos2[axis] + amount + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.player_notify(name, count .. " nodes moved") + end, +}) + +minetest.register_chatcommand("/stack", { + params = "x/y/z/? ", + description = "Stack the current WorldEdit region along the x/y/z/? axis times", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, count = param:find("^([xyz%?])%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + count = tonumber(count) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + count = count * sign + end + + local count = worldedit.stack(pos1, pos2, axis, count) + worldedit.player_notify(name, count .. " nodes stacked") + end, +}) + +minetest.register_chatcommand("/scale", { + params = "", + description = "Scale the current WorldEdit positions and region by a factor of positive integer with position 1 as the origin", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local factor = tonumber(param) + if not factor or factor ~= math.floor(factor) or factor <= 0 then + worldedit.player_notify(name, "invalid scaling factor: " .. param) + end + + local count, pos1, pos2 = worldedit.scale(pos1, pos2, factor) + + --reset markers to scaled positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes scaled") + end, +}) + +minetest.register_chatcommand("/transpose", { + params = "x/y/z/? x/y/z/?", + description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + if axis1 == "?" then + axis1 = worldedit.player_axis(name) + end + if axis2 == "?" then + axis2 = worldedit.player_axis(name) + end + if axis1 == axis2 then + worldedit.player_notify(name, "invalid usage: axes must be different") + return + end + + local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + + --reset markers to transposed positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes transposed") + end, +}) + +minetest.register_chatcommand("/flip", { + params = "x/y/z/?", + description = "Flip the current WorldEdit region along the x/y/z/? axis", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + if param == "?" then + param = worldedit.player_axis(name) + end + if param ~= "x" and param ~= "y" and param ~= "z" then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + local count = worldedit.flip(pos1, pos2, param) + worldedit.player_notify(name, count .. " nodes flipped") + end, +}) + +minetest.register_chatcommand("/rotate", { + params = " ", + description = "Rotate the current WorldEdit region around the axis by angle (90 degree increment)", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + if axis == "?" then + axis = worldedit.player_axis(name) + end + if angle % 90 ~= 0 then + worldedit.player_notify(name, "invalid usage: angle must be multiple of 90") + return + end + + local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle) + + --reset markers to rotated positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes rotated") + end, +}) + +minetest.register_chatcommand("/orient", { + params = "", + description = "Rotate oriented nodes in the current WorldEdit region around the Y axis by angle (90 degree increment)", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, angle = param:find("^([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + if angle % 90 ~= 0 then + worldedit.player_notify(name, "invalid usage: angle must be multiple of 90") + return + end + + local count = worldedit.orient(pos1, pos2, angle) + + worldedit.player_notify(name, count .. " nodes oriented") + end, +}) + +minetest.register_chatcommand("/fixlight", { + params = "", + description = "Fix the lighting in the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local count = worldedit.fixlight(pos1, pos2) + worldedit.player_notify(name, count .. " nodes updated") + end, +}) + +minetest.register_chatcommand("/hide", { + params = "", + description = "Hide all nodes in the current WorldEdit region non-destructively", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local count = worldedit.hide(pos1, pos2) + worldedit.player_notify(name, count .. " nodes hidden") + end, +}) + +minetest.register_chatcommand("/suppress", { + params = "", + description = "Suppress all in the current WorldEdit region non-destructively", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) + return + end + + local count = worldedit.suppress(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes suppressed") + end, +}) + +minetest.register_chatcommand("/highlight", { + params = "", + description = "Highlight in the current WorldEdit region by hiding everything else non-destructively", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) + return + end + + local count = worldedit.highlight(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes highlighted") + end, +}) + +minetest.register_chatcommand("/restore", { + params = "", + description = "Restores nodes hidden with WorldEdit in the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local count = worldedit.restore(pos1, pos2) + worldedit.player_notify(name, count .. " nodes restored") + end, +}) + +minetest.register_chatcommand("/save", { + params = "", + description = "Save the current WorldEdit region to \"(world folder)/schems/.we\"", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + if param == "" then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + local result, count = worldedit.serialize(pos1, pos2) + + local path = minetest.get_worldpath() .. "/schems" + local filename = path .. "/" .. param .. ".we" + os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist + local file, err = io.open(filename, "wb") + if err ~= nil then + worldedit.player_notify(name, "could not save file to \"" .. filename .. "\"") + return + end + file:write(result) + file:flush() + file:close() + + worldedit.player_notify(name, count .. " nodes saved") + end, +}) + +minetest.register_chatcommand("/allocate", { + params = "", + description = "Set the region defined by nodes from \"(world folder)/schems/.we\" as the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1 = worldedit.pos1[name] + if pos1 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + if param == "" then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we" + local file, err = io.open(filename, "rb") + if err ~= nil then + worldedit.player_notify(name, "could not open file \"" .. filename .. "\"") + return + end + local value = file:read("*a") + file:close() + + if worldedit.valueversion(value) == 0 then --unknown version + worldedit.player_notify(name, "invalid file: file is invalid or created with newer version of WorldEdit") + return + end + local nodepos1, nodepos2, count = worldedit.allocate(pos1, value) + + worldedit.pos1[name] = nodepos1 + worldedit.mark_pos1(name) + worldedit.pos2[name] = nodepos2 + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes allocated") + end, +}) + +minetest.register_chatcommand("/load", { + params = "", + description = "Load nodes from \"(world folder)/schems/[.we[m]]\" with position 1 of the current WorldEdit region as the origin", + privs = {worldedit=true}, + func = function(name, param) + local pos1 = worldedit.pos1[name] + if pos1 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + if param == "" then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + --find the file in the world path + local testpaths = { + minetest.get_worldpath() .. "/schems/" .. param, + minetest.get_worldpath() .. "/schems/" .. param .. ".we", + minetest.get_worldpath() .. "/schems/" .. param .. ".wem", + } + local file, err + for index, path in ipairs(testpaths) do + file, err = io.open(path, "rb") + if not err then + break + end + end + if err then + worldedit.player_notify(name, "could not open file \"" .. param .. "\"") + return + end + local value = file:read("*a") + file:close() + + if worldedit.valueversion(value) == 0 then --unknown version + worldedit.player_notify(name, "invalid file: file is invalid or created with newer version of WorldEdit") + return + end + + local count = worldedit.deserialize(pos1, value) + + worldedit.player_notify(name, count .. " nodes loaded") + end, +}) + +minetest.register_chatcommand("/lua", { + params = "", + description = "Executes as a Lua chunk in the global namespace", + privs = {worldedit=true, server=true}, + func = function(name, param) + local err = worldedit.lua(param) + if err then + worldedit.player_notify(name, "code error: " .. err) + else + worldedit.player_notify(name, "code successfully executed", false) + end + end, +}) + +minetest.register_chatcommand("/luatransform", { + params = "", + description = "Executes as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region", + privs = {worldedit=true, server=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local err = worldedit.luatransform(pos1, pos2, param) + if err then + worldedit.player_notify(name, "code error: " .. err, false) + else + worldedit.player_notify(name, "code successfully executed", false) + end + end, +}) + +if minetest.place_schematic then +minetest.register_chatcommand("/mtschemcreate", { + params = "", + description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/.mts\"", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "No region selected") + return + end + if param == nil then + worldedit.player_notify(name, "No filename specified") + return + end + + local path = minetest.get_worldpath() .. "/schems" + local filename = path .. "/" .. param .. ".mts" + os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist + + local ret = minetest.create_schematic(pos1, pos2, worldedit.prob_list[name], filename) + if ret == nil then + worldedit.player_notify(name, "Failed to create Minetest schematic", false) + else + worldedit.player_notify(name, "Saved Minetest schematic to " .. param, false) + end + worldedit.prob_list[name] = {} + end, +}) + +minetest.register_chatcommand("/mtschemplace", { + params = "", + description = "Load nodes from \"(world folder)/schems/.mts\" with position 1 of the current WorldEdit region as the origin", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "No position selected") + return + end + if param == nil then + worldedit.player_notify(name, "No filename specified") + return + end + + local path = minetest.get_worldpath() .. "/schems/" .. param .. ".mts" + if minetest.place_schematic(pos, path) == nil then + worldedit.player_notify(name, "Failed to place Minetest schematic", false) + else + worldedit.player_notify(name, "Placed Minetest schematic " .. param .. + " at " .. minetest.pos_to_string(pos), false) + end + end, +}) + +minetest.register_chatcommand("/mtschemprob", { + params = "start/finish/get", + description = "Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry", + privs = {worldedit=true}, + func = function(name, param) + if param == "start" then --start probability setting + worldedit.set_pos[name] = "prob" + worldedit.prob_list[name] = {} + worldedit.player_notify(name, "select Minetest schematic probability values by punching nodes") + elseif param == "finish" then --finish probability setting + worldedit.set_pos[name] = nil + worldedit.player_notify(name, "finished Minetest schematic probability selection") + elseif param == "get" then --get all nodes that had probabilities set on them + local text = "" + local problist = worldedit.prob_list[name] + if problist == nil then + return + end + for k,v in pairs(problist) do + local prob = math.floor(((v["prob"] / 256) * 100) * 100 + 0.5) / 100 + text = text .. minetest.pos_to_string(v["pos"]) .. ": " .. prob .. "% | " + end + worldedit.player_notify(name, "Currently set node probabilities:") + worldedit.player_notify(name, text) + else + worldedit.player_notify(name, "unknown subcommand: " .. param) + end + end, +}) + +minetest.register_on_player_receive_fields( + function(player, formname, fields) + if (formname == "prob_val_enter") and (fields.text ~= "") then + local name = player:get_player_name() + local prob_entry = {pos=worldedit.prob_pos[name], prob=tonumber(fields.text)} + local index = table.getn(worldedit.prob_list[name]) + 1 + worldedit.prob_list[name][index] = prob_entry + end + end +) +end + +minetest.register_chatcommand("/clearobjects", { + params = "", + description = "Clears all objects within the WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local count = worldedit.clearobjects(pos1, pos2) + worldedit.player_notify(name, count .. " objects cleared") + end, +}) diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/mark.lua b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/mark.lua new file mode 100644 index 0000000..461518e --- /dev/null +++ b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/mark.lua @@ -0,0 +1,125 @@ +worldedit.marker1 = {} +worldedit.marker2 = {} +worldedit.marker = {} + +--wip: use this as a huge entity to make a full worldedit region box +minetest.register_entity(":worldedit:region_cube", { + initial_properties = { + visual = "upright_sprite", + visual_size = {x=1.1, y=1.1}, + textures = {"worldedit_pos1.png"}, + visual_size = {x=10, y=10}, + physical = false, + }, + on_step = function(self, dtime) + if self.active == nil then + self.object:remove() + end + end, + on_punch = function(self, hitter) + --wip: remove the entire region marker + end, +}) + +--marks worldedit region position 1 +worldedit.mark_pos1 = function(name) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + + if pos1 ~= nil then + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos1) + end + if worldedit.marker1[name] ~= nil then --marker already exists + worldedit.marker1[name]:remove() --remove marker + worldedit.marker1[name] = nil + end + if pos1 ~= nil then + --add marker + worldedit.marker1[name] = minetest.add_entity(pos1, "worldedit:pos1") + worldedit.marker1[name]:get_luaentity().active = true + if pos2 ~= nil then --region defined + worldedit.mark_region(pos1, pos2) + end + end +end + +--marks worldedit region position 2 +worldedit.mark_pos2 = function(name) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + + if pos2 ~= nil then + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos2, pos2) + end + if worldedit.marker2[name] ~= nil then --marker already exists + worldedit.marker2[name]:remove() --remove marker + worldedit.marker2[name] = nil + end + if pos2 ~= nil then + --add marker + worldedit.marker2[name] = minetest.add_entity(pos2, "worldedit:pos2") + worldedit.marker2[name]:get_luaentity().active = true + if pos1 ~= nil then --region defined + worldedit.mark_region(pos1, pos2) + end + end +end + +worldedit.mark_region = function(pos1, pos2) + --make area stay loaded + local manip = minetest.get_voxel_manip() + manip:read_from_map(pos1, pos2) + + if worldedit.marker[name] ~= nil then --marker already exists + --wip: remove markers + end + if pos1 ~= nil and pos2 ~= nil then + --wip: place markers + end +end + +minetest.register_entity(":worldedit:pos1", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"worldedit_pos1.png", "worldedit_pos1.png", + "worldedit_pos1.png", "worldedit_pos1.png", + "worldedit_pos1.png", "worldedit_pos1.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + physical = false, + }, + on_step = function(self, dtime) + if self.active == nil then + self.object:remove() + end + end, + on_punch = function(self, hitter) + self.object:remove() + local name = hitter:get_player_name() + worldedit.marker1[name] = nil + end, +}) + +minetest.register_entity(":worldedit:pos2", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"worldedit_pos2.png", "worldedit_pos2.png", + "worldedit_pos2.png", "worldedit_pos2.png", + "worldedit_pos2.png", "worldedit_pos2.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + physical = false, + }, + on_step = function(self, dtime) + if self.active == nil then + self.object:remove() + end + end, + on_punch = function(self, hitter) + self.object:remove() + local name = hitter:get_player_name() + worldedit.marker2[name] = nil + end, +}) \ No newline at end of file diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos1.png b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos1.png new file mode 100644 index 0000000..4c304aa Binary files /dev/null and b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos1.png differ diff --git a/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos2.png b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos2.png new file mode 100644 index 0000000..1502f16 Binary files /dev/null and b/kingdoms_game/mods/Minetest-WorldEdit-1.0/worldedit_commands/textures/worldedit_pos2.png differ diff --git a/kingdoms_game/mods/ambience/14init.lua b/kingdoms_game/mods/ambience/14init.lua new file mode 100644 index 0000000..1f4acd6 --- /dev/null +++ b/kingdoms_game/mods/ambience/14init.lua @@ -0,0 +1,390 @@ +-------------------------------------------------------------------------------------------------------- +--Ambiance Configuration for version .14 + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 100 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 1000 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local music_frequency = 7 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 +--End of Config +---------------------------------------------------------------------------------------------------- +local played_on_start = false +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=3, gain=night_volume}, + {name="Wolves_Howling", length=11, gain=night_volume}, + {name="ComboWind", length=17, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=69, gain=night_frequent_volume} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=17, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=16, gain=day_frequent_volume}, + {name="birdsongnl", length=13, gain=day_frequent_volume}, + {name="bird", length=30, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=17, gain=day_frequent_volume*3} +} + + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + on_start = "Splash", + {name="scuba1bubbles", length=11, gain=water_frequent_volume}, + {name="scuba1calm", length=10}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=14, gain=.4} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=11, gain=.3} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15} +} + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + {name="mtest", length=4*60+33, gain=music_volume}, + {name="echos", length=2*60+26, gain=music_volume}, + {name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + {name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +--[[old +local nodes_in_range = function(pos, search_distance, node_name) + local search_p = {x=0, y=0, z=0} + local nodes_found = 0 + for p_x=(pos.x-search_distance), (pos.x+search_distance) do + for p_y=(pos.y-search_distance), (pos.y+search_distance) do + for p_z=(pos.z-search_distance), (pos.z+search_distance) do + local search_n = minetest.env:get_node({x=p_x, y=p_y, z=p_z}) + if search_n.name == node_name then + nodes_found = nodes_found + 1 + end + end + end + end + return nodes_found + --minetest.chat_send_all("Range: " .. tostring(search_distance) .. " | Found (" .. node_name .. ": " .. nodes_found .. ")") +end --]] + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + + +local get_ambience = function(player) + local pos = player:getpos() + pos.y = pos.y+1.0 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + end + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 7, "default:water_flowing")>5 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, music=music} + else + return {night=night, night_frequent=night_frequent} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + end + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/Badinit.lua b/kingdoms_game/mods/ambience/Badinit.lua new file mode 100644 index 0000000..ba85193 --- /dev/null +++ b/kingdoms_game/mods/ambience/Badinit.lua @@ -0,0 +1,439 @@ +-------------------------------------------------------------------------------------------------------- +--Ambiance Configuration for version .16 + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 100 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 1000 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local beach_frequency = 20 --seagulls +local beach_volume = 1.0 +local beach_frequent_frequency = 1000 --waves +local beach_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local music_frequency = 7 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 +--End of Config +---------------------------------------------------------------------------------------------------- +local played_on_start = false +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=3, gain=night_volume}, + {name="Wolves_Howling", length=11, gain=night_volume}, + {name="ComboWind", length=17, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=69, gain=night_frequent_volume} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=17, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=16, gain=day_frequent_volume}, + {name="birdsongnl", length=13, gain=day_frequent_volume}, + {name="bird", length=30, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=17, gain=day_frequent_volume*3} +} + + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local beach = { + handler = {}, + frequency = beach_frequency, + {name="seagull", length=4.5, gain=beach_volume} +} + +local beach_frequent = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=43.5, gain=beach_frequent_volume} +} + + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + on_start = "Splash", + {name="scuba1bubbles", length=11, gain=water_frequent_volume}, + {name="scuba1calm", length=10}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=14, gain=.4} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=11, gain=.3} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15} +} + + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + {name="mtest", length=4*60+33, gain=music_volume}, + {name="echos", length=2*60+26, gain=music_volume}, + {name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + {name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +--[[old +local nodes_in_range = function(pos, search_distance, node_name) + local search_p = {x=0, y=0, z=0} + local nodes_found = 0 + for p_x=(pos.x-search_distance), (pos.x+search_distance) do + for p_y=(pos.y-search_distance), (pos.y+search_distance) do + for p_z=(pos.z-search_distance), (pos.z+search_distance) do + local search_n = minetest.env:get_node({x=p_x, y=p_y, z=p_z}) + if search_n.name == node_name then + nodes_found = nodes_found + 1 + end + end + end + end + return nodes_found + --minetest.chat_send_all("Range: " .. tostring(search_distance) .. " | Found (" .. node_name .. ": " .. nodes_found .. ")") +end --]] + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + + +local get_ambience = function(player) + local pos = player:getpos() + pos.y = pos.y+1.0 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + end + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 7, "default:water_flowing")>5 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + pos.y = pos.y-2 + nodename = minetest.env:get_node(pos).name + --minetest.chat_send_all("Found " .. nodename .. pos.y ) + if string.find(nodename, "default:sand") and pos.y < 5 then + if music then + return {beach=beach, beach_frequent=beach_frequent, music=music} + else + return {beach=beach, beach_frequent=beach_frequent} + end + end + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, music=music} + else + return {night=night, night_frequent=night_frequent} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach == nil then + local list = beach + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent == nil then + local list = beach_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + end + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/depends.txt b/kingdoms_game/mods/ambience/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/kingdoms_game/mods/ambience/depends.txt @@ -0,0 +1 @@ +default diff --git a/kingdoms_game/mods/ambience/init.lua b/kingdoms_game/mods/ambience/init.lua new file mode 100644 index 0000000..44bf039 --- /dev/null +++ b/kingdoms_game/mods/ambience/init.lua @@ -0,0 +1,832 @@ +-------------------------------------------------------------------------------------------------------- +--Ambience Configuration for version .34 +--Added Faraway & Ethereal by Amethystium + +--Working on: +--removing magic leap when not enough air under feet. + + +--find out why wind stops while flying +--add an extra node near feet to handle treading water as a special case, and don't have to use node under feet. which gets + --invoked when staning on a ledge near water. +--reduce redundant code (stopplay and add ambience to list) + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 80 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 250 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local beach_frequency = 20 --seagulls +local beach_volume = 1.0 +local beach_frequent_frequency = 1000 --waves +local beach_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local desert_frequency = 20 --coyote +local desert_volume = 1.0 +local desert_frequent_frequency = 700 --desertwind +local desert_frequent_volume = 1.0 +local swimming_frequent_frequency = 1000 --swimming splashes +local swimming_frequent_volume = 1.0 +local water_surface_volume = 1.0 -- sloshing water +local lava_volume = 1.0 --lava +local flowing_water_volume = .4 --waterfall +local splashing_water_volume = 1 +local music_frequency = 7 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 + +--End of Config +---------------------------------------------------------------------------------------------------- +local ambiences +local counter=0--***************** +local SOUNDVOLUME = 1 +local MUSICVOLUME = 1 +local sound_vol = 1 +local last_x_pos = 0 +local last_y_pos = 0 +local last_z_pos = 0 +local node_under_feet +local node_at_upper_body +local node_at_lower_body +local node_3_under_feet +local played_on_start = false + + + + +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=2.8, gain=night_volume}, + {name="Wolves_Howling", length=4.4, gain=night_volume}, + {name="ComboWind", length=9.7, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=8.25, gain=night_frequent_volume}, + {name="Crickets_At_NightCombo", length=5.25, gain=night_frequent_volume*.6} +} + +local night_frequent2 = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=8.25, gain=night_frequent_volume*.4} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=9.7, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=7.8, gain=day_frequent_volume}, + {name="birdsongnl", length=7.1, gain=day_frequent_volume}, + {name="bird", length=13.1, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=9.7, gain=day_frequent_volume*3} +} +local swimming_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="water_swimming_splashing_breath", length=11.5, gain=swimming_frequent_volume}, + {name="water_swimming_splashing", length=9, gain=swimming_frequent_volume} +} + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local beach = { + handler = {}, + frequency = beach_frequency, + {name="seagull", length=4.5, gain=beach_volume} +} + +local beach_frequent = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=13.4, gain=beach_frequent_volume}, + {name="fiji_beach", length=13.1, gain=beach_frequent_volume*.5} +} + +local beach_frequent2 = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=11, gain=beach_frequent_volume*.3} +} + +local desert = { + handler = {}, + frequency = desert_frequency, + {name="coyote2", length=2.1, gain=desert_volume}, + {name="RattleSnake", length=8, gain=desert_volume} +} + +local desert_frequent = { + handler = {}, + frequency = desert_frequent_frequency, + {name="DesertMonolithMed", length=15.1, gain=desert_frequent_volume}, + {name="ComboWind", length=9.7, gain=desert_frequent_volume}, + {name="ComboWind", length=8.7, gain=desert_frequent_volume*.5}, + {name="DesertMonolithMed", length=14.1, gain=desert_frequent_volume*.5}, +} + +local flying = { + handler = {}, + frequency = 1000, + on_start = "nothing_yet", + on_stop = "nothing_yet", + {name="ComboWind", length=9.7, gain=1} +} + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6, gain=1}, + {name="dolphins_screaming", length=16.5, gain=1} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + --on_start = "Splash", + {name="scuba1bubbles", length=5.4, gain=water_frequent_volume}, + {name="scuba1calm", length=10, gain=water_frequent_volume}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local water_surface = { + handler = {}, + frequency = 1000, + on_stop = "Splash", + on_start = "Splash", + {name="lake_waves_2_calm", length=5.4, gain=water_surface_volume}, + {name="lake_waves_2_variety", length=6.6, gain=water_surface_volume} +} +local splashing_water = { + handler = {}, + frequency = 1000, + {name="Splash", length=1.22, gain=splashing_water_volume} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=5.9, gain=flowing_water_volume} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=4, gain=flowing_water_volume} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20, gain=lava_volume} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15, gain=lava_volume} +} + + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + is_music=true, + {name="StrangelyBeautifulShort", length=3*60+.5, gain=music_volume*.7}, + {name="AvalonShort", length=2*60+58, gain=music_volume*1.4}, + --{name="mtest", length=4*60+33, gain=music_volume}, + --{name="echos", length=2*60+26, gain=music_volume}, + --{name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + --{name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="EtherealShort", length=3*60+4, gain=music_volume*.7}, + {name="FarawayShort", length=3*60+5, gain=music_volume*.7}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) + --minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + +local nodes_in_coords = function(minp, maxp, node_name) + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) + --minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + +local atleast_nodes_in_grid = function(pos, search_distance, height, node_name, threshold) + counter = counter +1 +-- minetest.chat_send_all("counter: (" .. counter .. ")") + minp = {x=pos.x-search_distance,y=height, z=pos.z+20} + maxp = {x=pos.x+search_distance,y=height, z=pos.z+20} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("z+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = #nodes + minp = {x=pos.x-search_distance,y=height, z=pos.z-20} + maxp = {x=pos.x+search_distance,y=height, z=pos.z-20} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("z-Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes + maxp = {x=pos.x+20,y=height, z=pos.z+search_distance} + minp = {x=pos.x+20,y=height, z=pos.z-search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("x+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes + maxp = {x=pos.x-20,y=height, z=pos.z+search_distance} + minp = {x=pos.x-20,y=height, z=pos.z-search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("x+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes +-- minetest.chat_send_all("Found total(" .. totalnodes .. ")") + if totalnodes >= threshold*2 then + return true + end + return false +end + +local get_immediate_nodes = function(pos) + pos.y = pos.y-1 + node_under_feet = minetest.env:get_node(pos).name + pos.y = pos.y-3 + node_3_under_feet = minetest.env:get_node(pos).name + pos.y = pos.y+3 + pos.y = pos.y+2.2 + node_at_upper_body = minetest.env:get_node(pos).name + pos.y = pos.y-1.19 + node_at_lower_body = minetest.env:get_node(pos).name + pos.y = pos.y+0.99 + --minetest.chat_send_all("node_under_feet(" .. nodename .. ")") +end + + +local get_ambience = function(player) + local player_is_climbing = false + local player_is_descending = false + local player_is_moving_horiz = false + local standing_in_water = false + local pos = player:getpos() + get_immediate_nodes(pos) + + if last_x_pos ~=pos.x or last_z_pos ~=pos.z then + player_is_moving_horiz = true + end + if pos.y > last_y_pos+.5 then + player_is_climbing = true + end + if pos.y < last_y_pos-.5 then + player_is_descending = true + end + + last_x_pos =pos.x + last_z_pos =pos.z + last_y_pos =pos.y + + if string.find(node_at_upper_body, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + elseif node_at_upper_body == "air" then + if string.find(node_at_lower_body, "default:water") or string.find(node_under_feet, "default:water") then + --minetest.chat_send_all("bottom counted as water") + --we found air at upperbody, and water at lower body. Now there are 4 possibilities: + --Key: under feet, moving or not + --swimming w, m swimming + --walking in water nw, m splashing + --treading water w, nm sloshing + --standing in water nw, nm beach trumps, then sloshing + if player_is_moving_horiz then + if string.find(node_under_feet, "default:water") then + if music then + return {swimming_frequent=swimming_frequent, music=music} + else + return {swimming_frequent} + end + else --didn't find water under feet: walking in water + if music then + return {splashing_water=splashing_water, music=music} + else + return {splashing_water} + end + end + else--player is not moving: treading water + if string.find(node_under_feet, "default:water") then + if music then + return {water_surface=water_surface, music=music} + else + return {water_surface} + end + else --didn't find water under feet + standing_in_water = true + end + end + end + end +-- minetest.chat_send_all("----------") +-- if not player_is_moving_horiz then +-- minetest.chat_send_all("not moving horiz") +-- else +-- minetest.chat_send_all("moving horiz") +-- end +-- minetest.chat_send_all("nub:" ..node_at_upper_body) +-- minetest.chat_send_all("nlb:" ..node_at_lower_body) +-- minetest.chat_send_all("nuf:" ..node_under_feet) +-- minetest.chat_send_all("----------") + + +-- if player_is_moving_horiz then +-- minetest.chat_send_all("playermoving") +-- end +-- if player_is_climbing then +-- minetest.chat_send_all("player Climbing") +-- end +-- minetest.chat_send_all("nub:" ..node_at_upper_body) +-- minetest.chat_send_all("nlb:" ..node_at_lower_body) +-- minetest.chat_send_all("nuf:" ..node_under_feet) +-- minetest.chat_send_all("n3uf:" ..node_3_under_feet) +-- + local air_or_ignore = {air=true,ignore=true} + minp = {x=pos.x-3,y=pos.y-4, z=pos.z-3} + maxp = {x=pos.x+3,y=pos.y-1, z=pos.z+3} + local air_under_player = nodes_in_coords(minp, maxp, "air") + local ignore_under_player = nodes_in_coords(minp, maxp, "ignore") + air_plus_ignore_under = air_under_player + ignore_under_player +-- minetest.chat_send_all("airUnder:" ..air_under_player) +-- minetest.chat_send_all("ignoreUnder:" ..ignore_under_player) +-- minetest.chat_send_all("a+i:" ..air_plus_ignore_under) +-- minetest.chat_send_all("counter: (" .. counter .. "-----------------)") + --minetest.chat_send_all(air_or_ignore[node_under_feet]) +-- if (player_is_moving_horiz or player_is_climbing) and air_or_ignore[node_at_upper_body] and air_or_ignore[node_at_lower_body] +-- and air_or_ignore[node_under_feet] and air_plus_ignore_under == 196 and not player_is_descending then + --minetest.chat_send_all("flying!!!!") + -- if music then + -- return {flying=flying, music=music} + -- else + --- return {flying} +-- end +-- end + --minetest.chat_send_all("not flying!!!!") + + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 6, "default:water_flowing")>45 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + + +--if we are near sea level and there is lots of water around the area + if pos.y < 7 and pos.y >0 and atleast_nodes_in_grid(pos, 60, 1, "default:water_source", 51 ) then + if music then + return {beach=beach, beach_frequent=beach_frequent, beach_frequent2=beach_frequent2, music=music} + else + return {beach=beach, beach_frequent=beach_frequent, beach_frequent2=beach_frequent2} + end + end + if standing_in_water then + if music then + return {water_surface=water_surface, music=music} + else + return {water_surface} + end + end + + + desert_in_range = (nodes_in_range(pos, 6, "default:desert_sand")+nodes_in_range(pos, 6, "default:desert_stone")) + --minetest.chat_send_all("desertcount: " .. desert_in_range .. ",".. pos.y ) + if desert_in_range >250 then + if music then + return {desert=desert, desert_frequent=desert_frequent, music=music} + else + return {desert=desert, desert_frequent=desert_frequent} + end + end + +-- pos.y = pos.y-2 +-- nodename = minetest.env:get_node(pos).name +-- minetest.chat_send_all("Found " .. nodename .. pos.y ) + + + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, night_frequent2=night_frequent2, music=music} + else + return {night=night, night_frequent=night_frequent, night_frequent2=night_frequent2,} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number, is_music) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + if is_music then + gain = list[number].gain*MUSICVOLUME + --minetest.chat_send_all("gain music: " .. gain ) + else + gain = list[number].gain*SOUNDVOLUME + --minetest.chat_send_all("gain sound: " .. gain ) + end + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.swimming_frequent == nil then + local list = swimming_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach == nil then + local list = beach + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent == nil then + local list = beach_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent2 == nil then + local list = beach_frequent2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.desert == nil then + local list = desert + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.desert_frequent == nil then + local list = desert_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent2 == nil then + local list = night_frequent2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_surface == nil then + local list = water_surface + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + -- minetest.chat_send_all("list.on_stop " .. list.on_stop ) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flying == nil then + --minetest.chat_send_all("begin stop flying " ) + local list = flying + if list.handler[player_name] ~= nil then + -- minetest.chat_send_all("handler flying " ) + if list.on_stop ~= nil then + -- minetest.chat_send_all("onstop flying" ) + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.splashing_water == nil then + local list = splashing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then +-- if(played_on_start) then +-- -- minetest.chat_send_all("playedOnStart " ) +-- else +-- -- minetest.chat_send_all("FALSEplayedOnStart " ) +-- end + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name(),gain=SOUNDVOLUME}) + end + -- minetest.chat_send_all("ambience: " ..ambience ) + -- if ambience.on_start ~= nil and played_on_start_flying == false then + -- played_on_start_flying = true + -- minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + -- end + local is_music =false + if ambience.is_music ~= nil then + is_music = true + end + play_sound(player, ambience, math.random(1, #ambience),is_music) + end + end + end +end) + +minetest.register_chatcommand("svol", { + params = "", + description = "set volume of sounds, default 1 normal volume.", + privs = {server=true}, + func = function(name, param) + SOUNDVOLUME = param + -- local player = minetest.env:get_player_by_name(name) + -- ambiences = get_ambience(player) + -- stop_sound({}, player) + minetest.chat_send_player(name, "Sound volume set.") + end, }) +minetest.register_chatcommand("mvol", { + params = "", + description = "set volume of music, default 1 normal volume.", + privs = {server=true}, + func = function(name, param) + MUSICVOLUME = param + -- local player = minetest.env:get_player_by_name(name) + -- stop_sound({}, player) + -- ambiences = get_ambience(player) + minetest.chat_send_player(name, "Music volume set.") + end, }) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/init.lua.pilz.lua b/kingdoms_game/mods/ambience/init.lua.pilz.lua new file mode 100644 index 0000000..b1d1796 --- /dev/null +++ b/kingdoms_game/mods/ambience/init.lua.pilz.lua @@ -0,0 +1,287 @@ +local night = { + handler = {}, + frequency = 10, + {name="horned_owl", length=3}, + {name="Wolves_Howling", length=11}, + {name="ComboWind", length=17}, +} + +local night_frequent = { + handler = {}, + frequency = 25, + {name="Crickets_At_NightCombo", length=69}, +} + +local day = { + handler = {}, + frequency = 5, + {name="Best Cardinal Bird", length=4}, + {name="craw", length=3}, + {name="bluejay", length=18}, + {name="ComboWind", length=17}, +} + +local day_frequent = { + handler = {}, + frequency = 25, + {name="robin2", length=16}, + {name="birdsongnl", length=12.5}, + {name="bird", length=30}, +} + +local cave = { + handler = {}, + frequency = 5, + {name="Bats_in_Cave", length=5}, +} + +local cave_frequent = { + handler = {}, + frequency = 100, + {name="drippingwater_drip_a", length=2}, + {name="drippingwater_drip_b", length=2}, + {name="drippingwater_drip_c", length=2}, + {name="Single_Water_Droplet", length=3}, + {name="Spooky_Water_Drops", length=7}, +} + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5}, +} + +local water_frequent = { + handler = {}, + frequency = 100, + on_stop = "drowning_gasp", + {name="scuba1bubbles", length=11}, + {name="scuba1calm", length=10}, + {name="scuba1calm2", length=8.5}, + {name="scuba1interestingbubbles", length=11}, + {name="scuba1tubulentbubbles", length=10.5}, +} + +local splash = { + handler = {}, + frequency = 100, + {name="Splash", length=1.5}, +} + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = 1, + {name="mtest", length=4*60+33, gain=0.3}, + {name="music_1", length=1*60+52, gain=0.3}, + {name="ambiance", length=19, gain=0.3}, + {name="dark_ambiance", length=46, gain=0.3}, + {name="eastern_feeling", length=3*60+51, gain=0.3}, + {name="echos", length=2*60+26, gain=0.3}, + {name="FoamOfTheSea", length=1*60+50, gain=0.3}, +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +local get_ambience = function(player) + local table = {} + + local play_water = false + local play_splash = false + local play_day = false + local play_cave = false + local play_night = false + + local pos = player:getpos() + pos.y = pos.y+1.5 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + play_water = true + elseif nodename == "air" then + pos.y = pos.y-1.5 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + play_splash = true + end + end + if player:getpos().y < 0 then + play_cave = true + elseif is_daytime() then + play_day = true + else + play_night = true + end + + if play_music then + table.music = music + end + if play_water then + table.water = water + table.water_frequent = water_frequent + return table + end + if play_splash then + table.splash = splash + end + if play_day then + table.day = day + table.day_frequent = day_frequent + elseif play_night then + table.night = night + table.night_frequent = night_frequent + elseif play_cave then + table.cave = cave + table.cave_frequent = cave_frequent + end + return table +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.splash == nil then + local list = splash + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 100) <= ambience.frequency then + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/init16.lua b/kingdoms_game/mods/ambience/init16.lua new file mode 100644 index 0000000..ba85193 --- /dev/null +++ b/kingdoms_game/mods/ambience/init16.lua @@ -0,0 +1,439 @@ +-------------------------------------------------------------------------------------------------------- +--Ambiance Configuration for version .16 + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 100 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 1000 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local beach_frequency = 20 --seagulls +local beach_volume = 1.0 +local beach_frequent_frequency = 1000 --waves +local beach_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local music_frequency = 7 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 +--End of Config +---------------------------------------------------------------------------------------------------- +local played_on_start = false +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=3, gain=night_volume}, + {name="Wolves_Howling", length=11, gain=night_volume}, + {name="ComboWind", length=17, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=69, gain=night_frequent_volume} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=17, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=16, gain=day_frequent_volume}, + {name="birdsongnl", length=13, gain=day_frequent_volume}, + {name="bird", length=30, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=17, gain=day_frequent_volume*3} +} + + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local beach = { + handler = {}, + frequency = beach_frequency, + {name="seagull", length=4.5, gain=beach_volume} +} + +local beach_frequent = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=43.5, gain=beach_frequent_volume} +} + + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + on_start = "Splash", + {name="scuba1bubbles", length=11, gain=water_frequent_volume}, + {name="scuba1calm", length=10}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=14, gain=.4} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=11, gain=.3} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15} +} + + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + {name="mtest", length=4*60+33, gain=music_volume}, + {name="echos", length=2*60+26, gain=music_volume}, + {name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + {name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +--[[old +local nodes_in_range = function(pos, search_distance, node_name) + local search_p = {x=0, y=0, z=0} + local nodes_found = 0 + for p_x=(pos.x-search_distance), (pos.x+search_distance) do + for p_y=(pos.y-search_distance), (pos.y+search_distance) do + for p_z=(pos.z-search_distance), (pos.z+search_distance) do + local search_n = minetest.env:get_node({x=p_x, y=p_y, z=p_z}) + if search_n.name == node_name then + nodes_found = nodes_found + 1 + end + end + end + end + return nodes_found + --minetest.chat_send_all("Range: " .. tostring(search_distance) .. " | Found (" .. node_name .. ": " .. nodes_found .. ")") +end --]] + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + + +local get_ambience = function(player) + local pos = player:getpos() + pos.y = pos.y+1.0 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + end + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 7, "default:water_flowing")>5 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + pos.y = pos.y-2 + nodename = minetest.env:get_node(pos).name + --minetest.chat_send_all("Found " .. nodename .. pos.y ) + if string.find(nodename, "default:sand") and pos.y < 5 then + if music then + return {beach=beach, beach_frequent=beach_frequent, music=music} + else + return {beach=beach, beach_frequent=beach_frequent} + end + end + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, music=music} + else + return {night=night, night_frequent=night_frequent} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach == nil then + local list = beach + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent == nil then + local list = beach_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + end + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/init17.lua b/kingdoms_game/mods/ambience/init17.lua new file mode 100644 index 0000000..610bb3b --- /dev/null +++ b/kingdoms_game/mods/ambience/init17.lua @@ -0,0 +1,474 @@ +-------------------------------------------------------------------------------------------------------- +--Ambiance Configuration for version .17 + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 100 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 1000 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local beach_frequency = 20 --seagulls +local beach_volume = 1.0 +local beach_frequent_frequency = 1000 --waves +local beach_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local music_frequency = 0 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 +--End of Config +---------------------------------------------------------------------------------------------------- +local played_on_start = false +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=3, gain=night_volume}, + {name="Wolves_Howling", length=11, gain=night_volume}, + {name="ComboWind", length=17, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=69, gain=night_frequent_volume} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=17, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=16, gain=day_frequent_volume}, + {name="birdsongnl", length=13, gain=day_frequent_volume}, + {name="bird", length=30, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=17, gain=day_frequent_volume*3} +} + + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local beach = { + handler = {}, + frequency = beach_frequency, + {name="seagull", length=4.5, gain=beach_volume} +} + +local beach_frequent = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=43.5, gain=beach_frequent_volume} +} + + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + on_start = "Splash", + {name="scuba1bubbles", length=11, gain=water_frequent_volume}, + {name="scuba1calm", length=10}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local water_surface = { + handler = {}, + frequency = 10, + on_start = "Splash", + {name="lake_waves_2_calm", length=9.5}, + {name="lake_waves_2_variety", length=13.1} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=14, gain=.4} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=11, gain=.3} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15} +} + + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + {name="mtest", length=4*60+33, gain=music_volume}, + {name="echos", length=2*60+26, gain=music_volume}, + {name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + {name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +--[[old +local nodes_in_range = function(pos, search_distance, node_name) + local search_p = {x=0, y=0, z=0} + local nodes_found = 0 + for p_x=(pos.x-search_distance), (pos.x+search_distance) do + for p_y=(pos.y-search_distance), (pos.y+search_distance) do + for p_z=(pos.z-search_distance), (pos.z+search_distance) do + local search_n = minetest.env:get_node({x=p_x, y=p_y, z=p_z}) + if search_n.name == node_name then + nodes_found = nodes_found + 1 + end + end + end + end + return nodes_found + --minetest.chat_send_all("Range: " .. tostring(search_distance) .. " | Found (" .. node_name .. ": " .. nodes_found .. ")") +end --]] + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + + +local get_ambience = function(player) + local pos = player:getpos() + pos.y = pos.y+1.0 + local nodename = minetest.env:get_node(pos).name + if string.find(nodename, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + elseif nodename == "air" then + pos.y = pos.y-1.5 + local nodename = minetest.env:get_node(pos).name + pos.y = pos.y+1.5 + if string.find(nodename, "default:water") then + if music then + return {water_surface=water_surface, music=music} + else + return {water_surface} + end + end + end + + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 7, "default:water_flowing")>5 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + pos.y = pos.y-2 + nodename = minetest.env:get_node(pos).name + --minetest.chat_send_all("Found " .. nodename .. pos.y ) + if string.find(nodename, "default:sand") and pos.y < 5 then + if music then + return {beach=beach, beach_frequent=beach_frequent, music=music} + else + return {beach=beach, beach_frequent=beach_frequent} + end + end + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, music=music} + else + return {night=night, night_frequent=night_frequent} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach == nil then + local list = beach + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent == nil then + local list = beach_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_surface == nil then + local list = water_surface + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + minetest.chat_send_all("list.on_stop " .. list.on_stop ) + -- played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + + + +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + end + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/init29debug.lua b/kingdoms_game/mods/ambience/init29debug.lua new file mode 100644 index 0000000..60bf38f --- /dev/null +++ b/kingdoms_game/mods/ambience/init29debug.lua @@ -0,0 +1,722 @@ +-------------------------------------------------------------------------------------------------------- +--Ambiance Configuration for version .29 +--working on Flying +--PROB: wind stops short even though it says we are still flying and don't hear the start sound. +--really BIG prob, it ruins water meaning you hear beach while treading water. (find out if still hear it in .28) because +--it is fairly rare in .29 +--need a separate onstart variable for flying + + +local max_frequency_all = 1000 --the larger you make this number the lest frequent ALL sounds will happen recommended values between 100-2000. + +--for frequencies below use a number between 0 and max_frequency_all +--for volumes below, use a number between 0.0 and 1, the larger the number the louder the sounds +local night_frequency = 20 --owls, wolves +local night_volume = 0.9 +local night_frequent_frequency = 150 --crickets +local night_frequent_volume = 0.9 +local day_frequency = 100 --crow, bluejay, cardinal +local day_volume = 0.9 +local day_frequent_frequency = 1000 --crow, bluejay, cardinal +local day_frequent_volume = 0.18 +local cave_frequency = 10 --bats +local cave_volume = 1.0 +local cave_frequent_frequency = 70 --drops of water dripping +local cave_frequent_volume = 1.0 +local beach_frequency = 20 --seagulls +local beach_volume = 1.0 +local beach_frequent_frequency = 1000 --waves +local beach_frequent_volume = 1.0 +local water_frequent_frequency = 1000 --water sounds +local water_frequent_volume = 1.0 +local desert_frequency = 20 --coyote +local desert_volume = 1.0 +local desert_frequent_frequency = 700 --desertwind +local desert_frequent_volume = 1.0 +local swimming_frequent_frequency = 1000 --swimming splashes +local swimming_frequent_volume = 1.0 +local music_frequency = 0 --music (suggestion: keep this one low like around 6) +local music_volume = 0.3 +--End of Config +---------------------------------------------------------------------------------------------------- +local counter=0--***************** +local last_x_pos = 0 +local last_y_pos = 0 +local last_z_pos = 0 +local node_under_feet +local node_at_upper_body +local node_at_lower_body +local node_3_under_feet + +local played_on_start = false +local played_on_start_flying = false + +local night = { + handler = {}, + frequency = night_frequency, + {name="horned_owl", length=3, gain=night_volume}, + {name="Wolves_Howling", length=11, gain=night_volume}, + {name="ComboWind", length=17, gain=night_volume} +} + +local night_frequent = { + handler = {}, + frequency = night_frequent_frequency, + {name="Crickets_At_NightCombo", length=69, gain=night_frequent_volume} +} + +local day = { + handler = {}, + frequency = day_frequency, + {name="Best Cardinal Bird", length=4, gain=day_volume}, + {name="craw", length=3, gain=day_volume}, + {name="bluejay", length=18, gain=day_volume}, + {name="ComboWind", length=17, gain=day_volume} +} + +local day_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="robin2", length=16, gain=day_frequent_volume}, + {name="birdsongnl", length=13, gain=day_frequent_volume}, + {name="bird", length=30, gain=day_frequent_volume}, + {name="Best Cardinal Bird", length=4, gain=day_frequent_volume}, + {name="craw", length=3, gain=day_frequent_volume}, + {name="bluejay", length=18, gain=day_frequent_volume}, + {name="ComboWind", length=17, gain=day_frequent_volume*3} +} +local swimming_frequent = { + handler = {}, + frequency = day_frequent_frequency, + {name="water_swimming_splashing_breath", length=11.5, gain=swimming_frequent_volume}, + {name="water_swimming_splashing", length=9, gain=swimming_frequent_volume} +} + +local cave = { + handler = {}, + frequency = cave_frequency, + {name="Bats_in_Cave", length=5, gain=cave_volume} +} + +local cave_frequent = { + handler = {}, + frequency = cave_frequent_frequency, + {name="drippingwater_drip_a", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_b", length=2, gain=cave_frequent_volume}, + {name="drippingwater_drip_c", length=2, gain=cave_frequent_volume}, + {name="Single_Water_Droplet", length=3, gain=cave_frequent_volume}, + {name="Spooky_Water_Drops", length=7, gain=cave_frequent_volume} +} + +local beach = { + handler = {}, + frequency = beach_frequency, + {name="seagull", length=4.5, gain=beach_volume} +} + +local beach_frequent = { + handler = {}, + frequency = beach_frequent_frequency, + {name="fiji_beach", length=43.5, gain=beach_frequent_volume} +} + +local desert = { + handler = {}, + frequency = desert_frequency, + {name="coyote2", length=2.5, gain=desert_volume}, + {name="RattleSnake", length=8, gain=desert_volume} +} + +local desert_frequent = { + handler = {}, + frequency = desert_frequent_frequency, + {name="DesertMonolithMed", length=34.5, gain=desert_frequent_volume} +} + +local flying = { + handler = {}, + frequency = 1000, + on_start = "crystal_airlines", + on_stop = "nothing_yet", + {name="ComboWind", length=17, gain=1} +} + +local water = { + handler = {}, + frequency = 0,--dolphins dont fit into small lakes + {name="dolphins", length=6}, + {name="dolphins_screaming", length=16.5} +} + +local water_frequent = { + handler = {}, + frequency = water_frequent_frequency, + on_stop = "drowning_gasp", + --on_start = "Splash", + {name="scuba1bubbles", length=11, gain=water_frequent_volume}, + {name="scuba1calm", length=10}, --not sure why but sometimes I get errors when setting gain=water_frequent_volume here. + {name="scuba1calm2", length=8.5, gain=water_frequent_volume}, + {name="scuba1interestingbubbles", length=11, gain=water_frequent_volume}, + {name="scuba1tubulentbubbles", length=10.5, gain=water_frequent_volume} +} + +local water_surface = { + handler = {}, + frequency = 1000, + on_stop = "Splash", + on_start = "Splash", + {name="lake_waves_2_calm", length=9.5}, + {name="lake_waves_2_variety", length=13.1} +} +local splashing_water = { + handler = {}, + frequency = 1000, + {name="Splash", length=1.22, gain=1} +} + +local flowing_water = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=14, gain=.4} +} +local flowing_water2 = { + handler = {}, + frequency = 1000, + {name="small_waterfall", length=11, gain=.3} +} + +local lava = { + handler = {}, + frequency = 1000, + {name="earth01a", length=20} +} +local lava2 = { + handler = {}, + frequency = 1000, + {name="earth01a", length=15} +} + + +local play_music = minetest.setting_getbool("music") or false +local music = { + handler = {}, + frequency = music_frequency, + {name="mtest", length=4*60+33, gain=music_volume}, + {name="echos", length=2*60+26, gain=music_volume}, + {name="FoamOfTheSea", length=1*60+50, gain=music_volume}, + {name="eastern_feeling", length=3*60+51, gain=music_volume}, + {name="Mass_Effect_Uncharted_Worlds", length=2*60+29, gain=music_volume}, + {name="dark_ambiance", length=44, gain=music_volume} +} + +local is_daytime = function() + return (minetest.env:get_timeofday() > 0.2 and minetest.env:get_timeofday() < 0.8) +end + +local nodes_in_range = function(pos, search_distance, node_name) + minp = {x=pos.x-search_distance,y=pos.y-search_distance, z=pos.z-search_distance} + maxp = {x=pos.x+search_distance,y=pos.y+search_distance, z=pos.z+search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) + --minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + +local nodes_in_coords = function(minp, maxp, node_name) + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) + --minetest.chat_send_all("Found (" .. node_name .. ": " .. #nodes .. ")") + return #nodes +end + +local atleast_nodes_in_grid = function(pos, search_distance, height, node_name, threshold) +-- counter = counter +1 +-- minetest.chat_send_all("counter: (" .. counter .. ")") + minp = {x=pos.x-search_distance,y=height, z=pos.z+20} + maxp = {x=pos.x+search_distance,y=height, z=pos.z+20} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("z+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = #nodes + minp = {x=pos.x-search_distance,y=height, z=pos.z-20} + maxp = {x=pos.x+search_distance,y=height, z=pos.z-20} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("z-Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes + maxp = {x=pos.x+20,y=height, z=pos.z+search_distance} + minp = {x=pos.x+20,y=height, z=pos.z-search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("x+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes + maxp = {x=pos.x-20,y=height, z=pos.z+search_distance} + minp = {x=pos.x-20,y=height, z=pos.z-search_distance} + nodes = minetest.env:find_nodes_in_area(minp, maxp, node_name) +-- minetest.chat_send_all("x+Found (" .. node_name .. ": " .. #nodes .. ")") + if #nodes >= threshold then + return true + end + totalnodes = totalnodes + #nodes +-- minetest.chat_send_all("Found total(" .. totalnodes .. ")") + if totalnodes >= threshold*2 then + return true + end + return false +end + +local get_immediate_nodes = function(pos) + pos.y = pos.y-1 + node_under_feet = minetest.env:get_node(pos).name + pos.y = pos.y-3 + node_3_under_feet = minetest.env:get_node(pos).name + pos.y = pos.y+3 + pos.y = pos.y+2.2 + node_at_upper_body = minetest.env:get_node(pos).name + pos.y = pos.y-1.19 + node_at_lower_body = minetest.env:get_node(pos).name + pos.y = pos.y+0.99 --1.6 + --minetest.chat_send_all("node_under_feet(" .. nodename .. ")") +end + + +local get_ambience = function(player) + local player_is_climbing = false + local player_is_descending = false + local player_is_moving_horiz = false + local standing_in_water = false + local pos = player:getpos() + get_immediate_nodes(pos) + + if last_x_pos ~=pos.x or last_z_pos ~=pos.z then + player_is_moving_horiz = true + end + if pos.y > last_y_pos+.5 then + player_is_climbing = true + end + if pos.y < last_y_pos-.5 then + player_is_descending = true + end + + last_x_pos =pos.x + last_z_pos =pos.z + last_y_pos =pos.y + + if string.find(node_at_upper_body, "default:water") then + if music then + return {water=water, water_frequent=water_frequent, music=music} + else + return {water=water, water_frequent=water_frequent} + end + elseif node_at_upper_body == "air" then + if string.find(node_at_lower_body, "default:water") then + --minetest.chat_send_all("bottom counted as water") + --we found air at upperbody, and water at lower body. Now there are 4 possibilities: + --Key: under feet, moving or not + --swimming w, m swimming + --walking in water nw, m splashing + --treading water w, nm sloshing + --standing in water nw, nm beach trumps, then sloshing + if player_is_moving_horiz then + if string.find(node_under_feet, "default:water") then + if music then + return {swimming_frequent=swimming_frequent, music=music} + else + return {swimming_frequent} + end + else --didn't find water under feet: walking in water + if music then + return {splashing_water=splashing_water, music=music} + else + return {splashing_water} + end + end + else--player is not moving + if string.find(node_under_feet, "default:water") then + if music then + return {water_surface=water_surface, music=music} + else + return {water_surface} + end + else --didn't find water under feet + standing_in_water = true + end + end + end + end + if player_is_moving_horiz then + minetest.chat_send_all("playermoving") + end + if player_is_climbing then + minetest.chat_send_all("player Climbing") + end + minetest.chat_send_all("nub:" ..node_at_upper_body) + minetest.chat_send_all("nlb:" ..node_at_lower_body) + minetest.chat_send_all("nuf:" ..node_under_feet) + minetest.chat_send_all("n3uf:" ..node_3_under_feet) + + local air_or_ignore = {air=true,ignore=true} + --minetest.chat_send_all(air_or_ignore[node_under_feet]) + if (player_is_moving_horiz or player_is_climbing) and air_or_ignore[node_at_upper_body] and air_or_ignore[node_at_lower_body] + and air_or_ignore[node_under_feet] and air_or_ignore[node_3_under_feet] and not player_is_descending then + minetest.chat_send_all("flying!!!!") + if music then + return {flying=flying, music=music} + else + return {flying} + end + end + minetest.chat_send_all("not flying!!!!") + + if nodes_in_range(pos, 7, "default:lava_flowing")>5 or nodes_in_range(pos, 7, "default:lava_source")>5 then + if music then + return {lava=lava, lava2=lava2, music=music} + else + return {lava=lava} + end + end + if nodes_in_range(pos, 6, "default:water_flowing")>45 then + if music then + return {flowing_water=flowing_water, flowing_water2=flowing_water2, music=music} + else + return {flowing_water=flowing_water, flowing_water2=flowing_water2} + end + end + + +--if we are near sea level and there is lots of water around the area + if pos.y < 7 and pos.y >0 and atleast_nodes_in_grid(pos, 60, 1, "default:water_source", 51 ) then + if music then + return {beach=beach, beach_frequent=beach_frequent, music=music} + else + return {beach=beach, beach_frequent=beach_frequent} + end + end + if standing_in_water then + if music then + return {water_surface=water_surface, music=music} + else + return {water_surface} + end + end + + + desert_in_range = (nodes_in_range(pos, 6, "default:desert_sand")+nodes_in_range(pos, 6, "default:desert_stone")) + --minetest.chat_send_all("desertcount: " .. desert_in_range .. ",".. pos.y ) + if desert_in_range >250 then + if music then + return {desert=desert, desert_frequent=desert_frequent, music=music} + else + return {desert=desert, desert_frequent=desert_frequent} + end + end + + pos.y = pos.y-2 + nodename = minetest.env:get_node(pos).name +-- minetest.chat_send_all("Found " .. nodename .. pos.y ) + + + if player:getpos().y < 0 then + if music then + return {cave=cave, cave_frequent=cave_frequent, music=music} + else + return {cave=cave, cave_frequent=cave_frequent} + end + end + if is_daytime() then + if music then + return {day=day, day_frequent=day_frequent, music=music} + else + return {day=day, day_frequent=day_frequent} + end + else + if music then + return {night=night, night_frequent=night_frequent, music=music} + else + return {night=night, night_frequent=night_frequent} + end + end +end + +-- start playing the sound, set the handler and delete the handler after sound is played +local play_sound = function(player, list, number) + local player_name = player:get_player_name() + if list.handler[player_name] == nil then + local gain = 1.0 + if list[number].gain ~= nil then + gain = list[number].gain + end + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) + if handler ~= nil then + list.handler[player_name] = handler + minetest.after(list[number].length, function(args) + local list = args[1] + local player_name = args[2] + if list.handler[player_name] ~= nil then + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end, {list, player_name}) + end + end +end + +-- stops all sounds that are not in still_playing +local stop_sound = function(still_playing, player) + local player_name = player:get_player_name() + if still_playing.cave == nil then + local list = cave + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.cave_frequent == nil then + local list = cave_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.swimming_frequent == nil then + local list = swimming_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach == nil then + local list = beach + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.beach_frequent == nil then + local list = beach_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.desert == nil then + local list = desert + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.desert_frequent == nil then + local list = desert_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night == nil then + local list = night + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.night_frequent == nil then + local list = night_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day == nil then + local list = day + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.day_frequent == nil then + local list = day_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.music == nil then + local list = music + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water == nil then + local list = flowing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flowing_water2 == nil then + local list = flowing_water2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava == nil then + local list = lava + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.lava2 == nil then + local list = lava2 + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water == nil then + local list = water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_surface == nil then + local list = water_surface + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.water_frequent == nil then + local list = water_frequent + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + -- minetest.chat_send_all("list.on_stop " .. list.on_stop ) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.flying == nil then + --minetest.chat_send_all("begin stop flying " ) + local list = flying + if list.handler[player_name] ~= nil then + -- minetest.chat_send_all("handler flying " ) + if list.on_stop ~= nil then + -- minetest.chat_send_all("onstop flying" ) + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + played_on_start = false + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + if still_playing.splashing_water == nil then + local list = splashing_water + if list.handler[player_name] ~= nil then + if list.on_stop ~= nil then + minetest.sound_play(list.on_stop, {to_player=player:get_player_name()}) + end + minetest.sound_stop(list.handler[player_name]) + list.handler[player_name] = nil + end + end + +end + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer+dtime + if timer < 1 then + return + end + timer = 0 + + for _,player in ipairs(minetest.get_connected_players()) do + local ambiences = get_ambience(player) + stop_sound(ambiences, player) + for _,ambience in pairs(ambiences) do + if math.random(1, 1000) <= ambience.frequency then + if(played_on_start) then + -- minetest.chat_send_all("playedOnStart " ) + else + -- minetest.chat_send_all("FALSEplayedOnStart " ) + end + if ambience.on_start ~= nil and played_on_start == false then + played_on_start = true + minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + end + minetest.chat_send_all("ambience: " ..ambience ) + -- if ambience.on_start ~= nil and played_on_start_flying == false then + -- played_on_start_flying = true + -- minetest.sound_play(ambience.on_start, {to_player=player:get_player_name()}) + -- end + play_sound(player, ambience, math.random(1, #ambience)) + end + end + end +end) \ No newline at end of file diff --git a/kingdoms_game/mods/ambience/sounds/Bats_in_Cave.ogg b/kingdoms_game/mods/ambience/sounds/Bats_in_Cave.ogg new file mode 100644 index 0000000..468eeba Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Bats_in_Cave.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/Best Cardinal Bird.ogg b/kingdoms_game/mods/ambience/sounds/Best Cardinal Bird.ogg new file mode 100644 index 0000000..4a93395 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Best Cardinal Bird.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/ComboWind.ogg b/kingdoms_game/mods/ambience/sounds/ComboWind.ogg new file mode 100644 index 0000000..3158993 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/ComboWind.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/Crickets_At_NightCombo.ogg b/kingdoms_game/mods/ambience/sounds/Crickets_At_NightCombo.ogg new file mode 100644 index 0000000..176636d Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Crickets_At_NightCombo.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/DesertMonolithMed.ogg b/kingdoms_game/mods/ambience/sounds/DesertMonolithMed.ogg new file mode 100644 index 0000000..ad8224a Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/DesertMonolithMed.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/RattleSnake.ogg b/kingdoms_game/mods/ambience/sounds/RattleSnake.ogg new file mode 100644 index 0000000..1bb09b8 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/RattleSnake.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/Single_Water_Droplet.ogg b/kingdoms_game/mods/ambience/sounds/Single_Water_Droplet.ogg new file mode 100644 index 0000000..b732453 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Single_Water_Droplet.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/SoundLicenses.txt b/kingdoms_game/mods/ambience/sounds/SoundLicenses.txt new file mode 100644 index 0000000..f37a799 --- /dev/null +++ b/kingdoms_game/mods/ambience/sounds/SoundLicenses.txt @@ -0,0 +1,115 @@ +--------------Music Lic: +Amethystium: +--Avalon +--Ethereal +--Faraway +--Strangely Beautiful +Used with kind permission from Øystein Ramfjord / AM.mu Records + +Jordach: +--dark_ambiance +--eastern_feeling +These sounds are used for the Mod for Minetest; Ambiance. +The included sounds are http://creativecommons.org/licenses/by-nc-sa/3.0/ +Not Used:--mtest + +-----------Sound Lic: +--Nightime Sound, Recorded by Mike Koenig, License: Attribution 3.0 http://soundbible.com/951-Nightime.html +--Crickets At Night Sound, License: Attribution 3.0 | Recorded by Mike Koenig |http://soundbible.com/365-Crickets-At-Night.html + +--Medium Pack Of Wolves Howling, License: Public Domain | Recorded by fws.gov, http://soundbible.com/277-Medium-Pack-Of-Wolves-Howling.html + +--Horned Owl Sound, License: Attribution 3.0 | Recorded by Mike Koenig , http://soundbible.com/1851-Horned-Owl.html +--Bats In Cave Sound, License: Attr-Noncommercial 3.0 | Recorded by Mike Koenig , http://soundbible.com/1939-Bats-In-Cave.html + +--Spooky Water Drops Sound, License: Attribution 3.0 | Recorded by Mike Koenig, http://soundbible.com/380-Spooky-Water-Drops.html + + +-- Single Water Droplet Sound, License: Attribution 3.0 | Recorded by Mike Koenig, http://soundbible.com/384-Single-Water-Droplet.html + +--HollowWind, Black Boe, Creative Commons 0 License, http://www.freesound.org/people/Black%20Boe/sounds/22331/ + +--drippingwater*.ogg sounds: CC0, Dripping Water Mod, by kddekadenz, http://minetest.net/forum/viewtopic.php?id=1688 + +--best cardinal bird: License: Attribution 3.0 | Recorded by PsychoBird, http://soundbible.com/1515-Best-Cardinal-Bird.html + +--birdsongnl: the Attribution License, HerbertBoland, http://www.freesound.org/people/HerbertBoland/sounds/28312/ (end) + +--robin2: Attribution License, reinsamba, http://www.freesound.org/people/reinsamba/sounds/32479/ (end) + +--Craw.WAV, Attribution License, inchadney, http://www.freesound.org/people/inchadney/sounds/52450/ + +--bluejay.wav, Creative Commons 0 License, UncleSigmund, http://www.freesound.org/people/UncleSigmund/sounds/42382/ + +--scuba1*.ogg- digifishmusic, Attribution License, http://www.freesound.org/people/digifishmusic/sounds/45521/ + +--Underwater Pool - Attribution 3.0 | Recorded by Mike Koenig, http://soundbible.com/1660-Underwater-Pool.html + +--dolphin_screaming - Creative Commons 0 License, felix.blume, http://www.freesound.org/people/felix.blume/sounds/161691/ + +--dolphins - Attribution Noncommercial License, acclivity, http://www.freesound.org/people/acclivity/sounds/13691/ + +ComboWind uses: +--wind-in-the-trees -Attribution License, laurent, http://www.freesound.org/people/laurent/sounds/16995/ +--drygrassInWind- Creative Commons 0 License, felix.blume, http://www.freesound.org/people/felix.blume/sounds/146436/ + +--Splash: Attribution 3.0 | Recorded by BlastwaveFx.com, http://soundbible.com/546-Fish-Splashing.html + +--small_waterfall Attribution License, volivieri, http://www.freesound.org/people/volivieri/sounds/38390/ + +--Lake_Waves_2*, Attribution License, Benboncan, http://www.freesound.org/people/Benboncan/sounds/67884/ + +--water_swimming_splashing*, Attribution Noncommercial License, Robinhood76, http://www.freesound.org/people/Robinhood76/sounds/79657/ + +--earth01a, Creative Commons 0 License., Halion , http://www.freesound.org/people/Halion/sounds/17785 + +--fiji_beach, Creative Commons 0 License, c97059890, http://www.freesound.org/people/c97059890/sounds/21754/ + +--seagull, Attribution Noncommercial License., hazure, http://www.freesound.org/people/hazure/sounds/23707/, + +desert: +coyote2, Attribution License, rogerforeman, http://www.freesound.org/people/rogerforeman/sounds/68068/ +http://www.freesound.org/people/Proxima4/sounds/104319/ +Desert Monolith.wav, Creative Commons 0 License, Proxima4, http://www.freesound.org/people/Proxima4/sounds/104319/ +Rattlesnake Rattle, Public Domain, fws.gov, http://soundbible.com/237-Rattlesnake-Rattle.html + +flying: +crystal_airlines: Attribution License, suonho, http://www.freesound.org/people/suonho/sounds/56364/ + +----------------Not used yet: +desert: +Desert Simple.wav, Creative Commons 0 License, Proxima4, http://www.freesound.org/people/Proxima4/sounds/104320/ + + 313hummer (Jordan Craige) +--echos http://soundcloud.com/jordan-craige/echos-1 +Creative Commons Attribution license (reuse allowed) Attribution 3.0 Unported (CC BY 3.0) +Not Used:--FoamOfTheSea http://soundcloud.com/jordan-craige/foam-of-the-sea + +xi-intersection: +http://soundcloud.com/xi-intersection/mass-effect-uncharted-worlds Creative Commons License +--not used: +http://soundcloud.com/xi-intersection/donkey-kong-country-2-flight +http://soundcloud.com/kogyo/kogyo-skalar-m1 + +lava: +http://www.freesound.org/people/Halion/sounds/17785/ (almost as good cc) (combine with rocks falling?) +http://www.freesound.org/people/pushtobreak/sounds/17823/ (attrib non cc really good) +http://www.freesound.org/people/klankbeeld/sounds/123970/ (horror rhythm) +Rockfall in mine.wav http://www.freesound.org/people/Benboncan/sounds/60085/ + + +http://www.freesound.org/people/snotch/sounds/96175/ (mud volcano) + +--natural night sounds in Boquete.wav, Attribution License, laurent, http://www.freesound.org/people/laurent/sounds/15851/ +http://www.freesound.org/people/Dynamicell/sounds/17553/ +http://www.freesound.org/people/juskiddink/sounds/78955/ aspen tree in wind +http://www.freesound.org/people/Benboncan/sounds/69761/ wind in hedge birds animals + + +ButterflyTea: +Creative Commons : Attribution-Noncommercial-Share Alike 3.0 +http://www.jamendo.com/en/track/904012/dance-of-magical-flowers +http://www.jamendo.com/en/track/904013/magic-of-the-seventh-world +http://www.jamendo.com/en/track/904016/in-search-of-the-soul + +zero-project diff --git a/kingdoms_game/mods/ambience/sounds/Splash.ogg b/kingdoms_game/mods/ambience/sounds/Splash.ogg new file mode 100644 index 0000000..8a433a7 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Splash.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/Spooky_Water_Drops.ogg b/kingdoms_game/mods/ambience/sounds/Spooky_Water_Drops.ogg new file mode 100644 index 0000000..c2a3be9 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Spooky_Water_Drops.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/Wolves_Howling.ogg b/kingdoms_game/mods/ambience/sounds/Wolves_Howling.ogg new file mode 100644 index 0000000..f23b1f9 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/Wolves_Howling.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/bird.ogg b/kingdoms_game/mods/ambience/sounds/bird.ogg new file mode 100644 index 0000000..7077d3e Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/bird.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/birdsongnl.ogg b/kingdoms_game/mods/ambience/sounds/birdsongnl.ogg new file mode 100644 index 0000000..baa4970 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/birdsongnl.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/coyote2.ogg b/kingdoms_game/mods/ambience/sounds/coyote2.ogg new file mode 100644 index 0000000..dc29674 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/coyote2.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/craw.ogg b/kingdoms_game/mods/ambience/sounds/craw.ogg new file mode 100644 index 0000000..7b87a6b Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/craw.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/drippingwater_drip_a.ogg b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_a.ogg new file mode 100644 index 0000000..84c3e01 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_a.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/drippingwater_drip_b.ogg b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_b.ogg new file mode 100644 index 0000000..18790fc Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_b.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/drippingwater_drip_c.ogg b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_c.ogg new file mode 100644 index 0000000..ad2424a Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/drippingwater_drip_c.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/drowning_gasp.ogg b/kingdoms_game/mods/ambience/sounds/drowning_gasp.ogg new file mode 100644 index 0000000..5d62a8e Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/drowning_gasp.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/earth01a.ogg b/kingdoms_game/mods/ambience/sounds/earth01a.ogg new file mode 100644 index 0000000..d08740f Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/earth01a.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/fiji_beach.ogg b/kingdoms_game/mods/ambience/sounds/fiji_beach.ogg new file mode 100644 index 0000000..69c37b7 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/fiji_beach.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/horned_owl.ogg b/kingdoms_game/mods/ambience/sounds/horned_owl.ogg new file mode 100644 index 0000000..4656ae6 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/horned_owl.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/lake_waves_2_calm.ogg b/kingdoms_game/mods/ambience/sounds/lake_waves_2_calm.ogg new file mode 100644 index 0000000..b8f4647 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/lake_waves_2_calm.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/lake_waves_2_variety.ogg b/kingdoms_game/mods/ambience/sounds/lake_waves_2_variety.ogg new file mode 100644 index 0000000..47c763b Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/lake_waves_2_variety.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/robin2.ogg b/kingdoms_game/mods/ambience/sounds/robin2.ogg new file mode 100644 index 0000000..001cf97 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/robin2.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/scuba1bubbles.ogg b/kingdoms_game/mods/ambience/sounds/scuba1bubbles.ogg new file mode 100644 index 0000000..054910a Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/scuba1bubbles.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/scuba1calm.ogg b/kingdoms_game/mods/ambience/sounds/scuba1calm.ogg new file mode 100644 index 0000000..e1e76cf Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/scuba1calm.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/scuba1calm2.ogg b/kingdoms_game/mods/ambience/sounds/scuba1calm2.ogg new file mode 100644 index 0000000..c1a348a Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/scuba1calm2.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/scuba1interestingbubbles.ogg b/kingdoms_game/mods/ambience/sounds/scuba1interestingbubbles.ogg new file mode 100644 index 0000000..b17d33c Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/scuba1interestingbubbles.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/scuba1tubulentbubbles.ogg b/kingdoms_game/mods/ambience/sounds/scuba1tubulentbubbles.ogg new file mode 100644 index 0000000..555edff Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/scuba1tubulentbubbles.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/seagull.ogg b/kingdoms_game/mods/ambience/sounds/seagull.ogg new file mode 100644 index 0000000..9dab963 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/seagull.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/small_waterfall.ogg b/kingdoms_game/mods/ambience/sounds/small_waterfall.ogg new file mode 100644 index 0000000..7be3ee4 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/small_waterfall.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/water_swimming_splashing.ogg b/kingdoms_game/mods/ambience/sounds/water_swimming_splashing.ogg new file mode 100644 index 0000000..08fd4db Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/water_swimming_splashing.ogg differ diff --git a/kingdoms_game/mods/ambience/sounds/water_swimming_splashing_breath.ogg b/kingdoms_game/mods/ambience/sounds/water_swimming_splashing_breath.ogg new file mode 100644 index 0000000..a28fa48 Binary files /dev/null and b/kingdoms_game/mods/ambience/sounds/water_swimming_splashing_breath.ogg differ diff --git a/kingdoms_game/mods/ambience/todo.txt b/kingdoms_game/mods/ambience/todo.txt new file mode 100644 index 0000000..4f95977 --- /dev/null +++ b/kingdoms_game/mods/ambience/todo.txt @@ -0,0 +1,11 @@ +To Do: + +-add random_volume parameter to night normal, day normal, & cave normal sounds to create feeling of distance. + +m-get constant birds more quiet during the day +m-bats seem way too frequent now? +m-when playing multiplayer seems to increase frequency of music & normal sounds to the point where they are obnoxious +m-which songs should go with which environments? Dark songs in caves or night, light sounds during day. +m-may be drowning out some of the normal sound effects like walking on stone. +l-what about other weird bubble +l-put in wind/ wind in trees during day and night diff --git a/kingdoms_game/mods/anvil/Readme.md b/kingdoms_game/mods/anvil/Readme.md new file mode 100644 index 0000000..8d3f10a --- /dev/null +++ b/kingdoms_game/mods/anvil/Readme.md @@ -0,0 +1,11 @@ +# Anvil + +_An anvil mod for minetest_ + +This mod is still in a WIP phase, so expect changes in the future :) + +Basing on the GPLv3 licensed anvil in the [cottages mod](https://forum.minetest.net/viewtopic.php?id=5120) from Sokomine ([github link](https://github.com/Sokomine/random_buildings/master/cottages)). + +Improved by est31. + +License: GPLv3 diff --git a/kingdoms_game/mods/anvil/depends.txt b/kingdoms_game/mods/anvil/depends.txt new file mode 100644 index 0000000..d9b8b81 --- /dev/null +++ b/kingdoms_game/mods/anvil/depends.txt @@ -0,0 +1 @@ +intllib? \ No newline at end of file diff --git a/kingdoms_game/mods/anvil/init.lua b/kingdoms_game/mods/anvil/init.lua new file mode 100644 index 0000000..fdc5d3f --- /dev/null +++ b/kingdoms_game/mods/anvil/init.lua @@ -0,0 +1,258 @@ +--------------------------------------------------------------------------------------- +-- simple anvil that can be used to repair tools +--------------------------------------------------------------------------------------- +-- * can be used to repair tools +-- * the hammer gets dammaged a bit at each repair step +--------------------------------------------------------------------------------------- +-- License of the hammer picture: CC-by-SA; done by GloopMaster; source: +-- https://github.com/GloopMaster/glooptest/blob/master/glooptest/textures/glooptest_tool_steelhammer.png + +-- Boilerplate to support localized strings if intllib mod is installed. +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) +else + S = function(s,a,...)if a==nil then return s end a={a,...}return s:gsub("(@?)@(%(?)(%d+)(%)?)",function(e,o,n,c)if e==""then return a[tonumber(n)]..(o==""and c or"")else return"@"..o..n..c end end) end +end + +-- the hammer for the anvil +minetest.register_tool("anvil:hammer", { + description = S("Steel hammer for repairing tools on the anvil"), + image = "glooptest_tool_steelhammer.png", + inventory_image = "glooptest_tool_steelhammer.png", + + tool_capabilities = { + full_punch_interval = 0.8, + max_drop_level=1, + groupcaps={ + -- about equal to a stone pick (it's not intended as a tool) + cracky={times={[2]=2.00, [3]=1.20}, uses=30, maxlevel=1}, + }, + damage_groups = {fleshy=6}, + } +}) + + + +minetest.register_node("anvil:anvil", { + drawtype = "nodebox", + description = S("anvil"), + tiles = {"default_stone.png"}, -- TODO default_steel_block.png, default_obsidian.png are also nice + paramtype = "light", + paramtype2 = "facedir", + groups = {cracky=2}, + -- the nodebox model comes from realtest + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.3,0.5,-0.4,0.3}, + {-0.35,-0.4,-0.25,0.35,-0.3,0.25}, + {-0.3,-0.3,-0.15,0.3,-0.1,0.15}, + {-0.35,-0.1,-0.2,0.35,0.1,0.2}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.3,0.5,-0.4,0.3}, + {-0.35,-0.4,-0.25,0.35,-0.3,0.25}, + {-0.3,-0.3,-0.15,0.3,-0.1,0.15}, + {-0.35,-0.1,-0.2,0.35,0.1,0.2}, + } + }, + on_construct = function(pos) + + local meta = minetest.env:get_meta(pos); + meta:set_string("infotext", S("Anvil")); + local inv = meta:get_inventory(); + inv:set_size("input", 1); +-- inv:set_size("material", 9); +-- inv:set_size("sample", 1); + end, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos); + meta:set_string("owner", placer:get_player_name() or ""); + --meta:set_string("infotext", S("Anvil (owned by %s)"):format((meta:get_string("owner") or ""))); + meta:set_string("formspec", + "size[8,6]".. + --"image[7,3;1,1;glooptest_tool_steelhammer.png]".. + "list[context;input;3.5,0.5;1,1;]".. + "label[0,0.7;"..S("Insert damaged tool here:").."]".. + --"label[0,0;"..S("Anvil, owned by %s"):format(meta:get_string('owner') or "").."]".. + --"label[0,3.0;"..S("Punch anvil with hammer to").."]".. + --"label[0,3.3;"..S("repair tool in workpiece-slot.").."]".. + "list[current_player;main;0,2;8,4;]"); + end, + + can_dig = function(pos,player) + + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory(); + local owner = meta:get_string('owner'); + + if( not( inv:is_empty("input")) +-- or not( inv:is_empty("material")) +-- or not( inv:is_empty("sample")) + or not( player ) + --[[or ( owner and owner ~= '' and player:get_player_name() ~= owner )--]]) then + + return false; + end + if not inv:is_empty("hammer") then + for _, stack in pairs(inv:get_list("hammer")) do + minetest.item_drop(stack, "", pos) + end + end + return true; + end, + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + --if( player and player:get_player_name() ~= meta:get_string('owner' )) then + --return 0 + --end + + return count; + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + -- if( player and player:get_player_name() ~= meta:get_string('owner' )) then + -- return 0; + --end + if( listname=='hammer' and stack and stack:get_name() ~= 'anvil:hammer') then + return 0; + end + if( listname=='input' and stack:get_wear() == 0 ) then + + --minetest.chat_send_player( player:get_player_name(), + --S('The workpiece slot is for damaged tools only.')); + + return 0; + end + return stack:get_count() + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + --if( player and player:get_player_name() ~= meta:get_string('owner' )) then + -- return 0 + --end + return stack:get_count() + end, + + + on_punch = function(pos, node, puncher) + if( not( pos ) or not( node ) or not( puncher )) then + return; + end + -- only punching with the hammer is supposed to work + local wielded = puncher:get_wielded_item(); + if( not( wielded ) or not( wielded:get_name() ) or wielded:get_name() ~= 'anvil:hammer') then + return; + end + local name = puncher:get_player_name(); + + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory(); + + local input = inv:get_stack('input',1); + + -- only tools can be repaired + if( not( input ) or input:is_empty() ) then + minetest.sound_play("hammerhitsoft.ogg", { + pos = pos, + max_hear_distance = 20, + gain = 1, + }) + return; + end + + local inputdef = minetest.registered_items[input:get_name()] + local mechanical = not inputdef.wear_represents or inputdef.wear_represents == "mechanical_wear" + if not mechanical then + return + end + + -- tell the player when the job is done + if( input:get_wear() == 0 ) then + --minetest.chat_send_player( puncher:get_player_name(), + --S('Your tool has been repaired successfully.')); + + minetest.sound_play("hammerhitsoft", { + pos = pos, + max_hear_distance = 50, + gain = 1, + }) + return; + end + + -- do the actual repair + input:add_wear( -5000 ); -- equals to what technic toolshop does in 5 seconds + inv:set_stack("input", 1, input) + + minetest.sound_play("hammerhithard", { + pos = pos, + max_hear_distance = 100, + gain = 1, + }) + + -- damage the hammer slightly + wielded:add_wear( 100 ); + puncher:set_wielded_item( wielded ); + + -- do not spam too much + --if( math.random( 1,5 )==1 ) then + --minetest.chat_send_player( puncher:get_player_name(), + --S('Your workpiece improves.')); + -- end + end, + is_ground_content = false, +}) + + + +--------------------------------------------------------------------------------------- +-- crafting receipes +--------------------------------------------------------------------------------------- +minetest.register_craft({ + output = "anvil:anvil", + recipe = { + {'default:steel_ingot','default:steel_ingot','default:steel_ingot'}, + {'', 'default:steel_ingot','' }, + {'default:steel_ingot','default:steel_ingot','default:steel_ingot'} }, +}) + + +-- the castle-mod has an anvil as well - with the same receipe. convert the two into each other +if ( minetest.get_modpath("castle") ~= nil ) then + + minetest.register_craft({ + output = "anvil:anvil", + recipe = { + {'castle:anvil'}, + }, + }) + + minetest.register_craft({ + output = "castle:anvil", + recipe = { + {'anvil:anvil'}, + }, + }) +end + +--legacy and compatibility with other mod +minetest.register_alias("cottages:anvil","anvil:anvil") +minetest.register_alias("cottages:hammer","anvil:hammer") + + +minetest.register_craft({ + output = "anvil:hammer", + recipe = { + {'default:steel_ingot','default:steel_ingot','default:steel_ingot'}, + {'default:steel_ingot','default:steel_ingot','default:steel_ingot'}, + {'', 'default:stick', '' } } +}) \ No newline at end of file diff --git a/kingdoms_game/mods/anvil/locale/de.txt b/kingdoms_game/mods/anvil/locale/de.txt new file mode 100644 index 0000000..9f16aa4 --- /dev/null +++ b/kingdoms_game/mods/anvil/locale/de.txt @@ -0,0 +1,17 @@ +# Translation by Xanthin + +### nodes_anvil.lua ### +Steel hammer for repairing tools on the anvil = Stahlhammer um Werkzeuge auf dem Amboss zu reparieren +anvil = Amboss +Anvil = Amboss +The workpiece slot is for damaged tools only. = Das Werkstueckfeld gilt nur fuer beschaedigtes Werkzeug. +Your tool has been repaired successfully. = Dein Werkzeug wurde erfolgreich repariert. +Your workpiece improves. = Dein Werkstueck verbessert sich. +Anvil (owned by %s) = Amboss (gehoert %s) +Workpiece: = Werkstueck +Optional = Moegliche +storage for = Aufbewahrung fuer +your hammer = deinen Hammer +Owner: %s = Besitzer: %s +Punch anvil with hammer to = Schlage mit dem Hammer auf den Amboss um +repair tool in workpiece-slot. = das Werkzeug im Werkstueckfeld zu reparieren. diff --git a/kingdoms_game/mods/anvil/locale/template.txt b/kingdoms_game/mods/anvil/locale/template.txt new file mode 100644 index 0000000..51b61f1 --- /dev/null +++ b/kingdoms_game/mods/anvil/locale/template.txt @@ -0,0 +1,18 @@ +# Template + +### nodes_anvil.lua ### +Steel hammer for repairing tools on the anvil = Stahlhammer um Werkzeuge auf dem Amboss zu reparieren +anvil = Amboss +Anvil = Amboss +The workpiece slot is for damaged tools only. = Das Werkstueckfeld gilt nur fuer beschaedigtes Werkzeug. +Your tool has been repaired successfully. = Dein Werkzeug wurde erfolgreich repariert. +Your workpiece improves. = Dein Werkstueck verbessert sich. +Anvil (owned by %s) = Amboss (gehoert %s) +Workpiece: = Werkstueck +Optional = Moegliche +storage for = Aufbewahrung fuer +your hammer = deinen Hammer +Owner: %s = Besitzer: %s +Punch anvil with hammer to = Schlage mit dem Hammer auf den Amboss um +repair tool in workpiece-slot. = das Werkzeug im Werkstueckfeld zu reparieren. + diff --git a/kingdoms_game/mods/anvil/sounds/hammerhithard.ogg b/kingdoms_game/mods/anvil/sounds/hammerhithard.ogg new file mode 100644 index 0000000..df2b517 Binary files /dev/null and b/kingdoms_game/mods/anvil/sounds/hammerhithard.ogg differ diff --git a/kingdoms_game/mods/anvil/sounds/hammerhitsoft.ogg b/kingdoms_game/mods/anvil/sounds/hammerhitsoft.ogg new file mode 100644 index 0000000..aed1553 Binary files /dev/null and b/kingdoms_game/mods/anvil/sounds/hammerhitsoft.ogg differ diff --git a/kingdoms_game/mods/anvil/textures/glooptest_tool_steelhammer.png b/kingdoms_game/mods/anvil/textures/glooptest_tool_steelhammer.png new file mode 100644 index 0000000..b662a71 Binary files /dev/null and b/kingdoms_game/mods/anvil/textures/glooptest_tool_steelhammer.png differ diff --git a/kingdoms_game/mods/areas/.gitignore b/kingdoms_game/mods/areas/.gitignore new file mode 100644 index 0000000..5236e1e --- /dev/null +++ b/kingdoms_game/mods/areas/.gitignore @@ -0,0 +1,2 @@ +*~ + diff --git a/kingdoms_game/mods/areas/LICENSE.txt b/kingdoms_game/mods/areas/LICENSE.txt new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/kingdoms_game/mods/areas/LICENSE.txt @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. 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 not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the 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 +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/kingdoms_game/mods/areas/README.md b/kingdoms_game/mods/areas/README.md new file mode 100644 index 0000000..bd6a54d --- /dev/null +++ b/kingdoms_game/mods/areas/README.md @@ -0,0 +1,104 @@ +Areas mod for Minetest 0.4.8+ +============================= + + +Configuration +------------- + +If you wish to specify configuration options, such as whether players are +allowed to protect their own areas with the `protect` command (disabled by +default), you should check config.lua and set the appropriate settings in your +server's configuration file (probably `minetest.conf`). + + +Tutorial +-------- + +To protect an area you must first set the corner positions of the area. +In order to set the corner positions you can run: + * `/area_pos set` and punch the two corner nodes to set them. + * `/area_pos set1/set2` and punch only the first or second corner node to + set them one at a time. + * `/area_pos1/2` to set one of the positions to your current position. + * `/area_pos1/2 X Y Z` to set one of the positions to the specified + coordinates. + +Once you have set the border positions you can protect the area by running one +of the following commands: + * `/set_owner ` -- If you have the `areas` privilege. + * `/protect ` -- If you have the `areas` privilege or the server + administrator has enabled area self-protection. + +The area name is used only for informational purposes (so that you know what +an area is for). It is not used for any other purpose. +For example: `/set_owner SomePlayer Mese city` + +Now that you own an area you may want to add sub-owners to it. You can do this +with the `add_owner` command. Anyone with an area can use the `add_owner` +command on their areas. Before using the `add_owner` command you have to +select the corners of the sub-area as you did for `set_owner`. If your markers +are still around your original area and you want to grant access to your +entire area you will not have to re-set them. You can also use `select_area` to +place the markers at the corners of an existing area if you've reset your +markers and want to grant access to a full area. +The `add_owner` command expects three arguments: + 1. The ID number of the parent area (the area that you want to add a + sub-area to). + 2. The name of the player that will own the sub-area. + 3. The name of the sub-area. (can contain spaces) + +For example: `/add_owner 123 BobTheBuilder Diamond lighthouse` + + +Commands +-------- + + * `/protect ` -- Protects an area for yourself. (if + self-protection is enabled) + + * `/set_owner ` -- Protects an area for a specified + player. (requires the `areas` privilege) + + * `/add_owner ` -- Grants another player + control over part (or all) of an area. + + * `/rename_area ` -- Renames an existing area. + + * `/list_areas` -- Lists all of the areas that you own, or all areas if you + have the `areas` privilege. + + * `/find_areas ` -- Finds areas using a Lua regular expresion. + For example, to find castles: + + /find_areas [Cc]astle + + * `/remove_area ` -- Removes an area that you own. Any sub-areas of that + area are made sub-areas of the removed area's parent, if it exists. + If the removed area has no parent it's sub-areas will have no parent. + + * `/recursive_remove_areas ` -- Removes an area and all sub-areas of it. + + * `/change_owner ` -- Change the owner of an area. + + * `/area_info` -- Returns information about area configuration and usage. + + * `/select_area ` -- Sets the area positions to those of an existing + area. + + * `/area_pos {set,set1,set2,get}` -- Sets the area positions by punching + nodes or shows the current area positions. + + * `/area_pos1 [X,Y,Z|X Y Z]` -- Sets area position one to your position or + the one supplied. + + * `/area_pos2 [X,Y,Z|X Y Z]` -- Sets area position two to your position or + the one supplied. + +License +------- + +Copyright (C) 2013 ShadowNinja + +Licensed under the GNU LGPL version 2.1 or later. +See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt + diff --git a/kingdoms_game/mods/areas/api.lua b/kingdoms_game/mods/areas/api.lua new file mode 100644 index 0000000..e8b9c7a --- /dev/null +++ b/kingdoms_game/mods/areas/api.lua @@ -0,0 +1,128 @@ + +--- Returns a list of areas that include the provided position. +function areas:getAreasAtPos(pos) + local res = {} + if self.store then + local a = self.store:get_areas_for_pos(pos, false, true) + for store_id, store_area in pairs(a) do + local id = tonumber(store_area.data) + res[id] = self.areas[id] + end + else + local px, py, pz = pos.x, pos.y, pos.z + for id, area in pairs(self.areas) do + local ap1, ap2 = area.pos1, area.pos2 + if + (px >= ap1.x and px <= ap2.x) and + (py >= ap1.y and py <= ap2.y) and + (pz >= ap1.z and pz <= ap2.z) then + res[id] = area + end + end + end + return res +end + +--- Returns areas that intersect with the passed area. +function areas:getAreasIntersectingArea(pos1, pos2) + local res = {} + if self.store then + local a = self.store:get_areas_in_area(pos1, pos2, + true, false, true) + for store_id, store_area in pairs(a) do + local id = tonumber(store_area.data) + res[id] = self.areas[id] + end + else + self:sortPos(pos1, pos2) + local p1x, p1y, p1z = pos1.x, pos1.y, pos1.z + local p2x, p2y, p2z = pos2.x, pos2.y, pos2.z + for id, area in pairs(self.areas) do + local ap1, ap2 = area.pos1, area.pos2 + if + (ap1.x <= p2x and ap2.x >= p1x) and + (ap1.y <= p2y and ap2.y >= p1y) and + (ap1.z <= p2z and ap2.z >= p1z) then + -- Found an intersecting area. + res[id] = area + end + end + end + return res +end + +-- Checks if the area is unprotected or owned by you +function areas:canInteract(pos, name) + if minetest.check_player_privs(name, self.adminPrivs) then + return true + end + local owned = false + for _, area in pairs(self:getAreasAtPos(pos)) do + if area.owner == name or area.open then + return true + else + owned = true + end + end + return not owned +end + +-- Returns a table (list) of all players that own an area +function areas:getNodeOwners(pos) + local owners = {} + for _, area in pairs(self:getAreasAtPos(pos)) do + table.insert(owners, area.owner) + end + return owners +end + +--- Checks if the area intersects with an area that the player can't interact in. +-- Note that this fails and returns false when the specified area is fully +-- owned by the player, but with multiple protection zones, none of which +-- cover the entire checked area. +-- @param name (optional) Player name. If not specified checks for any intersecting areas. +-- @param allow_open Whether open areas should be counted as if they didn't exist. +-- @return Boolean indicating whether the player can interact in that area. +-- @return Un-owned intersecting area ID, if found. +function areas:canInteractInArea(pos1, pos2, name, allow_open) + if name and minetest.check_player_privs(name, self.adminPrivs) then + return true + end + self:sortPos(pos1, pos2) + + -- Intersecting non-owned area ID, if found. + local blocking_area = nil + + local areas = self:getAreasIntersectingArea(pos1, pos2) + for id, area in pairs(areas) do + -- First check for a fully enclosing owned area. + -- A little optimization: isAreaOwner isn't necessary + -- here since we're iterating over all relevant areas. + if area.owner == name and + self:isSubarea(pos1, pos2, id) then + return true + end + + -- Then check for intersecting non-owned (blocking) areas. + -- We don't bother with this check if we've already found a + -- blocking area, as the check is somewhat expensive. + -- The area blocks if the area is closed or open areas aren't + -- acceptable to the caller, and the area isn't owned. + -- Note: We can't return directly here, because there might be + -- an exclosing owned area that we haven't gotten to yet. + if not blocking_area and + (not allow_open or not area.open) and + (not name or not self:isAreaOwner(id, name)) then + blocking_area = id + end + end + + if blocking_area then + return false, blocking_area + end + + -- There are no intersecting areas or they are only partially + -- intersecting areas and they are all owned by the player. + return true +end + diff --git a/kingdoms_game/mods/areas/chatcommands.lua b/kingdoms_game/mods/areas/chatcommands.lua new file mode 100644 index 0000000..d37634a --- /dev/null +++ b/kingdoms_game/mods/areas/chatcommands.lua @@ -0,0 +1,404 @@ + +minetest.register_chatcommand("protect", { + params = "", + description = "Protect your own area", + privs = {[areas.config.self_protection_privilege]=true}, + func = function(name, param) + if param == "" then + return false, "Invalid usage, see /help protect." + end + local pos1, pos2 = areas:getPos(name) + if not (pos1 and pos2) then + return false, "You need to select an area first." + end + + minetest.log("action", "/protect invoked, owner="..name.. + " AreaName="..param.. + " StartPos="..minetest.pos_to_string(pos1).. + " EndPos=" ..minetest.pos_to_string(pos2)) + + local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, name) + if not canAdd then + return false, "You can't protect that area: "..errMsg + end + + local id = areas:add(name, param, pos1, pos2, nil) + areas:save() + + return true, "Area protected. ID: "..id + end +}) + + +minetest.register_chatcommand("set_owner", { + params = " ", + description = "Protect an area beetween two positions and give" + .." a player access to it without setting the parent of the" + .." area to any existing area", + privs = areas.adminPrivs, + func = function(name, param) + local ownerName, areaName = param:match('^(%S+)%s(.+)$') + + if not ownerName then + return false, "Incorrect usage, see /help set_owner." + end + + local pos1, pos2 = areas:getPos(name) + if not (pos1 and pos2) then + return false, "You need to select an area first." + end + + if not areas:player_exists(ownerName) then + return false, "The player \"" + ..ownerName.."\" does not exist." + end + + minetest.log("action", name.." runs /set_owner. Owner = "..ownerName.. + " AreaName = "..areaName.. + " StartPos = "..minetest.pos_to_string(pos1).. + " EndPos = " ..minetest.pos_to_string(pos2)) + + local id = areas:add(ownerName, areaName, pos1, pos2, nil) + areas:save() + + minetest.chat_send_player(ownerName, + "You have been granted control over area #".. + id..". Type /list_areas to show your areas.") + return true, "Area protected. ID: "..id + end +}) + + +minetest.register_chatcommand("add_owner", { + params = " ", + description = "Give a player access to a sub-area beetween two" + .." positions that have already been protected," + .." Use set_owner if you don't want the parent to be set.", + func = function(name, param) + local pid, ownerName, areaName + = param:match('^(%d+) ([^ ]+) (.+)$') + + if not pid then + minetest.chat_send_player(name, "Incorrect usage, see /help add_owner") + return + end + + local pos1, pos2 = areas:getPos(name) + if not (pos1 and pos2) then + return false, "You need to select an area first." + end + + if not areas:player_exists(ownerName) then + return false, "The player \""..ownerName.."\" does not exist." + end + + minetest.log("action", name.." runs /add_owner. Owner = "..ownerName.. + " AreaName = "..areaName.." ParentID = "..pid.. + " StartPos = "..pos1.x..","..pos1.y..","..pos1.z.. + " EndPos = " ..pos2.x..","..pos2.y..","..pos2.z) + + -- Check if this new area is inside an area owned by the player + pid = tonumber(pid) + if (not areas:isAreaOwner(pid, name)) or + (not areas:isSubarea(pos1, pos2, pid)) then + return false, "You can't protect that area." + end + + local id = areas:add(ownerName, areaName, pos1, pos2, pid) + areas:save() + + minetest.chat_send_player(ownerName, + "You have been granted control over area #".. + id..". Type /list_areas to show your areas.") + return true, "Area protected. ID: "..id + end +}) + + +minetest.register_chatcommand("rename_area", { + params = " ", + description = "Rename a area that you own", + func = function(name, param) + local id, newName = param:match("^(%d+)%s(.+)$") + if not id then + return false, "Invalid usage, see /help rename_area." + end + + id = tonumber(id) + if not id then + return false, "That area doesn't exist." + end + + if not areas:isAreaOwner(id, name) then + return true, "You don't own that area." + end + + areas.areas[id].name = newName + areas:save() + return true, "Area renamed." + end +}) + + +minetest.register_chatcommand("find_areas", { + params = "", + description = "Find areas using a Lua regular expression", + privs = areas.adminPrivs, + func = function(name, param) + if param == "" then + return false, "A regular expression is required." + end + + -- Check expression for validity + local function testRegExp() + ("Test [1]: Player (0,0,0) (0,0,0)"):find(param) + end + if not pcall(testRegExp) then + return false, "Invalid regular expression." + end + + local matches = {} + for id, area in pairs(areas.areas) do + local str = areas:toString(id) + if str:find(param) then + table.insert(matches, str) + end + end + if #matches > 0 then + return true, table.concat(matches, "\n") + else + return true, "No matches found." + end + end +}) + + +minetest.register_chatcommand("list_areas", { + description = "List your areas, or all areas if you are an admin.", + func = function(name, param) + local admin = minetest.check_player_privs(name, areas.adminPrivs) + local areaStrings = {} + for id, area in pairs(areas.areas) do + if admin or areas:isAreaOwner(id, name) then + table.insert(areaStrings, areas:toString(id)) + end + end + if #areaStrings == 0 then + return true, "No visible areas." + end + return true, table.concat(areaStrings, "\n") + end +}) + + +minetest.register_chatcommand("recursive_remove_areas", { + params = "", + description = "Recursively remove areas using an id", + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see" + .." /help recursive_remove_areas" + end + + if not areas:isAreaOwner(id, name) then + return false, "Area "..id.." does not exist or is" + .." not owned by you." + end + + areas:remove(id, true) + areas:save() + return true, "Removed area "..id.." and it's sub areas." + end +}) + + +minetest.register_chatcommand("remove_area", { + params = "", + description = "Remove an area using an id", + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see /help remove_area" + end + + if not areas:isAreaOwner(id, name) then + return false, "Area "..id.." does not exist or" + .." is not owned by you." + end + + areas:remove(id) + areas:save() + return true, "Removed area "..id + end +}) + + +minetest.register_chatcommand("change_owner", { + params = " ", + description = "Change the owner of an area using it's ID", + func = function(name, param) + local id, newOwner = param:match("^(%d+)%s(%S+)$") + if not id then + return false, "Invalid usage, see" + .." /help change_owner." + end + + if not areas:player_exists(newOwner) then + return false, "The player \""..newOwner + .."\" does not exist." + end + + id = tonumber(id) + if not areas:isAreaOwner(id, name) then + return false, "Area "..id.." does not exist" + .." or is not owned by you." + end + areas.areas[id].owner = newOwner + areas:save() + minetest.chat_send_player(newOwner, + ("%s has given you control over the area %q (ID %d).") + :format(name, areas.areas[id].name, id)) + return true, "Owner changed." + end +}) + + +minetest.register_chatcommand("area_open", { + params = "", + description = "Toggle an area open (anyone can interact) or closed", + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see /help area_open." + end + + if not areas:isAreaOwner(id, name) then + return false, "Area "..id.." does not exist" + .." or is not owned by you." + end + local open = not areas.areas[id].open + -- Save false as nil to avoid inflating the DB. + areas.areas[id].open = open or nil + areas:save() + return true, ("Area %s."):format(open and "opened" or "closed") + end +}) + + +minetest.register_chatcommand("move_area", { + params = "", + description = "Move (or resize) an area to the current positions.", + privs = areas.adminPrivs, + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see /help move_area." + end + + local area = areas.areas[id] + if not area then + return false, "Area does not exist." + end + + local pos1, pos2 = areas:getPos(name) + if not pos1 then + return false, "You need to select an area first." + end + + area.pos1 = pos1 + area.pos2 = pos2 + areas:save() + return true, "Area successfully moved." + end, +}) + +minetest.register_chatcommand("area_info", { + description = "Get information about area configuration and usage.", + func = function(name, param) + local lines = {} + local privs = minetest.get_player_privs(name) + + -- Short (and fast to access) names + local cfg = areas.config + local self_prot = cfg.self_protection + local prot_priv = cfg.self_protection_privilege + local limit = cfg.self_protection_max_areas + local limit_high = cfg.self_protection_max_areas_high + local size_limit = cfg.self_protection_max_size + local size_limit_high = cfg.self_protection_max_size_high + + local has_high_limit = privs.areas_high_limit + local has_prot_priv = not prot_priv or privs[prot_priv] + local can_prot = privs.areas or (self_prot and has_prot_priv) + local max_count = can_prot and + (has_high_limit and limit_high or limit) or 0 + local max_size = has_high_limit and + size_limit_high or size_limit + + -- Privilege information + local self_prot_line = ("Self protection is %sabled"):format( + self_prot and "en" or "dis") + if self_prot and prot_priv then + self_prot_line = self_prot_line.. + (" %s have the neccessary privilege (%q).") + :format( + has_prot_priv and "and you" or + "but you don't", + prot_priv) + else + self_prot_line = self_prot_line.."." + end + table.insert(lines, self_prot_line) + if privs.areas then + table.insert(lines, "You are an area".. + " administrator (\"areas\" privilege).") + elseif has_high_limit then + table.insert(lines, + "You have extended area protection".. + " limits (\"areas_high_limit\" privilege).") + end + + -- Area count + local area_num = 0 + for id, area in pairs(areas.areas) do + if area.owner == name then + area_num = area_num + 1 + end + end + local count_line = ("You have %d area%s"):format( + area_num, area_num == 1 and "" or "s") + if privs.areas then + count_line = count_line.. + " and have no area protection limits." + elseif can_prot then + count_line = count_line..(", out of a maximum of %d.") + :format(max_count) + end + table.insert(lines, count_line) + + -- Area size limits + local function size_info(str, size) + table.insert(lines, ("%s spanning up to %dx%dx%d.") + :format(str, size.x, size.y, size.z)) + end + local function priv_limit_info(priv, max_count, max_size) + size_info(("Players with the %q privilege".. + " can protect up to %d areas"):format( + priv, max_count), max_size) + end + if self_prot then + if privs.areas then + priv_limit_info(prot_priv, + limit, size_limit) + priv_limit_info("areas_high_limit", + limit_high, size_limit_high) + elseif has_prot_priv then + size_info("You can protect areas", max_size) + end + end + + return true, table.concat(lines, "\n") + end, +}) + diff --git a/kingdoms_game/mods/areas/hud.lua b/kingdoms_game/mods/areas/hud.lua new file mode 100644 index 0000000..62bdf39 --- /dev/null +++ b/kingdoms_game/mods/areas/hud.lua @@ -0,0 +1,47 @@ +--[[ This is inspired by the landrush mod by Bremaweb + +areas.hud = {} + +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local pos = vector.round(player:getpos()) + local areaStrings = {} + for id, area in pairs(areas:getAreasAtPos(pos)) do + table.insert(areaStrings, ("%s [%u] (%s%s)") + :format(area.name, id, area.owner, + area.open and ":open" or "")) + end + local areaString = "Areas:" + if #areaStrings > 0 then + areaString = areaString.."\n".. + table.concat(areaStrings, "\n") + end + local hud = areas.hud[name] + if not hud then + hud = {} + areas.hud[name] = hud + hud.areasId = player:hud_add({ + hud_elem_type = "text", + name = "Areas", + number = 0xFFFFFF, + position = {x=0, y=1}, + offset = {x=8, y=-8}, + text = areaString, + scale = {x=200, y=60}, + alignment = {x=1, y=-1}, + }) + hud.oldAreas = areaString + return + elseif hud.oldAreas ~= areaString then + player:hud_change(hud.areasId, "text", areaString) + hud.oldAreas = areaString + end + end +end) + +minetest.register_on_leaveplayer(function(player) + areas.hud[player:get_player_name()] = nil +end) + +--]] \ No newline at end of file diff --git a/kingdoms_game/mods/areas/init.lua b/kingdoms_game/mods/areas/init.lua new file mode 100644 index 0000000..2c10cdd --- /dev/null +++ b/kingdoms_game/mods/areas/init.lua @@ -0,0 +1,39 @@ +-- Areas mod by ShadowNinja +-- Based on node_ownership +-- License: LGPLv2+ + +areas = {} + +areas.adminPrivs = {areas=true} +areas.startTime = os.clock() + +areas.modpath = minetest.get_modpath("areas") +dofile(areas.modpath.."/settings.lua") +dofile(areas.modpath.."/api.lua") +dofile(areas.modpath.."/internal.lua") +dofile(areas.modpath.."/chatcommands.lua") +dofile(areas.modpath.."/pos.lua") +dofile(areas.modpath.."/interact.lua") +dofile(areas.modpath.."/legacy.lua") +dofile(areas.modpath.."/hud.lua") + +areas:load() + +minetest.register_privilege("areas", { + description = "Can administer areas." +}) +minetest.register_privilege("areas_high_limit", { + description = "Can can more, bigger areas." +}) + +if not minetest.registered_privileges[areas.config.self_protection_privilege] then + minetest.register_privilege(areas.config.self_protection_privilege, { + description = "Can protect areas.", + }) +end + +if minetest.setting_getbool("log_mod") then + local diffTime = os.clock() - areas.startTime + minetest.log("action", "areas loaded in "..diffTime.."s.") +end + diff --git a/kingdoms_game/mods/areas/interact.lua b/kingdoms_game/mods/areas/interact.lua new file mode 100644 index 0000000..2e54800 --- /dev/null +++ b/kingdoms_game/mods/areas/interact.lua @@ -0,0 +1,19 @@ + +local old_is_protected = minetest.is_protected +function minetest.is_protected(pos, name) + if not areas:canInteract(pos, name) then + return true + end + return old_is_protected(pos, name) +end + +minetest.register_on_protection_violation(function(pos, name) + if not areas:canInteract(pos, name) then + local owners = areas:getNodeOwners(pos) + minetest.chat_send_player(name, + ("%s is protected by %s."):format( + minetest.pos_to_string(pos), + table.concat(owners, ", "))) + end +end) + diff --git a/kingdoms_game/mods/areas/internal.lua b/kingdoms_game/mods/areas/internal.lua new file mode 100644 index 0000000..ea94a27 --- /dev/null +++ b/kingdoms_game/mods/areas/internal.lua @@ -0,0 +1,265 @@ + +function areas:player_exists(name) + return minetest.auth_table[name] ~= nil +end + +-- Save the areas table to a file +function areas:save() + local datastr = minetest.serialize(self.areas) + if not datastr then + minetest.log("error", "[areas] Failed to serialize area data!") + return + end + local file, err = io.open(self.config.filename, "w") + if err then + return err + end + file:write(datastr) + file:close() +end + +-- Load the areas table from the save file +function areas:load() + local file, err = io.open(self.config.filename, "r") + if err then + self.areas = self.areas or {} + return err + end + self.areas = minetest.deserialize(file:read("*a")) + if type(self.areas) ~= "table" then + self.areas = {} + end + file:close() + self:populateStore() +end + +--- Checks an AreaStore ID. +-- Deletes the AreaStore (falling back to the iterative method) +-- and prints an error message if the ID is invalid. +-- @return Whether the ID was valid. +function areas:checkAreaStoreId(sid) + if not sid then + minetest.log("error", "AreaStore failed to find an ID for an " + .."area! Falling back to iterative area checking.") + self.store = nil + self.store_ids = nil + end + return sid and true or false +end + +-- Populates the AreaStore after loading, if needed. +function areas:populateStore() + if not rawget(_G, "AreaStore") then + return + end + local store = AreaStore() + local store_ids = {} + for id, area in pairs(areas.areas) do + local sid = store:insert_area(area.pos1, + area.pos2, tostring(id)) + if not self:checkAreaStoreId(sid) then + return + end + store_ids[id] = sid + end + self.store = store + self.store_ids = store_ids +end + +-- Finds the first usable index in a table +-- Eg: {[1]=false,[4]=true} -> 2 +local function findFirstUnusedIndex(t) + local i = 0 + repeat i = i + 1 + until t[i] == nil + return i +end + +--- Add a area. +-- @return The new area's ID. +function areas:add(owner, name, pos1, pos2, parent) + local id = findFirstUnusedIndex(self.areas) + self.areas[id] = { + name = name, + pos1 = pos1, + pos2 = pos2, + owner = owner, + parent = parent + } + -- Add to AreaStore + if self.store then + local sid = self.store:insert_area(pos1, pos2, tostring(id)) + if self:checkAreaStoreId(sid) then + self.store_ids[id] = sid + end + end + return id +end + +--- Remove a area, and optionally it's children recursively. +-- If a area is deleted non-recursively the children will +-- have the removed area's parent as their new parent. +function areas:remove(id, recurse) + if recurse then + -- Recursively find child entries and remove them + local cids = self:getChildren(id) + for _, cid in pairs(cids) do + self:remove(cid, true) + end + else + -- Update parents + local parent = self.areas[id].parent + local children = self:getChildren(id) + for _, cid in pairs(children) do + -- The subarea parent will be niled out if the + -- removed area does not have a parent + self.areas[cid].parent = parent + + end + end + + -- Remove main entry + self.areas[id] = nil + + -- Remove from AreaStore + if self.store then + self.store:remove_area(self.store_ids[id]) + self.store_ids[id] = nil + end +end + +-- Checks if a area between two points is entirely contained by another area +function areas:isSubarea(pos1, pos2, id) + local area = self.areas[id] + if not area then + return false + end + local p1, p2 = area.pos1, area.pos2 + if (pos1.x >= p1.x and pos1.x <= p2.x) and + (pos2.x >= p1.x and pos2.x <= p2.x) and + (pos1.y >= p1.y and pos1.y <= p2.y) and + (pos2.y >= p1.y and pos2.y <= p2.y) and + (pos1.z >= p1.z and pos1.z <= p2.z) and + (pos2.z >= p1.z and pos2.z <= p2.z) then + return true + end +end + +-- Returns a table (list) of children of an area given it's identifier +function areas:getChildren(id) + local children = {} + for cid, area in pairs(self.areas) do + if area.parent and area.parent == id then + table.insert(children, cid) + end + end + return children +end + +-- Checks if the user has sufficient privileges. +-- If the player is not a administrator it also checks +-- if the area intersects other areas that they do not own. +-- Also checks the size of the area and if the user already +-- has more than max_areas. +function areas:canPlayerAddArea(pos1, pos2, name) + local privs = minetest.get_player_privs(name) + if privs.areas then + return true + end + + -- Check self protection privilege, if it is enabled, + -- and if the area is too big. + if not self.config.self_protection or + not privs[areas.config.self_protection_privilege] then + return false, "Self protection is disabled or you do not have" + .." the necessary privilege." + end + + local max_size = privs.areas_high_limit and + self.config.self_protection_max_size_high or + self.config.self_protection_max_size + if + (pos2.x - pos1.x) > max_size.x or + (pos2.y - pos1.y) > max_size.y or + (pos2.z - pos1.z) > max_size.z then + return false, "Area is too big." + end + + -- Check number of areas the user has and make sure it not above the max + local count = 0 + for _, area in pairs(self.areas) do + if area.owner == name then + count = count + 1 + end + end + local max_areas = privs.areas_high_limit and + self.config.self_protection_max_areas_high or + self.config.self_protection_max_areas + if count >= max_areas then + return false, "You have reached the maximum amount of" + .." areas that you are allowed to protect." + end + + -- Check intersecting areas + local can, id = self:canInteractInArea(pos1, pos2, name) + if not can then + local area = self.areas[id] + return false, ("The area intersects with %s [%u] (%s).") + :format(area.name, id, area.owner) + end + + return true +end + +-- Given a id returns a string in the format: +-- "name [id]: owner (x1, y1, z1) (x2, y2, z2) -> children" +function areas:toString(id) + local area = self.areas[id] + local message = ("%s [%d]: %s %s %s"):format( + area.name, id, area.owner, + minetest.pos_to_string(area.pos1), + minetest.pos_to_string(area.pos2)) + + local children = areas:getChildren(id) + if #children > 0 then + message = message.." -> "..table.concat(children, ", ") + end + return message +end + +-- Re-order areas in table by their identifiers +function areas:sort() + local sa = {} + for k, area in pairs(self.areas) do + if not area.parent then + table.insert(sa, area) + local newid = #sa + for _, subarea in pairs(self.areas) do + if subarea.parent == k then + subarea.parent = newid + table.insert(sa, subarea) + end + end + end + end + self.areas = sa +end + +-- Checks if a player owns an area or a parent of it +function areas:isAreaOwner(id, name) + local cur = self.areas[id] + if cur and minetest.check_player_privs(name, self.adminPrivs) then + return true + end + while cur do + if cur.owner == name then + return true + elseif cur.parent then + cur = self.areas[cur.parent] + else + return false + end + end + return false +end + diff --git a/kingdoms_game/mods/areas/legacy.lua b/kingdoms_game/mods/areas/legacy.lua new file mode 100644 index 0000000..83b3d27 --- /dev/null +++ b/kingdoms_game/mods/areas/legacy.lua @@ -0,0 +1,138 @@ +-- This file contains functions to convert from +-- the old areas format and other compatability code. + +minetest.register_chatcommand("legacy_load_areas", { + params = "", + description = "Loads, converts, and saves the areas from" + .." a legacy save file.", + privs = {areas=true, server=true}, + func = function(name, param) + minetest.chat_send_player(name, "Converting areas...") + local version = tonumber(param) + if version == 0 then + err = areas:node_ownership_load() + if err then + minetest.chat_send_player(name, "Error loading legacy file: "..err) + return + end + else + minetest.chat_send_player(name, "Invalid version number. (0 allowed)") + return + end + minetest.chat_send_player(name, "Legacy file loaded.") + + for k, area in pairs(areas.areas) do + -- New position format + area.pos1 = {x=area.x1, y=area.y1, z=area.z1} + area.pos2 = {x=area.x2, y=area.y2, z=area.z2} + + area.x1, area.y1, area.z1, + area.x2, area.y2, area.z2 = + nil, nil, nil, nil, nil, nil + + -- Area positions sorting + areas:sortPos(area.pos1, area.pos2) + + -- Add name + area.name = "unnamed" + + -- Remove ID + area.id = nil + end + minetest.chat_send_player(name, "Table format updated.") + + areas:save() + minetest.chat_send_player(name, "Converted areas saved. Done.") + end +}) + +function areas:node_ownership_load() + local filename = minetest.get_worldpath().."/owners.tbl" + tables, err = loadfile(filename) + if err then + return err + end + + tables = tables() + for idx = 1, #tables do + local tolinkv, tolinki = {}, {} + for i, v in pairs(tables[idx]) do + if type(v) == "table" and tables[v[1]] then + table.insert(tolinkv, {i, tables[v[1]]}) + end + if type(i) == "table" and tables[i[1]] then + table.insert(tolinki, {i, tables[i[1]]}) + end + end + -- link values, first due to possible changes of indices + for _, v in ipairs(tolinkv) do + tables[idx][v[1]] = v[2] + end + -- link indices + for _, v in ipairs(tolinki) do + tables[idx][v[2]], tables[idx][v[1]] = tables[idx][v[1]], nil + end + end + self.areas = tables[1] +end + +-- Returns the name of the first player that owns an area +function areas.getNodeOwnerName(pos) + for id, area in pairs(areas:getAreasAtPos(pos)) do + return area.owner + end + return false +end + +-- Checks if a node is owned by you +function areas.isNodeOwner(pos, name) + if minetest.check_player_privs(name, areas.adminPrivs) then + return true + end + for id, area in pairs(areas:getAreasAtPos(pos)) do + if name == area.owner then + return true + end + end + return false +end + +-- Checks if an area has an owner +function areas.hasOwner(pos) + for id, area in pairs(areas:getAreasAtPos(pos)) do + return true + end + return false +end + +IsPlayerNodeOwner = areas.isNodeOwner +GetNodeOwnerName = areas.getNodeOwnerName +HasOwner = areas.hasOwner + +-- This is entirely untested and may break in strange and new ways. +if areas.config.legacy_table then + owner_defs = setmetatable({}, { + __index = function(table, key) + local a = rawget(areas.areas, key) + if not a then return a end + local b = {} + for k, v in pairs(a) do b[k] = v end + b.x1, b.y1, b.z1 = b.pos1.x, b.pos1.y, b.pos1.z + b.x2, b.y1, b.z2 = b.pos2.x, b.pos2.y, b.pos2.z + b.pos1, b.pos2 = nil, nil + b.id = key + return b + end, + __newindex = function(table, key, value) + local a = value + a.pos1, a.pos2 = {x=a.x1, y=a.y1, z=a.z1}, + {x=a.x2, y=a.y2, z=a.z2} + a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 = + nil, nil, nil, nil, nil, nil + a.name = a.name or "unnamed" + a.id = nil + return rawset(areas.areas, key, a) + end + }) +end + diff --git a/kingdoms_game/mods/areas/pos.lua b/kingdoms_game/mods/areas/pos.lua new file mode 100644 index 0000000..8d3e6fe --- /dev/null +++ b/kingdoms_game/mods/areas/pos.lua @@ -0,0 +1,255 @@ + +-- I could depend on WorldEdit for this, but you need to have the 'worldedit' +-- permission to use those commands and you don't have +-- /area_pos{1,2} [X Y Z|X,Y,Z]. +-- Since this is mostly copied from WorldEdit it is mostly +-- licensed under the AGPL. (select_area is a exception) + +areas.marker1 = {} +areas.marker2 = {} +areas.set_pos = {} +areas.pos1 = {} +areas.pos2 = {} + +minetest.register_chatcommand("select_area", { + params = "", + description = "Select a area by id.", + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see /help select_area." + end + if not areas.areas[id] then + return false, "The area "..id.." does not exist." + end + + areas:setPos1(name, areas.areas[id].pos1) + areas:setPos2(name, areas.areas[id].pos2) + return true, "Area "..id.." selected." + end, +}) + +minetest.register_chatcommand("area_pos1", { + params = "[X Y Z|X,Y,Z]", + description = "Set area protection region position 1 to your" + .." location or the one specified", + privs = {}, + func = function(name, param) + local pos = nil + local found, _, x, y, z = param:find( + "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$") + if found then + pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)} + elseif param == "" then + local player = minetest.get_player_by_name(name) + if player then + pos = player:getpos() + else + return false, "Unable to get position." + end + else + return false, "Invalid usage, see /help area_pos1." + end + pos = vector.round(pos) + areas:setPos1(name, pos) + return true, "Area position 1 set to " + ..minetest.pos_to_string(pos) + end, +}) + +minetest.register_chatcommand("area_pos2", { + params = "[X Y Z|X,Y,Z]", + description = "Set area protection region position 2 to your" + .." location or the one specified", + func = function(name, param) + local pos = nil + local found, _, x, y, z = param:find( + "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$") + if found then + pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)} + elseif param == "" then + local player = minetest.get_player_by_name(name) + if player then + pos = player:getpos() + else + return false, "Unable to get position." + end + else + return false, "Invalid usage, see /help area_pos2." + end + pos = vector.round(pos) + areas:setPos2(name, pos) + return true, "Area position 2 set to " + ..minetest.pos_to_string(pos) + end, +}) + + +minetest.register_chatcommand("area_pos", { + params = "set/set1/set2/get", + description = "Set area protection region, position 1, or position 2" + .." by punching nodes, or display the region", + func = function(name, param) + if param == "set" then -- Set both area positions + areas.set_pos[name] = "pos1" + return true, "Select positions by punching two nodes." + elseif param == "set1" then -- Set area position 1 + areas.set_pos[name] = "pos1only" + return true, "Select position 1 by punching a node." + elseif param == "set2" then -- Set area position 2 + areas.set_pos[name] = "pos2" + return true, "Select position 2 by punching a node." + elseif param == "get" then -- Display current area positions + local pos1str, pos2str = "Position 1: ", "Position 2: " + if areas.pos1[name] then + pos1str = pos1str..minetest.pos_to_string(areas.pos1[name]) + else + pos1str = pos1str.."" + end + if areas.pos2[name] then + pos2str = pos2str..minetest.pos_to_string(areas.pos2[name]) + else + pos2str = pos2str.."" + end + return true, pos1str.."\n"..pos2str + else + return false, "Unknown subcommand: "..param + end + end, +}) + +function areas:getPos(playerName) + local pos1, pos2 = areas.pos1[playerName], areas.pos2[playerName] + if not (pos1 and pos2) then + return nil + end + -- Copy positions so that the area table doesn't contain multiple + -- references to the same position. + pos1, pos2 = vector.new(pos1), vector.new(pos2) + return areas:sortPos(pos1, pos2) +end + +function areas:setPos1(playerName, pos) + areas.pos1[playerName] = pos + areas.markPos1(playerName) +end + +function areas:setPos2(playerName, pos) + areas.pos2[playerName] = pos + areas.markPos2(playerName) +end + + +minetest.register_on_punchnode(function(pos, node, puncher) + local name = puncher:get_player_name() + -- Currently setting position + if name ~= "" and areas.set_pos[name] then + if areas.set_pos[name] == "pos1" then + areas.pos1[name] = pos + areas.markPos1(name) + areas.set_pos[name] = "pos2" + minetest.chat_send_player(name, + "Position 1 set to " + ..minetest.pos_to_string(pos)) + elseif areas.set_pos[name] == "pos1only" then + areas.pos1[name] = pos + areas.markPos1(name) + areas.set_pos[name] = nil + minetest.chat_send_player(name, + "Position 1 set to " + ..minetest.pos_to_string(pos)) + elseif areas.set_pos[name] == "pos2" then + areas.pos2[name] = pos + areas.markPos2(name) + areas.set_pos[name] = nil + minetest.chat_send_player(name, + "Position 2 set to " + ..minetest.pos_to_string(pos)) + end + end +end) + +-- Modifies positions `pos1` and `pos2` so that each component of `pos1` +-- is less than or equal to its corresponding component of `pos2`, +-- returning the two positions. +function areas:sortPos(pos1, pos2) + if pos1.x > pos2.x then + pos2.x, pos1.x = pos1.x, pos2.x + end + if pos1.y > pos2.y then + pos2.y, pos1.y = pos1.y, pos2.y + end + if pos1.z > pos2.z then + pos2.z, pos1.z = pos1.z, pos2.z + end + return pos1, pos2 +end + +-- Marks area position 1 +areas.markPos1 = function(name) + local pos = areas.pos1[name] + if areas.marker1[name] ~= nil then -- Marker already exists + areas.marker1[name]:remove() -- Remove marker + areas.marker1[name] = nil + end + if pos ~= nil then -- Add marker + areas.marker1[name] = minetest.add_entity(pos, "areas:pos1") + areas.marker1[name]:get_luaentity().active = true + end +end + +-- Marks area position 2 +areas.markPos2 = function(name) + local pos = areas.pos2[name] + if areas.marker2[name] ~= nil then -- Marker already exists + areas.marker2[name]:remove() -- Remove marker + areas.marker2[name] = nil + end + if pos ~= nil then -- Add marker + areas.marker2[name] = minetest.add_entity(pos, "areas:pos2") + areas.marker2[name]:get_luaentity().active = true + end +end + +minetest.register_entity("areas:pos1", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"areas_pos1.png", "areas_pos1.png", + "areas_pos1.png", "areas_pos1.png", + "areas_pos1.png", "areas_pos1.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + }, + on_step = function(self, dtime) + if self.active == nil then + self.object:remove() + end + end, + on_punch = function(self, hitter) + self.object:remove() + local name = hitter:get_player_name() + areas.marker1[name] = nil + end, +}) + +minetest.register_entity("areas:pos2", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"areas_pos2.png", "areas_pos2.png", + "areas_pos2.png", "areas_pos2.png", + "areas_pos2.png", "areas_pos2.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + }, + on_step = function(self, dtime) + if self.active == nil then + self.object:remove() + end + end, + on_punch = function(self, hitter) + self.object:remove() + local name = hitter:get_player_name() + areas.marker2[name] = nil + end, +}) + diff --git a/kingdoms_game/mods/areas/settings.lua b/kingdoms_game/mods/areas/settings.lua new file mode 100644 index 0000000..140a655 --- /dev/null +++ b/kingdoms_game/mods/areas/settings.lua @@ -0,0 +1,43 @@ +local world_path = minetest.get_worldpath() + +areas.config = {} + +local function setting(tp, name, default) + local full_name = "areas."..name + local value + if tp == "boolean" then + value = minetest.setting_getbool(full_name) + elseif tp == "string" then + value = minetest.setting_get(full_name) + elseif tp == "position" then + value = minetest.setting_get_pos(full_name) + elseif tp == "number" then + value = tonumber(minetest.setting_get(full_name)) + else + error("Invalid setting type!") + end + if value == nil then + value = default + end + areas.config[name] = value +end + +-------------- +-- Settings -- +-------------- + +setting("string", "filename", world_path.."/areas.dat") + +-- Allow players with a privilege create their own areas +-- within the maximum size and number. +setting("boolean", "self_protection", false) +setting("string", "self_protection_privilege", "interact") +setting("position", "self_protection_max_size", {x=64, y=128, z=64}) +setting("number", "self_protection_max_areas", 4) +-- For players with the areas_high_limit privilege. +setting("position", "self_protection_max_size_high", {x=512, y=512, z=512}) +setting("number", "self_protection_max_areas_high", 32) + +-- legacy_table (owner_defs) compatibility. Untested and has known issues. +setting("boolean", "legacy_table", false) + diff --git a/kingdoms_game/mods/areas/textures/areas_pos1.png b/kingdoms_game/mods/areas/textures/areas_pos1.png new file mode 100644 index 0000000..4c304aa Binary files /dev/null and b/kingdoms_game/mods/areas/textures/areas_pos1.png differ diff --git a/kingdoms_game/mods/areas/textures/areas_pos2.png b/kingdoms_game/mods/areas/textures/areas_pos2.png new file mode 100644 index 0000000..1502f16 Binary files /dev/null and b/kingdoms_game/mods/areas/textures/areas_pos2.png differ diff --git a/kingdoms_game/mods/bandages/README.md b/kingdoms_game/mods/bandages/README.md new file mode 100644 index 0000000..77134fc --- /dev/null +++ b/kingdoms_game/mods/bandages/README.md @@ -0,0 +1,16 @@ +Minetest 0.4 mod: bandages +========================= + +License of source code: +----------------------- +Andrey's mod for minetest + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +http://www.gnu.org/licenses/lgpl-2.1.html + + +Bandages can be used to heal other players, but not yourself. diff --git a/kingdoms_game/mods/bandages/depends.txt b/kingdoms_game/mods/bandages/depends.txt new file mode 100644 index 0000000..470ec30 --- /dev/null +++ b/kingdoms_game/mods/bandages/depends.txt @@ -0,0 +1,2 @@ +default +wool diff --git a/kingdoms_game/mods/bandages/init.lua b/kingdoms_game/mods/bandages/init.lua new file mode 100644 index 0000000..caccc4d --- /dev/null +++ b/kingdoms_game/mods/bandages/init.lua @@ -0,0 +1,91 @@ +-- Minetest 0.4 mod: bandages +-- +-- See README.txt for licensing and other information. + +minetest.register_craftitem("bandages:bandage_1", { + range = 1, + description = "Simple bandage", + inventory_image = "bandage_1.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "object" then + local object = pointed_thing.ref + if object:is_player() then + local hp=object:get_hp() + if hp > 0 and hp+1 < 20 then + object:set_hp(hp+2) + itemstack:take_item() + return itemstack + end + else + minetest.log("error", "not player!") + end + else + minetest.log("error", "not object!") + end + end, +}) + +minetest.register_craft({ + output = 'bandages:bandage_1', + recipe = { + {'', '', ''}, + {'default:paper', 'default:paper', 'default:paper'}, + {'', '', ''}, + } +}) + +minetest.register_craftitem("bandages:bandage_2", { + range = 1, + description = "Bandage", + inventory_image = "bandage_2.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "object" then + local object = pointed_thing.ref + if object:is_player() then + local hp=object:get_hp() + if hp > 0 and hp+3 < 20 then + object:set_hp(hp+6) + itemstack:take_item() + return itemstack + end + end + end + end, +}) + +minetest.register_craft({ + output = 'bandages:bandage_2', + recipe = { + {'', '', ''}, + {'default:paper', 'default:leaves', 'default:paper'}, + {'', '', ''}, + } +}) + +minetest.register_craftitem("bandages:bandage_3", { + range = 1, + description = "Advanced bandage", + inventory_image = "bandage_3.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "object" then + local object = pointed_thing.ref + if object:is_player() then + local hp=object:get_hp() + if hp > 0 and hp+5 < 20 then + object:set_hp(hp+8) + itemstack:take_item() + return itemstack + end + end + end + end, +}) + +minetest.register_craft({ + output = 'bandages:bandage_3', + recipe = { + {'', '', ''}, + {'default:paper', 'wool:white', 'default:paper'}, + {'', '', ''}, + } +}) \ No newline at end of file diff --git a/kingdoms_game/mods/bandages/textures/bandage_1.png b/kingdoms_game/mods/bandages/textures/bandage_1.png new file mode 100644 index 0000000..3afd76e Binary files /dev/null and b/kingdoms_game/mods/bandages/textures/bandage_1.png differ diff --git a/kingdoms_game/mods/bandages/textures/bandage_2.png b/kingdoms_game/mods/bandages/textures/bandage_2.png new file mode 100644 index 0000000..28f39d4 Binary files /dev/null and b/kingdoms_game/mods/bandages/textures/bandage_2.png differ diff --git a/kingdoms_game/mods/bandages/textures/bandage_3.png b/kingdoms_game/mods/bandages/textures/bandage_3.png new file mode 100644 index 0000000..d25c880 Binary files /dev/null and b/kingdoms_game/mods/bandages/textures/bandage_3.png differ diff --git a/kingdoms_game/mods/beds/README.txt b/kingdoms_game/mods/beds/README.txt new file mode 100644 index 0000000..9710c45 --- /dev/null +++ b/kingdoms_game/mods/beds/README.txt @@ -0,0 +1,30 @@ +Minetest Game mod: beds +======================= +by BlockMen (c) 2014-2015 + +Version: 1.1.1 + +About +~~~~~ +This mod adds a bed to Minetest which allows to skip the night. To sleep rightclick the bed, if playing +in singleplayer mode the night gets skipped imideatly. If playing on server you get shown how many other +players are in bed too. If all players are sleeping the night gets skipped aswell. Also the night skip can be forced +if more than 50% of the players are lying in bed and use this option. + +Another feature is a controled respawning. If you have slept in bed (not just lying in it) your respawn point +is set to the beds location and you will respawn there after death. +You can disable the respawn at beds by setting "enable_bed_respawn = false" in minetest.conf +You can also disable the night skip feature by setting "enable_bed_night_skip = false" in minetest.conf or by using +the /set command ingame. + + +License of source code, textures: WTFPL +--------------------------------------- +(c) Copyright BlockMen (2014-2015) + + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://sam.zoy.org/wtfpl/COPYING for more details. diff --git a/kingdoms_game/mods/beds/api.lua b/kingdoms_game/mods/beds/api.lua new file mode 100644 index 0000000..0c27c4e --- /dev/null +++ b/kingdoms_game/mods/beds/api.lua @@ -0,0 +1,110 @@ +function beds.register_bed(name, def) + minetest.register_node(name .. "_bottom", { + description = def.description, + inventory_image = def.inventory_image, + wield_image = def.wield_image, + drawtype = "nodebox", + tiles = def.tiles.bottom, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + stack_max = 1, + groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1}, + sounds = default.node_sound_wood_defaults(), + node_box = { + type = "fixed", + fixed = def.nodebox.bottom, + }, + selection_box = { + type = "fixed", + fixed = def.selectionbox, + }, + + after_place_node = function(pos, placer, itemstack) + local n = minetest.get_node_or_nil(pos) + if not n or not n.param2 then + minetest.remove_node(pos) + return true + end + local dir = minetest.facedir_to_dir(n.param2) + local p = vector.add(pos, dir) + local n2 = minetest.get_node_or_nil(p) + local def = n2 and minetest.registered_items[n2.name] + if not def or not def.buildable_to then + minetest.remove_node(pos) + return true + end + minetest.set_node(p, {name = n.name:gsub("%_bottom", "_top"), param2 = n.param2}) + return false + end, + + on_destruct = function(pos) + local n = minetest.get_node_or_nil(pos) + if not n then return end + local dir = minetest.facedir_to_dir(n.param2) + local p = vector.add(pos, dir) + local n2 = minetest.get_node(p) + if minetest.get_item_group(n2.name, "bed") == 2 and n.param2 == n2.param2 then + minetest.remove_node(p) + end + end, + + on_rightclick = function(pos, node, clicker) + beds.on_rightclick(pos, clicker) + end, + + on_rotate = function(pos, node, user, mode, new_param2) + local dir = minetest.facedir_to_dir(node.param2) + local p = vector.add(pos, dir) + local node2 = minetest.get_node_or_nil(p) + if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or + not node.param2 == node2.param2 then + return false + end + if minetest.is_protected(p, user:get_player_name()) then + minetest.record_protection_violation(p, user:get_player_name()) + return false + end + if mode ~= screwdriver.ROTATE_FACE then + return false + end + local newp = vector.add(pos, minetest.facedir_to_dir(new_param2)) + local node3 = minetest.get_node_or_nil(newp) + local def = node3 and minetest.registered_nodes[node3.name] + if not def or not def.buildable_to then + return false + end + if minetest.is_protected(newp, user:get_player_name()) then + minetest.record_protection_violation(newp, user:get_player_name()) + return false + end + node.param2 = new_param2 + minetest.swap_node(pos, node) + minetest.remove_node(p) + minetest.set_node(newp, {name = node.name:gsub("%_bottom", "_top"), param2 = new_param2}) + return true + end, + }) + + minetest.register_node(name .. "_top", { + drawtype = "nodebox", + tiles = def.tiles.top, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + pointable = false, + groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2}, + sounds = default.node_sound_wood_defaults(), + node_box = { + type = "fixed", + fixed = def.nodebox.top, + }, + }) + + minetest.register_alias(name, name .. "_bottom") + + minetest.register_craft({ + output = name, + recipe = def.recipe + }) +end diff --git a/kingdoms_game/mods/beds/beds.lua b/kingdoms_game/mods/beds/beds.lua new file mode 100644 index 0000000..5f31f13 --- /dev/null +++ b/kingdoms_game/mods/beds/beds.lua @@ -0,0 +1,90 @@ +-- Fancy shaped bed + +beds.register_bed("beds:fancy_bed", { + description = "Fancy Bed", + inventory_image = "beds_bed_fancy.png", + wield_image = "beds_bed_fancy.png", + tiles = { + bottom = { + "beds_bed_top1.png", + "default_wood.png", + "beds_bed_side1.png", + "beds_bed_side1.png^[transformFX", + "default_wood.png", + "beds_bed_foot.png", + }, + top = { + "beds_bed_top2.png", + "default_wood.png", + "beds_bed_side2.png", + "beds_bed_side2.png^[transformFX", + "beds_bed_head.png", + "default_wood.png", + } + }, + nodebox = { + bottom = { + {-0.5, -0.5, -0.5, -0.375, -0.065, -0.4375}, + {0.375, -0.5, -0.5, 0.5, -0.065, -0.4375}, + {-0.5, -0.375, -0.5, 0.5, -0.125, -0.4375}, + {-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5}, + {0.4375, -0.375, -0.5, 0.5, -0.125, 0.5}, + {-0.4375, -0.3125, -0.4375, 0.4375, -0.0625, 0.5}, + }, + top = { + {-0.5, -0.5, 0.4375, -0.375, 0.1875, 0.5}, + {0.375, -0.5, 0.4375, 0.5, 0.1875, 0.5}, + {-0.5, 0, 0.4375, 0.5, 0.125, 0.5}, + {-0.5, -0.375, 0.4375, 0.5, -0.125, 0.5}, + {-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5}, + {0.4375, -0.375, -0.5, 0.5, -0.125, 0.5}, + {-0.4375, -0.3125, -0.5, 0.4375, -0.0625, 0.4375}, + } + }, + selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5}, + recipe = { + {"", "", "group:stick"}, + {"wool:red", "wool:red", "wool:white"}, + {"group:wood", "group:wood", "group:wood"}, + }, +}) + +-- Simple shaped bed + +beds.register_bed("beds:bed", { + description = "Simple Bed", + inventory_image = "beds_bed.png", + wield_image = "beds_bed.png", + tiles = { + bottom = { + "beds_bed_top_bottom.png^[transformR90", + "default_wood.png", + "beds_bed_side_bottom_r.png", + "beds_bed_side_bottom_r.png^[transformfx", + "beds_transparent.png", + "beds_bed_side_bottom.png" + }, + top = { + "beds_bed_top_top.png^[transformR90", + "default_wood.png", + "beds_bed_side_top_r.png", + "beds_bed_side_top_r.png^[transformfx", + "beds_bed_side_top.png", + "beds_transparent.png", + } + }, + nodebox = { + bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + }, + selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5}, + recipe = { + {"wool:red", "wool:red", "wool:white"}, + {"group:wood", "group:wood", "group:wood"} + }, +}) + +-- Aliases for PilzAdam's beds mod + +minetest.register_alias("beds:bed_bottom_red", "beds:bed_bottom") +minetest.register_alias("beds:bed_top_red", "beds:bed_top") diff --git a/kingdoms_game/mods/beds/depends.txt b/kingdoms_game/mods/beds/depends.txt new file mode 100644 index 0000000..470ec30 --- /dev/null +++ b/kingdoms_game/mods/beds/depends.txt @@ -0,0 +1,2 @@ +default +wool diff --git a/kingdoms_game/mods/beds/functions.lua b/kingdoms_game/mods/beds/functions.lua new file mode 100644 index 0000000..ae8e5af --- /dev/null +++ b/kingdoms_game/mods/beds/functions.lua @@ -0,0 +1,227 @@ +local pi = math.pi +local player_in_bed = 0 +local is_sp = minetest.is_singleplayer() +local enable_respawn = minetest.setting_getbool("enable_bed_respawn") +if enable_respawn == nil then + enable_respawn = true +end + +-- Helper functions + +local function get_look_yaw(pos) + local n = minetest.get_node(pos) + if n.param2 == 1 then + return pi / 2, n.param2 + elseif n.param2 == 3 then + return -pi / 2, n.param2 + elseif n.param2 == 0 then + return pi, n.param2 + else + return 0, n.param2 + end +end + +local function is_night_skip_enabled() + local enable_night_skip = minetest.setting_getbool("enable_bed_night_skip") + if enable_night_skip == nil then + enable_night_skip = true + end + return enable_night_skip +end + +local function check_in_beds(players) + local in_bed = beds.player + if not players then + players = minetest.get_connected_players() + end + + for n, player in ipairs(players) do + local name = player:get_player_name() + if not in_bed[name] then + return false + end + end + + return #players > 0 +end + +local function lay_down(player, pos, bed_pos, state, skip) + local name = player:get_player_name() + local hud_flags = player:hud_get_flags() + + if not player or not name then + return + end + + -- stand up + if state ~= nil and not state then + local p = beds.pos[name] or nil + if beds.player[name] ~= nil then + beds.player[name] = nil + player_in_bed = player_in_bed - 1 + end + -- skip here to prevent sending player specific changes (used for leaving players) + if skip then + return + end + if p then + player:setpos(p) + end + + -- physics, eye_offset, etc + player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + player:set_look_yaw(math.random(1, 180) / 100) + default.player_attached[name] = false +-- player:set_physics_override(1, 1, 1) + hud_flags.wielditem = true + default.player_set_animation(player, "stand" , 30) + + -- lay down + else + beds.player[name] = 1 + beds.pos[name] = pos + player_in_bed = player_in_bed + 1 + + -- physics, eye_offset, etc + player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0}) + local yaw, param2 = get_look_yaw(bed_pos) + player:set_look_yaw(yaw) + local dir = minetest.facedir_to_dir(param2) + local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2} +-- player:set_physics_override(0, 0, 0) + player:setpos(p) + default.player_attached[name] = true + hud_flags.wielditem = false + default.player_set_animation(player, "lay" , 0) + end + + player:hud_set_flags(hud_flags) +end + +local function update_formspecs(finished) + local ges = #minetest.get_connected_players() + local form_n = "" + local is_majority = (ges / 2) < player_in_bed + + if finished then + form_n = beds.formspec .. "label[2.7,11; Good morning.]" + else + form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) .. + " of " .. tostring(ges) .. " players are in bed]" + if is_majority and is_night_skip_enabled() then + form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night skip]" + end + end + + for name,_ in pairs(beds.player) do + minetest.show_formspec(name, "beds_form", form_n) + end +end + + +-- Public functions + +function beds.kick_players() + for name, _ in pairs(beds.player) do + local player = minetest.get_player_by_name(name) + lay_down(player, nil, nil, false) + end +end + +function beds.skip_night() + minetest.set_timeofday(0.23) + beds.set_spawns() +end + +function beds.on_rightclick(pos, player) + local name = player:get_player_name() + local ppos = player:getpos() + local tod = minetest.get_timeofday() + + if tod > 0.2 and tod < 0.805 then + if beds.player[name] then + lay_down(player, nil, nil, false) + end + minetest.chat_send_player(name, "You can only sleep at night.") + return + end + + -- move to bed + if not beds.player[name] then + lay_down(player, ppos, pos) + else + lay_down(player, nil, nil, false) + end + + if not is_sp then + update_formspecs(false) + end + + -- skip the night and let all players stand up + if check_in_beds() then + minetest.after(2, function() + if not is_sp then + update_formspecs(is_night_skip_enabled()) + end + if is_night_skip_enabled() then + beds.skip_night() + beds.kick_players() + end + end) + end +end + + +-- Callbacks + +minetest.register_on_joinplayer(function(player) + beds.read_spawns() +end) + +-- respawn player at bed if enabled and valid position is found +minetest.register_on_respawnplayer(function(player) + if not enable_respawn then + return false + end + local name = player:get_player_name() + local pos = beds.spawn[name] or nil + if pos then + if not minetest.is_protected(pos, name) then + player:setpos(pos) + return true + end + end +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + lay_down(player, nil, nil, false, true) + beds.player[name] = nil + if check_in_beds() then + minetest.after(2, function() + update_formspecs(is_night_skip_enabled()) + if is_night_skip_enabled() then + beds.skip_night() + beds.kick_players() + end + end) + end +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "beds_form" then + return + end + if fields.quit or fields.leave then + lay_down(player, nil, nil, false) + update_formspecs(false) + end + + if fields.force then + update_formspecs(is_night_skip_enabled()) + if is_night_skip_enabled() then + beds.skip_night() + beds.kick_players() + end + end +end) diff --git a/kingdoms_game/mods/beds/init.lua b/kingdoms_game/mods/beds/init.lua new file mode 100644 index 0000000..8b25890 --- /dev/null +++ b/kingdoms_game/mods/beds/init.lua @@ -0,0 +1,17 @@ +beds = {} +beds.player = {} +beds.pos = {} +beds.spawn = {} + +beds.formspec = "size[8,15;true]" .. + "bgcolor[#080808BB; true]" .. + "button_exit[2,12;4,0.75;leave;Leave Bed]" + +local modpath = minetest.get_modpath("beds") + +-- Load files + +dofile(modpath .. "/functions.lua") +dofile(modpath .. "/api.lua") +dofile(modpath .. "/beds.lua") +dofile(modpath .. "/spawns.lua") diff --git a/kingdoms_game/mods/beds/spawns.lua b/kingdoms_game/mods/beds/spawns.lua new file mode 100644 index 0000000..14ec75b --- /dev/null +++ b/kingdoms_game/mods/beds/spawns.lua @@ -0,0 +1,58 @@ +local world_path = minetest.get_worldpath() +local org_file = world_path .. "/beds_spawns" +local file = world_path .. "/beds_spawns" +local bkwd = false + +-- check for PA's beds mod spawns +local cf = io.open(world_path .. "/beds_player_spawns", "r") +if cf ~= nil then + io.close(cf) + file = world_path .. "/beds_player_spawns" + bkwd = true +end + +function beds.read_spawns() + local spawns = beds.spawn + local input = io.open(file, "r") + if input and not bkwd then + repeat + local x = input:read("*n") + if x == nil then + break + end + local y = input:read("*n") + local z = input:read("*n") + local name = input:read("*l") + spawns[name:sub(2)] = {x = x, y = y, z = z} + until input:read(0) == nil + io.close(input) + elseif input and bkwd then + beds.spawn = minetest.deserialize(input:read("*all")) + input:close() + beds.save_spawns() + os.rename(file, file .. ".backup") + file = org_file + else + spawns = {} + end +end + +function beds.save_spawns() + if not beds.spawn then + return + end + local output = io.open(org_file, "w") + for i, v in pairs(beds.spawn) do + output:write(v.x .. " " .. v.y .. " " .. v.z .. " " .. i .. "\n") + end + io.close(output) +end + +function beds.set_spawns() + for name,_ in pairs(beds.player) do + local player = minetest.get_player_by_name(name) + local p = player:getpos() + beds.spawn[name] = p + end + beds.save_spawns() +end diff --git a/kingdoms_game/mods/beds/textures/beds_bed.png b/kingdoms_game/mods/beds/textures/beds_bed.png new file mode 100644 index 0000000..5c0054c Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_fancy.png b/kingdoms_game/mods/beds/textures/beds_bed_fancy.png new file mode 100644 index 0000000..4f9e8a7 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_fancy.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_foot.png b/kingdoms_game/mods/beds/textures/beds_bed_foot.png new file mode 100644 index 0000000..74d84c8 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_foot.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_head.png b/kingdoms_game/mods/beds/textures/beds_bed_head.png new file mode 100644 index 0000000..763f5e1 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_head.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side1.png b/kingdoms_game/mods/beds/textures/beds_bed_side1.png new file mode 100644 index 0000000..1ed8158 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side1.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side2.png b/kingdoms_game/mods/beds/textures/beds_bed_side2.png new file mode 100644 index 0000000..9d1384d Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side2.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side_bottom.png b/kingdoms_game/mods/beds/textures/beds_bed_side_bottom.png new file mode 100644 index 0000000..99ff309 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side_bottom.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side_bottom_r.png b/kingdoms_game/mods/beds/textures/beds_bed_side_bottom_r.png new file mode 100644 index 0000000..6f870e8 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side_bottom_r.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side_top.png b/kingdoms_game/mods/beds/textures/beds_bed_side_top.png new file mode 100644 index 0000000..b2807c5 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side_top.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_side_top_r.png b/kingdoms_game/mods/beds/textures/beds_bed_side_top_r.png new file mode 100644 index 0000000..429ad7d Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_side_top_r.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_top1.png b/kingdoms_game/mods/beds/textures/beds_bed_top1.png new file mode 100644 index 0000000..b6fcc2c Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_top1.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_top2.png b/kingdoms_game/mods/beds/textures/beds_bed_top2.png new file mode 100644 index 0000000..2fe5bf2 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_top2.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_top_bottom.png b/kingdoms_game/mods/beds/textures/beds_bed_top_bottom.png new file mode 100644 index 0000000..9b78be6 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_top_bottom.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_bed_top_top.png b/kingdoms_game/mods/beds/textures/beds_bed_top_top.png new file mode 100644 index 0000000..e877c80 Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_bed_top_top.png differ diff --git a/kingdoms_game/mods/beds/textures/beds_transparent.png b/kingdoms_game/mods/beds/textures/beds_transparent.png new file mode 100644 index 0000000..2dc0e3d Binary files /dev/null and b/kingdoms_game/mods/beds/textures/beds_transparent.png differ diff --git a/kingdoms_game/mods/boats/README.txt b/kingdoms_game/mods/boats/README.txt new file mode 100644 index 0000000..1de7167 --- /dev/null +++ b/kingdoms_game/mods/boats/README.txt @@ -0,0 +1,16 @@ +Minetest Game mod: boats +======================== +by PilzAdam + +License of source code: +----------------------- +WTFPL + +License of media (textures and sounds): +--------------------------------------- +WTFPL + +Authors of media files: +----------------------- +textures: Zeg9 +model: thetoon and Zeg9, modified by PavelS(SokolovPavel) diff --git a/kingdoms_game/mods/boats/depends.txt b/kingdoms_game/mods/boats/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/kingdoms_game/mods/boats/depends.txt @@ -0,0 +1 @@ +default diff --git a/kingdoms_game/mods/boats/init.lua b/kingdoms_game/mods/boats/init.lua new file mode 100644 index 0000000..a85f6e1 --- /dev/null +++ b/kingdoms_game/mods/boats/init.lua @@ -0,0 +1,247 @@ +-- +-- Helper functions +-- + +local function is_water(pos) + local nn = minetest.get_node(pos).name + return minetest.get_item_group(nn, "water") ~= 0 +end + + +local function get_sign(i) + if i == 0 then + return 0 + else + return i / math.abs(i) + end +end + + +local function get_velocity(v, yaw, y) + local x = -math.sin(yaw) * v + local z = math.cos(yaw) * v + return {x = x, y = y, z = z} +end + + +local function get_v(v) + return math.sqrt(v.x ^ 2 + v.z ^ 2) +end + +-- +-- Boat entity +-- + +local boat = { + physical = true, + collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5}, + visual = "mesh", + mesh = "boats_boat.obj", + textures = {"default_wood.png"}, + + driver = nil, + v = 0, + last_v = 0, + removed = false +} + + +function boat.on_rightclick(self, clicker) + if not clicker or not clicker:is_player() then + return + end + local name = clicker:get_player_name() + if self.driver and clicker == self.driver then + self.driver = nil + clicker:set_detach() + default.player_attached[name] = false + default.player_set_animation(clicker, "stand" , 30) + local pos = clicker:getpos() + pos = {x = pos.x, y = pos.y + 0.2, z = pos.z} + minetest.after(0.1, function() + clicker:setpos(pos) + end) + elseif not self.driver then + local attach = clicker:get_attach() + if attach and attach:get_luaentity() then + local luaentity = attach:get_luaentity() + if luaentity.driver then + luaentity.driver = nil + end + clicker:set_detach() + end + self.driver = clicker + clicker:set_attach(self.object, "", + {x = 0, y = 11, z = -3}, {x = 0, y = 0, z = 0}) + default.player_attached[name] = true + minetest.after(0.2, function() + default.player_set_animation(clicker, "sit" , 30) + end) + self.object:setyaw(clicker:get_look_yaw() - math.pi / 2) + end +end + + +function boat.on_activate(self, staticdata, dtime_s) + self.object:set_armor_groups({immortal = 1}) + if staticdata then + self.v = tonumber(staticdata) + end + self.last_v = self.v +end + + +function boat.get_staticdata(self) + return tostring(self.v) +end + + +function boat.on_punch(self, puncher) + if not puncher or not puncher:is_player() or self.removed then + return + end + if self.driver and puncher == self.driver then + self.driver = nil + puncher:set_detach() + default.player_attached[puncher:get_player_name()] = false + end + if not self.driver then + self.removed = true + -- delay remove to ensure player is detached + minetest.after(0.1, function() + self.object:remove() + end) + if not minetest.setting_getbool("creative_mode") then + local inv = puncher:get_inventory() + if inv:room_for_item("main", "boats:boat") then + inv:add_item("main", "boats:boat") + else + minetest.add_item(self.object:getpos(), "boats:boat") + end + end + end +end + + +function boat.on_step(self, dtime) + self.v = get_v(self.object:getvelocity()) * get_sign(self.v) + if self.driver then + local ctrl = self.driver:get_player_control() + local yaw = self.object:getyaw() + if ctrl.up then + self.v = self.v + 0.1 + elseif ctrl.down then + self.v = self.v - 0.1 + end + if ctrl.left then + if self.v < 0 then + self.object:setyaw(yaw - (1 + dtime) * 0.03) + else + self.object:setyaw(yaw + (1 + dtime) * 0.03) + end + elseif ctrl.right then + if self.v < 0 then + self.object:setyaw(yaw + (1 + dtime) * 0.03) + else + self.object:setyaw(yaw - (1 + dtime) * 0.03) + end + end + end + local velo = self.object:getvelocity() + if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then + self.object:setpos(self.object:getpos()) + return + end + local s = get_sign(self.v) + self.v = self.v - 0.02 * s + if s ~= get_sign(self.v) then + self.object:setvelocity({x = 0, y = 0, z = 0}) + self.v = 0 + return + end + if math.abs(self.v) > 4.5 then + self.v = 4.5 * get_sign(self.v) + end + + local p = self.object:getpos() + p.y = p.y - 0.5 + local new_velo = {x = 0, y = 0, z = 0} + local new_acce = {x = 0, y = 0, z = 0} + if not is_water(p) then + local nodedef = minetest.registered_nodes[minetest.get_node(p).name] + if (not nodedef) or nodedef.walkable then + self.v = 0 + new_acce = {x = 0, y = 1, z = 0} + else + new_acce = {x = 0, y = -9.8, z = 0} + end + new_velo = get_velocity(self.v, self.object:getyaw(), + self.object:getvelocity().y) + self.object:setpos(self.object:getpos()) + else + p.y = p.y + 1 + if is_water(p) then + local y = self.object:getvelocity().y + if y >= 4.5 then + y = 4.5 + elseif y < 0 then + new_acce = {x = 0, y = 20, z = 0} + else + new_acce = {x = 0, y = 5, z = 0} + end + new_velo = get_velocity(self.v, self.object:getyaw(), y) + self.object:setpos(self.object:getpos()) + else + new_acce = {x = 0, y = 0, z = 0} + if math.abs(self.object:getvelocity().y) < 1 then + local pos = self.object:getpos() + pos.y = math.floor(pos.y) + 0.5 + self.object:setpos(pos) + new_velo = get_velocity(self.v, self.object:getyaw(), 0) + else + new_velo = get_velocity(self.v, self.object:getyaw(), + self.object:getvelocity().y) + self.object:setpos(self.object:getpos()) + end + end + end + self.object:setvelocity(new_velo) + self.object:setacceleration(new_acce) +end + + +minetest.register_entity("boats:boat", boat) + + +minetest.register_craftitem("boats:boat", { + description = "Boat", + inventory_image = "boats_inventory.png", + wield_image = "boats_wield.png", + wield_scale = {x = 2, y = 2, z = 1}, + liquids_pointable = true, + + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return + end + if not is_water(pointed_thing.under) then + return + end + pointed_thing.under.y = pointed_thing.under.y + 0.5 + minetest.add_entity(pointed_thing.under, "boats:boat") + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end, +}) + + +minetest.register_craft({ + output = "boats:boat", + recipe = { + {"", "", "" }, + {"group:wood", "", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, + }, +}) diff --git a/kingdoms_game/mods/boats/models/boats_boat.obj b/kingdoms_game/mods/boats/models/boats_boat.obj new file mode 100644 index 0000000..8c3424f --- /dev/null +++ b/kingdoms_game/mods/boats/models/boats_boat.obj @@ -0,0 +1,3111 @@ +# Blender v2.73 (sub 0) OBJ File: '' +# www.blender.org +v -6.786140 -1.967150 -4.863200 +v -6.786140 -3.034000 -6.001260 +v -6.786140 -3.034000 -4.863200 +v -6.786140 -1.967150 -3.725140 +v -6.786140 -3.034000 -3.725140 +v -6.786140 -1.967150 -6.001260 +v -6.786140 -3.034000 -7.139320 +v -6.786140 -1.967150 -7.139320 +v -6.786140 -3.034000 -8.277380 +v -6.786140 -1.967150 -8.277380 +v -6.786140 -3.034000 -9.415440 +v -6.786140 -1.967150 -9.415440 +v -6.786140 -1.967150 -2.587080 +v -6.786140 -3.034000 -2.587080 +v -6.786140 -1.967150 -1.449020 +v -6.786140 -3.034000 -1.449020 +v -6.786140 -1.967150 -0.310965 +v -6.786140 -3.034000 -0.310965 +v -6.786140 -1.967150 0.827094 +v -6.786140 -3.034000 0.827094 +v -6.786140 -1.967150 1.965150 +v -6.786140 -3.034000 1.965150 +v -6.786140 -1.967150 3.103210 +v -6.786140 -3.034000 3.103210 +v -6.786140 -1.967150 4.241270 +v -6.786140 -3.034000 4.241270 +v -6.786140 -1.967150 5.379330 +v -6.786140 -3.034000 5.379330 +v -6.786140 -1.967150 6.517390 +v -6.786140 -3.034000 6.517390 +v -6.786140 -1.967150 7.655450 +v -6.786140 -3.034000 7.655450 +v -6.786140 -1.967150 8.793510 +v -6.786140 -3.033999 8.793510 +v 5.732520 -1.967150 -8.277380 +v 5.732520 -3.034000 -7.139320 +v 5.732520 -3.034000 -8.277380 +v 5.732520 -1.967150 -9.415440 +v 5.732520 -3.034000 -9.415440 +v 5.732520 -1.967150 -7.139320 +v 5.732520 -3.034000 -6.001260 +v 5.732520 -1.967150 -6.001260 +v 5.732520 -3.034000 -4.863200 +v 5.732520 -1.967150 -4.863200 +v 5.732520 -3.034000 -3.725140 +v 5.732520 -1.967150 -3.725140 +v 5.732520 -3.034000 -2.587080 +v 5.732520 -1.967150 -2.587080 +v 5.732520 -3.034000 -1.449020 +v 5.732520 -1.967150 -1.449020 +v 5.732520 -3.034000 -0.310965 +v 5.732520 -1.967150 -0.310965 +v 5.732520 -3.034000 0.827094 +v 5.732520 -1.967150 0.827094 +v 5.732520 -3.034000 1.965150 +v 5.732520 -1.967150 1.965150 +v 5.732520 -3.034000 3.103210 +v 5.732520 -1.967150 3.103210 +v 5.732520 -3.034000 4.241270 +v 5.732520 -1.967150 4.241270 +v 5.732520 -3.034000 5.379330 +v 5.732520 -1.967150 5.379330 +v 5.732520 -3.034000 6.517390 +v 5.732520 -1.967150 6.517390 +v 5.732520 -3.034000 7.655450 +v 5.732520 -1.967150 7.655450 +v 5.732520 -3.033999 8.793510 +v 5.732520 -1.967150 8.793510 +v -2.233900 -1.967150 -6.001260 +v -2.233900 -3.034000 -7.139320 +v -2.233900 -3.034000 -6.001260 +v -2.233900 -1.967150 -4.863200 +v -2.233900 -3.034000 -4.863200 +v -2.233900 -1.967150 -7.139320 +v -2.233900 -3.034000 -8.277380 +v -2.233900 -1.967150 -8.277380 +v -2.233900 -3.034000 -9.415440 +v -2.233900 -1.967150 -9.415440 +v -2.233900 -1.967150 -3.725140 +v -2.233900 -3.034000 -3.725140 +v -2.233900 -1.967150 -2.587080 +v -2.233900 -3.034000 -2.587080 +v -2.233900 -1.967150 -1.449020 +v -2.233900 -3.034000 -1.449020 +v -2.233900 -1.967150 -0.310965 +v -2.233900 -3.034000 -0.310965 +v -2.233900 -1.967150 0.827094 +v -2.233900 -3.034000 0.827094 +v -2.233900 -1.967150 1.965150 +v -2.233900 -3.034000 1.965150 +v -2.233900 -1.967150 3.103210 +v -2.233900 -3.034000 3.103210 +v -2.233900 -1.967150 4.241270 +v -2.233900 -3.034000 4.241270 +v -2.233900 -1.967150 5.379330 +v -2.233900 -3.034000 5.379330 +v -2.233900 -1.967150 6.517390 +v -2.233900 -3.034000 6.517390 +v -2.233900 -1.967150 7.655450 +v -2.233900 -3.034000 7.655450 +v -2.233900 -1.967150 8.793510 +v -2.233900 -3.033999 8.793510 +v 2.318340 -1.967150 -3.725140 +v 2.318340 -3.034000 -4.863200 +v 2.318340 -3.034000 -3.725140 +v 2.318340 -1.967150 -2.587080 +v 2.318340 -3.034000 -2.587080 +v 2.318340 -1.967150 -4.863200 +v 2.318340 -3.034000 -6.001260 +v 2.318340 -1.967150 -6.001260 +v 2.318340 -3.034000 -7.139320 +v 2.318340 -1.967150 -7.139320 +v 2.318340 -3.034000 -8.277380 +v 2.318340 -1.967150 -8.277380 +v 2.318340 -3.034000 -9.415440 +v 2.318340 -1.967150 -9.415440 +v 2.318340 -1.967150 -1.449020 +v 2.318340 -3.034000 -1.449020 +v 2.318340 -1.967150 -0.310965 +v 2.318340 -3.034000 -0.310965 +v 2.318340 -1.967150 0.827094 +v 2.318340 -3.034000 0.827094 +v 2.318340 -1.967150 1.965150 +v 2.318340 -3.034000 1.965150 +v 2.318340 -1.967150 3.103210 +v 2.318340 -3.034000 3.103210 +v 2.318340 -1.967150 4.241270 +v 2.318340 -3.034000 4.241270 +v 2.318340 -1.967150 5.379330 +v 2.318340 -3.034000 5.379330 +v 2.318340 -1.967150 6.517390 +v 2.318340 -3.034000 6.517390 +v 2.318340 -1.967150 7.655450 +v 2.318340 -3.034000 7.655450 +v 2.318340 -1.967150 8.793510 +v 2.318340 -3.033999 8.793510 +v -3.371960 -1.967150 6.517390 +v -3.371960 -3.034000 7.655450 +v -3.371960 -3.034000 6.517390 +v -3.371960 -1.967150 5.379330 +v -3.371960 -3.034000 5.379330 +v -3.371960 -1.967150 7.655450 +v -3.371960 -3.033999 8.793510 +v -3.371960 -1.967150 8.793510 +v -3.371960 -1.967150 4.241270 +v -3.371960 -3.034000 4.241270 +v -3.371960 -1.967150 3.103210 +v -3.371960 -3.034000 3.103210 +v -3.371960 -1.967150 1.965150 +v -3.371960 -3.034000 1.965150 +v -3.371960 -1.967150 0.827094 +v -3.371960 -3.034000 0.827094 +v -3.371960 -1.967150 -0.310965 +v -3.371960 -3.034000 -0.310965 +v -3.371960 -1.967150 -1.449020 +v -3.371960 -3.034000 -1.449020 +v -3.371960 -1.967150 -2.587080 +v -3.371960 -3.034000 -2.587080 +v -3.371960 -1.967150 -3.725140 +v -3.371960 -3.034000 -3.725140 +v -3.371960 -1.967150 -4.863200 +v -3.371960 -3.034000 -4.863200 +v -3.371960 -1.967150 -6.001260 +v -3.371960 -3.034000 -6.001260 +v -3.371960 -1.967150 -7.139320 +v -3.371960 -3.034000 -7.139320 +v -3.371960 -1.967150 -8.277380 +v -3.371960 -3.034000 -8.277380 +v -3.371960 -1.967150 -9.415440 +v -3.371960 -3.034000 -9.415440 +v 4.594460 -1.967150 8.793510 +v 3.456400 -3.033999 8.793510 +v 4.594460 -3.033999 8.793510 +v 3.456400 -1.967150 8.793510 +v 4.594460 0.276645 8.793510 +v 3.456400 0.276645 8.793510 +v 2.318340 0.276645 8.793510 +v 1.180280 -1.967150 8.793510 +v 3.456400 1.039180 8.793510 +v 4.594460 1.039180 8.793510 +v 5.732520 0.276645 8.793510 +v 5.732520 1.039180 8.793510 +v 6.870580 0.276645 8.793510 +v 6.870580 -1.967150 8.793510 +v 2.318340 1.039180 8.793510 +v 1.180280 0.276645 8.793510 +v 0.042220 0.276645 8.793510 +v 1.180280 1.039180 8.793510 +v 0.042220 -1.967150 8.793510 +v -1.095840 0.276645 8.793510 +v 0.042220 1.039180 8.793510 +v -1.095840 -1.967150 8.793510 +v 0.042220 -3.033999 8.793510 +v -1.095840 -3.033999 8.793510 +v 1.180280 -3.033999 8.793510 +v -2.233900 0.276645 8.793510 +v -4.510020 -1.967150 8.793510 +v -4.510020 -3.033999 8.793510 +v -3.371960 0.276645 8.793510 +v -1.095840 1.039180 8.793510 +v -2.233900 1.039180 8.793510 +v -4.510020 0.276645 8.793510 +v -3.371960 1.039180 8.793510 +v -4.510020 1.039180 8.793510 +v -5.648080 0.276645 8.793510 +v -5.648080 -1.967150 8.793510 +v -5.648080 1.039180 8.793510 +v -6.786140 0.276645 8.793510 +v -5.648080 -3.033999 8.793510 +v -7.786200 0.276645 8.793510 +v -7.786200 -1.967150 8.793510 +v -6.786140 1.039180 8.793510 +v 1.180280 -1.967150 1.965150 +v 1.180280 -3.034000 3.103210 +v 1.180280 -3.034000 1.965150 +v 1.180280 -1.967150 0.827094 +v 1.180280 -3.034000 0.827094 +v 1.180280 -1.967150 3.103210 +v 1.180280 -3.034000 4.241270 +v 1.180280 -1.967150 4.241270 +v 1.180280 -3.034000 5.379330 +v 1.180280 -1.967150 5.379330 +v 1.180280 -3.034000 6.517390 +v 1.180280 -1.967150 6.517390 +v 1.180280 -3.034000 7.655450 +v 1.180280 -1.967150 7.655450 +v 1.180280 -1.967150 -0.310965 +v 1.180280 -3.034000 -0.310965 +v 1.180280 -1.967150 -1.449020 +v 1.180280 -3.034000 -1.449020 +v 1.180280 -1.967150 -2.587080 +v 1.180280 -3.034000 -2.587080 +v 1.180280 -1.967150 -3.725140 +v 1.180280 -3.034000 -3.725140 +v 1.180280 -1.967150 -4.863200 +v 1.180280 -3.034000 -4.863200 +v 1.180280 -1.967150 -6.001260 +v 1.180280 -3.034000 -6.001260 +v 1.180280 -1.967150 -7.139320 +v 1.180280 -3.034000 -7.139320 +v 1.180280 -1.967150 -8.277380 +v 1.180280 -3.034000 -8.277380 +v 1.180280 -1.967150 -9.415440 +v 1.180280 -3.034000 -9.415440 +v 3.456400 -3.034000 -9.415440 +v 3.456400 -1.967150 -9.415440 +v 2.318340 0.276645 -9.415440 +v 1.180280 0.276645 -9.415440 +v 4.594460 -3.034000 -9.415440 +v 4.594460 -1.967150 -9.415440 +v 3.456400 0.276645 -9.415440 +v 2.318340 1.039180 -9.415440 +v 4.594460 0.276645 -9.415440 +v 3.456400 1.039180 -9.415440 +v 4.594460 1.039180 -9.415440 +v 5.732520 0.276645 -9.415440 +v 6.870580 -1.967150 -9.415440 +v 5.732520 1.039180 -9.415440 +v 6.870580 0.276645 -9.415440 +v 0.042220 0.276645 -9.415440 +v 0.042220 1.039180 -9.415440 +v 1.180280 1.039180 -9.415440 +v 0.042220 -1.967150 -9.415440 +v 0.042220 -3.034000 -9.415440 +v -1.095840 -1.967150 -9.415440 +v -1.095840 -3.034000 -9.415440 +v -2.233900 0.276645 -9.415440 +v -1.095840 0.276645 -9.415440 +v -3.371960 0.276645 -9.415440 +v -2.233900 1.039180 -9.415440 +v -1.095840 1.039180 -9.415440 +v -4.510020 0.276645 -9.415440 +v -4.510020 1.039180 -9.415440 +v -3.371960 1.039180 -9.415440 +v -4.510020 -1.967150 -9.415440 +v -5.648080 0.276645 -9.415440 +v -5.648080 1.039180 -9.415440 +v -5.648080 -1.967150 -9.415440 +v -4.510020 -3.034000 -9.415440 +v -6.786140 0.276645 -9.415440 +v -6.786140 1.039180 -9.415440 +v -5.648080 -3.034000 -9.415440 +v -7.786200 -1.967150 -9.415440 +v -7.786200 0.276645 -9.415440 +v 6.870580 -1.967150 7.655450 +v 6.870580 -1.967150 6.517390 +v 6.870580 -1.967150 5.379330 +v 6.870580 -1.967150 4.241270 +v 6.870580 -1.967150 3.103210 +v 6.870580 -1.967150 1.965150 +v 6.870580 -1.967150 0.827094 +v 6.870580 -1.967150 -0.310965 +v 6.870580 -1.967150 -1.449020 +v 6.870580 -1.967150 -2.587080 +v 6.870580 -1.967150 -3.725140 +v 6.870580 -1.967150 -4.863200 +v 6.870580 -1.967150 -6.001260 +v 6.870580 -1.967150 -7.139320 +v 6.870580 -1.967150 -8.277380 +v -5.648080 -3.034000 0.827094 +v -5.648080 -3.034000 -0.310965 +v -5.648080 -3.034000 1.965150 +v -4.510020 -3.034000 1.965150 +v -5.648080 -3.034000 3.103210 +v -4.510020 -3.034000 0.827094 +v -5.648080 -3.034000 4.241270 +v -4.510020 -3.034000 3.103210 +v -4.510020 -3.034000 -0.310965 +v -4.510020 -3.034000 -1.449020 +v -4.510020 -3.034000 -2.587080 +v -5.648080 -3.034000 -1.449020 +v -5.648080 -3.034000 -2.587080 +v -4.510020 -3.034000 -3.725140 +v -5.648080 -3.034000 -3.725140 +v -4.510020 -3.034000 -4.863200 +v -5.648080 -3.034000 -4.863200 +v -4.510020 -3.034000 -6.001260 +v -5.648080 -3.034000 -6.001260 +v -4.510020 -3.034000 -7.139320 +v -5.648080 -3.034000 -7.139320 +v -4.510020 -3.034000 -8.277380 +v -5.648080 -3.034000 -8.277380 +v -4.510020 -3.034000 4.241270 +v -4.510020 -3.034000 5.379330 +v -5.648080 -3.034000 5.379330 +v -5.648080 -3.034000 6.517390 +v -4.510020 -3.034000 6.517390 +v -5.648080 -3.034000 7.655450 +v -4.510020 -3.034000 7.655450 +v -1.095840 -3.034000 0.827094 +v -1.095840 -3.034000 -0.310965 +v -1.095840 -3.034000 1.965150 +v 0.042220 -3.034000 1.965150 +v -1.095840 -3.034000 3.103210 +v 0.042220 -3.034000 0.827094 +v -1.095840 -3.034000 4.241270 +v 0.042220 -3.034000 3.103210 +v 0.042220 -3.034000 -0.310965 +v 0.042220 -3.034000 -1.449020 +v 0.042220 -3.034000 -2.587080 +v -1.095840 -3.034000 -1.449020 +v -1.095840 -3.034000 -2.587080 +v 0.042220 -3.034000 -3.725140 +v -1.095840 -3.034000 -3.725140 +v 0.042220 -3.034000 -4.863200 +v -1.095840 -3.034000 -4.863200 +v 0.042220 -3.034000 -6.001260 +v -1.095840 -3.034000 -6.001260 +v 0.042220 -3.034000 -7.139320 +v -1.095840 -3.034000 -7.139320 +v 0.042220 -3.034000 -8.277380 +v -1.095840 -3.034000 -8.277380 +v 0.042220 -3.034000 4.241270 +v 0.042220 -3.034000 5.379330 +v -1.095840 -3.034000 5.379330 +v -1.095840 -3.034000 6.517390 +v 0.042220 -3.034000 6.517390 +v -1.095840 -3.034000 7.655450 +v 0.042220 -3.034000 7.655450 +v 3.456400 -3.034000 -3.725140 +v 3.456400 -3.034000 -4.863200 +v 3.456400 -3.034000 -2.587080 +v 4.594460 -3.034000 -2.587080 +v 3.456400 -3.034000 -1.449020 +v 4.594460 -3.034000 -3.725140 +v 3.456400 -3.034000 -0.310965 +v 4.594460 -3.034000 -1.449020 +v 4.594460 -3.034000 -4.863200 +v 4.594460 -3.034000 -6.001260 +v 4.594460 -3.034000 -7.139320 +v 3.456400 -3.034000 -6.001260 +v 3.456400 -3.034000 -7.139320 +v 4.594460 -3.034000 -8.277380 +v 3.456400 -3.034000 -8.277380 +v 4.594460 -3.034000 -0.310965 +v 4.594460 -3.034000 0.827094 +v 3.456400 -3.034000 0.827094 +v 3.456400 -3.034000 1.965150 +v 4.594460 -3.034000 1.965150 +v 3.456400 -3.034000 3.103210 +v 4.594460 -3.034000 3.103210 +v 3.456400 -3.034000 4.241270 +v 4.594460 -3.034000 4.241270 +v 3.456400 -3.034000 5.379330 +v 4.594460 -3.034000 5.379330 +v 3.456400 -3.034000 6.517390 +v 4.594460 -3.034000 6.517390 +v 3.456400 -3.034000 7.655450 +v 4.594460 -3.034000 7.655450 +v -2.233900 0.276645 -2.587080 +v -2.233900 1.039180 -1.449020 +v -2.233900 1.039180 -2.587080 +v -2.233900 0.276645 -3.725140 +v -2.233900 1.039180 -3.725140 +v -2.233900 0.276645 -1.449020 +v -2.233900 1.039180 -0.310965 +v -2.233900 0.276645 -0.310965 +v -2.233900 1.039180 0.827094 +v -2.233900 0.276645 0.827094 +v -2.233900 1.039180 1.965150 +v -2.233900 0.276645 1.965150 +v -2.233900 1.039180 3.103210 +v -2.233900 0.276645 3.103210 +v -2.233900 1.039180 4.241270 +v -2.233900 0.276645 4.241270 +v -2.233900 1.039180 5.379330 +v -2.233900 0.276645 5.379330 +v -2.233900 1.039180 6.517390 +v -2.233900 0.276645 6.517390 +v -2.233900 1.039180 7.655450 +v -2.233900 0.276645 7.655450 +v -2.233900 0.276645 -4.863200 +v -2.233900 1.039180 -4.863200 +v -2.233900 0.276645 -6.001260 +v -2.233900 1.039180 -6.001260 +v -2.233900 0.276645 -7.139320 +v -2.233900 1.039180 -7.139320 +v -2.233900 0.276645 -8.277380 +v -2.233900 1.039180 -8.277380 +v 2.318340 0.276645 4.241270 +v 2.318340 1.039180 5.379330 +v 2.318340 1.039180 4.241270 +v 2.318340 0.276645 3.103210 +v 2.318340 1.039180 3.103210 +v 2.318340 0.276645 5.379330 +v 2.318340 1.039180 6.517390 +v 2.318340 0.276645 6.517390 +v 2.318340 1.039180 7.655450 +v 2.318340 0.276645 7.655450 +v 2.318340 0.276645 1.965150 +v 2.318340 1.039180 1.965150 +v 2.318340 0.276645 0.827094 +v 2.318340 1.039180 0.827094 +v 2.318340 0.276645 -0.310965 +v 2.318340 1.039180 -0.310965 +v 2.318340 0.276645 -1.449020 +v 2.318340 1.039180 -1.449020 +v 2.318340 0.276645 -2.587080 +v 2.318340 1.039180 -2.587080 +v 2.318340 0.276645 -3.725140 +v 2.318340 1.039180 -3.725140 +v 2.318340 0.276645 -4.863200 +v 2.318340 1.039180 -4.863200 +v 2.318340 0.276645 -6.001260 +v 2.318340 1.039180 -6.001260 +v 2.318340 0.276645 -7.139320 +v 2.318340 1.039180 -7.139320 +v 2.318340 0.276645 -8.277380 +v 2.318340 1.039180 -8.277380 +v -6.786140 0.276645 6.517390 +v -6.786140 1.039180 7.655450 +v -6.786140 1.039180 6.517390 +v -6.786140 0.276645 5.379330 +v -6.786140 1.039180 5.379330 +v -6.786140 0.276645 7.655450 +v -6.786140 0.276645 4.241270 +v -6.786140 1.039180 4.241270 +v -6.786140 0.276645 3.103210 +v -6.786140 1.039180 3.103210 +v -6.786140 0.276645 1.965150 +v -6.786140 1.039180 1.965150 +v -6.786140 0.276645 0.827094 +v -6.786140 1.039180 0.827094 +v -6.786140 0.276645 -0.310965 +v -6.786140 1.039180 -0.310965 +v -6.786140 0.276645 -1.449020 +v -6.786140 1.039180 -1.449020 +v -6.786140 0.276645 -2.587080 +v -6.786140 1.039180 -2.587080 +v -6.786140 0.276645 -3.725140 +v -6.786140 1.039180 -3.725140 +v -6.786140 0.276645 -4.863200 +v -6.786140 1.039180 -4.863200 +v -6.786140 0.276645 -6.001260 +v -6.786140 1.039180 -6.001260 +v -6.786140 0.276645 -7.139320 +v -6.786140 1.039180 -7.139320 +v -6.786140 0.276645 -8.277380 +v -6.786140 1.039180 -8.277380 +v 1.180280 0.276645 -7.139320 +v 1.180280 1.039180 -8.277380 +v 1.180280 1.039180 -7.139320 +v 1.180280 0.276645 -6.001260 +v 1.180280 1.039180 -6.001260 +v 1.180280 0.276645 -8.277380 +v 1.180280 0.276645 -4.863200 +v 1.180280 1.039180 -4.863200 +v 1.180280 0.276645 -3.725140 +v 1.180280 1.039180 -3.725140 +v 1.180280 0.276645 -2.587080 +v 1.180280 1.039180 -2.587080 +v 1.180280 0.276645 -1.449020 +v 1.180280 1.039180 -1.449020 +v 1.180280 0.276645 -0.310965 +v 1.180280 1.039180 -0.310965 +v 1.180280 0.276645 0.827094 +v 1.180280 1.039180 0.827094 +v 1.180280 0.276645 1.965150 +v 1.180280 1.039180 1.965150 +v 1.180280 0.276645 3.103210 +v 1.180280 1.039180 3.103210 +v 1.180280 0.276645 4.241270 +v 1.180280 1.039180 4.241270 +v 1.180280 0.276645 5.379330 +v 1.180280 1.039180 5.379330 +v 1.180280 0.276645 6.517390 +v 1.180280 1.039180 6.517390 +v 1.180280 0.276645 7.655450 +v 1.180280 1.039180 7.655450 +v 5.732520 0.276645 3.103210 +v 5.732520 1.039180 1.965150 +v 5.732520 1.039180 3.103210 +v 5.732520 0.276645 4.241270 +v 5.732520 1.039180 4.241270 +v 5.732520 0.276645 1.965150 +v 5.732520 1.039180 0.827094 +v 5.732520 0.276645 0.827094 +v 5.732520 1.039180 -0.310965 +v 5.732520 0.276645 -0.310965 +v 5.732520 1.039180 -1.449020 +v 5.732520 0.276645 -1.449020 +v 5.732520 1.039180 -2.587080 +v 5.732520 0.276645 -2.587080 +v 5.732520 1.039180 -3.725140 +v 5.732520 0.276645 -3.725140 +v 5.732520 1.039180 -4.863200 +v 5.732520 0.276645 -4.863200 +v 5.732520 1.039180 -6.001260 +v 5.732520 0.276645 -6.001260 +v 5.732520 1.039180 -7.139320 +v 5.732520 0.276645 -7.139320 +v 5.732520 1.039180 -8.277380 +v 5.732520 0.276645 -8.277380 +v 5.732520 0.276645 5.379330 +v 5.732520 1.039180 5.379330 +v 5.732520 0.276645 6.517390 +v 5.732520 1.039180 6.517390 +v 5.732520 0.276645 7.655450 +v 5.732520 1.039180 7.655450 +v -3.371960 1.039180 7.655450 +v -3.371960 0.276645 7.655450 +v -3.371960 1.039180 6.517390 +v -3.371960 0.276645 6.517390 +v -3.371960 1.039180 5.379330 +v -3.371960 0.276645 5.379330 +v -3.371960 1.039180 4.241270 +v -3.371960 0.276645 4.241270 +v -3.371960 1.039180 3.103210 +v -3.371960 0.276645 3.103210 +v -3.371960 1.039180 1.965150 +v -3.371960 0.276645 1.965150 +v -3.371960 1.039180 0.827094 +v -3.371960 0.276645 0.827094 +v -3.371960 1.039180 -0.310965 +v -3.371960 0.276645 -0.310965 +v -3.371960 1.039180 -1.449020 +v -3.371960 0.276645 -1.449020 +v -3.371960 1.039180 -2.587080 +v -3.371960 0.276645 -2.587080 +v -3.371960 1.039180 -3.725140 +v -3.371960 0.276645 -3.725140 +v -3.371960 1.039180 -4.863200 +v -3.371960 0.276645 -4.863200 +v -3.371960 1.039180 -6.001260 +v -3.371960 0.276645 -6.001260 +v -3.371960 1.039180 -7.139320 +v -3.371960 0.276645 -7.139320 +v -3.371960 1.039180 -8.277380 +v -3.371960 0.276645 -8.277380 +v 6.870580 0.276645 7.655450 +v 6.870580 0.276645 6.517390 +v 6.870580 0.276645 5.379330 +v 6.870580 0.276645 4.241270 +v 6.870580 0.276645 3.103210 +v 6.870580 0.276645 1.965150 +v 6.870580 0.276645 0.827094 +v 6.870580 0.276645 -0.310965 +v 6.870580 0.276645 -1.449020 +v 6.870580 0.276645 -2.587080 +v 6.870580 0.276645 -3.725140 +v 6.870580 0.276645 -4.863200 +v 6.870580 0.276645 -6.001260 +v 6.870580 0.276645 -7.139320 +v 6.870580 0.276645 -8.277380 +v -1.095840 0.276645 -10.802900 +v -1.095840 -1.967150 -10.802900 +v -1.095840 0.276644 -12.034100 +v -1.095840 -1.967150 -12.034100 +v -1.095840 -4.601110 -10.802900 +v -1.095840 -4.601110 -12.034100 +v -1.095840 -4.601110 -9.415440 +v -1.095840 1.039180 -10.802900 +v -1.095840 1.039180 -12.034100 +v -1.095840 2.768579 -10.802900 +v -1.095840 2.768579 -12.034100 +v -1.095840 3.746069 -10.802900 +v -1.095840 2.768580 -7.883420 +v -1.095840 3.746069 -12.034100 +v -1.095840 3.746070 -7.883420 +v -1.095840 0.276644 -14.284900 +v -1.095840 -1.967151 -14.284900 +v -1.095840 -4.601110 -14.284900 +v 0.042220 -1.967150 -12.034100 +v 0.042220 -4.601110 -10.802900 +v 0.042220 -4.601110 -12.034100 +v 0.042220 -4.601110 -14.284900 +v 0.042220 -1.967150 -10.802900 +v 0.042220 -4.601110 -9.415440 +v 0.042220 0.276645 -10.802900 +v 0.042220 1.039180 -10.802900 +v 0.042220 0.276644 -12.034100 +v 0.042220 1.039180 -12.034100 +v 0.042220 2.768579 -12.034100 +v 0.042220 2.768579 -10.802900 +v 0.042220 -1.967151 -14.284900 +v 0.042220 0.276644 -14.284900 +v 0.042220 3.746069 -12.034100 +v 0.042220 3.746069 -10.802900 +v 0.042220 3.746070 -7.883420 +v 0.042220 2.768580 -7.883420 +v -7.786200 -1.967150 -8.277380 +v -7.786200 -1.967150 -7.139320 +v -7.786200 -1.967150 -6.001260 +v -7.786200 -1.967150 -4.863200 +v -7.786200 -1.967150 -3.725140 +v -7.786200 -1.967150 -2.587080 +v -7.786200 -1.967150 -1.449020 +v -7.786200 -1.967150 -0.310965 +v -7.786200 -1.967150 0.827094 +v -7.786200 -1.967150 1.965150 +v -7.786200 -1.967150 3.103210 +v -7.786200 -1.967150 4.241270 +v -7.786200 -1.967150 5.379330 +v -7.786200 -1.967150 6.517390 +v -7.786200 -1.967150 7.655450 +v -7.786200 0.276645 3.103210 +v -7.786200 0.276645 4.241270 +v -7.786200 0.276645 5.379330 +v -7.786200 0.276645 1.965150 +v -7.786200 0.276645 0.827094 +v -7.786200 0.276645 -0.310965 +v -7.786200 0.276645 -1.449020 +v -7.786200 0.276645 -2.587080 +v -7.786200 0.276645 -3.725140 +v -7.786200 0.276645 -4.863200 +v -7.786200 0.276645 -6.001260 +v -7.786200 0.276645 -7.139320 +v -7.786200 0.276645 -8.277380 +v -7.786200 0.276645 6.517390 +v -7.786200 0.276645 7.655450 +v 0.042220 1.039180 7.655450 +v 0.042220 1.039180 6.517390 +v -1.095840 1.039180 7.655450 +v 0.042220 1.039180 5.379330 +v -1.095840 1.039180 6.517390 +v -1.095840 1.039180 5.379330 +v 0.042220 1.039180 4.241270 +v -1.095840 1.039180 4.241270 +v 0.042220 1.039180 3.103210 +v -1.095840 1.039180 3.103210 +v 0.042220 1.039180 1.965150 +v -1.095840 1.039180 1.965150 +v 0.042220 1.039180 0.827094 +v -1.095840 1.039180 0.827094 +v 0.042220 1.039180 -0.310965 +v -1.095840 1.039180 -0.310965 +v 0.042220 1.039180 -1.449020 +v -1.095840 1.039180 -1.449020 +v 0.042220 1.039180 -2.587080 +v -1.095840 1.039180 -2.587080 +v 0.042220 1.039180 -3.725140 +v -1.095840 1.039180 -3.725140 +v 0.042220 1.039180 -4.863200 +v -1.095840 1.039180 -4.863200 +v 0.042220 1.039180 -6.001260 +v -1.095840 1.039180 -6.001260 +v 0.042220 1.039180 -7.139320 +v -1.095840 1.039180 -7.139320 +v 0.042220 1.039180 -8.277380 +v -1.095840 1.039180 -8.277380 +v -4.510020 1.039180 7.655450 +v -4.510020 1.039180 6.517390 +v -5.648080 1.039180 7.655450 +v -4.510020 1.039180 5.379330 +v -5.648080 1.039180 6.517390 +v -5.648080 1.039180 5.379330 +v -4.510020 1.039180 4.241270 +v -5.648080 1.039180 4.241270 +v -4.510020 1.039180 3.103210 +v -5.648080 1.039180 3.103210 +v -4.510020 1.039180 1.965150 +v -5.648080 1.039180 1.965150 +v -4.510020 1.039180 0.827094 +v -5.648080 1.039180 0.827094 +v -4.510020 1.039180 -0.310965 +v -5.648080 1.039180 -0.310965 +v -4.510020 1.039180 -1.449020 +v -5.648080 1.039180 -1.449020 +v -4.510020 1.039180 -2.587080 +v -5.648080 1.039180 -2.587080 +v -4.510020 1.039180 -3.725140 +v -5.648080 1.039180 -3.725140 +v -4.510020 1.039180 -4.863200 +v -5.648080 1.039180 -4.863200 +v -4.510020 1.039180 -6.001260 +v -5.648080 1.039180 -6.001260 +v -4.510020 1.039180 -7.139320 +v -5.648080 1.039180 -7.139320 +v -4.510020 1.039180 -8.277380 +v -5.648080 1.039180 -8.277380 +v 4.594460 1.039180 7.655450 +v 4.594460 1.039180 6.517390 +v 3.456400 1.039180 7.655450 +v 4.594460 1.039180 5.379330 +v 3.456400 1.039180 6.517390 +v 3.456400 1.039180 5.379330 +v 4.594460 1.039180 4.241270 +v 3.456400 1.039180 4.241270 +v 4.594460 1.039180 3.103210 +v 3.456400 1.039180 3.103210 +v 4.594460 1.039180 1.965150 +v 3.456400 1.039180 1.965150 +v 4.594460 1.039180 0.827094 +v 3.456400 1.039180 0.827094 +v 4.594460 1.039180 -0.310965 +v 3.456400 1.039180 -0.310965 +v 4.594460 1.039180 -1.449020 +v 3.456400 1.039180 -1.449020 +v 4.594460 1.039180 -2.587080 +v 3.456400 1.039180 -2.587080 +v 4.594460 1.039180 -3.725140 +v 3.456400 1.039180 -3.725140 +v 4.594460 1.039180 -4.863200 +v 3.456400 1.039180 -4.863200 +v 4.594460 1.039180 -6.001260 +v 3.456400 1.039180 -6.001260 +v 4.594460 1.039180 -7.139320 +v 3.456400 1.039180 -7.139320 +v 4.594460 1.039180 -8.277380 +v 3.456400 1.039180 -8.277380 +vt 0.116019 0.974315 +vt 0.087066 0.947167 +vt 0.116022 0.947170 +vt 0.144976 0.974318 +vt 0.144979 0.947173 +vt 0.087063 0.974311 +vt 0.058110 0.947165 +vt 0.058107 0.974308 +vt 0.029155 0.947162 +vt 0.029152 0.974306 +vt 0.000199 0.947159 +vt 0.000197 0.974303 +vt 0.173933 0.974322 +vt 0.173936 0.947177 +vt 0.202891 0.974326 +vt 0.202894 0.947180 +vt 0.231849 0.974330 +vt 0.231853 0.947184 +vt 0.260808 0.974334 +vt 0.260812 0.947187 +vt 0.289768 0.974338 +vt 0.289772 0.947190 +vt 0.318729 0.974342 +vt 0.318732 0.947194 +vt 0.347690 0.974345 +vt 0.347693 0.947196 +vt 0.376652 0.974348 +vt 0.376654 0.947199 +vt 0.405614 0.974351 +vt 0.405616 0.947201 +vt 0.434577 0.974353 +vt 0.434578 0.947203 +vt 0.463539 0.974355 +vt 0.463541 0.947205 +vt 0.029160 0.492913 +vt 0.058118 0.520059 +vt 0.029160 0.520059 +vt 0.000202 0.492913 +vt 0.000202 0.520059 +vt 0.058118 0.492913 +vt 0.087076 0.520059 +vt 0.087076 0.492913 +vt 0.116034 0.520059 +vt 0.116034 0.492914 +vt 0.144992 0.520060 +vt 0.144992 0.492914 +vt 0.173949 0.520060 +vt 0.173950 0.492914 +vt 0.202907 0.520060 +vt 0.202907 0.492915 +vt 0.231864 0.520060 +vt 0.231865 0.492915 +vt 0.260822 0.520061 +vt 0.260822 0.492916 +vt 0.289779 0.520061 +vt 0.289778 0.492916 +vt 0.318735 0.520060 +vt 0.318735 0.492916 +vt 0.347692 0.520060 +vt 0.347691 0.492915 +vt 0.376649 0.520059 +vt 0.376648 0.492915 +vt 0.405605 0.520058 +vt 0.405604 0.492914 +vt 0.434561 0.520056 +vt 0.434560 0.492912 +vt 0.463517 0.520055 +vt 0.463516 0.492911 +vt 0.087075 0.804197 +vt 0.058119 0.777052 +vt 0.087076 0.777053 +vt 0.116032 0.804198 +vt 0.116033 0.777053 +vt 0.058119 0.804197 +vt 0.029163 0.777052 +vt 0.029163 0.804196 +vt 0.000207 0.777052 +vt 0.000207 0.804196 +vt 0.144989 0.804200 +vt 0.144990 0.777054 +vt 0.173947 0.804201 +vt 0.173948 0.777055 +vt 0.202905 0.804202 +vt 0.202906 0.777056 +vt 0.231863 0.804203 +vt 0.231864 0.777057 +vt 0.260822 0.804204 +vt 0.260822 0.777057 +vt 0.289780 0.804205 +vt 0.289781 0.777058 +vt 0.318740 0.804205 +vt 0.318740 0.777058 +vt 0.347700 0.804206 +vt 0.347700 0.777058 +vt 0.376660 0.804206 +vt 0.376659 0.777058 +vt 0.405620 0.804205 +vt 0.405620 0.777057 +vt 0.434581 0.804205 +vt 0.434580 0.777056 +vt 0.463543 0.804203 +vt 0.463541 0.777054 +vt 0.144991 0.634078 +vt 0.116033 0.606933 +vt 0.144991 0.606933 +vt 0.173949 0.634079 +vt 0.173949 0.606933 +vt 0.116034 0.634078 +vt 0.087076 0.606933 +vt 0.087076 0.634079 +vt 0.058118 0.606933 +vt 0.058118 0.634079 +vt 0.029160 0.606933 +vt 0.029160 0.634079 +vt 0.000202 0.606933 +vt 0.000202 0.634080 +vt 0.202907 0.634079 +vt 0.202907 0.606933 +vt 0.231864 0.634078 +vt 0.231864 0.606933 +vt 0.260822 0.634078 +vt 0.260822 0.606933 +vt 0.289780 0.634078 +vt 0.289780 0.606932 +vt 0.318738 0.634077 +vt 0.318737 0.606932 +vt 0.347696 0.634077 +vt 0.347695 0.606931 +vt 0.376653 0.634076 +vt 0.376652 0.606930 +vt 0.405611 0.634074 +vt 0.405609 0.606928 +vt 0.434569 0.634072 +vt 0.434567 0.606927 +vt 0.463527 0.634069 +vt 0.463524 0.606924 +vt 0.405621 0.833166 +vt 0.434582 0.860316 +vt 0.405620 0.860316 +vt 0.376660 0.833166 +vt 0.376659 0.860315 +vt 0.434582 0.833166 +vt 0.463545 0.860317 +vt 0.463544 0.833166 +vt 0.347699 0.833166 +vt 0.347698 0.860314 +vt 0.318739 0.833165 +vt 0.318738 0.860313 +vt 0.289780 0.833164 +vt 0.289778 0.860311 +vt 0.260820 0.833163 +vt 0.260819 0.860309 +vt 0.231862 0.833161 +vt 0.231860 0.860308 +vt 0.202903 0.833160 +vt 0.202902 0.860306 +vt 0.173946 0.833158 +vt 0.173944 0.860304 +vt 0.144988 0.833157 +vt 0.144987 0.860302 +vt 0.116031 0.833155 +vt 0.116029 0.860300 +vt 0.087074 0.833154 +vt 0.087073 0.860299 +vt 0.058118 0.833153 +vt 0.058116 0.860297 +vt 0.029162 0.833152 +vt 0.029161 0.860295 +vt 0.000206 0.833151 +vt 0.000205 0.860294 +vt 0.662141 0.076691 +vt 0.691099 0.103837 +vt 0.662141 0.103837 +vt 0.633183 0.076691 +vt 0.633183 0.103837 +vt 0.691099 0.076691 +vt 0.720057 0.103837 +vt 0.720058 0.076691 +vt 0.662141 0.019597 +vt 0.691100 0.019597 +vt 0.720058 0.019597 +vt 0.749016 0.076691 +vt 0.691100 0.000194 +vt 0.662142 0.000194 +vt 0.633183 0.019597 +vt 0.633183 0.000194 +vt 0.604225 0.019597 +vt 0.604225 0.076691 +vt 0.720058 0.000194 +vt 0.749016 0.019597 +vt 0.777974 0.019597 +vt 0.749016 0.000195 +vt 0.777974 0.076691 +vt 0.806932 0.019597 +vt 0.777974 0.000195 +vt 0.806932 0.076691 +vt 0.777974 0.103837 +vt 0.806932 0.103837 +vt 0.749016 0.103837 +vt 0.835890 0.103837 +vt 0.835890 0.076691 +vt 0.864848 0.076691 +vt 0.835890 0.019597 +vt 0.893806 0.076691 +vt 0.893806 0.103837 +vt 0.864848 0.103837 +vt 0.864848 0.019597 +vt 0.806932 0.000195 +vt 0.835890 0.000195 +vt 0.893806 0.019597 +vt 0.864848 0.000195 +vt 0.893806 0.000194 +vt 0.922764 0.019597 +vt 0.922764 0.076691 +vt 0.922764 0.000194 +vt 0.951722 0.019597 +vt 0.951722 0.076691 +vt 0.951722 0.103837 +vt 0.922764 0.103837 +vt 0.977169 0.019597 +vt 0.977169 0.076690 +vt 0.951722 0.000194 +vt 0.289780 0.663036 +vt 0.318739 0.690182 +vt 0.289781 0.690182 +vt 0.260822 0.663036 +vt 0.260823 0.690182 +vt 0.318739 0.663035 +vt 0.347698 0.690181 +vt 0.347697 0.663035 +vt 0.376656 0.690180 +vt 0.376655 0.663033 +vt 0.405615 0.690178 +vt 0.405613 0.663032 +vt 0.434574 0.690176 +vt 0.434571 0.663030 +vt 0.463533 0.690173 +vt 0.463530 0.663027 +vt 0.231865 0.663036 +vt 0.231865 0.690182 +vt 0.202907 0.663036 +vt 0.202907 0.690182 +vt 0.173949 0.663036 +vt 0.173949 0.690182 +vt 0.144991 0.663036 +vt 0.144991 0.690182 +vt 0.116034 0.663036 +vt 0.116034 0.690182 +vt 0.087076 0.663036 +vt 0.087076 0.690182 +vt 0.058118 0.663036 +vt 0.058119 0.690182 +vt 0.029161 0.663037 +vt 0.029162 0.690182 +vt 0.000203 0.663038 +vt 0.000205 0.690183 +vt 0.579762 0.491109 +vt 0.550803 0.463966 +vt 0.579760 0.463963 +vt 0.550805 0.491111 +vt 0.579767 0.548202 +vt 0.608720 0.491107 +vt 0.608724 0.548199 +vt 0.521845 0.463968 +vt 0.521847 0.491114 +vt 0.550809 0.548204 +vt 0.579768 0.567604 +vt 0.521852 0.548206 +vt 0.550811 0.567606 +vt 0.492890 0.491116 +vt 0.492888 0.463971 +vt 0.521853 0.567608 +vt 0.492895 0.548208 +vt 0.463933 0.491118 +vt 0.492896 0.567610 +vt 0.463938 0.548210 +vt 0.637682 0.548197 +vt 0.637683 0.567600 +vt 0.608726 0.567602 +vt 0.637678 0.491105 +vt 0.608718 0.463961 +vt 0.637676 0.463959 +vt 0.666636 0.491103 +vt 0.666635 0.463957 +vt 0.695594 0.491102 +vt 0.695595 0.548197 +vt 0.666637 0.548197 +vt 0.695593 0.463956 +vt 0.724553 0.491102 +vt 0.724554 0.548197 +vt 0.695596 0.567600 +vt 0.666637 0.567600 +vt 0.753512 0.548197 +vt 0.753512 0.567600 +vt 0.724554 0.567600 +vt 0.753512 0.491102 +vt 0.724553 0.463955 +vt 0.782471 0.548197 +vt 0.782471 0.567600 +vt 0.782471 0.491102 +vt 0.753512 0.463955 +vt 0.811429 0.548197 +vt 0.811429 0.567600 +vt 0.782471 0.463955 +vt 0.811430 0.491102 +vt 0.836877 0.491102 +vt 0.836877 0.548197 +vt 0.811430 0.463955 +vt 0.434558 0.463956 +vt 0.405603 0.463958 +vt 0.463514 0.463955 +vt 0.376647 0.463959 +vt 0.347691 0.463959 +vt 0.318735 0.463959 +vt 0.289779 0.463959 +vt 0.260822 0.463959 +vt 0.231865 0.463958 +vt 0.202908 0.463957 +vt 0.173950 0.463956 +vt 0.144992 0.463956 +vt 0.116034 0.463956 +vt 0.087076 0.463955 +vt 0.058118 0.463955 +vt 0.029160 0.463955 +vt 0.000202 0.463955 +vt 0.260815 0.918228 +vt 0.231856 0.918225 +vt 0.289774 0.918230 +vt 0.289777 0.889271 +vt 0.318734 0.918233 +vt 0.260817 0.889269 +vt 0.347695 0.918235 +vt 0.318737 0.889273 +vt 0.231858 0.889266 +vt 0.202900 0.889264 +vt 0.173942 0.889262 +vt 0.202897 0.918222 +vt 0.173939 0.918219 +vt 0.144984 0.889259 +vt 0.144982 0.918216 +vt 0.116028 0.889257 +vt 0.116025 0.918214 +vt 0.087071 0.889255 +vt 0.087069 0.918211 +vt 0.058115 0.889253 +vt 0.058113 0.918209 +vt 0.029159 0.889251 +vt 0.029157 0.918206 +vt 0.000204 0.889249 +vt 0.000202 0.918204 +vt 0.347697 0.889274 +vt 0.376658 0.889276 +vt 0.376656 0.918237 +vt 0.405618 0.918239 +vt 0.405619 0.889277 +vt 0.434580 0.918241 +vt 0.434581 0.889278 +vt 0.463543 0.918242 +vt 0.463544 0.889279 +vt 0.260823 0.748099 +vt 0.231864 0.748098 +vt 0.289781 0.748099 +vt 0.289781 0.719140 +vt 0.318740 0.748099 +vt 0.260823 0.719140 +vt 0.347699 0.748099 +vt 0.318740 0.719140 +vt 0.231865 0.719140 +vt 0.202907 0.719140 +vt 0.173949 0.719140 +vt 0.202906 0.748098 +vt 0.173948 0.748097 +vt 0.144991 0.719139 +vt 0.144991 0.748097 +vt 0.116034 0.719139 +vt 0.116033 0.748096 +vt 0.087076 0.719139 +vt 0.087076 0.748096 +vt 0.058119 0.719139 +vt 0.058119 0.748096 +vt 0.029162 0.719139 +vt 0.029163 0.748096 +vt 0.000206 0.719140 +vt 0.000207 0.748096 +vt 0.347698 0.719140 +vt 0.376657 0.719139 +vt 0.376659 0.748098 +vt 0.405618 0.748097 +vt 0.405617 0.719137 +vt 0.434578 0.748095 +vt 0.434576 0.719135 +vt 0.463539 0.748093 +vt 0.463536 0.719133 +vt 0.144991 0.577975 +vt 0.116033 0.577975 +vt 0.173949 0.577975 +vt 0.173949 0.549017 +vt 0.202907 0.577975 +vt 0.144991 0.549017 +vt 0.231864 0.577975 +vt 0.202907 0.549018 +vt 0.116034 0.549017 +vt 0.087076 0.549017 +vt 0.058118 0.549017 +vt 0.087076 0.577975 +vt 0.058118 0.577975 +vt 0.029160 0.549017 +vt 0.029160 0.577975 +vt 0.000202 0.549017 +vt 0.000202 0.577975 +vt 0.231864 0.549018 +vt 0.260822 0.549018 +vt 0.260822 0.577975 +vt 0.289779 0.577975 +vt 0.289779 0.549018 +vt 0.318736 0.577974 +vt 0.318736 0.549017 +vt 0.347694 0.577974 +vt 0.347693 0.549017 +vt 0.376651 0.577973 +vt 0.376650 0.549016 +vt 0.405608 0.577971 +vt 0.405606 0.549014 +vt 0.434565 0.577969 +vt 0.434563 0.549013 +vt 0.463521 0.577967 +vt 0.463519 0.549011 +vt 0.237437 0.289790 +vt 0.256842 0.260831 +vt 0.256841 0.289791 +vt 0.237435 0.318750 +vt 0.256839 0.318751 +vt 0.237438 0.260831 +vt 0.256843 0.231873 +vt 0.237440 0.231872 +vt 0.256844 0.202915 +vt 0.237441 0.202914 +vt 0.256845 0.173957 +vt 0.237443 0.173956 +vt 0.256846 0.145001 +vt 0.237444 0.145000 +vt 0.256847 0.116044 +vt 0.237446 0.116043 +vt 0.256848 0.087089 +vt 0.237447 0.087088 +vt 0.256849 0.058134 +vt 0.237449 0.058133 +vt 0.256850 0.029180 +vt 0.237450 0.029179 +vt 0.256852 0.000226 +vt 0.237452 0.000225 +vt 0.237433 0.347711 +vt 0.256839 0.347712 +vt 0.237432 0.376673 +vt 0.256838 0.376674 +vt 0.237431 0.405636 +vt 0.256837 0.405637 +vt 0.237430 0.434601 +vt 0.256837 0.434601 +vt 0.237429 0.463567 +vt 0.256838 0.463567 +vt 0.392072 0.116043 +vt 0.411472 0.087086 +vt 0.411474 0.116042 +vt 0.392074 0.144999 +vt 0.411476 0.144998 +vt 0.392071 0.087087 +vt 0.411469 0.058130 +vt 0.392068 0.058132 +vt 0.411467 0.029175 +vt 0.392066 0.029177 +vt 0.411463 0.000221 +vt 0.392064 0.000223 +vt 0.392076 0.173956 +vt 0.411478 0.173955 +vt 0.392077 0.202913 +vt 0.411480 0.202912 +vt 0.392079 0.231871 +vt 0.411481 0.231870 +vt 0.392080 0.260829 +vt 0.411483 0.260828 +vt 0.392082 0.289788 +vt 0.411485 0.289787 +vt 0.392084 0.318747 +vt 0.411488 0.318746 +vt 0.392086 0.347707 +vt 0.411490 0.347705 +vt 0.392089 0.376667 +vt 0.411493 0.376665 +vt 0.392093 0.405628 +vt 0.411497 0.405625 +vt 0.392097 0.434589 +vt 0.411501 0.434585 +vt 0.392102 0.463550 +vt 0.411507 0.463546 +vt 0.082827 0.058117 +vt 0.102232 0.029164 +vt 0.102228 0.058119 +vt 0.082823 0.087072 +vt 0.102224 0.087075 +vt 0.082831 0.029162 +vt 0.102236 0.000209 +vt 0.082835 0.000207 +vt 0.082819 0.116028 +vt 0.102221 0.116031 +vt 0.082815 0.144984 +vt 0.102217 0.144987 +vt 0.082811 0.173940 +vt 0.102213 0.173943 +vt 0.082806 0.202897 +vt 0.102209 0.202900 +vt 0.082802 0.231854 +vt 0.102204 0.231857 +vt 0.082797 0.260812 +vt 0.102200 0.260815 +vt 0.082791 0.289770 +vt 0.102194 0.289774 +vt 0.082785 0.318729 +vt 0.102189 0.318733 +vt 0.082779 0.347689 +vt 0.102183 0.347693 +vt 0.082772 0.376649 +vt 0.102177 0.376654 +vt 0.082764 0.405611 +vt 0.102170 0.405616 +vt 0.082755 0.434573 +vt 0.102162 0.434579 +vt 0.082745 0.463537 +vt 0.102153 0.463544 +vt 0.363131 0.405631 +vt 0.343729 0.434595 +vt 0.343726 0.405633 +vt 0.363129 0.376670 +vt 0.343724 0.376671 +vt 0.363135 0.434593 +vt 0.343733 0.463559 +vt 0.363139 0.463555 +vt 0.363126 0.347709 +vt 0.343722 0.347710 +vt 0.363124 0.318749 +vt 0.343720 0.318750 +vt 0.363123 0.289790 +vt 0.343719 0.289791 +vt 0.363122 0.260831 +vt 0.343718 0.260832 +vt 0.363121 0.231873 +vt 0.343718 0.231873 +vt 0.363120 0.202915 +vt 0.343717 0.202915 +vt 0.363118 0.173957 +vt 0.343716 0.173958 +vt 0.363117 0.145001 +vt 0.343716 0.145001 +vt 0.363116 0.116044 +vt 0.343715 0.116045 +vt 0.363115 0.087089 +vt 0.343714 0.087089 +vt 0.363114 0.058133 +vt 0.343713 0.058134 +vt 0.363112 0.029179 +vt 0.343712 0.029180 +vt 0.363110 0.000226 +vt 0.343711 0.000226 +vt 0.517748 0.144989 +vt 0.498349 0.173948 +vt 0.498346 0.144991 +vt 0.517745 0.116032 +vt 0.498343 0.116034 +vt 0.517751 0.173946 +vt 0.498352 0.202905 +vt 0.517754 0.202903 +vt 0.498355 0.231863 +vt 0.517757 0.231861 +vt 0.498358 0.260820 +vt 0.517760 0.260818 +vt 0.498361 0.289778 +vt 0.517763 0.289776 +vt 0.498364 0.318737 +vt 0.517767 0.318734 +vt 0.498367 0.347695 +vt 0.517770 0.347693 +vt 0.498371 0.376653 +vt 0.517774 0.376651 +vt 0.498375 0.405612 +vt 0.517778 0.405609 +vt 0.498379 0.434570 +vt 0.517782 0.434567 +vt 0.498384 0.463528 +vt 0.517787 0.463525 +vt 0.517742 0.087075 +vt 0.498340 0.087077 +vt 0.517739 0.058119 +vt 0.498337 0.058121 +vt 0.517735 0.029162 +vt 0.498333 0.029165 +vt 0.517731 0.000205 +vt 0.498329 0.000208 +vt 0.208499 0.000223 +vt 0.189096 0.029175 +vt 0.189099 0.000221 +vt 0.208496 0.029177 +vt 0.189093 0.058129 +vt 0.208494 0.058131 +vt 0.189091 0.087084 +vt 0.208492 0.087086 +vt 0.189088 0.116040 +vt 0.208490 0.116042 +vt 0.189086 0.144996 +vt 0.208488 0.144998 +vt 0.189083 0.173953 +vt 0.208486 0.173955 +vt 0.189081 0.202910 +vt 0.208483 0.202912 +vt 0.189078 0.231868 +vt 0.208481 0.231870 +vt 0.189076 0.260827 +vt 0.208479 0.260829 +vt 0.189073 0.289786 +vt 0.208477 0.289788 +vt 0.189070 0.318746 +vt 0.208474 0.318748 +vt 0.189067 0.347707 +vt 0.208472 0.347709 +vt 0.189063 0.376669 +vt 0.208469 0.376671 +vt 0.189060 0.405633 +vt 0.208467 0.405635 +vt 0.189056 0.434597 +vt 0.208464 0.434599 +vt 0.189053 0.463564 +vt 0.208462 0.463566 +vt 0.546692 0.029158 +vt 0.546688 0.000201 +vt 0.546696 0.058115 +vt 0.546699 0.087072 +vt 0.546702 0.116029 +vt 0.546705 0.144986 +vt 0.546709 0.173943 +vt 0.546712 0.202900 +vt 0.546715 0.231858 +vt 0.546718 0.260815 +vt 0.546721 0.289773 +vt 0.546725 0.318731 +vt 0.546728 0.347689 +vt 0.546732 0.376647 +vt 0.546736 0.405605 +vt 0.546740 0.434563 +vt 0.546744 0.463521 +vt 0.779682 0.749443 +vt 0.744378 0.806538 +vt 0.744377 0.749444 +vt 0.713049 0.806539 +vt 0.713048 0.749445 +vt 0.744376 0.682422 +vt 0.713047 0.682423 +vt 0.779683 0.806538 +vt 0.779681 0.682421 +vt 0.779683 0.825941 +vt 0.744379 0.825941 +vt 0.713050 0.825941 +vt 0.744378 0.869946 +vt 0.713050 0.869946 +vt 0.744378 0.894818 +vt 0.818664 0.869946 +vt 0.713050 0.894818 +vt 0.818664 0.894818 +vt 0.655778 0.806540 +vt 0.655777 0.749446 +vt 0.655775 0.682424 +vt 0.569547 0.749447 +vt 0.538217 0.682426 +vt 0.569546 0.682425 +vt 0.626817 0.682425 +vt 0.538218 0.749448 +vt 0.502912 0.682427 +vt 0.502914 0.806542 +vt 0.502913 0.749448 +vt 0.538218 0.806541 +vt 0.502915 0.825944 +vt 0.538219 0.825944 +vt 0.569547 0.806541 +vt 0.569547 0.825944 +vt 0.569546 0.869948 +vt 0.538218 0.869947 +vt 0.626818 0.749446 +vt 0.626819 0.806540 +vt 0.569546 0.894819 +vt 0.538218 0.894819 +vt 0.463933 0.894818 +vt 0.463933 0.869946 +vt 0.603794 0.116022 +vt 0.603790 0.087065 +vt 0.603797 0.144979 +vt 0.603801 0.173936 +vt 0.603804 0.202894 +vt 0.603808 0.231851 +vt 0.603811 0.260809 +vt 0.603814 0.289766 +vt 0.603818 0.318724 +vt 0.603822 0.347682 +vt 0.603825 0.376640 +vt 0.603829 0.405597 +vt 0.603833 0.434555 +vt 0.603837 0.463513 +vt 0.603787 0.058108 +vt 0.603783 0.029151 +vt 0.603779 0.000194 +vt 0.029149 0.999750 +vt 0.000194 0.999747 +vt 0.058105 0.999753 +vt 0.087060 0.999756 +vt 0.116016 0.999760 +vt 0.144972 0.999764 +vt 0.173929 0.999768 +vt 0.202887 0.999773 +vt 0.231845 0.999778 +vt 0.260805 0.999783 +vt 0.289765 0.999787 +vt 0.318726 0.999792 +vt 0.347687 0.999795 +vt 0.376649 0.999799 +vt 0.405612 0.999801 +vt 0.434575 0.999804 +vt 0.463537 0.999806 +vt 0.057370 0.144980 +vt 0.057374 0.116024 +vt 0.057379 0.087069 +vt 0.057365 0.173936 +vt 0.057361 0.202893 +vt 0.057355 0.231850 +vt 0.057350 0.260807 +vt 0.057344 0.289765 +vt 0.057338 0.318724 +vt 0.057331 0.347683 +vt 0.057323 0.376643 +vt 0.057314 0.405603 +vt 0.057305 0.434564 +vt 0.057294 0.463526 +vt 0.057383 0.058113 +vt 0.057387 0.029158 +vt 0.057391 0.000203 +vt 0.314758 0.000227 +vt 0.314758 0.029181 +vt 0.285805 0.000227 +vt 0.314758 0.058135 +vt 0.285804 0.029180 +vt 0.314759 0.087090 +vt 0.285804 0.058135 +vt 0.285803 0.087090 +vt 0.314759 0.116045 +vt 0.285803 0.116045 +vt 0.314759 0.145002 +vt 0.285802 0.145001 +vt 0.314759 0.173958 +vt 0.285802 0.173958 +vt 0.314759 0.202916 +vt 0.285802 0.202915 +vt 0.314759 0.231874 +vt 0.285801 0.231873 +vt 0.314760 0.260832 +vt 0.285801 0.260832 +vt 0.314760 0.289791 +vt 0.285800 0.289791 +vt 0.314760 0.318751 +vt 0.285800 0.318751 +vt 0.314761 0.347712 +vt 0.285800 0.347712 +vt 0.314762 0.376673 +vt 0.285800 0.376674 +vt 0.314764 0.405635 +vt 0.285801 0.405637 +vt 0.314766 0.434598 +vt 0.285802 0.434600 +vt 0.314769 0.463562 +vt 0.285804 0.463565 +vt 0.160145 0.000217 +vt 0.160142 0.029172 +vt 0.131191 0.000214 +vt 0.160138 0.058126 +vt 0.131187 0.029168 +vt 0.160135 0.087082 +vt 0.131183 0.058123 +vt 0.131180 0.087078 +vt 0.160132 0.116037 +vt 0.131176 0.116034 +vt 0.160129 0.144994 +vt 0.131173 0.144990 +vt 0.160126 0.173950 +vt 0.131170 0.173947 +vt 0.160123 0.202907 +vt 0.131166 0.202904 +vt 0.160120 0.231865 +vt 0.131162 0.231862 +vt 0.160117 0.260824 +vt 0.131158 0.260820 +vt 0.160113 0.289783 +vt 0.131154 0.289779 +vt 0.160109 0.318743 +vt 0.131149 0.318739 +vt 0.160105 0.347704 +vt 0.131144 0.347699 +vt 0.160101 0.376666 +vt 0.131138 0.376660 +vt 0.160096 0.405629 +vt 0.131132 0.405623 +vt 0.160091 0.434593 +vt 0.131126 0.434587 +vt 0.160085 0.463559 +vt 0.131119 0.463552 +vt 0.469373 0.000213 +vt 0.469377 0.029168 +vt 0.440418 0.000217 +vt 0.469381 0.058124 +vt 0.440421 0.029172 +vt 0.469384 0.087080 +vt 0.440425 0.058127 +vt 0.440428 0.087083 +vt 0.469387 0.116037 +vt 0.440430 0.116039 +vt 0.469389 0.144994 +vt 0.440433 0.144996 +vt 0.469392 0.173951 +vt 0.440435 0.173953 +vt 0.469394 0.202908 +vt 0.440437 0.202910 +vt 0.469397 0.231865 +vt 0.440439 0.231868 +vt 0.469400 0.260823 +vt 0.440442 0.260826 +vt 0.469402 0.289781 +vt 0.440444 0.289784 +vt 0.469405 0.318740 +vt 0.440447 0.318743 +vt 0.469409 0.347699 +vt 0.440450 0.347702 +vt 0.469412 0.376657 +vt 0.440453 0.376661 +vt 0.469416 0.405616 +vt 0.440457 0.405620 +vt 0.469421 0.434575 +vt 0.440461 0.434580 +vt 0.469426 0.463534 +vt 0.440467 0.463540 +vt 0.000206 0.434543 +vt 0.000194 0.463503 +vt 0.000217 0.405584 +vt 0.000226 0.376625 +vt 0.000235 0.347667 +vt 0.000244 0.318709 +vt 0.000251 0.289752 +vt 0.000258 0.260795 +vt 0.000264 0.231838 +vt 0.000270 0.202882 +vt 0.000276 0.173926 +vt 0.000281 0.144971 +vt 0.000285 0.116015 +vt 0.000290 0.087060 +vt 0.000294 0.058105 +vt 0.000299 0.029149 +vt 0.000303 0.000194 +vt 0.666640 0.558125 +vt 0.637681 0.558127 +vt 0.604225 0.133183 +vt 0.639530 0.104225 +vt 0.639530 0.133183 +vt 0.604225 0.104225 +vt 0.661494 0.463564 +vt 0.680897 0.434607 +vt 0.680897 0.463565 +vt 0.724902 0.434608 +vt 0.724902 0.463566 +vt 0.661495 0.434607 +vt 0.749775 0.434608 +vt 0.749774 0.463567 +vt 0.683535 0.104225 +vt 0.683535 0.133183 +vt 0.781104 0.434608 +vt 0.781104 0.463567 +vt 0.855393 0.434608 +vt 0.855393 0.463567 +vt 0.666641 0.593430 +vt 0.637683 0.593431 +vt 0.666643 0.624759 +vt 0.637685 0.624760 +vt 0.666646 0.682031 +vt 0.637688 0.682033 +vt 0.604225 0.463561 +vt 0.604227 0.434604 +vt 0.757821 0.133183 +vt 0.782694 0.104225 +vt 0.782694 0.133183 +vt 0.757821 0.104225 +s off +f 1/1 2/2 3/3 +f 4/4 1/1 3/3 +f 4/4 3/3 5/5 +f 1/1 6/6 2/2 +f 6/6 7/7 2/2 +f 6/6 8/8 7/7 +f 8/8 9/9 7/7 +f 8/8 10/10 9/9 +f 10/10 11/11 9/9 +f 10/10 12/12 11/11 +f 13/13 4/4 5/5 +f 13/13 5/5 14/14 +f 15/15 13/13 14/14 +f 15/15 14/14 16/16 +f 17/17 15/15 16/16 +f 17/17 16/16 18/18 +f 19/19 17/17 18/18 +f 19/19 18/18 20/20 +f 21/21 19/19 20/20 +f 21/21 20/20 22/22 +f 23/23 21/21 22/22 +f 23/23 22/22 24/24 +f 25/25 23/23 24/24 +f 25/25 24/24 26/26 +f 27/27 25/25 26/26 +f 27/27 26/26 28/28 +f 29/29 27/27 28/28 +f 29/29 28/28 30/30 +f 31/31 29/29 30/30 +f 31/31 30/30 32/32 +f 33/33 31/31 32/32 +f 33/33 32/32 34/34 +f 35/35 36/36 37/37 +f 38/38 35/35 37/37 +f 38/38 37/37 39/39 +f 35/35 40/40 36/36 +f 40/40 41/41 36/36 +f 40/40 42/42 41/41 +f 42/42 43/43 41/41 +f 42/42 44/44 43/43 +f 44/44 45/45 43/43 +f 44/44 46/46 45/45 +f 46/46 47/47 45/45 +f 46/46 48/48 47/47 +f 48/48 49/49 47/47 +f 48/48 50/50 49/49 +f 50/50 51/51 49/49 +f 50/50 52/52 51/51 +f 52/52 53/53 51/51 +f 52/52 54/54 53/53 +f 54/54 55/55 53/53 +f 54/54 56/56 55/55 +f 56/56 57/57 55/55 +f 56/56 58/58 57/57 +f 58/58 59/59 57/57 +f 58/58 60/60 59/59 +f 60/60 61/61 59/59 +f 60/60 62/62 61/61 +f 62/62 63/63 61/61 +f 62/62 64/64 63/63 +f 64/64 65/65 63/63 +f 64/64 66/66 65/65 +f 66/66 67/67 65/65 +f 66/66 68/68 67/67 +f 69/69 70/70 71/71 +f 72/72 69/69 71/71 +f 72/72 71/71 73/73 +f 69/69 74/74 70/70 +f 74/74 75/75 70/70 +f 74/74 76/76 75/75 +f 76/76 77/77 75/75 +f 76/76 78/78 77/77 +f 79/79 72/72 73/73 +f 79/79 73/73 80/80 +f 81/81 79/79 80/80 +f 81/81 80/80 82/82 +f 83/83 81/81 82/82 +f 83/83 82/82 84/84 +f 85/85 83/83 84/84 +f 85/85 84/84 86/86 +f 87/87 85/85 86/86 +f 87/87 86/86 88/88 +f 89/89 87/87 88/88 +f 89/89 88/88 90/90 +f 91/91 89/89 90/90 +f 91/91 90/90 92/92 +f 93/93 91/91 92/92 +f 93/93 92/92 94/94 +f 95/95 93/93 94/94 +f 95/95 94/94 96/96 +f 97/97 95/95 96/96 +f 97/97 96/96 98/98 +f 99/99 97/97 98/98 +f 99/99 98/98 100/100 +f 101/101 99/99 100/100 +f 101/101 100/100 102/102 +f 103/103 104/104 105/105 +f 106/106 103/103 105/105 +f 106/106 105/105 107/107 +f 103/103 108/108 104/104 +f 108/108 109/109 104/104 +f 108/108 110/110 109/109 +f 110/110 111/111 109/109 +f 110/110 112/112 111/111 +f 112/112 113/113 111/111 +f 112/112 114/114 113/113 +f 114/114 115/115 113/113 +f 114/114 116/116 115/115 +f 117/117 106/106 107/107 +f 117/117 107/107 118/118 +f 119/119 117/117 118/118 +f 119/119 118/118 120/120 +f 121/121 119/119 120/120 +f 121/121 120/120 122/122 +f 123/123 121/121 122/122 +f 123/123 122/122 124/124 +f 125/125 123/123 124/124 +f 125/125 124/124 126/126 +f 127/127 125/125 126/126 +f 127/127 126/126 128/128 +f 129/129 127/127 128/128 +f 129/129 128/128 130/130 +f 131/131 129/129 130/130 +f 131/131 130/130 132/132 +f 133/133 131/131 132/132 +f 133/133 132/132 134/134 +f 135/135 133/133 134/134 +f 135/135 134/134 136/136 +f 137/137 138/138 139/139 +f 140/140 137/137 139/139 +f 140/140 139/139 141/141 +f 137/137 142/142 138/138 +f 142/142 143/143 138/138 +f 142/142 144/144 143/143 +f 145/145 140/140 141/141 +f 145/145 141/141 146/146 +f 147/147 145/145 146/146 +f 147/147 146/146 148/148 +f 149/149 147/147 148/148 +f 149/149 148/148 150/150 +f 151/151 149/149 150/150 +f 151/151 150/150 152/152 +f 153/153 151/151 152/152 +f 153/153 152/152 154/154 +f 155/155 153/153 154/154 +f 155/155 154/154 156/156 +f 157/157 155/155 156/156 +f 157/157 156/156 158/158 +f 159/159 157/157 158/158 +f 159/159 158/158 160/160 +f 161/161 159/159 160/160 +f 161/161 160/160 162/162 +f 163/163 161/161 162/162 +f 163/163 162/162 164/164 +f 165/165 163/163 164/164 +f 165/165 164/164 166/166 +f 167/167 165/165 166/166 +f 167/167 166/166 168/168 +f 169/169 167/167 168/168 +f 169/169 168/168 170/170 +f 171/171 172/172 173/173 +f 68/174 171/171 173/173 +f 68/174 173/173 67/175 +f 171/171 174/176 172/172 +f 174/176 136/177 172/172 +f 174/176 135/178 136/177 +f 174/176 171/171 175/179 +f 174/176 175/179 176/180 +f 135/178 174/176 176/180 +f 135/178 176/180 177/181 +f 178/182 135/178 177/181 +f 177/181 176/180 179/183 +f 176/180 175/179 180/184 +f 176/180 180/184 179/183 +f 175/179 181/185 182/186 +f 175/179 182/186 180/184 +f 171/171 181/185 175/179 +f 171/171 68/174 181/185 +f 68/174 183/187 181/185 +f 68/174 184/188 183/187 +f 177/181 179/183 185/189 +f 178/182 177/181 186/190 +f 187/191 186/190 188/192 +f 189/193 178/182 186/190 +f 189/193 186/190 187/191 +f 190/194 187/191 191/195 +f 187/191 188/192 191/195 +f 192/196 189/193 187/191 +f 192/196 187/191 190/194 +f 178/182 189/193 193/197 +f 189/193 192/196 194/198 +f 189/193 194/198 193/197 +f 178/182 193/197 195/199 +f 192/196 102/200 194/198 +f 192/196 101/201 102/200 +f 101/201 192/196 190/194 +f 144/202 101/201 196/203 +f 101/201 190/194 196/203 +f 144/202 197/204 198/205 +f 144/202 198/205 143/206 +f 197/204 144/202 199/207 +f 144/202 196/203 199/207 +f 196/203 190/194 200/208 +f 196/203 200/208 201/209 +f 190/194 191/195 200/208 +f 202/210 199/207 203/211 +f 197/204 199/207 202/210 +f 202/210 203/211 204/212 +f 205/213 202/210 204/212 +f 206/214 197/204 202/210 +f 206/214 202/210 205/213 +f 205/213 204/212 207/215 +f 208/216 205/213 207/215 +f 33/217 206/214 205/213 +f 33/217 205/213 208/216 +f 206/214 33/217 34/218 +f 206/214 34/218 209/219 +f 197/204 206/214 209/219 +f 197/204 209/219 198/205 +f 33/217 208/216 210/220 +f 33/217 210/220 211/221 +f 208/216 207/215 212/222 +f 213/223 214/224 215/225 +f 216/226 213/223 215/225 +f 216/226 215/225 217/227 +f 213/223 218/228 214/224 +f 218/228 219/229 214/224 +f 218/228 220/230 219/229 +f 220/230 221/231 219/229 +f 220/230 222/232 221/231 +f 222/232 223/233 221/231 +f 222/232 224/234 223/233 +f 224/234 225/235 223/233 +f 224/234 226/236 225/235 +f 226/236 195/237 225/235 +f 226/236 178/238 195/237 +f 227/239 216/226 217/227 +f 227/239 217/227 228/240 +f 229/241 227/239 228/240 +f 229/241 228/240 230/242 +f 231/243 229/241 230/242 +f 231/243 230/242 232/244 +f 233/245 231/243 232/244 +f 233/245 232/244 234/246 +f 235/247 233/245 234/246 +f 235/247 234/246 236/248 +f 237/249 235/247 236/248 +f 237/249 236/248 238/250 +f 239/251 237/249 238/250 +f 239/251 238/250 240/252 +f 241/253 239/251 240/252 +f 241/253 240/252 242/254 +f 243/255 241/253 242/254 +f 243/255 242/254 244/256 +f 116/257 245/258 115/259 +f 116/257 246/260 245/258 +f 246/260 116/257 247/261 +f 116/257 243/262 248/263 +f 116/257 248/263 247/261 +f 246/260 249/264 245/258 +f 246/260 250/265 249/264 +f 250/265 246/260 251/266 +f 246/260 247/261 251/266 +f 251/266 247/261 252/267 +f 253/268 251/266 254/269 +f 251/266 252/267 254/269 +f 250/265 251/266 253/268 +f 250/265 38/270 39/271 +f 250/265 39/271 249/264 +f 38/270 250/265 253/268 +f 253/268 254/269 255/272 +f 256/273 253/268 255/272 +f 38/270 253/268 256/273 +f 257/274 38/270 256/273 +f 256/273 255/272 258/275 +f 257/274 256/273 259/276 +f 248/263 260/277 261/278 +f 248/263 261/278 262/279 +f 243/262 260/277 248/263 +f 243/262 263/280 260/277 +f 263/280 243/262 244/281 +f 263/280 244/281 264/282 +f 265/283 263/280 264/282 +f 265/283 264/282 266/284 +f 78/285 265/283 266/284 +f 265/283 78/285 267/286 +f 265/283 267/286 268/287 +f 78/285 266/284 77/288 +f 78/285 169/289 269/290 +f 78/285 269/290 267/286 +f 268/287 267/286 270/291 +f 268/287 270/291 271/292 +f 269/290 272/293 273/294 +f 269/290 273/294 274/295 +f 169/289 272/293 269/290 +f 275/296 169/289 170/297 +f 169/289 275/296 272/293 +f 272/293 276/298 277/299 +f 272/293 277/299 273/294 +f 275/296 276/298 272/293 +f 278/300 275/296 279/301 +f 275/296 170/297 279/301 +f 275/296 278/300 276/298 +f 276/298 280/302 281/303 +f 276/298 281/303 277/299 +f 278/300 280/302 276/298 +f 278/300 279/301 282/304 +f 12/305 278/300 282/304 +f 278/300 12/305 280/302 +f 280/302 12/305 283/306 +f 280/302 283/306 284/307 +f 12/305 282/304 11/308 +f 133/133 178/238 226/236 +f 131/131 133/133 226/236 +f 131/131 226/236 224/234 +f 133/133 135/135 178/238 +f 129/129 131/131 224/234 +f 129/129 224/234 222/232 +f 127/127 129/129 222/232 +f 127/127 222/232 220/230 +f 125/125 127/127 220/230 +f 125/125 220/230 218/228 +f 123/123 125/125 218/228 +f 123/123 218/228 213/223 +f 121/121 123/123 213/223 +f 121/121 213/223 216/226 +f 119/119 121/121 216/226 +f 119/119 216/226 227/239 +f 117/117 119/119 227/239 +f 117/117 227/239 229/241 +f 106/106 117/117 229/241 +f 106/106 229/241 231/243 +f 103/103 106/106 231/243 +f 103/103 231/243 233/245 +f 108/108 103/103 233/245 +f 108/108 233/245 235/247 +f 110/110 108/108 235/247 +f 110/110 235/247 237/249 +f 112/112 110/110 237/249 +f 112/112 237/249 239/251 +f 114/114 112/112 239/251 +f 114/114 239/251 241/253 +f 116/116 114/114 241/253 +f 116/116 241/253 243/255 +f 99/99 144/144 142/142 +f 97/97 99/99 142/142 +f 97/97 142/142 137/137 +f 99/99 101/101 144/144 +f 95/95 97/97 137/137 +f 95/95 137/137 140/140 +f 93/93 95/95 140/140 +f 93/93 140/140 145/145 +f 91/91 93/93 145/145 +f 91/91 145/145 147/147 +f 89/89 91/91 147/147 +f 89/89 147/147 149/149 +f 87/87 89/89 149/149 +f 87/87 149/149 151/151 +f 85/85 87/87 151/151 +f 85/85 151/151 153/153 +f 83/83 85/85 153/153 +f 83/83 153/153 155/155 +f 81/81 83/83 155/155 +f 81/81 155/155 157/157 +f 79/79 81/81 157/157 +f 79/79 157/157 159/159 +f 72/72 79/79 159/159 +f 72/72 159/159 161/161 +f 69/69 72/72 161/161 +f 69/69 161/161 163/163 +f 74/74 69/69 163/163 +f 74/74 163/163 165/165 +f 76/76 74/74 165/165 +f 76/76 165/165 167/167 +f 78/78 76/76 167/167 +f 78/78 167/167 169/169 +f 285/309 68/68 66/66 +f 286/310 285/309 66/66 +f 286/310 66/66 64/64 +f 285/309 184/311 68/68 +f 287/312 286/310 64/64 +f 287/312 64/64 62/62 +f 288/313 287/312 62/62 +f 288/313 62/62 60/60 +f 289/314 288/313 60/60 +f 289/314 60/60 58/58 +f 290/315 289/314 58/58 +f 290/315 58/58 56/56 +f 291/316 290/315 56/56 +f 291/316 56/56 54/54 +f 292/317 291/316 54/54 +f 292/317 54/54 52/52 +f 293/318 292/317 52/52 +f 293/318 52/52 50/50 +f 294/319 293/318 50/50 +f 294/319 50/50 48/48 +f 295/320 294/319 48/48 +f 295/320 48/48 46/46 +f 296/321 295/320 46/46 +f 296/321 46/46 44/44 +f 297/322 296/321 44/44 +f 297/322 44/44 42/42 +f 298/323 297/322 42/42 +f 298/323 42/42 40/40 +f 299/324 298/323 40/40 +f 299/324 40/40 35/35 +f 257/325 299/324 35/35 +f 257/325 35/35 38/38 +f 300/326 22/22 20/20 +f 301/327 300/326 20/20 +f 301/327 20/20 18/18 +f 300/326 302/328 22/22 +f 302/328 24/24 22/22 +f 303/329 304/330 302/328 +f 302/328 304/330 24/24 +f 305/331 303/329 302/328 +f 305/331 302/328 300/326 +f 304/330 26/26 24/24 +f 304/330 306/332 26/26 +f 307/333 306/332 304/330 +f 303/329 307/333 304/330 +f 152/152 150/150 303/329 +f 152/152 303/329 305/331 +f 150/150 307/333 303/329 +f 154/154 152/152 305/331 +f 154/154 305/331 308/334 +f 308/334 305/331 300/326 +f 156/156 154/154 308/334 +f 156/156 308/334 309/335 +f 309/335 308/334 301/327 +f 308/334 300/326 301/327 +f 158/158 156/156 309/335 +f 158/158 309/335 310/336 +f 309/335 301/327 311/337 +f 310/336 309/335 311/337 +f 311/337 301/327 18/18 +f 311/337 18/18 16/16 +f 310/336 311/337 312/338 +f 312/338 311/337 16/16 +f 160/160 158/158 310/336 +f 160/160 310/336 313/339 +f 313/339 310/336 312/338 +f 314/340 312/338 14/14 +f 312/338 16/16 14/14 +f 313/339 312/338 314/340 +f 315/341 313/339 314/340 +f 162/162 160/160 313/339 +f 162/162 313/339 315/341 +f 314/340 14/14 5/5 +f 315/341 314/340 316/342 +f 316/342 314/340 5/5 +f 164/164 162/162 315/341 +f 164/164 315/341 317/343 +f 317/343 315/341 316/342 +f 318/344 316/342 3/3 +f 316/342 5/5 3/3 +f 317/343 316/342 318/344 +f 166/166 164/164 317/343 +f 166/166 317/343 319/345 +f 319/345 317/343 318/344 +f 318/344 3/3 2/2 +f 319/345 318/344 320/346 +f 320/346 318/344 2/2 +f 168/168 166/166 319/345 +f 168/168 319/345 321/347 +f 321/347 319/345 320/346 +f 322/348 320/346 7/7 +f 320/346 2/2 7/7 +f 321/347 320/346 322/348 +f 170/170 168/168 321/347 +f 170/170 321/347 279/349 +f 279/349 321/347 322/348 +f 322/348 7/7 9/9 +f 279/349 322/348 282/350 +f 282/350 322/348 9/9 +f 282/350 9/9 11/11 +f 148/148 323/351 307/333 +f 150/150 148/148 307/333 +f 307/333 323/351 306/332 +f 148/148 146/146 323/351 +f 323/351 324/352 325/353 +f 323/351 325/353 306/332 +f 146/146 324/352 323/351 +f 306/332 325/353 28/28 +f 306/332 28/28 26/26 +f 325/353 326/354 30/30 +f 325/353 30/30 28/28 +f 324/352 326/354 325/353 +f 141/141 327/355 324/352 +f 324/352 327/355 326/354 +f 146/146 141/141 324/352 +f 327/355 328/356 326/354 +f 326/354 328/356 32/32 +f 326/354 32/32 30/30 +f 141/141 139/139 327/355 +f 139/139 329/357 327/355 +f 327/355 329/357 328/356 +f 328/356 209/358 34/34 +f 328/356 34/34 32/32 +f 329/357 209/358 328/356 +f 138/138 198/359 329/357 +f 139/139 138/138 329/357 +f 329/357 198/359 209/358 +f 138/138 143/143 198/359 +f 330/360 90/90 88/88 +f 331/361 330/360 88/88 +f 331/361 88/88 86/86 +f 330/360 332/362 90/90 +f 332/362 92/92 90/90 +f 333/363 334/364 332/362 +f 332/362 334/364 92/92 +f 335/365 333/363 332/362 +f 335/365 332/362 330/360 +f 334/364 94/94 92/92 +f 334/364 336/366 94/94 +f 337/367 336/366 334/364 +f 333/363 337/367 334/364 +f 217/227 215/225 333/363 +f 217/227 333/363 335/365 +f 215/225 337/367 333/363 +f 338/368 335/365 330/360 +f 228/240 217/227 335/365 +f 228/240 335/365 338/368 +f 230/242 228/240 338/368 +f 230/242 338/368 339/369 +f 338/368 330/360 331/361 +f 339/369 338/368 331/361 +f 232/244 230/242 339/369 +f 232/244 339/369 340/370 +f 339/369 331/361 341/371 +f 340/370 339/369 341/371 +f 341/371 331/361 86/86 +f 341/371 86/86 84/84 +f 340/370 341/371 342/372 +f 342/372 341/371 84/84 +f 234/246 232/244 340/370 +f 234/246 340/370 343/373 +f 343/373 340/370 342/372 +f 344/374 342/372 82/82 +f 342/372 84/84 82/82 +f 343/373 342/372 344/374 +f 236/248 234/246 343/373 +f 236/248 343/373 345/375 +f 345/375 343/373 344/374 +f 344/374 82/82 80/80 +f 345/375 344/374 346/376 +f 346/376 344/374 80/80 +f 238/250 236/248 345/375 +f 238/250 345/375 347/377 +f 347/377 345/375 346/376 +f 348/378 346/376 73/73 +f 346/376 80/80 73/73 +f 347/377 346/376 348/378 +f 240/252 238/250 347/377 +f 240/252 347/377 349/379 +f 349/379 347/377 348/378 +f 348/378 73/73 71/71 +f 349/379 348/378 350/380 +f 350/380 348/378 71/71 +f 242/254 240/252 349/379 +f 242/254 349/379 351/381 +f 351/381 349/379 350/380 +f 352/382 350/380 70/70 +f 350/380 71/71 70/70 +f 351/381 350/380 352/382 +f 244/256 242/254 351/381 +f 244/256 351/381 264/383 +f 264/383 351/381 352/382 +f 352/382 70/70 75/75 +f 264/383 352/382 266/384 +f 266/384 352/382 75/75 +f 266/384 75/75 77/77 +f 214/224 353/385 337/367 +f 215/225 214/224 337/367 +f 337/367 353/385 336/366 +f 214/224 219/229 353/385 +f 219/229 354/386 353/385 +f 353/385 354/386 355/387 +f 353/385 355/387 336/366 +f 336/366 355/387 96/96 +f 336/366 96/96 94/94 +f 355/387 356/388 98/98 +f 355/387 98/98 96/96 +f 354/386 356/388 355/387 +f 221/231 357/389 354/386 +f 219/229 221/231 354/386 +f 354/386 357/389 356/388 +f 357/389 358/390 356/388 +f 356/388 358/390 100/100 +f 356/388 100/100 98/98 +f 221/231 223/233 357/389 +f 223/233 359/391 357/389 +f 357/389 359/391 358/390 +f 358/390 194/392 102/102 +f 358/390 102/102 100/100 +f 359/391 194/392 358/390 +f 225/235 193/393 359/391 +f 223/233 225/235 359/391 +f 359/391 193/393 194/392 +f 225/235 195/237 193/393 +f 360/394 107/107 105/105 +f 361/395 360/394 105/105 +f 361/395 105/105 104/104 +f 360/394 362/396 107/107 +f 362/396 118/118 107/107 +f 363/397 364/398 362/396 +f 362/396 364/398 118/118 +f 365/399 363/397 362/396 +f 365/399 362/396 360/394 +f 364/398 120/120 118/118 +f 364/398 366/400 120/120 +f 367/401 366/400 364/398 +f 363/397 367/401 364/398 +f 45/45 47/47 363/397 +f 45/45 363/397 365/399 +f 47/47 367/401 363/397 +f 368/402 365/399 360/394 +f 43/43 45/45 365/399 +f 43/43 365/399 368/402 +f 41/41 43/43 368/402 +f 41/41 368/402 369/403 +f 368/402 360/394 361/395 +f 369/403 368/402 361/395 +f 36/36 41/41 369/403 +f 36/36 369/403 370/404 +f 369/403 361/395 371/405 +f 370/404 369/403 371/405 +f 371/405 361/395 104/104 +f 371/405 104/104 109/109 +f 370/404 371/405 372/406 +f 372/406 371/405 109/109 +f 37/37 36/36 370/404 +f 37/37 370/404 373/407 +f 373/407 370/404 372/406 +f 374/408 372/406 111/111 +f 372/406 109/109 111/111 +f 373/407 372/406 374/408 +f 39/39 37/37 373/407 +f 39/39 373/407 249/409 +f 249/409 373/407 374/408 +f 374/408 111/111 113/113 +f 249/409 374/408 245/410 +f 245/410 374/408 113/113 +f 245/410 113/113 115/115 +f 49/49 375/411 367/401 +f 47/47 49/49 367/401 +f 367/401 375/411 366/400 +f 49/49 51/51 375/411 +f 51/51 376/412 375/411 +f 375/411 376/412 377/413 +f 375/411 377/413 366/400 +f 366/400 377/413 122/122 +f 366/400 122/122 120/120 +f 377/413 378/414 124/124 +f 377/413 124/124 122/122 +f 376/412 378/414 377/413 +f 53/53 379/415 376/412 +f 51/51 53/53 376/412 +f 376/412 379/415 378/414 +f 379/415 380/416 378/414 +f 378/414 380/416 126/126 +f 378/414 126/126 124/124 +f 53/53 55/55 379/415 +f 55/55 381/417 379/415 +f 379/415 381/417 380/416 +f 380/416 382/418 128/128 +f 380/416 128/128 126/126 +f 381/417 382/418 380/416 +f 57/57 383/419 381/417 +f 55/55 57/57 381/417 +f 381/417 383/419 382/418 +f 383/419 384/420 382/418 +f 382/418 384/420 130/130 +f 382/418 130/130 128/128 +f 57/57 59/59 383/419 +f 383/419 385/421 384/420 +f 59/59 385/421 383/419 +f 384/420 386/422 132/132 +f 384/420 132/132 130/130 +f 385/421 386/422 384/420 +f 61/61 387/423 385/421 +f 385/421 387/423 386/422 +f 59/59 61/61 385/421 +f 387/423 388/424 386/422 +f 386/422 388/424 134/134 +f 386/422 134/134 132/132 +f 61/61 63/63 387/423 +f 63/63 389/425 387/423 +f 387/423 389/425 388/424 +f 388/424 172/426 136/136 +f 388/424 136/136 134/134 +f 389/425 172/426 388/424 +f 65/65 173/427 389/425 +f 63/63 65/65 389/425 +f 389/425 173/427 172/426 +f 65/65 67/67 173/427 +f 390/428 391/429 392/430 +f 393/431 390/428 392/430 +f 393/431 392/430 394/432 +f 390/428 395/433 391/429 +f 395/433 396/434 391/429 +f 395/433 397/435 396/434 +f 397/435 398/436 396/434 +f 397/435 399/437 398/436 +f 399/437 400/438 398/436 +f 399/437 401/439 400/438 +f 401/439 402/440 400/438 +f 401/439 403/441 402/440 +f 403/441 404/442 402/440 +f 403/441 405/443 404/442 +f 405/443 406/444 404/442 +f 405/443 407/445 406/444 +f 407/445 408/446 406/444 +f 407/445 409/447 408/446 +f 409/447 410/448 408/446 +f 409/447 411/449 410/448 +f 411/449 201/450 410/448 +f 411/449 196/451 201/450 +f 412/452 393/431 394/432 +f 412/452 394/432 413/453 +f 414/454 412/452 413/453 +f 414/454 413/453 415/455 +f 416/456 414/454 415/455 +f 416/456 415/455 417/457 +f 418/458 416/456 417/457 +f 418/458 417/457 419/459 +f 267/460 418/458 419/459 +f 267/460 419/459 270/461 +f 420/462 421/463 422/464 +f 423/465 420/462 422/464 +f 423/465 422/464 424/466 +f 420/462 425/467 421/463 +f 425/467 426/468 421/463 +f 425/467 427/469 426/468 +f 427/469 428/470 426/468 +f 427/469 429/471 428/470 +f 429/471 185/472 428/470 +f 429/471 177/473 185/472 +f 430/474 423/465 424/466 +f 430/474 424/466 431/475 +f 432/476 430/474 431/475 +f 432/476 431/475 433/477 +f 434/478 432/476 433/477 +f 434/478 433/477 435/479 +f 436/480 434/478 435/479 +f 436/480 435/479 437/481 +f 438/482 436/480 437/481 +f 438/482 437/481 439/483 +f 440/484 438/482 439/483 +f 440/484 439/483 441/485 +f 442/486 440/484 441/485 +f 442/486 441/485 443/487 +f 444/488 442/486 443/487 +f 444/488 443/487 445/489 +f 446/490 444/488 445/489 +f 446/490 445/489 447/491 +f 448/492 446/490 447/491 +f 448/492 447/491 449/493 +f 247/494 448/492 449/493 +f 247/494 449/493 252/495 +f 450/496 451/497 452/498 +f 453/499 450/496 452/498 +f 453/499 452/498 454/500 +f 450/496 455/501 451/497 +f 455/501 212/502 451/497 +f 455/501 208/503 212/502 +f 456/504 453/499 454/500 +f 456/504 454/500 457/505 +f 458/506 456/504 457/505 +f 458/506 457/505 459/507 +f 460/508 458/506 459/507 +f 460/508 459/507 461/509 +f 462/510 460/508 461/509 +f 462/510 461/509 463/511 +f 464/512 462/510 463/511 +f 464/512 463/511 465/513 +f 466/514 464/512 465/513 +f 466/514 465/513 467/515 +f 468/516 466/514 467/515 +f 468/516 467/515 469/517 +f 470/518 468/516 469/517 +f 470/518 469/517 471/519 +f 472/520 470/518 471/519 +f 472/520 471/519 473/521 +f 474/522 472/520 473/521 +f 474/522 473/521 475/523 +f 476/524 474/522 475/523 +f 476/524 475/523 477/525 +f 478/526 476/524 477/525 +f 478/526 477/525 479/527 +f 280/528 478/526 479/527 +f 280/528 479/527 281/529 +f 480/530 481/531 482/532 +f 483/533 480/530 482/532 +f 483/533 482/532 484/534 +f 480/530 485/535 481/531 +f 485/535 262/536 481/531 +f 485/535 248/537 262/536 +f 486/538 483/533 484/534 +f 486/538 484/534 487/539 +f 488/540 486/538 487/539 +f 488/540 487/539 489/541 +f 490/542 488/540 489/541 +f 490/542 489/541 491/543 +f 492/544 490/542 491/543 +f 492/544 491/543 493/545 +f 494/546 492/544 493/545 +f 494/546 493/545 495/547 +f 496/548 494/546 495/547 +f 496/548 495/547 497/549 +f 498/550 496/548 497/549 +f 498/550 497/549 499/551 +f 500/552 498/550 499/551 +f 500/552 499/551 501/553 +f 502/554 500/552 501/553 +f 502/554 501/553 503/555 +f 504/556 502/554 503/555 +f 504/556 503/555 505/557 +f 506/558 504/556 505/557 +f 506/558 505/557 507/559 +f 508/560 506/558 507/559 +f 508/560 507/559 509/561 +f 186/562 508/560 509/561 +f 186/562 509/561 188/563 +f 510/564 511/565 512/566 +f 513/567 510/564 512/566 +f 513/567 512/566 514/568 +f 510/564 515/569 511/565 +f 515/569 516/570 511/565 +f 515/569 517/571 516/570 +f 517/571 518/572 516/570 +f 517/571 519/573 518/572 +f 519/573 520/574 518/572 +f 519/573 521/575 520/574 +f 521/575 522/576 520/574 +f 521/575 523/577 522/576 +f 523/577 524/578 522/576 +f 523/577 525/579 524/578 +f 525/579 526/580 524/578 +f 525/579 527/581 526/580 +f 527/581 528/582 526/580 +f 527/581 529/583 528/582 +f 529/583 530/584 528/582 +f 529/583 531/585 530/584 +f 531/585 532/586 530/584 +f 531/585 533/587 532/586 +f 533/587 258/588 532/586 +f 533/587 256/589 258/588 +f 534/590 513/567 514/568 +f 534/590 514/568 535/591 +f 536/592 534/590 535/591 +f 536/592 535/591 537/593 +f 538/594 536/592 537/593 +f 538/594 537/593 539/595 +f 181/596 538/594 539/595 +f 181/596 539/595 182/597 +f 199/598 540/599 203/600 +f 199/598 541/601 540/599 +f 541/601 542/602 540/599 +f 541/601 543/603 542/602 +f 543/603 544/604 542/602 +f 543/603 545/605 544/604 +f 545/605 546/606 544/604 +f 545/605 547/607 546/606 +f 547/607 548/608 546/606 +f 547/607 549/609 548/608 +f 549/609 550/610 548/608 +f 549/609 551/611 550/610 +f 551/611 552/612 550/610 +f 551/611 553/613 552/612 +f 553/613 554/614 552/612 +f 553/613 555/615 554/614 +f 555/615 556/616 554/614 +f 555/615 557/617 556/616 +f 557/617 558/618 556/616 +f 557/617 559/619 558/618 +f 559/619 560/620 558/618 +f 559/619 561/621 560/620 +f 561/621 562/622 560/620 +f 561/621 563/623 562/622 +f 563/623 564/624 562/622 +f 563/623 565/625 564/624 +f 565/625 566/626 564/624 +f 565/625 567/627 566/626 +f 567/627 568/628 566/626 +f 567/627 569/629 568/628 +f 569/629 274/630 568/628 +f 569/629 269/631 274/630 +f 429/471 186/562 177/473 +f 429/471 508/560 186/562 +f 427/469 508/560 429/471 +f 427/469 506/558 508/560 +f 425/467 506/558 427/469 +f 425/467 504/556 506/558 +f 420/462 504/556 425/467 +f 420/462 502/554 504/556 +f 423/465 502/554 420/462 +f 423/465 500/552 502/554 +f 430/474 500/552 423/465 +f 430/474 498/550 500/552 +f 432/476 498/550 430/474 +f 432/476 496/548 498/550 +f 434/478 496/548 432/476 +f 434/478 494/546 496/548 +f 436/480 494/546 434/478 +f 436/480 492/544 494/546 +f 438/482 492/544 436/480 +f 438/482 490/542 492/544 +f 440/484 490/542 438/482 +f 440/484 488/540 490/542 +f 442/486 488/540 440/484 +f 442/486 486/538 488/540 +f 444/488 486/538 442/486 +f 444/488 483/533 486/538 +f 446/490 483/533 444/488 +f 446/490 480/530 483/533 +f 448/492 480/530 446/490 +f 448/492 485/535 480/530 +f 247/494 485/535 448/492 +f 247/494 248/537 485/535 +f 411/449 199/598 196/451 +f 411/449 541/601 199/598 +f 409/447 541/601 411/449 +f 409/447 543/603 541/601 +f 407/445 543/603 409/447 +f 407/445 545/605 543/603 +f 405/443 545/605 407/445 +f 405/443 547/607 545/605 +f 403/441 547/607 405/443 +f 403/441 549/609 547/607 +f 401/439 549/609 403/441 +f 401/439 551/611 549/609 +f 399/437 551/611 401/439 +f 399/437 553/613 551/611 +f 397/435 553/613 399/437 +f 397/435 555/615 553/613 +f 395/433 555/615 397/435 +f 395/433 557/617 555/615 +f 390/428 557/617 395/433 +f 390/428 559/619 557/617 +f 393/431 559/619 390/428 +f 393/431 561/621 559/619 +f 412/452 561/621 393/431 +f 412/452 563/623 561/621 +f 414/454 563/623 412/452 +f 414/454 565/625 563/623 +f 416/456 565/625 414/454 +f 416/456 567/627 565/625 +f 418/458 567/627 416/456 +f 418/458 569/629 567/627 +f 267/460 569/629 418/458 +f 267/460 269/631 569/629 +f 570/632 181/596 183/633 +f 570/632 538/594 181/596 +f 571/634 538/594 570/632 +f 571/634 536/592 538/594 +f 572/635 536/592 571/634 +f 572/635 534/590 536/592 +f 573/636 534/590 572/635 +f 573/636 513/567 534/590 +f 574/637 513/567 573/636 +f 574/637 510/564 513/567 +f 575/638 510/564 574/637 +f 575/638 515/569 510/564 +f 576/639 515/569 575/638 +f 576/639 517/571 515/569 +f 577/640 517/571 576/639 +f 577/640 519/573 517/571 +f 578/641 519/573 577/640 +f 578/641 521/575 519/573 +f 579/642 521/575 578/641 +f 579/642 523/577 521/575 +f 580/643 523/577 579/642 +f 580/643 525/579 523/577 +f 581/644 525/579 580/643 +f 581/644 527/581 525/579 +f 582/645 527/581 581/644 +f 582/645 529/583 527/581 +f 583/646 529/583 582/645 +f 583/646 531/585 529/583 +f 584/647 531/585 583/646 +f 584/647 533/587 531/585 +f 259/648 533/587 584/647 +f 259/648 256/589 533/587 +f 265/649 585/650 586/651 +f 586/651 585/650 587/652 +f 586/651 587/652 588/653 +f 265/649 586/651 589/654 +f 586/651 588/653 590/655 +f 586/651 590/655 589/654 +f 265/649 268/656 585/650 +f 265/649 589/654 591/657 +f 268/656 271/658 592/659 +f 268/656 592/659 585/650 +f 585/650 592/659 593/660 +f 593/660 592/659 594/661 +f 585/650 593/660 587/652 +f 593/660 594/661 595/662 +f 596/663 594/661 597/664 +f 595/662 594/661 596/663 +f 595/662 596/663 598/665 +f 596/663 597/664 599/666 +f 588/653 587/652 600/667 +f 590/655 588/653 601/668 +f 588/653 600/667 601/668 +f 590/655 601/668 602/669 +f 603/670 604/671 605/672 +f 603/670 605/672 606/673 +f 603/670 607/674 604/671 +f 607/674 608/675 604/671 +f 260/676 263/677 607/674 +f 260/676 607/674 609/678 +f 609/678 607/674 603/670 +f 607/674 263/677 608/675 +f 261/679 260/676 609/678 +f 261/679 609/678 610/680 +f 610/680 609/678 611/681 +f 609/678 603/670 611/681 +f 610/680 611/681 612/682 +f 610/680 612/682 613/683 +f 610/680 613/683 614/684 +f 611/681 603/670 615/685 +f 611/681 615/685 616/686 +f 603/670 606/673 615/685 +f 614/684 613/683 617/687 +f 614/684 617/687 618/688 +f 614/684 618/688 619/689 +f 614/684 619/689 620/690 +f 288/691 574/637 573/636 +f 287/692 288/691 573/636 +f 287/692 573/636 572/635 +f 288/691 289/693 574/637 +f 289/693 575/638 574/637 +f 289/693 290/694 575/638 +f 290/694 576/639 575/638 +f 290/694 291/695 576/639 +f 291/695 577/640 576/639 +f 291/695 292/696 577/640 +f 292/696 578/641 577/640 +f 292/696 293/697 578/641 +f 293/697 579/642 578/641 +f 293/697 294/698 579/642 +f 294/698 580/643 579/642 +f 294/698 295/699 580/643 +f 295/699 581/644 580/643 +f 295/699 296/700 581/644 +f 296/700 582/645 581/644 +f 296/700 297/701 582/645 +f 297/701 583/646 582/645 +f 297/701 298/702 583/646 +f 298/702 584/647 583/646 +f 298/702 299/703 584/647 +f 299/703 259/648 584/647 +f 299/703 257/704 259/648 +f 286/705 287/692 572/635 +f 286/705 572/635 571/634 +f 285/706 286/705 571/634 +f 285/706 571/634 570/632 +f 184/707 285/706 570/632 +f 184/707 570/632 183/633 +f 12/12 621/708 283/709 +f 12/12 10/10 621/708 +f 10/10 622/710 621/708 +f 10/10 8/8 622/710 +f 8/8 623/711 622/710 +f 8/8 6/6 623/711 +f 6/6 624/712 623/711 +f 6/6 1/1 624/712 +f 1/1 625/713 624/712 +f 1/1 4/4 625/713 +f 4/4 626/714 625/713 +f 4/4 13/13 626/714 +f 13/13 627/715 626/714 +f 13/13 15/15 627/715 +f 15/15 628/716 627/715 +f 15/15 17/17 628/716 +f 17/17 629/717 628/716 +f 17/17 19/19 629/717 +f 19/19 630/718 629/717 +f 19/19 21/21 630/718 +f 21/21 631/719 630/718 +f 21/21 23/23 631/719 +f 23/23 632/720 631/719 +f 23/23 25/25 632/720 +f 25/25 633/721 632/720 +f 25/25 27/27 633/721 +f 27/27 634/722 633/721 +f 27/27 29/29 634/722 +f 29/29 635/723 634/722 +f 29/29 31/31 635/723 +f 31/31 211/724 635/723 +f 31/31 33/33 211/724 +f 456/504 636/725 637/726 +f 453/499 456/504 637/726 +f 453/499 637/726 638/727 +f 456/504 458/506 636/725 +f 458/506 639/728 636/725 +f 458/506 460/508 639/728 +f 460/508 640/729 639/728 +f 460/508 462/510 640/729 +f 462/510 641/730 640/729 +f 462/510 464/512 641/730 +f 464/512 642/731 641/730 +f 464/512 466/514 642/731 +f 466/514 643/732 642/731 +f 466/514 468/516 643/732 +f 468/516 644/733 643/732 +f 468/516 470/518 644/733 +f 470/518 645/734 644/733 +f 470/518 472/520 645/734 +f 472/520 646/735 645/734 +f 472/520 474/522 646/735 +f 474/522 647/736 646/735 +f 474/522 476/524 647/736 +f 476/524 648/737 647/736 +f 476/524 478/526 648/737 +f 478/526 284/738 648/737 +f 478/526 280/528 284/738 +f 450/496 453/499 638/727 +f 450/496 638/727 649/739 +f 455/501 450/496 649/739 +f 455/501 649/739 650/740 +f 208/503 455/501 650/740 +f 208/503 650/740 210/741 +f 509/561 191/742 188/563 +f 509/561 651/743 191/742 +f 507/559 651/743 509/561 +f 651/743 200/744 191/742 +f 507/559 652/745 651/743 +f 651/743 653/746 200/744 +f 652/745 653/746 651/743 +f 505/557 652/745 507/559 +f 505/557 654/747 652/745 +f 652/745 655/748 653/746 +f 654/747 655/748 652/745 +f 653/746 410/448 201/450 +f 653/746 201/450 200/744 +f 655/748 410/448 653/746 +f 656/749 408/446 655/748 +f 655/748 408/446 410/448 +f 654/747 656/749 655/748 +f 503/555 657/750 654/747 +f 503/555 654/747 505/557 +f 657/750 656/749 654/747 +f 656/749 406/444 408/446 +f 657/750 658/751 656/749 +f 658/751 406/444 656/749 +f 501/553 659/752 657/750 +f 501/553 657/750 503/555 +f 659/752 658/751 657/750 +f 660/753 404/442 658/751 +f 658/751 404/442 406/444 +f 659/752 660/753 658/751 +f 499/551 661/754 659/752 +f 499/551 659/752 501/553 +f 661/754 660/753 659/752 +f 660/753 402/440 404/442 +f 661/754 662/755 660/753 +f 662/755 402/440 660/753 +f 497/549 663/756 661/754 +f 497/549 661/754 499/551 +f 663/756 662/755 661/754 +f 664/757 400/438 662/755 +f 662/755 400/438 402/440 +f 663/756 664/757 662/755 +f 665/758 664/757 663/756 +f 495/547 665/758 663/756 +f 495/547 663/756 497/549 +f 664/757 398/436 400/438 +f 665/758 666/759 664/757 +f 666/759 398/436 664/757 +f 493/545 667/760 665/758 +f 493/545 665/758 495/547 +f 667/760 666/759 665/758 +f 668/761 396/434 666/759 +f 666/759 396/434 398/436 +f 667/760 668/761 666/759 +f 491/543 669/762 667/760 +f 491/543 667/760 493/545 +f 669/762 668/761 667/760 +f 668/761 391/429 396/434 +f 669/762 670/763 668/761 +f 670/763 391/429 668/761 +f 489/541 671/764 669/762 +f 489/541 669/762 491/543 +f 671/764 670/763 669/762 +f 672/765 392/430 670/763 +f 670/763 392/430 391/429 +f 671/764 672/765 670/763 +f 487/539 673/766 671/764 +f 487/539 671/764 489/541 +f 673/766 672/765 671/764 +f 672/765 394/432 392/430 +f 673/766 674/767 672/765 +f 674/767 394/432 672/765 +f 484/534 675/768 673/766 +f 484/534 673/766 487/539 +f 675/768 674/767 673/766 +f 676/769 413/453 674/767 +f 674/767 413/453 394/432 +f 675/768 676/769 674/767 +f 482/532 677/770 675/768 +f 482/532 675/768 484/534 +f 677/770 676/769 675/768 +f 676/769 415/455 413/453 +f 677/770 678/771 676/769 +f 678/771 415/455 676/769 +f 481/531 679/772 677/770 +f 481/531 677/770 482/532 +f 679/772 678/771 677/770 +f 680/773 417/457 678/771 +f 678/771 417/457 415/455 +f 679/772 680/773 678/771 +f 262/536 261/774 679/772 +f 262/536 679/772 481/531 +f 261/774 680/773 679/772 +f 680/773 419/459 417/457 +f 261/774 271/775 680/773 +f 271/775 419/459 680/773 +f 271/775 270/461 419/459 +f 540/599 204/776 203/600 +f 540/599 681/777 204/776 +f 542/602 681/777 540/599 +f 681/777 207/778 204/776 +f 542/602 682/779 681/777 +f 681/777 683/780 207/778 +f 682/779 683/780 681/777 +f 544/604 682/779 542/602 +f 544/604 684/781 682/779 +f 682/779 685/782 683/780 +f 684/781 685/782 682/779 +f 683/780 451/497 212/502 +f 683/780 212/502 207/778 +f 685/782 451/497 683/780 +f 686/783 452/498 685/782 +f 685/782 452/498 451/497 +f 684/781 686/783 685/782 +f 687/784 686/783 684/781 +f 546/606 687/784 684/781 +f 546/606 684/781 544/604 +f 686/783 454/500 452/498 +f 687/784 688/785 686/783 +f 688/785 454/500 686/783 +f 548/608 689/786 687/784 +f 548/608 687/784 546/606 +f 689/786 688/785 687/784 +f 690/787 457/505 688/785 +f 688/785 457/505 454/500 +f 689/786 690/787 688/785 +f 550/610 691/788 689/786 +f 550/610 689/786 548/608 +f 691/788 690/787 689/786 +f 690/787 459/507 457/505 +f 691/788 692/789 690/787 +f 692/789 459/507 690/787 +f 552/612 693/790 691/788 +f 552/612 691/788 550/610 +f 693/790 692/789 691/788 +f 694/791 461/509 692/789 +f 692/789 461/509 459/507 +f 693/790 694/791 692/789 +f 554/614 695/792 693/790 +f 554/614 693/790 552/612 +f 695/792 694/791 693/790 +f 694/791 463/511 461/509 +f 695/792 696/793 694/791 +f 696/793 463/511 694/791 +f 556/616 697/794 695/792 +f 556/616 695/792 554/614 +f 697/794 696/793 695/792 +f 698/795 465/513 696/793 +f 697/794 698/795 696/793 +f 696/793 465/513 463/511 +f 558/618 699/796 697/794 +f 558/618 697/794 556/616 +f 699/796 698/795 697/794 +f 698/795 467/515 465/513 +f 699/796 700/797 698/795 +f 700/797 467/515 698/795 +f 560/620 701/798 699/796 +f 560/620 699/796 558/618 +f 701/798 700/797 699/796 +f 702/799 469/517 700/797 +f 700/797 469/517 467/515 +f 701/798 702/799 700/797 +f 703/800 702/799 701/798 +f 562/622 703/800 701/798 +f 562/622 701/798 560/620 +f 702/799 471/519 469/517 +f 703/800 704/801 702/799 +f 704/801 471/519 702/799 +f 564/624 705/802 703/800 +f 564/624 703/800 562/622 +f 705/802 704/801 703/800 +f 706/803 473/521 704/801 +f 704/801 473/521 471/519 +f 705/802 706/803 704/801 +f 566/626 707/804 705/802 +f 566/626 705/802 564/624 +f 707/804 706/803 705/802 +f 706/803 475/523 473/521 +f 707/804 708/805 706/803 +f 708/805 475/523 706/803 +f 568/628 709/806 707/804 +f 568/628 707/804 566/626 +f 709/806 708/805 707/804 +f 710/807 477/525 708/805 +f 708/805 477/525 475/523 +f 709/806 710/807 708/805 +f 274/630 273/808 709/806 +f 274/630 709/806 568/628 +f 273/808 710/807 709/806 +f 710/807 479/527 477/525 +f 273/808 277/809 710/807 +f 277/809 479/527 710/807 +f 277/809 281/529 479/527 +f 539/595 180/810 182/597 +f 539/595 711/811 180/810 +f 537/593 711/811 539/595 +f 711/811 179/812 180/810 +f 537/593 712/813 711/811 +f 711/811 713/814 179/812 +f 712/813 713/814 711/811 +f 535/591 712/813 537/593 +f 535/591 714/815 712/813 +f 712/813 715/816 713/814 +f 714/815 715/816 712/813 +f 713/814 428/470 185/472 +f 713/814 185/472 179/812 +f 715/816 428/470 713/814 +f 716/817 426/468 715/816 +f 715/816 426/468 428/470 +f 714/815 716/817 715/816 +f 717/818 716/817 714/815 +f 514/568 717/818 714/815 +f 514/568 714/815 535/591 +f 716/817 421/463 426/468 +f 717/818 718/819 716/817 +f 718/819 421/463 716/817 +f 512/566 719/820 717/818 +f 512/566 717/818 514/568 +f 719/820 718/819 717/818 +f 720/821 422/464 718/819 +f 718/819 422/464 421/463 +f 719/820 720/821 718/819 +f 511/565 721/822 719/820 +f 511/565 719/820 512/566 +f 721/822 720/821 719/820 +f 720/821 424/466 422/464 +f 721/822 722/823 720/821 +f 722/823 424/466 720/821 +f 516/570 723/824 721/822 +f 516/570 721/822 511/565 +f 723/824 722/823 721/822 +f 724/825 431/475 722/823 +f 722/823 431/475 424/466 +f 723/824 724/825 722/823 +f 518/572 725/826 723/824 +f 518/572 723/824 516/570 +f 725/826 724/825 723/824 +f 724/825 433/477 431/475 +f 725/826 726/827 724/825 +f 726/827 433/477 724/825 +f 520/574 727/828 725/826 +f 520/574 725/826 518/572 +f 727/828 726/827 725/826 +f 728/829 435/479 726/827 +f 727/828 728/829 726/827 +f 726/827 435/479 433/477 +f 522/576 729/830 727/828 +f 522/576 727/828 520/574 +f 729/830 728/829 727/828 +f 728/829 437/481 435/479 +f 729/830 730/831 728/829 +f 730/831 437/481 728/829 +f 524/578 731/832 729/830 +f 524/578 729/830 522/576 +f 731/832 730/831 729/830 +f 732/833 439/483 730/831 +f 730/831 439/483 437/481 +f 731/832 732/833 730/831 +f 733/834 732/833 731/832 +f 526/580 733/834 731/832 +f 526/580 731/832 524/578 +f 732/833 441/485 439/483 +f 733/834 734/835 732/833 +f 734/835 441/485 732/833 +f 528/582 735/836 733/834 +f 528/582 733/834 526/580 +f 735/836 734/835 733/834 +f 736/837 443/487 734/835 +f 734/835 443/487 441/485 +f 735/836 736/837 734/835 +f 530/584 737/838 735/836 +f 530/584 735/836 528/582 +f 737/838 736/837 735/836 +f 736/837 445/489 443/487 +f 737/838 738/839 736/837 +f 738/839 445/489 736/837 +f 532/586 739/840 737/838 +f 532/586 737/838 530/584 +f 739/840 738/839 737/838 +f 740/841 447/491 738/839 +f 738/839 447/491 445/489 +f 739/840 740/841 738/839 +f 258/588 255/842 739/840 +f 258/588 739/840 532/586 +f 255/842 740/841 739/840 +f 740/841 449/493 447/491 +f 255/842 254/843 740/841 +f 254/843 449/493 740/841 +f 254/843 252/495 449/493 +f 621/844 647/736 648/737 +f 283/845 621/844 648/737 +f 283/845 648/737 284/738 +f 621/844 622/846 647/736 +f 622/846 646/735 647/736 +f 622/846 623/847 646/735 +f 623/847 645/734 646/735 +f 623/847 624/848 645/734 +f 624/848 644/733 645/734 +f 624/848 625/849 644/733 +f 625/849 643/732 644/733 +f 625/849 626/850 643/732 +f 626/850 642/731 643/732 +f 626/850 627/851 642/731 +f 627/851 641/730 642/731 +f 627/851 628/852 641/730 +f 628/852 640/729 641/730 +f 628/852 629/853 640/729 +f 629/853 639/728 640/729 +f 629/853 630/854 639/728 +f 630/854 636/725 639/728 +f 630/854 631/855 636/725 +f 631/855 637/726 636/725 +f 631/855 632/856 637/726 +f 632/856 638/727 637/726 +f 632/856 633/857 638/727 +f 633/857 649/739 638/727 +f 633/857 634/858 649/739 +f 634/858 650/740 649/739 +f 634/858 635/859 650/740 +f 635/859 210/741 650/740 +f 635/859 211/860 210/741 +f 263/280 591/861 608/862 +f 263/280 265/283 591/861 +f 271/863 610/864 592/865 +f 271/863 261/866 610/864 +f 611/867 593/868 612/869 +f 612/869 593/868 595/870 +f 612/869 595/870 613/871 +f 611/867 587/872 593/868 +f 613/871 595/870 598/873 +f 613/871 598/873 617/874 +f 592/865 614/875 594/876 +f 592/865 610/864 614/875 +f 596/877 617/874 598/873 +f 596/877 618/878 617/874 +f 618/878 596/877 599/879 +f 618/878 599/879 619/880 +f 608/862 589/881 604/882 +f 604/882 589/881 590/883 +f 604/882 590/883 605/884 +f 608/862 591/861 589/881 +f 605/884 590/883 602/885 +f 605/884 602/885 606/886 +f 615/685 600/667 616/686 +f 615/685 601/668 600/667 +f 601/668 615/685 606/673 +f 601/668 606/673 602/669 +f 587/872 616/887 600/888 +f 587/872 611/867 616/887 +f 597/889 619/890 599/891 +f 597/889 620/892 619/890 +f 594/876 620/892 597/889 +f 594/876 614/875 620/892 diff --git a/kingdoms_game/mods/boats/textures/boats_inventory.png b/kingdoms_game/mods/boats/textures/boats_inventory.png new file mode 100644 index 0000000..f9d082e Binary files /dev/null and b/kingdoms_game/mods/boats/textures/boats_inventory.png differ diff --git a/kingdoms_game/mods/boats/textures/boats_wield.png b/kingdoms_game/mods/boats/textures/boats_wield.png new file mode 100644 index 0000000..f998b5b Binary files /dev/null and b/kingdoms_game/mods/boats/textures/boats_wield.png differ diff --git a/kingdoms_game/mods/bones/README.txt b/kingdoms_game/mods/bones/README.txt new file mode 100644 index 0000000..91bcd10 --- /dev/null +++ b/kingdoms_game/mods/bones/README.txt @@ -0,0 +1,12 @@ +Minetest Game mod: bones +======================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by PilzAdam (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +All textures: paramat (CC BY-SA 3.0) diff --git a/kingdoms_game/mods/bones/depends.txt b/kingdoms_game/mods/bones/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/kingdoms_game/mods/bones/depends.txt @@ -0,0 +1 @@ +default diff --git a/kingdoms_game/mods/bones/init.lua b/kingdoms_game/mods/bones/init.lua new file mode 100644 index 0000000..a7595c4 --- /dev/null +++ b/kingdoms_game/mods/bones/init.lua @@ -0,0 +1,248 @@ +-- Minetest 0.4 mod: bones +-- See README.txt for licensing and other information. + +local function is_owner(pos, name) + local owner = minetest.get_meta(pos):get_string("owner") + if owner == "" or owner == name or minetest.check_player_privs(name, "protection_bypass") then + return true + end + return false +end + +local bones_formspec = + "size[8,11]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[current_name;main;0,0.3;8,6;]" .. + "list[current_player;main;0,6.85;8,1;]" .. + "list[current_player;main;0,8.08;8,3;8]" .. + "listring[current_name;main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,6.85) + +local share_bones_time = tonumber(minetest.setting_get("share_bones_time")) or 1200 +local share_bones_time_early = tonumber(minetest.setting_get("share_bones_time_early")) or share_bones_time / 4 + +minetest.register_node("bones:bones", { + description = "Bones", + tiles = { + "bones_top.png^[transform2", + "bones_bottom.png", + "bones_side.png", + "bones_side.png", + "bones_rear.png", + "bones_front.png" + }, + paramtype2 = "facedir", + groups = {dig_immediate = 2}, + sounds = default.node_sound_dirt_defaults(), + + can_dig = function(pos, player) + local inv = minetest.get_meta(pos):get_inventory() + local name = "" + if player then + name = player:get_player_name() + end + return is_owner(pos, name) and inv:is_empty("main") + end, + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + if is_owner(pos, player:get_player_name()) then + return count + end + return 0 + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + return 0 + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + if is_owner(pos, player:get_player_name()) then + return stack:get_count() + end + return 0 + end, + + on_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if meta:get_inventory():is_empty("main") then + minetest.remove_node(pos) + end + end, + + on_punch = function(pos, node, player) + if not is_owner(pos, player:get_player_name()) then + return + end + + if minetest.get_meta(pos):get_string("infotext") == "" then + return + end + + local inv = minetest.get_meta(pos):get_inventory() + local player_inv = player:get_inventory() + local has_space = true + + for i = 1, inv:get_size("main") do + local stk = inv:get_stack("main", i) + if player_inv:room_for_item("main", stk) then + inv:set_stack("main", i, nil) + player_inv:add_item("main", stk) + else + has_space = false + break + end + end + + -- remove bones if player emptied them + if has_space then + if player_inv:room_for_item("main", {name = "bones:bones"}) then + player_inv:add_item("main", {name = "bones:bones"}) + else + minetest.add_item(pos,"bones:bones") + end + minetest.remove_node(pos) + end + end, + + on_timer = function(pos, elapsed) + local meta = minetest.get_meta(pos) + local time = meta:get_int("time") + elapsed + if time >= share_bones_time then + meta:set_string("infotext", meta:get_string("owner") .. "'s old bones") + meta:set_string("owner", "") + else + meta:set_int("time", time) + return true + end + end, + on_blast = function(pos) + end, +}) + +local function may_replace(pos, player) + local node_name = minetest.get_node(pos).name + local node_definition = minetest.registered_nodes[node_name] + + -- if the node is unknown, we return false + if not node_definition then + return false + end + + -- allow replacing air and liquids + if node_name == "air" or node_definition.liquidtype ~= "none" then + return true + end + + -- don't replace filled chests and other nodes that don't allow it + local can_dig_func = node_definition.can_dig + if can_dig_func and not can_dig_func(pos, player) then + return false + end + + -- default to each nodes buildable_to; if a placed block would replace it, why shouldn't bones? + -- flowers being squished by bones are more realistical than a squished stone, too + -- exception are of course any protected buildable_to + return node_definition.buildable_to and not minetest.is_protected(pos, player:get_player_name()) +end + +local drop = function(pos, itemstack) + local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count())) + if obj then + obj:setvelocity({ + x = math.random(-10, 10) / 9, + y = 5, + z = math.random(-10, 10) / 9, + }) + end +end + +minetest.register_on_dieplayer(function(player) + + local bones_mode = minetest.setting_get("bones_mode") or "bones" + if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then + bones_mode = "bones" + end + + -- return if keep inventory set or in creative mode + if bones_mode == "keep" or minetest.setting_getbool("creative_mode") then + return + end + + local player_inv = player:get_inventory() + if player_inv:is_empty("main") and + player_inv:is_empty("craft") then + return + end + + local pos = vector.round(player:getpos()) + local player_name = player:get_player_name() + + -- check if it's possible to place bones, if not find space near player + if bones_mode == "bones" and not may_replace(pos, player) then + local air = minetest.find_node_near(pos, 1, {"air"}) + if air and not minetest.is_protected(air, player_name) then + pos = air + else + bones_mode = "drop" + end + end + + if bones_mode == "drop" then + + -- drop inventory items + for i = 1, player_inv:get_size("main") do + drop(pos, player_inv:get_stack("main", i)) + end + player_inv:set_list("main", {}) + + -- drop crafting grid items + for i = 1, player_inv:get_size("craft") do + drop(pos, player_inv:get_stack("craft", i)) + end + player_inv:set_list("craft", {}) + + drop(pos, ItemStack("bones:bones")) + return + end + + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(pos, {name = "bones:bones", param2 = param2}) + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("main", 8 * 6) + inv:set_list("main", player_inv:get_list("main")) + + for i = 1, player_inv:get_size("craft") do + local stack = player_inv:get_stack("craft", i) + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + else + --drop if no space left + drop(pos, stack) + end + end + + player_inv:set_list("main", {}) + player_inv:set_list("craft", {}) + + meta:set_string("formspec", bones_formspec) + meta:set_string("owner", player_name) + + if share_bones_time ~= 0 then + meta:set_string("infotext", player_name .. "'s fresh bones") + + if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then + meta:set_int("time", 0) + else + meta:set_int("time", (share_bones_time - share_bones_time_early)) + end + + minetest.get_node_timer(pos):start(10) + else + meta:set_string("infotext", player_name.."'s bones") + end +end) diff --git a/kingdoms_game/mods/bones/license.txt b/kingdoms_game/mods/bones/license.txt new file mode 100644 index 0000000..fe52584 --- /dev/null +++ b/kingdoms_game/mods/bones/license.txt @@ -0,0 +1,58 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2016 paramat + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + diff --git a/kingdoms_game/mods/bones/textures/bones_bottom.png b/kingdoms_game/mods/bones/textures/bones_bottom.png new file mode 100644 index 0000000..859c6bb Binary files /dev/null and b/kingdoms_game/mods/bones/textures/bones_bottom.png differ diff --git a/kingdoms_game/mods/bones/textures/bones_front.png b/kingdoms_game/mods/bones/textures/bones_front.png new file mode 100644 index 0000000..1e52437 Binary files /dev/null and b/kingdoms_game/mods/bones/textures/bones_front.png differ diff --git a/kingdoms_game/mods/bones/textures/bones_rear.png b/kingdoms_game/mods/bones/textures/bones_rear.png new file mode 100644 index 0000000..4cfe236 Binary files /dev/null and b/kingdoms_game/mods/bones/textures/bones_rear.png differ diff --git a/kingdoms_game/mods/bones/textures/bones_side.png b/kingdoms_game/mods/bones/textures/bones_side.png new file mode 100644 index 0000000..a07595f Binary files /dev/null and b/kingdoms_game/mods/bones/textures/bones_side.png differ diff --git a/kingdoms_game/mods/bones/textures/bones_top.png b/kingdoms_game/mods/bones/textures/bones_top.png new file mode 100644 index 0000000..198a8a2 Binary files /dev/null and b/kingdoms_game/mods/bones/textures/bones_top.png differ diff --git a/kingdoms_game/mods/bucket/README.txt b/kingdoms_game/mods/bucket/README.txt new file mode 100644 index 0000000..a6674b4 --- /dev/null +++ b/kingdoms_game/mods/bucket/README.txt @@ -0,0 +1,26 @@ +Minetest Game mod: bucket +========================= + +License of source code: +----------------------- +Copyright (C) 2011-2012 Kahrl +Copyright (C) 2011-2012 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +http://www.gnu.org/licenses/lgpl-2.1.html + +License of media (textures and sounds) +-------------------------------------- +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +http://creativecommons.org/licenses/by-sa/3.0/ + +Authors of media files +----------------------- +Everything not listed in here: +Copyright (C) 2010-2012 celeron55, Perttu Ahola + + diff --git a/kingdoms_game/mods/bucket/depends.txt b/kingdoms_game/mods/bucket/depends.txt new file mode 100644 index 0000000..3a7daa1 --- /dev/null +++ b/kingdoms_game/mods/bucket/depends.txt @@ -0,0 +1,2 @@ +default + diff --git a/kingdoms_game/mods/bucket/init.lua b/kingdoms_game/mods/bucket/init.lua new file mode 100644 index 0000000..89730de --- /dev/null +++ b/kingdoms_game/mods/bucket/init.lua @@ -0,0 +1,192 @@ +-- Minetest 0.4 mod: bucket +-- See README.txt for licensing and other information. + +minetest.register_alias("bucket", "bucket:bucket_empty") +minetest.register_alias("bucket_water", "bucket:bucket_water") +minetest.register_alias("bucket_lava", "bucket:bucket_lava") + +minetest.register_craft({ + output = 'bucket:bucket_empty 1', + recipe = { + {'default:steel_ingot', '', 'default:steel_ingot'}, + {'', 'default:steel_ingot', ''}, + } +}) + +bucket = {} +bucket.liquids = {} + +local function check_protection(pos, name, text) + if minetest.is_protected(pos, name) then + minetest.log("action", (name ~= "" and name or "A mod") + .. " tried to " .. text + .. " at protected position " + .. minetest.pos_to_string(pos) + .. " with a bucket") + minetest.record_protection_violation(pos, name) + return true + end + return false +end + +-- Register a new liquid +-- source = name of the source node +-- flowing = name of the flowing node +-- itemname = name of the new bucket item (or nil if liquid is not takeable) +-- inventory_image = texture of the new bucket item (ignored if itemname == nil) +-- name = text description of the bucket item +-- groups = (optional) groups of the bucket item, for example {water_bucket = 1} +-- This function can be called from any mod (that depends on bucket). +function bucket.register_liquid(source, flowing, itemname, inventory_image, name, groups) + bucket.liquids[source] = { + source = source, + flowing = flowing, + itemname = itemname, + } + bucket.liquids[flowing] = bucket.liquids[source] + + if itemname ~= nil then + minetest.register_craftitem(itemname, { + description = name, + inventory_image = inventory_image, + stack_max = 1, + liquids_pointable = true, + groups = groups, + on_place = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + + local node = minetest.get_node_or_nil(pointed_thing.under) + local ndef + if node then + ndef = minetest.registered_nodes[node.name] + end + -- Call on_rightclick if the pointed node defines it + if ndef and ndef.on_rightclick and + user and not user:get_player_control().sneak then + return ndef.on_rightclick( + pointed_thing.under, + node, user, + itemstack) or itemstack + end + + local place_liquid = function(pos, node, source, flowing) + if check_protection(pos, + user and user:get_player_name() or "", + "place "..source) then + return + end + minetest.add_node(pos, {name=source}) + end + + -- Check if pointing to a buildable node + if ndef and ndef.buildable_to then + -- buildable; replace the node + place_liquid(pointed_thing.under, node, + source, flowing) + else + -- not buildable to; place the liquid above + -- check if the node above can be replaced + local node = minetest.get_node_or_nil(pointed_thing.above) + if node and minetest.registered_nodes[node.name].buildable_to then + place_liquid(pointed_thing.above, + node, source, + flowing) + else + -- do not remove the bucket with the liquid + return + end + end + return {name="bucket:bucket_empty"} + end + }) + end +end + +minetest.register_craftitem("bucket:bucket_empty", { + description = "Empty Bucket", + inventory_image = "bucket.png", + stack_max = 99, + liquids_pointable = true, + on_use = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + -- Check if pointing to a liquid source + local node = minetest.get_node(pointed_thing.under) + local liquiddef = bucket.liquids[node.name] + local item_count = user:get_wielded_item():get_count() + + if liquiddef ~= nil + and liquiddef.itemname ~= nil + and node.name == liquiddef.source then + if check_protection(pointed_thing.under, + user:get_player_name(), + "take ".. node.name) then + return + end + + -- default set to return filled bucket + local giving_back = liquiddef.itemname + + -- check if holding more than 1 empty bucket + if item_count > 1 then + + -- if space in inventory add filled bucked, otherwise drop as item + local inv = user:get_inventory() + if inv:room_for_item("main", {name=liquiddef.itemname}) then + inv:add_item("main", liquiddef.itemname) + else + local pos = user:getpos() + pos.y = math.floor(pos.y + 0.5) + core.add_item(pos, liquiddef.itemname) + end + + -- set to return empty buckets minus 1 + giving_back = "bucket:bucket_empty "..tostring(item_count-1) + + end + + minetest.add_node(pointed_thing.under, {name="air"}) + + return ItemStack(giving_back) + end + end, +}) + +bucket.register_liquid( + "default:water_source", + "default:water_flowing", + "bucket:bucket_water", + "bucket_water.png", + "Water Bucket", + {water_bucket = 1} +) + +bucket.register_liquid( + "default:river_water_source", + "default:river_water_flowing", + "bucket:bucket_river_water", + "bucket_river_water.png", + "River Water Bucket", + {water_bucket = 1} +) + +bucket.register_liquid( + "default:lava_source", + "default:lava_flowing", + "bucket:bucket_lava", + "bucket_lava.png", + "Lava Bucket" +) + +minetest.register_craft({ + type = "fuel", + recipe = "bucket:bucket_lava", + burntime = 60, + replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}}, +}) + diff --git a/kingdoms_game/mods/bucket/textures/bucket.png b/kingdoms_game/mods/bucket/textures/bucket.png new file mode 100644 index 0000000..17b0c49 Binary files /dev/null and b/kingdoms_game/mods/bucket/textures/bucket.png differ diff --git a/kingdoms_game/mods/bucket/textures/bucket_lava.png b/kingdoms_game/mods/bucket/textures/bucket_lava.png new file mode 100644 index 0000000..ac6108d Binary files /dev/null and b/kingdoms_game/mods/bucket/textures/bucket_lava.png differ diff --git a/kingdoms_game/mods/bucket/textures/bucket_river_water.png b/kingdoms_game/mods/bucket/textures/bucket_river_water.png new file mode 100644 index 0000000..d4648bb Binary files /dev/null and b/kingdoms_game/mods/bucket/textures/bucket_river_water.png differ diff --git a/kingdoms_game/mods/bucket/textures/bucket_water.png b/kingdoms_game/mods/bucket/textures/bucket_water.png new file mode 100644 index 0000000..5af836b Binary files /dev/null and b/kingdoms_game/mods/bucket/textures/bucket_water.png differ diff --git a/kingdoms_game/mods/cake/README.txt b/kingdoms_game/mods/cake/README.txt new file mode 100644 index 0000000..5665dea --- /dev/null +++ b/kingdoms_game/mods/cake/README.txt @@ -0,0 +1,36 @@ +Minetest 0.4 mod: cake +====================== + +License of source code: +----------------------- +The MIT License (MIT) + +Copyright (c) 2015 MrIbby + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Authors and licenses of textures: +--------------------------------- +TenPlus1 (WTFPL): + cake.png + cake_bottom.png, derivative + cake_inner.png, derivative + cake_side.png, derivative + cake_sugar.png + cake_top.png, derivative diff --git a/kingdoms_game/mods/cake/depends.txt b/kingdoms_game/mods/cake/depends.txt new file mode 100644 index 0000000..c53185f --- /dev/null +++ b/kingdoms_game/mods/cake/depends.txt @@ -0,0 +1,5 @@ +bucket +farming +awards? +food? +intllib? diff --git a/kingdoms_game/mods/cake/description.txt b/kingdoms_game/mods/cake/description.txt new file mode 100644 index 0000000..319d217 --- /dev/null +++ b/kingdoms_game/mods/cake/description.txt @@ -0,0 +1 @@ +Adds delicious cakes to Minetest! diff --git a/kingdoms_game/mods/cake/init.lua b/kingdoms_game/mods/cake/init.lua new file mode 100644 index 0000000..1453620 --- /dev/null +++ b/kingdoms_game/mods/cake/init.lua @@ -0,0 +1,152 @@ +local throwable_cake = false + +-- CAKE -- + +local S +if minetest.get_modpath("intllib") then + S = intllib.Getter() +else + S = function(s) return s end +end + +local sizes = {-0.4375, -0.3125, -0.1875, -0.0625, 0.0625, 0.1875, 0.3125} + +for i, size in ipairs(sizes) do + local slice = i - 1 + local name + local description + local drop + local tiles + + if slice == 0 then + name = "cake:cake" + description = S("Cake") + drop = nil + tiles = {"cake_top.png", "cake_bottom.png", "cake_side.png"} + else + name = "cake:cake_"..slice + drop = '' + tiles = {"cake_top.png", "cake_bottom.png", "cake_side.png", "cake_inner.png", "cake_side.png", "cake_side.png"} + end + + minetest.register_node(name, { + description = description, + drop = drop, + drawtype = "nodebox", + tiles = tiles, + inventory_image = "cake.png", + wield_image = "cake.png", + paramtype = "light", + is_ground_content = false, + groups = {crumbly=3}, + --sounds = sounds, + node_box = { + type = "fixed", + fixed = { + {size, -0.5, -0.4375, 0.4375, 0, 0.4375}, + } + }, + on_rightclick = function(pos, node, clicker) + clicker:set_hp(clicker:get_hp() + 1) + + if i < #sizes then + minetest.swap_node(pos, {name="cake:cake_"..i}) + else + minetest.remove_node(pos) + end + end, + }) +end + +if not minetest.get_modpath("food") then + minetest.register_craftitem("cake:sugar", { + description = S("Sugar"), + inventory_image = "cake_sugar.png", + groups = {food_sugar=1} + }) + + minetest.register_craft({ + type = "shapeless", + output = "cake:sugar", + recipe = {"default:papyrus"} + }) +else + minetest.register_alias("cake:sugar", "food:sugar") +end + +minetest.register_craft({ + type = "shapeless", + output = "cake:cake", + recipe = {"farming:flour", "group:water_bucket", "group:food_sugar", "group:food_sugar"}, + replacements = { + {"group:water_bucket", "bucket:bucket_empty"}, + + -- Not needed >0.4.13 + {"bucket:bucket_water", "bucket:bucket_empty"}, + {"bucket:bucket_river_water", "bucket:bucket_empty"} + } +}) + +-- THROWABLE CAKE -- + +minetest.register_entity("cake:cake_entity", { + physical = false, + timer = 0, + textures = {"cake.png"}, + lastpos = {}, + collisionbox = {0,0,0,0,0,0}, + on_step = function(self, dtime) + self.timer=self.timer+dtime + local pos = self.object:getpos() + local node = minetest.get_node(pos) + + if self.timer>0.2 then + local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2) + for k, obj in pairs(objs) do + if obj:get_luaentity() == nil or obj:get_luaentity().name ~= "cake:cake_entity" and obj:get_luaentity().name ~= "__builtin:item" then + obj:set_hp(obj:get_hp() + 7) + self.object:remove() + end + end + end + + if self.lastpos.x~=nil then + if node.name ~= "air" then + minetest.add_item(self.lastpos, 'cake:cake') + self.object:remove() + end + end + self.lastpos={x=pos.x, y=pos.y, z=pos.z} + end, +}) + +if throwable_cake then + minetest.override_item("cake:cake", { + on_use = function(itemstack, player, pointed_thing) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + local playerpos = player:getpos() + local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, "cake:cake_entity") + local dir = player:get_look_dir() + obj:setvelocity({x=dir.x*19, y=dir.y*19, z=dir.z*19}) + obj:setacceleration({x=dir.x*-3, y=-10, z=dir.z*-3}) + obj:setyaw(player:get_look_yaw()+math.pi) + return itemstack + end, + }) +end + +-- CAKE AWARD -- +if minetest.get_modpath("awards") then + awards.register_achievement("award_the_lie", { + title = S("The Lie"), + description = S("Craft a cake"), + icon = "cake.png", + trigger = { + type = "craft", + item = "cake:cake", + target = 1 + } + }) +end diff --git a/kingdoms_game/mods/cake/locale/de.txt b/kingdoms_game/mods/cake/locale/de.txt new file mode 100644 index 0000000..a905b2a --- /dev/null +++ b/kingdoms_game/mods/cake/locale/de.txt @@ -0,0 +1,2 @@ +Cake = Kuchen +Sugar = Zucker diff --git a/kingdoms_game/mods/cake/locale/es.txt b/kingdoms_game/mods/cake/locale/es.txt new file mode 100644 index 0000000..d0271ae --- /dev/null +++ b/kingdoms_game/mods/cake/locale/es.txt @@ -0,0 +1,2 @@ +Cake = Pastel +Sugar = Azúcar diff --git a/kingdoms_game/mods/cake/locale/fr.txt b/kingdoms_game/mods/cake/locale/fr.txt new file mode 100644 index 0000000..557bfad --- /dev/null +++ b/kingdoms_game/mods/cake/locale/fr.txt @@ -0,0 +1,2 @@ +Cake = Gâteau +Sugar = Sucre diff --git a/kingdoms_game/mods/cake/locale/pt.txt b/kingdoms_game/mods/cake/locale/pt.txt new file mode 100644 index 0000000..b10fdea --- /dev/null +++ b/kingdoms_game/mods/cake/locale/pt.txt @@ -0,0 +1,2 @@ +Cake = Bolo +Sugar = Açúcar diff --git a/kingdoms_game/mods/cake/locale/ru.txt b/kingdoms_game/mods/cake/locale/ru.txt new file mode 100644 index 0000000..7274378 --- /dev/null +++ b/kingdoms_game/mods/cake/locale/ru.txt @@ -0,0 +1,2 @@ +Cake = Пирожное +Sugar = Сахар diff --git a/kingdoms_game/mods/cake/mod.conf b/kingdoms_game/mods/cake/mod.conf new file mode 100644 index 0000000..21ae169 --- /dev/null +++ b/kingdoms_game/mods/cake/mod.conf @@ -0,0 +1 @@ +name = cake diff --git a/kingdoms_game/mods/cake/screenshot.png b/kingdoms_game/mods/cake/screenshot.png new file mode 100644 index 0000000..3307068 Binary files /dev/null and b/kingdoms_game/mods/cake/screenshot.png differ diff --git a/kingdoms_game/mods/cake/textures/cake.png b/kingdoms_game/mods/cake/textures/cake.png new file mode 100644 index 0000000..22c70d4 Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake.png differ diff --git a/kingdoms_game/mods/cake/textures/cake_bottom.png b/kingdoms_game/mods/cake/textures/cake_bottom.png new file mode 100644 index 0000000..84d8ad3 Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake_bottom.png differ diff --git a/kingdoms_game/mods/cake/textures/cake_inner.png b/kingdoms_game/mods/cake/textures/cake_inner.png new file mode 100644 index 0000000..f1d0b52 Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake_inner.png differ diff --git a/kingdoms_game/mods/cake/textures/cake_side.png b/kingdoms_game/mods/cake/textures/cake_side.png new file mode 100644 index 0000000..87902d1 Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake_side.png differ diff --git a/kingdoms_game/mods/cake/textures/cake_sugar.png b/kingdoms_game/mods/cake/textures/cake_sugar.png new file mode 100644 index 0000000..5cb7fa0 Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake_sugar.png differ diff --git a/kingdoms_game/mods/cake/textures/cake_top.png b/kingdoms_game/mods/cake/textures/cake_top.png new file mode 100644 index 0000000..764566f Binary files /dev/null and b/kingdoms_game/mods/cake/textures/cake_top.png differ diff --git a/kingdoms_game/mods/campfire/.gitattributes b/kingdoms_game/mods/campfire/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/kingdoms_game/mods/campfire/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/kingdoms_game/mods/campfire/.gitignore b/kingdoms_game/mods/campfire/.gitignore new file mode 100644 index 0000000..5ebd21a --- /dev/null +++ b/kingdoms_game/mods/campfire/.gitignore @@ -0,0 +1,163 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store diff --git a/kingdoms_game/mods/campfire/depends.txt b/kingdoms_game/mods/campfire/depends.txt new file mode 100644 index 0000000..331d858 --- /dev/null +++ b/kingdoms_game/mods/campfire/depends.txt @@ -0,0 +1 @@ +default \ No newline at end of file diff --git a/kingdoms_game/mods/campfire/init.lua b/kingdoms_game/mods/campfire/init.lua new file mode 100644 index 0000000..714c86c --- /dev/null +++ b/kingdoms_game/mods/campfire/init.lua @@ -0,0 +1,299 @@ + +-- +-- Formspecs +-- + +local function active_formspec(fuel_percent, item_percent) + local formspec = + "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[current_name;src;2.75,0.5;1,1;]".. + "list[current_name;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. + (100-fuel_percent)..":default_furnace_fire_fg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:".. + (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]".. + "list[current_name;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[current_name;dst]".. + "listring[current_player;main]".. + "listring[current_name;src]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4.25) + return formspec +end + +local inactive_formspec = + "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[current_name;src;2.75,0.5;1,1;]".. + "list[current_name;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "list[current_name;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[current_name;dst]".. + "listring[current_player;main]".. + "listring[current_name;src]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4.25) + +-- +-- Node callback functions that are the same for active and inactive furnace +-- + +local function can_dig(pos, player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src") +end + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if listname == "fuel" then + if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then + if inv:is_empty("src") then + meta:set_string("infotext", "Campfire has no wood") + end + return stack:get_count() + else + return 0 + end + elseif listname == "src" then + return stack:get_count() + elseif listname == "dst" then + return 0 + end +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(from_list, from_index) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function swap_node(pos, name) + local node = minetest.get_node(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function furnace_node_timer(pos, elapsed) + -- + -- Inizialize metadata + -- + local meta = minetest.get_meta(pos) + local fuel_time = meta:get_float("fuel_time") or 0 + local src_time = meta:get_float("src_time") or 0 + local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 + + local inv = meta:get_inventory() + local srclist = inv:get_list("src") + local fuellist = inv:get_list("fuel") + local dstlist = inv:get_list("dst") + + -- + -- Cooking + -- + + -- Check if we have cookable content + local cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) + local cookable = true + + if cooked.time == 0 then + cookable = false + end + + -- Check if we have enough fuel to burn + if fuel_time < fuel_totaltime then + -- The furnace is currently active and has enough fuel + fuel_time = fuel_time + .75 + + -- If there is a cookable item then check if it is ready yet + if cookable then + src_time = src_time + .75 + if src_time >= cooked.time then + -- Place result in dst list if possible + if inv:room_for_item("dst", cooked.item) then + inv:add_item("dst", cooked.item) + inv:set_stack("src", 1, aftercooked.items[1]) + src_time = 0 + end + end + end + else + -- Furnace ran out of fuel + if cookable then + -- We need to get new fuel + local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist}) + + if fuel.time == 0 then + -- No valid fuel in fuel list + fuel_totaltime = 0 + fuel_time = 0 + src_time = 0 + else + -- Take fuel from fuel list + inv:set_stack("fuel", 1, afterfuel.items[1]) + + fuel_totaltime = fuel.time + fuel_time = 0 + end + else + -- We don't need to get new fuel since there is no cookable item + fuel_totaltime = 0 + fuel_time = 0 + src_time = 0 + end + end + + -- + -- Update formspec, infotext and node + -- + local formspec = inactive_formspec + local item_state = "" + local item_percent = 0 + if cookable then + item_percent = math.floor(src_time / cooked.time * 100) + item_state = item_percent .. "%" + else + if srclist[1]:is_empty() then + item_state = "Empty" + else + item_state = "Not cookable" + end + end + + local fuel_state = "Empty" + local active = "inactive " + local result = false + + if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then + active = "active " + local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100) + fuel_state = fuel_percent .. "%" + formspec = active_formspec(fuel_percent, item_percent) + swap_node(pos, "campfire:campfire_active") + -- make sure timer restarts automatically + result = true + else + if not fuellist[1]:is_empty() then + fuel_state = "0%" + end + swap_node(pos, "campfire:campfire") + -- stop timer on the inactive furnace + local timer = minetest.get_node_timer(pos) + timer:stop() + end + + local infotext = "Campfire " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")" + + -- + -- Set meta values + -- + meta:set_float("fuel_totaltime", fuel_totaltime) + meta:set_float("fuel_time", fuel_time) + meta:set_float("src_time", src_time) + meta:set_string("formspec", formspec) + meta:set_string("infotext", infotext) + + return result +end + +-- +-- Node definitions +-- + +minetest.register_node("campfire:campfire", { + description = "Camp Fire", + drawtype = "plantlike", + tiles = {"CampFire_off.png"}, + walkable=false, + sunlight_propogates=true, + paramtype="light", + paramtype2 = "facedir", + groups = {oddly_breakable_by_hand=1}, + legacy_facedir_simple = true, + sounds = default.node_sound_stone_defaults(), + + can_dig = can_dig, + + on_timer = furnace_node_timer, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", inactive_formspec) + local inv = meta:get_inventory() + inv:set_size('src', 1) + inv:set_size('fuel', 1) + inv:set_size('dst', 4) + end, + + on_metadata_inventory_move = function(pos) + local timer = minetest.get_node_timer(pos) + timer:start(1.0) + end, + on_metadata_inventory_put = function(pos) + -- start timer function, it will sort out whether furnace can burn or not. + local timer = minetest.get_node_timer(pos) + timer:start(1.0) + end, + on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "src", drops) + default.get_inventory_drops(pos, "fuel", drops) + default.get_inventory_drops(pos, "dst", drops) + drops[#drops+1] = "campfire:campfire" + minetest.remove_node(pos) + return drops + end, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) + +minetest.register_node("campfire:campfire_active", { + description = "Campfire Active", + drawtype = "plantlike", + tiles = {{name="CampFire.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}}, + light_source = 8, + paramtype="light", + walkable=false, + drop = "campfire:campfire", + groups = {cracky=2, not_in_creative_inventory=1}, + legacy_facedir_simple = true, + sounds = default.node_sound_stone_defaults(), + + drop = "campfire:campfire", + is_ground_content = false, + on_timer = furnace_node_timer, + + can_dig = can_dig, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) + diff --git a/kingdoms_game/mods/campfire/textures/CampFire.png b/kingdoms_game/mods/campfire/textures/CampFire.png new file mode 100644 index 0000000..85f8451 Binary files /dev/null and b/kingdoms_game/mods/campfire/textures/CampFire.png differ diff --git a/kingdoms_game/mods/campfire/textures/CampFire_off.png b/kingdoms_game/mods/campfire/textures/CampFire_off.png new file mode 100644 index 0000000..cc3f980 Binary files /dev/null and b/kingdoms_game/mods/campfire/textures/CampFire_off.png differ diff --git a/kingdoms_game/mods/carts/README.txt b/kingdoms_game/mods/carts/README.txt new file mode 100644 index 0000000..31ce644 --- /dev/null +++ b/kingdoms_game/mods/carts/README.txt @@ -0,0 +1,22 @@ +Carts (formerly boost_cart) +========================== + +Carts, based almost entirely on the mod boost_cart [1], which +itself is based on (and fully compatible with) the carts mod [2]. + +The model was originally designed by stujones11 [3] (CC-0). + +Cart textures are based on original work from PixelBOX (WTFPL). + + +[1] https://github.com/SmallJoker/boost_cart/ +[2] https://github.com/PilzAdam/carts/ +[3] https://github.com/stujones11/railcart/ + + +Features +---------- +- A fast cart for your railway or roller coaster (up to 7 m/s!) +- Boost and brake rails +- Rail junction switching with the 'right-left' walking keys +- Handbrake with the 'back' key diff --git a/kingdoms_game/mods/carts/cart_entity.lua b/kingdoms_game/mods/carts/cart_entity.lua new file mode 100644 index 0000000..e8707fb --- /dev/null +++ b/kingdoms_game/mods/carts/cart_entity.lua @@ -0,0 +1,392 @@ +local cart_entity = { + physical = false, -- otherwise going uphill breaks + collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + visual = "mesh", + mesh = "carts_cart.b3d", + visual_size = {x=1, y=1}, + textures = {"carts_cart.png"}, + + driver = nil, + punched = false, -- used to re-send velocity and position + velocity = {x=0, y=0, z=0}, -- only used on punch + old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch + old_pos = nil, + old_switch = 0, + railtype = nil, + attached_items = {} +} + +function cart_entity:on_rightclick(clicker) + if not clicker or not clicker:is_player() then + return + end + local player_name = clicker:get_player_name() + if self.driver and player_name == self.driver then + self.driver = nil + carts:manage_attachment(clicker, nil) + elseif not self.driver then + self.driver = player_name + carts:manage_attachment(clicker, self.object) + end +end + +function cart_entity:on_activate(staticdata, dtime_s) + self.object:set_armor_groups({immortal=1}) + if string.sub(staticdata, 1, string.len("return")) ~= "return" then + return + end + local data = minetest.deserialize(staticdata) + if not data or type(data) ~= "table" then + return + end + self.railtype = data.railtype + if data.old_dir then + self.old_dir = data.old_dir + end + if data.old_vel then + self.old_vel = data.old_vel + end +end + +function cart_entity:get_staticdata() + return minetest.serialize({ + railtype = self.railtype, + old_dir = self.old_dir, + old_vel = self.old_vel + }) +end + +function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) + local pos = self.object:getpos() + if not self.railtype then + local node = minetest.get_node(pos).name + self.railtype = minetest.get_item_group(node, "connect_to_raillike") + end + -- Punched by non-player + if not puncher or not puncher:is_player() then + local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + self.velocity = vector.multiply(cart_dir, 2) + self.punched = true + return + end + -- Player digs cart by sneak-punch + if puncher:get_player_control().sneak then + if self.sound_handle then + minetest.sound_stop(self.sound_handle) + end + -- Detach driver and items + if self.driver then + if self.old_pos then + self.object:setpos(self.old_pos) + end + local player = minetest.get_player_by_name(self.driver) + carts:manage_attachment(player, nil) + end + for _,obj_ in ipairs(self.attached_items) do + if obj_ then + obj_:set_detach() + end + end + -- Pick up cart + local inv = puncher:get_inventory() + if not minetest.setting_getbool("creative_mode") + or not inv:contains_item("main", "carts:cart") then + local leftover = inv:add_item("main", "carts:cart") + -- If no room in inventory add a replacement cart to the world + if not leftover:is_empty() then + minetest.add_item(self.object:getpos(), leftover) + end + end + self.object:remove() + return + end + -- Player punches cart to alter velocity + local vel = self.object:getvelocity() + if puncher:get_player_name() == self.driver then + if math.abs(vel.x + vel.z) > carts.punch_speed_max then + return + end + end + + local punch_dir = carts:velocity_to_dir(puncher:get_look_dir()) + punch_dir.y = 0 + local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + + local punch_interval = 1 + if tool_capabilities and tool_capabilities.full_punch_interval then + punch_interval = tool_capabilities.full_punch_interval + end + time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval) + local f = 2 * (time_from_last_punch / punch_interval) + + self.velocity = vector.multiply(cart_dir, f) + self.old_dir = cart_dir + self.punched = true +end + +local function rail_on_step_event(handler, obj, dtime) + if handler then + handler(obj, dtime) + end +end + +-- sound refresh interval = 1.0sec +local function rail_sound(self, dtime) + if not self.sound_ttl then + self.sound_ttl = 1.0 + return + elseif self.sound_ttl > 0 then + self.sound_ttl = self.sound_ttl - dtime + return + end + self.sound_ttl = 1.0 + if self.sound_handle then + local handle = self.sound_handle + self.sound_handle = nil + minetest.after(0.2, minetest.sound_stop, handle) + end + local vel = self.object:getvelocity() + local speed = vector.length(vel) + if speed > 0 then + self.sound_handle = minetest.sound_play( + "carts_cart_moving", { + object = self.object, + gain = (speed / carts.speed_max) / 2, + loop = true, + }) + end +end + +local function get_railparams(pos) + local node = minetest.get_node(pos) + return carts.railparams[node.name] or {} +end + +local function rail_on_step(self, dtime) + local vel = self.object:getvelocity() + if self.punched then + vel = vector.add(vel, self.velocity) + self.object:setvelocity(vel) + self.old_dir.y = 0 + elseif vector.equals(vel, {x=0, y=0, z=0}) then + return + end + + local pos = self.object:getpos() + local update = {} + + -- stop cart if velocity vector flips + if self.old_vel and self.old_vel.y == 0 and + (self.old_vel.x * vel.x < 0 or self.old_vel.z * vel.z < 0) then + self.old_vel = {x = 0, y = 0, z = 0} + self.old_pos = pos + self.object:setvelocity(vector.new()) + self.object:setacceleration(vector.new()) + rail_on_step_event(get_railparams(pos).on_step, self, dtime) + return + end + self.old_vel = vector.new(vel) + + if self.old_pos and not self.punched then + local flo_pos = vector.round(pos) + local flo_old = vector.round(self.old_pos) + if vector.equals(flo_pos, flo_old) then + -- Do not check one node multiple times + return + end + end + + local ctrl, player + + -- Get player controls + if self.driver then + player = minetest.get_player_by_name(self.driver) + if player then + ctrl = player:get_player_control() + end + end + + if self.old_pos then + -- Detection for "skipping" nodes + local found_path = carts:pathfinder( + pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype + ) + + if not found_path then + -- No rail found: reset back to the expected position + pos = vector.new(self.old_pos) + update.pos = true + end + end + + local cart_dir = carts:velocity_to_dir(vel) + local railparams + + -- dir: New moving direction of the cart + -- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node + local dir, switch_keys = carts:get_rail_direction( + pos, cart_dir, ctrl, self.old_switch, self.railtype + ) + + local new_acc = {x=0, y=0, z=0} + if vector.equals(dir, {x=0, y=0, z=0}) then + vel = {x = 0, y = 0, z = 0} + pos = vector.round(pos) + update.pos = true + update.vel = true + else + -- Direction change detected + if not vector.equals(dir, self.old_dir) then + vel = vector.multiply(dir, math.abs(vel.x + vel.z)) + update.vel = true + if dir.y ~= self.old_dir.y then + pos = vector.round(pos) + update.pos = true + end + end + -- Center on the rail + if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then + pos.x = math.floor(pos.x + 0.5) + update.pos = true + end + if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then + pos.z = math.floor(pos.z + 0.5) + update.pos = true + end + + -- Slow down or speed up.. + local acc = dir.y * -4.0 + + -- Get rail for corrected position + railparams = get_railparams(pos) + + -- no need to check for railparams == nil since we always make it exist. + local speed_mod = railparams.acceleration + if speed_mod and speed_mod ~= 0 then + -- Try to make it similar to the original carts mod + acc = acc + speed_mod + else + -- Handbrake or coast + if ctrl and ctrl.down then + acc = acc - 3 + else + acc = acc - 0.4 + end + end + + new_acc = vector.multiply(dir, acc) + end + + -- Limits + local max_vel = carts.speed_max + for _, v in pairs({"x","y","z"}) do + if math.abs(vel[v]) > max_vel then + vel[v] = carts:get_sign(vel[v]) * max_vel + new_acc[v] = 0 + update.vel = true + end + end + + self.object:setacceleration(new_acc) + self.old_pos = vector.new(pos) + if not vector.equals(dir, {x=0, y=0, z=0}) then + self.old_dir = vector.new(dir) + end + self.old_switch = switch_keys + + if self.punched then + -- Collect dropped items + for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if not obj_:is_player() and + obj_:get_luaentity() and + not obj_:get_luaentity().physical_state and + obj_:get_luaentity().name == "__builtin:item" then + + obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}) + self.attached_items[#self.attached_items + 1] = obj_ + end + end + self.punched = false + update.vel = true + end + + railparams = railparams or get_railparams(pos) + + if not (update.vel or update.pos) then + rail_on_step_event(railparams.on_step, self, dtime) + return + end + + local yaw = 0 + if self.old_dir.x < 0 then + yaw = 0.5 + elseif self.old_dir.x > 0 then + yaw = 1.5 + elseif self.old_dir.z < 0 then + yaw = 1 + end + self.object:setyaw(yaw * math.pi) + + local anim = {x=0, y=0} + if dir.y == -1 then + anim = {x=1, y=1} + elseif dir.y == 1 then + anim = {x=2, y=2} + end + self.object:set_animation(anim, 1, 0) + + self.object:setvelocity(vel) + if update.pos then + self.object:setpos(pos) + end + + -- call event handler + rail_on_step_event(railparams.on_step, self, dtime) +end + +function cart_entity:on_step(dtime) + rail_on_step(self, dtime) + rail_sound(self, dtime) +end + +minetest.register_entity("carts:cart", cart_entity) + +minetest.register_craftitem("carts:cart", { + description = "Cart (Sneak+Click to pick up)", + inventory_image = minetest.inventorycube("carts_cart_top.png", "carts_cart_side.png", "carts_cart_side.png"), + wield_image = "carts_cart_side.png", + on_place = function(itemstack, placer, pointed_thing) + if not pointed_thing.type == "node" then + return + end + if carts:is_rail(pointed_thing.under) then + minetest.add_entity(pointed_thing.under, "carts:cart") + elseif carts:is_rail(pointed_thing.above) then + minetest.add_entity(pointed_thing.above, "carts:cart") + else + return + end + + minetest.sound_play({name = "default_place_node_metal", gain = 0.5}, + {pos = pointed_thing.above}) + + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end, +}) + +minetest.register_craft({ + output = "carts:cart", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + }, +}) diff --git a/kingdoms_game/mods/carts/depends.txt b/kingdoms_game/mods/carts/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/kingdoms_game/mods/carts/depends.txt @@ -0,0 +1 @@ +default diff --git a/kingdoms_game/mods/carts/functions.lua b/kingdoms_game/mods/carts/functions.lua new file mode 100644 index 0000000..ed64884 --- /dev/null +++ b/kingdoms_game/mods/carts/functions.lua @@ -0,0 +1,221 @@ +function carts:get_sign(z) + if z == 0 then + return 0 + else + return z / math.abs(z) + end +end + +function carts:manage_attachment(player, obj) + if not player then + return + end + local status = obj ~= nil + local player_name = player:get_player_name() + if default.player_attached[player_name] == status then + return + end + default.player_attached[player_name] = status + + if status then + player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0}) + player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0}) + else + player:set_detach() + player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) + end +end + +function carts:velocity_to_dir(v) + if math.abs(v.x) > math.abs(v.z) then + return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0} + else + return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)} + end +end + +function carts:is_rail(pos, railtype) + local node = minetest.get_node(pos).name + if node == "ignore" then + local vm = minetest.get_voxel_manip() + local emin, emax = vm:read_from_map(pos, pos) + local area = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax, + } + local data = vm:get_data() + local vi = area:indexp(pos) + node = minetest.get_name_from_content_id(data[vi]) + end + if minetest.get_item_group(node, "rail") == 0 then + return false + end + if not railtype then + return true + end + return minetest.get_item_group(node, "connect_to_raillike") == railtype +end + +function carts:check_front_up_down(pos, dir_, check_up, railtype) + local dir = vector.new(dir_) + local cur + + -- Front + dir.y = 0 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + -- Up + if check_up then + dir.y = 1 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + end + -- Down + dir.y = -1 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + return nil +end + +function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) + local pos = vector.round(pos_) + local cur + local left_check, right_check = true, true + + -- Check left and right + local left = {x=0, y=0, z=0} + local right = {x=0, y=0, z=0} + if dir.z ~= 0 and dir.x == 0 then + left.x = -dir.z + right.x = dir.z + elseif dir.x ~= 0 and dir.z == 0 then + left.z = dir.x + right.z = -dir.x + end + + if ctrl then + if old_switch == 1 then + left_check = false + elseif old_switch == 2 then + right_check = false + end + if ctrl.left and left_check then + cur = carts:check_front_up_down(pos, left, false, railtype) + if cur then + return cur, 1 + end + left_check = false + end + if ctrl.right and right_check then + cur = carts:check_front_up_down(pos, right, false, railtype) + if cur then + return cur, 2 + end + right_check = true + end + end + + -- Normal + cur = carts:check_front_up_down(pos, dir, true, railtype) + if cur then + return cur + end + + -- Left, if not already checked + if left_check then + cur = carts:check_front_up_down(pos, left, false, railtype) + if cur then + return cur + end + end + + -- Right, if not already checked + if right_check then + cur = carts:check_front_up_down(pos, right, false, railtype) + if cur then + return cur + end + end + + -- Backwards + if not old_switch then + cur = carts:check_front_up_down(pos, { + x = -dir.x, + y = dir.y, + z = -dir.z + }, true, railtype) + if cur then + return cur + end + end + + return {x=0, y=0, z=0} +end + +function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) + local pos = vector.round(pos_) + local pf_pos = vector.round(old_pos) + local pf_dir = vector.new(old_dir) + + for i = 1, 3 do + if vector.equals(pf_pos, pos) then + -- Success! Cart moved on correctly + return true + end + + pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype) + if vector.equals(pf_dir, {x=0, y=0, z=0}) then + -- No way forwards + return false + end + + pf_pos = vector.add(pf_pos, pf_dir) + end + -- Cart not found + return false +end + +function carts:register_rail(name, def, railparams) + local def_default = { + drawtype = "raillike", + paramtype = "light", + sunlight_propagates = true, + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, + }, + sounds = default.node_sound_stone_defaults() + } + for k, v in pairs(def_default) do + def[k] = v + end + if not def.inventory_image then + def.wield_image = def.tiles[1] + def.inventory_image = def.tiles[1] + end + + if railparams then + carts.railparams[name] = table.copy(railparams) + end + + minetest.register_node(name, def) +end + +function carts:get_rail_groups(additional_groups) + -- Get the default rail groups and add more when a table is given + local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1} + if type(additional_groups) == "table" then + for k, v in pairs(additional_groups) do + groups[k] = v + end + end + return groups +end diff --git a/kingdoms_game/mods/carts/init.lua b/kingdoms_game/mods/carts/init.lua new file mode 100644 index 0000000..53b33cc --- /dev/null +++ b/kingdoms_game/mods/carts/init.lua @@ -0,0 +1,20 @@ + +carts = {} +carts.modpath = minetest.get_modpath("carts") +carts.railparams = {} + +-- Maximal speed of the cart in m/s (min = -1) +carts.speed_max = 7 +-- Set to -1 to disable punching the cart from inside (min = -1) +carts.punch_speed_max = 5 + + +dofile(carts.modpath.."/functions.lua") +dofile(carts.modpath.."/rails.lua") + +-- Support for non-default games +if not default.player_attached then + default.player_attached = {} +end + +dofile(carts.modpath.."/cart_entity.lua") diff --git a/kingdoms_game/mods/carts/license.txt b/kingdoms_game/mods/carts/license.txt new file mode 100644 index 0000000..6c5beb4 --- /dev/null +++ b/kingdoms_game/mods/carts/license.txt @@ -0,0 +1,54 @@ + +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 SmallJoker +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media +----------------- + +CC-0, see: https://creativecommons.org/share-your-work/public-domain/cc0/, except +if other license is mentioned. + + +Authors +--------- +Originally from PixelBOX (Gambit): + carts_cart_side.png + carts_cart_top.png + carts_cart_front.png* + carts_cart.png* + +sofar + stujones11: + carts_cart.b3d and carts_cart.blend + +hexafraction, modified by sofar + carts_rail_*.png + +http://www.freesound.org/people/YleArkisto/sounds/253159/ - YleArkisto - CC-BY-3.0 + carts_cart_moving.*.ogg diff --git a/kingdoms_game/mods/carts/models/carts_cart.b3d b/kingdoms_game/mods/carts/models/carts_cart.b3d new file mode 100644 index 0000000..4e7eba3 Binary files /dev/null and b/kingdoms_game/mods/carts/models/carts_cart.b3d differ diff --git a/kingdoms_game/mods/carts/models/carts_cart.blend b/kingdoms_game/mods/carts/models/carts_cart.blend new file mode 100644 index 0000000..7d2515e Binary files /dev/null and b/kingdoms_game/mods/carts/models/carts_cart.blend differ diff --git a/kingdoms_game/mods/carts/rails.lua b/kingdoms_game/mods/carts/rails.lua new file mode 100644 index 0000000..5da4ac4 --- /dev/null +++ b/kingdoms_game/mods/carts/rails.lua @@ -0,0 +1,59 @@ +carts:register_rail("carts:rail", { + description = "Rail", + tiles = { + "carts_rail_straight.png", "carts_rail_curved.png", + "carts_rail_t_junction.png", "carts_rail_crossing.png" + }, + inventory_image = "carts_rail_straight.png", + wield_image = "carts_rail_straight.png", + groups = carts:get_rail_groups(), +}, {}) + +minetest.register_craft({ + output = "carts:rail 16", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"}, + } +}) + +minetest.register_alias("default:rail", "carts:rail") + + +carts:register_rail("carts:powerrail", { + description = "Powered rail", + tiles = { + "carts_rail_straight_pwr.png", "carts_rail_curved_pwr.png", + "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png" + }, + groups = carts:get_rail_groups(), +}, {acceleration = 5}) + +minetest.register_craft({ + output = "carts:powerrail 8", + recipe = { + {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, + } +}) + + +carts:register_rail("carts:brakerail", { + description = "Brake rail", + tiles = { + "carts_rail_straight_brk.png", "carts_rail_curved_brk.png", + "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png" + }, + groups = carts:get_rail_groups(), +}, {acceleration = -3}) + +minetest.register_craft({ + output = "carts:brakerail 8", + recipe = { + {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, + } +}) diff --git a/kingdoms_game/mods/carts/sounds/carts_cart_moving.1.ogg b/kingdoms_game/mods/carts/sounds/carts_cart_moving.1.ogg new file mode 100644 index 0000000..869e765 Binary files /dev/null and b/kingdoms_game/mods/carts/sounds/carts_cart_moving.1.ogg differ diff --git a/kingdoms_game/mods/carts/sounds/carts_cart_moving.2.ogg b/kingdoms_game/mods/carts/sounds/carts_cart_moving.2.ogg new file mode 100644 index 0000000..b4cc508 Binary files /dev/null and b/kingdoms_game/mods/carts/sounds/carts_cart_moving.2.ogg differ diff --git a/kingdoms_game/mods/carts/sounds/carts_cart_moving.3.ogg b/kingdoms_game/mods/carts/sounds/carts_cart_moving.3.ogg new file mode 100644 index 0000000..e19a782 Binary files /dev/null and b/kingdoms_game/mods/carts/sounds/carts_cart_moving.3.ogg differ diff --git a/kingdoms_game/mods/carts/textures/carts_cart.png b/kingdoms_game/mods/carts/textures/carts_cart.png new file mode 100644 index 0000000..965347c Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_cart.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_cart_front.png b/kingdoms_game/mods/carts/textures/carts_cart_front.png new file mode 100644 index 0000000..b85696f Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_cart_front.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_cart_side.png b/kingdoms_game/mods/carts/textures/carts_cart_side.png new file mode 100644 index 0000000..4362d6b Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_cart_side.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_cart_top.png b/kingdoms_game/mods/carts/textures/carts_cart_top.png new file mode 100644 index 0000000..5f775ff Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_cart_top.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_crossing.png b/kingdoms_game/mods/carts/textures/carts_rail_crossing.png new file mode 100644 index 0000000..e10f3b1 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_crossing.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_crossing_brk.png b/kingdoms_game/mods/carts/textures/carts_rail_crossing_brk.png new file mode 100644 index 0000000..0bf455e Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_crossing_brk.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_crossing_pwr.png b/kingdoms_game/mods/carts/textures/carts_rail_crossing_pwr.png new file mode 100644 index 0000000..d763d50 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_crossing_pwr.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_curved.png b/kingdoms_game/mods/carts/textures/carts_rail_curved.png new file mode 100644 index 0000000..b320f0d Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_curved.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_curved_brk.png b/kingdoms_game/mods/carts/textures/carts_rail_curved_brk.png new file mode 100644 index 0000000..ca40723 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_curved_brk.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_curved_pwr.png b/kingdoms_game/mods/carts/textures/carts_rail_curved_pwr.png new file mode 100644 index 0000000..781bbd0 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_curved_pwr.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_straight.png b/kingdoms_game/mods/carts/textures/carts_rail_straight.png new file mode 100644 index 0000000..30dcafe Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_straight.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_straight_brk.png b/kingdoms_game/mods/carts/textures/carts_rail_straight_brk.png new file mode 100644 index 0000000..0c69052 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_straight_brk.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_straight_pwr.png b/kingdoms_game/mods/carts/textures/carts_rail_straight_pwr.png new file mode 100644 index 0000000..e067ff1 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_straight_pwr.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_t_junction.png b/kingdoms_game/mods/carts/textures/carts_rail_t_junction.png new file mode 100644 index 0000000..8b1b946 Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_t_junction.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_t_junction_brk.png b/kingdoms_game/mods/carts/textures/carts_rail_t_junction_brk.png new file mode 100644 index 0000000..6b4f6fa Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_t_junction_brk.png differ diff --git a/kingdoms_game/mods/carts/textures/carts_rail_t_junction_pwr.png b/kingdoms_game/mods/carts/textures/carts_rail_t_junction_pwr.png new file mode 100644 index 0000000..dd0eede Binary files /dev/null and b/kingdoms_game/mods/carts/textures/carts_rail_t_junction_pwr.png differ diff --git a/kingdoms_game/mods/cme/API.txt b/kingdoms_game/mods/cme/API.txt new file mode 100644 index 0000000..d16d8e3 --- /dev/null +++ b/kingdoms_game/mods/cme/API.txt @@ -0,0 +1,202 @@ +Creatures MOB-Engine API +------------------------ + +creatures.register_mob(#Creature definition) + -registers a mob at MOB-Engine; returns true when sucessfull + +creatures.rnd(chance_table) + -returns a weighted random table element; chance_sum of table must be 1 + ^ example: creatures.rnd({elem1 = {chance = 0.7}, {elem2 = {chance = 0.3}}) + +creatures.compare_pos(pos1, pos2) + -returns true if pos1 == pos2 + +creatures.findTarget(search_obj, pos, radius, search_type, mob_name, xray, no_count) + -returns table of found objects (as ObjectRef) and boolean player_near + ^ search_obj is searching object; can be nil + ^ pos is starting position for search radius + ^ radius for searching in blocks/node + ^ search_type that specifies returned object requirements + ^ "all" -- returns every object except dropped Items + ^ "hostile" -- returns every object(creature) that has hostile setting or is player + ^ ignores "mob_type" if specified + ^ "nonhostile" -- returns every object that is not hostile or player + ^ "player" -- returns all players + ^ "mates" -- returns all objects(creatures) that are of same kind + ^ requires "mob_type" specifies + ^ mob_type specifies creature that is ignored or searched, depending on search_type + ^ xray allows searching through blocks/nodes (default == false) + ^ no_count skips collecting loop and returns just the boolean player_near + ^ table is empty + +creatures.dropItems(pos, drops) + -drops items at position pos + ^ pos where to drop Items + ^ drops table in #ItemDrops format + + +#ItemDrops +---------- +{ + { + , -- e.g. "default:wood" + , -- either a or table in format {min = , max = }; optional + -- "chance = ": between 0.0 and 1.0 + }, +} + +Example: +Will drop with a chance of 30% 1 to 3 items of type "default:wood" +and with a chance of 100% 2 items of type "default:stone" +{ + {"default:wood", {min = 1, max = 3}, chance = 0.3}, + {"default:stone", 2} +} + + +#Creature definition +-------------------- +{ + name = "", -- e.g. "creatures:sheep" + stats = { + hp = 1, -- 1 HP = "1/2 player heart" + hostile = false, -- is mob hostile (required for mode "attack") + lifetime = 300, -- after which time mob despawns, in seconds + dies_when_tamed = false, -- stop despawn when tamed + can_jump = 1, -- height in nodes + can_swim = false, -- can mob swim or will it drown + can_fly = false, -- allows to fly (requires mode "fly") and disable step sounds + can_burn = false, -- takes damage of lava + can_panic = false, -- runs fast around when hit (requires mode "walk") + has_falldamage = false, -- deals damage if falling more than 3 blocks + has_kockback = false, -- get knocked back when hit + sneaky = false, -- disables step sounds + light = {min, max}, -- which light level will burn creature (requires can_burn = true) + }, + + modes = { + idle = {chance = , duration =