I've played with the code a little and here is a start to the change needed to move the player with the cart.
in scriptapi.cpp around line 1869
Code: Select all
static int l_setpos(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
//LuaEntitySAO *co = getluaobject(ref);
v3f pos = readFloatPos(L, 2);
ServerRemotePlayer *player = getplayer(ref);
if(player != NULL)
{
player->setPos(pos);
std::ostringstream os(std::ios::binary);
// command (3 = force update position)
writeU8(os, 3);
// pos
writeV3F1000(os, pos);
// yaw
writeF1000(os, player->getYaw());
// create message and add to list
ActiveObjectMessage aom(player->getId(), false, os.str());
player->m_messages_out.push_back(aom);
return 0;
}
ServerActiveObject *co = getobject(ref);
if(co != NULL)
{
// Do it
co->setPos(pos);
return 0;
}
return 0;
}
and in content_cao.cpp around line 2248
Code: Select all
void processMessage(const std::string &data)
{
//infostream<<"PlayerCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0) // update position
{
// pos
m_position = readV3F1000(is);
// yaw
m_yaw = readF1000(is);
pos_translator.update(m_position, false);
updateNodePos();
}
else if(cmd == 1) // punched
{
// damage
s16 damage = readS16(is);
if(m_is_local_player)
m_env->damageLocalPlayer(damage, false);
m_damage_visual_timer = 0.5;
updateTextures("^[brighten");
}
else if(cmd == 3) // force update position
{
// pos
m_position = readV3F1000(is);
// yaw
m_yaw = readF1000(is);
if(m_is_local_player)
{
m_local_player->setPosition(m_position);
}
pos_translator.update(m_position, false);
updateNodePos();
}
}
I also moved the code that moves the player in the mod script and made it so you and get attached if you are standing in the cart when you activate it:
Code: Select all
-- first state: cart is moving
if self.moving ~= false and self.time == 0 then
local pos_f = self.object:getpos()
if self.moving ~= false then
if eq(pos_f.x, self.moving.x) and eq(pos_f.y, self.moving.y) and eq(pos_f.z, self.moving.z) then
self.moving = false
self.object:setacceleration({x = 0, y = -10, z = 0})
if self.stopnow then
self.stopnow = false
self.attached_to = false
end
else
local needed = {x = self.moving.x - pos_f.x,
y = self.moving.y - pos_f.y,
z = self.moving.z - pos_f.z}
needed = resize(needed, math.min(length(needed), speed))
self.object:setpos(move(pos_f, needed))
-- move player that attached to this cart; FIXME
local player = minetest.env:get_player_by_name(self.attached_to)
if player ~= nil then
--print (self.attached_to .. " moved to " .. self.object:getpos().x .. ", " .. self.object:getpos().y .. ", " .. self.object:getpos().z)
p_pos = self.object:getpos()
p_pos.y = p_pos.y - 0.5
player:setpos(p_pos)
end
end
return
end
end
-- second state: cart just need to check whether to move next self.time==0
...
...
function cart:on_rightclick(clicker)
if self.attached_to == false then
local playerpos = clicker:getpos()
local selfpos = self.object:getpos()
if ((playerpos.x-1) < selfpos.x and (playerpos.x+1) > selfpos.x and
(playerpos.y-2) < (selfpos.y) and (playerpos.y+1) > (selfpos.y) and
(playerpos.z-1) < selfpos.z and (playerpos.z+1) > selfpos.z) then
self.attached_to = clicker:get_player_name()
else
self.attached_to = ""
end
local best = 1e15
-- find initial moving direction by searching through 4 nearby possibly positions
self.vec = {x = 1, z = 0}
for dx = -1,1 do
for dz = -1,1 do
if (dx * dz == 0) and (dx ~= 0 or dz ~= 0) then
local dst = dist(playerpos, {x = selfpos.x + dx, z = selfpos.z + dz})
if dst < best
and (is_rail({x = selfpos.x - dx, y = selfpos.y, z = selfpos.z - dz})
or is_rail({x = selfpos.x - dx, y = selfpos.y + 1, z = selfpos.z - dz})
or is_rail({x = selfpos.x - dx, y = selfpos.y - 1, z = selfpos.z - dz})) then
best = dst
self.vec = {x = -dx, z = -dz}
end
end
end
end
else
self.stopnow = true
end
end