diff --git a/mods/ENTITIES/mcl_minecarts/functions.lua b/mods/ENTITIES/mcl_minecarts/functions.lua index 766412f71..9f1157ad6 100644 --- a/mods/ENTITIES/mcl_minecarts/functions.lua +++ b/mods/ENTITIES/mcl_minecarts/functions.lua @@ -98,6 +98,31 @@ mod.south = south mod.east = east mod.west = west +--[[ + mcl_minecarts.snap_direction(dir) + + returns a valid cart direction that has the smallest angle difference to `dir' +]] +local VALID_DIRECTIONS = { + north, vector.offset(north, 0, 1, 0), vector.offset(north, 0, -1, 0), + south, vector.offset(south, 0, 1, 0), vector.offset(south, 0, -1, 0), + east, vector.offset(east, 0, 1, 0), vector.offset(east, 0, -1, 0), + west, vector.offset(west, 0, 1, 0), vector.offset(west, 0, -1, 0), +} +function mod.snap_direction(dir) + dir = vector.normalize(dir) + local best = nil + local diff = -1 + for _,d in pairs(VALID_DIRECTIONS) do + local dot = vector.dot(dir,d) + if dot > diff then + best = d + diff = dot + end + end + return best +end + local CONNECTIONS = { north, south, east, west } local HORIZONTAL_STANDARD_RULES = { [N] = { "", 0, mask = N, score = 1, can_slope = true }, diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 137de228a..426e534f1 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -41,7 +41,6 @@ end local function detach_minecart(self) local staticdata = self._staticdata - print("Detaching minecart") staticdata.connected_at = nil self.object:set_velocity(staticdata.dir * staticdata.velocity) @@ -453,13 +452,15 @@ local function do_detached_movement(self, dtime) local pos_r = vector.round(self.object:get_pos()) local node = minetest.get_node(pos_r) if minetest.get_item_group(node.name, "rail") ~= 0 then - print("Reconnected railcart at "..tostring(pos_r)) staticdata.connected_at = pos_r staticdata.railtype = node.name local freebody_velocity = self.object:get_velocity() - staticdata.dir = vector.normalize(freebody_velocity) - staticdata.velocity = vector.length(freebody_velocity) + staticdata.dir = mod:get_rail_direction(pos_r, mod.snap_direction(freebody_velocity)) + + -- Use vector projection to only keep the velocity in the new direction of movement on the rail + -- https://en.wikipedia.org/wiki/Vector_projection + staticdata.velocity = vector.dot(staticdata.dir,freebody_velocity) -- Clear freebody movement self.object:set_velocity(vector.new(0,0,0))