2021-05-29 16:12:33 +02:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2021-02-24 09:31:27 +01:00
2021-03-30 19:24:39 +02:00
local boat_visual_size = { x = 1 , y = 1 , z = 1 }
2021-02-24 09:31:27 +01:00
local paddling_speed = 22
local boat_y_offset = 0.35
local boat_y_offset_ground = boat_y_offset + 0.6
local boat_side_offset = 1.001
local boat_max_hp = 4
2017-06-12 23:21:41 +02:00
2021-02-24 10:38:49 +01:00
local function is_group ( pos , group )
2017-06-12 23:21:41 +02:00
local nn = minetest.get_node ( pos ) . name
2021-02-24 10:38:49 +01:00
return minetest.get_item_group ( nn , group ) ~= 0
end
2021-03-30 00:44:38 +02:00
local is_water = flowlib.is_water
2022-08-01 05:20:19 +02:00
local function is_river_water ( p )
local n = minetest.get_node ( p ) . name
if n == " mclx_core:river_water_source " or n == " mclx_core:river_water_flowing " then
return true
end
end
2021-02-24 10:38:49 +01:00
local function is_ice ( pos )
return is_group ( pos , " ice " )
2017-06-12 23:21:41 +02:00
end
2022-08-09 02:12:44 +02:00
local function is_fire ( pos )
return is_group ( pos , " set_on_fire " )
end
2017-06-12 23:21:41 +02:00
local function get_sign ( i )
if i == 0 then
return 0
else
return i / math.abs ( i )
end
end
local function get_velocity ( v , yaw , y )
local x = - math.sin ( yaw ) * v
local z = math.cos ( yaw ) * v
return { x = x , y = y , z = z }
end
local function get_v ( v )
return math.sqrt ( v.x ^ 2 + v.z ^ 2 )
end
2021-02-24 09:31:27 +01:00
local function check_object ( obj )
return obj and ( obj : is_player ( ) or obj : get_luaentity ( ) ) and obj
end
local function get_visual_size ( obj )
return obj : is_player ( ) and { x = 1 , y = 1 , z = 1 } or obj : get_luaentity ( ) . _old_visual_size or obj : get_properties ( ) . visual_size
end
local function set_attach ( boat )
boat._driver : set_attach ( boat.object , " " ,
2022-10-18 14:45:53 +02:00
{ x = 0 , y = 1.5 , z = 1 } , { x = 0 , y = 0 , z = 0 } )
2021-02-24 09:31:27 +01:00
end
local function set_double_attach ( boat )
boat._driver : set_attach ( boat.object , " " ,
{ x = 0 , y = 0.42 , z = 0.8 } , { x = 0 , y = 0 , z = 0 } )
2023-11-02 20:24:52 +01:00
if boat._passenger : is_player ( ) then
boat._passenger : set_attach ( boat.object , " " ,
{ x = 0 , y = 0.42 , z = - 6.2 } , { x = 0 , y = 0 , z = 0 } )
else
boat._passenger : set_attach ( boat.object , " " ,
{ x = 0 , y = 0.42 , z = - 4.5 } , { x = 0 , y = 270 , z = 0 } )
end
2021-02-24 09:31:27 +01:00
end
2022-10-14 22:55:52 +02:00
local function set_choat_attach ( boat )
boat._driver : set_attach ( boat.object , " " ,
2022-10-18 14:45:53 +02:00
{ x = 0 , y = 1.5 , z = 1 } , { x = 0 , y = 0 , z = 0 } )
2022-10-14 22:55:52 +02:00
end
2021-02-24 09:31:27 +01:00
local function attach_object ( self , obj )
2022-10-14 22:55:52 +02:00
if self._driver and not self._inv_id then
2021-02-24 09:31:27 +01:00
if self._driver : is_player ( ) then
self._passenger = obj
else
self._passenger = self._driver
self._driver = obj
end
set_double_attach ( self )
else
self._driver = obj
2022-10-14 22:55:52 +02:00
if self._inv_id then
set_choat_attach ( self )
else
set_attach ( self )
end
2021-02-24 09:31:27 +01:00
end
local visual_size = get_visual_size ( obj )
local yaw = self.object : get_yaw ( )
obj : set_properties ( { visual_size = vector.divide ( visual_size , boat_visual_size ) } )
if obj : is_player ( ) then
local name = obj : get_player_name ( )
mcl_player.player_attached [ name ] = true
minetest.after ( 0.2 , function ( name )
local player = minetest.get_player_by_name ( name )
if player then
mcl_player.player_set_animation ( player , " sit " , 30 )
end
end , name )
obj : set_look_horizontal ( yaw )
2021-07-20 16:14:34 +02:00
mcl_title.set ( obj , " actionbar " , { text = S ( " Sneak to dismount " ) , color = " white " , stay = 60 } )
2021-02-24 09:31:27 +01:00
else
obj : get_luaentity ( ) . _old_visual_size = visual_size
end
end
local function detach_object ( obj , change_pos )
2022-11-20 02:54:42 +01:00
if not obj or not obj : get_pos ( ) then return end
2021-02-24 09:31:27 +01:00
obj : set_detach ( )
obj : set_properties ( { visual_size = get_visual_size ( obj ) } )
if obj : is_player ( ) then
mcl_player.player_attached [ obj : get_player_name ( ) ] = false
mcl_player.player_set_animation ( obj , " stand " , 30 )
else
obj : get_luaentity ( ) . _old_visual_size = nil
end
if change_pos then
obj : set_pos ( vector.add ( obj : get_pos ( ) , vector.new ( 0 , 0.2 , 0 ) ) )
end
end
2017-06-20 15:21:44 +02:00
2017-06-12 23:21:41 +02:00
--
-- Boat entity
--
local boat = {
physical = true ,
2022-06-02 07:20:44 +02:00
pointable = true ,
2017-06-12 23:21:41 +02:00
-- Warning: Do not change the position of the collisionbox top surface,
-- lowering it causes the boat to fall through the world if underwater
2022-10-14 22:59:09 +02:00
collisionbox = { - 0.5 , - 0.15 , - 0.5 , 0.5 , 0.55 , 0.5 } ,
selectionbox = { - 0.7 , - 0.15 , - 0.7 , 0.7 , 0.55 , 0.7 } ,
2017-06-12 23:21:41 +02:00
visual = " mesh " ,
2017-06-13 01:39:21 +02:00
mesh = " mcl_boats_boat.b3d " ,
2022-10-18 14:45:53 +02:00
textures = { " mcl_boats_texture_oak_boat.png " , " blank.png " } ,
2017-06-20 15:21:44 +02:00
visual_size = boat_visual_size ,
2021-02-18 14:47:35 +01:00
hp_max = boat_max_hp ,
2021-02-22 12:43:29 +01:00
damage_texture_modifier = " ^[colorize:white:0 " ,
2017-06-12 23:50:42 +02:00
2017-06-13 00:26:17 +02:00
_driver = nil , -- Attached driver (player) or nil if none
2021-01-31 12:54:40 +01:00
_passenger = nil ,
2017-06-13 00:26:17 +02:00
_v = 0 , -- Speed
_last_v = 0 , -- Temporary speed variable
_removed = false , -- If true, boat entity is considered removed (e.g. after punch) and should be ignored
_itemstring = " mcl_boats:boat " , -- Itemstring of the boat item (implies boat type)
2022-10-18 14:45:53 +02:00
_animation = 0 , -- 0: not animated; 1: paddling forwards; -1: paddling backwards
2021-02-22 12:43:29 +01:00
_regen_timer = 0 ,
_damage_anim = 0 ,
2017-06-12 23:21:41 +02:00
}
2021-02-24 09:31:27 +01:00
minetest.register_on_respawnplayer ( detach_object )
2021-01-04 14:21:28 +01:00
2017-06-12 23:21:41 +02:00
function boat . on_rightclick ( self , clicker )
2023-11-03 23:09:49 +01:00
if self._passenger or not clicker or clicker : get_attach ( ) or ( self.name == " mcl_boats:chest_boat " and self._driver ) then
2017-06-12 23:21:41 +02:00
return
end
2021-02-24 09:31:27 +01:00
attach_object ( self , clicker )
2017-06-12 23:21:41 +02:00
end
function boat . on_activate ( self , staticdata , dtime_s )
2024-04-30 16:24:24 +02:00
self.object : set_armor_groups ( { fleshy = 125 } )
2017-06-13 00:14:17 +02:00
local data = minetest.deserialize ( staticdata )
if type ( data ) == " table " then
2017-06-13 00:26:17 +02:00
self._v = data.v
self._last_v = self._v
2017-06-13 00:14:17 +02:00
self._itemstring = data.itemstring
2021-11-09 17:39:39 +01:00
2022-10-18 14:45:53 +02:00
-- Update the texutes for existing old boat entity instances.
-- Maybe remove this in the future.
if # data.textures ~= 2 then
local has_chest = self._itemstring : find ( " chest " )
data.textures = {
data.textures [ 1 ] : gsub ( " _chest " , " " ) ,
has_chest and " mcl_chests_normal.png " or " blank.png "
}
2021-11-09 17:39:39 +01:00
end
2021-02-22 12:43:29 +01:00
self.object : set_properties ( { textures = data.textures } )
2017-06-12 23:21:41 +02:00
end
end
function boat . get_staticdata ( self )
2017-06-13 00:14:17 +02:00
return minetest.serialize ( {
2017-06-13 00:26:17 +02:00
v = self._v ,
2017-06-13 00:14:17 +02:00
itemstring = self._itemstring ,
textures = self.object : get_properties ( ) . textures
} )
2017-06-12 23:21:41 +02:00
end
2021-01-24 16:27:04 +01:00
function boat . on_death ( self , killer )
2021-03-18 12:31:25 +01:00
mcl_burning.extinguish ( self.object )
2021-01-24 16:27:04 +01:00
if killer and killer : is_player ( ) and minetest.is_creative_enabled ( killer : get_player_name ( ) ) then
local inv = killer : get_inventory ( )
if not inv : contains_item ( " main " , self._itemstring ) then
inv : add_item ( " main " , self._itemstring )
2017-06-12 23:21:41 +02:00
end
2021-01-24 16:27:04 +01:00
else
minetest.add_item ( self.object : get_pos ( ) , self._itemstring )
end
if self._driver then
2021-02-24 09:31:27 +01:00
detach_object ( self._driver )
2017-06-12 23:21:41 +02:00
end
2021-01-31 12:54:40 +01:00
if self._passenger then
2021-02-24 09:31:27 +01:00
detach_object ( self._passenger )
2021-01-31 12:54:40 +01:00
end
2021-01-24 16:27:04 +01:00
self._driver = nil
2021-01-31 12:54:40 +01:00
self._passenger = nil
2017-06-12 23:21:41 +02:00
end
2021-02-22 12:43:29 +01:00
function boat . on_punch ( self , puncher , time_from_last_punch , tool_capabilities , dir , damage )
if damage > 0 then
self._regen_timer = 0
end
end
2021-01-28 19:02:44 +01:00
function boat . on_step ( self , dtime , moveresult )
2021-04-25 13:09:20 +02:00
mcl_burning.tick ( self.object , dtime , self )
2022-08-07 06:09:12 +02:00
-- mcl_burning.tick may remove object immediately
if not self.object : get_pos ( ) then return end
2021-03-18 12:31:25 +01:00
2019-03-06 04:38:57 +01:00
self._v = get_v ( self.object : get_velocity ( ) ) * get_sign ( self._v )
2019-09-11 11:17:42 +02:00
local v_factor = 1
local v_slowdown = 0.02
local p = self.object : get_pos ( )
2021-02-24 10:38:49 +01:00
local on_water = true
local on_ice = false
local in_water = is_water ( { x = p.x , y = p.y - boat_y_offset + 1 , z = p.z } )
2022-08-01 05:20:19 +02:00
local in_river_water = is_river_water ( { x = p.x , y = p.y - boat_y_offset + 1 , z = p.z } )
2021-02-24 10:38:49 +01:00
local waterp = { x = p.x , y = p.y - boat_y_offset - 0.1 , z = p.z }
if not is_water ( waterp ) then
2019-09-11 12:11:04 +02:00
on_water = false
2021-02-24 10:38:49 +01:00
if not in_water and is_ice ( waterp ) then
on_ice = true
2022-08-09 02:12:44 +02:00
elseif is_fire ( { x = p.x , y = p.y - boat_y_offset , z = p.z } ) then
2022-08-09 18:23:44 +02:00
boat.on_death ( self , nil )
self.object : remove ( )
return
2021-02-24 10:38:49 +01:00
else
v_slowdown = 0.04
2021-02-27 14:38:53 +01:00
v_factor = 0.5
2021-02-24 10:38:49 +01:00
end
2022-08-01 05:20:19 +02:00
elseif in_water and not in_river_water then
2019-09-11 12:11:04 +02:00
on_water = false
in_water = true
v_factor = 0.75
v_slowdown = 0.05
2019-09-11 11:17:42 +02:00
end
2019-09-11 12:11:04 +02:00
2021-02-22 12:43:29 +01:00
local hp = self.object : get_hp ( )
local regen_timer = self._regen_timer + dtime
if hp >= boat_max_hp then
regen_timer = 0
elseif regen_timer >= 0.5 then
hp = hp + 1
self.object : set_hp ( hp )
regen_timer = 0
end
self._regen_timer = regen_timer
2021-02-18 14:47:35 +01:00
2021-01-28 19:02:44 +01:00
if moveresult and moveresult.collides then
2021-03-16 17:43:32 +01:00
for _ , collision in pairs ( moveresult.collisions ) do
2021-01-28 19:02:44 +01:00
local pos = collision.node_pos
2021-02-23 10:25:17 +01:00
if collision.type == " node " and minetest.get_item_group ( minetest.get_node ( pos ) . name , " dig_by_boat " ) > 0 then
2021-01-28 19:02:44 +01:00
minetest.dig_node ( pos )
end
end
end
2021-01-31 12:54:40 +01:00
local had_passenger = self._passenger
self._driver = check_object ( self._driver )
self._passenger = check_object ( self._passenger )
if self._passenger then
if not self._driver then
self._driver = self._passenger
self._passenger = nil
else
local ctrl = self._passenger : get_player_control ( )
if ctrl and ctrl.sneak then
2021-03-26 17:51:13 +01:00
detach_object ( self._passenger , true )
2021-01-31 12:54:40 +01:00
self._passenger = nil
end
end
end
2017-06-13 00:26:17 +02:00
if self._driver then
2021-01-31 12:54:40 +01:00
if had_passenger and not self._passenger then
set_attach ( self )
end
2017-06-13 00:26:17 +02:00
local ctrl = self._driver : get_player_control ( )
2021-01-31 12:54:40 +01:00
if ctrl and ctrl.sneak then
2021-02-24 09:31:27 +01:00
detach_object ( self._driver , true )
2021-01-28 17:44:55 +01:00
self._driver = nil
return
end
2019-03-06 04:38:57 +01:00
local yaw = self.object : get_yaw ( )
2022-01-26 17:37:55 +01:00
if ctrl and ctrl.up then
2017-07-08 17:26:07 +02:00
-- Forwards
2019-09-11 11:17:42 +02:00
self._v = self._v + 0.1 * v_factor
2017-07-08 17:26:07 +02:00
-- Paddling animation
if self._animation ~= 1 then
self.object : set_animation ( { x = 0 , y = 40 } , paddling_speed , 0 , true )
self._animation = 1
end
2022-01-26 17:37:55 +01:00
elseif ctrl and ctrl.down then
2017-07-08 17:26:07 +02:00
-- Backwards
2019-09-11 11:17:42 +02:00
self._v = self._v - 0.1 * v_factor
2017-07-08 17:26:07 +02:00
-- Paddling animation, reversed
if self._animation ~= - 1 then
self.object : set_animation ( { x = 0 , y = 40 } , - paddling_speed , 0 , true )
self._animation = - 1
end
else
-- Stop paddling animation if no control pressed
if self._animation ~= 0 then
self.object : set_animation ( { x = 0 , y = 40 } , 0 , 0 , true )
self._animation = 0
end
2017-06-12 23:21:41 +02:00
end
2021-01-31 12:54:40 +01:00
if ctrl and ctrl.left then
2017-06-13 00:26:17 +02:00
if self._v < 0 then
2019-09-11 11:17:42 +02:00
self.object : set_yaw ( yaw - ( 1 + dtime ) * 0.03 * v_factor )
2017-06-12 23:21:41 +02:00
else
2019-09-11 11:17:42 +02:00
self.object : set_yaw ( yaw + ( 1 + dtime ) * 0.03 * v_factor )
2017-06-12 23:21:41 +02:00
end
2021-01-31 12:54:40 +01:00
elseif ctrl and ctrl.right then
2017-06-13 00:26:17 +02:00
if self._v < 0 then
2019-09-11 11:17:42 +02:00
self.object : set_yaw ( yaw + ( 1 + dtime ) * 0.03 * v_factor )
2017-06-12 23:21:41 +02:00
else
2019-09-11 11:17:42 +02:00
self.object : set_yaw ( yaw - ( 1 + dtime ) * 0.03 * v_factor )
2017-06-12 23:21:41 +02:00
end
end
2017-07-08 17:26:07 +02:00
else
-- Stop paddling without driver
if self._animation ~= 0 then
self.object : set_animation ( { x = 0 , y = 40 } , 0 , 0 , true )
self._animation = 0
end
2021-02-24 09:31:27 +01:00
2021-03-16 17:43:32 +01:00
for _ , obj in pairs ( minetest.get_objects_inside_radius ( self.object : get_pos ( ) , 1.3 ) ) do
2021-02-24 09:31:27 +01:00
local entity = obj : get_luaentity ( )
2022-05-25 14:02:10 +02:00
if entity and entity.is_mob then
2021-02-24 09:31:27 +01:00
attach_object ( self , obj )
break
end
end
2017-06-12 23:21:41 +02:00
end
2017-06-13 00:26:17 +02:00
local s = get_sign ( self._v )
2021-02-24 10:38:49 +01:00
if not on_ice and not on_water and not in_water and math.abs ( self._v ) > 2.0 then
v_slowdown = math.min ( math.abs ( self._v ) - 2.0 , v_slowdown * 5 )
elseif not on_ice and in_water and math.abs ( self._v ) > 1.5 then
2019-10-02 20:53:47 +02:00
v_slowdown = math.min ( math.abs ( self._v ) - 1.5 , v_slowdown * 5 )
2019-09-11 11:17:42 +02:00
end
self._v = self._v - v_slowdown * s
2017-06-13 00:26:17 +02:00
if s ~= get_sign ( self._v ) then
self._v = 0
2017-06-12 23:21:41 +02:00
end
2017-07-08 17:55:46 +02:00
p.y = p.y - boat_y_offset
2017-06-12 23:21:41 +02:00
local new_velo
2021-05-25 00:50:04 +02:00
local new_acce
2021-02-24 10:38:49 +01:00
if not is_water ( p ) and not on_ice then
2019-09-11 12:11:04 +02:00
-- Not on water or inside water: Free fall
2021-05-25 00:50:04 +02:00
--local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
2019-09-11 11:17:42 +02:00
new_acce = { x = 0 , y = - 9.8 , z = 0 }
2019-03-06 04:38:57 +01:00
new_velo = get_velocity ( self._v , self.object : get_yaw ( ) ,
self.object : get_velocity ( ) . y )
2017-06-12 23:21:41 +02:00
else
p.y = p.y + 1
2021-11-17 18:03:45 +01:00
local is_obsidian_boat = self.object : get_luaentity ( ) . _itemstring == " mcl_boats:boat_obsidian "
2022-08-01 05:20:19 +02:00
if is_river_water ( p ) then
local y = self.object : get_velocity ( ) . y
if y >= 5 then
y = 5
elseif y < 0 then
new_acce = { x = 0 , y = 10 , z = 0 }
else
new_acce = { x = 0 , y = 2 , z = 0 }
end
new_velo = get_velocity ( self._v , self.object : get_yaw ( ) , y )
self.object : set_pos ( self.object : get_pos ( ) )
elseif is_water ( p ) and not is_river_water ( p ) or is_obsidian_boat then
2019-09-11 12:11:04 +02:00
-- Inside water: Slowly sink
2019-03-06 04:38:57 +01:00
local y = self.object : get_velocity ( ) . y
2019-09-11 12:11:04 +02:00
y = y - 0.01
if y < - 0.2 then
y = - 0.2
2017-06-12 23:21:41 +02:00
end
2019-09-11 12:11:04 +02:00
new_acce = { x = 0 , y = 0 , z = 0 }
2019-03-06 04:38:57 +01:00
new_velo = get_velocity ( self._v , self.object : get_yaw ( ) , y )
2017-06-12 23:21:41 +02:00
else
2019-09-11 12:11:04 +02:00
-- On top of water
2017-06-12 23:21:41 +02:00
new_acce = { x = 0 , y = 0 , z = 0 }
2019-09-11 12:50:58 +02:00
if math.abs ( self.object : get_velocity ( ) . y ) < 0 then
2019-03-06 04:38:57 +01:00
new_velo = get_velocity ( self._v , self.object : get_yaw ( ) , 0 )
2017-06-12 23:21:41 +02:00
else
2019-03-06 04:38:57 +01:00
new_velo = get_velocity ( self._v , self.object : get_yaw ( ) ,
self.object : get_velocity ( ) . y )
2017-06-12 23:21:41 +02:00
end
end
end
2019-09-11 13:28:14 +02:00
-- Terminal velocity: 8 m/s per axis of travel
2021-02-24 10:38:49 +01:00
local terminal_velocity = on_ice and 57.1 or 8.0
2019-09-11 13:28:14 +02:00
for _ , axis in pairs ( { " z " , " y " , " x " } ) do
2021-02-24 10:38:49 +01:00
if math.abs ( new_velo [ axis ] ) > terminal_velocity then
new_velo [ axis ] = terminal_velocity * get_sign ( new_velo [ axis ] )
2019-09-11 13:28:14 +02:00
end
end
2021-02-22 12:43:29 +01:00
local yaw = self.object : get_yaw ( )
local anim = ( boat_max_hp - hp - regen_timer * 2 ) / boat_max_hp * math.pi / 4
self.object : set_rotation ( vector.new ( anim , yaw , anim ) )
2019-03-06 04:38:57 +01:00
self.object : set_velocity ( new_velo )
self.object : set_acceleration ( new_acce )
2017-06-12 23:21:41 +02:00
end
2017-06-13 00:21:43 +02:00
-- Register one entity for all boat types
minetest.register_entity ( " mcl_boats:boat " , boat )
2022-09-23 17:12:10 +02:00
local cboat = table.copy ( boat )
2022-10-18 14:45:53 +02:00
cboat.textures = { " mcl_boats_texture_oak_chest_boat.png " , " mcl_chests_normal.png " }
2022-09-23 17:12:10 +02:00
cboat._itemstring = " mcl_boats:chest_boat "
2022-10-14 23:03:38 +02:00
cboat.collisionbox = { - 0.5 , - 0.15 , - 0.5 , 0.5 , 0.75 , 0.5 }
cboat.selectionbox = { - 0.7 , - 0.15 , - 0.7 , 0.7 , 0.75 , 0.7 }
2022-09-23 17:12:10 +02:00
minetest.register_entity ( " mcl_boats:chest_boat " , cboat )
mcl_entity_invs.register_inv ( " mcl_boats:chest_boat " , " Boat " , 27 )
2023-05-01 03:36:39 +02:00
local boat_ids = { " boat " , " boat_spruce " , " boat_birch " , " boat_jungle " , " boat_acacia " , " boat_dark_oak " , " boat_obsidian " , " boat_mangrove " , " boat_cherry " , " chest_boat " , " chest_boat_spruce " , " chest_boat_birch " , " chest_boat_jungle " , " chest_boat_acacia " , " chest_boat_dark_oak " , " chest_boat_mangrove " , " chest_boat_cherry " }
local names = { S ( " Oak Boat " ) , S ( " Spruce Boat " ) , S ( " Birch Boat " ) , S ( " Jungle Boat " ) , S ( " Acacia Boat " ) , S ( " Dark Oak Boat " ) , S ( " Obsidian Boat " ) , S ( " Mangrove Boat " ) , S ( " Cherry Boat " ) , S ( " Oak Chest Boat " ) , S ( " Spruce Chest Boat " ) , S ( " Birch Chest Boat " ) , S ( " Jungle Chest Boat " ) , S ( " Acacia Chest Boat " ) , S ( " Dark Oak Chest Boat " ) , S ( " Mangrove Chest Boat " ) , S ( " Cherry Chest Boat " ) }
local craftstuffs = { " mcl_core:wood " , " mcl_core:sprucewood " , " mcl_core:birchwood " , " mcl_core:junglewood " , " mcl_core:acaciawood " , " mcl_core:darkwood " , " mcl_core:obsidian " , " mcl_mangrove:mangrove_wood " , " mcl_cherry_blossom:cherrywood " }
2015-06-29 19:55:56 +02:00
2017-06-12 23:21:41 +02:00
for b = 1 , # boat_ids do
local itemstring = " mcl_boats: " .. boat_ids [ b ]
2015-06-29 19:55:56 +02:00
2020-02-19 04:54:17 +01:00
local longdesc , usagehelp , tt_help , help , helpname
2017-06-13 00:33:31 +02:00
help = false
-- Only create one help entry for all boats
if b == 1 then
help = true
2019-03-07 20:43:39 +01:00
longdesc = S ( " Boats are used to travel on the surface of water. " )
2021-04-26 10:17:07 +02:00
usagehelp = S ( " Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item. " )
2019-03-07 20:43:39 +01:00
helpname = S ( " Boat " )
2017-06-13 00:33:31 +02:00
end
2020-02-19 04:54:17 +01:00
tt_help = S ( " Water vehicle " )
2017-06-13 00:33:31 +02:00
2022-10-18 14:45:53 +02:00
local inventory_image
local texture
local id = boat_ids [ b ]
if id : find ( " chest " ) then
if id == " chest_boat " then id = " oak " end
local id = id : gsub ( " chest_boat_ " , " " )
inventory_image = " mcl_boats_ " .. id .. " _chest_boat.png "
texture = " mcl_boats_texture_ " .. id .. " _boat.png "
else
if id == " boat " then id = " oak " end
local id = id : gsub ( " boat_ " , " " )
inventory_image = " mcl_boats_ " .. id .. " _boat.png "
texture = " mcl_boats_texture_ " .. id .. " _boat.png "
end
2017-06-12 23:21:41 +02:00
minetest.register_craftitem ( itemstring , {
description = names [ b ] ,
2020-02-19 04:54:17 +01:00
_tt_help = tt_help ,
2017-06-13 00:33:31 +02:00
_doc_items_create_entry = help ,
_doc_items_entry_name = helpname ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = usagehelp ,
2022-10-18 14:45:53 +02:00
inventory_image = inventory_image ,
2017-01-16 19:10:18 +01:00
liquids_pointable = true ,
2017-01-20 04:54:09 +01:00
groups = { boat = 1 , transport = 1 } ,
2017-01-16 23:34:40 +01:00
stack_max = 1 ,
2017-01-16 19:10:18 +01:00
on_place = function ( itemstack , placer , pointed_thing )
if pointed_thing.type ~= " node " then
2019-09-11 12:23:56 +02:00
return itemstack
2017-01-16 19:10:18 +01:00
end
2017-03-02 15:44:31 +01:00
-- Call on_rightclick if the pointed node defines it
local node = minetest.get_node ( pointed_thing.under )
if placer and not placer : get_player_control ( ) . sneak then
if minetest.registered_nodes [ node.name ] and minetest.registered_nodes [ node.name ] . on_rightclick then
return minetest.registered_nodes [ node.name ] . on_rightclick ( pointed_thing.under , node , placer , itemstack ) or itemstack
end
end
2019-09-11 12:23:56 +02:00
local pos = table.copy ( pointed_thing.under )
local dir = vector.subtract ( pointed_thing.above , pointed_thing.under )
if math.abs ( dir.x ) > 0.9 or math.abs ( dir.z ) > 0.9 then
pos = vector.add ( pos , vector.multiply ( dir , boat_side_offset ) )
elseif is_water ( pos ) then
pos = vector.add ( pos , vector.multiply ( dir , boat_y_offset ) )
2019-09-11 11:17:42 +02:00
else
2019-09-11 12:23:56 +02:00
pos = vector.add ( pos , vector.multiply ( dir , boat_y_offset_ground ) )
2017-01-16 19:10:18 +01:00
end
2022-09-23 17:12:10 +02:00
local boat_ent = " mcl_boats:boat "
2022-10-18 14:45:53 +02:00
local chest_tex = " blank.png "
2022-09-23 17:12:10 +02:00
if itemstring : find ( " chest " ) then
boat_ent = " mcl_boats:chest_boat "
2022-10-18 14:45:53 +02:00
chest_tex = " mcl_chests_normal.png "
2022-09-23 17:12:10 +02:00
end
local boat = minetest.add_entity ( pos , boat_ent )
2017-06-12 23:50:42 +02:00
boat : get_luaentity ( ) . _itemstring = itemstring
2022-10-18 14:45:53 +02:00
boat : set_properties ( { textures = { texture , chest_tex } } )
2018-05-09 18:43:07 +02:00
boat : set_yaw ( placer : get_look_horizontal ( ) )
2020-07-10 16:08:40 +02:00
if not minetest.is_creative_enabled ( placer : get_player_name ( ) ) then
2017-01-16 19:10:18 +01:00
itemstack : take_item ( )
end
return itemstack
end ,
2018-02-01 22:45:19 +01:00
_on_dispense = function ( stack , pos , droppos , dropnode , dropdir )
local below = { x = droppos.x , y = droppos.y - 1 , z = droppos.z }
local belownode = minetest.get_node ( below )
-- Place boat as entity on or in water
if minetest.get_item_group ( dropnode.name , " water " ) ~= 0 or ( dropnode.name == " air " and minetest.get_item_group ( belownode.name , " water " ) ~= 0 ) then
minetest.add_entity ( droppos , " mcl_boats:boat " )
else
minetest.add_item ( droppos , stack )
end
end ,
2017-01-16 19:10:18 +01:00
} )
2017-06-12 23:21:41 +02:00
local c = craftstuffs [ b ]
2022-09-24 05:34:06 +02:00
if not itemstring : find ( " chest " ) then
minetest.register_craft ( {
output = itemstring : gsub ( " :boat " , " :chest_boat " ) ,
recipe = {
{ " mcl_chests:chest " } ,
{ itemstring } ,
} ,
} )
minetest.register_craft ( {
output = itemstring ,
recipe = {
{ c , " " , c } ,
{ c , c , c } ,
} ,
} )
end
2017-01-16 19:10:18 +01:00
end
2015-06-29 19:55:56 +02:00
2017-01-10 06:43:07 +01:00
minetest.register_craft ( {
type = " fuel " ,
recipe = " group:boat " ,
burntime = 20 ,
} )
2021-05-29 16:12:33 +02:00
if minetest.get_modpath ( " doc_identifier " ) then
2017-06-13 00:18:51 +02:00
doc.sub . identifier.register_object ( " mcl_boats:boat " , " craftitems " , " mcl_boats:boat " )
end