This commit is contained in:
root 2021-06-12 20:20:04 +02:00
parent f36efacca8
commit 6f3c3f8b60
103 changed files with 4143 additions and 4353 deletions

View file

@ -18,5 +18,6 @@ Based on Immersive Sounds .36 mod by Neuromancer and optimized to run on servers
- 1.3 - Added API for use with other mods, code rewrite
- 1.4 - Re-ordered water sets to come before fire and lava, day/night sounds play when leaves around and above ground
- 1.5 - Added 'flame_sound' and fire redo check, code tidy and tweak, added ephemeral flag for background sounds.
- 1.6 - Finding env_sounds disables water and lava sets, added 'ambience_water_move' flag to override water walking sounds, use eye level for head node.
Code license: MIT

View file

@ -1,13 +1,6 @@
ambience = {}
-- override default water sounds
minetest.override_item("default:water_source", { sounds = {} })
minetest.override_item("default:water_flowing", { sounds = {} })
minetest.override_item("default:river_water_source", { sounds = {} })
minetest.override_item("default:river_water_flowing", { sounds = {} })
-- settings
local SOUNDVOLUME = 1.0
local MUSICVOLUME = 1.0
@ -132,13 +125,14 @@ local get_ambience = function(player, tod, name)
-- get foot and head level nodes at player position
local pos = player:get_pos() ; if not pos then return end
local prop = player:get_properties()
pos.y = pos.y + 1.4 -- head level
pos.y = pos.y + prop.eye_height -- eye level
local nod_head = pplus and name and playerplus[name]
and playerplus[name].nod_head or minetest.get_node(pos).name
pos.y = pos.y - 1.2 -- foot level
pos.y = (pos.y - prop.eye_height) + 0.2 -- foot level
local nod_feet = pplus and name and playerplus[name]
and playerplus[name].nod_feet or minetest.get_node(pos).name
@ -190,19 +184,17 @@ minetest.register_globalstep(function(dtime)
if timer < 1 then return end
timer = 0
-- get list of players and set some variables
local players = minetest.get_connected_players()
local player_name, number, chance, ambience, handler, ok
local tod = minetest.get_timeofday()
-- loop through players
for n = 1, #players do
for _, player in ipairs(minetest.get_connected_players()) do
player_name = players[n]:get_player_name()
player_name = player:get_player_name()
--local t1 = os.clock()
local set_name, MORE_GAIN = get_ambience(players[n], tod, player_name)
local set_name, MORE_GAIN = get_ambience(player, tod, player_name)
--print(string.format("elapsed time: %.4f\n", os.clock() - t1))
@ -258,25 +250,24 @@ minetest.register_globalstep(function(dtime)
playing[player_name].handler = handler
-- set timer to stop sound
minetest.after(ambience.length, function()
--print("-- after", set_name, handler)
-- make sure we are stopping same sound we started
if playing[player_name]
and playing[player_name].handler
and playing[player_name].handler == handler then
minetest.after(ambience.length, function(handler, player_name)
--print("-- timed stop", set_name, handler)
if handler then
minetest.sound_stop(handler)
end
-- reset variables if handlers match
if playing[player_name]
and playing[player_name].handler == handler then
--print("-- timed reset", handler, player_name)
-- reset player variables
playing[player_name].set = nil
playing[player_name].gain = nil
playing[player_name].handler = nil
end
end)
end, handler, player_name)
end
end
end

View file

@ -1,2 +1,5 @@
# If enabled will play a random music file from ./minetest/sounds at midnight
ambience_music (Ambience music) bool true
# If enabled then ambience will take over sounds when moving in water
ambience_water_move (Ambience water movement) bool true

View file

@ -25,7 +25,15 @@ ambience.add_set("underwater", {
end
})
-- Splashing sound plays when player walks inside water nodes
-- Splashing sound plays when player walks inside water nodes (if enabled)
if minetest.settings:get_bool("ambience_water_move") ~= false then
-- override default water sounds
minetest.override_item("default:water_source", { sounds = {} })
minetest.override_item("default:water_flowing", { sounds = {} })
minetest.override_item("default:river_water_source", { sounds = {} })
minetest.override_item("default:river_water_flowing", { sounds = {} })
ambience.add_set("splash", {
@ -49,7 +57,9 @@ ambience.add_set("splash", {
end
})
-- check for env_sounds mod, if not found enable water flowing sounds
end
-- check for env_sounds mod, if not found enable water flowing and lava sounds
if not minetest.get_modpath("env_sounds") then
-- Water sound plays when near flowing water
@ -102,6 +112,32 @@ ambience.add_set("river", {
end
})
-- Lava sound plays when near lava
ambience.add_set("lava", {
frequency = 1000,
sounds = {
{name = "lava", length = 7}
},
nodes = {"default:lava_source", "default:lava_flowing"},
sound_check = function(def)
local c = (def.totals["default:lava_source"] or 0)
+ (def.totals["default:lava_flowing"] or 0)
if c > 20 then
return "lava", 0.5
elseif c > 5 then
return "lava"
end
end
})
else
print ("[Ambience] found env_sounds, flowing water sounds disabled.")
end
@ -170,32 +206,6 @@ ambience.add_set("largefire", {
end
-- Lava sound plays when near lava
ambience.add_set("lava", {
frequency = 1000,
sounds = {
{name = "lava", length = 7}
},
nodes = {"default:lava_source", "default:lava_flowing"},
sound_check = function(def)
local c = (def.totals["default:lava_source"] or 0)
+ (def.totals["default:lava_flowing"] or 0)
if c > 20 then
return "lava", 0.5
elseif c > 5 then
return "lava"
end
end
})
-- Beach sounds play when below y-pos 6 and 150+ water source found
ambience.add_set("beach", {

View file

@ -6,18 +6,17 @@ local bridger_colors = {
}
for _, color in pairs(bridger_colors) do
local oldname = color
local newname = string.lower(color)
if minetest.get_modpath("moreblocks") then
stairsplus:register_alias_all("bridges", "block_"..oldname, "bridger", "block_"..newname)
minetest.register_alias("bridges:step_"..oldname, "bridger:panel_block_"..newname)
stairsplus:register_alias_all("bridges", "block_" .. oldname, "bridger", "block_" .. newname)
minetest.register_alias("bridges:step_" .. oldname, "bridger:panel_block_" .. newname)
elseif minetest.get_modpath("stairs") then
minetest.register_alias("stairs:slab_block_"..oldname, "stairs:slab_block_"..newname)
minetest.register_alias("stairs:stair_block_"..oldname, "stairs:stair_block_"..newname)
minetest.register_alias("stairs:slab_block_" .. oldname, "stairs:slab_block_" .. newname)
minetest.register_alias("stairs:stair_block_" .. oldname, "stairs:stair_block_" .. newname)
end
local bridger_error1 = {
"block_",
"step_",
@ -41,12 +40,11 @@ for _, color in pairs(bridger_colors) do
"truss_substructure_end_left_slant_",
"truss_substructure_end_right_slant_"
}
for _, prefix in pairs (bridger_error1) do
minetest.register_alias("bridges:"..prefix..oldname, "bridger:"..prefix..newname)
minetest.register_alias("bridges:" .. prefix .. oldname, "bridger:" .. prefix .. newname)
end
local bridger_error2 = {
"truss_substructure_mid",
"truss_substructure_simple",
@ -58,18 +56,18 @@ for _, color in pairs(bridger_colors) do
"truss_superstructure_simple",
"truss_superstructure_simple_end_right"
}
for _, prefix in pairs (bridger_error2) do
minetest.register_alias("bridges:"..prefix..oldname, "bridger:"..prefix.."_"..newname)
minetest.register_alias("bridges:" .. prefix .. oldname, "bridger:" .. prefix .. "_" .. newname)
end
minetest.register_alias("bridges:truss_superstructure_simple_end"..oldname, "bridger:truss_superstructure_simple_end_left_"..newname)
minetest.register_alias("bridges:girder_left_end"..oldname, "bridger:girder_left_"..newname)
minetest.register_alias("bridges:truss_superstructure_simple_end" .. oldname, "bridger:truss_superstructure_simple_end_left_" .. newname)
minetest.register_alias("bridges:girder_left_end" .. oldname, "bridger:girder_left_" .. newname)
end
minetest.register_alias("bridges:corrugated_steel", "bridger:corrugated_steel_steel")
minetest.register_alias("bridges:corrugated_steel_ceiling", "bridger:corrugated_steel_ceiling_steel")
minetest.register_alias("bridges:scaffolding", "bridger:scaffolding")
minetest.register_alias("bridges:zbridges_diagonal_steel_rod", "bridger:bridges_diagonal_steel_rod")
minetest.register_alias("bridges:zbridges_steel_rod", "bridger:bridges_steel_rod")
minetest.register_alias("bridges:zbridges_steel_rod", "bridger:bridges_steel_rod")

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,6 @@ minetest.register_node("bridger:scaffolding", {
drawtype = "glasslike_framed_optional",
tiles = {"bridges_scaffolding.png", "bridges_scaffolding_detail.png"},
paramtype = "light",
paramtype2 = "glasslikeliquidlevel",
sunlight_propagates = true,
walkable = false,
climbable = true,
@ -12,9 +11,9 @@ minetest.register_node("bridger:scaffolding", {
})
dofile(minetest.get_modpath("bridger").."/nodes.lua")
dofile(minetest.get_modpath("bridger").."/crafts.lua")
dofile(minetest.get_modpath("bridger") .. "/nodes.lua")
dofile(minetest.get_modpath("bridger") .. "/crafts.lua")
if minetest.settings:get_bool("Bridger_enable_alias") then
dofile(minetest.get_modpath("bridger").."/alias.lua")
end
dofile(minetest.get_modpath("bridger") .. "/alias.lua")
end

View file

@ -1 +1,4 @@
name = bridger
name = bridger
depends = default
optional_depends = stairs, moreblocks, mesecons
description = Adds a large number of advanced nodes conducive to building large, industrial bridges.

File diff suppressed because it is too large Load diff

View file

@ -10,15 +10,17 @@ Features:
- Particle effects added
- Dropped items slide on nodes with {slippery} groups
- Items stuck inside solid nodes move to nearest empty space
- Added 'dropped_step(self, pos, dtime)' custom on_step for dropped items
- Added 'dropped_step(self, pos, dtime, moveresult)' custom on_step for dropped items
'self.node_inside' contains node table that item is inside
'self.def_inside' contains node definition for above
'self.node_under' contains node table that is below item
'self.def_under' contains node definition for above
'self.age' holds age of dropped item in seconds
'self.itemstring' contains itemstring e.g. "default:dirt", "default:ice 20"
'self.is_moving' true if dropped item is moving
'pos' holds position of dropped item
'dtime' used for timers
'moveresult' table containing collision info
return false to skip further checks by builtin_item

View file

@ -271,7 +271,7 @@ core.register_entity(":__builtin:item", {
pos.y = pos.y + ((total_count - count) / max_count) * 0.15
self.object:move_to(pos)
self.age = 0 -- Handle as new entity
self.age = 0 -- Reset age
-- Merge velocities
local vel_a = self.object:get_velocity()
@ -300,35 +300,49 @@ core.register_entity(":__builtin:item", {
-- get nodes every 1/4 second
self.timer = (self.timer or 0) + dtime
if self.timer > 0.25 or not self.node_inside then
if self.timer < 0.25 and self.node_inside then
return
end
self.node_inside = minetest.get_node_or_nil(pos)
self.def_inside = self.node_inside
and core.registered_nodes[self.node_inside.name]
self.node_inside = minetest.get_node_or_nil(pos)
self.def_inside = self.node_inside
and core.registered_nodes[self.node_inside.name]
-- get ground node for collision
self.node_under = nil
self.falling_state = true
-- get ground node for collision
self.node_under = nil
self.falling_state = true
if moveresult and moveresult.touching_ground then
--[[ new ground check (glitchy)
if moveresult and moveresult.touching_ground then
for _, info in ipairs(moveresult.collisions) do
for _, info in ipairs(moveresult.collisions) do
if info.axis == "y" then
if info.axis == "y" then
self.node_under = core.get_node(info.node_pos)
self.falling_state = false
self.node_under = core.get_node_or_nil(info.node_pos)
self.falling_state = false
break
end
break
end
end
end]]
self.def_under = self.node_under
and core.registered_nodes[self.node_under.name]
-- old ground check (stable)
self.node_under = minetest.get_node_or_nil({
x = pos.x,
y = pos.y + self.object:get_properties().collisionbox[2] - 0.05,
z = pos.z
})
self.timer = 0
self.def_under = self.node_under
and core.registered_nodes[self.node_under.name]
-- part of old ground check
if self.def_under and self.def_under.walkable then
self.falling_state = false
end
self.timer = 0
end,
step_node_inside_checks = function(self)
@ -336,7 +350,8 @@ core.register_entity(":__builtin:item", {
local pos = self.object:get_pos()
-- Delete in 'ignore' nodes
if self.node_inside and self.node_inside.name == "ignore" then
if (self.node_inside and self.node_inside.name == "ignore")
or self.itemstring == "" then
self.itemstring = ""
self.object:remove()
@ -382,8 +397,7 @@ core.register_entity(":__builtin:item", {
step_check_slippery = function(self)
-- don't check for slippery ground if we're not on
-- any ground to begin with
-- don't check for slippery if we're not on the ground
if self.falling_state or not self.node_under then
self.slippery_state = false
@ -441,6 +455,21 @@ core.register_entity(":__builtin:item", {
local vel = self.object:get_velocity()
-- this stops the entity drift glitch by re-setting entity pos when not moving
if vel.x == 0 and vel.y == 0 and vel.z == 0 then
if self.is_moving == true then
self.is_moving = false
local pos = self.object:get_pos()
self.object:set_pos(pos)
end
else
self.is_moving = true
end
if self.slippery_state then
-- apply slip factor (tiny friction that depends on the actual block type)
@ -572,17 +601,16 @@ core.register_entity(":__builtin:item", {
return -- destroyed
end
self:step_check_slippery()
-- do physics checks, then apply
self:step_water_physics()
self:step_check_slippery()
self:step_ground_friction()
self:step_gravity()
self:step_air_drag_physics()
self:step_gravity()
self:step_apply_forces()
-- do item checks
self:step_try_collect()
self:step_try_collect() -- merge
end,
on_punch = function(self, hitter)

View file

@ -1,541 +0,0 @@
-- Minetest: builtin/item_entity.lua
-- override ice to make slippery for 0.4.16
if not minetest.raycast then
minetest.override_item("default:ice", {
groups = {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 3}})
end
function core.spawn_item(pos, item)
local stack = ItemStack(item)
local obj = core.add_entity(pos, "__builtin:item")
if obj then
obj:get_luaentity():set_item(stack:to_string())
end
return obj
end
-- If item_entity_ttl is not set, enity will have default life time
-- Setting it to -1 disables the feature
local time_to_live = tonumber(core.settings:get("item_entity_ttl")) or 900
local gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
local destroy_item = core.settings:get_bool("destroy_item") ~= false
-- water flow functions by QwertyMine3, edited by TenPlus1
local inv_roots = {
[0] = 1
}
local function to_unit_vector(dir_vector)
local sum = dir_vector.x * dir_vector.x + dir_vector.z * dir_vector.z
local invr_sum = 0
-- find inverse square root if possible
if inv_roots[sum] ~= nil then
invr_sum = inv_roots[sum]
else
-- not found, compute and save the inverse square root
invr_sum = 1.0 / math.sqrt(sum)
inv_roots[sum] = invr_sum
end
return {
x = dir_vector.x * invr_sum,
y = dir_vector.y,
z = dir_vector.z * invr_sum
}
end
local function node_ok(pos)
local node = minetest.get_node_or_nil(pos)
if node and minetest.registered_nodes[node.name] then
return node
end
return minetest.registered_nodes["default:dirt"]
end
local function quick_flow_logic(node, pos_testing, direction)
local node_testing = node_ok(pos_testing)
local param2 = node.param2
if not minetest.registered_nodes[node.name].groups.liquid then
param2 = 0
end
if minetest.registered_nodes[node_testing.name].liquidtype ~= "flowing"
and minetest.registered_nodes[node_testing.name].liquidtype ~= "source" then
return 0
end
local param2_testing = node_testing.param2
if param2_testing < param2 then
if (param2 - param2_testing) > 6 then
return -direction
else
return direction
end
elseif param2_testing > param2 then
if (param2_testing - param2) > 6 then
return direction
else
return -direction
end
end
return 0
end
-- reciprocal of the length of an unit square's diagonal
local DIAG_WEIGHT = 2 / math.sqrt(2)
local function quick_flow(pos, node)
local x, z = 0.0, 0.0
x = x + quick_flow_logic(node, {x = pos.x - 1, y = pos.y, z = pos.z},-1)
x = x + quick_flow_logic(node, {x = pos.x + 1, y = pos.y, z = pos.z}, 1)
z = z + quick_flow_logic(node, {x = pos.x, y = pos.y, z = pos.z - 1},-1)
z = z + quick_flow_logic(node, {x = pos.x, y = pos.y, z = pos.z + 1}, 1)
return to_unit_vector({x = x, y = 0, z = z})
end
-- END water flow functions
-- particle effects for when item is destroyed
local function add_effects(pos)
minetest.add_particlespawner({
amount = 1,
time = 0.25,
minpos = pos,
maxpos = pos,
minvel = {x = -1, y = 2, z = -1},
maxvel = {x = 1, y = 4, z = 1},
minacc = {x = 0, y = 0, z = 0},
maxacc = {x = 0, y = 0, z = 0},
minexptime = 1,
maxexptime = 3,
minsize = 1,
maxsize = 4,
texture = "tnt_smoke.png",
})
end
local water_force = 0.8
local water_friction = 0.8
local dry_friction = 2.5
core.register_entity(":__builtin:item", {
initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3},
visual = "wielditem",
visual_size = {x = 0.4, y = 0.4},
textures = {""},
spritediv = {x = 1, y = 1},
initial_sprite_basepos = {x = 0, y = 0},
is_visible = false,
infotext = "",
},
itemstring = "",
moving_state = true,
slippery_state = false,
age = 0,
set_item = function(self, item)
local stack = ItemStack(item or self.itemstring)
self.itemstring = stack:to_string()
if self.itemstring == "" then
return
end
local itemname = stack:is_known() and stack:get_name() or "unknown"
local max_count = stack:get_stack_max()
local count = math.min(stack:get_count(), max_count)
local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3)
local col_height = size * 0.75
local def = core.registered_nodes[itemname]
local glow = def and def.light_source
local c1, c2 = "",""
if not(stack:get_count() == 1) then
c1 = " x"..tostring(stack:get_count())
c2 = " "..tostring(stack:get_count())
end
local name1 = stack:get_meta():get_string("description")
local name
if name1 == "" then
name = core.registered_items[itemname].description
else
name = name1
end
self.object:set_properties({
is_visible = true,
visual = "wielditem",
textures = {itemname},
visual_size = {x = size, y = size},
collisionbox = {-size, -col_height, -size, size, col_height, size},
selectionbox = {-size, -size, -size, size, size, size},
automatic_rotate = 0.314 / size,
wield_item = self.itemstring,
glow = glow,
infotext = name .. c1 .. "\n(" .. itemname .. c2 .. ")"
})
end,
get_staticdata = function(self)
return core.serialize({
itemstring = self.itemstring,
age = self.age,
dropped_by = self.dropped_by
})
end,
on_activate = function(self, staticdata, dtime_s)
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = core.deserialize(staticdata)
if data and type(data) == "table" then
self.itemstring = data.itemstring
self.age = (data.age or 0) + dtime_s
self.dropped_by = data.dropped_by
end
else
self.itemstring = staticdata
end
self.object:set_armor_groups({immortal = 1})
self.object:set_velocity({x = 0, y = 2, z = 0})
self.object:set_acceleration({x = 0, y = -gravity, z = 0})
self:set_item()
end,
try_merge_with = function(self, own_stack, object, entity)
if self.age == entity.age then
return false -- Can not merge with itself
end
local stack = ItemStack(entity.itemstring)
local name = stack:get_name()
if own_stack:get_name() ~= name
or own_stack:get_meta() ~= stack:get_meta()
or own_stack:get_wear() ~= stack:get_wear()
or own_stack:get_free_space() == 0 then
return false -- Can not merge different or full stack
end
local count = own_stack:get_count()
local total_count = stack:get_count() + count
local max_count = stack:get_stack_max()
if total_count > max_count then
return false
end
-- Merge the remote stack into this one
local pos = object:get_pos()
pos.y = pos.y + ((total_count - count) / max_count) * 0.15
self.object:move_to(pos)
self.age = 0 -- Handle as new entity
own_stack:set_count(total_count)
self:set_item(own_stack)
entity.itemstring = ""
object:remove()
return true
end,
on_step = function(self, dtime, moveresult)
local pos = self.object:get_pos()
self.age = self.age + dtime
if time_to_live > 0 and self.age > time_to_live then
self.itemstring = ""
self.object:remove()
add_effects(pos)
return
end
-- get nodes every 1/4 second
self.timer = (self.timer or 0) + dtime
if self.timer > 0.25 or not self.node_inside then
self.node_inside = minetest.get_node_or_nil(pos)
self.def_inside = self.node_inside
and core.registered_nodes[self.node_inside.name]
-- get ground node for collision
self.node_under = nil
if moveresult.touching_ground then
for _, info in ipairs(moveresult.collisions) do
if info.axis == "y" then
self.node_under = core.get_node(info.node_pos)
break
end
end
end
self.def_under = self.node_under
and core.registered_nodes[self.node_under.name]
self.timer = 0
end
local node = self.node_inside
-- Delete in 'ignore' nodes
if node and node.name == "ignore" then
self.itemstring = ""
self.object:remove()
return
end
-- do custom step function
local name = ItemStack(self.itemstring):get_name() or ""
local custom = core.registered_items[name]
and core.registered_items[name].dropped_step
if custom and custom(self, pos, dtime) == false then
return -- skip further checks if false
end
local vel = self.object:get_velocity()
local def = self.def_inside
local is_slippery = false
local is_moving = (def and not def.walkable) or
vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
-- destroy item when dropped into lava (if enabled)
if destroy_item and def and def.groups and def.groups.lava then
minetest.sound_play("builtin_item_lava", {
pos = pos,
max_hear_distance = 6,
gain = 0.5
})
self.itemstring = ""
self.object:remove()
add_effects(pos)
return
end
-- water flowing
if def and def.liquidtype == "flowing" then
-- force applies on acceleration over time, thus multiply
local force = water_force * dtime
-- friction applies on velocity over time, thus exponentiate
local friction = (1.0 + water_friction) ^ dtime
-- get flow velocity and current vel/acc state
local vec = quick_flow(pos, node)
local a = self.object:get_acceleration()
self.object:set_acceleration({
x = a.x + vec.x * force,
y = a.y,
z = a.z + vec.z * force
})
-- apply friction to prevent items going too fast, and also to make
-- water flow override previous horizontal momentum more quickly
local v = self.object:get_velocity()
-- adjust friction for going against the current
local v_horz = { x = v.x, y = 0, z = v.z }
local v_dir = to_unit_vector(v_horz)
local flow_dot = v_dir.x * vec.x + v_dir.y * vec.y
-- also maps flow_dot from [-1,0] to [0.5,2.5]
friction = 1.0 + ((friction - 1.0) * (flow_dot + 1.5))
self.object:set_velocity({
x = v.x / friction,
y = v.y / friction,
z = v.z / friction
})
return
end
-- item inside block, move to vacant space
if def and (def.walkable == nil or def.walkable == true)
and (def.collision_box == nil or def.collision_box.type == "regular")
and (def.node_box == nil or def.node_box.type == "regular") then
local npos = minetest.find_node_near(pos, 1, "air")
if npos then
self.object:move_to(npos)
end
self.node_inside = nil -- force get_node
return
end
-- Switch locals to node under
node = self.node_under
def = self.def_under
-- Slippery node check
if def and def.walkable then
local slippery = core.get_item_group(node.name, "slippery")
is_slippery = slippery ~= 0
if is_slippery and (math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2) then
-- Horizontal deceleration
local slip_factor = 4.0 / (slippery + 4)
self.object:set_acceleration({
x = -vel.x * slip_factor,
y = 0,
z = -vel.z * slip_factor
})
elseif vel.y == 0 then
is_moving = false
end
end
if self.moving_state == is_moving
and self.slippery_state == is_slippery then
return -- No further updates until moving state changes
end
self.moving_state = is_moving
self.slippery_state = is_slippery
local a_curr = self.object:get_acceleration()
local v_curr = self.object:get_velocity()
if is_moving then
self.object:set_acceleration({
x = a_curr.x,
y = a_curr.y - gravity,
z = a_curr.z
})
else
self.object:set_acceleration({x = 0, y = 0, z = 0})
-- preserve *some* velocity so items don't get stuck on the very ledges
-- of nodes once they move just enough to leave the hitbox of flowing water
self.object:set_velocity({
x = v_curr.x / dry_friction,
y = v_curr.y / dry_friction,
z = v_curr.z / dry_friction
})
end
--Only collect items if not moving
if is_moving then
return
end
-- Collect the items around to merge with
local own_stack = ItemStack(self.itemstring)
if own_stack:get_free_space() == 0 then
return
end
local objects = core.get_objects_inside_radius(pos, 1.0)
for k, obj in pairs(objects) do
local entity = obj:get_luaentity()
if entity and entity.name == "__builtin:item" then
if self:try_merge_with(own_stack, obj, entity) then
own_stack = ItemStack(self.itemstring)
if own_stack:get_free_space() == 0 then
return
end
end
end
end
end,
on_punch = function(self, hitter)
local inv = hitter:get_inventory()
if inv and self.itemstring ~= "" then
local left = inv:add_item("main", self.itemstring)
if left and not left:is_empty() then
self:set_item(left)
return
end
end
self.itemstring = ""
self.object:remove()
end,
})

View file

@ -15,13 +15,6 @@ minetest.override_item("default:apple", {
leafdecay = 3, leafdecay_drop = 1}
})
if minetest.registered_nodes["flowers:mushroom_brown"] then
minetest.override_item("flowers:mushroom_brown", {
light_source = 1,
groups = {food_mushroom = 1, snappy = 3, attached_node = 1, flammable = 2}
})
end
--= Aliases
-- Banana

View file

@ -71,22 +71,22 @@ def.tiles = {"farming_melon_7.png"}
minetest.register_node("farming:melon_7", table.copy(def))
-- stage 8 (final)
def.drawtype = "nodebox"
def.description = S("Melon")
def.tiles = {
"farming_melon_top.png", "farming_melon_bottom.png", "farming_melon_side.png"
}
def.selection_box = {-.5, -.5, -.5, .5, .5, .5}
def.walkable = true
def.buildable_to = false
def.paramtype2 = "facedir"
def.groups = {
food_melon = 1, snappy = 2, oddly_breakable_by_hand = 1,
flammable = 2, plant = 1
}
def.drop = "farming:melon_8"
def.on_place = minetest.rotate_node
minetest.register_node("farming:melon_8", table.copy(def))
minetest.register_node("farming:melon_8", {
description = S("Melon"),
tiles = {
"farming_melon_top.png",
"farming_melon_bottom.png",
"farming_melon_side.png"
},
groups = {
food_melon = 1, snappy = 2, oddly_breakable_by_hand = 1,
flammable = 2, plant = 1
},
drop = "farming:melon_8",
sounds = default.node_sound_wood_defaults(),
paramtype2 = "facedir",
on_place = minetest.rotate_node
})
-- add to registered_plants
farming.registered_plants["farming:melon"] = {

View file

@ -183,7 +183,7 @@ minetest.register_node("farming:pumpkin_8", {
description = S("Pumpkin"),
tiles = {
"farming_pumpkin_top.png",
"farming_pumpkin_top.png",
"farming_pumpkin_bottom.png",
"farming_pumpkin_side.png"
},
groups = {
@ -191,7 +191,9 @@ minetest.register_node("farming:pumpkin_8", {
flammable = 2, plant = 1
},
drop = "farming:pumpkin_8",
sounds = default.node_sound_wood_defaults()
sounds = default.node_sound_wood_defaults(),
paramtype2 = "facedir",
on_place = minetest.rotate_node
})
minetest.register_alias("farming:pumpkin", "farming:pumpkin_8")

View file

@ -361,7 +361,7 @@ farming.add_to_scythe_not_drops = function(item)
end
minetest.register_tool("farming:scythe_mithril", {
description = S("Mithril Scythe (Right-click to harvest and replant crops)"),
description = S("Mithril Scythe (Use to harvest and replant crops)"),
inventory_image = "farming_scythe_mithril.png",
sound = {breaks = "default_tool_breaks"},

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

View file

@ -77,6 +77,7 @@ mobs:register_mob("mob_horse:horse", {
self.terrain_type = 3
self.driver_attach_at = {x = 0, y = y_off, z = -2}
self.driver_eye_offset = {x = 0, y = 3, z = 0}
self.driver_scale = {x = 0.8, y = 0.8} -- shrink driver to fit model
end
-- if driver present allow control of horse
@ -92,22 +93,20 @@ mobs:register_mob("mob_horse:horse", {
on_die = function(self, pos)
-- drop saddle when horse is killed while riding
-- also detach from horse properly
-- detach player from horse properly
if self.driver then
minetest.add_item(pos, "mobs:saddle")
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
end
self.saddle = nil
-- drop saddle if found
if self.saddle then
minetest.add_item(pos, "mobs:saddle")
end
-- drop any horseshoes added
if self.shoed then
minetest.add_item(pos, self.shoed)
end
end,
do_punch = function(self, hitter)
@ -149,29 +148,27 @@ mobs:register_mob("mob_horse:horse", {
mobs.detach(clicker, {x = 1, y = 0, z = 1})
-- add saddle back to inventory
if inv:room_for_item("main", "mobs:saddle") then
inv:add_item("main", "mobs:saddle")
else
minetest.add_item(clicker:get_pos(), "mobs:saddle")
end
return
end
self.saddle = nil
-- attach player to horse
elseif (not self.driver and not self.child
and clicker:get_wielded_item():get_name() == "mobs:saddle")
or self.saddle then
self.object:set_properties({stepheight = 1.1})
mobs.attach(self, clicker)
-- take saddle from inventory
if not self.saddle then
inv:remove_item("main", "mobs:saddle")
end
-- attach saddle to horse
if not self.driver
and not self.child
and clicker:get_wielded_item():get_name() == "mobs:saddle"
and not self.saddle then
self.saddle = true
self.order = "stand"
self.object:set_properties({stepheight = 1.1})
-- take saddle from inventory
inv:remove_item("main", "mobs:saddle")
self.texture_mods = self.texture_mods .. "^mobs_saddle_overlay.png"
self.object:set_texture_mod(self.texture_mods)
return
end
-- apply horseshoes
@ -196,6 +193,12 @@ mobs:register_mob("mob_horse:horse", {
-- apply horseshoe overlay to current horse texture
if overlay then
self.texture_mods = "^" .. overlay
if self.saddle then
self.texture_mods = self.texture_mods
.. "^mobs_saddle_overlay.png"
end
self.object:set_texture_mod(self.texture_mods)
end
@ -215,8 +218,13 @@ mobs:register_mob("mob_horse:horse", {
end
-- used to capture horse with magic lasso
mobs:capture_mob(self, clicker, 0, 0, 80, false, nil)
end,
if mobs:capture_mob(self, clicker, nil, nil, 100, false, nil) then return end
-- ride horse if saddled
if self.saddle and self.owner == player_name then
mobs.attach(self, clicker)
end
end
})
mobs:spawn({

View file

@ -7,6 +7,10 @@ There are three different horse textures (white, brown, black) which will spawn
### Taming
Horses can be tamed with 10x wheat, apple, barley, oats of corn which then allows the player to pick up the horse using a lasso and ride by right-clicking with a saddle.
---
### Saddle
Right clicking a horse with a saddle equips it and the horse will be ordered to stand still until you wish to ride.
---
### Horseshoes
Horseshoes can be crafted using steel, bronze, mese, diamond and crystal (4x ingots - 2 down either side with 1x block top middle) and placed on a horse by right clicking with the item. These can make horses run faster or jump higher while riding depending on tier.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,6 +1,16 @@
local S = mobs.intllib
local mob_drops = {
{name = "fireflies:firefly", chance = 1, min = 1, max = 1}
}
if minetest.get_modpath("ethereal") then
table.insert(mob_drops,
{name = "ethereal:fire_dust", chance = 1, min = 1, max = 1})
end
-- Fire Spirit
mobs:register_mob("mobs_monster:fire_spirit", {
@ -22,6 +32,8 @@ mobs:register_mob("mobs_monster:fire_spirit", {
glow = 14,
blood_texture = "fire_basic_flame.png",
immune_to = {
{"bucket:bucket_water", 1},
{"bucket:bucket_river_water", 1},
{"all"}
},
makes_footstep_sound = false,
@ -34,9 +46,8 @@ mobs:register_mob("mobs_monster:fire_spirit", {
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "fireflies:firefly", chance = 2, min = 1, max = 1}
},
jump_height = 6,
drops = mob_drops,
water_damage = 1,
lava_damage = 0,
fire_damage = 0,
@ -56,7 +67,7 @@ mobs:register_mob("mobs_monster:fire_spirit", {
self.flame_timer = (self.flame_timer or 0) + dtime
if self.flame_timer < 0.5 then
if self.flame_timer < 0.25 then
return
end
@ -65,24 +76,23 @@ mobs:register_mob("mobs_monster:fire_spirit", {
local pos = self.object:get_pos()
-- pos, amount, texture, min_size, max_size, radius, gravity, glow, fall
mobs:effect(pos, 5, "fire_basic_flame.png", 1, 2, 0.5, 0.5, 14, nil)
mobs:effect(pos, 5, "fire_basic_flame.png", 1, 2, 0.1, 0.2, 14, nil)
end
})
--[[
if not mobs.custom_spawn_monster then
mobs:spawn({
name = "mobs_monster:dirt_monster",
nodes = {"default:dirt_with_grass", "ethereal:gray_dirt", "ethereal:dry_dirt"},
min_light = 0,
max_light = 7,
chance = 6000,
active_object_count = 2,
min_height = 0,
day_toggle = false,
name = "mobs_monster:fire_spirit",
nodes = {"default:obsidian", "caverealms:hot_cobble"},
neighbors = {"group:fire"},
min_light = 12,
max_light = 15,
chance = 1500,
active_object_count = 1,
max_height = -150
})
end
]]
mobs:register_egg("mobs_monster:fire_spirit", S("Fire Spirit"), "fire_basic_flame.png", 1)

View file

@ -41,4 +41,8 @@ Land Guard
- These huge monsters roam the land in cold, hot and temperate areas and don't like players wandering around their domain.
Fire Spirit
- Fire Spirits will not tolerate players roaming around their domain and will fiercely attack until their dying puff of smoke. Will drop it's spirit and some fire dust when using ethereal.
Lucky Blocks: 11

View file

@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
mobs = {
mod = "redo",
version = "20210601",
version = "20210610",
intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {}
}
@ -3553,6 +3553,13 @@ function mobs:register_mob(name, def)
mobs.spawning_mobs[name] = {}
local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}
-- quick fix to stop mobs glitching through nodes if too small
if -collisionbox[2] + collisionbox[5] < 1.01 then
collisionbox[5] = collisionbox[2] + 0.99
end
minetest.register_entity(name, setmetatable({
stepheight = def.stepheight,
@ -3574,8 +3581,8 @@ minetest.register_entity(name, setmetatable({
lifetimer = def.lifetimer,
hp_min = max(1, (def.hp_min or 5) * difficulty),
hp_max = max(1, (def.hp_max or 10) * difficulty),
collisionbox = def.collisionbox,
selectionbox = def.selectionbox or def.collisionbox,
collisionbox = collisionbox, --def.collisionbox,
selectionbox = def.selectionbox or collisionbox, --def.collisionbox,
visual = def.visual,
visual_size = def.visual_size,
mesh = def.mesh,

View file

@ -22,6 +22,7 @@ end
local function node_is(pos)
local node = node_ok(pos)
if node.name == "air" then
@ -69,6 +70,7 @@ end
local function force_detach(player)
local attached_to = player:get_attach()
if not attached_to then
@ -97,7 +99,9 @@ minetest.register_on_leaveplayer(function(player)
end)
minetest.register_on_shutdown(function()
local players = minetest.get_connected_players()
for i = 1, #players do
force_detach(players[i])
end
@ -112,6 +116,7 @@ end)
-- Just for correct detaching
local function find_free_pos(pos)
local check = {
{x = 1, y = 0, z = 0},
{x = 1, y = 1, z = 0},
@ -124,10 +129,14 @@ local function find_free_pos(pos)
}
for _, c in pairs(check) do
local npos = {x = pos.x + c.x, y = pos.y + c.y, z = pos.z + c.z}
local node = minetest.get_node_or_nil(npos)
if node and node.name then
local def = minetest.registered_nodes[node.name]
if def and not def.walkable and
def.liquidtype == "none" then
return npos
@ -141,6 +150,7 @@ end
-------------------------------------------------------------------------------
function mobs.attach(entity, player)
entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0}
entity.driver_attach_at = entity.driver_attach_at or {x = 0, y = 0, z = 0}
entity.driver_eye_offset = entity.driver_eye_offset or {x = 0, y = 0, z = 0}
@ -154,6 +164,7 @@ function mobs.attach(entity, player)
local attach_at = entity.driver_attach_at
local eye_offset = entity.driver_eye_offset
entity.driver = player
force_detach(player)
@ -170,6 +181,7 @@ function mobs.attach(entity, player)
})
minetest.after(0.2, function()
if player and player:is_player() then
player_api.set_animation(player, "sit", 30)
end
@ -183,9 +195,13 @@ function mobs.detach(player)
force_detach(player)
minetest.after(0.1, function()
if player and player:is_player() then
local pos = find_free_pos(player:get_pos())
pos.y = pos.y + 0.5
player:set_pos(pos)
end
end)
@ -193,8 +209,8 @@ end
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local yaw = entity.object:get_yaw() or 0
local yaw = entity.object:get_yaw() or 0
local rot_view = 0
if entity.player_rotation.y == 90 then
@ -208,14 +224,17 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- process controls
if entity.driver then
local ctrl = entity.driver:get_player_control()
-- move forwards
if ctrl.up then
entity.v = entity.v + entity.accel / 10
-- move backwards
elseif ctrl.down then
if entity.max_speed_reverse == 0 and entity.v == 0 then
return
end
@ -225,7 +244,9 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- mob rotation
local horz
if entity.alt_turn == true then
horz = yaw
if ctrl.left then
@ -243,21 +264,29 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if can_fly then
-- fly up
if ctrl.jump then
velo.y = velo.y + 1
if velo.y > entity.accel then velo.y = entity.accel end
elseif velo.y > 0 then
velo.y = velo.y - 0.1
if velo.y < 0 then velo.y = 0 end
end
-- fly down
if ctrl.sneak then
velo.y = velo.y - 1
if velo.y < -entity.accel then velo.y = -entity.accel end
elseif velo.y < 0 then
velo.y = velo.y + 0.1
if velo.y > 0 then velo.y = 0 end
end
else
@ -274,6 +303,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- if not moving then set animation and return
if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
if stand_anim then
mobs:set_animation(entity, stand_anim)
end
@ -292,8 +322,10 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.v = entity.v - 0.02 * s
if s ~= get_sign(entity.v) then
entity.object:set_velocity({x = 0, y = 0, z = 0})
entity.v = 0
return
end
@ -310,6 +342,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- Set position, velocity and acceleration
local p = entity.object:get_pos()
if not p then return end
local new_acce = {x = 0, y = -9.81, z = 0}
@ -320,18 +353,23 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local v = entity.v
if ni == "air" then
if can_fly == true then
new_acce.y = 0
end
elseif ni == "liquid" or ni == "lava" then
if ni == "lava" and entity.lava_damage ~= 0 then
entity.lava_counter = (entity.lava_counter or 0) + dtime
if entity.lava_counter > 1 then
minetest.sound_play("default_punch", {
object = entity.object,
max_hear_distance = 5
})
}, true)
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
@ -343,11 +381,14 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
local terrain_type = entity.terrain_type
if terrain_type == 2 or terrain_type == 3 then
new_acce.y = 0
p.y = p.y + 1
if node_is(p) == "liquid" then
if velo.y >= 5 then
velo.y = 5
elseif velo.y < 0 then
@ -357,7 +398,9 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
else
if abs(velo.y) < 1 then
local pos = entity.object:get_pos()
if not pos then return end
pos.y = floor(pos.y) + 0.5
@ -371,6 +414,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
local new_velo = get_velocity(v, yaw - rot_view, velo.y)
new_acce.y = new_acce.y + acce_y
entity.object:set_velocity(new_velo)
@ -382,6 +426,7 @@ end
-- directional flying routine by D00Med (edited by TenPlus1)
function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
local ctrl = entity.driver:get_player_control()
local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir()
@ -397,6 +442,7 @@ if not ctrl or not velo then return end
})
elseif ctrl.down then
entity.object:set_velocity({
x = -dir.x * speed,
y = dir.y * speed + 2,
@ -411,6 +457,7 @@ if not ctrl or not velo then return end
-- firing arrows
if ctrl.LMB and ctrl.sneak and shoots then
local pos = entity.object:get_pos()
local obj = minetest.add_entity({
x = pos.x + 0 + dir.x * 2.5,
@ -418,11 +465,15 @@ if not ctrl or not velo then return end
z = pos.z + 0 + dir.z * 2.5}, arrow)
local ent = obj:get_luaentity()
if ent then
ent.switch = 1 -- for mob specific arrows
ent.owner_id = tostring(entity.object) -- so arrows dont hurt entity you are riding
local vec = {x = dir.x * 6, y = dir.y * 6, z = dir.z * 6}
yaw = entity.driver:get_look_horizontal()
obj:set_yaw(yaw + pi / 2)
obj:set_velocity(vec)
else

View file

@ -12,65 +12,65 @@ minetest.register_node("cavestuff:pebble_1",{
description = S("Pebble"),
drawtype = "mesh",
mesh = "cavestuff_pebble.obj",
tiles = {"undergrowth_pebble.png"},
paramtype = "light",
tiles = {"undergrowth_pebble.png"},
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=3, stone=1},
selection_box = cbox,
collision_box = cbox,
on_place = function(itemstack, placer, pointed_thing)
groups = {cracky=3, stone=1},
selection_box = cbox,
collision_box = cbox,
on_place = function(itemstack, placer, pointed_thing)
-- place a random pebble node
local stack = ItemStack("cavestuff:pebble_"..math.random(1,2))
local ret = minetest.item_place(stack, placer, pointed_thing)
return ItemStack("cavestuff:pebble_1 "..itemstack:get_count()-(1-ret:get_count()))
end,
sounds = default.node_sound_stone_defaults(),
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("cavestuff:pebble_2",{
drawtype = "mesh",
mesh = "cavestuff_pebble.obj",
tiles = {"undergrowth_pebble.png"},
tiles = {"undergrowth_pebble.png"},
drop = "cavestuff:pebble_1",
tiles = {"undergrowth_pebble.png"},
paramtype = "light",
tiles = {"undergrowth_pebble.png"},
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=3, stone=1, not_in_creative_inventory=1},
groups = {cracky=3, stone=1, not_in_creative_inventory=1},
selection_box = cbox,
collision_box = cbox,
sounds = default.node_sound_stone_defaults(),
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("cavestuff:desert_pebble_1",{
description = S("Desert Pebble"),
drawtype = "mesh",
mesh = "cavestuff_pebble.obj",
tiles = {"default_desert_stone.png"},
paramtype = "light",
tiles = {"default_desert_stone.png"},
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=3, stone=1},
groups = {cracky=3, stone=1},
selection_box = cbox,
collision_box = cbox,
on_place = function(itemstack, placer, pointed_thing)
on_place = function(itemstack, placer, pointed_thing)
-- place a random pebble node
local stack = ItemStack("cavestuff:desert_pebble_"..math.random(1,2))
local ret = minetest.item_place(stack, placer, pointed_thing)
return ItemStack("cavestuff:desert_pebble_1 "..itemstack:get_count()-(1-ret:get_count()))
end,
sounds = default.node_sound_stone_defaults(),
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("cavestuff:desert_pebble_2",{
drawtype = "mesh",
mesh = "cavestuff_pebble.obj",
drop = "cavestuff:desert_pebble_1",
tiles = {"default_desert_stone.png"},
paramtype = "light",
tiles = {"default_desert_stone.png"},
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=3, stone=1, not_in_creative_inventory=1},
groups = {cracky=3, stone=1, not_in_creative_inventory=1},
selection_box = cbox,
collision_box = cbox,
sounds = default.node_sound_stone_defaults(),
sounds = default.node_sound_stone_defaults(),
})
--Staclactites
@ -85,19 +85,34 @@ minetest.register_node("cavestuff:stalactite_1",{
node_box = {
type = "fixed",
fixed = {
{-0.187500,0.425000,-0.150003,0.162500,0.500000,0.162500},
{-0.112500,0.162500,-0.100000,0.087500,0.475000,0.087500},
{-0.062500,-0.275000,-0.062500,0.062500,0.500000,0.062500},
{-0.037500,-0.837500,0.037500,0.037500,0.500000,-0.025000},
{-0.187500,-0.425000,-0.150003,0.162500,-0.500000,0.162500},
{-0.112500,-0.162500,-0.100000,0.087500,-0.475000,0.087500},
{-0.062500,0.275000,-0.062500,0.062500,-0.500000,0.062500},
{-0.037500,0.837500,0.037500,0.037500,-0.500000,-0.025000},
}
},
on_place = function(itemstack, placer, pointed_thing)
local pt = pointed_thing
if minetest.get_node(pt.under).name=="default:stone"
and minetest.get_node({x=pt.under.x, y=pt.under.y-1, z=pt.under.z}).name=="air"
and minetest.get_node({x=pt.under.x, y=pt.under.y-2, z=pt.under.z}).name=="air" then
minetest.swap_node({x=pt.under.x, y=pt.under.y-1, z=pt.under.z}, {name="cavestuff:stalactite_"..math.random(1,3)})
local dir = vector.subtract(pointed_thing.above, pointed_thing.under)
local base = pointed_thing.under
local place = vector.add(base, dir)
local above = vector.add(place, dir)
if not placer then return end
local playername = placer:get_player_name()
if minetest.is_protected(place, playername)
or minetest.is_protected(above, playername) then
minetest.record_protection_violation(place, playername)
return
end
if minetest.get_node(base).name == "default:stone"
and minetest.get_node(place).name == "air"
and minetest.get_node(above).name == "air"
then
minetest.swap_node(place, {
name = "cavestuff:stalactite_"..math.random(1,3),
param2 = minetest.dir_to_wallmounted(vector.multiply(dir, -1))
})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
@ -116,10 +131,10 @@ minetest.register_node("cavestuff:stalactite_2",{
node_box = {
type = "fixed",
fixed = {
{-0.187500,0.387500,-0.150003,0.162500,0.500000,0.162500},
{-0.112500,0.112500,-0.100000,0.087500,0.475000,0.087500},
{-0.062500,-0.675000,-0.062500,0.062500,0.500000,0.062500},
{-0.037500,-0.975000,0.037500,0.037500,0.500000,-0.025000},
{-0.187500,-0.387500,-0.150003,0.162500,-0.500000,0.162500},
{-0.112500,-0.112500,-0.100000,0.087500,-0.475000,0.087500},
{-0.062500,0.675000,-0.062500,0.062500,-0.500000,0.062500},
{-0.037500,0.975000,0.037500,0.037500,-0.500000,-0.025000},
}
},
})
@ -132,14 +147,14 @@ minetest.register_node("cavestuff:stalactite_3",{
paramtype = "light",
paramtype2 = "wallmounted",
node_box = {
type = "fixed",
fixed = {
{-0.187500,0.387500,-0.150003,0.162500,0.500000,0.162500},
{-0.112500,0.037500,-0.100000,0.087500,0.475000,0.087500},
{-0.062500,-0.437500,-0.062500,0.062500,0.500000,0.062500},
{-0.037500,-1.237500,0.037500,0.037500,0.500000,-0.025000},
}
},
type = "fixed",
fixed = {
{-0.187500,-0.387500,-0.150003,0.162500,-0.500000,0.162500},
{-0.112500,-0.037500,-0.100000,0.087500,-0.475000,0.087500},
{-0.062500,0.437500,-0.062500,0.062500,-0.500000,0.062500},
{-0.037500,1.237500,0.037500,0.037500,-0.500000,-0.025000},
}
},
})
--Stalagmites

View file

@ -22,7 +22,7 @@ That said, there are some basic text formatting options:
Writing "^" followed by a letter "a" through "h" will produce double-wide versions of these arrows, in the same order. These wide arrows occupy 0x89 to 0x91 in the character set.
* A color may be specified in the sign text by using "#" followed by a single hexadcimal digit (0-9 or a-f). These colors come from the standard Linux/IRC/CGA color set, and are shown in the sign's formspec. Any color change will remain in effect until changed again, or until the next line break. Any number of color changes in any arbitrary arrangement is allowed.
* A color may be specified in the sign text by using "#" followed by a single hexadcimal digit (0-9 or a-f). These colors come from the standard Linux/IRC/CGA color set, and are shown in the sign's formspec. Any color change will remain in effect until changed again, or until the next line break. Any number of color changes in any arbitrary arrangement is allowed. To write "#" on a sign, write "##".
* Most writable signs can display double-wide text by flipping a switch in the sign's formspec.

View file

@ -555,8 +555,9 @@ local function make_line_texture(line, lineno, pos, line_width, line_height, cwi
end
end
local c = word:sub(i, i)
if c == "#" then
local cc = tonumber(word:sub(i+1, i+1), 16)
local c2 = word:sub(i+1, i+1)
if c == "#" and c2 ~= "#" then
local cc = tonumber(c2, 16)
if cc then
i = i + 1
cur_color = cc

View file

@ -0,0 +1,3 @@
Plagegeist
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
FBI Agent
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Cyber bot
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
The dead
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
ICE Knight
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Nothing
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Endermann
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Sandzombie
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Nebel man
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Cyber Huhn
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Green glas
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
X Kost&uuml;m
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Neon Knight
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Elf Woman
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
pacman
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
killer woman
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
gohst
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
rainbow man
Phill
CC BY-SA 3.0

View file

@ -0,0 +1,3 @@
Green Gohst
Phill
CC BY-SA 3.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

View file

@ -1,5 +1,5 @@
stamina = {players = {}}
stamina = {players = {}, mod = "redo"}
STAMINA_TICK = tonumber(minetest.settings:get("stamina_tick")) or 800
-- time in seconds after that 1 stamina point is taken
@ -681,3 +681,43 @@ end
minetest.register_on_leaveplayer(function(player)
stamina.players[player:get_player_name()] = nil
end)
--lucky blocks (if damage and stamina active)
if minetest.get_modpath("lucky_block")
and minetest.settings:get_bool("enable_damage")
and minetest.settings:get_bool("enable_stamina") ~= false then
local effect_me = function(pos, player, def)
local green = minetest.get_color_escape_sequence("#bada55")
local name = player:get_player_name()
if def.poison or def.drunk then
player:hud_change(stamina.players[name].hud_id,
"text", "stamina_hud_poison.png")
end
if def.poison and def.poison > 0 then
stamina.players[name].poisoned = def.poison
minetest.chat_send_player(name,
green .. "Seems you have been poisoned!")
elseif def.drunk and def.drunk > 0 then
stamina.players[name].drunk = def.drunk
minetest.chat_send_player(name,
green .. "You seem a little tipsy!")
end
end
lucky_block:add_blocks({
{"cus", effect_me, {poison = 5} },
{"cus", effect_me, {poison = 10} },
{"cus", effect_me, {drunk = 30} },
})
end

View file

@ -1,4 +1,4 @@
name = stamina
depends = default
optional_depends = 3d_armor, player_monoids, pova
optional_depends = 3d_armor, player_monoids, pova, lucky_block
description = Adds stamina, hunger and drunk effects.

View file

@ -1,4 +1,4 @@
# TechPack V2.05
# TechPack V2.06
TechPack, a Mining, Crafting, &amp; Farming Modpack for Minetest.
@ -27,6 +27,7 @@ TechPack is a collection of following Mods:
**The moved/copied nodes will not have valid node numbers, which could lead to a server crash.**
TechPack provides:
- lumber tubes to connect 2 nodes
- a Pusher node to pull/push items through tubes
- a Distributor node with 4 output channels to sort incoming items
@ -64,9 +65,11 @@ TechPack provides:
- a Display node for text outputs of the Controller
- Metal ladders, stairways, and bridges
- Warehouse Boxes in steel, copper, and gold
- A chest cart for the mod minecart
TechPack supports the following mods:
- Farming Redo (Harvester, Fermenter)
- Ethereal (Harvester, Quarry, Fermenter)
- Pipeworks (Gravel Sieve)
@ -75,12 +78,14 @@ TechPack supports the following mods:
### Configuration
The following can be changed in the minetest menu (Settings -> Advanced Settings -> Mods -> tubelib) or directly in 'minetest.conf'
- Maximum number of Forceload Blocks per player
- Enable Basalt Stone (and disable ore generation via Cobblestone generator)
- Machine aging value to calculate the lifetime of machines
Example for 'minetest.conf':
```LUA
tubelib_basalt_stone_enabled = false
tubelib_max_num_forceload_blocks = 12
@ -88,6 +93,7 @@ tubelib_machine_aging_value = 200
```
Example for a v1 compatible 'minetest.conf':
```LUA
tubelib_basalt_stone_enabled = false
tubelib_max_num_forceload_blocks = 0
@ -96,24 +102,30 @@ tubelib_machine_aging_value = 999999
#### Maximum number of Forceload Blocks per player
Default value is 12.
Default value is 12.
I higher number allows to build larger farms and machines which keep loaded, but increases the server load, too.
But the areas are only loaded when the player is online.
To be able to use e.g. 12 forceloaded blocks per player, the pararamter 'max_forceloaded_blocks' in 'minetest.conf' has to be ajusted.
#### Enable Basalt Stone (and disable ore generation via Cobblestone generator)
The lava/water Cobblestone generator allows to produce infinite Cobblestone. By means of Quarry,
The lava/water Cobblestone generator allows to produce infinite Cobblestone. By means of Quarry,
Grinder, and Gravel Sieve it allows to infinite generate ores.
This can be disabled by means of the setting parameter. If enabled, the Cobblestone
generator generates Basalt instead, which only can be used for building purposes.
#### Machine aging value to calculate the lifetime of machines
Default value is 200.
Default value is 200.
This aging value is used to calculate the lifetime of machines before they go defect.
The value 200 (default) results in a lifetime for standard machines of about 2000 - 8000 item processing cycles (~2-4 hours).
### License
Copyright (C) 2017-2021 Joachim Stolberg
Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt
Textures: CC BY-SA 3.0
@ -121,26 +133,33 @@ Textures: CC BY-SA 3.0
## Credits
### Contributors
- oversword (PR #43, #57, #58, #59, #60, #62, #68, #74, #76)
- oversword (PR #43, #57, #58, #59, #60, #62, #68, #74, #76, and many more)
- afkplayer5000 (PR #70, #71)
- andrenete (PR #37, #66)
- fluxionary (PR #27, #28, #30, #31, #34, #54)
- Arigatas (PR #51, #53)
- realmicu (PR #6, #8, #12)
- theFox6 (PR #3, #4)
- superfloh247 (PR #89, #88, #87)
- SciFurz (via forum)
### Dependencies
default, doors, intllib, basic_materials
default, doors, intllib, basic_materials
tubelib2 (![GitHub](https://github.com/joe7575/tubelib2))
Tubelib Color Lamps optional: unifieddyes
SmartLine Controller optional: mail
Gravelsieve optional: moreores, hopper, pipeworks
tubelib_addons1 optional: unified_inventory
tubelib_addons13 optional: minecart
### History
- 2018-03-18 V1.00 * Tubelib, tubelib_addons1, tubelib_addons2, smartline, and gravelsieve combined to one modpack.
- 2018-03-24 V1.01 * Support for Ethereal added
- 2018-03-27 V1.02 * Timer improvements for unloaded areas
@ -166,8 +185,11 @@ tubelib_addons1 optional: unified_inventory
- 2019-04-23 V2.03 * Piston/WorldEdit/replacer detection added, farming and grinder recipes added
- 2020-11-20 V2.04 * Switch to AGPL v3, adapt to minetest 5.3, add translation support, fix minor bugs
- 2021-01-24 V2.05 * PR #74, #76: Implement checks for valid connection sides for many nodes
- 2021-06-06 V2.06 * PR #78 - #89, chest cart added
## New in v2 (from players point of view)
- Almost all machines break after a certain amount of time (switch into the state 'defect') and have to be repaired.
- A Repair Kit is available to repair defect machines.
- A Forceload block (16x16x16) is added which keeps the corresponding area loaded and the machines operational as far as the player is logged in.
@ -178,6 +200,7 @@ tubelib_addons1 optional: unified_inventory
## New in v2 (from admins point of view)
- settingtypes introduced with the following settings: tubelib_max_num_forceload_blocks, tubelib_basalt_stone_enabled, tubelib_machine_aging_value
- the new mods 'techpack_stairway' and 'techpack_warehouse' have to be enabled
- TechPack depends now on the mod 'basic_materials' and 'tubelib2' (![GitHub](https://github.com/joe7575/tubelib2))

View file

@ -1,6 +1,22 @@
# Release Notes for ModPack TechPack [techpack]
## V2.06.00 (2021-06-06)
### Additions
- Add chest cart for the mod minecart (optional)
- Add support for the mod "underch" (#88)
### Removals
### Changes
- Account for new red & yellow pepper varieties (#86)
- Pusher improvements (#84, #83)
### Fixes
- Fix crash with "ethereal:strawberry" (#89)
## V2.05.00 (2021-01-24)
### Additions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 B

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 B

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 878 B

View file

@ -57,6 +57,13 @@ tn("default:pine_tree", "default:pine_tree", "default:pine_sapling")
tn("default:acacia_tree", "default:acacia_tree", "default:acacia_sapling")
tn("default:jungletree", "default:jungletree", "default:junglesapling")
tn("default:bush_stem", "default:bush_stem", "default:bush_sapling")
tn("default:acacia_bush_stem", "default:acacia_bush_stem", "default:acacia_bush_sapling")
tn("default:pine_bush_stem", "default:pine_bush_stem", "default:pine_bush_sapling")
fn("default:pine_bush_needles")
tubelib_addons1.FarmingNodes["default:pine_bush_needles"].leaves = true -- accepted as leaves
fn("default:leaves")
fn("default:aspen_leaves")
fn("default:pine_needles")
@ -118,7 +125,7 @@ end
-------------------------------------------------------------------------------
-- Ethereal Farming
-------------------------------------------------------------------------------
fn("ethereal:strawberry_8", "ethereal:strawberry 2", "ethereal:strawberry 1")
fn("ethereal:strawberry_8", "ethereal:strawberry 2", "ethereal:strawberry_1")
fn("ethereal:onion_5", "ethereal:wild_onion_plant 2", "ethereal:onion_1")

View file

@ -1,6 +1,7 @@
# textdomain: tubelib_addons2
### accesscontrol.lua ###
Access code (4 digits):=

View file

@ -0,0 +1,171 @@
--[[
Tubelib Addons 3
================
Copyright (C) 2017-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
chest.lua
A high performance chest
]]--
-- Load support for I18n
local S = tubelib_addons3.S
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S2P = minetest.string_to_pos
local M = minetest.get_meta
local function on_rightclick(pos, node, clicker)
if clicker and clicker:is_player() then
if M(pos):get_int("userID") == 0 then
minecart.show_formspec(pos, clicker)
end
end
end
local function formspec()
return "size[8,6]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;main;3,0;2,2;]"..
"list[current_player;main;0,2.3;8,4;]"..
"listring[context;main]"..
"listring[current_player;main]"
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
local owner = M(pos):get_string("owner")
if owner ~= "" and owner ~= player:get_player_name() then
return 0
end
return stack:get_count()
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
local owner = M(pos):get_string("owner")
if owner ~= "" and owner ~= player:get_player_name() then
return 0
end
return stack:get_count()
end
minetest.register_node("tubelib_addons3:chest_cart", {
description = S("TA Chest Cart"),
tiles = {
-- up, down, right, left, back, front
"tubelib_addons3_chest_cart_top.png",
"tubelib_addons3_chest_cart_bottom.png",
"tubelib_addons3_chest_cart_side.png",
"tubelib_addons3_chest_cart_side.png",
"tubelib_addons3_chest_cart_front.png",
"tubelib_addons3_chest_cart_front.png",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-7/16, 3/16, -7/16, 7/16, 8/16, 7/16},
{-8/16, -8/16, -8/16, 8/16, 3/16, 8/16},
},
},
paramtype2 = "facedir",
paramtype = "light",
use_texture_alpha = true,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 2, crumbly = 2, choppy = 2},
node_placement_prediction = "",
diggable = false,
on_place = minecart.on_nodecart_place,
on_punch = minecart.on_nodecart_punch,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
on_rightclick = on_rightclick,
after_place_node = function(pos, placer)
local inv = M(pos):get_inventory()
inv:set_size('main', 4)
if placer and placer:is_player() then
minecart.show_formspec(pos, placer)
else
M(pos):set_string("formspec", formspec())
end
end,
set_cargo = function(pos, data)
local inv = M(pos):get_inventory()
for idx, stack in ipairs(data) do
inv:set_stack("main", idx, stack)
end
end,
get_cargo = function(pos)
local inv = M(pos):get_inventory()
local data = {}
for idx = 1, 4 do
local stack = inv:get_stack("main", idx)
data[idx] = {name = stack:get_name(), count = stack:get_count()}
end
return data
end,
has_cargo = function(pos)
local inv = minetest.get_meta(pos):get_inventory()
return not inv:is_empty("main")
end
})
minecart.register_cart_entity("tubelib_addons3:chest_cart_entity", "tubelib_addons3:chest_cart", "chest", {
initial_properties = {
physical = false,
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
visual = "wielditem",
textures = {"tubelib_addons3:chest_cart"},
visual_size = {x=0.66, y=0.66, z=0.66},
static_save = false,
},
})
tubelib.register_node("tubelib_addons3:chest_cart", {}, {
on_pull_stack = function(pos, side)
local meta = minetest.get_meta(pos)
return tubelib.get_stack(meta, "main")
end,
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
return tubelib.get_item(meta, "main")
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "main", item)
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "main", item)
end,
on_recv_message = function(pos, topic, payload)
if topic == "state" then
local meta = minetest.get_meta(pos)
return tubelib.get_inv_state(meta, "main")
else
return "unsupported"
end
end,
})
minetest.register_craft({
output = "tubelib_addons3:chest_cart",
recipe = {
{"default:junglewood", "default:chest_locked", "default:junglewood"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
})

View file

@ -21,3 +21,7 @@ dofile(minetest.get_modpath("tubelib_addons3") .. '/distributor.lua')
dofile(minetest.get_modpath("tubelib_addons3") .. '/pushing_chest.lua')
dofile(minetest.get_modpath("tubelib_addons3") .. '/teleporter.lua')
dofile(minetest.get_modpath("tubelib_addons3") .. '/funnel.lua')
if minetest.global_exists("minecart") then
dofile(minetest.get_modpath("tubelib_addons3") .. '/chest_cart.lua')
end

View file

@ -7,6 +7,10 @@
HighPerf Chest=
connected with=
### chest_cart.lua ###
TA Chest Cart=
### distributor.lua ###
HighPerf Distributor=

View file

@ -7,6 +7,10 @@
HighPerf Chest=HighPerf Kiste
connected with=verbunden mit
### chest_cart.lua ###
TA Chest Cart=TA Kistenwagen
### distributor.lua ###
HighPerf Distributor=HighPerf Verteiler

View file

@ -1,3 +1,4 @@
name=tubelib_addons3
description=Tubelib Extension with High Performance nodes
depends=tubelib,tubelib_addons1,default
depends=tubelib,tubelib_addons1,default
optional_depends=minecart

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

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