Merge pull request 'develop' (#23) from develop into master

Reviewed-on: #23
This commit is contained in:
Milan Meduna 2020-12-17 09:34:35 +01:00
commit bf485be5b9
125 changed files with 1765 additions and 458 deletions

View file

@ -0,0 +1,482 @@
# [mod] Visible Player Armor [3d_armor]
| | | | |
|--|--|--|--|
|-[Overview](#overview) |||-[API](#api)|
|-[Armor Configuration](#armor-configuration) |||- - [3d_Armor Item Storage](#3d_armor-item-storage)
|- - [disable_specific_materials](#to-disable-individual-armor-materials) |||- - [Armor Registration](#armor-registration)
|- - [armor_init_delay](#initialization-glitches-when-a-player-first-joins) |||- - [Registering Armor Groups](#registering-armor-groups)
|- - [armor_init_times](#number-of-initialization-attempts) |||- - [Groups used by 3d_Armor](#groups-used-by-3d_armor)
|- - [armor_bones_delay](#armor-not-in-bones-due-to-server-lag) |||- - - [Elements](#elements)
|- - [armor_update_time](#how-often-player-armor-items-are-updated) |||- - - [Attributes](#attributes)
|- - [armor_drop](#drop-armor-when-a-player-dies) |||- - - [Physics](#physics)
|- - [armor_destroy](#destroy-armor-when-a-player-dies) |||- - - [Durability](#durability)
|- - [armor_level_multiplier](#armor-level-multiplyer) |||- - [Armour Functions](#armour-functions)
|- - [armor_heal_multiplier](#armor-healing-multiplyer) |||- - - [armor:set_player_armor](#armor-set_player_armor)
|- - [armor_water_protect](#enable-water-protection) |||- - - [armor:punch](#armor-punch)
|- - [armor_fire_protect](#enable-fire-protection) |||- - - [armor:damage](#armor-damage)
|- - [armor_punch_damage](#enable-punch-damage-effects) |||- - - [armor:remove_all](#armor-remove_all)
|- - [armor_migrate_old_inventory](#migration-of-old-armor-inventories) |||- - - [armor:equip](#armor-equip)
|- - [wieldview_update_time](#how-often-player-wield-items-are-updated) |||- - - [armor:unequip](#armor-unequip)
| - [Credits](#credits) |||- - - [armor:update_skin](#armor-update_skin)
| |||- - [Callbacks](#Callbacks)
| |||- - - [Item callbacks](#item-callbacks)
| |||- - - [Global callbacks](#global-callbacks)
# Overview
**Depends:** default
**Recommends:** sfinv, unified_inventory or smart_inventory (use only one to avoid conflicts)
**Supports:** player_monoids, armor_monoid and POVA
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.
# Armor Configuration
Override the following default settings by adding them to your ***minetest.conf*** file.
### To disable individual armor materials
**set the below to false**
armor_material_wood = true
armor_material_cactus = true
armor_material_steel = true
armor_material_bronze = true
armor_material_diamond = true
armor_material_gold = true
armor_material_mithril = true
armor_material_crystal = true
### Initialization glitches when a player first joins
**Increase to prevent glitches**
armor_init_delay = 2
### Number of initialization attempts
**Increase to prevent glitches - Use in conjunction with armor_init_delay if initialization problems persist.**
armor_init_times = 10
### Armor not in bones due to server lag
**Increase to help resolve**
armor_bones_delay = 1
### How often player armor items are updated
**Number represents how often per second update is performed, higher value means less performance hit for servers but armor items maybe delayed in updating when switching.Fractional seconds also supported eg 0.1**
armor_update_time = 1
### Drop armor when a player dies
**Uses bones mod if present, otherwise items are dropped around the player when false.**
armor_drop = true
### Destroy armor when a player dies
**overrides armor_drop.**
armor_destroy = false
### Armor level multiplyer
**Increase to make armor more effective and decrease to make armor less effective**
**eg: level_multiplier = 0.5 will reduce armor level by half.**
armor_level_multiplier = 1
### Armor healing multiplyer
**Increase to make armor healing more effective and decrease to make healing less effective**
**eg: armor_heal_multiplier = 0 will disable healing altogether.**
armor_heal_multiplier = 1
### Enable water protection
**periodically restores breath when activated**
armor_water_protect = true
### Enable fire protection
**defaults to true if using ethereal mod**
armor_fire_protect = false
### Fire protection enabled, disable torch fire damage
**when fire protection is enabled allows you to disable fire damage from torches**
**defaults to true if using ethereal mod**
armor_fire_protect_torch = false
### Enable punch damage effects
armor_punch_damage = true
### Migration of old armor inventories
armor_migrate_old_inventory = true
### How often player wield items are updated
**Number represents how often per second update is performed, higher value means less performance hit for servers but wield items maybe delayed in updating when switching. Fractional seconds also supported eg 0.1**
***Note this is MT engine functionality but included for completness***
wieldview_update_time = 1
# API
## 3d_Armor item storage
3d_Armor stores each armor piece a player currently has equiped in a ***detached*** inventory. The easiest way to access this inventory if needed is using this line of code
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
**Example**
armor:register_on_equip(function(player, index, stack)
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
for i = 1, 6 do
local stack = armor_inv:get_stack("armor", i)
if stack:get_name() == "3d_armor:chestplate_gold" then
minetest.chat_send_player(player:get_player_name(),"Got to love the Bling!!!")
end
end
end)
## Armor Registration
armor:register_armor(name, def)
Wrapper function for `minetest.register_tool`, which enables the easy registration of new armor items. While registering armor as a tool item is still supported, this may be deprecated in future so all armor items should be registered using *armor:register_armor(name,def)*.
### Additional fields supported by 3d_armor
texture = <filename>
preview = <filename>
armor_groups = <table>
damage_groups = <table>
reciprocate_damage = <bool>
on_equip = <function>
on_unequip = <function>
on_destroy = <function>
on_damage = <function>
on_punched = <function>
***Reciprocal tool*** damage will apply damage back onto the attacking tool/weapon, however this will only be done by the first armor inventory item with `reciprocate_damage = true`, damage does not stack.
**Example Simple:**
armor:register_armor("mod_name:chestplate_leather", {
description = "Leather Chestplate",
inventory_image = "mod_name_inv_chestplate_leather.png",
texture = "mod_name_leather_chestplate.png",
preview = "mod_name_leather_chestplate_preview.png",
groups = {armor_torso=1, armor_heal=0, armor_use=2000, flammable=1},
armor_groups = {fleshy=10},
damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}
})
*See ***armor.lua*** under **3d_armor>>3d_armor** for further examples*
**Extended functionality**
The values for ***texture*** and ***preview*** do not need to be included when registering armor if they follow the naming convention in the textures mod folder of:
***texture:*** *mod_name_leather_chestplate.png*
***preview:*** *mod_name_leather_chestplate_preview.png*
## Registering Armor Groups
3d armor has a built in armor group which is ***fleshy*** all players base vulnerability to being fleshy is ***100***.
3d armour allows for the easy registration/addition of new armor groups::
armor:register_armor_group(group, base)
***group:*** Is the name of the new armor group
***base*** Is the starting vulnerability that all players have to that new group. This dosent need to be 100.
**Example**
armor:register_armor_group("radiation", 100)
New armor group is registered called *radiation* and all players start off with a base vulnerability of *100* to radiation.
**Example** *Showing armor reg, new group usage and custom function*
armor:register_armor("mod_name:speed_boots", {
description = "Speed Boots",
inventory_image = "mod_name_speed_boots_inv.png",
texture = "mod_name_speed_boots.png",
preview = "mod_name_speed_boots_preview.png",
groups = {armor_feet=1, armor_use=500, physics_speed=1.2, flammable=1},
armor_groups = {fleshy=10, radiation=10},
damage_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1},
reciprocate_damage = true,
on_destroy = function(player, index, stack)
local pos = player:get_pos()
if pos then
minetest.sound_play({
name = "mod_name_break_sound",
pos = pos,
gain = 0.5,
})
end
end,
})
### Tools/weapons and new armor groups
The above allows armor to block/prevent new damage types but you also need to assign the new damage group to a tool/weapon or even a node (see technic mod) to make wearing the armor item meaningful. Simply add the ***armor_groups*** name to the tool items ***damage_groups***.
**Example**
minetest.register_tool("mod_name:glowing_sword", {
description = "Glowing Sword",
inventory_image = "mod_name_tool_glowingsword.png",
tool_capabilities = {full_punch_interval = 1.2,max_drop_level=0,
groupcaps={
cracky = {times={[3]=1.60}, uses=10, maxlevel=1},},
damage_groups = {fleshy=10,radiation=20},
},
sound = {breaks = "default_tool_breaks"},
groups = {pickaxe = 1, flammable = 2}
})
## Groups used by 3d_Armor
3d_armor has many default groups already registered, these are categorized under 4 main headings
- **Elements:** armor_head, armor_torso, armor_legs, armor_feet
- **Attributes:** armor_heal, armor_fire, armor_water
- **Physics:** physics_jump, physics_speed, physics_gravity
- **Durability:** armor_use, flammable
***Note: for calculation purposes "Attributes" and "Physics" values stack***
### Elements
Additional armor elements can be added by dependant mods, for example shields adds the group armor_shield which has by default a limit that only 1 shield can be worn at a time.
Adding Elements is more complex but the below code can be used to add new elements;
if minetest.global_exists("armor") and armor.elements then
table.insert(armor.elements, "hands")
local mult = armor.config.level_multiplier or 1
armor.config.level_multiplier = mult * 0.5
end
**1st line** not strictly needed but checks that the global table "armor" and subtable "elements" exists
**2nd line** adds a new value to the armor.elements table called "hands"
**3rd line** in this case will be set to one ***note: need more detail here***
**4th line** simply sets the multiplier, by setting 0.5 smaller armor becomes less effective and larger more effective. good values are between 0.1 and 1 in increments of 0.1.
See ***init.lua*** under **3d_armor>>shields** for a further example
The new armor item can now be registered using the new element
**Example**
armor:register_armor("mod_name:gloves_wood", {
description = "Wood Gauntlets",
inventory_image = "mod_name_inv_gloves_wood.png",
texture = "mod_name_gloves_wood.png",
preview = "mod_name_gloves_wood_preview.png",
groups = {armor_hands=1, armor_heal=0, armor_use=2000, flammable=1},
armor_groups = {fleshy=5},
damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1},
})
### Attributes
Three attributes are avaliable in 3d_armor these are armor_heal, armor_fire and armor_water. Although possible to add additional attributes they would do nothing as code needs to be provide to specifiy the behaviour this could be done in a dependant mod
#### Armor_heal
This isn't how much the armor will heal but relates to the chance the armor will completely block the damage. For each point of ***armor_heal*** there is a 1% chance that damage will be completely blocked, this value will stack between all armor pieces
**Example**
The below Diamond chestplate has a 12% chance to completely block all damage (armor_heal=12), however so do boots, helmet and trousers so if the player was wearing all 4 pieces they would have a 48% chance of blocking all damage each attack.
armor:register_armor("3d_armor:chestplate_diamond", {
description = S("Diamond Chestplate"),
inventory_image = "3d_armor_inv_chestplate_diamond.png",
groups = {armor_torso=1, armor_heal=12, armor_use=200},
armor_groups = {fleshy=20},
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
})
#### Armor_fire
***"Armor_fire"*** provides 5 levels of fire protection
- level 1 protects against torches
- level 2 protects against crystal spike (Ethereal mod)
- level 3 protects against fire
- level 4 unused
- level 5 protects against lava
**Example**
armor:register_armor("mod_name:fire_proof_jacket", {
description = "Fire Proof Jacket",
inventory_image = "mod_name_inv_fire_proof_jacket.png",
groups = {armor_torso=1, armor_fire=3, armor_use=1000},
armor_groups = {fleshy=10},
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
})
#### Armor_water
***"Armor_water"*** will periodically restore a players breath when underwater. This only has one level or state, which is armor_water=1
**Example**
armor:register_armor("mod_name:helmet_underwater_breath", {
description = "Helmet of Underwater Breathing",
inventory_image = "mod_name_inv_helmet_underwater_breath.png",
groups = {armor_head=1, armor_water=1, armor_use=1000},
armor_groups = {fleshy=5},
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
})
### Physics
The physics attributes supported by 3d_armor are ***physics_jump, physics_speed and physics_gravity***. Although 3d_armor supports the use of this with no other mods it is recommended that the mod [player_monoids](https://forum.minetest.net/viewtopic.php?t=14895) is used to help with intermod compatability.
***physics_jump*** - Will increase/decrease the jump strength of the player so they can jump more/less. The base number is "1" and any value is added or subtracted, supports fractional so "physics_jump=1" will increase jump strength by 100%. "physics_jump= -0.5" will decrease jump by 50%.
***physics_speed*** - Will increase/decrease the walk speed of the player so they walk faster/slower. The base number is "1" and any value is added or subtracted, supports fractional so "physics_speed=1.5" will increase speed by 150%, "physics_speed= -0.5" will decrease speed by 50%.
***physics_gravity*** - Will increase/decrease gravity the player experiences so it's higher/lower. The base number is "1" and any value is added or subtracted, supports fractional so "physics_gravity=2" will increase gravity by 200%, "physics_gravity= -1" will decrease gravity by 100%.
*Note: The player physics modifications won't be applied via `set_physics_override` if `player_physics_locked` is set to 1 in the respective player's meta.*
### Durability
Durability is determined by the value assigned to the group ***armor_use***. The higher the ***armor_use*** value the faster/more quickly it is damaged/degrades. This is calculated using the formula:
Total uses = approx(65535/armor_use)
**Example**
All wood armor items have an ***armor_use=2000***;
65535/2000 = 32.76 (32)
After 32 uses(hits) the armor item will break.
All diamond armor items have an ***armor_use=200***;
65535/2000 = 327.6 (327)
After 327 uses(hits) the armor item will break.
## Armor Functions
### armor set_player_armor
armor:set_player_armor(player)
Primarily an internal function but can be called externally to apply any
changes that might not otherwise get handled.
### armor punch
armor:punch(player, hitter, time_from_last_punch, tool_capabilities)
Used to apply damage to all equipped armor based on the damage groups of
each individual item.`hitter`, `time_from_last_punch` and `tool_capabilities`
are optional but should be valid if included.
### armor damage
armor:damage(player, index, stack, use)
Adds wear to a single armor itemstack, triggers `on_damage` callbacks and
updates the necessary inventories. Also handles item destruction callbacks
and so should NOT be called from `on_unequip` to avoid an infinite loop.
### armor remove_all
armor:remove_all(player)
Removes all armors from the player's inventory without triggering any callback.
### armor equip
armor:equip(player, armor_name)
Equip the armor, removing the itemstack from the main inventory if there's one.
### armor unequip
armor:unequip(player, armor_name)
Unequip the armor, adding the itemstack to the main inventory.
### armor update_skin
armor:update_skin(player_name)
Triggers a skin update with the same action as if a field with `skins_set` was submitted.
## Callbacks
### Item Callbacks
In all of the below when armor is destroyed `stack` will contain a copy of the previous stack.
*unsure what this note means may apply to all item callbacks or just on_punched*
Return `false` to override armor damage effects.
#### on_equip
on_equip = func(player, index, stack)
#### on_unequip
on_unequip = func(player, index, stack)
#### on_destroy
on_destroy = func(player, index, stack)
#### on_damage
on_damage = func(player, index, stack)
#### on_punched
on_punched = func(player, hitter, time_from_last_punch, tool_capabilities)
`on_punched` is called every time a player is punched or takes damage, `hitter`, `time_from_last_punch` and `tool_capabilities` can be `nil` and will be in the case of fall damage.
When fire protection is enabled, hitter == "fire" in the event of fire damage.
### Global Callbacks
#### armor register_on_update
armor:register_on_update(function(player))
#### armor register_on_equip
armor:register_on_equip(function(player, index, stack))
#### armor register_on_unequip
armor:register_on_unequip(function(player, index, stack))
#### armor register_on_destroy
armor:register_on_destroy(function(player, index, stack))
**Example**
armor:register_on_update(function(player)
print(player:get_player_name().." armor updated!")
end)
# Credits
### The below have added too, tested or in other ways contributed to the development and ongoing support of 3d_Armor
|Stu |Stujones11 |Stu |Github Ghosts |
|:---------------:|:---------------:|:---------------:|:---------------:|
|Pavel_S |BlockMen |Tenplus1 |donat-b |
|JPRuehmann |BrandonReese |Megaf |Zeg9 |
|poet.nohit |Echoes91 |Adimgar |Khonkhortisan |
|VanessaE |CraigyDavi |proller |Thomasrudin |
|Byakuren |kilbith (jp) |afflatus |G1ov4 |
|Thomas-S |Dragonop |Napiophelios |Emojigit |
|rubenwardy |daviddoesminetest|bell07 |OgelGames |
|tobyplowy |crazyginger72 |fireglow |bhree |
|Lone_Wolf(HT) |Wuzzy(2) |numberZero |Monte48 |
|AntumDeluge |Terumoc |runsy |Dacmot |
|codexp |davidthecreator |SmallJoker |orbea |
|BuckarooBanzay |daret |Exeterdad |Calinou |
|Pilcrow182 |indriApollo |HybridDog |CraigyDavi |
|Paly-2 |Diogogomes | | |
*Note: Names gathered from 3d_armor forum thread and github, I may have missed some people, apologises if I have - S01*

View file

@ -1,212 +0,0 @@
[mod] Visible Player Armor [3d_armor]
=====================================
Depends: default
Recommends: sfinv, unified_inventory or smart_inventory (use only one to avoid conflicts)
Supports: player_monoids and armor_monoid
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.
Armor Configuration
-------------------
Override the following default settings by adding them to your minetest.conf file.
-- Set false to disable individual armor materials.
armor_material_wood = true
armor_material_cactus = true
armor_material_steel = true
armor_material_bronze = true
armor_material_diamond = true
armor_material_gold = true
armor_material_mithril = true
armor_material_crystal = true
-- Increase this if you get initialization glitches when a player first joins.
armor_init_delay = 2
-- Number of initialization attempts.
-- Use in conjunction with armor_init_delay if initialization problems persist.
armor_init_times = 10
-- Increase this if armor is not getting into bones due to server lag.
armor_bones_delay = 1
-- How often player armor 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: 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
-- Enable water protection (periodically restores breath when activated)
armor_water_protect = true
-- Enable fire protection (defaults true if using ethereal mod)
armor_fire_protect = false
-- Enable punch damage effects.
armor_punch_damage = true
-- Enable migration of old armor inventories
armor_migrate_old_inventory = true
API
---
Armor Registration:
armor:register_armor(name, def)
Wrapper function for `minetest.register_tool`, while registering armor as
a tool item is still supported, this may be deprecated in future so new code
should use this method.
Additional fields supported by 3d_armor:
texture = <filename>
preview = <filename>
armor_groups = <table>
damage_groups = <table>
reciprocate_damage = <bool>
on_equip = <function>
on_unequip = <function>
on_destroy = <function>
on_damage = <function>
on_punched = <function>
armor:register_armor_group(group, base)
Example:
armor:register_armor_group("radiation", 100)
armor:register_armor("mod_name:speed_boots", {
description = "Speed Boots",
inventory_image = "mod_name_speed_boots_inv.png",
texture = "mod_name_speed_boots.png",
preview = "mod_name_speed_boots_preview.png",
groups = {armor_feet=1, armor_use=500, physics_speed=1.2, flammable=1},
armor_groups = {fleshy=10, radiation=10},
damage_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1},
reciprocate_damage = true,
on_destroy = function(player, index, stack)
local pos = player:get_pos()
if pos then
minetest.sound_play({
name = "mod_name_break_sound",
pos = pos,
gain = 0.5,
})
end
end,
})
See armor.lua, technic_armor and shields mods for more examples.
Default groups:
Elements: armor_head, armor_torso, armor_legs, armor_feet
Attributes: armor_heal, armor_fire, armor_water
Physics: physics_jump, physics_speed, physics_gravity
Durability: armor_use, flammable
Notes:
Elements may be modified by dependent mods, eg shields adds armor_shield.
Attributes and physics values are 'stackable', durability is determined
by the level of armor_use, total uses == approx (65535/armor_use), non-fleshy
damage groups need to be defined in the tool/weapon used against the player.
Reciprocal tool damage will be done only by the first armor inventory item
with `reciprocate_damage = true`
Armor Functions:
armor:set_player_armor(player)
Primarily an internal function but can be called externally to apply any
changes that might not otherwise get handled.
armor:punch(player, hitter, time_from_last_punch, tool_capabilities)
Used to apply damage to all equipped armor based on the damage groups of
each individual item.`hitter`, `time_from_last_punch` and `tool_capabilities`
are optional but should be valid if included.
armor:damage(player, index, stack, use)
Adds wear to a single armor itemstack, triggers `on_damage` callbacks and
updates the necessary inventories. Also handles item destruction callbacks
and so should NOT be called from `on_unequip` to avoid an infinite loop.
armor:remove_all(player)
Removes all armors from the player's inventory without triggering any callback.
armor:equip(player, armor_name)
Equip the armor, removing the itemstack from the main inventory if there's one.
armor:unequip(player, armor_name)
Unequip the armor, adding the itemstack to the main inventory.
armor:update_skin(player_name)
Triggers a skin update with the same action as if a field with `skins_set` was submitted.
Item Callbacks:
on_equip = func(player, index, stack)
on_unequip = func(player, index, stack)
on_destroy = func(player, index, stack)
on_damage = func(player, index, stack)
on_punched = func(player, hitter, time_from_last_punch, tool_capabilities)
Notes:
`on_punched` is called every time a player is punched or takes damage, `hitter`,
`time_from_last_punch` and `tool_capabilities` can be `nil` and will be in the
case of fall damage, etc. When fire protection is enabled, hitter == "fire"
in the event of fire damage. Return `false` to override armor damage effects.
When armor is destroyed `stack` will contain a copy of the previous stack.
Global Callbacks:
armor:register_on_update(func(player))
armor:register_on_equip(func(player, index, stack))
armor:register_on_unequip(func(player, index, stack))
armor:register_on_destroy(func(player, index, stack))
Global Callback Example:
armor:register_on_update(function(player)
print(player:get_player_name().." armor updated!")
end)
Note:
The player physics modifications won't be applied via `set_physics_override` if `player_physics_locked` is set to 1
in the respective player's meta.

View file

@ -97,6 +97,7 @@ armor.config = {
material_crystal = true, material_crystal = true,
water_protect = true, water_protect = true,
fire_protect = minetest.get_modpath("ethereal") ~= nil, fire_protect = minetest.get_modpath("ethereal") ~= nil,
fire_protect_torch = minetest.get_modpath("ethereal") ~= nil,
punch_damage = true, punch_damage = true,
} }
@ -356,6 +357,9 @@ armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabili
local groupcaps = tool_capabilities.groupcaps or {} local groupcaps = tool_capabilities.groupcaps or {}
local uses = 0 local uses = 0
damage = false damage = false
if next(groupcaps) == nil then
damage = true
end
for group, caps in pairs(groupcaps) do for group, caps in pairs(groupcaps) do
local maxlevel = caps.maxlevel or 0 local maxlevel = caps.maxlevel or 0
local diff = maxlevel - level local diff = maxlevel - level

View file

@ -62,6 +62,17 @@ for material, _ in pairs(armor.materials) do
end end
end end
-- Remove torch damage if fire_protect_torch == false
if armor.config.fire_protect_torch == false and armor.config.fire_protect == true then
for k,v in pairs(armor.fire_nodes) do
for k2,v2 in pairs(v) do
if string.find (v2,"torch") then
armor.fire_nodes[k] = nil
end
end
end
end
-- Mod Compatibility -- Mod Compatibility
if minetest.get_modpath("technic") then if minetest.get_modpath("technic") then

View file

@ -1,5 +1,7 @@
Modpack - 3d Armor [0.4.13] Modpack - 3d Armor [0.4.13]
=========================== ===========================
![3d_armor screenshot](https://github.com/minetest-mods/3d_armor/blob/master/screenshot.png)
![](https://github.com/minetest-mods/3d_armor/workflows/luacheck/badge.svg) ![](https://github.com/minetest-mods/3d_armor/workflows/luacheck/badge.svg)
![](https://github.com/minetest-mods/3d_armor/workflows/integration-test/badge.svg) ![](https://github.com/minetest-mods/3d_armor/workflows/integration-test/badge.svg)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

View file

@ -44,6 +44,9 @@ armor_water_protect (Enable water protection) bool true
# Enable fire protection (defaults true if using ethereal mod). # Enable fire protection (defaults true if using ethereal mod).
armor_fire_protect (Enable fire protection) bool false armor_fire_protect (Enable fire protection) bool false
# Enable fire damage from torches (defaults true if using ethereal mod).
armor_fire_protect_torch (Enable fire protection torch damage) bool false
# Enable punch damage effects. # Enable punch damage effects.
armor_punch_damage (Enable damage effects) bool true armor_punch_damage (Enable damage effects) bool true

View file

@ -80,6 +80,9 @@ if minetest.global_exists("unified_inventory") then -- unified inventory install
unified_inventory.register_button("worldedit_gui", { unified_inventory.register_button("worldedit_gui", {
type = "image", type = "image",
image = "inventory_plus_worldedit_gui.png", image = "inventory_plus_worldedit_gui.png",
condition = function(player)
return minetest.check_player_privs(player:get_player_name(), {worldedit=true})
end,
}) })
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)

View file

@ -307,7 +307,7 @@ advtrains.ap.t_90plusx_crossing={
trackworker = "60r", trackworker = "60r",
}, },
["60r"]={ ["60r"]={
conns = { {c=0}, {c=8}, {c=7}, {c=15} }, conns = { {c=0}, {c=8}, {c=7}, {c=13} },
desc = "60/90 degree crossing (right)", desc = "60/90 degree crossing (right)",
tpdouble = true, tpdouble = true,
tpsingle = true, tpsingle = true,

View file

@ -181,7 +181,7 @@ local function check_sapling(pos, nodename)
if can_grow then if can_grow then
particle_effect(pos) particle_effect(pos)
grow_tree(pos, saplings[n][2]) grow_tree(pos, saplings[n][2])
return return true
end end
end end
end end
@ -216,7 +216,7 @@ local function check_crops(pos, nodename, strength)
particle_effect(pos) particle_effect(pos)
return return true
end end
end end
end end
@ -438,13 +438,13 @@ function bonemeal:on_use(pos, strength, node)
default.grow_papyrus(pos, node) default.grow_papyrus(pos, node)
particle_effect(pos) particle_effect(pos)
return return true
elseif node.name == "default:cactus" then elseif node.name == "default:cactus" then
default.grow_cactus(pos, node) default.grow_cactus(pos, node)
particle_effect(pos) particle_effect(pos)
return return true
end end
-- grow grass and flowers -- grow grass and flowers
@ -452,7 +452,7 @@ function bonemeal:on_use(pos, strength, node)
or minetest.get_item_group(node.name, "sand") > 0 or minetest.get_item_group(node.name, "sand") > 0
or minetest.get_item_group(node.name, "can_bonemeal") > 0 then or minetest.get_item_group(node.name, "can_bonemeal") > 0 then
check_soil(pos, node.name, strength) check_soil(pos, node.name, strength)
return return true
end end
-- light check depending on strength (strength of 4 = no light needed) -- light check depending on strength (strength of 4 = no light needed)
@ -464,11 +464,13 @@ function bonemeal:on_use(pos, strength, node)
if minetest.get_item_group(node.name, "sapling") > 0 if minetest.get_item_group(node.name, "sapling") > 0
and random(5 - strength) == 1 then and random(5 - strength) == 1 then
check_sapling(pos, node.name) check_sapling(pos, node.name)
return return true
end end
-- check for crop growth -- check for crop growth
check_crops(pos, node.name, strength) if check_crops(pos, node.name, strength) then
return true
end
end end
@ -494,13 +496,14 @@ minetest.register_craftitem("bonemeal:mulch", {
return return
end end
-- call global on_use function with strength of 1
if bonemeal:on_use(pointed_thing.under, 1) then
-- take item if not in creative -- take item if not in creative
if not bonemeal.is_creative(user:get_player_name()) then if not bonemeal.is_creative(user:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
end
-- call global on_use function with strength of 1
bonemeal:on_use(pointed_thing.under, 1)
return itemstack return itemstack
end end
@ -524,13 +527,14 @@ minetest.register_craftitem("bonemeal:bonemeal", {
return return
end end
-- call global on_use function with strength of 2
if bonemeal:on_use(pointed_thing.under, 2) then
-- take item if not in creative -- take item if not in creative
if not bonemeal.is_creative(user:get_player_name()) then if not bonemeal.is_creative(user:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
end
-- call global on_use function with strength of 2
bonemeal:on_use(pointed_thing.under, 2)
return itemstack return itemstack
end end
@ -554,13 +558,14 @@ minetest.register_craftitem("bonemeal:fertiliser", {
return return
end end
-- call global on_use function with strength of 3
if bonemeal:on_use(pointed_thing.under, 3) then
-- take item if not in creative -- take item if not in creative
if not bonemeal.is_creative(user:get_player_name()) then if not bonemeal.is_creative(user:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
end
-- call global on_use function with strength of 3
bonemeal:on_use(pointed_thing.under, 3)
return itemstack return itemstack
end end

View file

@ -32,7 +32,7 @@ if farming and farming.mod and farming.mod == "redo" then
{"farming:chili_", 8}, {"farming:chili_", 8},
{"farming:garlic_", 5}, {"farming:garlic_", 5},
{"farming:onion_", 5}, {"farming:onion_", 5},
{"farming:pepper_", 5}, {"farming:pepper_", 7},
{"farming:pineapple_", 8}, {"farming:pineapple_", 8},
{"farming:pea_", 5}, {"farming:pea_", 5},
{"farming:beetroot_", 5}, {"farming:beetroot_", 5},
@ -40,7 +40,11 @@ if farming and farming.mod and farming.mod == "redo" then
{"farming:oat_", 8}, {"farming:oat_", 8},
{"farming:rice_", 8}, {"farming:rice_", 8},
{"farming:mint_", 4}, {"farming:mint_", 4},
{"farming:cabbage_", 6} {"farming:cabbage_", 6},
{"farming:lettuce_", 5},
{"farming:blackberry_", 4},
{"farming:vanilla_", 8},
{"farming:soy_", 7}
}) })
end end
@ -65,7 +69,9 @@ if minetest.get_modpath("ethereal") then
{"ethereal:orange_tree_sapling", ethereal.grow_orange_tree, "soil"}, {"ethereal:orange_tree_sapling", ethereal.grow_orange_tree, "soil"},
{"ethereal:bamboo_sprout", ethereal.grow_bamboo_tree, "soil"}, {"ethereal:bamboo_sprout", ethereal.grow_bamboo_tree, "soil"},
{"ethereal:birch_sapling", ethereal.grow_birch_tree, "soil"}, {"ethereal:birch_sapling", ethereal.grow_birch_tree, "soil"},
{"ethereal:sakura_sapling", ethereal.grow_sakura_tree, "soil"} {"ethereal:sakura_sapling", ethereal.grow_sakura_tree, "soil"},
{"ethereal:lemon_tree_sapling", ethereal.grow_lemon_tree, "soil"},
{"ethereal:olive_tree_sapling", ethereal.grow_olive_tree, "soil"}
}) })
local grass = {"default:grass_3", "default:grass_4", "default:grass_5", ""} local grass = {"default:grass_3", "default:grass_4", "default:grass_5", ""}

View file

@ -13,6 +13,7 @@ This mod works by adding your new plant to the {growing=1} group and numbering t
### Changelog: ### Changelog:
- 1.46 - Added min/max default light settings, added lettuce and blackberries with food items (thanks OgelGames), added soya and vanilla (thanks Felfa), added tofu
- 1.45 - Dirt and Hoes are more in line with default by using dry/wet/base, added cactus juice, added pasta, spaghetti, cabbage, korean bibimbap, code tidy - 1.45 - Dirt and Hoes are more in line with default by using dry/wet/base, added cactus juice, added pasta, spaghetti, cabbage, korean bibimbap, code tidy
options, onion soup added (thanks edcrypt), Added apple pie, added wild cotton to savanna options, onion soup added (thanks edcrypt), Added apple pie, added wild cotton to savanna
- 1.44 - Added 'farming_stage_length' in mod settings for speed of crop growth, also thanks to TheDarkTiger for translation updates - 1.44 - Added 'farming_stage_length' in mod settings for speed of crop growth, also thanks to TheDarkTiger for translation updates

View file

@ -108,8 +108,8 @@ minetest.register_node("farming:barley_7", table.copy(def))
farming.registered_plants["farming:barley"] = { farming.registered_plants["farming:barley"] = {
crop = "farming:barley", crop = "farming:barley",
seed = "farming:seed_barley", seed = "farming:seed_barley",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 7 steps = 7
} }

View file

@ -226,8 +226,8 @@ minetest.register_node("farming:beanpole_5", table.copy(def))
farming.registered_plants["farming:beans"] = { farming.registered_plants["farming:beans"] = {
crop = "farming:beanpole", crop = "farming:beanpole",
seed = "farming:beans", seed = "farming:beans",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -86,7 +86,7 @@ minetest.register_node("farming:beetroot_5", table.copy(def))
farming.registered_plants["farming:beetroot"] = { farming.registered_plants["farming:beetroot"] = {
crop = "farming:beetroot", crop = "farming:beetroot",
seed = "farming:beetroot", seed = "farming:beetroot",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -0,0 +1,62 @@
local S = farming.intllib
-- blackberries
minetest.register_craftitem("farming:blackberry", {
description = S("Blackberries"),
inventory_image = "farming_blackberry.png",
groups = {seed = 2, food_blackberries = 1, food_blackberry = 1,
food_berry = 1, flammable = 2},
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:blackberry_1")
end,
on_use = minetest.item_eat(1),
})
local def = {
drawtype = "plantlike",
tiles = {"farming_blackberry_1.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults()
}
-- stage 1
minetest.register_node("farming:blackberry_1", table.copy(def))
-- stage 2
def.tiles = {"farming_blackberry_2.png"}
minetest.register_node("farming:blackberry_2", table.copy(def))
-- stage 3
def.tiles = {"farming_blackberry_3.png"}
minetest.register_node("farming:blackberry_3", table.copy(def))
-- stage 4
def.tiles = {"farming_blackberry_4.png"}
def.groups.growing = nil
def.drop = {
items = {
{items = {'farming:blackberry 2'}, rarity = 1},
{items = {'farming:blackberry'}, rarity = 2},
{items = {'farming:blackberry'}, rarity = 3},
}
}
minetest.register_node("farming:blackberry_4", table.copy(def))
-- add to registered_plants
farming.registered_plants["farming:blackberry"] = {
crop = "farming:blackberry",
seed = "farming:blackberry",
minlight = farming.min_light,
maxlight = farming.max_light,
steps = 4
}

View file

@ -88,7 +88,7 @@ minetest.register_node("farming:blueberry_4", table.copy(def))
farming.registered_plants["farming:blueberries"] = { farming.registered_plants["farming:blueberries"] = {
crop = "farming:blueberry", crop = "farming:blueberry",
seed = "farming:blueberries", seed = "farming:blueberries",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -53,8 +53,8 @@ def.tiles = {"farming_cabbage_6.png"}
def.groups.growing = nil def.groups.growing = nil
def.drop = { def.drop = {
max_items = 2, items = { max_items = 2, items = {
{items = {"farming:cabbage"}, rarity = 1}, {items = {"farming:cabbage 2"}, rarity = 1},
{items = {"farming:cabbage"}, rarity = 2} {items = {"farming:cabbage 1"}, rarity = 2}
} }
} }
minetest.register_node("farming:cabbage_6", table.copy(def)) minetest.register_node("farming:cabbage_6", table.copy(def))
@ -63,7 +63,7 @@ minetest.register_node("farming:cabbage_6", table.copy(def))
farming.registered_plants["farming:cabbage"] = { farming.registered_plants["farming:cabbage"] = {
crop = "farming:cabbage", crop = "farming:cabbage",
seed = "farming:cabbage", seed = "farming:cabbage",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 6 steps = 6
} }

View file

@ -118,7 +118,7 @@ minetest.register_node("farming:carrot_8", table.copy(def))
farming.registered_plants["farming:carrot"] = { farming.registered_plants["farming:carrot"] = {
crop = "farming:carrot", crop = "farming:carrot",
seed = "farming:carrot", seed = "farming:carrot",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -95,7 +95,7 @@ minetest.register_node("farming:chili_8", table.copy(def))
farming.registered_plants["farming:chili_pepper"] = { farming.registered_plants["farming:chili_pepper"] = {
crop = "farming:chili", crop = "farming:chili",
seed = "farming:chili_pepper", seed = "farming:chili_pepper",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -194,8 +194,8 @@ minetest.register_node("farming:cocoa_4", table.copy(def))
farming.registered_plants["farming:cocoa_beans"] = { farming.registered_plants["farming:cocoa_beans"] = {
crop = "farming:cocoa", crop = "farming:cocoa",
seed = "farming:cocoa_beans", seed = "farming:cocoa_beans",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -106,7 +106,7 @@ minetest.register_node("farming:coffee_5", table.copy(def))
farming.registered_plants["farming:coffee"] = { farming.registered_plants["farming:coffee"] = {
crop = "farming:coffee", crop = "farming:coffee",
seed = "farming:coffee_beans", seed = "farming:coffee_beans",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -153,7 +153,7 @@ minetest.register_node("farming:corn_8", table.copy(def))
farming.registered_plants["farming:corn"] = { farming.registered_plants["farming:corn"] = {
crop = "farming:corn", crop = "farming:corn",
seed = "farming:corn", seed = "farming:corn",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -172,8 +172,8 @@ minetest.register_node("farming:cotton_8", table.copy(def))
farming.registered_plants["farming:cotton"] = { farming.registered_plants["farming:cotton"] = {
crop = "farming:cotton", crop = "farming:cotton",
seed = "farming:seed_cotton", seed = "farming:seed_cotton",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -59,7 +59,7 @@ minetest.register_node("farming:cucumber_4", table.copy(def))
farming.registered_plants["farming:cucumber"] = { farming.registered_plants["farming:cucumber"] = {
crop = "farming:cucumber", crop = "farming:cucumber",
seed = "farming:cucumber", seed = "farming:cucumber",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -129,7 +129,7 @@ minetest.register_node("farming:garlic_5", table.copy(def))
farming.registered_plants["farming:garlic"] = { farming.registered_plants["farming:garlic"] = {
crop = "farming:garlic", crop = "farming:garlic",
seed = "farming:garlic_clove", seed = "farming:garlic_clove",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -233,8 +233,8 @@ minetest.register_node("farming:grapes_8", table.copy(def))
farming.registered_plants["farming:grapes"] = { farming.registered_plants["farming:grapes"] = {
crop = "farming:grapes", crop = "farming:grapes",
seed = "farming:grapes", seed = "farming:grapes",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -256,7 +256,7 @@ minetest.register_node("farming:hemp_8", table.copy(def))
farming.registered_plants["farming:hemp"] = { farming.registered_plants["farming:hemp"] = {
crop = "farming:hemp", crop = "farming:hemp",
seed = "farming:seed_hemp", seed = "farming:seed_hemp",
minlight = 13, mminlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -0,0 +1,63 @@
local S = farming.intllib
-- lettuce
minetest.register_craftitem("farming:lettuce", {
description = S("Lettuce"),
inventory_image = "farming_lettuce.png",
groups = {seed = 2, food_lettuce = 1, flammable = 2},
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:lettuce_1")
end,
on_use = minetest.item_eat(2),
})
local def = {
drawtype = "plantlike",
tiles = {"farming_lettuce_1.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults()
}
-- stage 1
minetest.register_node("farming:lettuce_1", table.copy(def))
-- stage 2
def.tiles = {"farming_lettuce_2.png"}
minetest.register_node("farming:lettuce_2", table.copy(def))
-- stage 3
def.tiles = {"farming_lettuce_3.png"}
minetest.register_node("farming:lettuce_3", table.copy(def))
-- stage 4
def.tiles = {"farming_lettuce_4.png"}
minetest.register_node("farming:lettuce_4", table.copy(def))
-- stage 5
def.tiles = {"farming_lettuce_5.png"}
def.groups.growing = nil
def.drop = {
items = {
{items = {'farming:lettuce 2'}, rarity = 1},
{items = {'farming:lettuce 1'}, rarity = 2},
}
}
minetest.register_node("farming:lettuce_5", table.copy(def))
-- add to registered_plants
farming.registered_plants["farming:lettuce"] = {
crop = "farming:lettuce",
seed = "farming:lettuce",
minlight = farming.min_light,
maxlight = farming.max_light,
steps = 5
}

View file

@ -88,7 +88,7 @@ minetest.register_node("farming:melon_8", table.copy(def))
farming.registered_plants["farming:melon"] = { farming.registered_plants["farming:melon"] = {
crop = "farming:melon", crop = "farming:melon",
seed = "farming:melon_slice", seed = "farming:melon_slice",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -101,7 +101,7 @@ minetest.register_node("farming:mint_4", table.copy(def))
farming.registered_plants["farming:mint"] = { farming.registered_plants["farming:mint"] = {
crop = "farming:mint", crop = "farming:mint",
seed = "farming:seed_mint", seed = "farming:seed_mint",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -90,7 +90,7 @@ minetest.register_node("farming:onion_5", table.copy(def))
farming.registered_plants["farming:onion"] = { farming.registered_plants["farming:onion"] = {
crop = "farming:onion", crop = "farming:onion",
seed = "farming:onion", seed = "farming:onion",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -91,7 +91,7 @@ minetest.register_node("farming:pea_5", table.copy(def))
farming.registered_plants["farming:pea_pod"] = { farming.registered_plants["farming:pea_pod"] = {
crop = "farming:pea", crop = "farming:pea",
seed = "farming:pea_pod", seed = "farming:pea_pod",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -19,16 +19,32 @@ minetest.register_craftitem("farming:peppercorn", {
-- green pepper -- green pepper
minetest.register_craftitem("farming:pepper", { minetest.register_craftitem("farming:pepper", {
description = S("Pepper"), description = S("Green Pepper"),
inventory_image = "crops_pepper.png", inventory_image = "crops_pepper.png",
on_use = minetest.item_eat(2), on_use = minetest.item_eat(2),
groups = {food_pepper = 1, flammable = 3} groups = {food_pepper = 1, flammable = 3}
}) })
-- yellow pepper
minetest.register_craftitem("farming:pepper_yellow", {
description = S("Yellow Pepper"),
inventory_image = "crops_pepper_yellow.png",
on_use = minetest.item_eat(3),
groups = {food_pepper = 1, flammable = 3},
})
-- red pepper
minetest.register_craftitem("farming:pepper_red", {
description = S("Red Pepper"),
inventory_image = "crops_pepper_red.png",
on_use = minetest.item_eat(4),
groups = {food_pepper = 1, flammable = 3},
})
minetest.register_craft({ minetest.register_craft({
type = "shapeless", type = "shapeless",
output = "farming:peppercorn", output = "farming:peppercorn",
recipe = {"farming:pepper"} recipe = {"group:food_pepper"}
}) })
-- ground pepper -- ground pepper
@ -93,11 +109,10 @@ minetest.register_node("farming:pepper_3", table.copy(def))
def.tiles = {"crops_pepper_plant_4.png"} def.tiles = {"crops_pepper_plant_4.png"}
minetest.register_node("farming:pepper_4", table.copy(def)) minetest.register_node("farming:pepper_4", table.copy(def))
-- stage 5 -- stage 5 (green pepper)
def.tiles = {"crops_pepper_plant_5.png"} def.tiles = {"crops_pepper_plant_5.png"}
def.groups.growing = 0
def.drop = { def.drop = {
items = { max_items = 2, items = {
{items = {"farming:pepper 2"}, rarity = 1}, {items = {"farming:pepper 2"}, rarity = 1},
{items = {"farming:pepper"}, rarity = 2}, {items = {"farming:pepper"}, rarity = 2},
{items = {"farming:pepper"}, rarity = 3} {items = {"farming:pepper"}, rarity = 3}
@ -105,11 +120,34 @@ def.drop = {
} }
minetest.register_node("farming:pepper_5", table.copy(def)) minetest.register_node("farming:pepper_5", table.copy(def))
-- stage 6 (yellow pepper)
def.tiles = {"crops_pepper_plant_6.png"}
def.drop = {
max_items = 2, items = {
{items = {'farming:pepper_yellow 2'}, rarity = 1},
{items = {'farming:pepper_yellow'}, rarity = 2},
{items = {'farming:pepper_yellow'}, rarity = 3},
}
}
minetest.register_node("farming:pepper_6", table.copy(def))
-- stage 7 (red pepper)
def.tiles = {"crops_pepper_plant_7.png"}
def.groups.growing = nil
def.drop = {
max_items = 2, items = {
{items = {'farming:pepper_red 2'}, rarity = 1},
{items = {'farming:pepper_red'}, rarity = 2},
{items = {'farming:pepper_red'}, rarity = 3},
}
}
minetest.register_node("farming:pepper_7", table.copy(def))
-- add to registered_plants -- add to registered_plants
farming.registered_plants["farming:pepper"] = { farming.registered_plants["farming:pepper"] = {
crop = "farming:pepper", crop = "farming:pepper",
seed = "farming:peppercorn", seed = "farming:peppercorn",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 5 steps = 5
} }

View file

@ -135,7 +135,7 @@ minetest.register_node("farming:pineapple_8", table.copy(def))
farming.registered_plants["farming:pineapple"] = { farming.registered_plants["farming:pineapple"] = {
crop = "farming:pineapple", crop = "farming:pineapple",
seed = "farming:pineapple_top", seed = "farming:pineapple_top",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -106,7 +106,7 @@ minetest.register_node("farming:potato_4", table.copy(def))
farming.registered_plants["farming:potato"] = { farming.registered_plants["farming:potato"] = {
crop = "farming:potato", crop = "farming:potato",
seed = "farming:potato", seed = "farming:potato",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -200,7 +200,7 @@ minetest.register_alias("farming:pumpkin", "farming:pumpkin_8")
farming.registered_plants["farming:pumpkin"] = { farming.registered_plants["farming:pumpkin"] = {
crop = "farming:pumpkin", crop = "farming:pumpkin",
seed = "farming:pumpkin_slice", seed = "farming:pumpkin_slice",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -74,7 +74,7 @@ minetest.register_node("farming:raspberry_4", table.copy(def))
farming.registered_plants["farming:raspberries"] = { farming.registered_plants["farming:raspberries"] = {
crop = "farming:raspberry", crop = "farming:raspberry",
seed = "farming:raspberries", seed = "farming:raspberries",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 4 steps = 4
} }

View file

@ -71,7 +71,7 @@ minetest.register_node("farming:rhubarb_3", table.copy(def))
farming.registered_plants["farming:rhubarb"] = { farming.registered_plants["farming:rhubarb"] = {
crop = "farming:rhubarb", crop = "farming:rhubarb",
seed = "farming:rhubarb", seed = "farming:rhubarb",
minlight = 13, minlight = 10,
maxlight = 15, maxlight = 12,
steps = 3 steps = 3
} }

171
mods/farming/crops/soy.lua Normal file
View file

@ -0,0 +1,171 @@
local S = farming.intllib
-- soy pod
minetest.register_craftitem("farming:soy_pod", {
description = S("Soy Pod"),
inventory_image = "farming_soy_pod.png",
groups = {seed = 2, food_soy_pod = 1, flammable = 2},
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:soy_1")
end
})
minetest.register_craftitem("farming:soy_beans", {
description = S("Soy Beans"),
inventory_image = "farming_soy_beans.png",
groups = {food_soy = 1, flammable = 2},
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "shapeless",
output = "farming:soy_beans",
recipe = {"farming:soy_pod"}
})
-- soy milk
minetest.register_node("farming:soy_milk", {
description = S("Soy Milk"),
drawtype = "plantlike",
tiles = {"farming_soy_milk_glass.png"},
inventory_image = "farming_soy_milk_glass.png",
wield_image = "farming_soy_milk_glass.png",
paramtype = "light",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.5, 0.3}
},
on_use = minetest.item_eat(2, "vessels:drinking_glass"),
groups = {
vessel = 1, food_milk_glass = 1, dig_immediate = 3,
attached_node = 1, drink = 1
},
sounds = default.node_sound_glass_defaults()
})
minetest.register_craft( {
type = "shapeless",
output = "farming:soy_milk",
recipe = {
"group:food_soy", "group:food_soy", "group:food_soy",
"farming:vanilla_extract", "bucket:bucket_water", "vessels:drinking_glass"
},
replacements = {
{"bucket:bucket_water", "bucket:bucket_empty"},
{"farming:vanilla_extract", "vessels:glass_bottle"}
}
})
-- tofu
minetest.register_craftitem("farming:tofu", {
description = S("Tofu"),
inventory_image = "farming_tofu.png",
groups = {food_tofu = 1, food_meat_raw = 1, flammable = 2},
on_use = minetest.item_eat(3)
})
minetest.register_craft({
output = "farming:tofu",
type = "shapeless",
recipe = {
"farming:baking_tray", "group:food_soy", "group:food_soy",
"group:food_soy", "group:food_soy", "group:food_soy",
},
replacements = {{"farming:baking_tray", "farming:baking_tray"}}
})
-- cooked tofu
minetest.register_craftitem("farming:tofu_cooked", {
description = S("Cooked Tofu"),
inventory_image = "farming_tofu_cooked.png",
groups = {food_meat = 1, flammable = 2},
on_use = minetest.item_eat(6)
})
minetest.register_craft({
type = "cooking",
output = "farming:tofu_cooked",
recipe = "farming:tofu",
cooktime = 5
})
-- crop definition
local def = {
drawtype = "plantlike",
tiles = {"farming_soy_1.png"},
paramtype = "light",
paramtype2 = "meshoptions",
place_param2 = 3,
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults()
}
-- stage 1
minetest.register_node("farming:soy_1", table.copy(def))
-- stage 2
def.tiles = {"farming_soy_2.png"}
minetest.register_node("farming:soy_2", table.copy(def))
-- stage 3
def.tiles = {"farming_soy_3.png"}
minetest.register_node("farming:soy_3", table.copy(def))
-- stage 4
def.tiles = {"farming_soy_4.png"}
minetest.register_node("farming:soy_4", table.copy(def))
-- stage 5
def.tiles = {"farming_soy_5.png"}
def.drop = {
max_items = 1, items = {
{items = {'farming:soy_pod'}, rarity = 1},
}
}
minetest.register_node("farming:soy_5", table.copy(def))
-- stage 6
def.tiles = {"farming_soy_6.png"}
def.drop = {
max_items = 3, items = {
{items = {'farming:soy_pod'}, rarity = 1},
{items = {'farming:soy_pod'}, rarity = 2},
{items = {'farming:soy_pod'}, rarity = 3},
}
}
minetest.register_node("farming:soy_6", table.copy(def))
-- stage 7
def.tiles = {"farming_soy_7.png"}
def.groups.growing = nil
def.drop = {
max_items = 5, items = {
{items = {'farming:soy_pod'}, rarity = 1},
{items = {'farming:soy_pod'}, rarity = 2},
{items = {'farming:soy_pod'}, rarity = 3},
{items = {'farming:soy_pod'}, rarity = 4},
{items = {'farming:soy_pod'}, rarity = 5}
}
}
minetest.register_node("farming:soy_7", table.copy(def))
-- add to registered_plants
farming.registered_plants["farming:soy_pod"] = {
crop = "farming:soy",
seed = "farming:soy_pod",
minlight = farming.min_light,
maxlight = farming.max_light,
steps = 7
}

View file

@ -83,7 +83,7 @@ minetest.register_node("farming:tomato_8", table.copy(def))
farming.registered_plants["farming:tomato"] = { farming.registered_plants["farming:tomato"] = {
crop = "farming:tomato", crop = "farming:tomato",
seed = "farming:tomato", seed = "farming:tomato",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -0,0 +1,122 @@
local S = farming.intllib
-- vanilla
minetest.register_craftitem("farming:vanilla", {
description = S("Vanilla"),
inventory_image = "farming_vanilla.png",
groups = {seed = 2, food_vanilla = 1, flammable = 2},
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:vanilla_1")
end,
on_use = minetest.item_eat(1),
})
-- crop definition
local def = {
drawtype = "plantlike",
tiles = {"farming_vanilla_1.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults()
}
-- vanilla extract
minetest.register_node("farming:vanilla_extract", {
description = S("Vanilla Extract"),
drawtype = "plantlike",
tiles = {"farming_vanilla_extract.png"},
inventory_image = "farming_vanilla_extract.png",
wield_image = "farming_vanilla_extract.png",
paramtype = "light",
is_ground_content = false,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25}
},
groups = {vessel = 1, dig_immediate = 3, attached_node = 1},
sounds = default.node_sound_glass_defaults(),
})
minetest.register_craft( {
output = "farming:vanilla_extract",
recipe = {
{ "group:food_vanilla", "group:food_vanilla", "group:food_vanilla"},
{ "group:food_vanilla", "farming:bottle_ethanol", "bucket:bucket_water"},
},
replacements = {
{"bucket:bucket_water", "bucket:bucket_empty"},
}
})
minetest.register_craft({
type = "fuel",
recipe = "farming:vanilla_extract",
burntime = 25,
replacements = {{ "farming:vanilla_extract", "vessels:glass_bottle" }}
})
-- stage 1
minetest.register_node("farming:vanilla_1", table.copy(def))
-- stage 2
def.tiles = {"farming_vanilla_2.png"}
minetest.register_node("farming:vanilla_2", table.copy(def))
-- stage 3
def.tiles = {"farming_vanilla_3.png"}
minetest.register_node("farming:vanilla_3", table.copy(def))
-- stage 4
def.tiles = {"farming_vanilla_4.png"}
minetest.register_node("farming:vanilla_4", table.copy(def))
-- stage 5
def.tiles = {"farming_vanilla_5.png"}
minetest.register_node("farming:vanilla_5", table.copy(def))
-- stage 6
def.tiles = {"farming_vanilla_6.png"}
def.visual_scale = 1.9
minetest.register_node("farming:vanilla_6", table.copy(def))
-- stage 7
def.tiles = {"farming_vanilla_7.png"}
def.drop = {
items = {
{items = {'farming:vanilla'}, rarity = 1},
{items = {'farming:vanilla'}, rarity = 2},
{items = {'farming:vanilla'}, rarity = 3}
}
}
minetest.register_node("farming:vanilla_7", table.copy(def))
-- stage 8 (final)
def.tiles = {"farming_vanilla_8.png"}
def.groups.growing = nil
def.drop = {
items = {
{items = {'farming:vanilla 2'}, rarity = 1},
{items = {'farming:vanilla 2'}, rarity = 2},
{items = {'farming:vanilla 2'}, rarity = 2},
{items = {'farming:vanilla 2'}, rarity = 3}
}
}
minetest.register_node("farming:vanilla_8", table.copy(def))
-- add to registered_plants
farming.registered_plants["farming:vanilla"] = {
crop = "farming:vanilla",
seed = "farming:vanilla",
minlight = farming.min_light,
maxlight = farming.max_light,
steps = 8
}

View file

@ -234,8 +234,8 @@ minetest.register_node("farming:wheat_8", table.copy(def))
farming.registered_plants["farming:wheat"] = { farming.registered_plants["farming:wheat"] = {
crop = "farming:wheat", crop = "farming:wheat",
seed = "farming:seed_wheat", seed = "farming:seed_wheat",
minlight = 13, minlight = farming.min_light,
maxlight = 15, maxlight = farming.max_light,
steps = 8 steps = 8
} }

View file

@ -31,7 +31,15 @@ farming.peas = 0.001
farming.beetroot = 0.001 farming.beetroot = 0.001
farming.mint = 0.005 farming.mint = 0.005
farming.cabbage = 0.001 farming.cabbage = 0.001
farming.blackberry = 0.002
farming.lettuce = 0.001
farming.soy = 0.001
farming.vanilla = 0.001
farming.grains = true -- true or false only farming.grains = true -- true or false only
-- default rarety of crops on map (higher number = more crops) -- default rarety of crops on map (higher number = more crops)
farming.rarety = 0.002 farming.rarety = 0.002
-- default minimum and maximum light levels crops need to grow
farming.min_light = 12
farming.max_light = 15

View file

@ -181,44 +181,18 @@ minetest.register_craftitem("farming:porridge", {
on_use = minetest.item_eat(6, "farming:bowl") on_use = minetest.item_eat(6, "farming:bowl")
}) })
minetest.after(0, function()
local fluid = "group:water_bucket"
local fluid_return = {
{"group:water_bucket", "bucket:bucket_empty"},
{"group:water_bucket_wooden", "bucket:bucket_empty"}
}
if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" then
fluid = "group:food_milk"
fluid_return = {
{"mobs:bucket_milk", "bucket:bucket_empty"}
}
else
minetest.register_craft({ minetest.register_craft({
type = "shapeless", type = "shapeless",
output = "farming:porridge", output = "farming:porridge",
recipe = { recipe = {
"group:food_oats", "group:food_oats", "group:food_oats", "group:food_oats", "group:food_oats", "group:food_oats",
"group:food_oats", "group:food_bowl", "group:water_bucket_wooden" "group:food_oats", "group:food_bowl", "group:food_milk_glass"
}, },
replacements = fluid_return replacements = {
{"mobs:glass_milk", "vessels:drinking_glass"},
{"farming:soy_milk", "vessels:drinking_glass"}
}
}) })
end
minetest.register_craft({
type = "shapeless",
output = "farming:porridge",
recipe = {
"group:food_oats", "group:food_oats", "group:food_oats",
"group:food_oats", "group:food_bowl", fluid
},
replacements = fluid_return
})
if minetest.get_modpath("bucket_wooden") then
end
end)
--= Jaffa Cake --= Jaffa Cake
@ -373,3 +347,57 @@ minetest.register_craft({
replacements = {{"group:food_skillet", "farming:skillet"}} replacements = {{"group:food_skillet", "farming:skillet"}}
}) })
end end
-- Burger
minetest.register_craftitem("farming:burger", {
description = S("Burger"),
inventory_image = "farming_burger.png",
on_use = minetest.item_eat(16),
})
minetest.register_craft({
type = "shapeless",
output = "farming:burger",
recipe = {
"farming:bread", "group:food_meat", "group:food_cheese",
"group:food_tomato", "group:food_cucumber", "group:food_onion",
"group:food_lettuce"
}
})
-- Salad
minetest.register_craftitem("farming:salad", {
description = S("Salad"),
inventory_image = "farming_salad.png",
on_use = minetest.item_eat(8, "farming:bowl")
})
minetest.register_craft({
output = "farming:salad",
type = "shapeless",
recipe = {
"group:food_bowl", "group:food_tomato", "group:food_cucumber",
"group:food_lettuce", "group:food_oil"
},
})
-- Triple Berry Smoothie
minetest.register_craftitem("farming:smoothie_berry", {
description = S("Triple Berry Smoothie"),
inventory_image = "farming_berry_smoothie.png",
on_use = minetest.item_eat(6, "vessels:drinking_glass"),
groups = {vessel = 1, drink = 1}
})
minetest.register_craft({
output = "farming:smoothie_berry",
type = "shapeless",
recipe = {
"group:food_raspberries", "group:food_blackberries",
"group:food_strawberry", "group:food_banana",
"vessels:drinking_glass"
}
})

View file

@ -7,13 +7,15 @@
farming = { farming = {
mod = "redo", mod = "redo",
version = "20200702", version = "20201213",
path = minetest.get_modpath("farming"), path = minetest.get_modpath("farming"),
select = { select = {
type = "fixed", type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5} fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}
}, },
registered_plants = {} registered_plants = {},
min_light = 12,
max_light = 15
} }
@ -332,9 +334,8 @@ function farming.plant_growth_timer(pos, elapsed, node_name)
return true return true
end end
local MIN_LIGHT = minetest.registered_nodes[node_name].minlight or 12 local MIN_LIGHT = minetest.registered_nodes[node_name].minlight or farming.min_light
local MAX_LIGHT = minetest.registered_nodes[node_name].maxlight or 15 local MAX_LIGHT = minetest.registered_nodes[node_name].maxlight or farming.max_light
--print ("---", MIN_LIGHT, MAX_LIGHT)
if max_growth == 1 or lambda < 2.0 then if max_growth == 1 or lambda < 2.0 then
@ -628,6 +629,10 @@ farming.peas = 0.001
farming.beetroot = 0.001 farming.beetroot = 0.001
farming.mint = 0.005 farming.mint = 0.005
farming.cabbage = 0.001 farming.cabbage = 0.001
farming.blackberry = 0.002
farming.soy = 0.001
farming.vanilla = 0.001
farming.lettuce = 0.001
farming.grains = true farming.grains = true
farming.rarety = 0.002 farming.rarety = 0.002
@ -694,6 +699,10 @@ ddoo("chili.lua", farming.chili)
ddoo("ryeoatrice.lua", farming.grains) ddoo("ryeoatrice.lua", farming.grains)
ddoo("mint.lua", farming.mint) ddoo("mint.lua", farming.mint)
ddoo("cabbage.lua", farming.cabbage) ddoo("cabbage.lua", farming.cabbage)
ddoo("blackberry.lua", farming.blackberry)
ddoo("soy.lua", farming.soy)
ddoo("vanilla.lua", farming.vanilla)
ddoo("lettuce.lua", farming.lettuce)
dofile(farming.path .. "/food.lua") dofile(farming.path .. "/food.lua")
dofile(farming.path .. "/mapgen.lua") dofile(farming.path .. "/mapgen.lua")

View file

@ -128,6 +128,7 @@ Created by TenPlus1 (CC BY 3.0)
farming_rhubarb.png farming_rhubarb.png
farming_rhubarb_pie.png farming_rhubarb_pie.png
farming_hemp*.png farming_hemp*.png
farming_tofu*.png
Created by ademant (CC-BY-3.0) Created by ademant (CC-BY-3.0)
farming_rye*.png farming_rye*.png
@ -142,3 +143,15 @@ Created by VanessaE and edited by SpaghettiToastBook (CC0):
Created by mDiyo (Natura), modified by TenPlus1 (License: CC BY-SA 3.0): Created by mDiyo (Natura), modified by TenPlus1 (License: CC BY-SA 3.0):
farming_barley.png farming_barley.png
Created by OgelGames (CC BY-SA 4.0)
farming_berry_smoothie.png
farming_cactus_juice.png
farming_salad.png
Created by Felfa
farming_blackberry*.png
farming_lettuce*.png
farming_burger.png
farming_soy*.png
farming_vanilla*.png

View file

@ -50,6 +50,12 @@ register_plant("beetroot_5", 1, 15, nil, "", -1, farming.beetroot)
register_plant("mint_4", 1, 75, {"default:dirt_with_grass", register_plant("mint_4", 1, 75, {"default:dirt_with_grass",
"default:dirt_with_coniferous_litter"}, "group:water", 1, farming.mint) "default:dirt_with_coniferous_litter"}, "group:water", 1, farming.mint)
register_plant("cabbage_6", 2, 10, nil, "", -1, farming.cabbage) register_plant("cabbage_6", 2, 10, nil, "", -1, farming.cabbage)
register_plant("lettuce_5", 5, 30, nil, "", -1, farming.lettuce)
register_plant("blackberry_4", 3, 10, nil, "", -1, farming.blackberry)
register_plant("soy_6", 20, 50, {"default:dirt_with_dry_grass",
"default:dirt_with_rainforest_litter",
"default:dry_dirt_with_dry_grass"}, "", -1, farming.soy)
register_plant("vanilla_7", 5, 35, nil, "", -1, farming.vanilla)
if minetest.get_mapgen_setting("mg_name") == "v6" then if minetest.get_mapgen_setting("mg_name") == "v6" then
@ -124,7 +130,7 @@ minetest.register_decoration({
}, },
y_min = 5, y_min = 5,
y_max = 35, y_max = 35,
decoration = {"farming:pepper_5"}, decoration = {"farming:pepper_5", "farming:pepper_6", "farming:pepper_7"},
spawn_by = "group:tree", spawn_by = "group:tree",
num_spawn_by = 1 num_spawn_by = 1
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

View file

@ -41,7 +41,7 @@ minetest.register_craft({
minetest.register_craft({ minetest.register_craft({
output = 'building_blocks:fakegrass 2', output = 'building_blocks:fakegrass 2',
recipe = { recipe = {
{'default:leaves'}, {'group:leaves'},
{"default:dirt"}, {"default:dirt"},
} }
}) })
@ -139,7 +139,7 @@ minetest.register_craft({
minetest.register_craft({ minetest.register_craft({
output = 'building_blocks:woodglass 1', output = 'building_blocks:woodglass 1',
recipe = { recipe = {
{"default:wood"}, {"group:wood"},
{"default:glass"}, {"default:glass"},
} }
}) })

View file

@ -76,7 +76,7 @@ homedecor.register("wall_shelf", {
minetest.register_craft({ minetest.register_craft({
output = "homedecor:table", output = "homedecor:table",
recipe = { recipe = {
{ "default:wood","default:wood", "default:wood" }, { "group:wood","group:wood", "group:wood" },
{ "group:stick", "", "group:stick" }, { "group:stick", "", "group:stick" },
}, },
}) })

View file

@ -96,8 +96,8 @@ minetest.register_craft({
output = "homedecor:desk", output = "homedecor:desk",
recipe = { recipe = {
{ "stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood" }, { "stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood" },
{ "homedecor:drawer_small", "default:wood", "default:wood" }, { "homedecor:drawer_small", "group:wood", "group:wood" },
{ "homedecor:drawer_small", "", "default:wood" }, { "homedecor:drawer_small", "", "group:wood" },
}, },
}) })
@ -105,17 +105,17 @@ minetest.register_craft({
output = "homedecor:desk", output = "homedecor:desk",
recipe = { recipe = {
{ "moreblocks:slab_wood", "moreblocks:slab_wood", "moreblocks:slab_wood" }, { "moreblocks:slab_wood", "moreblocks:slab_wood", "moreblocks:slab_wood" },
{ "homedecor:drawer_small", "default:wood", "default:wood" }, { "homedecor:drawer_small", "group:wood", "group:wood" },
{ "homedecor:drawer_small", "", "default:wood" }, { "homedecor:drawer_small", "", "group:wood" },
}, },
}) })
minetest.register_craft({ minetest.register_craft({
output = "homedecor:filing_cabinet", output = "homedecor:filing_cabinet",
recipe = { recipe = {
{ "", "default:wood", "" }, { "", "group:wood", "" },
{ "default:wood", "homedecor:drawer_small", "default:wood" }, { "group:wood", "homedecor:drawer_small", "group:wood" },
{ "", "default:wood", "" }, { "", "group:wood", "" },
}, },
}) })

View file

@ -189,7 +189,7 @@ minetest.register_craft( {
output = "homedecor:wardrobe", output = "homedecor:wardrobe",
recipe = { recipe = {
{ "homedecor:drawer_small", "homedecor:kitchen_cabinet" }, { "homedecor:drawer_small", "homedecor:kitchen_cabinet" },
{ "homedecor:drawer_small", "default:wood" }, { "homedecor:drawer_small", "group:wood" },
{ "homedecor:drawer_small", "default:wood" } { "homedecor:drawer_small", "group:wood" }
}, },
}) })

View file

@ -6,7 +6,7 @@ local S = minetest.get_translator and minetest.get_translator("mob_horse") or
-- 0.4.17 or 5.0 check -- 0.4.17 or 5.0 check
local y_off = 20 local y_off = 20
if minetest.registered_nodes["default:permafrost"] then if minetest.features.object_independent_selectionbox then
y_off = 10 y_off = 10
end end
@ -104,6 +104,14 @@ mobs:register_mob("mob_horse:horse", {
end, end,
do_punch = function(self, hitter)
-- don't cut the branch you're... ah, that's not about that
if hitter ~= self.driver then
return true
end
end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
-- make sure player is clicking -- make sure player is clicking
@ -121,8 +129,10 @@ mobs:register_mob("mob_horse:horse", {
return return
end end
local player_name = clicker:get_player_name()
-- make sure tamed horse is being clicked by owner only -- make sure tamed horse is being clicked by owner only
if self.tamed and self.owner == clicker:get_player_name() then if self.tamed and self.owner == player_name then
local inv = clicker:get_inventory() local inv = clicker:get_inventory()
local tool = clicker:get_wielded_item() local tool = clicker:get_wielded_item()
@ -184,13 +194,15 @@ mobs:register_mob("mob_horse:horse", {
end end
-- show horse speed and jump stats with shoes fitted -- show horse speed and jump stats with shoes fitted
minetest.chat_send_player(clicker:get_player_name(), minetest.chat_send_player(player_name,
S("Horse shoes fitted -") S("Horse shoes fitted -")
.. S(" speed: ") .. speed .. S(" speed: ") .. speed
.. S(" , jump height: ") .. jump .. S(" , jump height: ") .. jump
.. S(" , stop speed: ") .. reverse) .. S(" , stop speed: ") .. reverse)
tool:take_item() ; clicker:set_wielded_item(tool) tool:take_item()
clicker:set_wielded_item(tool)
return return
end end

View file

@ -64,6 +64,12 @@ for _, col in ipairs(all_colours) do
stand_end = 80, stand_end = 80,
walk_start = 81, walk_start = 81,
walk_end = 100, walk_end = 100,
die_start = 1, -- we dont have a specific death animation so we will
die_end = 2, -- re-use 2 standing frames at a speed of 1 fps and
die_speed = 1, -- have mob rotate when dying.
die_loop = false,
die_rotate = true,
}, },
follow = { follow = {
"farming:wheat", "default:grass_1", "farming:barley", "farming:wheat", "default:grass_1", "farming:barley",
@ -97,7 +103,7 @@ for _, col in ipairs(all_colours) do
--are we feeding? --are we feeding?
if mobs:feed_tame(self, clicker, 8, true, true) then if mobs:feed_tame(self, clicker, 8, true, true) then
--if fed 7x grass or wheat then sheep regrows wool --if fed 7 times then sheep regrows wool
if self.food and self.food > 6 then if self.food and self.food > 6 then
self.gotten = false self.gotten = false

View file

@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20201115", version = "20201206",
intllib = S, intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {} invis = minetest.global_exists("invisibility") and invisibility or {}
} }
@ -58,6 +58,7 @@ local mobs_drop_items = settings:get_bool("mobs_drop_items") ~= false
local mobs_griefing = settings:get_bool("mobs_griefing") ~= false local mobs_griefing = settings:get_bool("mobs_griefing") ~= false
local spawn_protected = settings:get_bool("mobs_spawn_protected") ~= false local spawn_protected = settings:get_bool("mobs_spawn_protected") ~= false
local remove_far = settings:get_bool("remove_far_mobs") ~= false local remove_far = settings:get_bool("remove_far_mobs") ~= false
local mob_area_spawn = settings:get_bool("mob_area_spawn")
local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0 local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0
local show_health = settings:get_bool("mob_show_health") ~= false local show_health = settings:get_bool("mob_show_health") ~= false
local max_per_block = tonumber(settings:get("max_objects_per_block") or 99) local max_per_block = tonumber(settings:get("max_objects_per_block") or 99)
@ -111,6 +112,7 @@ local mob_class = {
light_damage_max = 15, light_damage_max = 15,
water_damage = 0, water_damage = 0,
lava_damage = 0, lava_damage = 0,
air_damage = 0,
suffocation = 2, suffocation = 2,
fall_damage = 1, fall_damage = 1,
fall_speed = -10, -- must be lower than -2 (default: -10) fall_speed = -10, -- must be lower than -2 (default: -10)
@ -276,10 +278,10 @@ function mob_class:set_velocity(v)
c_x, c_y = unpack(self:collision()) c_x, c_y = unpack(self:collision())
end end
local yaw = (self.object:get_yaw() or 0) + self.rotate local yaw = (self.object:get_yaw() or 0) + (self.rotate or 0)
-- nil check for velocity -- nil check for velocity
v = v or 0 v = v or 0.01
-- check if standing in liquid with max viscosity of 7 -- check if standing in liquid with max viscosity of 7
local visc = min(minetest.registered_nodes[self.standing_in].liquid_viscosity, 7) local visc = min(minetest.registered_nodes[self.standing_in].liquid_viscosity, 7)
@ -291,8 +293,8 @@ function mob_class:set_velocity(v)
v = v / (visc + 1) v = v / (visc + 1)
end end
-- set velocity with hard limit of 10 -- set velocity
local vel = self.object:get_velocity() local vel = self.object:get_velocity() or 0
local new_vel = { local new_vel = {
x = (sin(yaw) * -v) + c_x, x = (sin(yaw) * -v) + c_x,
@ -828,6 +830,11 @@ end
-- check if mob is dead or only hurt -- check if mob is dead or only hurt
function mob_class:check_for_death(cmi_cause) function mob_class:check_for_death(cmi_cause)
-- We dead already
if self.state == "die" then
return true
end
-- has health actually changed? -- has health actually changed?
if self.health == self.old_health and self.health > 0 then if self.health == self.old_health and self.health > 0 then
return false return false
@ -898,6 +905,7 @@ function mob_class:check_for_death(cmi_cause)
local frames = self.animation.die_end - self.animation.die_start local frames = self.animation.die_end - self.animation.die_start
local speed = self.animation.die_speed or 15 local speed = self.animation.die_speed or 15
local length = max((frames / speed), 0) local length = max((frames / speed), 0)
local rot = self.animation.die_rotate and 5
self.attack = nil self.attack = nil
self.v_start = false self.v_start = false
@ -905,6 +913,10 @@ function mob_class:check_for_death(cmi_cause)
self.blinktimer = 0 self.blinktimer = 0
self.passive = true self.passive = true
self.state = "die" self.state = "die"
self.object:set_properties({
pointable = false, collide_with_objects = false,
automatic_rotate = rot,
})
self:set_velocity(0) self:set_velocity(0)
self:set_animation("die") self:set_animation("die")
@ -1089,6 +1101,19 @@ function mob_class:do_env_damage()
end end
end end
-- air damage
if self.air_damage ~= 0 and self.standing_in == "air" then
self.health = self.health - self.air_damage
effect(pos, 3, "bubble.png", 1, 1, 1, 0.2)
if self:check_for_death({type = "environment",
pos = pos, node = self.standing_in}) then
return true
end
end
-- is mob light sensative, or scared of the dark :P -- is mob light sensative, or scared of the dark :P
if self.light_damage ~= 0 then if self.light_damage ~= 0 then
@ -1295,16 +1320,20 @@ function mob_class:follow_holding(clicker)
return false return false
end end
-- Thanks Wuzzy for the following editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 300
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- find two animals of same type and breed if nearby and horny -- find two animals of same type and breed if nearby and horny
function mob_class:breed() function mob_class:breed()
-- child takes 240 seconds before growing into adult -- child takes a long time before growing into adult
if self.child == true then if self.child == true then
self.hornytimer = self.hornytimer + 1 self.hornytimer = self.hornytimer + 1
if self.hornytimer > 240 then if self.hornytimer > CHILD_GROW_TIME then
self.child = false self.child = false
self.hornytimer = 0 self.hornytimer = 0
@ -1333,14 +1362,14 @@ function mob_class:breed()
return return
end end
-- horny animal can mate for 40 seconds, -- horny animal can mate for HORNY_TIME seconds,
-- afterwards horny animal cannot mate again for 200 seconds -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds
if self.horny == true if self.horny == true
and self.hornytimer < 240 then and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = self.hornytimer + 1 self.hornytimer = self.hornytimer + 1
if self.hornytimer >= 240 then if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = 0 self.hornytimer = 0
self.horny = false self.horny = false
end end
@ -1348,7 +1377,7 @@ function mob_class:breed()
-- find another same animal who is also horny and mate if nearby -- find another same animal who is also horny and mate if nearby
if self.horny == true if self.horny == true
and self.hornytimer <= 40 then and self.hornytimer <= HORNY_TIME then
local pos = self.object:get_pos() local pos = self.object:get_pos()
@ -1356,7 +1385,6 @@ function mob_class:breed()
"heart.png", 3, 4, 1, 0.1) "heart.png", 3, 4, 1, 0.1)
local objs = minetest.get_objects_inside_radius(pos, 3) local objs = minetest.get_objects_inside_radius(pos, 3)
local num = 0
local ent local ent
for n = 1, #objs do for n = 1, #objs do
@ -1385,18 +1413,20 @@ function mob_class:breed()
end end
end end
if ent -- found another similar horny animal that isn't self?
if ent and ent.object ~= self.object
and canmate == true and canmate == true
and ent.horny == true and ent.horny == true
and ent.hornytimer <= 40 then and ent.hornytimer <= HORNY_TIME then
num = num + 1
end
-- found your mate? then have a baby local pos2 = ent.object:get_pos()
if num > 1 then
self.hornytimer = 41 -- Have mobs face one another
ent.hornytimer = 41 yaw_to_pos(self, pos2)
yaw_to_pos(ent, self.object:get_pos())
self.hornytimer = HORNY_TIME + 1
ent.hornytimer = HORNY_TIME + 1
-- have we reached active mob limit -- have we reached active mob limit
if active_limit > 0 and active_mobs >= active_limit then if active_limit > 0 and active_mobs >= active_limit then
@ -1464,8 +1494,6 @@ function mob_class:breed()
ent2.owner = self.owner ent2.owner = self.owner
end, self, ent) end, self, ent)
num = 0
break break
end end
end end
@ -2010,10 +2038,11 @@ function mob_class:follow_flop()
self.following = nil self.following = nil
end end
else else
-- stop following player if not holding specific item -- stop following player if not holding specific item or mob is horny
if self.following if self.following
and self.following:is_player() and self.following:is_player()
and self:follow_holding(self.following) == false then and (self:follow_holding(self.following) == false
or self.horny) then
self.following = nil self.following = nil
end end
@ -2069,6 +2098,15 @@ function mob_class:follow_flop()
if not self:attempt_flight_correction() then if not self:attempt_flight_correction() then
self.state = "flop" self.state = "flop"
-- do we have a custom on_flop function?
if self.on_flop then
if self:on_flop(self) then
return
end
end
self.object:set_velocity({x = 0, y = -5, z = 0}) self.object:set_velocity({x = 0, y = -5, z = 0})
self:set_animation("stand") self:set_animation("stand")
@ -3467,6 +3505,7 @@ minetest.register_entity(name, setmetatable({
owner = def.owner, owner = def.owner,
order = def.order, order = def.order,
on_die = def.on_die, on_die = def.on_die,
on_flop = def.on_flop,
do_custom = def.do_custom, do_custom = def.do_custom,
jump_height = def.jump_height, jump_height = def.jump_height,
drawtype = def.drawtype, -- DEPRECATED, use rotate instead drawtype = def.drawtype, -- DEPRECATED, use rotate instead
@ -3490,6 +3529,7 @@ minetest.register_entity(name, setmetatable({
light_damage_max = def.light_damage_max, light_damage_max = def.light_damage_max,
water_damage = def.water_damage, water_damage = def.water_damage,
lava_damage = def.lava_damage, lava_damage = def.lava_damage,
air_damage = def.air_damage,
suffocation = def.suffocation, suffocation = def.suffocation,
fall_damage = def.fall_damage, fall_damage = def.fall_damage,
fall_speed = def.fall_speed, fall_speed = def.fall_speed,
@ -3908,8 +3948,27 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
end end
-- should we check mob area for obstructions ?
if mob_area_spawn ~= true then
-- do we have enough height clearance to spawn mob?
local ent = minetest.registered_entities[name]
local height = max(1, math.ceil(
(ent.collisionbox[5] or 0.25) - (ent.collisionbox[2] or -0.25) - 1))
for n = 0, height do
local pos2 = {x = pos.x, y = pos.y + n, z = pos.z}
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
--print ("--- inside block", name, node_ok(pos2).name)
return
end
end
else
-- returns position if we have enough space to spawn mob -- returns position if we have enough space to spawn mob
pos = can_spawn(pos, name) pos = can_spawn(pos, name)
end
if pos then if pos then
@ -4552,8 +4611,11 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
-- make children grow quicker -- make children grow quicker
if self.child == true then if self.child == true then
self.hornytimer = self.hornytimer + 20 -- self.hornytimer = self.hornytimer + 20
-- deduct 10% of the time to adulthood
self.hornytimer = self.hornytimer + (
(CHILD_GROW_TIME - self.hornytimer) * 0.1)
print ("====", self.hornytimer)
return true return true
end end

View file

@ -64,6 +64,7 @@ functions needed for the mob to work properly which contains the following:
'fall_damage' when true causes falling to inflict damage. 'fall_damage' when true causes falling to inflict damage.
'water_damage' holds the damage per second infliced to mobs when standing in 'water_damage' holds the damage per second infliced to mobs when standing in
water. water.
'air_damage' holds damage per second inflicted to mob when standing in air.
'lava_damage' holds the damage per second inflicted to mobs when standing 'lava_damage' holds the damage per second inflicted to mobs when standing
in lava or fire or an ignition source. in lava or fire or an ignition source.
'light_damage' holds the damage per second inflicted to mobs when light 'light_damage' holds the damage per second inflicted to mobs when light
@ -226,6 +227,7 @@ functions needed for the mob to work properly which contains the following:
'die_end' 'die_end'
'die_speed' 'die_speed'
'die_loop' when set to false stops the animation looping. 'die_loop' when set to false stops the animation looping.
'die_rotate' if true mob spins during death animation.
Using '_loop = false' setting will stop any of the above animations from Using '_loop = false' setting will stop any of the above animations from
looping. looping.
@ -298,6 +300,9 @@ enhance mob functionality and have them do many interesting things:
is returned normal attack function continued. is returned normal attack function continued.
'on_die' a function that is called when mob is killed (self, pos), also 'on_die' a function that is called when mob is killed (self, pos), also
has access to self.cause_of_death table. has access to self.cause_of_death table.
'on_flop' function called when flying or swimmimng mob is no longer in
air/water, (self) paramater and return true to skip the built
in api flop feature.
'do_custom' a custom function that is called every tick while mob is 'do_custom' a custom function that is called every tick while mob is
active and which has access to all of the self.* variables active and which has access to all of the self.* variables
e.g. (self.health for health or self.standing_in for node e.g. (self.health for health or self.standing_in for node
@ -329,6 +334,14 @@ for each mob.
'self.order' set to "follow" or "stand" so that npc will follow owner 'self.order' set to "follow" or "stand" so that npc will follow owner
or stand it's ground or stand it's ground
'self.nametag' contains the name of the mob which it can show above 'self.nametag' contains the name of the mob which it can show above
'self.state' Current mob state.
"stand": no movement (except turning around)
"walk": walk or move around aimlessly
"attack": chase and attack enemy
"runaway": flee from target
"flop": bounce around aimlessly
(for swimming mobs that have stranded)
"die": during death
Adding Mobs in World Adding Mobs in World
@ -697,6 +710,9 @@ External Settings for "minetest.conf"
function. function.
'mob_nospawn_range' Minimum range a mob can spawn near player (def: 12) 'mob_nospawn_range' Minimum range a mob can spawn near player (def: 12)
'mob_active_limit' Number of active mobs in game, 0 for unlimited 'mob_active_limit' Number of active mobs in game, 0 for unlimited
'mob_area_spawn' When true will check surrounding area the size of the
mob for obstructions before spawning, otherwise it
defaults to checking the height of the mob only.
Players can override the spawn chance for each mob registered by adding a line Players can override the spawn chance for each mob registered by adding a line
to their minetest.conf file with a new value, the lower the value the more each to their minetest.conf file with a new value, the lower the value the more each

View file

@ -23,6 +23,7 @@ Lucky Blocks: 9
Changelog: Changelog:
- 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added.
- 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded. - 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded.
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game, - 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game,
(default is 0 for unlimited), removed {immortal} from mob armor, fluid viscocity slows mobs (default is 0 for unlimited), removed {immortal} from mob armor, fluid viscocity slows mobs

View file

@ -33,3 +33,6 @@ mob_nospawn_range (Mob no-spawn range) float 12.0
# Sets maximum number of active mobs in game (0 for unlimited) # Sets maximum number of active mobs in game (0 for unlimited)
mob_active_limit (Mob Active Limit) float 0 mob_active_limit (Mob Active Limit) float 0
# Enables area check when spawning mobs
mob_area_spawn (Mob Area Spawn) bool false

View file

@ -71,13 +71,28 @@ mobs:register_mob("mobs_fish:clownfish", {
fall_speed = 0, fall_speed = 0,
view_range = 8, view_range = 8,
water_damage = 0, water_damage = 0,
air_damage = 1,
lava_damage = 5, lava_damage = 5,
light_damage = 0, light_damage = 0,
animation = l_anims, animation = l_anims,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
mobs:capture_mob(self, clicker, l_cc_hand, l_cc_net, 0, true, mobs:capture_mob(self, clicker, l_cc_hand, l_cc_net, 0, true,
"mobs_fish:clownfish") "mobs_fish:clownfish")
end end,
on_flop = function(self)
-- print("=== am on land, help!", self.state)
self.object:set_acceleration({
x = math.random(-0.1, 0.1),
y = -10,
z = math.random(-0.1, 0.1)
})
self.object:set_velocity({x = 0, y = -10, z = 0})
return true
end,
}) })
mobs:spawn({ mobs:spawn({
@ -116,11 +131,26 @@ mobs:register_mob("mobs_fish:tropical", {
water_damage = 0, water_damage = 0,
lava_damage = 5, lava_damage = 5,
light_damage = 0, light_damage = 0,
air_damage = 1,
animation = l_anims, animation = l_anims,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
mobs:capture_mob(self, clicker, l_cc_hand, l_cc_net, 0, true, mobs:capture_mob(self, clicker, l_cc_hand, l_cc_net, 0, true,
"mobs_fish:tropical") "mobs_fish:tropical")
end end,
on_flop = function(self)
-- print("=== am on land, help!", self.state)
self.object:set_acceleration({
x = math.random(-0.1, 0.1),
y = -10,
z = math.random(-0.1, 0.1)
})
self.object:set_velocity({x = 0, y = -10, z = 0})
return true
end,
}) })
mobs:spawn({ mobs:spawn({

Some files were not shown because too many files have changed in this diff Show more