forked from VoxeLibre/VoxeLibre
Compare commits
1 Commits
master
...
buildable_
Author | SHA1 | Date |
---|---|---|
Mikita Wiśniewski | 7ab10a8db4 |
|
@ -117,6 +117,10 @@ end
|
|||
-- Array of unique hardness values for each group which affects dig time.
|
||||
local hardness_values = get_hardness_values_for_groups()
|
||||
|
||||
-- Map indexed by hardness values which return the index of that value in
|
||||
-- hardness_value. Used for quick lookup.
|
||||
local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
|
||||
|
||||
--[[local function compute_creativetimes(group)
|
||||
local creativetimes = {}
|
||||
|
||||
|
@ -182,7 +186,6 @@ local function add_groupcaps(toolname, groupcaps, groupcaps_def, efficiency)
|
|||
local mult = capsdef.speed or 1
|
||||
local uses = capsdef.uses
|
||||
local def = mcl_autogroup.registered_diggroups[g]
|
||||
assert(def, toolname .. " has unknown diggroup '" .. dump(g) .. "'")
|
||||
local max_level = def.levels and #def.levels or 1
|
||||
|
||||
assert(capsdef.level, toolname .. ' is missing level for ' .. g)
|
||||
|
@ -310,13 +313,6 @@ function mcl_autogroup.get_wear(toolname, diggroup)
|
|||
end
|
||||
|
||||
local function overwrite()
|
||||
-- Refresh, now that all groups are known.
|
||||
hardness_values = get_hardness_values_for_groups()
|
||||
|
||||
-- Map indexed by hardness values which return the index of that value in
|
||||
-- hardness_value. Used for quick lookup.
|
||||
local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
|
||||
|
||||
for nname, ndef in pairs(minetest.registered_nodes) do
|
||||
local newgroups = table.copy(ndef.groups)
|
||||
if (nname ~= "ignore" and ndef.diggable) then
|
||||
|
@ -378,5 +374,4 @@ local function overwrite()
|
|||
end
|
||||
end
|
||||
|
||||
-- Make sure all tools and groups are registered
|
||||
minetest.register_on_mods_loaded(overwrite)
|
||||
overwrite()
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
name = _mcl_autogroup
|
||||
depends = mcl_autogroup
|
||||
author = ryvnf
|
||||
description = VoxeLibre core mod which automatically adds groups to all items. Very important for digging times.
|
||||
|
|
|
@ -2,33 +2,33 @@
|
|||
Simple flow functions.
|
||||
|
||||
## flowlib.is_touching(realpos, nodepos, radius)
|
||||
Return true if a sphere of `radius` at `realpos` collide with node at `nodepos`.
|
||||
Return true if a sphere of <radius> at <realpos> collide with node at <nodepos>.
|
||||
* realpos: position
|
||||
* nodepos: position
|
||||
* radius: number
|
||||
|
||||
## flowlib.is_water(pos)
|
||||
Return true if node at `pos` is water, false otherwise.
|
||||
Return true if node at <pos> is water, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_water(node)
|
||||
Return true if `node` is water, false otherwise.
|
||||
Return true if <node> is water, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_lava(pos)
|
||||
Return true if node at `pos` is lava, false otherwise.
|
||||
Return true if node at <pos> is lava, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_lava(node)
|
||||
Return true if `node` is lava, false otherwise.
|
||||
Return true if <node> is lava, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_liquid(pos)
|
||||
Return true if node at `pos` is liquid, false otherwise.
|
||||
Return true if node at <pos> is liquid, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_liquid(node)
|
||||
Return true if `node` is liquid, false otherwise.
|
||||
Return true if <node> is liquid, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.quick_flow(pos, node)
|
||||
|
@ -37,9 +37,9 @@ Return direction where the water is flowing (to be use to push mobs, items...).
|
|||
* node: node
|
||||
|
||||
## flowlib.move_centre(pos, realpos, node, radius)
|
||||
Return the pos of the nearest not water block near from `pos` in a sphere of `radius` at `realpos`.
|
||||
WARNING: This function is never used in VL, use at your own risk. The informations described here may be wrong.
|
||||
Return the pos of the nearest not water block near from <pos> in a sphere of <radius> at <realpos>.
|
||||
WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong.
|
||||
* pos: position
|
||||
* realpos: position, position of the entity
|
||||
* node: node
|
||||
* radius: number
|
||||
* radius: number
|
|
@ -1,8 +1,8 @@
|
|||
# mcl_autogroup
|
||||
This mod emulates digging times from MC.
|
||||
This mod emulate digging times from mc.
|
||||
|
||||
## mcl_autogroup.can_harvest(nodename, toolname, player)
|
||||
Return true if `nodename` can be dig with `toolname` by <player>.
|
||||
Return true if <nodename> can be dig with <toolname> by <player>.
|
||||
* nodename: string, valid nodename
|
||||
* toolname: (optional) string, valid toolname
|
||||
* player: (optinal) ObjectRef, valid player
|
||||
|
@ -14,7 +14,7 @@ WARNING: This function can only be called after mod initialization.
|
|||
* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0)
|
||||
|
||||
## mcl_autogroup.get_wear(toolname, diggroup)
|
||||
Return the max wear of `toolname` with `diggroup`
|
||||
Return the max wear of <toolname> with <diggroup>
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool used
|
||||
* diggroup: string, the name of the diggroup the tool is used on
|
||||
|
@ -25,4 +25,4 @@ WARNING: This function can only be called after mod initialization.
|
|||
* level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports
|
||||
|
||||
## mcl_autogroup.registered_diggroups
|
||||
List of registered diggroups, indexed by name.
|
||||
List of registered diggroups, indexed by name.
|
|
@ -1,5 +1,5 @@
|
|||
# mcl_colors
|
||||
Mod providing global table containing legacy Minecraft colors to be used in mods.
|
||||
Mod providing global table containing legacity minecraft colors to be used in mods.
|
||||
|
||||
## mcl_colors.*
|
||||
Colors by upper name, in hex value.
|
||||
|
|
|
@ -6,10 +6,10 @@ WARNING: Not using it inside your mods may cause strange bugs (using the native
|
|||
|
||||
## Callbacks
|
||||
|
||||
To modify the amount of damage dealt by something:
|
||||
To modify the amount of damage made by something:
|
||||
|
||||
```lua
|
||||
--obj: an ObjectRef
|
||||
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||
end, 0)
|
||||
```
|
||||
```
|
|
@ -1,13 +1,9 @@
|
|||
# mcl_events
|
||||
## mcl_events
|
||||
### Registering Events
|
||||
`mlc_events.register_event("name",def)`
|
||||
|
||||
## Registering Events
|
||||
|
||||
`mcl_events.register_event("name", def)`
|
||||
|
||||
### Event Definition
|
||||
|
||||
```
|
||||
{
|
||||
#### Event Definition
|
||||
{
|
||||
stage = 0,
|
||||
max_stage = 1,
|
||||
percent = 100,
|
||||
|
@ -26,8 +22,6 @@
|
|||
cond_complete = function(event) end,
|
||||
--return true if event finished successfully
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
* /event_start `event` -- starts the given event at the current player coordinates
|
||||
### Debugging
|
||||
* /event_start <event> -- starts the given event at the current player coordinates
|
||||
|
|
|
@ -3,13 +3,13 @@ This mod provide helper functions to create explosions.
|
|||
|
||||
## mcl_explosions.explode(pos, strength, info, puncher)
|
||||
* pos: position, initial position of the explosion
|
||||
* strength: number, radius of the explosion
|
||||
* strenght: number, radius of the explosion
|
||||
* info: table, explosion informations:
|
||||
* drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength)
|
||||
* max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value
|
||||
* sound: bool, if true, the explosion will play a sound (default: true)
|
||||
* particles: bool, if true, the explosion will create particles (default: true)
|
||||
* fire: bool, if true, 1/3 of nodes become fire (default: false)
|
||||
* fire: bool, if true, 1/3 nodes become fire (default: false)
|
||||
* griefing: bool, if true, the explosion will destroy nodes (default: true)
|
||||
* grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false)
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
|
@ -48,20 +48,6 @@ function table.pairs_by_keys(t, f)
|
|||
return iter
|
||||
end
|
||||
|
||||
-- Removes one element randomly selected from the array section of the table and
|
||||
-- returns it, or nil if there are no elements in the array section of the table
|
||||
function table.remove_random_element(table)
|
||||
local count = #table
|
||||
if count == 0 then return nil end
|
||||
|
||||
local idx = math.random(count)
|
||||
local res = table[idx]
|
||||
table[idx] = table[count]
|
||||
table[count] = nil
|
||||
count = count - 1
|
||||
return res
|
||||
end
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
|
||||
local LOG_MODULE = "[MCL2]"
|
||||
function mcl_util.mcl_log(message, module, bypass_default_logger)
|
||||
|
@ -1122,34 +1108,3 @@ function mcl_util.to_bool(val)
|
|||
if not val then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
if not vector.in_area then
|
||||
-- backport from minetest 5.8, can be removed when the minimum version is 5.8
|
||||
vector.in_area = function(pos, min, max)
|
||||
return (pos.x >= min.x) and (pos.x <= max.x) and
|
||||
(pos.y >= min.y) and (pos.y <= max.y) and
|
||||
(pos.z >= min.z) and (pos.z <= max.z)
|
||||
end
|
||||
end
|
||||
|
||||
-- Traces along a line of nodes vertically to find the next possition that isn't an allowed node
|
||||
---@param pos The position to start tracing from
|
||||
---@param dir The direction to trace in. 1 is up, -1 is down, all other values are not allowed.
|
||||
---@param allowed_nodes A set of node names to trace along.
|
||||
---@param limit The maximum number of steps to make. Defaults to 16 if nil or missing
|
||||
---@return Three return values:
|
||||
--- the position of the next node that isn't allowed or nil if no such node was found,
|
||||
--- the distance from the start where that node was found,
|
||||
--- the node table if a node was found
|
||||
function mcl_util.trace_nodes(pos, dir, allowed_nodes, limit)
|
||||
if (dir ~= -1) and (dir ~= 1) then return nil, 0, nil end
|
||||
limit = limit or 16
|
||||
|
||||
for i = 1,limit do
|
||||
pos = vector.offset(pos, 0, dir, 0)
|
||||
local node = minetest.get_node(pos)
|
||||
if not allowed_nodes[node.name] then return pos, i, node end
|
||||
end
|
||||
|
||||
return nil, limit, nil
|
||||
end
|
||||
|
|
|
@ -5,21 +5,20 @@ This mod provides utility functions about positions and dimensions.
|
|||
This function returns:
|
||||
|
||||
* true, true: if pos is in deep void (deadly)
|
||||
* true, false: if the pos is in void (non-deadly)
|
||||
* false, false: otherwise
|
||||
* true, false: if the pos is in void (non deadly)
|
||||
* false, false: owerwise
|
||||
|
||||
Params:
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
This function is used to calculate the Minetest y layer and dimension of the given y Minecraft layer.
|
||||
This function is used to calculate the minetest y layer and dimension of the given <y> minecraft layer.
|
||||
Mainly used for ore generation.
|
||||
Takes a Y coordinate as input and returns:
|
||||
|
||||
* The corresponding Minecraft layer (can be `nil` if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if y is in the void
|
||||
Takes an Y coordinate as input and returns:
|
||||
|
||||
* The corresponding Minecraft layer (can be nil if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if <y> is in the void
|
||||
If the Y coordinate is not located in any dimension, it will return: nil, "void"
|
||||
|
||||
Params:
|
||||
|
@ -27,7 +26,7 @@ Params:
|
|||
* y: int
|
||||
|
||||
## mcl_worlds.pos_to_dimension(pos)
|
||||
This function return the Minecraft dimension of pos ("overworld", "nether" or "end") or "void" if y is in the void.
|
||||
This function return the Minecraft dimension of <pos> ("overworld", "nether" or "end") or "void" if <y> is in the void.
|
||||
|
||||
* pos: position
|
||||
|
||||
|
@ -39,32 +38,31 @@ mc_dimension can be "overworld", "nether", "end" (default: "overworld").
|
|||
* mc_dimension: string
|
||||
|
||||
## mcl_worlds.has_weather(pos)
|
||||
Returns true if pos can have weather, false otherwise.
|
||||
Returns true if <pos> can have weather, false owerwise.
|
||||
Weather can be only in the overworld.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.has_dust(pos)
|
||||
Returns true if pos can have nether dust, false otherwise.
|
||||
Returns true if <pos> can have nether dust, false owerwise.
|
||||
Nether dust can be only in the nether.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if compasses are working at pos, false otherwise.
|
||||
In MC, you cant use compass in the nether and the end.
|
||||
Returns true if compasses are working at <pos>, false owerwise.
|
||||
In mc, you cant use compass in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if clock are working at pos, false otherwise.
|
||||
In MC, you cant use clock in the nether and the end.
|
||||
Returns true if clock are working at <pos>, false owerwise.
|
||||
In mc, you cant use clock in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.register_on_dimension_change(function(player, dimension, last_dimension))
|
||||
Register a callback function func(player, dimension).
|
||||
|
||||
It will be called whenever a player changes between dimensions.
|
||||
The void counts as dimension.
|
||||
|
||||
|
@ -77,7 +75,7 @@ The void counts as dimension.
|
|||
Table containing all function registered with mcl_worlds.register_on_dimension_change()
|
||||
|
||||
## mcl_worlds.dimension_change(player, dimension)
|
||||
Notify this mod of a dimension change of player to dimension
|
||||
Notify this mod of a dimension change of <player> to <dimension>
|
||||
|
||||
* player: player, player who changed the dimension
|
||||
* dimension: string, new dimension ("overworld", "nether", "end", "void")
|
||||
|
|
|
@ -388,7 +388,7 @@ end
|
|||
|
||||
|
||||
|
||||
local function on_step_work(self, dtime, moveresult)
|
||||
local function on_step_work (self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
|
||||
|
@ -402,7 +402,7 @@ local function on_step_work(self, dtime, moveresult)
|
|||
-- Do we abandon out of here now?
|
||||
end
|
||||
|
||||
if self:falling(pos, moveresult) then return end
|
||||
if self:falling(pos) then return end
|
||||
if self:step_damage (dtime, pos) then return end
|
||||
|
||||
if self.state == "die" then return end
|
||||
|
@ -502,11 +502,11 @@ end
|
|||
|
||||
|
||||
-- main mob function
|
||||
function mob_class:on_step(dtime, moveresult)
|
||||
function mob_class:on_step(dtime)
|
||||
if not DEVELOPMENT then
|
||||
-- Removed as bundled Lua (5.1 doesn't support xpcall)
|
||||
--local status, retVal = xpcall(on_step_work, on_step_error_handler, self, dtime)
|
||||
local status, retVal = pcall(on_step_work, self, dtime, moveresult)
|
||||
local status, retVal = pcall(on_step_work, self, dtime)
|
||||
if status then
|
||||
return retVal
|
||||
else
|
||||
|
@ -521,7 +521,7 @@ function mob_class:on_step(dtime, moveresult)
|
|||
log_error (dump(retVal), dump(pos), dump(self))
|
||||
end
|
||||
else
|
||||
return on_step_work (self, dtime, moveresult)
|
||||
return on_step_work (self, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -285,7 +285,6 @@ function mob_class:check_breeding()
|
|||
end
|
||||
|
||||
local child = mcl_mobs.spawn_child(pos, parent1.name)
|
||||
if not child then return end
|
||||
|
||||
local ent_c = child:get_luaentity()
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ local validate_vector = mcl_util.validate_vector
|
|||
local active_particlespawners = {}
|
||||
local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
|
||||
local DEFAULT_FALL_SPEED = -9.81*1.5
|
||||
local PI_THIRD = math.pi / 3 -- 60 degrees
|
||||
|
||||
local PATHFINDING = "gowp"
|
||||
|
||||
|
@ -295,66 +294,86 @@ function mcl_mobs:set_animation(self, anim)
|
|||
self:set_animation(anim)
|
||||
end
|
||||
|
||||
local function who_are_you_looking_at (self, dtime)
|
||||
if self.order == "sleep" then
|
||||
self._locked_object = nil
|
||||
return
|
||||
end
|
||||
local function dir_to_pitch(dir)
|
||||
--local dir2 = vector.normalize(dir)
|
||||
local xz = math.abs(dir.x) + math.abs(dir.z)
|
||||
return -math.atan2(-dir.y, xz)
|
||||
end
|
||||
|
||||
local function who_are_you_looking_at (self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
local stop_look_at_player_chance = math.random(833/self.curiosity)
|
||||
-- was 10000 - div by 12 for avg entities as outside loop
|
||||
local stop_look_at_player = math.random() * 833 <= self.curiosity
|
||||
|
||||
local stop_look_at_player = stop_look_at_player_chance == 1
|
||||
|
||||
if self.attack then
|
||||
self._locked_object = not self.target_time_lost and self.attack or nil
|
||||
if not self.target_time_lost then
|
||||
self._locked_object = self.attack
|
||||
else
|
||||
self._locked_object = nil
|
||||
end
|
||||
elseif self.following then
|
||||
self._locked_object = self.following
|
||||
elseif self._locked_object then
|
||||
if stop_look_at_player then self._locked_object = nil end
|
||||
if stop_look_at_player then
|
||||
--minetest.log("Stop look: ".. self.name)
|
||||
self._locked_object = nil
|
||||
end
|
||||
elseif not self._locked_object then
|
||||
if mcl_util.check_dtime_timer(self, dtime, "step_look_for_someone", 0.2) then
|
||||
local pos = self.object:get_pos()
|
||||
--minetest.log("Change look check: ".. self.name)
|
||||
|
||||
-- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates.
|
||||
-- but frequency of check isn't good as it is costly. Making others too infrequent requires testing
|
||||
local chance = 150/self.curiosity
|
||||
|
||||
if chance < 1 then chance = 1 end
|
||||
local look_at_player_chance = math.random(chance)
|
||||
|
||||
-- was 5000 but called in loop based on entities. so div by 12 as estimate avg of entities found,
|
||||
-- then div by 20 as less freq lookup
|
||||
|
||||
local look_at_player = look_at_player_chance == 1
|
||||
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 8)) do
|
||||
if obj:is_player() and vector.distance(pos, obj:get_pos()) < 4 then
|
||||
if obj:is_player() and vector.distance(pos,obj:get_pos()) < 4 then
|
||||
--minetest.log("Change look to player: ".. self.name)
|
||||
self._locked_object = obj
|
||||
break
|
||||
elseif obj:is_player() or (obj:get_luaentity() and self ~= obj:get_luaentity() and obj:get_luaentity().name == self.name) then
|
||||
-- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates.
|
||||
-- but frequency of check isn't good as it is costly. Making others too infrequent requires testing
|
||||
-- was 5000 but called in loop based on entities. so div by 12 as estimate avg of entities found,
|
||||
-- then div by 20 as less freq lookup
|
||||
if math.random() * 150 <= self.curiosity then
|
||||
elseif obj:is_player() or (obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity()) then
|
||||
if look_at_player then
|
||||
--minetest.log("Change look to mob: ".. self.name)
|
||||
self._locked_object = obj
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function mob_class:check_head_swivel(dtime)
|
||||
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
|
||||
|
||||
who_are_you_looking_at(self, dtime)
|
||||
|
||||
local newr, oldp, oldr = vector.zero(), nil, nil
|
||||
if self.object.get_bone_override then -- minetest >= 5.9
|
||||
local ov = self.object:get_bone_override(self.head_swivel)
|
||||
oldp, oldr = ov.position.vec, ov.rotation.vec
|
||||
else -- minetest < 5.9
|
||||
oldp, oldr = self.object:get_bone_position(self.head_swivel)
|
||||
oldr = vector.apply(oldr, math.rad) -- old API uses radians
|
||||
end
|
||||
who_are_you_looking_at (self, dtime)
|
||||
|
||||
local locked_object = self._locked_object
|
||||
if locked_object and (locked_object:is_player() or locked_object:get_luaentity()) and locked_object:get_hp() > 0 then
|
||||
local final_rotation = vector.zero()
|
||||
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
|
||||
|
||||
if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then
|
||||
local _locked_object_eye_height = 1.5
|
||||
if locked_object:is_player() then
|
||||
_locked_object_eye_height = locked_object:get_properties().eye_height
|
||||
elseif locked_object:get_luaentity() then
|
||||
_locked_object_eye_height = locked_object:get_luaentity().head_eye_height
|
||||
if self._locked_object:get_luaentity() then
|
||||
_locked_object_eye_height = self._locked_object:get_luaentity().head_eye_height
|
||||
end
|
||||
if self._locked_object:is_player() then
|
||||
_locked_object_eye_height = self._locked_object:get_properties().eye_height
|
||||
end
|
||||
if _locked_object_eye_height then
|
||||
|
||||
local self_rot = self.object:get_rotation()
|
||||
-- If a mob is attached, should we really be messing with what they are looking at?
|
||||
-- Should this be excluded?
|
||||
|
@ -362,48 +381,40 @@ function mob_class:check_head_swivel(dtime)
|
|||
self_rot = self.object:get_attach():get_rotation()
|
||||
end
|
||||
|
||||
local ps = self.object:get_pos()
|
||||
ps.y = ps.y + self.head_eye_height * .7
|
||||
local pt = locked_object:get_pos()
|
||||
pt.y = pt.y + _locked_object_eye_height
|
||||
local dir = vector.direction(ps, pt)
|
||||
local mob_yaw = self_rot.y + math.atan2(dir.x, dir.z) + self.head_yaw_offset
|
||||
local mob_pitch = math.asin(-dir.y) * self.head_pitch_multiplier
|
||||
local player_pos = self._locked_object:get_pos()
|
||||
local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0)))
|
||||
local mob_yaw = math.deg(-(-(self_rot.y)-(-minetest.dir_to_yaw(direction_player))))+self.head_yaw_offset
|
||||
local mob_pitch = math.deg(-dir_to_pitch(direction_player))*self.head_pitch_multiplier
|
||||
|
||||
if (mob_yaw < -PI_THIRD or mob_yaw > PI_THIRD) and not (self.attack and self.state == "attack" and not self.runaway) then
|
||||
newr = vector.multiply(oldr, 0.9)
|
||||
if (mob_yaw < -60 or mob_yaw > 60) and not (self.attack and self.state == "attack" and not self.runaway) then
|
||||
final_rotation = vector.multiply(oldr, 0.9)
|
||||
elseif self.attack and self.state == "attack" and not self.runaway then
|
||||
if self.head_yaw == "y" then
|
||||
newr = vector.new(mob_pitch, mob_yaw, 0)
|
||||
final_rotation = vector.new(mob_pitch, mob_yaw, 0)
|
||||
elseif self.head_yaw == "z" then
|
||||
newr = vector.new(mob_pitch, 0, -mob_yaw)
|
||||
final_rotation = vector.new(mob_pitch, 0, -mob_yaw)
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
if self.head_yaw == "y" then
|
||||
newr = vector.new((mob_pitch-oldr.x)*.3+oldr.x, (mob_yaw-oldr.y)*.3+oldr.y, 0)
|
||||
final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, ((mob_yaw-oldr.y)*.3)+oldr.y, 0)
|
||||
elseif self.head_yaw == "z" then
|
||||
newr = vector.new((mob_pitch-oldr.x)*.3+oldr.x, 0, ((mob_yaw-oldr.y)*.3+oldr.y)*-3)
|
||||
final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, 0, -(((mob_yaw-oldr.y)*.3)+oldr.y)*3)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif not locked_object and math.abs(oldr.y) > 0.05 and math.abs(oldr.x) < 0.05 then
|
||||
newr = vector.multiply(oldr, 0.9)
|
||||
end
|
||||
|
||||
-- 0.02 is about 1.14 degrees tolerance, to update less often
|
||||
local newp = vector.new(0, self.bone_eye_height, self.horizontal_head_height)
|
||||
if math.abs(oldr.x-newr.x) + math.abs(oldr.y-newr.y) + math.abs(oldr.z-newr.z) < 0.02 and vector.equals(oldp, newp) then return end
|
||||
if self.object.get_bone_override then -- minetest >= 5.9
|
||||
self.object:set_bone_override(self.head_swivel, {
|
||||
position = { vec = newp, absolute = true },
|
||||
rotation = { vec = newr, absolute = true } })
|
||||
else -- minetest < 5.9
|
||||
-- old API uses degrees not radians
|
||||
self.object:set_bone_position(self.head_swivel, newp, vector.apply(newr, math.deg))
|
||||
elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then
|
||||
final_rotation = vector.multiply(oldr, 0.9)
|
||||
else
|
||||
--final_rotation = vector.new(0,0,0)
|
||||
end
|
||||
|
||||
mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horizontal_head_height), final_rotation)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function mob_class:set_animation_speed()
|
||||
local v = self.object:get_velocity()
|
||||
if v then
|
||||
|
|
|
@ -141,7 +141,7 @@ function mcl_mobs.register_mob(name, def)
|
|||
local final_def = {
|
||||
use_texture_alpha = def.use_texture_alpha,
|
||||
head_swivel = def.head_swivel or nil, -- bool to activate this function
|
||||
head_yaw_offset = math.rad(def.head_yaw_offset or 0), -- for wonkey model bones
|
||||
head_yaw_offset = def.head_yaw_offset or 0, -- for wonkey model bones
|
||||
head_pitch_multiplier = def.head_pitch_multiplier or 1, --for inverted pitch
|
||||
bone_eye_height = def.bone_eye_height or 1.4, -- head bone offset
|
||||
head_eye_height = def.head_eye_height or def.bone_eye_height or 0, -- how hight aproximatly the mobs head is fromm the ground to tell the mob how high to look up at the player
|
||||
|
@ -528,7 +528,7 @@ end
|
|||
-- Note: This also introduces the “spawn_egg” group:
|
||||
-- * spawn_egg=1: Spawn egg (generic mob, no metadata)
|
||||
-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata)
|
||||
function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, addegg, no_creative)
|
||||
function mcl_mobs.register_egg(mob, desc, background_color, overlay_color, addegg, no_creative)
|
||||
|
||||
local grp = {spawn_egg = 1}
|
||||
|
||||
|
@ -539,7 +539,7 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
|
||||
local invimg = "(spawn_egg.png^[multiply:" .. background_color ..")^(spawn_egg_overlay.png^[multiply:" .. overlay_color .. ")"
|
||||
if old_spawn_icons then
|
||||
local mobname = mob_id:gsub("mobs_mc:","")
|
||||
local mobname = mob:gsub("mobs_mc:","")
|
||||
local fn = "mobs_mc_spawn_icon_"..mobname..".png"
|
||||
if mcl_util.file_exists(minetest.get_modpath("mobs_mc").."/textures/"..fn) then
|
||||
invimg = fn
|
||||
|
@ -551,7 +551,7 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
end
|
||||
|
||||
-- register old stackable mob egg
|
||||
minetest.register_craftitem(mob_id, {
|
||||
minetest.register_craftitem(mob, {
|
||||
|
||||
description = desc,
|
||||
inventory_image = invimg,
|
||||
|
@ -561,6 +561,7 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
_doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."),
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
|
||||
local pos = pointed_thing.above
|
||||
|
||||
-- am I clicking on something with existing on_rightclick function?
|
||||
|
@ -570,12 +571,11 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
return def.on_rightclick(pointed_thing.under, under, placer, itemstack)
|
||||
end
|
||||
|
||||
local mob_name = itemstack:get_name()
|
||||
|
||||
if pos and within_limits(pos, 0) and not minetest.is_protected(pos, placer:get_player_name()) then
|
||||
local name = placer:get_player_name()
|
||||
local privs = minetest.get_player_privs(name)
|
||||
|
||||
|
||||
if under.name == "mcl_mobspawners:spawner" then
|
||||
if minetest.is_protected(pointed_thing.under, name) then
|
||||
minetest.record_protection_violation(pointed_thing.under, name)
|
||||
|
@ -593,6 +593,7 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
--minetest.log("max light: " .. mob_light_lvl[2])
|
||||
|
||||
-- Handle egg conversion
|
||||
local mob_name = itemstack:get_name()
|
||||
local convert_to = (minetest.registered_entities[mob_name] or {})._convert_to
|
||||
if convert_to then mob_name = convert_to end
|
||||
|
||||
|
@ -603,24 +604,19 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
return itemstack
|
||||
end
|
||||
|
||||
if not minetest.registered_entities[mob_name] then
|
||||
if not minetest.registered_entities[mob] then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
if minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
and minetest.registered_entities[mob_name].type == "monster" then
|
||||
and minetest.registered_entities[mob].type == "monster" then
|
||||
minetest.chat_send_player(name, S("Only peaceful mobs allowed!"))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
pos.y = pos.y - 1
|
||||
local mob = mcl_mobs.spawn(pos, mob_name)
|
||||
if not mob then
|
||||
pos.y = pos.y + 1
|
||||
mob = mcl_mobs.spawn(pos, mob_name)
|
||||
if not mob then return end
|
||||
end
|
||||
pos.y = pos.y - 0.5
|
||||
|
||||
local mob = minetest.add_entity(pos, mob)
|
||||
local entityname = itemstack:get_name()
|
||||
minetest.log("action", "Player " ..name.." spawned "..entityname.." at "..minetest.pos_to_string(pos))
|
||||
local ent = mob:get_luaentity()
|
||||
|
@ -651,4 +647,5 @@ function mcl_mobs.register_egg(mob_id, desc, background_color, overlay_color, ad
|
|||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
end
|
||||
|
|
|
@ -927,7 +927,8 @@ end
|
|||
|
||||
-- falling and fall damage
|
||||
-- returns true if mob died
|
||||
function mob_class:falling(pos, moveresult)
|
||||
function mob_class:falling(pos)
|
||||
|
||||
if self.fly and self.state ~= "die" then
|
||||
return
|
||||
end
|
||||
|
@ -950,13 +951,7 @@ function mob_class:falling(pos, moveresult)
|
|||
new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0)
|
||||
elseif v.y <= 0 and v.y > self.fall_speed then
|
||||
-- fall downwards at set speed
|
||||
if moveresult and moveresult.touching_ground then
|
||||
-- when touching ground, retain a minimal gravity to keep the touching_ground flag
|
||||
-- but also to not get upwards acceleration with large dtime when on bouncy ground
|
||||
new_acceleration = vector.new(0, self.fall_speed * 0.01, 0)
|
||||
else
|
||||
new_acceleration = vector.new(0, self.fall_speed, 0)
|
||||
end
|
||||
new_acceleration = vector.new(0, self.fall_speed, 0)
|
||||
else
|
||||
-- stop accelerating once max fall speed hit
|
||||
new_acceleration =vector.zero()
|
||||
|
|
|
@ -10,12 +10,12 @@ local overworld_sky_threshold = tonumber(minetest.settings:get("mcl_mobs_overwor
|
|||
local overworld_passive_threshold = tonumber(minetest.settings:get("mcl_mobs_overworld_passive_threshold")) or 7
|
||||
|
||||
local get_node = minetest.get_node
|
||||
local get_item_group = minetest.get_item_group
|
||||
local get_node_light = minetest.get_node_light
|
||||
local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
|
||||
local mt_get_biome_name = minetest.get_biome_name
|
||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local get_connected_players = minetest.get_connected_players
|
||||
local registered_nodes = minetest.registered_nodes
|
||||
|
||||
local math_min = math.min
|
||||
local math_max = math.max
|
||||
|
@ -25,7 +25,6 @@ local math_ceil = math.ceil
|
|||
local math_cos = math.cos
|
||||
local math_sin = math.sin
|
||||
local math_sqrt = math.sqrt
|
||||
local math_abs = math.abs
|
||||
|
||||
local vector_distance = vector.distance
|
||||
local vector_new = vector.new
|
||||
|
@ -36,14 +35,18 @@ local table_remove = table.remove
|
|||
local pairs = pairs
|
||||
|
||||
local logging = minetest.settings:get_bool("mcl_logging_mobs_spawn", false)
|
||||
local function mcl_log(message, property)
|
||||
if property then message = message .. ": " .. dump(property) end
|
||||
mcl_util.mcl_log(message, "[Mobs spawn]", true)
|
||||
local function mcl_log (message, property)
|
||||
if logging then
|
||||
if property then
|
||||
message = message .. ": " .. dump(property)
|
||||
end
|
||||
mcl_util.mcl_log (message, "[Mobs spawn]", true)
|
||||
end
|
||||
end
|
||||
if not logging then mcl_log = function() end end
|
||||
|
||||
local dbg_spawn_attempts = 0
|
||||
local dbg_spawn_succ = 0
|
||||
local dbg_spawn_counts = {}
|
||||
|
||||
local remove_far = true
|
||||
|
||||
|
@ -96,6 +99,169 @@ mcl_log("Percentage of hostile spawns are group: " .. hostile_group_percentage_s
|
|||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
|
||||
|
||||
-- THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||
-- Also used for missing parameter
|
||||
-- Please update the list when adding new biomes!
|
||||
|
||||
local list_of_all_biomes = {
|
||||
|
||||
-- underground:
|
||||
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"MangroveSwamp_underground",
|
||||
|
||||
-- ocean:
|
||||
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"MangroveSwamp_ocean",
|
||||
"MangroveSwamp_deep_ocean",
|
||||
|
||||
-- water or beach?
|
||||
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
|
||||
-- beach:
|
||||
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"BambooJungleM_shore",
|
||||
"BambooJungle_shore",
|
||||
"MangroveSwamp_shore",
|
||||
|
||||
-- dimension biome:
|
||||
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"CrimsonForest",
|
||||
"WarpedForest",
|
||||
"SoulsandValley",
|
||||
"End",
|
||||
|
||||
-- Overworld regular:
|
||||
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+_snowtop",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"MangroveSwamp",
|
||||
"BambooJungle",
|
||||
"BambooJungleEdge",
|
||||
"BambooJungleEdgeM",
|
||||
"BambooJungleM",
|
||||
}
|
||||
|
||||
-- count how many mobs are in an area
|
||||
local function count_mobs(pos,r,mob_type)
|
||||
local num = 0
|
||||
|
@ -123,7 +289,11 @@ local function count_mobs_total(mob_type)
|
|||
end
|
||||
|
||||
local function count_mobs_add_entry (mobs_list, mob_cat)
|
||||
mobs_list[mob_cat] = (mobs_list[mob_cat] or 0) + 1
|
||||
if mobs_list[mob_cat] then
|
||||
mobs_list[mob_cat] = mobs_list[mob_cat] + 1
|
||||
else
|
||||
mobs_list[mob_cat] = 1
|
||||
end
|
||||
end
|
||||
|
||||
--categorise_by can be name or type or spawn_class
|
||||
|
@ -282,7 +452,7 @@ function mcl_mobs:spawn_setup(def)
|
|||
|
||||
local dimension = def.dimension or "overworld"
|
||||
local type_of_spawning = def.type_of_spawning or "ground"
|
||||
local biomes = def.biomes or nil
|
||||
local biomes = def.biomes or list_of_all_biomes
|
||||
local min_light = def.min_light or 0
|
||||
local max_light = def.max_light or (minetest.LIGHT_MAX + 1)
|
||||
local chance = def.chance or 1000
|
||||
|
@ -449,14 +619,14 @@ local function get_next_mob_spawn_pos(pos)
|
|||
xoff, yoff, zoff = xoff * dd, yoff * dd, zoff * dd
|
||||
local goal_pos = vector.offset(pos, xoff, yoff, zoff)
|
||||
|
||||
if not (math_abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math_abs(goal_pos.y) <= SPAWN_MAPGEN_LIMIT and math_abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT) then
|
||||
if not ( math.abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.y) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT ) then
|
||||
mcl_log("Pos outside mapgen limits: " .. minetest.pos_to_string(goal_pos))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Calculate upper/lower y limits
|
||||
local d2 = xoff*xoff + zoff*zoff -- squared distance in x,z plane only
|
||||
local y1 = math_sqrt(MOB_SPAWN_ZONE_OUTER_SQ - d2) -- absolue value of distance to outer sphere
|
||||
local y1 = math_sqrt( MOB_SPAWN_ZONE_OUTER_SQ - d2 ) -- absolue value of distance to outer sphere
|
||||
|
||||
local y_min, y_max
|
||||
if d2 >= MOB_SPAWN_ZONE_INNER_SQ then
|
||||
|
@ -465,7 +635,7 @@ local function get_next_mob_spawn_pos(pos)
|
|||
y_max = pos.y + y1
|
||||
else
|
||||
-- Inner region, y range spans between inner and outer spheres
|
||||
local y2 = math_sqrt(MOB_SPAWN_ZONE_INNER_SQ - d2)
|
||||
local y2 = math_sqrt( MOB_SPAWN_ZONE_INNER_SQ - d2 )
|
||||
if goal_pos.y > pos.y then
|
||||
-- Upper hemisphere
|
||||
y_min = pos.y + y2
|
||||
|
@ -510,12 +680,12 @@ end
|
|||
|
||||
--a simple helper function for mob_spawn
|
||||
local function biome_check(biome_list, biome_goal)
|
||||
if not biome_goal then return false end
|
||||
for _, data in pairs(biome_list) do
|
||||
if data == biome_goal then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -530,8 +700,8 @@ local function get_water_spawn(p)
|
|||
end
|
||||
end
|
||||
|
||||
local function has_room(self, pos)
|
||||
local cb = self.spawnbox or self.collisionbox
|
||||
local function has_room(self,pos)
|
||||
local cb = self.collisionbox
|
||||
local nodes = {}
|
||||
if self.fly_in then
|
||||
local t = type(self.fly_in)
|
||||
|
@ -542,74 +712,18 @@ local function has_room(self, pos)
|
|||
end
|
||||
end
|
||||
table.insert(nodes,"air")
|
||||
|
||||
-- Calculate area to check for room
|
||||
local cb_height = cb[5] - cb[2]
|
||||
local p1 = vector.new(
|
||||
math.round(pos.x + cb[1]),
|
||||
math.floor(pos.y),
|
||||
math.round(pos.z + cb[3]))
|
||||
local p2 = vector.new(
|
||||
math.round(pos.x + cb[4]),
|
||||
math.ceil(p1.y + cb_height) - 1,
|
||||
math.round(pos.z + cb[6]))
|
||||
|
||||
-- Check if the entire spawn volume is free
|
||||
local dx = p2.x - p1.x + 1
|
||||
local dy = p2.y - p1.y + 1
|
||||
local dz = p2.z - p1.z + 1
|
||||
local found_nodes = minetest.find_nodes_in_area(p1,p2,nodes) or 0
|
||||
local n = #found_nodes
|
||||
if n == dx * dy * dz then
|
||||
return true
|
||||
local x = cb[4] - cb[1]
|
||||
local y = cb[5] - cb[2]
|
||||
local z = cb[6] - cb[3]
|
||||
local r = math.ceil(x * y * z)
|
||||
local p1 = vector.offset(pos,cb[1],cb[2],cb[3])
|
||||
local p2 = vector.offset(pos,cb[4],cb[5],cb[6])
|
||||
local n = #minetest.find_nodes_in_area(p1,p2,nodes) or 0
|
||||
if r > n then
|
||||
minetest.log("warning","[mcl_mobs] No room for mob "..self.name.." at "..minetest.pos_to_string(vector.round(pos)))
|
||||
return false
|
||||
end
|
||||
|
||||
-- If we don't have an implementation of get_node_boxes, we can't check for sub-node space
|
||||
if not minetest.get_node_boxes then return false end
|
||||
|
||||
-- Check if it's possible for a sub-node space check to succeed
|
||||
local needed_in_bottom_section = dx * ( dy - 1) * dz
|
||||
if n < needed_in_bottom_section then return false end
|
||||
|
||||
-- Make sure the entire volume except for the top level is free before checking the top layer
|
||||
if dy > 1 then
|
||||
-- Remove nodes in the top layer from the count
|
||||
for i = 1,#found_nodes do
|
||||
if found_nodes[i].y == p2.y then
|
||||
n = n - 1
|
||||
end
|
||||
end
|
||||
|
||||
-- If the entire volume except the top layer isn't air (or nodes) then we can't spawn this mob here
|
||||
if n < needed_in_bottom_section then return false end
|
||||
end
|
||||
|
||||
-- Check the top layer to see if we have enough space to spawn in
|
||||
local top_layer_height = 1
|
||||
local processed = {}
|
||||
for x = p1.x,p2.x do
|
||||
for z = p1.z,p2.z do
|
||||
local test_pos = vector.new(x,p2.y,z)
|
||||
local node = minetest.get_node(test_pos) or { name = "ignore" }
|
||||
local cache_name = string.format("%s-%d", node.name, node.param2)
|
||||
if not processed[cache_name] then
|
||||
-- Calculate node bounding box and select the lowest y value
|
||||
local boxes = minetest.get_node_boxes("collision_box", test_pos, node)
|
||||
for i = 1,#boxes do
|
||||
local box = boxes[i]
|
||||
local y_test = box[2] + 0.5
|
||||
if y_test < top_layer_height then top_layer_height = y_test end
|
||||
|
||||
local y_test = box[5] + 0.5
|
||||
if y_test < top_layer_height then top_layer_height = y_test end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if top_layer_height + dy - 1 >= cb_height then return true end
|
||||
|
||||
-- We don't have room
|
||||
return false
|
||||
return true
|
||||
end
|
||||
|
||||
mcl_mobs.custom_biomecheck = nil
|
||||
|
@ -618,92 +732,119 @@ function mcl_mobs.register_custom_biomecheck(custom_biomecheck)
|
|||
mcl_mobs.custom_biomecheck = custom_biomecheck
|
||||
end
|
||||
|
||||
|
||||
local function get_biome_name(pos)
|
||||
if mcl_mobs.custom_biomecheck then return mcl_mobs.custom_biomecheck(pos) end
|
||||
local gotten_biome = minetest.get_biome_data(pos)
|
||||
return gotten_biome and mt_get_biome_name(gotten_biome.biome)
|
||||
if mcl_mobs.custom_biomecheck then
|
||||
return mcl_mobs.custom_biomecheck (pos)
|
||||
else
|
||||
local gotten_biome = minetest.get_biome_data(pos)
|
||||
|
||||
if not gotten_biome then
|
||||
return
|
||||
end
|
||||
|
||||
gotten_biome = mt_get_biome_name(gotten_biome.biome)
|
||||
--minetest.log ("biome: " .. dump(gotten_biome))
|
||||
|
||||
return gotten_biome
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_check(pos, spawn_def)
|
||||
if not spawn_def or not pos then return end
|
||||
|
||||
dbg_spawn_attempts = dbg_spawn_attempts + 1
|
||||
|
||||
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||
if spawn_def.dimension ~= dimension then return end -- wrong dimension
|
||||
-- find ground node below spawn position
|
||||
local node_name = get_node(pos).name
|
||||
local node_def = registered_nodes[node_name]
|
||||
if node_def and not node_def.groups.solid then -- try node one below instead
|
||||
pos.y = pos.y - 1
|
||||
node_name = get_node(pos).name
|
||||
node_def = registered_nodes[node_name]
|
||||
end
|
||||
if not node_def or not node_def.groups then return end
|
||||
-- do not spawn on bedrock
|
||||
if node_name == "mcl_core:bedrock" then return end
|
||||
pos.y = pos.y + 1
|
||||
-- check spawn height
|
||||
if pos.y < spawn_def.min_height or pos.y > spawn_def.max_height then return end
|
||||
mcl_log("spawn_check#1 position checks passed")
|
||||
|
||||
-- do not spawn ground mobs on leaves
|
||||
if spawn_def.type_of_spawning == "ground" and (not node_def.groups.solid or node_def.groups.leaves) then return end
|
||||
-- water mobs only on water
|
||||
if spawn_def.type_of_spawning == "water" and not node_def.groups.water then return end
|
||||
-- lava mobs only on lava
|
||||
if spawn_def.type_of_spawning == "lava" and not node_def.groups.lava then return end
|
||||
-- farm animals on grass only
|
||||
if is_farm_animal(spawn_def.name) and not node_def.groups.grass_block then return end
|
||||
|
||||
---- More expensive calls:
|
||||
-- check the biome
|
||||
if spawn_def.biomes and not biome_check(spawn_def.biomes, get_biome_name(pos)) then return end
|
||||
-- check if there is enough room
|
||||
local mob_def = minetest.registered_entities[spawn_def.name]
|
||||
if not has_room(mob_def,pos) then return end
|
||||
-- additional checks (slime etc.)
|
||||
if spawn_def.check_position and not spawn_def.check_position(pos) then return end
|
||||
if spawn_protected and minetest.is_protected(pos, "") then return end
|
||||
mcl_log("spawn_check#2 advanced checks passed")
|
||||
local mob_type = mob_def.type
|
||||
local gotten_node = get_node(pos).name
|
||||
if not gotten_node then return end
|
||||
|
||||
-- check light thresholds
|
||||
local gotten_light = get_node_light(pos)
|
||||
-- old lighting
|
||||
if not modern_lighting then return gotten_light >= spawn_def.min_light and gotten_light <= spawn_def.max_light end
|
||||
local biome_name = get_biome_name(pos)
|
||||
if not biome_name then return end
|
||||
|
||||
local sky_light = minetest.get_natural_light(pos)
|
||||
local art_light = minetest.get_artificial_light(get_node(pos).param1)
|
||||
if mob_def.spawn_check then
|
||||
return mob_def.spawn_check(pos, gotten_light, art_light, sky_light)
|
||||
local is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
|
||||
if not is_ground then
|
||||
pos.y = pos.y - 1
|
||||
gotten_node = get_node(pos).name
|
||||
is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
|
||||
end
|
||||
if mob_def.type == "monster" then
|
||||
if dimension == "nether" then
|
||||
if art_light <= nether_threshold then
|
||||
return true
|
||||
end
|
||||
elseif dimension == "end" then
|
||||
if art_light <= end_threshold then
|
||||
return true
|
||||
end
|
||||
elseif dimension == "overworld" then
|
||||
if art_light <= overworld_threshold and sky_light <= overworld_sky_threshold then
|
||||
return true
|
||||
pos.y = pos.y + 1
|
||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||
local is_leaf = get_item_group(gotten_node, "leaves") ~= 0
|
||||
local is_bedrock = gotten_node == "mcl_core:bedrock"
|
||||
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
|
||||
|
||||
if pos.y >= spawn_def.min_height
|
||||
and pos.y <= spawn_def.max_height
|
||||
and spawn_def.dimension == dimension
|
||||
and biome_check(spawn_def.biomes, biome_name) then
|
||||
|
||||
mcl_log("Spawn level 1 check - Passed")
|
||||
if (is_ground or spawn_def.type_of_spawning ~= "ground")
|
||||
and (spawn_def.type_of_spawning ~= "ground" or not is_leaf)
|
||||
and (not is_farm_animal(spawn_def.name) or is_grass)
|
||||
and (spawn_def.type_of_spawning ~= "water" or is_water)
|
||||
and not is_bedrock
|
||||
and has_room(mob_def,pos)
|
||||
and (spawn_def.check_position and spawn_def.check_position(pos) or spawn_def.check_position == nil)
|
||||
and ( not spawn_protected or not minetest.is_protected(pos, "") ) then
|
||||
|
||||
mcl_log("Spawn level 2 check - Passed")
|
||||
local gotten_light = get_node_light(pos)
|
||||
|
||||
if modern_lighting then
|
||||
local my_node = get_node(pos)
|
||||
local sky_light = minetest.get_natural_light(pos)
|
||||
local art_light = minetest.get_artificial_light(my_node.param1)
|
||||
|
||||
if mob_def.spawn_check then
|
||||
return mob_def.spawn_check(pos, gotten_light, art_light, sky_light)
|
||||
elseif mob_type == "monster" then
|
||||
if dimension == "nether" then
|
||||
if art_light <= nether_threshold then
|
||||
return true
|
||||
end
|
||||
elseif dimension == "end" then
|
||||
if art_light <= end_threshold then
|
||||
return true
|
||||
end
|
||||
elseif dimension == "overworld" then
|
||||
if art_light <= overworld_threshold and sky_light <= overworld_sky_threshold then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- passive threshold is apparently the same in all dimensions ...
|
||||
if gotten_light > overworld_passive_threshold then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
if gotten_light >= spawn_def.min_light and gotten_light <= spawn_def.max_light then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
-- passive threshold is apparently the same in all dimensions ...
|
||||
return gotten_light > overworld_passive_threshold
|
||||
return false
|
||||
end
|
||||
|
||||
function mcl_mobs.spawn(pos,id)
|
||||
if not pos or not id then return false end
|
||||
local def = minetest.registered_entities[id] or minetest.registered_entities["mobs_mc:"..id] or minetest.registered_entities["extra_mobs:"..id]
|
||||
if not def or not def.is_mob or (def.can_spawn and not def.can_spawn(pos)) then return false end
|
||||
if not has_room(def, pos) then return false end
|
||||
if not def or (def.can_spawn and not def.can_spawn(pos)) or not def.is_mob then
|
||||
return false
|
||||
end
|
||||
if not dbg_spawn_counts[def.name] then
|
||||
dbg_spawn_counts[def.name] = 1
|
||||
else
|
||||
dbg_spawn_counts[def.name] = dbg_spawn_counts[def.name] + 1
|
||||
end
|
||||
return minetest.add_entity(pos, def.name)
|
||||
end
|
||||
|
||||
|
||||
local function spawn_group(p,mob,spawn_on,amount_to_spawn)
|
||||
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
||||
local o
|
||||
|
@ -1097,6 +1238,7 @@ end
|
|||
minetest.register_chatcommand("mobstats",{
|
||||
privs = { debug = true },
|
||||
func = function(n,param)
|
||||
--minetest.chat_send_player(n,dump(dbg_spawn_counts))
|
||||
local pos = minetest.get_player_by_name(n):get_pos()
|
||||
minetest.chat_send_player(n,"mobs: within 32 radius of player/total loaded :"..count_mobs(pos,MOB_CAP_INNER_RADIUS) .. "/" .. count_mobs_total())
|
||||
minetest.chat_send_player(n,"spawning attempts since server start:" .. dbg_spawn_succ .. "/" .. dbg_spawn_attempts)
|
||||
|
|
|
@ -72,24 +72,18 @@ local axolotl = {
|
|||
fly = true,
|
||||
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
|
||||
breathes_in_water = true,
|
||||
jump = false, -- would get them out of the water too often
|
||||
jump = true,
|
||||
damage = 2,
|
||||
reach = 2,
|
||||
attack_type = "dogfight",
|
||||
attack_animals = true,
|
||||
specific_attack = {
|
||||
"mobs_mc:cod",
|
||||
"mobs_mc:glow_squid",
|
||||
"mobs_mc:salmon",
|
||||
"mobs_mc:tropical_fish",
|
||||
"mobs_mc:squid",
|
||||
"mobs_mc:zombie", -- todo: only drowned?
|
||||
"mobs_mc:baby_zombie",
|
||||
"mobs_mc:husk",
|
||||
"mobs_mc:baby_husk",
|
||||
"mobs_mc:guardian_elder",
|
||||
"mobs_mc:guardian",
|
||||
},
|
||||
"extra_mobs_cod",
|
||||
"extra_mobs_glow_squid",
|
||||
"extra_mobs_salmon",
|
||||
"extra_mobs_tropical_fish",
|
||||
"mobs_mc_squid"
|
||||
},
|
||||
runaway = true,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name = mobs_mc
|
||||
author = maikerumine
|
||||
description = Adds Minecraft-like monsters and animals.
|
||||
depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_core, mcl_util, mcl_entity_invs
|
||||
depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_core, mcl_util
|
||||
optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, doc_items, mcl_worlds
|
||||
|
|
|
@ -103,7 +103,6 @@ local skeleton = {
|
|||
return true
|
||||
end,
|
||||
ignited_by_sunlight = true,
|
||||
floats = 0,
|
||||
view_range = 16,
|
||||
fear_height = 4,
|
||||
attack_type = "dogshoot",
|
||||
|
|
|
@ -94,7 +94,6 @@ mcl_mobs.register_mob("mobs_mc:witherskeleton", {
|
|||
dogshoot_switch = 1,
|
||||
dogshoot_count_max =0.5,
|
||||
fear_height = 4,
|
||||
floats = 0,
|
||||
harmed_by_heal = true,
|
||||
fire_resistant = true,
|
||||
dealt_effect = {
|
||||
|
|
|
@ -1,31 +1,112 @@
|
|||
--License for code WTFPL and otherwise stated in readmes
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
||||
local MAPBLOCK_SIZE = 16 -- size for slime chunk logic
|
||||
local SEED_OFFSET = 362 -- module specific seed
|
||||
local world_seed = (minetest.get_mapgen_setting("seed") + SEED_OFFSET) % 4294967296
|
||||
-- slime density, where default N=10 is every 10th chunk
|
||||
local slime_ratio = tonumber(minetest.settings:get("slime_ratio")) or 10
|
||||
-- use 3D chunking instead of 2d chunks
|
||||
local slime_3d_chunks = minetest.settings:get_bool("slime_3d_chunks", false)
|
||||
-- maximum light level, for slimes in caves only, not magma/swamps
|
||||
local slime_max_light = (tonumber(minetest.settings:get("slime_max_light")) or minetest.LIGHT_MAX) + 1
|
||||
-- maximum light level for swamp spawning
|
||||
local swamp_light_max = 7
|
||||
-- maximum height to spawn in slime chunks
|
||||
local slime_chunk_spawn_max = mcl_worlds.layer_to_y(40)
|
||||
local MAPBLOCK_SIZE = 16
|
||||
|
||||
local floor = math.floor
|
||||
local max = math.max
|
||||
local seed = minetest.get_mapgen_setting("seed")
|
||||
|
||||
local slime_chunk_match
|
||||
local slime_chunk_spawn_max = mcl_worlds.layer_to_y(40)
|
||||
local x_modifier
|
||||
local z_modifier
|
||||
|
||||
local function split_by_char (inputstr, sep, limit)
|
||||
if sep == nil then
|
||||
sep = "%d"
|
||||
end
|
||||
local t = {}
|
||||
|
||||
local i = 0
|
||||
for str in string.gmatch(inputstr, "(["..sep.."])") do
|
||||
i = i --+ 1
|
||||
table.insert(t, tonumber(str))
|
||||
if limit and i >= limit then
|
||||
break
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--Seed: "16002933932875202103" == random seed
|
||||
--Seed: "1807191622654296300" == cheese
|
||||
--Seed: "1" = 1
|
||||
local function process_seed (seed)
|
||||
--minetest.log("seed: " .. seed)
|
||||
|
||||
local split_chars = split_by_char(tostring(seed), nil, 10)
|
||||
|
||||
slime_chunk_match = split_chars[1]
|
||||
x_modifier = split_chars[2]
|
||||
z_modifier = split_chars[3]
|
||||
|
||||
--minetest.log("x_modifier: " .. tostring(x_modifier))
|
||||
--minetest.log("z_modifier: " .. tostring(z_modifier))
|
||||
--minetest.log("slime_chunk_match: " .. tostring(slime_chunk_match))
|
||||
end
|
||||
|
||||
local processed = process_seed (seed)
|
||||
|
||||
|
||||
local function convert_to_chunk_value (co_ord, modifier)
|
||||
local converted = math.floor(math.abs(co_ord) / MAPBLOCK_SIZE)
|
||||
|
||||
if modifier then
|
||||
converted = (converted + modifier)
|
||||
end
|
||||
converted = converted % 10
|
||||
|
||||
--minetest.log("co_ord: " .. co_ord)
|
||||
--minetest.log("converted: " .. converted)
|
||||
return converted
|
||||
end
|
||||
|
||||
assert(convert_to_chunk_value(-16) == 1, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(-15) == 0, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(-1) == 0, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(0) == 0, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(1) == 0, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(15) == 0, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(16) == 1, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(31) == 1, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(32) == 2, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(1599) == 9, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(1600) == 0, "Incorrect convert_to_chunk_value result")
|
||||
|
||||
assert(convert_to_chunk_value(0,9) == 9, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(16,5) == 6, "Incorrect convert_to_chunk_value result")
|
||||
assert(convert_to_chunk_value(1599,4) == 3, "Incorrect convert_to_chunk_value result")
|
||||
|
||||
local function calculate_chunk_value (pos, x_mod, z_mod)
|
||||
local chunk_val = math.abs(convert_to_chunk_value(pos.x, x_mod) - convert_to_chunk_value(pos.z, z_mod)) % 10
|
||||
return chunk_val
|
||||
end
|
||||
|
||||
assert(calculate_chunk_value(vector.new(0,0,0)) == 0, "calculate_chunk_value failed")
|
||||
assert(calculate_chunk_value(vector.new(0,0,0), 1, 1) == 0, "calculate_chunk_value failed")
|
||||
assert(calculate_chunk_value(vector.new(0,0,0), 2, 1) == 1, "calculate_chunk_value failed")
|
||||
assert(calculate_chunk_value(vector.new(64,0,16)) == (4-1), "calculate_chunk_value failed")
|
||||
assert(calculate_chunk_value(vector.new(16,0,64)) == (3), "calculate_chunk_value failed")
|
||||
assert(calculate_chunk_value(vector.new(-160,0,-160)) == 0, "calculate_chunk_value failed")
|
||||
|
||||
local function is_slime_chunk(pos)
|
||||
if not pos then return end -- no position given
|
||||
if slime_ratio == 0 then return end -- no slime chunks
|
||||
if slime_ratio <= 1 then return true end -- slime everywhere
|
||||
local bpos = vector.new(floor(pos.x / MAPBLOCK_SIZE), slime_3d_chunks and floor(pos.y / MAPBLOCK_SIZE) or 0, floor(pos.z / MAPBLOCK_SIZE))
|
||||
return PcgRandom(minetest.hash_node_position(bpos) + world_seed):next(0,1e9)/1e9 * slime_ratio < 1
|
||||
if not pos then return end
|
||||
|
||||
local chunk_val = calculate_chunk_value (pos, x_modifier, z_modifier)
|
||||
local slime_chunk = chunk_val == slime_chunk_match
|
||||
|
||||
--minetest.log("x: " ..pos.x .. ", z:" .. pos.z)
|
||||
|
||||
--minetest.log("seed slime_chunk_match: " .. tostring(slime_chunk_match))
|
||||
--minetest.log("chunk_val: " .. tostring(chunk_val))
|
||||
--minetest.log("Is slime chunk: " .. tostring(slime_chunk))
|
||||
return slime_chunk
|
||||
end
|
||||
|
||||
local check_position = function (pos)
|
||||
return is_slime_chunk(pos)
|
||||
end
|
||||
|
||||
|
||||
-- Returns a function that spawns children in a circle around pos.
|
||||
-- To be used as on_die callback.
|
||||
-- self: mob reference
|
||||
|
@ -35,15 +116,19 @@ end
|
|||
-- eject_speed: Initial speed of child mob away from "mother" mob
|
||||
local spawn_children_on_die = function(child_mob, spawn_distance, eject_speed)
|
||||
return function(self, pos)
|
||||
eject_speed = eject_speed or 1
|
||||
local posadd, newpos, dir
|
||||
if not eject_speed then
|
||||
eject_speed = 1
|
||||
end
|
||||
local mndef = minetest.registered_nodes[minetest.get_node(pos).name]
|
||||
local mother_stuck = mndef and mndef.walkable
|
||||
local angle = math.random() * math.pi * 2
|
||||
local children = {}
|
||||
local spawn_count = math.random(2, 4)
|
||||
for i = 1, spawn_count do
|
||||
local dir = vector.new(math.cos(angle), 0, math.sin(angle))
|
||||
local newpos = pos + dir * spawn_distance
|
||||
dir = vector.new(math.cos(angle), 0, math.sin(angle))
|
||||
posadd = vector.normalize(dir) * spawn_distance
|
||||
newpos = pos + posadd
|
||||
-- If child would end up in a wall, use position of the "mother", unless
|
||||
-- the "mother" was stuck as well
|
||||
if not mother_stuck then
|
||||
|
@ -53,14 +138,12 @@ local spawn_children_on_die = function(child_mob, spawn_distance, eject_speed)
|
|||
eject_speed = eject_speed * 0.5
|
||||
end
|
||||
end
|
||||
local mob = mcl_mobs.spawn(newpos, child_mob)
|
||||
if mob then
|
||||
if not mother_stuck then
|
||||
mob:set_velocity(dir * eject_speed)
|
||||
end
|
||||
mob:set_yaw(angle - math.pi/2)
|
||||
table.insert(children, mob)
|
||||
local mob = minetest.add_entity(newpos, child_mob)
|
||||
if not mother_stuck then
|
||||
mob:set_velocity(dir * eject_speed)
|
||||
end
|
||||
mob:set_yaw(angle - math.pi/2)
|
||||
table.insert(children, mob)
|
||||
angle = angle + (math.pi*2) / spawn_count
|
||||
end
|
||||
-- If mother was murdered, children attack the killer after 1 second
|
||||
|
@ -79,12 +162,16 @@ local spawn_children_on_die = function(child_mob, spawn_distance, eject_speed)
|
|||
end
|
||||
end
|
||||
|
||||
-- two different rules, underground slime chunks and regular swamp spawning
|
||||
local swamp_light_max = 7
|
||||
|
||||
local function slime_spawn_check(pos, environmental_light, artificial_light, sky_light)
|
||||
local maxlight = swamp_light_max
|
||||
|
||||
if pos.y <= slime_chunk_spawn_max and is_slime_chunk(pos) then
|
||||
return max(artificial_light, sky_light) <= slime_max_light
|
||||
maxlight = minetest.LIGHT_MAX + 1
|
||||
end
|
||||
return max(artificial_light, sky_light) <= swamp_light_max
|
||||
|
||||
return math.max(artificial_light, sky_light) <= maxlight
|
||||
end
|
||||
|
||||
-- Slime
|
||||
|
@ -235,13 +322,13 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
cave_biomes,
|
||||
0,
|
||||
slime_max_light,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
1000,
|
||||
4,
|
||||
cave_min,
|
||||
cave_max,
|
||||
nil, nil, is_slime_chunk)
|
||||
nil, nil, check_position)
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:slime_tiny",
|
||||
|
@ -262,13 +349,13 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
cave_biomes,
|
||||
0,
|
||||
slime_max_light,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
1000,
|
||||
4,
|
||||
cave_min,
|
||||
cave_max,
|
||||
nil, nil, is_slime_chunk)
|
||||
nil, nil, check_position)
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:slime_small",
|
||||
|
@ -289,13 +376,13 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
cave_biomes,
|
||||
0,
|
||||
slime_max_light,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
1000,
|
||||
4,
|
||||
cave_min,
|
||||
cave_max,
|
||||
nil, nil, is_slime_chunk)
|
||||
nil, nil, check_position)
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:slime_big",
|
||||
|
@ -472,4 +559,3 @@ mcl_mobs:non_spawn_specific("mobs_mc:magma_cube_big","overworld",0, minetest.LIG
|
|||
mcl_mobs.register_egg("mobs_mc:slime_big", S("Slime"), "#52a03e", "#7ebf6d")
|
||||
|
||||
-- FIXME: add spawn eggs for small and tiny slimes and magma cubes
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ local spider = {
|
|||
curiosity = 10,
|
||||
head_yaw="z",
|
||||
collisionbox = {-0.7, -0.01, -0.7, 0.7, 0.89, 0.7},
|
||||
spawnbox = {-1.2, -0.01, -1.2, 1.2, 0.89, 1.2},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_spider.b3d",
|
||||
textures = {
|
||||
|
|
|
@ -7,13 +7,12 @@ local S = minetest.get_translator("mobs_mc")
|
|||
--###################
|
||||
|
||||
|
||||
local function get_texture(self, prev)
|
||||
local standing_on = minetest.registered_nodes[self.standing_on]
|
||||
-- TODO: we do not have access to param2 here (color palette index) yet
|
||||
local function get_texture(self)
|
||||
local on_name = self.standing_on
|
||||
local texture
|
||||
local texture_suff = ""
|
||||
if standing_on and (standing_on.walkable or standing_on.groups.liquid) then
|
||||
local tiles = standing_on.tiles
|
||||
if on_name and on_name ~= "air" then
|
||||
local tiles = minetest.registered_nodes[on_name].tiles
|
||||
if tiles then
|
||||
local tile = tiles[1]
|
||||
local color
|
||||
|
@ -26,7 +25,7 @@ local function get_texture(self, prev)
|
|||
texture = tile
|
||||
end
|
||||
if not color then
|
||||
color = minetest.colorspec_to_colorstring(standing_on.color)
|
||||
color = minetest.colorspec_to_colorstring(minetest.registered_nodes[on_name].color)
|
||||
end
|
||||
if color then
|
||||
texture_suff = "^[multiply:" .. color .. "^[hsl:0:0:20"
|
||||
|
@ -34,19 +33,14 @@ local function get_texture(self, prev)
|
|||
end
|
||||
end
|
||||
if not texture or texture == "" then
|
||||
-- try to keep last texture when, e.g., falling
|
||||
if prev and (not (not self.attack)) == (string.find(prev, "vl_mobs_stalker_overlay_angry.png") ~= nil) then
|
||||
return prev
|
||||
end
|
||||
texture = "vl_stalker_default.png"
|
||||
else
|
||||
texture = texture:gsub("([\\^:\\[])", "\\%1") -- escape texture modifiers
|
||||
texture = "(vl_stalker_default.png^[combine:16x24:0,0=(" .. texture .. "):0,16=(" .. texture .. ")" .. texture_suff .. ")"
|
||||
end
|
||||
texture = texture:gsub("([\\^:\\[])","\\%1") -- escape texture modifiers
|
||||
texture = "([combine:16x24:0,0=(" .. texture .. "):0,16=(" .. texture ..")".. texture_suff
|
||||
if self.attack then
|
||||
texture = texture .. "^vl_mobs_stalker_overlay_angry.png"
|
||||
texture = texture .. ")^vl_mobs_stalker_overlay_angry.png"
|
||||
else
|
||||
texture = texture .. "^vl_mobs_stalker_overlay.png"
|
||||
texture = texture .. ")^vl_mobs_stalker_overlay.png"
|
||||
end
|
||||
return texture
|
||||
end
|
||||
|
@ -138,7 +132,7 @@ mcl_mobs.register_mob("mobs_mc:stalker", {
|
|||
self:boom(mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
end
|
||||
end
|
||||
local new_texture = get_texture(self, self._stalker_texture)
|
||||
local new_texture = get_texture(self)
|
||||
if self._stalker_texture ~= new_texture then
|
||||
self.object:set_properties({textures={new_texture, "mobs_mc_empty.png"}})
|
||||
self._stalker_texture = new_texture
|
||||
|
|
|
@ -818,7 +818,7 @@ local function find_closest_bed (self)
|
|||
|
||||
if (owned_by and owned_by == self._id) then
|
||||
mcl_log("Clear as already owned by me.")
|
||||
bed_meta:set_string("villager", "")
|
||||
bed_meta:set_string("villager", nil)
|
||||
owned_by = nil
|
||||
end
|
||||
|
||||
|
@ -1049,18 +1049,14 @@ local function has_summon_participants(self)
|
|||
end
|
||||
|
||||
local function summon_golem(self)
|
||||
local pos = self.object:get_pos()
|
||||
local p1 = vector.offset(pos, -10, -10, -10)
|
||||
local p2 = vector.offset(pos, 10, 10, 10)
|
||||
local nn = minetest.find_nodes_in_area_under_air(p1, p2,{"group:solid","group:water"})
|
||||
while #nn > 0 do
|
||||
local n = table.remove_random_element(nn)
|
||||
n.y = n.y + 1
|
||||
|
||||
local summon = mcl_mobs.spawn(n, "mobs_mc:iron_golem")
|
||||
if summon then
|
||||
vector.offset(self.object:get_pos(),-10,-10,-10)
|
||||
local nn = minetest.find_nodes_in_area_under_air(vector.offset(self.object:get_pos(),-10,-10,-10),vector.offset(self.object:get_pos(),10,10,10),{"group:solid","group:water"})
|
||||
table.shuffle(nn)
|
||||
for _,n in pairs(nn) do
|
||||
local up = minetest.find_nodes_in_area(vector.offset(n,0,1,0),vector.offset(n,0,3,0),{"air"})
|
||||
if up and #up >= 3 then
|
||||
minetest.sound_play("mcl_portals_open_end_portal", {pos=n, gain=0.5, max_hear_distance = 16}, true)
|
||||
return summon
|
||||
return minetest.add_entity(vector.offset(n,0,1,0),"mobs_mc:iron_golem")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1283,7 +1279,7 @@ local function validate_jobsite(self)
|
|||
mcl_log("Jobsite far, so resettle: " .. tostring(resettle))
|
||||
if resettle then
|
||||
local m = minetest.get_meta(self._jobsite)
|
||||
m:set_string("villager", "")
|
||||
m:set_string("villager", nil)
|
||||
remove_job (self)
|
||||
return false
|
||||
end
|
||||
|
@ -1425,7 +1421,7 @@ local function validate_bed(self)
|
|||
mcl_log("Bed far, so resettle: " .. tostring(resettle))
|
||||
if resettle then
|
||||
mcl_log("Resettled. Ditch bed.")
|
||||
m:set_string("villager", "")
|
||||
m:set_string("villager", nil)
|
||||
self._bed = nil
|
||||
bed_valid = false
|
||||
return false
|
||||
|
@ -1435,7 +1431,7 @@ local function validate_bed(self)
|
|||
mcl_log("Player owner: " .. owned_by_player)
|
||||
if owned_by_player ~= "" then
|
||||
mcl_log("Player owns this. Villager won't take this.")
|
||||
m:set_string("villager", "")
|
||||
m:set_string("villager", nil)
|
||||
self._bed = nil
|
||||
bed_valid = false
|
||||
return false
|
||||
|
@ -2304,13 +2300,13 @@ mcl_mobs.register_mob("mobs_mc:villager", {
|
|||
local bed = self._bed
|
||||
if bed then
|
||||
local bed_meta = minetest.get_meta(bed)
|
||||
bed_meta:set_string("villager", "")
|
||||
bed_meta:set_string("villager", nil)
|
||||
mcl_log("Died, so bye bye bed")
|
||||
end
|
||||
local jobsite = self._jobsite
|
||||
if jobsite then
|
||||
local jobsite_meta = minetest.get_meta(jobsite)
|
||||
jobsite_meta:set_string("villager", "")
|
||||
jobsite_meta:set_string("villager", nil)
|
||||
mcl_log("Died, so bye bye jobsite")
|
||||
end
|
||||
|
||||
|
|
|
@ -55,16 +55,14 @@ mcl_mobs.register_mob("mobs_mc:evoker", {
|
|||
basepos.y = basepos.y + 1
|
||||
for i=1, r do
|
||||
local spawnpos = vector.add(basepos, minetest.yaw_to_dir(pr:next(0,360)))
|
||||
local vex = mcl_mobs.spawn(spawnpos, "mobs_mc:vex")
|
||||
if vex then
|
||||
local ent = vex:get_luaentity()
|
||||
local vex = minetest.add_entity(spawnpos, "mobs_mc:vex")
|
||||
local ent = vex:get_luaentity()
|
||||
|
||||
-- Mark vexes as summoned and start their life clock (they take damage it reaches 0)
|
||||
ent._summoned = true
|
||||
ent._lifetimer = pr:next(33, 108)
|
||||
-- Mark vexes as summoned and start their life clock (they take damage it reaches 0)
|
||||
ent._summoned = true
|
||||
ent._lifetimer = pr:next(33, 108)
|
||||
|
||||
table.insert(spawned_vexes[self],ent)
|
||||
end
|
||||
table.insert(spawned_vexes[self],ent)
|
||||
end
|
||||
end,
|
||||
passive = false,
|
||||
|
|
|
@ -134,7 +134,6 @@ mcl_mobs.register_mob("mobs_mc:villager_zombie", {
|
|||
end,
|
||||
sunlight_damage = 2,
|
||||
ignited_by_sunlight = true,
|
||||
floats = 0,
|
||||
view_range = 16,
|
||||
fear_height = 4,
|
||||
harmed_by_heal = true,
|
||||
|
|
|
@ -96,7 +96,6 @@ local zombie = {
|
|||
},
|
||||
ignited_by_sunlight = true,
|
||||
sunlight_damage = 2,
|
||||
floats = 0,
|
||||
view_range = 16,
|
||||
attack_type = "dogfight",
|
||||
harmed_by_heal = true,
|
||||
|
|
|
@ -19,6 +19,7 @@ local set_node = minetest.set_node
|
|||
local sound_play = minetest.sound_play
|
||||
local add_particlespawner = minetest.add_particlespawner
|
||||
local after = minetest.after
|
||||
local add_entity = minetest.add_entity
|
||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local get_item_group = minetest.get_item_group
|
||||
|
||||
|
@ -164,7 +165,7 @@ function lightning.strike_func(pos, pos2, objects)
|
|||
|
||||
-- Events caused by the lightning strike: Fire, damage, mob transformations, rare skeleton spawn
|
||||
|
||||
pos2.y = pos2.y + 1
|
||||
pos2.y = pos2.y + 1/2
|
||||
local skeleton_lightning = false
|
||||
if rng:next(1,100) <= 3 then
|
||||
skeleton_lightning = true
|
||||
|
@ -173,14 +174,14 @@ function lightning.strike_func(pos, pos2, objects)
|
|||
if get_node(pos2).name == "air" then
|
||||
-- Low chance for a lightning to spawn skeleton horse + skeletons
|
||||
if skeleton_lightning then
|
||||
mcl_mobs.spawn(pos2, "mobs_mc:skeleton_horse")
|
||||
add_entity(pos2, "mobs_mc:skeleton_horse")
|
||||
|
||||
local angle, posadd
|
||||
angle = math.random() * math.pi * 2
|
||||
for i=1,3 do
|
||||
posadd = { x=math.cos(angle),y=0,z=math.sin(angle) }
|
||||
posadd = vector.normalize(posadd)
|
||||
local mob = mcl_mobs.spawn(vector.add(pos2, posadd), "mobs_mc:skeleton")
|
||||
local mob = add_entity(vector.add(pos2, posadd), "mobs_mc:skeleton")
|
||||
if mob then
|
||||
mob:set_yaw(angle-math.pi/2)
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_void_damage
|
||||
author = Wuzzy
|
||||
description = Deal damage to entities stuck in the deep void
|
||||
depends = mcl_worlds, mcl_spawn
|
||||
depends = mcl_worlds
|
||||
|
|
|
@ -60,15 +60,13 @@ end
|
|||
-- set skybox based on time (uses skycolor api)
|
||||
function mcl_weather.rain.set_sky_box()
|
||||
if mcl_weather.state == "rain" then
|
||||
if mcl_weather.skycolor.current_layer_name() ~= "weather-pack-rain-sky" then
|
||||
mcl_weather.skycolor.add_layer(
|
||||
"weather-pack-rain-sky",
|
||||
{{r=0, g=0, b=0},
|
||||
{r=85, g=86, b=98},
|
||||
{r=135, g=135, b=151},
|
||||
{r=85, g=86, b=98},
|
||||
{r=0, g=0, b=0}})
|
||||
end
|
||||
mcl_weather.skycolor.add_layer(
|
||||
"weather-pack-rain-sky",
|
||||
{{r=0, g=0, b=0},
|
||||
{r=85, g=86, b=98},
|
||||
{r=135, g=135, b=151},
|
||||
{r=85, g=86, b=98},
|
||||
{r=0, g=0, b=0}})
|
||||
mcl_weather.skycolor.active = true
|
||||
for _, player in pairs(get_connected_players()) do
|
||||
player:set_clouds({color="#5D5D5FE8"})
|
||||
|
@ -157,7 +155,6 @@ function mcl_weather.rain.clear()
|
|||
mcl_weather.rain.remove_sound(player)
|
||||
mcl_weather.rain.remove_player(player)
|
||||
mcl_weather.remove_spawners_player(player)
|
||||
player:set_clouds({color="#FFF0EF"})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local NIGHT_VISION_RATIO = 0.45
|
||||
local DEBUG = false
|
||||
|
||||
-- Settings
|
||||
local minimum_update_interval = { 250e3 }
|
||||
|
@ -191,8 +190,8 @@ end
|
|||
|
||||
function skycolor_utils.convert_to_rgb(minval, maxval, current_val, colors)
|
||||
-- Clamp current_val to valid range
|
||||
current_val = math.max(minval, current_val)
|
||||
current_val = math.min(maxval, current_val)
|
||||
current_val = math.min(minval, current_val)
|
||||
current_val = math.max(maxval, current_val)
|
||||
|
||||
-- Rescale current_val from a number between minval and maxval to a number between 1 and #colors
|
||||
local scaled_value = (current_val - minval) / (maxval - minval) * (#colors - 1) + 1.0
|
||||
|
@ -200,7 +199,7 @@ function skycolor_utils.convert_to_rgb(minval, maxval, current_val, colors)
|
|||
-- Get the first color's values
|
||||
local index1 = math.floor(scaled_value)
|
||||
local color1 = colors[index1]
|
||||
local frac1 = 1.0 - (scaled_value - index1)
|
||||
local frac1 = scaled_value - index1
|
||||
|
||||
-- Get the second color's values
|
||||
local index2 = math.min(index1 + 1, #colors) -- clamp to maximum color index (will occur if index1 == #colors)
|
||||
|
@ -208,32 +207,11 @@ function skycolor_utils.convert_to_rgb(minval, maxval, current_val, colors)
|
|||
local color2 = colors[index2]
|
||||
|
||||
-- Interpolate between color1 and color2
|
||||
local res = {
|
||||
return {
|
||||
r = math.floor(frac1 * color1.r + frac2 * color2.r),
|
||||
g = math.floor(frac1 * color1.g + frac2 * color2.g),
|
||||
b = math.floor(frac1 * color1.b + frac2 * color2.b),
|
||||
}
|
||||
|
||||
if DEBUG then
|
||||
minetest.log(dump({
|
||||
minval = minval,
|
||||
maxval = maxval,
|
||||
current_val = current_val,
|
||||
colors = colors,
|
||||
res = res,
|
||||
scaled_value = scaled_value,
|
||||
|
||||
frac1 = frac1,
|
||||
index1 = index1,
|
||||
color1 = color1,
|
||||
|
||||
frac2 = frac2,
|
||||
index2 = index2,
|
||||
color2 = color2,
|
||||
}))
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
-- Simple getter. Either returns user given players list or get all connected players if none provided
|
||||
|
|
|
@ -40,21 +40,18 @@ function dimension_handlers.overworld(player, sky_data)
|
|||
end
|
||||
|
||||
-- Use overworld defaults
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.5)
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.15)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.27)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0.1)
|
||||
sky_data.sky = {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color or "#7BA4FF",
|
||||
day_horizon = day_color or "#C0D8FF",
|
||||
dawn_sky = dawn_color or "7BA4FF",
|
||||
dawn_horizon = dawn_color or "#C0D8FF",
|
||||
night_sky = night_color or "000000",
|
||||
night_horizon = night_color or "4A6790",
|
||||
fog_sun_tint = "#ff5f33",
|
||||
fog_moon_tint = nil,
|
||||
fog_tint_type = "custom",
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
}
|
||||
|
@ -78,15 +75,18 @@ function dimension_handlers.overworld(player, sky_data)
|
|||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.5)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.75)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0)
|
||||
table.update(sky_data.sky.sky_color,{
|
||||
day_sky = day_color or "#7BA4FF",
|
||||
day_horizon = day_color or "#C0D8FF",
|
||||
dawn_sky = dawn_color or "7BA4FF",
|
||||
dawn_horizon = dawn_color or "#C0D8FF",
|
||||
night_sky = night_color or "000000",
|
||||
night_horizon = night_color or "4A6790",
|
||||
fog_tint_type = "default",
|
||||
})
|
||||
sky_data.sky = {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
}
|
||||
sky_data.sun = {visible = false, sunrise_visible = false}
|
||||
sky_data.moon = {visible = false}
|
||||
sky_data.stars = {visible = false}
|
||||
|
@ -164,8 +164,7 @@ function dimension_handlers.nether(player, sky_data)
|
|||
end
|
||||
|
||||
function dimension_handlers.void(player, sky_data)
|
||||
sky_data.sky = {
|
||||
type = "plain",
|
||||
sky_data.sky = { type = "plain",
|
||||
base_color = "#000000",
|
||||
clouds = false,
|
||||
}
|
||||
|
|
|
@ -75,15 +75,13 @@ function mcl_weather.has_snow(pos)
|
|||
end
|
||||
|
||||
function mcl_weather.snow.set_sky_box()
|
||||
if mcl_weather.skycolor.current_layer_name() ~= "weather-pack-snow-sky" then
|
||||
mcl_weather.skycolor.add_layer(
|
||||
"weather-pack-snow-sky",
|
||||
{{r=0, g=0, b=0},
|
||||
{r=85, g=86, b=86},
|
||||
{r=135, g=135, b=135},
|
||||
{r=85, g=86, b=86},
|
||||
{r=0, g=0, b=0}})
|
||||
end
|
||||
mcl_weather.skycolor.add_layer(
|
||||
"weather-pack-snow-sky",
|
||||
{{r=0, g=0, b=0},
|
||||
{r=85, g=86, b=86},
|
||||
{r=135, g=135, b=135},
|
||||
{r=85, g=86, b=86},
|
||||
{r=0, g=0, b=0}})
|
||||
mcl_weather.skycolor.active = true
|
||||
for _, player in pairs(get_connected_players()) do
|
||||
player:set_clouds({color="#ADADADE8"})
|
||||
|
|
|
@ -23,15 +23,13 @@ minetest.register_globalstep(function(dtime)
|
|||
mcl_weather.rain.make_weather()
|
||||
|
||||
if mcl_weather.thunder.init_done == false then
|
||||
if mcl_weather.skycolor.current_layer_name() ~= "weather-pack-thunder-sky" then
|
||||
mcl_weather.skycolor.add_layer("weather-pack-thunder-sky", {
|
||||
{r=0, g=0, b=0},
|
||||
{r=40, g=40, b=40},
|
||||
{r=85, g=86, b=86},
|
||||
{r=40, g=40, b=40},
|
||||
{r=0, g=0, b=0},
|
||||
})
|
||||
end
|
||||
mcl_weather.skycolor.add_layer("weather-pack-thunder-sky", {
|
||||
{r=0, g=0, b=0},
|
||||
{r=40, g=40, b=40},
|
||||
{r=85, g=86, b=86},
|
||||
{r=40, g=40, b=40},
|
||||
{r=0, g=0, b=0},
|
||||
})
|
||||
mcl_weather.skycolor.active = true
|
||||
for _, player in pairs(get_connected_players()) do
|
||||
player:set_clouds({color="#3D3D3FE8"})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_death_messages
|
||||
author = 4Evergreen4
|
||||
description = Shows messages in chat when a player dies.
|
||||
depends = mcl_colors, mcl_damage
|
||||
depends = mcl_colors
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
## mcl_info
|
||||
An API to make custom entries in the VL debug hud.
|
||||
An api to make custom entries in the mcl2 debug hud.
|
||||
|
||||
### mcl_info.register_debug_field(name,defintion)
|
||||
Debug field defintion example:
|
||||
|
||||
```
|
||||
{
|
||||
level = 3,
|
||||
--show with debug level 3 and upwards
|
||||
|
@ -15,7 +13,6 @@ Debug field defintion example:
|
|||
-- It should output a string and determines
|
||||
-- the content of the debug field.
|
||||
}
|
||||
```
|
||||
|
||||
### mcl_info.registered_debug_fields
|
||||
Table the debug definitions are stored in. Do not modify this directly. If you need to overwrite a field just set it again with mcl_info.register_debug_field().
|
||||
|
|
|
@ -32,5 +32,4 @@ mcl_inventory.register_survival_inventory_tab({
|
|||
-- Returns true by default
|
||||
access = function(player)
|
||||
end,
|
||||
})
|
||||
```
|
||||
|
|
|
@ -418,18 +418,6 @@ minetest.register_on_joinplayer(function(player)
|
|||
end
|
||||
end)
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
local function is_touch_enabled(playername)
|
||||
-- Minetest < 5.7.0 support
|
||||
if not minetest.get_player_window_information then
|
||||
return false
|
||||
end
|
||||
local window = minetest.get_player_window_information(playername)
|
||||
-- Always return a boolean (not nil) to avoid false-negatives when
|
||||
-- comparing to a boolean later.
|
||||
return window and window.touch_controls or false
|
||||
end
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
function mcl_inventory.set_creative_formspec(player)
|
||||
local playername = player:get_player_name()
|
||||
|
@ -578,10 +566,8 @@ function mcl_inventory.set_creative_formspec(player)
|
|||
bg_img = "crafting_creative_inactive" .. button_bg_postfix[this_tab] .. ".png"
|
||||
end
|
||||
return table.concat({
|
||||
"style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=]",
|
||||
"style[" .. this_tab .. "_outer;border=false;bgimg=" .. bg_img ..
|
||||
";bgimg_pressed=" .. bg_img .. "]",
|
||||
"button[" .. offset[this_tab] .. ";1.5,1.44;" .. this_tab .. "_outer;]",
|
||||
"style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=;noclip=true]",
|
||||
"image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]",
|
||||
"item_image_button[" .. boffset[this_tab] .. ";1,1;" .. tab_icon[this_tab] .. ";" .. this_tab .. ";]",
|
||||
})
|
||||
end
|
||||
|
@ -591,21 +577,11 @@ function mcl_inventory.set_creative_formspec(player)
|
|||
caption = "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, filtername[name])) .. "]"
|
||||
end
|
||||
|
||||
local touch_enabled = is_touch_enabled(playername)
|
||||
players[playername].last_touch_enabled = touch_enabled
|
||||
|
||||
local formspec = table.concat({
|
||||
"formspec_version[6]",
|
||||
-- Original formspec height was 8.75, increased to include tab buttons.
|
||||
-- This avoids tab buttons going off-screen with high scaling values.
|
||||
"size[13,11.43]",
|
||||
-- Use as much space as possible on mobile - the tab buttons are a lot
|
||||
-- of padding already.
|
||||
touch_enabled and "padding[-0.015,-0.015]" or "",
|
||||
"size[13,8.75]",
|
||||
|
||||
"no_prepend[]", mcl_vars.gui_nonbg, mcl_vars.gui_bg_color,
|
||||
"background9[0,1.34;13,8.75;mcl_base_textures_background9.png;;7]",
|
||||
"container[0,1.34]",
|
||||
"style_type[image;noclip=true]",
|
||||
|
||||
-- Hotbar
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 7.375, 9, 1),
|
||||
|
@ -662,7 +638,6 @@ function mcl_inventory.set_creative_formspec(player)
|
|||
"set_focus[search;true]",
|
||||
})
|
||||
end
|
||||
formspec = formspec .. "container_end[]"
|
||||
if pagenum then formspec = formspec .. "p" .. tostring(pagenum) end
|
||||
player:set_inventory_formspec(formspec)
|
||||
end
|
||||
|
@ -680,54 +655,54 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
|
||||
local name = player:get_player_name()
|
||||
|
||||
if fields.blocks or fields.blocks_outer then
|
||||
if fields.blocks then
|
||||
if players[name].page == "blocks" then return end
|
||||
set_inv_page("blocks", player)
|
||||
page = "blocks"
|
||||
elseif fields.deco or fields.deco_outer then
|
||||
elseif fields.deco then
|
||||
if players[name].page == "deco" then return end
|
||||
set_inv_page("deco", player)
|
||||
page = "deco"
|
||||
elseif fields.redstone or fields.redstone_outer then
|
||||
elseif fields.redstone then
|
||||
if players[name].page == "redstone" then return end
|
||||
set_inv_page("redstone", player)
|
||||
page = "redstone"
|
||||
elseif fields.rail or fields.rail_outer then
|
||||
elseif fields.rail then
|
||||
if players[name].page == "rail" then return end
|
||||
set_inv_page("rail", player)
|
||||
page = "rail"
|
||||
elseif fields.misc or fields.misc_outer then
|
||||
elseif fields.misc then
|
||||
if players[name].page == "misc" then return end
|
||||
set_inv_page("misc", player)
|
||||
page = "misc"
|
||||
elseif fields.nix or fields.nix_outer then
|
||||
elseif fields.nix then
|
||||
set_inv_page("all", player)
|
||||
page = "nix"
|
||||
elseif fields.food or fields.food_outer then
|
||||
elseif fields.food then
|
||||
if players[name].page == "food" then return end
|
||||
set_inv_page("food", player)
|
||||
page = "food"
|
||||
elseif fields.tools or fields.tools_outer then
|
||||
elseif fields.tools then
|
||||
if players[name].page == "tools" then return end
|
||||
set_inv_page("tools", player)
|
||||
page = "tools"
|
||||
elseif fields.combat or fields.combat_outer then
|
||||
elseif fields.combat then
|
||||
if players[name].page == "combat" then return end
|
||||
set_inv_page("combat", player)
|
||||
page = "combat"
|
||||
elseif fields.mobs or fields.mobs_outer then
|
||||
elseif fields.mobs then
|
||||
if players[name].page == "mobs" then return end
|
||||
set_inv_page("mobs", player)
|
||||
page = "mobs"
|
||||
elseif fields.brew or fields.brew_outer then
|
||||
elseif fields.brew then
|
||||
if players[name].page == "brew" then return end
|
||||
set_inv_page("brew", player)
|
||||
page = "brew"
|
||||
elseif fields.matr or fields.matr_outer then
|
||||
elseif fields.matr then
|
||||
if players[name].page == "matr" then return end
|
||||
set_inv_page("matr", player)
|
||||
page = "matr"
|
||||
elseif fields.inv or fields.inv_outer then
|
||||
elseif fields.inv then
|
||||
if players[name].page == "inv" then return end
|
||||
page = "inv"
|
||||
elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then
|
||||
|
@ -843,19 +818,3 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
|
|||
player:get_inventory():set_stack("main", inventory_info.index, stack)
|
||||
end
|
||||
end)
|
||||
|
||||
-- This is necessary because get_player_window_information may return nil in
|
||||
-- on_joinplayer.
|
||||
-- (Also, Minetest plans to add support for toggling touchscreen mode in-game.)
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
|
||||
if minetest.is_creative_enabled(name) then
|
||||
local touch_enabled = is_touch_enabled(name)
|
||||
if touch_enabled ~= players[name].last_touch_enabled then
|
||||
mcl_inventory.set_creative_formspec(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -8,7 +8,7 @@ Show a hud message of `type` to player `player` with `data` as params.
|
|||
|
||||
The element will stay for the per-player param `stay` or `data.stay` (in gametick which is 1/20 second).
|
||||
|
||||
Here is a usage example:
|
||||
Here is a usage exemple:
|
||||
|
||||
```lua
|
||||
--show a title in the HUD with minecraft color "gold"
|
||||
|
@ -35,7 +35,7 @@ Basicaly run `mcl_title.remove(player, type)` for every type.
|
|||
|
||||
## mcl_title.params_set(player, params)
|
||||
|
||||
Allow mods to set `stay` and upcoming `fadeIn`/`fadeOut` params.
|
||||
Allow mods to set `stay` and upcomming `fadeIn`/`fadeOut` params.
|
||||
|
||||
```lua
|
||||
mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field will stay during 30s (600/20)
|
||||
|
@ -43,8 +43,8 @@ mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field
|
|||
|
||||
## mcl_title.params_get(player)
|
||||
|
||||
Get `stay` and upcoming `fadeIn` and `fadeOut` params of a player as a table.
|
||||
Get `stay` and upcomming `fadeIn` and `fadeOut` params of a player as a table.
|
||||
|
||||
```lua
|
||||
mcl_title.params_get(player)
|
||||
```
|
||||
```
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_title
|
||||
description = Add an API to add in HUD title
|
||||
depends = mcl_colors, mcl_util
|
||||
description = Add an API to add in HUD title
|
||||
depends = mcl_colors
|
||||
author = AFCMS
|
|
@ -1,3 +1,3 @@
|
|||
name = mesecons_button
|
||||
depends = mesecons, mesecons_mvps
|
||||
depends = mesecons
|
||||
optional_depends = doc
|
||||
|
|
|
@ -119,7 +119,7 @@ mcl_armor.register_set({
|
|||
end,
|
||||
},
|
||||
|
||||
--this is used to generate automaticaly armor crafts based on each element type following the regular minecraft pattern
|
||||
--this is used to generate automaticaly armor crafts based on each element type folowing the regular minecraft pattern
|
||||
--if set to nil no craft will be added
|
||||
craft_material = "mcl_mobitems:leather",
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
--- Copyright (C) 2022 - 2023, Michieal. See License.txt
|
||||
|
||||
-- CONSTS
|
||||
local DOUBLE_DROP_CHANCE = 8
|
||||
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
|
||||
-- "BAMBOO" goes here.
|
||||
local BAMBOO = "mcl_bamboo:bamboo"
|
||||
local BAMBOO_ENDCAP_NAME = "mcl_bamboo:bamboo_endcap"
|
||||
local BAMBOO_PLANK = BAMBOO .. "_plank"
|
||||
|
@ -13,7 +16,7 @@ local BAMBOO_PLANK = BAMBOO .. "_plank"
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local node_sound = mcl_sounds.node_sound_wood_defaults()
|
||||
local pr = PseudoRandom((os.time() + 15766) * 12)
|
||||
local pr = PseudoRandom((os.time() + 15766) * 12) -- switched from math.random() to PseudoRandom because the random wasn't very random.
|
||||
|
||||
local on_rotate
|
||||
if minetest.get_modpath("screwdriver") then
|
||||
|
@ -28,16 +31,38 @@ local bamboo_def = {
|
|||
paramtype = "light",
|
||||
groups = {handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3},
|
||||
sounds = node_sound,
|
||||
drop = BAMBOO,
|
||||
|
||||
drop = {
|
||||
max_items = 1,
|
||||
-- From the API:
|
||||
-- max_items: Maximum number of item lists to drop.
|
||||
-- The entries in 'items' are processed in order. For each:
|
||||
-- Item filtering is applied, chance of drop is applied, if both are
|
||||
-- successful the entire item list is dropped.
|
||||
-- Entry processing continues until the number of dropped item lists
|
||||
-- equals 'max_items'.
|
||||
-- Therefore, entries should progress from low to high drop chance.
|
||||
items = {
|
||||
-- Examples:
|
||||
{
|
||||
-- 1 in DOUBLE_DROP_CHANCE chance of dropping.
|
||||
-- Default rarity is '1'.
|
||||
rarity = DOUBLE_DROP_CHANCE,
|
||||
items = {BAMBOO .. " 2"},
|
||||
},
|
||||
{
|
||||
-- 1 in 1 chance of dropping. (Note: this means that it will drop 100% of the time.)
|
||||
-- Default rarity is '1'.
|
||||
rarity = 1,
|
||||
items = {BAMBOO},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
inventory_image = "mcl_bamboo_bamboo_shoot.png",
|
||||
wield_image = "mcl_bamboo_bamboo_shoot.png",
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
return mcl_bamboo.grow_bamboo(pos, true)
|
||||
end,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
|
@ -61,6 +86,7 @@ local bamboo_def = {
|
|||
on_rotate = on_rotate,
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
|
||||
if not pointed_thing then
|
||||
return itemstack
|
||||
end
|
||||
|
@ -215,6 +241,9 @@ local bamboo_def = {
|
|||
if node_above and ((bamboo_node and bamboo_node > 0) or node_above.name == BAMBOO_ENDCAP_NAME) then
|
||||
minetest.remove_node(new_pos)
|
||||
minetest.sound_play(node_sound.dug, sound_params, true)
|
||||
if pr:next(1, DOUBLE_DROP_CHANCE) == 1 then
|
||||
minetest.add_item(new_pos, istack)
|
||||
end
|
||||
minetest.add_item(new_pos, istack)
|
||||
end
|
||||
end,
|
||||
|
@ -224,12 +253,10 @@ minetest.register_node(BAMBOO, bamboo_def)
|
|||
local bamboo_top = table.copy(bamboo_def)
|
||||
bamboo_top.groups = {not_in_creative_inventory = 1, handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3}
|
||||
bamboo_top.tiles = {"mcl_bamboo_endcap.png"}
|
||||
|
||||
-- bamboo_top.drawtype = "plantlike_rooted" --"plantlike"
|
||||
bamboo_top.drawtype = "plantlike"
|
||||
bamboo_top.paramtype2 = "meshoptions"
|
||||
bamboo_top.param2 = 2
|
||||
bamboo_top.waving = 2
|
||||
bamboo_top.drawtype = "plantlike_rooted" --"plantlike"
|
||||
--bamboo_top.paramtype2 = "meshoptions"
|
||||
--bamboo_top.param2 = 2
|
||||
-- bamboo_top.waving = 2
|
||||
bamboo_top.special_tiles = {{name = "mcl_bamboo_endcap.png"}}
|
||||
bamboo_top.nodebox = nil
|
||||
bamboo_top.selection_box = nil
|
||||
|
|
|
@ -9,6 +9,8 @@ local SIDE_SCAFFOLDING = false
|
|||
local SIDE_SCAFFOLD_NAME = "mcl_bamboo:scaffolding_horizontal"
|
||||
-- ---------------------------------------------------------------------------
|
||||
local SCAFFOLDING_NAME = "mcl_bamboo:scaffolding"
|
||||
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
|
||||
-- "BAMBOO" goes here.
|
||||
local BAMBOO = "mcl_bamboo:bamboo"
|
||||
local BAMBOO_PLANK = BAMBOO .. "_plank"
|
||||
|
||||
|
|
|
@ -44,10 +44,6 @@ mcl_bamboo.bamboo_index = {
|
|||
"mcl_bamboo:bamboo_2",
|
||||
"mcl_bamboo:bamboo_3",
|
||||
}
|
||||
mcl_bamboo.bamboo_set = {}
|
||||
for _,key in pairs(mcl_bamboo.bamboo_index) do
|
||||
mcl_bamboo.bamboo_set[key] = true
|
||||
end
|
||||
|
||||
function mcl_bamboo.is_bamboo(node_name)
|
||||
local index = table.indexof(mcl_bamboo.bamboo_index, node_name)
|
||||
|
@ -78,7 +74,7 @@ function mcl_bamboo.break_orphaned(pos)
|
|||
local node_name = node_below.name
|
||||
|
||||
-- short circuit checks.
|
||||
if node_name == "ignore" or mcl_bamboo.is_dirt(node_name) or mcl_bamboo.is_bamboo(node_name) or mcl_bamboo.is_bamboo(minetest.get_node(pos).name) == false then
|
||||
if mcl_bamboo.is_dirt(node_name) or mcl_bamboo.is_bamboo(node_name) or mcl_bamboo.is_bamboo(minetest.get_node(pos).name) == false then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -98,84 +94,172 @@ end
|
|||
--]]
|
||||
|
||||
function mcl_bamboo.grow_bamboo(pos, bonemeal_applied)
|
||||
local log = mcl_bamboo.mcl_log
|
||||
local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0))
|
||||
log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied))
|
||||
mcl_bamboo.mcl_log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied))
|
||||
|
||||
if not bonemeal_applied then
|
||||
-- Only allow natural growth at the top of the bamboo
|
||||
if mcl_bamboo.is_bamboo(node_above.name) ~= false then return false end
|
||||
|
||||
-- Don't perform natual growth in low light
|
||||
if minetest.get_node_light(pos) < 8 then return false end
|
||||
if not bonemeal_applied and mcl_bamboo.is_bamboo(node_above.name) ~= false then
|
||||
return false -- short circuit this function if we're trying to grow (std) the bamboo and it's not the top shoot.
|
||||
end
|
||||
|
||||
-- Determine the location of soil
|
||||
local soil_pos
|
||||
soil_pos,a,b = mcl_util.trace_nodes(pos, -1, mcl_bamboo.bamboo_set, BAMBOO_MAX_HEIGHT - 1)
|
||||
|
||||
-- No soil found, return false so that bonemeal isn't used
|
||||
if not soil_pos then return false end
|
||||
log("Grow bamboo; soil found. ")
|
||||
|
||||
-- Find the first bamboo shoot and retrieve data about it
|
||||
local first_shoot = vector.offset(soil_pos, 0, 1, 0)
|
||||
local first_shoot_meta = minetest.get_meta(first_shoot)
|
||||
|
||||
-- Get or initialize bamboo height
|
||||
local height = (first_shoot_meta and first_shoot_meta:get_int("height", -1)) or -1
|
||||
if height == -1 then
|
||||
height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1)
|
||||
first_shoot_meta:set_int("height", height)
|
||||
end
|
||||
log("Grow bamboo; height: " .. height)
|
||||
|
||||
-- Locate the bamboo tip
|
||||
local bamboo_tip,actual_height,bamboo_tip_node = mcl_util.trace_nodes(first_shoot, 1, mcl_bamboo.bamboo_set, height - 1)
|
||||
log("Current height: "..tostring(actual_height))
|
||||
|
||||
-- Short circuit growth if the bamboo is already finished growing
|
||||
if not bamboo_tip or not actual_height or actual_height >= height then
|
||||
log("Bamboo is already as large as it can grow")
|
||||
if minetest.get_node_light(pos) < 8 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Now that we are actually going to add nodes, initialize some more information
|
||||
local first_shoot_node_name = minetest.get_node(first_shoot).name
|
||||
-- variables used in more than one spot.
|
||||
local first_shoot
|
||||
local chk_pos
|
||||
local soil_pos
|
||||
local node_name = ""
|
||||
local dist = 0
|
||||
local node_below
|
||||
-- -------------------
|
||||
|
||||
-- If applying bonemeal, randomly grow two segments instead of one
|
||||
local grow_amount = 1
|
||||
mcl_bamboo.mcl_log("Grow bamboo; checking for soil: ")
|
||||
-- the soil node below the bamboo.
|
||||
for py = -1, BAMBOO_SOIL_DIST, -1 do
|
||||
chk_pos = vector.offset(pos, 0, py, 0)
|
||||
node_name = minetest.get_node(chk_pos).name
|
||||
if mcl_bamboo.is_dirt(node_name) then
|
||||
soil_pos = chk_pos
|
||||
break
|
||||
end
|
||||
if mcl_bamboo.is_bamboo(node_name) == false then
|
||||
break
|
||||
end
|
||||
end
|
||||
-- requires knowing where the soil node is.
|
||||
if soil_pos == nil then
|
||||
return false -- returning false means don't use up the bonemeal.
|
||||
end
|
||||
|
||||
mcl_bamboo.mcl_log("Grow bamboo; soil found. ")
|
||||
local grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
||||
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
||||
grow_amount = rand(1, GROW_DOUBLE_CHANCE) -- because yeah, not truly random, or even a good prng.
|
||||
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
||||
local init_height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1)
|
||||
mcl_bamboo.mcl_log("Grow bamboo; random height: " .. init_height)
|
||||
|
||||
node_name = ""
|
||||
|
||||
-- update: add randomized max height to first node's meta data.
|
||||
first_shoot = vector.offset(soil_pos, 0, 1, 0)
|
||||
local meta = minetest.get_meta(first_shoot)
|
||||
node_below = minetest.get_node(first_shoot).name
|
||||
|
||||
mcl_bamboo.mcl_log("Grow bamboo; checking height meta ")
|
||||
-- check the meta data for the first node, to see how high to make the stalk.
|
||||
if not meta then
|
||||
-- if no metadata, set the metadata!!!
|
||||
meta:set_int("height", init_height)
|
||||
end
|
||||
local height = meta:get_int("height", -1)
|
||||
mcl_bamboo.mcl_log("Grow bamboo; meta-height: " .. height)
|
||||
if height <= 10 then
|
||||
height = init_height
|
||||
meta:set_int("height", init_height)
|
||||
end
|
||||
|
||||
mcl_bamboo.mcl_log("Grow bamboo; height: " .. height)
|
||||
|
||||
-- Bonemeal: Grows the bamboo by 1-2 stems. (per the minecraft wiki.)
|
||||
if bonemeal_applied then
|
||||
local rng = PcgRandom(minetest.hash_node_position(pos) + minetest.get_us_time())
|
||||
if rng:next(1, GROW_DOUBLE_CHANGE) == 1 then
|
||||
grow_amount = 2
|
||||
-- handle applying bonemeal.
|
||||
for py = 1, BAM_MAX_HEIGHT_TOP do
|
||||
-- find the top node of bamboo.
|
||||
chk_pos = vector.offset(pos, 0, py, 0)
|
||||
node_name = minetest.get_node(chk_pos).name
|
||||
dist = vector.distance(soil_pos, chk_pos)
|
||||
if mcl_bamboo.is_bamboo(node_name) == false or node_name == BAMBOO_ENDCAP_NAME then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
|
||||
|
||||
if node_name == BAMBOO_ENDCAP_NAME then
|
||||
-- prevent overgrowth
|
||||
return false
|
||||
end
|
||||
|
||||
-- check to see if we have a full stalk of bamboo.
|
||||
if dist >= height - 1 then
|
||||
if dist == height - 1 then
|
||||
-- equals top of the stalk before the cap
|
||||
if node_name == "air" then
|
||||
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap")
|
||||
minetest.set_node(vector.offset(chk_pos, 0, 1, 0), { name = BAMBOO_ENDCAP_NAME })
|
||||
return true -- returning true means use up the bonemeal.
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
-- okay, we're higher than the end cap, fail out.
|
||||
return false -- returning false means don't use up the bonemeal.
|
||||
end
|
||||
end
|
||||
|
||||
-- and now, the meat of the section... add bamboo to the stalk.
|
||||
-- at this point, we should be lower than the generated maximum height. ~ about height -2 or lower.
|
||||
if dist <= height - 2 then
|
||||
if node_name == "air" then
|
||||
-- here we can check to see if we can do up to 2 bamboo shoots onto the stalk
|
||||
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
|
||||
minetest.set_node(chk_pos, { name = node_below })
|
||||
-- handle growing a second node.
|
||||
if grow_amount == 2 then
|
||||
chk_pos = vector.offset(chk_pos, 0, 1, 0)
|
||||
if minetest.get_node(chk_pos).name == "air" then
|
||||
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
|
||||
minetest.set_node(chk_pos, { name = node_below })
|
||||
end
|
||||
end
|
||||
return true -- exit out with a success. We've added 1-2 nodes, per the wiki.
|
||||
end
|
||||
end
|
||||
end
|
||||
log("Growing up to "..grow_amount.." segments")
|
||||
|
||||
-- Perform bamboo growth
|
||||
for i = 1,grow_amount do
|
||||
-- Check for air to grow into
|
||||
local bamboo_tip_node = minetest.get_node(bamboo_tip)
|
||||
if not bamboo_tip_node or bamboo_tip_node.name ~= "air" then
|
||||
-- Something is blocking growth, stop and signal that use bonemeal has been used if at least on segment has grown
|
||||
return i ~= 1
|
||||
-- Non-Bonemeal growth.
|
||||
for py = 1, BAM_MAX_HEIGHT_TOP do
|
||||
-- Find the topmost node above the stalk, and check it for "air"
|
||||
chk_pos = vector.offset(pos, 0, py, 0)
|
||||
node_below = minetest.get_node(pos).name
|
||||
node_name = minetest.get_node(chk_pos).name
|
||||
dist = vector.distance(soil_pos, chk_pos)
|
||||
|
||||
if node_name ~= "air" and mcl_bamboo.is_bamboo(node_name) == false then
|
||||
break
|
||||
end
|
||||
|
||||
if actual_height + 1 == height then
|
||||
-- This is the end cap
|
||||
minetest.set_node(bamboo_tip, { name = BAMBOO_ENDCAP_NAME })
|
||||
return true
|
||||
else
|
||||
-- This isn't the end cap, add a bamboo segment
|
||||
minetest.set_node(bamboo_tip, { name = first_shoot_node_name })
|
||||
actual_height = actual_height + 1
|
||||
-- stop growing check. ie, handle endcap placement.
|
||||
if dist >= height - 1 then
|
||||
local above_node_name = minetest.get_node(vector.offset(chk_pos, 0, 1, 0)).name
|
||||
if node_name == "air" and above_node_name == "air" then
|
||||
if height - 1 == dist then
|
||||
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap")
|
||||
minetest.set_node(chk_pos, { name = BAMBOO_ENDCAP_NAME })
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
bamboo_tip = vector.offset(bamboo_tip, 0, 1, 0)
|
||||
-- handle regular node placement.
|
||||
-- find the air node above the top shoot. place a node. And then, if short enough,
|
||||
-- check for second node placement.
|
||||
if node_name == "air" then
|
||||
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
|
||||
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
|
||||
minetest.set_node(chk_pos, { name = node_below })
|
||||
-- handle growing a second node. (1 in 32 chance.)
|
||||
if grow_amount == 2 and dist <= height - 2 then
|
||||
chk_pos = vector.offset(chk_pos, 0, 1, 0)
|
||||
if minetest.get_node(chk_pos).name == "air" then
|
||||
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
|
||||
minetest.set_node(chk_pos, { name = node_below })
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Add Groups function, courtesy of Warr1024.
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
-- LOCALS
|
||||
local modname = minetest.get_current_modname()
|
||||
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
|
||||
-- "BAMBOO" goes here.
|
||||
local BAMBOO = "mcl_bamboo:bamboo"
|
||||
|
||||
mcl_bamboo = {}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
--- These are all of the fuel recipes and all of the crafting recipes, consolidated into one place.
|
||||
--- Copyright (C) 2022 - 2023, Michieal. See License.txt
|
||||
|
||||
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
|
||||
-- "BAMBOO" goes here.
|
||||
local BAMBOO = "mcl_bamboo:bamboo"
|
||||
local BAMBOO_PLANK = BAMBOO .. "_plank"
|
||||
-- Craftings
|
||||
|
|
|
@ -2,4 +2,4 @@ name = mcl_beds
|
|||
author = BlockMen
|
||||
description =
|
||||
depends = playerphysics
|
||||
optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecons, mesecons_mvps
|
||||
optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecons
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
# Bone meal API
|
||||
Bonemealing callbacks and particle functions.
|
||||
|
||||
|
||||
## _on_bone_meal(itemstack, placer, pointed_thing)
|
||||
The bone meal API provides a callback definition that nodes can use to
|
||||
register a handler that is executed when a bone meal item is used on it.
|
||||
|
||||
Nodes that wish to use the bone meal API should in their node registration
|
||||
define a callback handler named `_on_bone_meal`.
|
||||
|
||||
Note that by registering the callback handler, the node declares that bone
|
||||
meal can be used on it and as a result, when the user is not in creative
|
||||
mode, the used bone meal is spent and taken from the itemstack passed to
|
||||
the `on_place()` handler of the bone meal item used regardless of whether
|
||||
the bone meal had an effect on the node and regardless of the result of
|
||||
the callback handler.
|
||||
|
||||
It is for all intents and purposes up to the callback defined in the node to
|
||||
decide how to handle the specific effect that bone meal has on that node.
|
||||
|
||||
The `_on_bone_meal` callback handler is a
|
||||
|
||||
`function(itemstack, placer, pointed_thing)`
|
||||
|
||||
Its arguments are:
|
||||
* `itemstack`: the stack of bonem eal being applied
|
||||
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
|
||||
* `pointed_thing`: exact pointing location (see Minetest API), where the
|
||||
bone meal is applied
|
||||
|
||||
The return value of the handler function indicates if the bonemealing had
|
||||
its intended effect. If `true`, 'bone meal particles' are spawned at the
|
||||
position of the bonemealed node.
|
||||
|
||||
The `on_place` code in the bone meal item will spawn bone meal particles and
|
||||
decrease the bone meal itemstack if the handler returned `true` and the
|
||||
`placer` is not in creative mode.
|
||||
|
||||
|
||||
## mcl_bone_meal.add_bone_meal_particle(pos, def)
|
||||
Spawns standard or custom bone meal particles.
|
||||
* `pos`: position, is ignored if you define def.minpos and def.maxpos
|
||||
* `def`: (optional) particle definition; see minetest.add_particlespawner()
|
||||
for more details.
|
||||
|
||||
## mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
|
||||
For use in on_rightclick handlers that need support bone meal processing in addition
|
||||
to other behaviors. Before calling, verify that the player is wielding bone meal.
|
||||
* `itemstack`: The stack of bone meal being used
|
||||
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
|
||||
* `pointed_thing`: exact pointing location (see Minetest API), where the
|
||||
bone meal is applied
|
||||
|
||||
Returns itemstack with one bone meal consumed if not in creative mode.
|
||||
|
||||
# Legacy API
|
||||
The bone meal API also provides a legacy compatibility function. This
|
||||
function is not meant to be continued and callers should migrate to the
|
||||
newer bonemealing API.
|
||||
|
||||
## mcl_bone_meal.register_on_bone_meal_apply(function(pointed_thing, placer))
|
||||
Called when the bone meal is applied anywhere.
|
||||
* `pointed_thing`: exact pointing location (see Minetest API), where the
|
||||
bone meal is applied
|
||||
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
|
||||
This function is deprecated and will be removed at some time in the future.
|
||||
Bone meal is not consumed unless the provided function returns true.
|
||||
|
||||
## mcl_dye.add_bone_meal_particle(pos, def)
|
||||
## mcl_dye.register_on_bone_meal_apply(function(pointed_thing, user))
|
||||
These shims in mcl_dye that point to corresponding legacy compatibility
|
||||
functions in mcl_bone_meal remain for legacy callers that have not yet been
|
||||
updated to the new API. These shims will be removed at some time in the
|
||||
future.
|
|
@ -1,156 +0,0 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local longdesc = S(
|
||||
"Bone meal is a white dye and also useful as a fertilizer to " ..
|
||||
"speed up the growth of many plants."
|
||||
)
|
||||
local usagehelp = S(
|
||||
"Rightclick a sheep to turn its wool white. Rightclick a plant " ..
|
||||
"to speed up its growth. Note that not all plants can be " ..
|
||||
"fertilized like this. When you rightclick a grass block, tall " ..
|
||||
"grass and flowers will grow all over the place."
|
||||
)
|
||||
|
||||
mcl_bone_meal = {}
|
||||
|
||||
-- Bone meal particle API:
|
||||
|
||||
--- Spawns bone meal particles.
|
||||
-- pos: where the particles spawn
|
||||
-- def: particle spawner parameters, see minetest.add_particlespawner() for
|
||||
-- details on these parameters.
|
||||
--
|
||||
function mcl_bone_meal.add_bone_meal_particle(pos, def)
|
||||
def = def or {}
|
||||
minetest.add_particlespawner({
|
||||
amount = def.amount or 10,
|
||||
time = def.time or 0.1,
|
||||
minpos = def.minpos or vector.subtract(pos, 0.5),
|
||||
maxpos = def.maxpos or vector.add(pos, 0.5),
|
||||
minvel = def.minvel or vector.new(-0.01, 0.01, -0.01),
|
||||
maxvel = def.maxvel or vector.new(0.01, 0.01, 0.01),
|
||||
minacc = def.minacc or vector.new(0, 0, 0),
|
||||
maxacc = def.maxacc or vector.new(0, 0, 0),
|
||||
minexptime = def.minexptime or 1,
|
||||
maxexptime = def.maxexptime or 4,
|
||||
minsize = def.minsize or 0.7,
|
||||
maxsize = def.maxsize or 2.4,
|
||||
texture = "mcl_particles_bonemeal.png^[colorize:#00EE00:125",
|
||||
glow = def.glow or 1,
|
||||
})
|
||||
end
|
||||
|
||||
-- Begin legacy bone meal API.
|
||||
--
|
||||
-- Compatibility code for legacy users of the old bone meal API.
|
||||
-- This code will be removed at some time in the future.
|
||||
--
|
||||
mcl_bone_meal.bone_meal_callbacks = {}
|
||||
|
||||
-- Shims for the old API are still available in mcl_dye and defer to
|
||||
-- the real functions in mcl_bone_meal.
|
||||
--
|
||||
function mcl_bone_meal.register_on_bone_meal_apply(func)
|
||||
minetest.log("warning", "register_on_bone_meal_apply(func) is deprecated. Read mcl_bone_meal/API.md!")
|
||||
local lines = string.split(debug.traceback(),"\n")
|
||||
for _,line in ipairs(lines) do
|
||||
minetest.log("warning",line)
|
||||
end
|
||||
table.insert(mcl_bone_meal.bone_meal_callbacks, func)
|
||||
end
|
||||
|
||||
-- Legacy registered users of the old API are handled through this function.
|
||||
--
|
||||
local function legacy_apply_bone_meal(pointed_thing, placer)
|
||||
-- Legacy API support
|
||||
local callbacks = mcl_bone_meal.bone_meal_callbacks
|
||||
for i = 1,#callbacks do
|
||||
if callbacks[i](pointed_thing, placer) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
-- End legacy bone meal API
|
||||
|
||||
function mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
|
||||
local positions = {pointed_thing.under, pointed_thing.above}
|
||||
for i = 1,2 do
|
||||
local pos = positions[i]
|
||||
|
||||
-- Check protection
|
||||
if mcl_util.check_area_protection(pos, pointed_thing.above, placer) then return false end
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
local success = false
|
||||
local consume
|
||||
|
||||
-- If the pointed node can be bonemealed, let it handle the processing.
|
||||
if ndef and ndef._on_bone_meal then
|
||||
success = ndef._on_bone_meal(itemstack, placer, {under = pos, above = vector.offset(pos, 0, 1, 0)})
|
||||
consume = true
|
||||
else
|
||||
-- Otherwise try the legacy API.
|
||||
success = legacy_apply_bone_meal(pointed_thing, placer)
|
||||
consume = success
|
||||
end
|
||||
|
||||
-- Take the item
|
||||
if consume then
|
||||
-- Particle effects
|
||||
mcl_bone_meal.add_bone_meal_particle(pos)
|
||||
|
||||
if not placer or not minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end
|
||||
|
||||
if success then return itemstack end
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end
|
||||
|
||||
minetest.register_craftitem("mcl_bone_meal:bone_meal", {
|
||||
description = S("Bone Meal"),
|
||||
_tt_help = S("Speeds up plant growth"),
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usagehelp,
|
||||
inventory_image = "mcl_bone_meal.png",
|
||||
groups = {craftitem=1},
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
local node = minetest.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
|
||||
-- Use pointed node's on_rightclick function first, if present.
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
if ndef and ndef.on_rightclick then
|
||||
local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pointed_thing)
|
||||
if new_stack and new_stack ~= itemstack then return new_stack end
|
||||
end
|
||||
end
|
||||
|
||||
return mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
|
||||
end,
|
||||
_on_dispense = function(itemstack, pos, droppos, dropnode, dropdir)
|
||||
local pointed_thing
|
||||
if dropnode.name == "air" then
|
||||
pointed_thing = {above = droppos, under = vector.offset(droppos, 0, -1 ,0)}
|
||||
else
|
||||
pointed_thing = {above = pos, under = droppos}
|
||||
end
|
||||
|
||||
return mcl_bone_meal.use_bone_meal(itemstack, nil, pointed_thing)
|
||||
end,
|
||||
_dispense_into_walkable = true
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_bone_meal:bone_meal 3",
|
||||
recipe = {{"mcl_mobitems:bone"}},
|
||||
})
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=Knochenmehl
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Knochenmehl ist ein weißer Farbstoff und auch nützlich als Dünger, um das Wachstum vieler Pflanzen zu beschleunigen.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Rechtsklicken Sie auf ein Schaf, um die Wolle weiß einzufärben. Rechtsklicken Sie auf eine Pflanze, um ihr Wachstum zu beschleunigen. Beachten Sie, dass nicht alle Pflanzen darauf ansprechen. Benutzen Sie es auf einem Grasblock, wächst viel hohes Gras und vielleicht auch ein paar Blumen.
|
||||
Speeds up plant growth=Beschleunigt Pflanzenwachstum
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=Harina de hueso
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La harina de hueso es un tinte blanco y también es útil como fertilizante para acelerar el crecimiento de muchas plantas.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=RHaga clic derecho en una oveja para volver su lana blanca. Haga clic derecho en una planta para acelerar su crecimiento. Tenga en cuenta que no todas las plantas pueden ser fertilizadas de esta manera. Cuando haces clic derecho en un bloque de hierba, crecerán hierba alta y flores por todo el lugar.
|
||||
Speeds up plant growth=Acelera el crecimiento de las plantas
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=Farine d'Os
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La farine d'os est une teinture blanche et est également utile comme engrais pour accélérer la croissance de nombreuses plantes.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Cliquez avec le bouton droit sur un mouton pour blanchir sa laine. Cliquez avec le bouton droit sur une plante pour accélérer sa croissance. Cependant, toutes les plantes ne peuvent pas être fertilisées de cette manière. Lorsque vous cliquez avec le bouton droit sur un bloc d'herbe, les hautes herbes et les fleurs poussent autour.
|
||||
Speeds up plant growth=Accélère la croissance des plantes
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=Mączka kostna
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Mączka kostna to biała farba i przydatny nawóz, który przyspiesza rośnięcie wielu roślin.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Kliknij prawym na owcę, aby wybielić jej wełnę. Kliknij prawym na roślinę aby przyspieszyć jej wzrost. Zważ, że nie na wszystkie rośliny to tak działa. Gdy klikniesz prawym na blok trawy, wysoka trawa wyrośnie wokół.
|
||||
Speeds up plant growth=Przyspiesza wzrost roślin
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=Костная мука
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Костная мука является белым красителем. Она также полезна в качестве удобрения, чтобы увеличить скорость роста многих растений.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Кликните правой по овце, чтобы сделать её шерсть белой. Кликните правой по растению, чтобы ускорить его рост. Имейте в виду, что не все растения можно удобрять таким способом. Если вы кликнете по травяному блоку, то на этом месте вырастет высокая трава и цветы.
|
||||
Speeds up plant growth=Ускоряет рост растений
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=骨粉
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=骨粉是一種白色染料,也可作為肥料,加速許多植物的生長。
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=右鍵點擊一隻羊,使其羊毛變白。右鍵點擊一株植物以加快其生長速度。注意,不是所有的植物都能像這樣施肥。當你右鍵點擊一個草方時,高高的草和花會到處生長。
|
||||
Speeds up plant growth=加速植物生長
|
|
@ -1,5 +0,0 @@
|
|||
# textdomain: mcl_bone_meal
|
||||
Bone Meal=
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=
|
||||
Speeds up plant growth=
|
|
@ -1,3 +0,0 @@
|
|||
name = mcl_bone_meal
|
||||
description = Bone meal can be used as a fertilizer and as a dye.
|
||||
author = kabou, teknomunk
|
|
@ -257,10 +257,10 @@ function ARROW_ENTITY.on_step(self, dtime)
|
|||
mcl_burning.set_on_fire(obj, 5)
|
||||
end
|
||||
if not self._in_player and not self._blocked then
|
||||
mcl_util.deal_damage(obj, self._damage, {type = "arrow", source = self._shooter, direct = self.object})
|
||||
if self._extra_hit_func then
|
||||
self._extra_hit_func(obj)
|
||||
end
|
||||
obj:punch(self.object, 1.0, {
|
||||
full_punch_interval=1.0,
|
||||
damage_groups={fleshy=self._damage},
|
||||
}, self.object:get_velocity())
|
||||
if obj:is_player() then
|
||||
if not mcl_shields.is_blocking(obj) then
|
||||
local placement
|
||||
|
|
|
@ -168,8 +168,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
|
|||
itemstack:get_meta():set_string("active", "true")
|
||||
return itemstack
|
||||
end,
|
||||
groups = {weapon=1,weapon_ranged=1,bow=1,cannot_block=1,enchantability=1},
|
||||
touch_interaction = "short_dig_long_place",
|
||||
groups = {weapon=1,weapon_ranged=1,bow=1,enchantability=1},
|
||||
_mcl_uses = 385,
|
||||
})
|
||||
|
||||
|
@ -217,7 +216,7 @@ for level=0, 2 do
|
|||
wield_scale = mcl_vars.tool_wield_scale,
|
||||
stack_max = 1,
|
||||
range = 0, -- Pointing range to 0 to prevent punching with bow :D
|
||||
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, cannot_block=1, enchantability=1},
|
||||
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1},
|
||||
-- Trick to disable digging as well
|
||||
on_use = function() return end,
|
||||
on_drop = function(itemstack, dropper, pos)
|
||||
|
@ -236,7 +235,6 @@ for level=0, 2 do
|
|||
on_place = function(itemstack)
|
||||
return itemstack
|
||||
end,
|
||||
touch_interaction = "short_dig_long_place",
|
||||
_mcl_uses = 385,
|
||||
})
|
||||
end
|
||||
|
|
|
@ -158,8 +158,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
|
|||
itemstack:get_meta():set_string("active", "true")
|
||||
return itemstack
|
||||
end,
|
||||
groups = {weapon=1,weapon_ranged=1,crossbow=1,cannot_block=1,enchantability=1},
|
||||
touch_interaction = "short_dig_long_place",
|
||||
groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1},
|
||||
_mcl_uses = 326,
|
||||
})
|
||||
|
||||
|
@ -194,8 +193,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
|
|||
itemstack:get_meta():set_string("active", "true")
|
||||
return itemstack
|
||||
end,
|
||||
groups = {weapon=1,weapon_ranged=1,crossbow=1,cannot_block=1,enchantability=1,not_in_creative_inventory=1},
|
||||
touch_interaction = "short_dig_long_place",
|
||||
groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1,not_in_creative_inventory=1},
|
||||
_mcl_uses = 326,
|
||||
})
|
||||
|
||||
|
@ -240,7 +238,7 @@ for level=0, 2 do
|
|||
wield_scale = mcl_vars.tool_wield_scale,
|
||||
stack_max = 1,
|
||||
range = 0, -- Pointing range to 0 to prevent punching with bow :D
|
||||
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, cannot_block=1, bow=1, enchantability=1},
|
||||
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1},
|
||||
-- Trick to disable digging as well
|
||||
on_use = function() return end,
|
||||
on_drop = function(itemstack, dropper, pos)
|
||||
|
@ -259,7 +257,6 @@ for level=0, 2 do
|
|||
on_place = function(itemstack)
|
||||
return itemstack
|
||||
end,
|
||||
touch_interaction = "short_dig_long_place",
|
||||
_mcl_uses = 385,
|
||||
})
|
||||
end
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
# mcl_buckets
|
||||
Adds an API to register buckets to VL
|
||||
Add an API to register buckets to mcl
|
||||
|
||||
## mcl_buckets.register_liquid(def)
|
||||
|
||||
Register a new liquid.
|
||||
|
||||
Accepts the following parameters:
|
||||
|
||||
* `source_place`: a string or a function
|
||||
* `string`: name of the node to place
|
||||
* `function(pos)`: will return name of the node to place with pos being the placement position
|
||||
* `source_take`: table of liquid source node names to take
|
||||
* `bucketname`: itemstring of the new bucket item
|
||||
* `inventory_image`: texture of the new bucket item (ignored if itemname == nil)
|
||||
* `name`: user-visible bucket description
|
||||
* `longdesc`: long explanatory description (for help)
|
||||
* `usagehelp`: short usage explanation (for help)
|
||||
* `tt_help`: very short tooltip help
|
||||
* `extra_check(pos, placer)`: (optional) additional check before liquid placement (return 2 booleans: (1) whether to place the liquid source and (2) whether to empty the bucket)
|
||||
* `groups`: optional list of item groups
|
||||
Register a new liquid
|
||||
Accept folowing params:
|
||||
* source_place: a string or function.
|
||||
* string: name of the node to place
|
||||
* function(pos): will returns name of the node to place with pos being the placement position
|
||||
* source_take: table of liquid source node names to take
|
||||
* bucketname: itemstring of the new bucket item
|
||||
* inventory_image: texture of the new bucket item (ignored if itemname == nil)
|
||||
* name: user-visible bucket description
|
||||
* longdesc: long explanatory description (for help)
|
||||
* usagehelp: short usage explanation (for help)
|
||||
* tt_help: very short tooltip help
|
||||
* extra_check(pos, placer): (optional) function(pos)
|
||||
* groups: optional list of item groups
|
||||
|
||||
|
||||
**Usage example:**
|
||||
|
||||
**Usage exemple:**
|
||||
```lua
|
||||
mcl_buckets.register_liquid({
|
||||
bucketname = "dummy:bucket_dummy",
|
||||
|
@ -42,7 +39,7 @@ mcl_buckets.register_liquid({
|
|||
tt_help = S("Places a dummy liquid source"),
|
||||
extra_check = function(pos, placer)
|
||||
--pos = pos where the liquid should be placed
|
||||
--placer who tried to place the bucket (can be nil)
|
||||
--placer people who tried to place the bucket (can be nil)
|
||||
|
||||
--no liquid node will be placed
|
||||
--the bucket will not be emptied
|
||||
|
@ -54,4 +51,4 @@ mcl_buckets.register_liquid({
|
|||
end,
|
||||
groups = { dummy_group = 123 },
|
||||
})
|
||||
```
|
||||
```
|
|
@ -39,9 +39,9 @@ local function drop_items(pos, node, oldmeta)
|
|||
if food_entity:get_luaentity().name == "mcl_campfires:food_entity" then
|
||||
food_entity:remove()
|
||||
for i = 1, 4 do
|
||||
meta:set_string("food_x_"..tostring(i), "")
|
||||
meta:set_string("food_y_"..tostring(i), "")
|
||||
meta:set_string("food_z_"..tostring(i), "")
|
||||
meta:set_string("food_x_"..tostring(i), nil)
|
||||
meta:set_string("food_y_"..tostring(i), nil)
|
||||
meta:set_string("food_z_"..tostring(i), nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -135,9 +135,9 @@ function mcl_campfires.cook_item(pos, elapsed)
|
|||
if cooked then
|
||||
if food_entity then
|
||||
food_entity:remove() -- Remove visual food entity
|
||||
meta:set_string("food_x_"..tostring(i), "")
|
||||
meta:set_string("food_y_"..tostring(i), "")
|
||||
meta:set_string("food_z_"..tostring(i), "")
|
||||
meta:set_string("food_x_"..tostring(i), nil)
|
||||
meta:set_string("food_y_"..tostring(i), nil)
|
||||
meta:set_string("food_z_"..tostring(i), nil)
|
||||
minetest.add_item(pos, cooked.item) -- Drop Cooked Item
|
||||
-- Throw some Experience Points because why not?
|
||||
-- Food is cooked, xp is deserved for using this unique cooking method. Take that Minecraft ;)
|
||||
|
|
|
@ -5,9 +5,9 @@ animations are achieved by giving each chest node an entity, as Minetest (as of
|
|||
5.8.1) doesn't support giving nodes animated meshes, only static ones.
|
||||
|
||||
Because of that, a lot of parameters passed through the exposed functions are
|
||||
related to nodes and entities.
|
||||
be related to nodes and entities.
|
||||
|
||||
Please refer to the [Minetest documentation](http://api.minetest.net/) and code
|
||||
Please refer to [Minetest documentation](http://api.minetest.net/) and the code
|
||||
comments in `api.lua`.
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ minetest.register_lbm({
|
|||
local node_name = node.name
|
||||
node.name = node_name .. "_small"
|
||||
minetest.swap_node(pos, node)
|
||||
mcl_chests.select_and_spawn_entity(pos, node)
|
||||
select_and_spawn_entity(pos, node)
|
||||
if node_name == "mcl_chests:trapped_chest_on" then
|
||||
minetest.log("action", "[mcl_chests] Disabled active trapped chest on load: " .. minetest.pos_to_string(pos))
|
||||
mcl_chests.chest_update_after_close(pos)
|
||||
|
|
|
@ -2,34 +2,29 @@ local S = minetest.get_translator(minetest.get_current_modname())
|
|||
|
||||
mcl_cocoas = {}
|
||||
|
||||
--- Place a cocoa pod.
|
||||
-- Attempt to place a cocoa pod on a jungle tree. Checks if attachment
|
||||
-- point is a jungle tree and sets the correct orientation of the stem.
|
||||
--
|
||||
function mcl_cocoas.place(itemstack, placer, pt, plantname)
|
||||
-- Place cocoa
|
||||
local function cocoa_place(itemstack, placer, pt, plantname)
|
||||
-- check if pointing at a node
|
||||
if not pt or pt.type ~= "node" then
|
||||
return
|
||||
end
|
||||
|
||||
local node = minetest.get_node(pt.under)
|
||||
local under = minetest.get_node(pt.under)
|
||||
|
||||
-- return if any of the nodes are not registered
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
if not def then
|
||||
if not minetest.registered_nodes[under.name] then
|
||||
return
|
||||
end
|
||||
|
||||
-- Am I right-clicking on something that has a custom on_rightclick set?
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
if def and def.on_rightclick then
|
||||
local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pt)
|
||||
if new_stack and new_stack ~= itemstack then return new_stack end
|
||||
if minetest.registered_nodes[under.name] and minetest.registered_nodes[under.name].on_rightclick then
|
||||
return minetest.registered_nodes[under.name].on_rightclick(pt.under, under, placer, itemstack) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if pointing at jungle tree
|
||||
if node.name ~= "mcl_core:jungletree"
|
||||
if under.name ~= "mcl_core:jungletree"
|
||||
or minetest.get_node(pt.above).name ~= "air" then
|
||||
return
|
||||
end
|
||||
|
@ -44,7 +39,9 @@ function mcl_cocoas.place(itemstack, placer, pt, plantname)
|
|||
|
||||
-- Add the node, set facedir and remove 1 item from the itemstack
|
||||
minetest.set_node(pt.above, {name = plantname, param2 = minetest.dir_to_facedir(clickdir)})
|
||||
|
||||
minetest.sound_play("default_place_node", {pos = pt.above, gain = 1.0}, true)
|
||||
|
||||
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
@ -52,119 +49,111 @@ function mcl_cocoas.place(itemstack, placer, pt, plantname)
|
|||
return itemstack
|
||||
end
|
||||
|
||||
--- Grows cocoa pod one size larger.
|
||||
-- Attempts to grow a cocoa at pos, returns true when grown, returns false
|
||||
-- if there's no cocoa or it is already at full size.
|
||||
--
|
||||
-- Attempts to grow a cocoa at pos, returns true when grown, returns false if there's no cocoa
|
||||
-- or it is already at full size
|
||||
function mcl_cocoas.grow(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "mcl_cocoas:cocoa_1" then
|
||||
minetest.set_node(pos, {name = "mcl_cocoas:cocoa_2", param2 = node.param2})
|
||||
elseif node.name == "mcl_cocoas:cocoa_2" then
|
||||
minetest.set_node(pos, {name = "mcl_cocoas:cocoa_3", param2 = node.param2})
|
||||
else
|
||||
return false
|
||||
return true
|
||||
end
|
||||
return true
|
||||
return false
|
||||
end
|
||||
|
||||
-- only caller was mcl_dye, consider converting these into local functions.
|
||||
local cocoa_place = mcl_cocoas.place
|
||||
local cocoa_grow = mcl_cocoas.grow
|
||||
-- Cocoa definition
|
||||
-- 1st stage
|
||||
local crop_def = {
|
||||
description = S("Premature Cocoa Pod"),
|
||||
_doc_items_create_entry = true,
|
||||
_doc_items_longdesc = S("Cocoa pods grow on the side of jungle trees in 3 stages."),
|
||||
drawtype = "mesh",
|
||||
mesh = "mcl_cocoas_cocoa_stage_0.obj",
|
||||
tiles = {"mcl_cocoas_cocoa_stage_0.png"},
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
drop = "mcl_cocoas:cocoa_beans",
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.125, -0.0625, 0.1875, 0.125, 0.25, 0.4375}, -- Pod
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.125, -0.0625, 0.1875, 0.125, 0.5, 0.5}, -- Pod
|
||||
},
|
||||
},
|
||||
groups = {
|
||||
handy = 1, axey = 1,
|
||||
dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1,
|
||||
attached_node_facedir=1,
|
||||
not_in_creative_inventory=1,
|
||||
cocoa=1
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
on_rotate = false,
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 0.2,
|
||||
}
|
||||
|
||||
-- Cocoa pod variant definitions.
|
||||
--[[ TODO: Use a mesh for cocoas for perfect texture compability. ]]
|
||||
local podinfo = {
|
||||
{ desc = S("Premature Cocoa Pod"),
|
||||
longdesc = S("Cocoa pods grow on the side of jungle trees in 3 stages."),
|
||||
tiles = {
|
||||
"mcl_cocoas_cocoa_stage_0.png",
|
||||
},
|
||||
n_box = {-0.125, -0.0625, 0.1875, 0.125, 0.25, 0.4375},
|
||||
s_box = {-0.125, -0.0625, 0.1875, 0.125, 0.5, 0.5 },
|
||||
-- 2nd stage
|
||||
minetest.register_node("mcl_cocoas:cocoa_1", table.copy(crop_def))
|
||||
|
||||
crop_def.description = S("Medium Cocoa Pod")
|
||||
crop_def._doc_items_create_entry = false
|
||||
crop_def.groups.cocoa = 2
|
||||
crop_def.mesh = "mcl_cocoas_cocoa_stage_1.obj"
|
||||
crop_def.tiles = {"mcl_cocoas_cocoa_stage_1.png"}
|
||||
crop_def.collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.1875, -0.1875, 0.0625, 0.1875, 0.25, 0.4375}, -- Pod
|
||||
},
|
||||
{ desc = S("Medium Cocoa Pod"),
|
||||
tiles = {
|
||||
"mcl_cocoas_cocoa_stage_1.png",
|
||||
},
|
||||
n_box = {-0.1875, -0.1875, 0.0625, 0.1875, 0.25, 0.4375},
|
||||
s_box = {-0.1875, -0.1875, 0.0625, 0.1875, 0.5, 0.5 },
|
||||
},
|
||||
{ desc = S("Mature Cocoa Pod"),
|
||||
longdesc = S("A mature cocoa pod grew on a jungle tree to its full size and it is ready to be harvested for cocoa beans. It won't grow any further."),
|
||||
tiles = {
|
||||
"mcl_cocoas_cocoa_stage_2.png",
|
||||
},
|
||||
n_box = {-0.25, -0.3125, -0.0625, 0.25, 0.25, 0.4375},
|
||||
s_box = {-0.25, -0.3125, -0.0625, 0.25, 0.5, 0.5 },
|
||||
}
|
||||
crop_def.selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.1875, -0.1875, 0.0625, 0.1875, 0.5, 0.5},
|
||||
},
|
||||
}
|
||||
|
||||
for i = 1, 3 do
|
||||
local def = {
|
||||
description = podinfo[i].desc,
|
||||
_doc_items_create_entry = true,
|
||||
_doc_items_longdesc = podinfo[i].longdesc,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
tiles = podinfo[i].tiles,
|
||||
use_texture_alpha = "clip",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
podinfo[i].n_box, -- Pod
|
||||
-- FIXME: This has a thickness of 0. Is this OK in Minetest?
|
||||
{ 0, 0.25, 0.25, 0, 0.5, 0.5 }, }, -- Stem
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = podinfo[i].n_box
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = podinfo[i].s_box
|
||||
},
|
||||
groups = {
|
||||
handy = 1, axey = 1, attached_node_facedir = 1,
|
||||
dig_by_water = 1, destroy_by_lava_flow = 1, dig_by_piston = 1,
|
||||
cocoa = i, not_in_creative_inventory = 1,
|
||||
},
|
||||
sunlight_propagates = true,
|
||||
walkable = true,
|
||||
drop = "mcl_cocoas:cocoa_beans",
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
on_rotate = false,
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 0.2,
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
return cocoa_grow(pos)
|
||||
end,
|
||||
}
|
||||
minetest.register_node("mcl_cocoas:cocoa_2", table.copy(crop_def))
|
||||
|
||||
if i == 2 then
|
||||
def._doc_items_longdesc = nil
|
||||
def._doc_items_create_entry = false
|
||||
end
|
||||
if i == 3 then
|
||||
def.drop = "mcl_cocoas:cocoa_beans 3"
|
||||
def._on_bone_mealing = nil
|
||||
end
|
||||
|
||||
minetest.register_node("mcl_cocoas:cocoa_" .. i, table.copy(def))
|
||||
end
|
||||
-- Final stage
|
||||
crop_def.description = S("Mature Cocoa Pod")
|
||||
crop_def._doc_items_longdesc = S("A mature cocoa pod grew on a jungle tree to its full size and it is ready to be harvested for cocoa beans. It won't grow any further.")
|
||||
crop_def._doc_items_create_entry = true
|
||||
crop_def.groups.cocoa = 3
|
||||
crop_def.mesh = "mcl_cocoas_cocoa_stage_2.obj"
|
||||
crop_def.tiles = {"mcl_cocoas_cocoa_stage_2.png"}
|
||||
crop_def.collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.25, -0.3125, -0.0625, 0.25, 0.25, 0.4375}, -- Pod
|
||||
},
|
||||
}
|
||||
crop_def.selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.25, -0.3125, -0.0625, 0.25, 0.5, 0.5},
|
||||
},
|
||||
}
|
||||
crop_def.drop = "mcl_cocoas:cocoa_beans 3"
|
||||
minetest.register_node("mcl_cocoas:cocoa_3", table.copy(crop_def))
|
||||
|
||||
minetest.register_craftitem("mcl_cocoas:cocoa_beans", {
|
||||
inventory_image = "mcl_cocoa_beans.png",
|
||||
_tt_help = S("Grows at the side of jungle trees"),
|
||||
_doc_items_longdesc = S("Cocoa beans can be used to plant cocoa, bake cookies or cract brown dye."),
|
||||
_doc_items_usagehelp = S("Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa."),
|
||||
description = S("Cocoa Beans"),
|
||||
stack_max = 64,
|
||||
groups = {
|
||||
craftitem = 1, compostability = 65,
|
||||
},
|
||||
_tt_help = S("Grows at the side of jungle trees"),
|
||||
_doc_items_longdesc = S("Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye."),
|
||||
_doc_items_usagehelp = S("Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa."),
|
||||
inventory_image = "mcl_cocoas_cocoa_beans.png",
|
||||
groups = {craftitem = 1, compostability = 65},
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
return cocoa_place(itemstack, placer, pointed_thing, "mcl_cocoas:cocoa_1")
|
||||
end,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=Kakaobohnen
|
||||
Grows at the side of jungle trees=Wächst an der Seite von Dschungelbäumen
|
||||
Cocoa beans can be used to plant cocoa pods, bake chocolate cookies or craft brown dye.=Kakaobohnen können benutzt werden, um Kakao anzupflanzen, Kekse zu backen oder braune Farbstoffe herzustellen.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie auf ein Schaf, um die Wolle braun einzufärben. Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen.
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen.
|
||||
Premature Cocoa Pod=Junge Kakaoschote
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=Kakaoschoten wachsen an der Seite von Dschungelbäumen in 3 Stufen.
|
||||
Medium Cocoa Pod=Mittelgroße Kakaoschote
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=Granos de cacao
|
||||
Grows at the side of jungle trees=Crece al lado de los árboles de la jungla
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Los granos de cacao se pueden usar para plantar cacao, hornear galletas o hacer tintes marrones.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en una oveja para convertir su lana en marrón. Haga clic derecho en el costado del tronco de un árbol de la jungla para plantar un cacao joven.
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en el costado del tronco de un árbol de la jungla para plantar un cacao joven.
|
||||
Premature Cocoa Pod=Vaina de cacao prematura
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=Las vainas de cacao crecen al lado de los árboles de jungla en 3 etapas.
|
||||
Medium Cocoa Pod=Vaina de cacao mediana
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=Fèves de Cacao
|
||||
Grows at the side of jungle trees=Pousse à côté des arbres de la jungle
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Les fèves de cacao peuvent être utilisées pour planter du cacao, faire des biscuits ou fabriquer de la teinture brune.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Faites un clic droit sur un mouton pour brunir sa laine. Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacao.
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacaoyer.
|
||||
Premature Cocoa Pod=Gousse de cacao prématurée
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=Les cabosses de cacao poussent sur le côté des arbres d'Acajou en 3 étapes.
|
||||
Medium Cocoa Pod=Gousse de cacao moyenne
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=Ziarna kakaowe
|
||||
Grows at the side of jungle trees=Rośnie na boku tropikalnych drzew
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Ziarna kakaowe mogą być używane do sadzenia kakao, pieczenia ciasteczek lub robienia brązowego barwnika.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym aby zafarbować wełnę owcy na brązowo. Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao.
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao.
|
||||
Premature Cocoa Pod=Niedojrzała roślina kakao
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=Roślina kakao rośnie na bokach tropikalnych drzew w 3 etapach
|
||||
Medium Cocoa Pod=Średnio-dojrzała roślina kakao
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=Какао-бобы
|
||||
Grows at the side of jungle trees=Растут на стволах тропических деревьев
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Какао-бобы можно использовать для посадки какао, выпечки печенья или изготовления коричневого красителя.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по овце, чтобы сделать её шерсть коричневой. Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао.
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао.
|
||||
Premature Cocoa Pod=Молодой стручок какао
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=Стручки какао растут на деревьях джунглей в 3 этапа.
|
||||
Medium Cocoa Pod=Средний стручок какао
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=可可豆
|
||||
Grows at the side of jungle trees=在叢林木側生長
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=可可豆可用於種植可可、烘烤餅乾或製作棕色染料。
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊一隻羊,使其羊毛變成褐色。右鍵點擊叢林木的一側,可以種植一個可可。
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊叢林木的一側,可以種植一個可可。
|
||||
Premature Cocoa Pod=成長中的可可豆莢(第1階段)
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=可可莢果分3個階段生長在叢林樹的側面。
|
||||
Medium Cocoa Pod=成長中的可可豆莢(第2階段)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Cocoa Beans=
|
||||
Grows at the side of jungle trees=
|
||||
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=
|
||||
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=
|
||||
Premature Cocoa Pod=
|
||||
Cocoa pods grow on the side of jungle trees in 3 stages.=
|
||||
Medium Cocoa Pod=
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_cocoas
|
||||
description = Cocoa pods which grow at jungle trees. Does not include cocoa beans.
|
||||
depends = mcl_sounds, mcl_core, mcl_util
|
||||
optional_depends = doc
|
||||
depends = mcl_sounds, mcl_core
|
||||
optional_depends = doc
|
|
@ -11,7 +11,7 @@ local composter_description = S(
|
|||
"Composter"
|
||||
)
|
||||
local composter_longdesc = S(
|
||||
"Composters can convert various organic items into bone meal."
|
||||
"Composters can convert various organic items into bonemeal."
|
||||
)
|
||||
local composter_usagehelp = S(
|
||||
"Use organic items on the composter to fill it with layers of compost. " ..
|
||||
|
@ -48,41 +48,6 @@ local vector_offset = vector.offset
|
|||
local is_protected = minetest.is_protected
|
||||
local record_protection_violation = minetest.record_protection_violation
|
||||
|
||||
--- Math and node swap during compost progression
|
||||
---@param pos Vector Position of the node
|
||||
---@param node node
|
||||
---@param chance integer Value of "compostability" group of inserted item
|
||||
local function composter_progress_chance(pos, node, chance)
|
||||
-- calculate leveling up chance
|
||||
local rand = math.random(0,100)
|
||||
if chance >= rand then
|
||||
-- get current compost level
|
||||
local level = registered_nodes[node.name]["_mcl_compost_level"]
|
||||
-- spawn green particles above new layer
|
||||
mcl_bone_meal.add_bone_meal_particle(vector_offset(pos, 0, level/8, 0))
|
||||
-- update composter block
|
||||
if level < 7 then
|
||||
level = level + 1
|
||||
else
|
||||
level = "ready"
|
||||
end
|
||||
swap_node(pos, {name = "mcl_composters:composter_" .. level})
|
||||
minetest.sound_play({name="default_grass_footstep", gain=0.4}, {
|
||||
pos = pos,
|
||||
gain= 0.4,
|
||||
max_hear_distance = 16,
|
||||
}, true)
|
||||
-- a full composter becomes ready for harvest after one second
|
||||
-- the block will get updated by the node timer callback set in node reg def
|
||||
if level == 7 then
|
||||
local timer = get_node_timer(pos)
|
||||
if not timer:is_started() then
|
||||
timer:start(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Fill the composter when rightclicked.
|
||||
--
|
||||
-- `on_rightclick` handler for composter blocks of all fill levels except
|
||||
|
@ -121,6 +86,41 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing)
|
|||
return itemstack
|
||||
end
|
||||
|
||||
--- Math and node swap during compost progression
|
||||
---@param pos Vector Position of the node
|
||||
---@param node node
|
||||
---@param chance integer Value of "compostability" group of inserted item
|
||||
function composter_progress_chance(pos, node, chance)
|
||||
-- calculate leveling up chance
|
||||
local rand = math.random(0,100)
|
||||
if chance >= rand then
|
||||
-- get current compost level
|
||||
local level = registered_nodes[node.name]["_mcl_compost_level"]
|
||||
-- spawn green particles above new layer
|
||||
mcl_dye.add_bone_meal_particle(vector_offset(pos, 0, level/8, 0))
|
||||
-- update composter block
|
||||
if level < 7 then
|
||||
level = level + 1
|
||||
else
|
||||
level = "ready"
|
||||
end
|
||||
swap_node(pos, {name = "mcl_composters:composter_" .. level})
|
||||
minetest.sound_play({name="default_grass_footstep", gain=0.4}, {
|
||||
pos = pos,
|
||||
gain= 0.4,
|
||||
max_hear_distance = 16,
|
||||
}, true)
|
||||
-- a full composter becomes ready for harvest after one second
|
||||
-- the block will get updated by the node timer callback set in node reg def
|
||||
if level == 7 then
|
||||
local timer = get_node_timer(pos)
|
||||
if not timer:is_started() then
|
||||
timer:start(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Update a full composter block to ready for harvesting.
|
||||
--
|
||||
-- `on_timer` handler. The timer is set in function 'composter_add_item'
|
||||
|
@ -203,7 +203,7 @@ end
|
|||
--
|
||||
minetest.register_node("mcl_composters:composter", {
|
||||
description = composter_description,
|
||||
_tt_help = S("Converts organic items into bone meal"),
|
||||
_tt_help = S("Converts organic items into bonemeal"),
|
||||
_doc_items_longdesc = composter_longdesc,
|
||||
_doc_items_usagehelp = composter_usagehelp,
|
||||
paramtype = "light",
|
||||
|
|
|
@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=Les composteurs peuv
|
|||
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Utiliser des objets organiques sur le composteur pour le remplir de couches de compost. Chaque fois qu'un objet est mis dans le composteur, il y a une chance d'ajouter une nouvelle couche de compost au composteur. Certains objets ont une plus grande chance que d'autres d'ajouter une couche supplémentaire. Après l'avoir rempli de 7 couches de compost, le composteur est plein. Après un délai d'approximativement une seconde, le composteur est prêt et on peut récupérer la farine d'os. Cliquer droit le composteur permet de récupérer la farine d'os et de vider le composteur.
|
||||
filled=rempli
|
||||
ready for harvest=prêt pour la récolte
|
||||
Converts organic items into bone meal=Convertit les objets organiques en farine d'os.
|
||||
Converts organic items into bonemeal=Convertit les objets organiques en farine d'os.
|
||||
|
|
|
@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=コンポスター
|
|||
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter."=コンポスターに有機物を入れて、堆肥の層を作りましょう。コンポスターに有機物を入れるたびに、次の堆肥の層が追加されるチャンスが起きます。 追加される確率がより高くなっているアイテムもいくつかあります。 7層分の堆肥が充填されると、コンポスターは満杯となります。その約1秒後に、骨粉を取り出せる準備が完了します。右クリックして骨粉を取り出すと、コンポスターは空になります。
|
||||
filled=充足
|
||||
ready for harvest=収穫可能
|
||||
Converts organic items into bone meal=有機物を骨粉に変える
|
||||
Converts organic items into bonemeal=有機物を骨粉に変える
|
||||
|
|
|
@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=Компостер
|
|||
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Используйте органические предметы на компостере, чтобы заполнить его слоями перегноя. Каждый раз когда в компостер попадает предмет, есть шанс что в компостере появится новый слой перегноя. Некоторые предметы имеют больший шанс на появление нового слоя. После заполнения 7 слоями перегноя, компостер можно опустошить, забрав из него костную муку. После задержки в одну секунду компостер будет готов и костная мука будет извлечена из него. Правым кликом по компостеру чтобы забрать костную муку.
|
||||
filled=заполнен
|
||||
ready for harvest=готов к сбору
|
||||
Converts organic items into bone meal=Перерабатывает органику в костную муку
|
||||
Converts organic items into bonemeal=Перерабатывает органику в костную муку
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# textdomain: mcl_composters
|
||||
Composter=
|
||||
Composters can convert various organic items into bone meal.=
|
||||
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=
|
||||
Composters can convert various organic items into bonemeal.=
|
||||
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=
|
||||
filled=
|
||||
ready for harvest=
|
||||
Converts organic items into bone meal=
|
||||
Converts organic items into bonemeal=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name = mcl_composters
|
||||
author = kabou
|
||||
description = Composters can convert various organic items into bonemeal.
|
||||
depends = mcl_core, mcl_sounds, mcl_bone_meal, mcl_hoppers
|
||||
depends = mcl_core, mcl_sounds, mcl_dye, mcl_hoppers
|
||||
optional_depends = doc
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -280,14 +280,6 @@ function mcl_core.register_sapling(subname, description, longdesc, tt_help, text
|
|||
nn == "mcl_core:podzol" or nn == "mcl_core:podzol_snow" or
|
||||
nn == "mcl_core:dirt" or nn == "mcl_core:mycelium" or nn == "mcl_core:coarse_dirt"
|
||||
end),
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
local n = minetest.get_node(pos)
|
||||
-- Saplings: 45% chance to advance growth stage
|
||||
if math.random(1,100) <= 45 then
|
||||
return mcl_core.grow_sapling(pos, n)
|
||||
end
|
||||
end,
|
||||
node_placement_prediction = "",
|
||||
_mcl_blast_resistance = 0,
|
||||
_mcl_hardness = 0,
|
||||
|
|
|
@ -5,8 +5,6 @@ local modpath = minetest.get_modpath(modname)
|
|||
-- by debiankaios
|
||||
-- adapted for mcl2 by cora
|
||||
|
||||
local MAXIMUM_VINE_HEIGHT = 25
|
||||
|
||||
local wood_slab_groups = {handy = 1, axey = 1, material_wood = 1, wood_slab = 1}
|
||||
local wood_stair_groups = {handy = 1, axey = 1, material_wood = 1, wood_stairs = 1}
|
||||
|
||||
|
@ -18,36 +16,21 @@ function generate_crimson_tree(pos)
|
|||
minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_1.mts","random",nil,false,"place_center_x,place_center_z")
|
||||
end
|
||||
|
||||
function grow_vines(pos, moreontop, vine, dir)
|
||||
-- Sanity checks
|
||||
function grow_vines(pos, moreontop ,vine, dir)
|
||||
if dir == nil then dir = 1 end
|
||||
if not moreontop or moreontop < 1 then return false end
|
||||
|
||||
local allowed_nodes = {}
|
||||
allowed_nodes[vine] = true
|
||||
|
||||
-- Find the root, tip and calculate height
|
||||
local root,_,root_node = mcl_util.trace_nodes(pos, -dir, allowed_nodes, MAXIMUM_VINE_HEIGHT)
|
||||
if not root then return false end
|
||||
local tip,height,tip_node = mcl_util.trace_nodes(vector.offset(root, 0, dir, 0), dir, allowed_nodes, MAXIMUM_VINE_HEIGHT)
|
||||
if not tip then return false end
|
||||
|
||||
local res = false
|
||||
for i = 1,moreontop do
|
||||
-- Check if we can grow into this position
|
||||
if height >= MAXIMUM_VINE_HEIGHT then return res end
|
||||
if tip_node.name ~= "air" then return res end
|
||||
|
||||
-- Update world map data
|
||||
minetest.set_node(tip, {name = vine})
|
||||
|
||||
-- Move to the next position and flag that growth has occured
|
||||
tip = vector.offset(tip, 0, dir, 0)
|
||||
tip_node = minetest.get_node(tip)
|
||||
height = height + 1
|
||||
res = true
|
||||
end
|
||||
return res
|
||||
local n
|
||||
repeat
|
||||
pos = vector.offset(pos,0,dir,0)
|
||||
n = minetest.get_node(pos)
|
||||
if n.name == "air" then
|
||||
for i=0,math.max(moreontop,1) do
|
||||
if minetest.get_node(pos).name == "air" then
|
||||
minetest.set_node(vector.offset(pos,0,i*dir,0),{name=vine})
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
until n.name ~= "air" and n.name ~= vine
|
||||
end
|
||||
|
||||
local nether_plants = {
|
||||
|
@ -100,20 +83,17 @@ minetest.register_node("mcl_crimson:warped_fungus", {
|
|||
light_source = 1,
|
||||
sounds = mcl_sounds.node_sound_leaves_defaults(),
|
||||
node_placement_prediction = "",
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
||||
|
||||
if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then
|
||||
local random = math.random(1, 5)
|
||||
if random == 1 then
|
||||
minetest.remove_node(pos)
|
||||
generate_warped_tree(pos)
|
||||
return true
|
||||
on_rightclick = function(pos, node, pointed_thing, player, itemstack)
|
||||
if pointed_thing:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
|
||||
local nodepos = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then
|
||||
local random = math.random(1, 5)
|
||||
if random == 1 then
|
||||
minetest.remove_node(pos)
|
||||
generate_warped_tree(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end,
|
||||
_mcl_blast_resistance = 0,
|
||||
})
|
||||
|
@ -122,12 +102,6 @@ mcl_flowerpots.register_potted_flower("mcl_crimson:warped_fungus", {
|
|||
name = "warped_fungus",
|
||||
desc = S("Warped Fungus"),
|
||||
image = "mcl_crimson_warped_fungus.png",
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local n = has_nylium_neighbor(pointed_thing.under)
|
||||
if n then
|
||||
minetest.set_node(pointed_thing.under,n)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_crimson:twisting_vines", {
|
||||
|
@ -147,9 +121,6 @@ minetest.register_node("mcl_crimson:twisting_vines", {
|
|||
fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 },
|
||||
},
|
||||
node_placement_prediction = "",
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
return grow_vines(pointed_thing.under, math.random(1, 3),"mcl_crimson:twisting_vines")
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
local pn = clicker:get_player_name()
|
||||
if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then
|
||||
|
@ -170,28 +141,26 @@ minetest.register_node("mcl_crimson:twisting_vines", {
|
|||
end
|
||||
|
||||
elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
|
||||
return mcl_bone_meal.use_bone_meal(itemstack, clicker, {under=pos, above=pos})
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
grow_vines(pos, math.random(1, 3),"mcl_crimson:twisting_vines")
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local under = pointed_thing.under
|
||||
local unode = minetest.get_node(under)
|
||||
local unode_def = minetest.registered_nodes[unode.name]
|
||||
|
||||
local above = pointed_thing.above
|
||||
local anode = minetest.get_node(above)
|
||||
local anode_def = minetest.registered_nodes[anode.name]
|
||||
|
||||
local unode = minetest.get_node(under)
|
||||
if under.y < above.y then
|
||||
minetest.set_node(above, {name = "mcl_crimson:twisting_vines"})
|
||||
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
elseif unode_def and unode_def.on_rightclick then
|
||||
return unode_def.on_rightclick(under, unode, placer, itemstack, pointed_thing)
|
||||
elseif anode_def and anode_def.on_rightclick then
|
||||
return unode_def.on_rightclick(above, anode, placer, itemstack, pointed_thing)
|
||||
else
|
||||
if unode.name == "mcl_crimson:twisting_vines" then
|
||||
return minetest.registered_nodes[unode.name].on_rightclick(under, unode, placer, itemstack, pointed_thing)
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
|
@ -199,7 +168,7 @@ minetest.register_node("mcl_crimson:twisting_vines", {
|
|||
local above = vector.offset(pos,0,1,0)
|
||||
local abovenode = minetest.get_node(above)
|
||||
minetest.node_dig(pos, node, digger)
|
||||
if abovenode.name == node.name then
|
||||
if abovenode.name == node.name and (not mcl_core.check_vines_supported(above, abovenode)) then
|
||||
minetest.registered_nodes[node.name].on_dig(above, node, digger)
|
||||
end
|
||||
end,
|
||||
|
@ -242,9 +211,6 @@ minetest.register_node("mcl_crimson:weeping_vines", {
|
|||
fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 },
|
||||
},
|
||||
node_placement_prediction = "",
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
return grow_vines(pointed_thing.under, math.random(1, 3),"mcl_crimson:weeping_vines", -1)
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
local pn = clicker:get_player_name()
|
||||
if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then
|
||||
|
@ -265,28 +231,26 @@ minetest.register_node("mcl_crimson:weeping_vines", {
|
|||
end
|
||||
|
||||
elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
|
||||
return mcl_bone_meal.use_bone_meal(itemstack, clicker, {under=pos, above=pos})
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
grow_vines(pos, math.random(1, 3),"mcl_crimson:weeping_vines", -1)
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local under = pointed_thing.under
|
||||
local unode = minetest.get_node(under)
|
||||
local unode_def = minetest.registered_nodes[unode.name]
|
||||
|
||||
local above = pointed_thing.above
|
||||
local anode = minetest.get_node(above)
|
||||
local anode_def = minetest.registered_nodes[anode.name]
|
||||
|
||||
local unode = minetest.get_node(under)
|
||||
if under.y > above.y then
|
||||
minetest.set_node(above, {name = "mcl_crimson:weeping_vines"})
|
||||
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
elseif unode_def and unode_def.on_rightclick then
|
||||
return unode_def.on_rightclick(under, unode, placer, itemstack, pointed_thing)
|
||||
elseif anode_def and anode_def.on_rightclick then
|
||||
return unode_def.on_rightclick(above, anode, placer, itemstack, pointed_thing)
|
||||
else
|
||||
if unode.name == "mcl_crimson:weeping_vines" then
|
||||
return minetest.registered_nodes[unode.name].on_rightclick(under, unode, placer, itemstack, pointed_thing)
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
|
@ -294,7 +258,7 @@ minetest.register_node("mcl_crimson:weeping_vines", {
|
|||
local below = vector.offset(pos,0,-1,0)
|
||||
local belownode = minetest.get_node(below)
|
||||
minetest.node_dig(pos, node, digger)
|
||||
if belownode.name == node.name then
|
||||
if belownode.name == node.name and (not mcl_core.check_vines_supported(below, belownode)) then
|
||||
minetest.registered_nodes[node.name].on_dig(below, node, digger)
|
||||
end
|
||||
end,
|
||||
|
@ -429,11 +393,6 @@ minetest.register_node("mcl_crimson:warped_nylium", {
|
|||
_mcl_hardness = 0.4,
|
||||
_mcl_blast_resistance = 0.4,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
spread_nether_plants(pointed_thing.under,node)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
--Stem bark, stripped stem and bark
|
||||
|
@ -566,21 +525,17 @@ minetest.register_node("mcl_crimson:crimson_fungus", {
|
|||
fixed = { -3/16, -0.5, -3/16, 3/16, -2/16, 3/16 },
|
||||
},
|
||||
node_placement_prediction = "",
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.under
|
||||
local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
||||
if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then
|
||||
local random = math.random(1, 5)
|
||||
if random == 1 then
|
||||
minetest.remove_node(pos)
|
||||
generate_crimson_tree(pos)
|
||||
|
||||
return true
|
||||
on_rightclick = function(pos, node, pointed_thing, player)
|
||||
if pointed_thing:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
|
||||
local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
||||
if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then
|
||||
local random = math.random(1, 5)
|
||||
if random == 1 then
|
||||
minetest.remove_node(pos)
|
||||
generate_crimson_tree(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Failed to spread nylium
|
||||
return false
|
||||
end,
|
||||
_mcl_blast_resistance = 0,
|
||||
})
|
||||
|
@ -727,11 +682,6 @@ minetest.register_node("mcl_crimson:crimson_nylium", {
|
|||
_mcl_hardness = 0.4,
|
||||
_mcl_blast_resistance = 0.4,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_on_bone_meal = function(itemstack, placer, pointed_thing)
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
spread_nether_plants(pointed_thing.under,node)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -773,6 +723,19 @@ minetest.register_craft({
|
|||
mcl_stairs.register_stair("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_stair_groups, false, S("Crimson Stair"))
|
||||
mcl_stairs.register_slab("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_slab_groups, false, S("Crimson Slab"))
|
||||
|
||||
mcl_dye.register_on_bone_meal_apply(function(pt,user)
|
||||
if not pt.type == "node" then return end
|
||||
local node = minetest.get_node(pt.under)
|
||||
if node.name == "mcl_nether:netherrack" then
|
||||
local n = has_nylium_neighbor(pt.under)
|
||||
if n then
|
||||
minetest.set_node(pt.under,n)
|
||||
end
|
||||
elseif node.name == "mcl_crimson:warped_nylium" or node.name == "mcl_crimson:crimson_nylium" then
|
||||
spread_nether_plants(pt.under,node)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Turn Crimson Nylium and Warped Nylium below solid block into Netherrack",
|
||||
nodenames = {"mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium"},
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
name = mcl_crimson
|
||||
author = debiankaios, Exhale
|
||||
depends = mcl_core, mcl_fences, mcl_stairs, mobs_mc, mcl_util, mcl_dye, mcl_flowerpots, mcl_doors
|
||||
depends = mcl_core, mcl_stairs, mobs_mc, mcl_util, mcl_dye, mcl_flowerpots
|
||||
|
|
|
@ -111,7 +111,7 @@ for _, p in pairs(deepslate_ores) do
|
|||
end
|
||||
|
||||
if copper_mod then
|
||||
register_deepslate_ore("Copper", "mcl_copper:raw_copper", "mcl_copper:copper_ingot", 3, 4)
|
||||
register_deepslate_ore("Copper", "mcl_copper:raw_copper", "mcl_copper:copper_ingot", 4, 4)
|
||||
end
|
||||
|
||||
local redstone_timer = 68.28
|
||||
|
|
|
@ -25,7 +25,7 @@ end
|
|||
|
||||
-- Registers a door
|
||||
-- name: The name of the door
|
||||
-- def: a table with the following fields:
|
||||
-- def: a table with the folowing fields:
|
||||
-- description
|
||||
-- inventory_image
|
||||
-- groups
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# mcl_dye
|
||||
|
||||
# Bone meal API
|
||||
Callback and particle functions.
|
||||
|
||||
## mcl_dye.add_bone_meal_particle(pos, def)
|
||||
Spawns standard or custom bone meal particles.
|
||||
* `pos`: position, is ignored if you define def.minpos and def.maxpos
|
||||
* `def`: (optional) particle definition
|
||||
|
||||
## mcl_dye.register_on_bone_meal_apply(function(pointed_thing, user))
|
||||
Called when the bone meal is applied anywhere.
|
||||
* `pointed_thing`: exact pointing location (see Minetest API), where the bone meal is applied
|
||||
* `user`: ObjectRef of the player who aplied the bone meal, can be nil!
|
|
@ -15,6 +15,7 @@ mcl_dye = {}
|
|||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local math = math
|
||||
local string = string
|
||||
|
||||
-- Base color groups:
|
||||
|
@ -114,23 +115,328 @@ for _, row in pairs(dyes) do
|
|||
})
|
||||
end
|
||||
|
||||
-- Legacy support for things now in mcl_bone_meal.
|
||||
-- These shims will at some time in the future be removed.
|
||||
-- Bone meal code to be moved into its own mod.
|
||||
--
|
||||
function mcl_dye.add_bone_meal_particle(pos, def)
|
||||
minetest.log("warning", "mcl_dye.add_bone_meal_particles() is deprecated. Read mcl_bone_meal/API.md!")
|
||||
local lines = string.split(debug.traceback(),"\n")
|
||||
for _,line in ipairs(lines) do
|
||||
minetest.log("warning",line)
|
||||
if not def then
|
||||
def = {}
|
||||
end
|
||||
mcl_bone_meal.add_bone_meal_particle(pos, def)
|
||||
minetest.add_particlespawner({
|
||||
amount = def.amount or 10,
|
||||
time = def.time or 0.1,
|
||||
minpos = def.minpos or vector.subtract(pos, 0.5),
|
||||
maxpos = def.maxpos or vector.add(pos, 0.5),
|
||||
minvel = def.minvel or vector.new(-0.01, 0.01, -0.01),
|
||||
maxvel = def.maxvel or vector.new(0.01, 0.01, 0.01),
|
||||
minacc = def.minacc or vector.new(0, 0, 0),
|
||||
maxacc = def.maxacc or vector.new(0, 0, 0),
|
||||
minexptime = def.minexptime or 1,
|
||||
maxexptime = def.maxexptime or 4,
|
||||
minsize = def.minsize or 0.7,
|
||||
maxsize = def.maxsize or 2.4,
|
||||
texture = "mcl_particles_bonemeal.png^[colorize:#00EE00:125", -- TODO: real MC color
|
||||
glow = def.glow or 1,
|
||||
})
|
||||
end
|
||||
|
||||
mcl_dye.bone_meal_callbacks = {}
|
||||
|
||||
function mcl_dye.register_on_bone_meal_apply(func)
|
||||
minetest.log("warning", "mcl_dye.register_on_bone_meal_apply() is deprecated. Read mcl_bone_meal/API.md!")
|
||||
mcl_bone_meal.register_on_bone_meal_apply(func)
|
||||
table.insert(mcl_dye.bone_meal_callbacks, func)
|
||||
end
|
||||
|
||||
local function apply_bone_meal(pointed_thing, user)
|
||||
-- Bone meal currently spawns all flowers found in the plains.
|
||||
local flowers_table_plains = {
|
||||
"mcl_flowers:dandelion",
|
||||
"mcl_flowers:dandelion",
|
||||
"mcl_flowers:poppy",
|
||||
|
||||
"mcl_flowers:oxeye_daisy",
|
||||
"mcl_flowers:tulip_orange",
|
||||
"mcl_flowers:tulip_red",
|
||||
"mcl_flowers:tulip_white",
|
||||
"mcl_flowers:tulip_pink",
|
||||
"mcl_flowers:azure_bluet",
|
||||
}
|
||||
local flowers_table_simple = {
|
||||
"mcl_flowers:dandelion",
|
||||
"mcl_flowers:poppy",
|
||||
}
|
||||
local flowers_table_swampland = {
|
||||
"mcl_flowers:blue_orchid",
|
||||
}
|
||||
local flowers_table_flower_forest = {
|
||||
"mcl_flowers:dandelion",
|
||||
"mcl_flowers:poppy",
|
||||
"mcl_flowers:oxeye_daisy",
|
||||
"mcl_flowers:tulip_orange",
|
||||
"mcl_flowers:tulip_red",
|
||||
"mcl_flowers:tulip_white",
|
||||
"mcl_flowers:tulip_pink",
|
||||
"mcl_flowers:azure_bluet",
|
||||
"mcl_flowers:allium",
|
||||
}
|
||||
|
||||
local pos = pointed_thing.under
|
||||
local n = minetest.get_node(pos)
|
||||
if n.name == "" then return false end
|
||||
|
||||
if mcl_util.check_area_protection(pos, pointed_thing.above, user) then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, func in pairs(mcl_dye.bone_meal_callbacks) do
|
||||
if func(pointed_thing, user) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.get_item_group(n.name, "sapling") >= 1 then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Saplings: 45% chance to advance growth stage
|
||||
if math.random(1, 100) <= 45 then
|
||||
if n.name == "mcl_cherry_blossom:cherrysapling" then
|
||||
return mcl_cherry_blossom.generate_cherry_tree(pos) -- If cherry blossom sapling, run that callback instead.
|
||||
else
|
||||
return mcl_core.grow_sapling(pos, n)
|
||||
end
|
||||
end
|
||||
elseif minetest.get_item_group(n.name, "mushroom") == 1 then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Try to grow huge mushroom
|
||||
|
||||
-- Must be on a dirt-type block
|
||||
local below = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
if below.name ~= "mcl_core:mycelium" and below.name ~= "mcl_core:dirt" and minetest.get_item_group(below.name, "grass_block") ~= 1 and below.name ~= "mcl_core:coarse_dirt" and below.name ~= "mcl_core:podzol" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Select schematic
|
||||
local schematic, offset, height
|
||||
if n.name == "mcl_mushrooms:mushroom_brown" then
|
||||
schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_brown.mts"
|
||||
offset = { x = -3, y = -1, z = -3 }
|
||||
height = 8
|
||||
elseif n.name == "mcl_mushrooms:mushroom_red" then
|
||||
schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_red.mts"
|
||||
offset = { x = -2, y = -1, z = -2 }
|
||||
height = 8
|
||||
else
|
||||
return false
|
||||
end
|
||||
-- 40% chance
|
||||
if math.random(1, 100) <= 40 then
|
||||
-- Check space requirements
|
||||
for i=1,3 do
|
||||
local cpos = vector.add(pos, {x=0, y=i, z=0})
|
||||
if minetest.get_node(cpos).name ~= "air" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
local yoff = 3
|
||||
local minp, maxp = {x=pos.x-3, y=pos.y+yoff, z=pos.z-3}, {x=pos.x+3, y=pos.y+yoff+(height-3), z=pos.z+3}
|
||||
local diff = vector.subtract(maxp, minp)
|
||||
diff = vector.add(diff, {x=1,y=1,z=1})
|
||||
local totalnodes = diff.x * diff.y * diff.z
|
||||
local goodnodes = minetest.find_nodes_in_area(minp, maxp, {"air", "group:leaves"})
|
||||
if #goodnodes < totalnodes then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Place the huge mushroom
|
||||
minetest.remove_node(pos)
|
||||
local place_pos = vector.add(pos, offset)
|
||||
local ok = minetest.place_schematic(place_pos, schematic, 0, nil, false)
|
||||
return ok ~= nil
|
||||
end
|
||||
return false
|
||||
-- Wheat, Potato, Carrot, Pumpkin Stem, Melon Stem: Advance by 2-5 stages
|
||||
elseif string.find(n.name, "mcl_farming:wheat_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_wheat", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:potato_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_potato", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:carrot_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_carrot", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:pumpkin_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_pumpkin_stem", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:melontige_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_melon_stem", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:beetroot_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Beetroot: 75% chance to advance to next stage
|
||||
if math.random(1, 100) <= 75 then
|
||||
return mcl_farming:grow_plant("plant_beetroot", pos, n, 1, true)
|
||||
end
|
||||
elseif string.find(n.name, "mcl_farming:sweet_berry_bush_") then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
if n.name == "mcl_farming:sweet_berry_bush_3" then
|
||||
return minetest.add_item(vector.offset(pos,math.random()-0.5,math.random()-0.5,math.random()-0.5),"mcl_farming:sweet_berry")
|
||||
else
|
||||
return mcl_farming:grow_plant("plant_sweet_berry_bush", pos, n, 0, true)
|
||||
end
|
||||
elseif n.name == "mcl_cocoas:cocoa_1" or n.name == "mcl_cocoas:cocoa_2" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Cocoa: Advance by 1 stage
|
||||
mcl_cocoas.grow(pos)
|
||||
return true
|
||||
elseif minetest.get_item_group(n.name, "grass_block") == 1 then
|
||||
-- Grass Block: Generate tall grass and random flowers all over the place
|
||||
for i = -7, 7 do
|
||||
for j = -7, 7 do
|
||||
for y = -1, 1 do
|
||||
pos = vector.offset(pointed_thing.above, i, y, j)
|
||||
n = minetest.get_node(pos)
|
||||
local n2 = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
||||
|
||||
if n.name ~= "" and n.name == "air" and (minetest.get_item_group(n2.name, "grass_block_no_snow") == 1) then
|
||||
-- Randomly generate flowers, tall grass or nothing
|
||||
if math.random(1, 100) <= 90 / ((math.abs(i) + math.abs(j)) / 2)then
|
||||
-- 90% tall grass, 10% flower
|
||||
mcl_dye.add_bone_meal_particle(pos, {amount = 4})
|
||||
if math.random(1,100) <= 90 then
|
||||
local col = n2.param2
|
||||
minetest.add_node(pos, {name="mcl_flowers:tallgrass", param2=col})
|
||||
else
|
||||
local flowers_table
|
||||
if mg_name == "v6" then
|
||||
flowers_table = flowers_table_plains
|
||||
else
|
||||
local biome = minetest.get_biome_name(minetest.get_biome_data(pos).biome)
|
||||
if biome == "Swampland" or biome == "Swampland_shore" or biome == "Swampland_ocean" or biome == "Swampland_deep_ocean" or biome == "Swampland_underground" then
|
||||
flowers_table = flowers_table_swampland
|
||||
elseif biome == "FlowerForest" or biome == "FlowerForest_beach" or biome == "FlowerForest_ocean" or biome == "FlowerForest_deep_ocean" or biome == "FlowerForest_underground" then
|
||||
flowers_table = flowers_table_flower_forest
|
||||
elseif biome == "Plains" or biome == "Plains_beach" or biome == "Plains_ocean" or biome == "Plains_deep_ocean" or biome == "Plains_underground" or biome == "SunflowerPlains" or biome == "SunflowerPlains_ocean" or biome == "SunflowerPlains_deep_ocean" or biome == "SunflowerPlains_underground" then
|
||||
flowers_table = flowers_table_plains
|
||||
else
|
||||
flowers_table = flowers_table_simple
|
||||
end
|
||||
end
|
||||
minetest.add_node(pos, {name=flowers_table[math.random(1, #flowers_table)]})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
|
||||
-- Double flowers: Drop corresponding item
|
||||
elseif n.name == "mcl_flowers:rose_bush" or n.name == "mcl_flowers:rose_bush_top" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:rose_bush")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:peony" or n.name == "mcl_flowers:peony_top" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:peony")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:lilac" or n.name == "mcl_flowers:lilac_top" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:lilac")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:sunflower" or n.name == "mcl_flowers:sunflower_top" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:sunflower")
|
||||
return true
|
||||
|
||||
elseif n.name == "mcl_flowers:tallgrass" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Tall Grass: Grow into double tallgrass
|
||||
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
|
||||
local topnode = minetest.get_node(toppos)
|
||||
if minetest.registered_nodes[topnode.name].buildable_to then
|
||||
minetest.set_node(pos, { name = "mcl_flowers:double_grass", param2 = n.param2 })
|
||||
minetest.set_node(toppos, { name = "mcl_flowers:double_grass_top", param2 = n.param2 })
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
Here for when Bonemeal becomes an api, there's code if needed for handling applying to bamboo.
|
||||
-- Handle applying bonemeal to bamboo.
|
||||
elseif mcl_bamboo.is_bamboo(n.name) then
|
||||
local success = mcl_bamboo.grow_bamboo(pos, true)
|
||||
if success then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
end
|
||||
return success
|
||||
--]]
|
||||
elseif n.name == "mcl_flowers:fern" then
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Fern: Grow into large fern
|
||||
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
|
||||
local topnode = minetest.get_node(toppos)
|
||||
if minetest.registered_nodes[topnode.name].buildable_to then
|
||||
minetest.set_node(pos, { name = "mcl_flowers:double_fern", param2 = n.param2 })
|
||||
minetest.set_node(toppos, { name = "mcl_flowers:double_fern_top", param2 = n.param2 })
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
mcl_dye.apply_bone_meal = apply_bone_meal
|
||||
|
||||
-- Bone meal item registration.
|
||||
--
|
||||
-- To be moved into its own mod.
|
||||
--
|
||||
minetest.register_craftitem(":mcl_bone_meal:bone_meal", {
|
||||
inventory_image = "mcl_bone_meal_bone_meal.png",
|
||||
description = S("Bone Meal"),
|
||||
_tt_help = S("Speeds up plant growth"),
|
||||
_doc_items_longdesc = S("Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants."),
|
||||
_doc_items_usagehelp = S("Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place."),
|
||||
stack_max = 64,
|
||||
on_place = function(itemstack, user, pointed_thing)
|
||||
-- Use pointed node's on_rightclick function first, if present
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if user and not user:get_player_control().sneak then
|
||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- Use the bone meal on the ground
|
||||
if (apply_bone_meal(pointed_thing, user) and (not minetest.is_creative_enabled(user:get_player_name()))) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||
-- Apply bone meal, if possible
|
||||
local pointed_thing
|
||||
if dropnode.name == "air" then
|
||||
pointed_thing = { above = droppos, under = { x=droppos.x, y=droppos.y-1, z=droppos.z } }
|
||||
else
|
||||
pointed_thing = { above = pos, under = droppos }
|
||||
end
|
||||
local success = apply_bone_meal(pointed_thing, nil)
|
||||
if success then
|
||||
stack:take_item()
|
||||
end
|
||||
return stack
|
||||
end,
|
||||
_dispense_into_walkable = true
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_bone_meal:bone_meal 3",
|
||||
recipe = {{"mcl_mobitems:bone"}},
|
||||
})
|
||||
|
||||
|
||||
-- Dye creation recipes.
|
||||
--
|
||||
minetest.register_craft({
|
||||
|
@ -303,16 +609,19 @@ minetest.register_craft({
|
|||
output = "mcl_dye:magenta 2",
|
||||
recipe = {"mcl_dye:violet", "mcl_dye:pink"},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "mcl_dye:pink 2",
|
||||
recipe = {"mcl_dye:red", "mcl_dye:white"},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "mcl_dye:cyan 2",
|
||||
recipe = {"mcl_dye:blue", "mcl_dye:dark_green"},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "mcl_dye:violet 2",
|
||||
|
|
|
@ -17,3 +17,11 @@ Magenta Dye=Magenta Farbstoff
|
|||
Pink Dye=Rosa Farbstoff
|
||||
This item is a dye which is used for dyeing and crafting.=Dieser Gegenstand ist ein Farbstoff, der zum Einfärben und in der Herstellung benutzt werden kann.
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Rechtsklicken Sie auf ein Schaf, um seine Wolle zu färben. Andere Dinge werden mit der Fertigung eingefärbt.
|
||||
Bone Meal=Knochenmehl
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Knochenmehl ist ein weißer Farbstoff und auch nützlich als Dünger, um das Wachstum vieler Pflanzen zu beschleunigen.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Rechtsklicken Sie auf ein Schaf, um die Wolle weiß einzufärben. Rechtsklicken Sie auf eine Pflanze, um ihr Wachstum zu beschleunigen. Beachten Sie, dass nicht alle Pflanzen darauf ansprechen. Benutzen Sie es auf einem Grasblock, wächst viel hohes Gras und vielleicht auch ein paar Blumen.
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=Kakaobohnen sind ein brauner Farbstoff und werden benutzt, um Kakao anzupflanzen.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie auf ein Schaf, um die Wolle braun einzufärben. Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen.
|
||||
Cocoa Beans=Kakaobohnen
|
||||
Grows at the side of jungle trees=Wächst an der Seite von Dschungelbäumen
|
||||
Speeds up plant growth=Beschleunigt Pflanzenwachstum
|
||||
|
|
|
@ -17,3 +17,9 @@ Magenta Dye=Tinte magenta
|
|||
Pink Dye=Tinte rosado
|
||||
This item is a dye which is used for dyeing and crafting.=Este artículo es un tinte que se utiliza para teñir y elaborar.
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Haga clic derecho sobre una oveja para teñir su lana. Otras cosas pueden ser teñidas mediante la elaboración.
|
||||
Bone Meal=Harina de hueso
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La harina de hueso es un tinte blanco y también es útil como fertilizante para acelerar el crecimiento de muchas plantas.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=RHaga clic derecho en una oveja para volver su lana blanca. Haga clic derecho en una planta para acelerar su crecimiento. Tenga en cuenta que no todas las plantas pueden ser fertilizadas de esta manera. Cuando haces clic derecho en un bloque de hierba, crecerán hierba alta y flores por todo el lugar.
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=Los granos de cacao son un tinte marrón y se pueden usar para plantar cacao.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en una oveja para convertir su lana en marrón. Haga clic derecho en el costado del tronco de un árbol de jungla para plantar un cacao joven.
|
||||
Cocoa Beans=Granos de cacao
|
||||
|
|
|
@ -17,3 +17,11 @@ Magenta Dye=Teinture Magenta
|
|||
Pink Dye=Teinture Rose
|
||||
This item is a dye which is used for dyeing and crafting.=Cet objet est un colorant utilisé pour la teinture et l'artisanat.
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Clic droit sur un mouton pour teindre sa laine. D'autres choses sont teintes par l'artisanat.
|
||||
Bone Meal=Farine d'Os
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La farine d'os est une teinture blanche et également utile comme engrais pour accélérer la croissance de nombreuses plantes.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Cliquez avec le bouton droit sur un mouton pour blanchir sa laine. Cliquez avec le bouton droit sur une plante pour accélérer sa croissance. Notez que toutes les plantes ne peuvent pas être fertilisées comme ça. Lorsque vous cliquez avec le bouton droit sur un bloc d'herbe, les hautes herbes et les fleurs poussent partout.
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=Les fèves de cacao ont une teinture brune et peuvent être utilisées pour planter du cacao.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Faites un clic droit sur un mouton pour brunir sa laine. Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacao.
|
||||
Cocoa Beans=Fèves de Cacao
|
||||
Grows at the side of jungle trees=Pousse à côté des arbres de la jungle
|
||||
Speeds up plant growth=Accélère la croissance des plantes
|
||||
|
|
|
@ -17,3 +17,11 @@ Magenta Dye=Karmazynowa farba
|
|||
Pink Dye=Różowa farba
|
||||
This item is a dye which is used for dyeing and crafting.=Ten przedmiot to farba wykorzystywana to farbowania i wytwarzania.
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Kliknij prawym na owcę aby zafarbować jej wełnę. Inne rzeczy mogą być zafarbowane przy wytwarzaniu.
|
||||
Bone Meal=Mączka kostna
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Mączka kostna to biała farba i przydatny nawóz, który przyspiesza rośnięcie wielu roślin.
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Kliknij prawym na owcę, aby wybielić jej wełnę. Kliknij prawym na roślinę aby przyspieszyć jej wzrost. Zważ, że nie na wszystkie rośliny to tak działa. Gdy klikniesz prawym na blok trawy, wysoka trawa wyrośnie wokół.
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=Ziarna kakaowe mogą być wykorzystane do sadzenia kakao.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym aby zafarbować wełnę owcy na brązowo. Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao.
|
||||
Cocoa Beans=Ziarna kakaowe
|
||||
Grows at the side of jungle trees=Rośnie na boku tropikalnych drzew
|
||||
Speeds up plant growth=Przyspiesza wzrost roślin
|
||||
|
|
|
@ -22,3 +22,6 @@ Bone meal is a white dye and also useful as a fertilizer to speed up the growth
|
|||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Кликните правой по овце, чтобы сделать её шерсть белой. Кликните правой по растению, чтобы ускорить его рост. Имейте в виду, что не все растения можно удобрять таким способом. Если вы кликнете по травяному блоку, то на этом месте вырастет высокая трава и цветы.
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=Какао-бобы являются коричневым красителем. Их также можно использовать, чтобы посадить какао.
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по овце, чтобы сделать её шерсть коричневой. Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао.
|
||||
Cocoa Beans=Какао-бобы
|
||||
Grows at the side of jungle trees=Растут на стволах тропических деревьев
|
||||
Speeds up plant growth=Ускоряет рост растений
|
||||
|
|
|
@ -17,3 +17,9 @@ Magenta Dye=洋紅色染料
|
|||
Pink Dye=粉紅色染料
|
||||
This item is a dye which is used for dyeing and crafting.=這個物品是一種用於染色和合成的染料。
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=右鍵單擊綿羊以染它的毛。其他東西是通過合成染色的。
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=骨粉是一種白色染料,也可作為肥料,加速許多植物的生長。
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=右鍵點擊一隻羊,使其羊毛變白。右鍵點擊一株植物以加快其生長速度。注意,不是所有的植物都能像這樣施肥。當你右鍵點擊一個草方時,高高的草和花會到處生長。
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=可可豆是一種棕色染料,也可用於種植可可。
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊一隻羊,使其羊毛變成褐色。右鍵點擊叢林木的一側,可以種植一個可可。
|
||||
Grows at the side of jungle trees=在叢林木側生長
|
||||
Speeds up plant growth=加速植物生長
|
||||
|
|
|
@ -17,3 +17,11 @@ Magenta Dye=
|
|||
Pink Dye=
|
||||
This item is a dye which is used for dyeing and crafting.=
|
||||
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=
|
||||
Bone Meal=
|
||||
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=
|
||||
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=
|
||||
Cocoa beans are a brown dye and can be used to plant cocoas.=
|
||||
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=
|
||||
Cocoa Beans=
|
||||
Grows at the side of jungle trees=
|
||||
Speeds up plant growth=
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
name = mcl_dye
|
||||
description = Adds color to your world!
|
||||
depends = mcl_bone_meal, mcl_cocoas
|
||||
depends = mcl_core, mcl_flowers, mcl_mobitems, mcl_cocoas
|
||||
|
|
|
@ -691,7 +691,7 @@ mcl_enchanting.enchantments.soul_speed = {
|
|||
disallow = {non_combat_armor = true},
|
||||
incompatible = {frost_walker = true},
|
||||
weight = 2,
|
||||
description = S("Increases walking speed on soul sand and soul soil."),
|
||||
description = S("Increases walking speed on soul sand."),
|
||||
curse = false,
|
||||
on_enchant = function() end,
|
||||
requires_tool = false,
|
||||
|
|
|
@ -68,7 +68,7 @@ Mined blocks drop themselves.=Abgebaute Blöcke werfen sich selbst ab.
|
|||
Smite=Qual
|
||||
Increases damage to undead mobs.=Erhöht Schaden für untote Mobs.
|
||||
Soul Speed=Schnelle Seele
|
||||
Increases walking speed on soul sand and soul soil.=Erhöht Gehgeschwindigkeit auf Seelensand.
|
||||
Increases walking speed on soul sand.=Erhöht Gehgeschwindigkeit auf Seelensand.
|
||||
Sweeping Edge=Schwungklinge
|
||||
Increases sweeping attack damage.=Erhöht Schwungangriffsschaden.
|
||||
Thorns=Dornen
|
||||
|
|
|
@ -36,7 +36,7 @@ Increases mob loot.=Incrementa el botín de los enemigos.
|
|||
Increases rate of good loot (enchanting books, etc.)=Incrementa la probabilidad de encontrar tesoros.
|
||||
Increases sweeping attack damage.=Incrementa el daño de efecto area.
|
||||
Increases underwater movement speed.=Incrementa la velocidad de nado bajo el agua.
|
||||
Increases walking speed on soul sand and soul soil.=Incrementa la velocidad al caminar sobre arena de Almas.
|
||||
Increases walking speed on soul sand.=Incrementa la velocidad al caminar sobre arena de Almas.
|
||||
Infinity=Infinidad
|
||||
Item destroyed on death.=El objeto se destruye tras tu muerte.
|
||||
Knockback=Empuje
|
||||
|
|
|
@ -36,7 +36,7 @@ Increases mob loot.=Augmente le butin des mobs.
|
|||
Increases rate of good loot (enchanting books, etc.)=Augmente le taux de bon butin (livres enchanteurs, etc.)
|
||||
Increases sweeping attack damage.=Augmente les dégâts de l'épée
|
||||
Increases underwater movement speed.=Augmente la vitesse de déplacement sous l'eau.
|
||||
Increases walking speed on soul sand and soul soil.=Augmente la vitesse de marche sur le sable des âmes.
|
||||
Increases walking speed on soul sand.=Augmente la vitesse de marche sur le sable des âmes.
|
||||
Infinity=Infinité
|
||||
Item destroyed on death.=Objet détruit à la mort.
|
||||
Knockback=Recul
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue