added couple entity, removed debug outputs and fixed code

master
orwell96 2016-05-31 23:13:08 +02:00
parent e8c9d6eb66
commit 2a719d941a
8 changed files with 235 additions and 29 deletions

120
couple.lua Normal file
View File

@ -0,0 +1,120 @@
--couple.lua
--defines couple entities.
--advtrains:discouple
--set into existing trains to split them when punched.
--they are attached to the wagons.
--[[fields
wagon_id
wagons keep their couple entity minetest-internal id inside the field discouple_id. if it refers to nowhere, they will spawn a new one if player is near
]]
local print=function(t, ...) minetest.log("action", table.concat({t, ...}, " ")) minetest.chat_send_all(table.concat({t, ...}, " ")) end
minetest.register_entity("advtrains:discouple", {
visual="sprite",
textures = {"advtrains_discouple.png"},
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual_size = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
is_discouple=true,
on_activate=function(self, staticdata)
if staticdata=="DISCOUPLE" then
--couple entities have no right to exist further...
self.object:remove()
return
end
end,
get_staticdata=function() return "DISCOUPLE" end,
on_punch=function()
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.unique_id==self.wagon_id then
advtrains.split_train_at_wagon(wagon)--found in trainlogic.lua
end
end
end
})
--advtrains:couple
--when two trains overlap with their end-positions, this entity will be spawned and both trains set its id into appropiate fields for them to know when to free them again. The entity will destroy automatically when it recognizes that any of the trains left the common position.
--[[fields
train_id_1
train_id_2
train1_is_backpos
train2_is_backpos
]]
minetest.register_entity("advtrains:couple", {
visual="sprite",
textures = {"advtrains_couple.png"},
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual_size = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
is_couple=true,
on_activate=function(self, staticdata)
if staticdata=="COUPLE" then
--couple entities have no right to exist further...
self.object:remove()
return
end
end,
get_staticdata=function(self) return "COUPLE" end,
on_rightclick=function(self)
if not self.train_id_1 or not self.train_id_2 then return end
local id1, id2=self.train_id_1, self.train_id_2
if self.train1_is_backpos and not self.train2_is_backpos then
advtrains.do_connect_trains(id1, id2)
--case 2 (second train is front)
elseif self.train2_is_backpos and not self.train1_is_backpos then
advtrains.do_connect_trains(id2, id1)
--case 3
elseif self.train1_is_backpos and self.train2_is_backpos then
advtrains.invert_train(id2)
advtrains.do_connect_trains(id1, id2)
--case 4
elseif not self.train1_is_backpos and not self.train2_is_backpos then
advtrains.invert_train(id1)
advtrains.do_connect_trains(id1, id2)
end
self.object:remove()
end,
on_step=function(self, dtime)
if not self.train_id_1 or not self.train_id_2 then print("wtf no train ids?")return end
local train1=advtrains.trains[self.train_id_1]
local train2=advtrains.trains[self.train_id_2]
if not train1 or not train2 or not train1.path or not train2.path or not train1.index or not train2.index then
self.object:remove()
return
end
local tp1
if not self.train1_is_backpos then
tp1=advtrains.get_real_index_position(train1.path, train1.index)
else
tp1=advtrains.get_real_index_position(train1.path, train1.index-(train1.trainlen or 2))
end
local tp2
if not self.train2_is_backpos then
tp2=advtrains.get_real_index_position(train2.path, train2.index)
else
tp2=advtrains.get_real_index_position(train2.path, train2.index-(train2.trainlen or 2))
end
local function nilsave_pts(pos) return pos and minetest.pos_to_string(pos) or "nil" end
if not tp1 or not tp2 or not (vector.distance(tp1,tp2)<0.5) then
self.object:remove()
return
else
local pos_median=advtrains.pos_median(tp1, tp2)
if not vector.equals(pos_median, self.object:getpos()) then
self.object:setpos(pos_median)
end
end
end,
})

View File

