update
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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", {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
})
|
|
@ -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
|
||||
|
|
|
@ -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"] = {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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"},
|
||||
|
||||
|
|
BIN
mods/farming/textures/farming_pumpkin_bottom.png
Normal file
After Width: | Height: | Size: 258 B |
|
@ -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({
|
||||
|
|
|
@ -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.
|
||||
|
|
BIN
mods/mob_horse/textures/mobs_saddle_overlay.png
Normal file
After Width: | Height: | Size: 1 KiB |
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
3
mods/skinsdb/meta/character_2041.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Plagegeist
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2042.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
FBI Agent
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2043.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Cyber bot
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2044.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
The dead
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2045.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
ICE Knight
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2046.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Nothing
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2047.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Endermann
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2048.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Sandzombie
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2049.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Nebel man
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2050.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Cyber Huhn
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2051.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Green glas
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2052.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
X Kostüm
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2053.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Neon Knight
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2054.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Elf Woman
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2055.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
pacman
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2056.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
killer woman
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2057.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
gohst
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2058.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
rainbow man
|
||||
Phill
|
||||
CC BY-SA 3.0
|
3
mods/skinsdb/meta/character_2059.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Green Gohst
|
||||
Phill
|
||||
CC BY-SA 3.0
|
BIN
mods/skinsdb/textures/character_2041.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
mods/skinsdb/textures/character_2042.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
mods/skinsdb/textures/character_2043.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
mods/skinsdb/textures/character_2044.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
mods/skinsdb/textures/character_2045.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
mods/skinsdb/textures/character_2046.png
Normal file
After Width: | Height: | Size: 279 B |
BIN
mods/skinsdb/textures/character_2047.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
mods/skinsdb/textures/character_2048.png
Normal file
After Width: | Height: | Size: 475 B |
BIN
mods/skinsdb/textures/character_2049.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
mods/skinsdb/textures/character_2050.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
mods/skinsdb/textures/character_2051.png
Normal file
After Width: | Height: | Size: 303 B |
BIN
mods/skinsdb/textures/character_2052.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
mods/skinsdb/textures/character_2053.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
mods/skinsdb/textures/character_2054.png
Normal file
After Width: | Height: | Size: 875 B |
BIN
mods/skinsdb/textures/character_2055.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
mods/skinsdb/textures/character_2056.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
mods/skinsdb/textures/character_2057.png
Normal file
After Width: | Height: | Size: 414 B |
BIN
mods/skinsdb/textures/character_2058.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
mods/skinsdb/textures/character_2059.png
Normal file
After Width: | Height: | Size: 991 B |
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# TechPack V2.05
|
||||
# TechPack V2.06
|
||||
|
||||
TechPack, a Mining, Crafting, & 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))
|
||||
|
|
|
@ -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
|
||||
|
|
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 166 B |
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 419 B |
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 444 B |
Before Width: | Height: | Size: 480 B After Width: | Height: | Size: 414 B |
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 408 B |
Before Width: | Height: | Size: 819 B After Width: | Height: | Size: 751 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 368 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 340 B |
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 430 B |
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 359 B |
Before Width: | Height: | Size: 361 B After Width: | Height: | Size: 311 B |
Before Width: | Height: | Size: 348 B After Width: | Height: | Size: 322 B |
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 359 B |
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 545 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 878 B |
|
@ -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")
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# textdomain: tubelib_addons2
|
||||
|
||||
|
||||
|
||||
### accesscontrol.lua ###
|
||||
|
||||
Access code (4 digits):=
|
||||
|
|
171
mods/techpack/tubelib_addons3/chest_cart.lua
Normal 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"},
|
||||
},
|
||||
})
|
|
@ -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
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
HighPerf Chest=
|
||||
connected with=
|
||||
|
||||
### chest_cart.lua ###
|
||||
|
||||
TA Chest Cart=
|
||||
|
||||
### distributor.lua ###
|
||||
|
||||
HighPerf Distributor=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 470 B |
After Width: | Height: | Size: 210 B |
After Width: | Height: | Size: 262 B |
After Width: | Height: | Size: 279 B |
After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 737 B After Width: | Height: | Size: 587 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.5 KiB |