Compare commits

...

5 Commits

Author SHA1 Message Date
Nils Dagsson Moskopp 47ef53db56
Force-detach minecart driver not attached to cart
If the driver manages to either die in a minecart or attach to some
other object, they may still be taking up space in the cart. No new
driver could enter a cart in such a situation, therefore any driver
of a cart without an attached object must be detached immediately.
2021-08-01 21:47:35 +02:00
Nils Dagsson Moskopp 37828b27a0
Do not rotate a boat while it is attached
Rotating a boat while it is attached to another object does not work as
expected: While the boat does not visually rotate, the head of the
driver rotates as if the boat did actually rotate. That looks wrong,
therefore no rotation must happen if the boat is attached to an object,
e.g. a minecart.
2021-08-01 21:05:23 +02:00
Nils Dagsson Moskopp 93b19d1588
Allow players to accelerate a minecart with a boat
In Minecraft you can put a boat in a minecart and steer the minecart
from the boat, which is quite useful to move mobs around – minecarts
have one seat, boats have two.
2021-08-01 19:34:50 +02:00
Nils Dagsson Moskopp cf3c335c37
Inhibit minecart pickup after detaching driver
When a minecart drives over an activator rail, it detaches its driver.
In cases where the “driver” is a mob or a boat, the mob or boat can get
picked up again immediately, which is likely to be unintended behaviour.

By inhibiting minecart pickup for a second when detaching a mob or boat
from a minecart, activator rails behave as expected: Minecart drivers
are detached and not picked up immediately if they are a mob or boat.
2021-07-22 06:50:20 +02:00
Nils Dagsson Moskopp c593036b61
Add support for mobs and boats in minecarts 2021-07-22 06:50:13 +02:00
2 changed files with 72 additions and 9 deletions

View File

@ -269,6 +269,25 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, paddling_speed, 0, true)
self._animation = 1
end
-- If boat is in a minecart, punch that cart.
--
-- Why? In Minecraft you can put a boat in a
-- minecart and steer the cart from the boat,
-- which is quite useful to move mobs around.
-- (Minecarts have one seat, boats have two.)
--
-- No, this is not a bug. Mojang has known it
-- for years and they never fixed that “bug”.
local parent = self.object:get_attach()
if parent then
local parent_name =
parent:get_luaentity().name
if parent_name == "mcl_minecarts:minecart" then
-- The driver must punch so
-- the steering works here.
parent:punch(self._driver, 1, {})
end
end
elseif ctrl.down then
-- Backwards
self._v = self._v - 0.1 * v_factor
@ -278,6 +297,7 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, -paddling_speed, 0, true)
self._animation = -1
end
-- TODO: If boat is in a minecart, slow cart.
else
-- Stop paddling animation if no control pressed
if self._animation ~= 0 then
@ -285,13 +305,22 @@ function boat.on_step(self, dtime, moveresult)
self._animation = 0
end
end
if ctrl and ctrl.left then
-- Rotating a boat while it is attached to another
-- object does not work as expected: While the boat
-- does not visually rotate, the head of the driver
-- rotates as if the boat did actually rotate. That
-- looks wrong, therefore no rotation must happen if
-- the boat is attached to an object, e.g. a minecart.
--
-- TODO: Actually rotate boat once someone figures out
-- how to rotate an object attached to another object.
if ctrl and ctrl.left and not self.object:get_attach() then
if self._v < 0 then
self.object:set_yaw(yaw - (1 + dtime) * 0.03 * v_factor)
else
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
end
elseif ctrl and ctrl.right then
elseif ctrl and ctrl.right and not self.object:get_attach() then
if self._v < 0 then
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
else

View File

@ -12,8 +12,15 @@ local function detach_driver(self)
if not self._driver then
return
end
mcl_player.player_attached[self._driver] = nil
local player = minetest.get_player_by_name(self._driver)
if not self._driver:is_player() then
self._pickup_inhibit_timer = 1
self._driver:set_detach()
self._driver = nil
return
end
local player_name = self._driver:get_player_name()
mcl_player.player_attached[player_name] = nil
local player = minetest.get_player_by_name(player_name)
self._driver = nil
self._start_pos = nil
if player then
@ -75,6 +82,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
_old_pos = nil,
_old_vel = {x=0, y=0, z=0},
_old_switch = 0,
_pickup_inhibit_timer = 0, -- how many seconds are mobs and boats not picked up after detaching?
_railtype = nil,
}
@ -151,7 +159,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
end
local vel = self.object:get_velocity()
if puncher:get_player_name() == self._driver then
if self._driver and puncher:get_player_name() == self._driver:get_player_name() then
if math.abs(vel.x + vel.z) > 7 then
return
end
@ -175,9 +183,35 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
cart.on_activate_by_rail = on_activate_by_rail
function cart:on_step(dtime)
-- If the driver manages to either die in a minecart
-- or attach to some other object, they may still be
-- taking up space in the cart. Therefore the driver
-- must be detached if the minecart has no children.
if self._driver and
#self.object:get_children() == 0 then
detach_driver(self)
end
if self._pickup_inhibit_timer > 0 then
self._pickup_inhibit_timer = self._pickup_inhibit_timer - dtime
end
local entity_name = self.object:get_luaentity().name
if entity_name == "mcl_minecarts:minecart" and self._pickup_inhibit_timer <= 0 then
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
local entity = obj:get_luaentity()
if not self._driver and entity and ( entity._cmi_is_mob or entity.name == "mcl_boats:boat" ) and not obj:get_attach() then
self._driver = obj
obj:set_attach(self.object)
break
end
end
end
local ctrl, player = nil, nil
if self._driver then
player = minetest.get_player_by_name(self._driver)
if self._driver and self._driver:is_player() then
local player_name = self._driver:get_player_name()
player = minetest.get_player_by_name(player_name)
if player then
ctrl = player:get_player_control()
-- player detach
@ -446,7 +480,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
end
-- Give achievement when player reached a distance of 1000 nodes from the start position
if self._driver and (vector.distance(self._start_pos, pos) >= 1000) then
if self._driver and self._driver:is_player() and (vector.distance(self._start_pos, pos) >= 1000) then
awards.unlock(self._driver, "mcl:onARail")
end
@ -634,7 +668,7 @@ register_minecart(
if self._driver and player_name == self._driver then
detach_driver(self)
elseif not self._driver then
self._driver = player_name
self._driver = clicker
self._start_pos = self.object:get_pos()
mcl_player.player_attached[player_name] = true
clicker:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})