@ -103,7 +103,7 @@ function advtrains.conway(midreal, prev, traintype)--in order prev,mid,return
--print("[advtrains]dir applied next pos: "..(next and minetest.pos_to_string(next) or "nil").."(chkdir is "..(chkdir or "nil")..", y-offset "..y_offset..")")
--is there a next
if not next then
print("[advtrains]in conway: no next rail(nil), returning!")
--print("[advtrains]in conway: no next rail(nil), returning!")
return nil
end
@ -111,30 +111,30 @@ function advtrains.conway(midreal, prev, traintype)--in order prev,mid,return
--is it a rail?
if(not nextnode_ok) then
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
--print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
next.y=next.y-1
y_offset=y_offset-1
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(next), traintype)
if(not nextnode_ok) then
print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
--print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
return nil
end
end
--is this next rail connecting to the mid?
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely-y_offset) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely-y_offset) ) then
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not connecting, trying one node below!")
--print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not connecting, trying one node below!")
next.y=next.y-1
y_offset=y_offset-1
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(next), traintype)
if(not nextnode_ok) then
print("[advtrains]in conway: (at connecting if check again) one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
--print("[advtrains]in conway: (at connecting if check again) one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
return nil
end
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely) ) then
print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." rail not connecting, returning!")
--print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." rail not connecting, returning!")
--print("[advtrains] in order mid1,2,next1,2,chkdir "..middir1.." "..middir2.." "..nextdir1.." "..nextdir2.." "..chkdir)
return nil
end
@ -205,3 +205,18 @@ function advtrains.get_wagon_yaw(front, first, second, back, pct)
--print("y "..(y1*360/(2*math.pi)).." "..(y2*360/(2*math.pi)))
return y1+advtrains.minAngleDiffRad(y1, y2)*pct
end
function advtrains.get_real_index_position(path, index)
if not path or not index then return end
local first_pos=path[math.floor(index)]
local second_pos=path[math.floor(index)+1]
if not first_pos or not second_pos then return nil end
local factor=index-math.floor(index)
local actual_pos={x=first_pos.x-(first_pos.x-second_pos.x)*factor, y=first_pos.y-(first_pos.y-second_pos.y)*factor, z=first_pos.z-(first_pos.z-second_pos.z)*factor,}
return actual_pos
end
function advtrains.pos_median(pos1, pos2)
return {x=pos1.x-(pos1.x-pos2.x)*0.5, y=pos1.y-(pos1.y-pos2.y)*0.5, z=pos1.z-(pos1.z-pos2.z)*0.5}
end

View File

@ -18,4 +18,5 @@ dofile(advtrains.modpath.."/trackplacer.lua")
dofile(advtrains.modpath.."/tracks.lua")
dofile(advtrains.modpath.."/wagons.lua")
dofile(advtrains.modpath.."/pseudoload.lua");
dofile(advtrains.modpath.."/pseudoload.lua");
dofile(advtrains.modpath.."/couple.lua");

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

1
textures/couple.png Normal file
View File

@ -0,0 +1 @@

View File

@ -1,7 +1,7 @@
--trainlogic.lua
--controls train entities stuff about connecting/disconnecting/colliding trains and other things
local print=function(t) minetest.log("action", t) minetest.chat_send_all(t) end
local print=function(t, ...) minetest.log("action", table.concat({t, ...}, " ")) minetest.chat_send_all(table.concat({t, ...}, " ")) end
advtrains.train_accel_force=5--per second and divided by number of wagons
advtrains.train_brake_force=3--per second, not divided by number of wagons
@ -122,6 +122,11 @@ function advtrains.train_step(id, train, dtime)
--TODO check for all vars to be present
--very unimportant thing: check if couple is here
if train.couple_eid_front and (not minetest.luaentities[train.couple_eid_front] or not minetest.luaentities[train.couple_eid_front].is_couple) then train.couple_eid_front=nil end
if train.couple_eid_back and (not minetest.luaentities[train.couple_eid_back] or not minetest.luaentities[train.couple_eid_back].is_couple) then train.couple_eid_back=nil end
--if not train.last_pos then advtrains.trains[id]=nil return end
if not advtrains.pathpredict(id, train) then
@ -372,7 +377,7 @@ function advtrains.pathpredict(id, train)
else
--do as if nothing has happened and preceed with path
--but do not update max_index_on_track
print("over-generating path max to index "..maxn+1)
--print("over-generating path max to index "..maxn+1)
train.path[maxn+1]=vector.add(train.path[maxn], vector.subtract(train.path[maxn], train.path[maxn-1]))
end
train.path_dist[maxn]=vector.distance(train.path[maxn+1], train.path[maxn])
@ -389,7 +394,7 @@ function advtrains.pathpredict(id, train)
else
--do as if nothing has happened and preceed with path
--but do not update min_index_on_track
print("over-generating path min to index "..minn-1)
--print("over-generating path min to index "..minn-1)
train.path[minn-1]=vector.add(train.path[minn], vector.subtract(train.path[minn], train.path[minn+1]))
end
train.path_dist[minn-1]=vector.distance(train.path[minn], train.path[minn-1])
@ -419,7 +424,6 @@ end
function advtrains.get_or_create_path(id, train)
if not train.path then return advtrains.pathpredict(id, train) end
return train.path
end
@ -530,29 +534,94 @@ function advtrains.try_connect_trains(id1, id2)
end
if #train1.trainparts==0 or #train2.trainparts==0 then return end
local frontpos1=train1.path[math.floor(train1.index+0.5)]
local backpos1=train1.path[math.floor(train1.index-(train1.trainlen or 2)+0.5)]
local frontpos2=train2.path[math.floor(train2.index+0.5)]
local backpos2=train2.path[math.floor(train2.index-(train1.trainlen or 2)+0.5)]
local frontpos1=advtrains.get_real_index_position(train1.path, train1.index)
local backpos1=advtrains.get_real_index_position(train1.path, train1.index-(train1.trainlen or 2))
local frontpos2=advtrains.get_real_index_position(train2.path, train2.index)
local backpos2=advtrains.get_real_index_position(train2.path, train2.index-(train2.trainlen or 2))
if not frontpos1 or not frontpos2 or not backpos1 or not backpos2 then return end
--case 1 (first train is front)
if vector.equals(frontpos2, backpos1) then
advtrains.do_connect_trains(id1, id2)
--case 2 (second train is front)
elseif vector.equals(frontpos1, backpos2) then
advtrains.do_connect_trains(id2, id1)
--case 3
elseif vector.equals(backpos2, backpos1) then
advtrains.invert_train(id2)
advtrains.do_connect_trains(id1, id2)
--case 4
elseif vector.equals(frontpos2, frontpos1) then
advtrains.invert_train(id1)
advtrains.do_connect_trains(id1, id2)
if vector.distance(frontpos2, backpos1)<0.5 then
advtrains.spawn_couple_if_neccessary(backpos1, frontpos2, id1, id2, true, false)
--case 2 (second train is front)
elseif vector.distance(frontpos1, backpos2)<0.5 then
advtrains.spawn_couple_if_neccessary(backpos2, frontpos1, id2, id1, true, false)
--case 3
elseif vector.distance(backpos2, backpos1)<0.5 then
advtrains.spawn_couple_if_neccessary(backpos1, backpos2, id1, id2, true, true)
--case 4
elseif vector.distance(frontpos2, frontpos1)<0.5 then
advtrains.spawn_couple_if_neccessary(frontpos1, frontpos2, id1, id2, false, false)
end
end
--order of trains may be irrelevant in some cases. check opposite cases. TODO does this work?
--pos1 and pos2 are just needed to form a median.
function advtrains.spawn_couple_if_neccessary(pos1, pos2, tid1, tid2, train1_is_backpos, train2_is_backpos)
--print("spawn_couple_if_neccessary..."..dump({pos1=pos1, pos2=pos2, train1_is_backpos=train1_is_backpos, train2_is_backpos=train2_is_backpos}))
local train1=advtrains.trains[tid1]
local train2=advtrains.trains[tid2]
local t1_has_couple
if train1_is_backpos then
t1_has_couple=train1.couple_eid_back
else
t1_has_couple=train1.couple_eid_front
end
local t2_has_couple
if train2_is_backpos then
t2_has_couple=train2.couple_eid_back
else
t2_has_couple=train2.couple_eid_front
end
if t1_has_couple and t2_has_couple then
if t1_has_couple~=t2_has_couple then--what the hell
if minetest.object_refs[t2_has_couple] then minetest.object_refs[t2_has_couple]:remove() end
if train2_is_backpos then
train2.couple_eid_back=t1_has_couple
else
train2.couple_eid_front=t1_has_couple
end
end
--[[elseif t1_has_couple and not t2_has_couple then
if train2_is_backpos then
train2.couple_eid_back=t1_has_couple
else
train2.couple_eid_front=t1_has_couple
end
elseif not t1_has_couple and t2_has_couple then
if train1_is_backpos then
train1.couple_eid_back=t2_has_couple
else
train1.couple_eid_front=t2_has_couple
end]]
else
local pos=advtrains.pos_median(pos1, pos2)
local obj=minetest.add_entity(pos, "advtrains:couple")
if not obj then print("failed creating object") return end
local le=obj:get_luaentity()
le.train_id_1=tid1
le.train_id_2=tid2
le.train1_is_backpos=train1_is_backpos
le.train2_is_backpos=train2_is_backpos
--find in object_refs
for aoi, compare in pairs(minetest.object_refs) do
if compare==obj then
if train1_is_backpos then
train1.couple_eid_back=aoi
else
train1.couple_eid_front=aoi
end
if train2_is_backpos then
train2.couple_eid_back=aoi
else
train2.couple_eid_front=aoi
end
end
end
end
end
function advtrains.do_connect_trains(first_id, second_id)
local first_wagoncnt=#advtrains.trains[first_id].trainparts
local second_wagoncnt=#advtrains.trains[second_id].trainparts

View File

@ -53,7 +53,7 @@ function wagon:train()
end
function wagon:on_activate(staticdata, dtime_s)
print("[advtrains][wagon "..(self.unique_id or "no-id").."] activated")
--print("[advtrains][wagon "..(self.unique_id or "no-id").."] activated")
self.object:set_armor_groups({immortal=1})
if staticdata then
local tmp = minetest.deserialize(staticdata)