aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--couple.lua120
-rw-r--r--helpers.lua27
-rw-r--r--init.lua3
-rw-r--r--textures/advtrains_couple.pngbin0 -> 265 bytes
-rw-r--r--textures/advtrains_discouple.pngbin0 -> 307 bytes
-rw-r--r--textures/couple.png1
-rw-r--r--trainlogic.lua111
-rw-r--r--wagons.lua2
8 files changed, 235 insertions, 29 deletions
diff --git a/couple.lua b/couple.lua
new file mode 100644
index 0000000..4b9b4d7
--- /dev/null
+++ b/couple.lua
@@ -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,
+})
diff --git a/helpers.lua b/helpers.lua
index 2c87e1e..737d15b 100644
--- a/helpers.lua
+++ b/helpers.lua
@@ -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 \ No newline at end of file
diff --git a/init.lua b/init.lua
index 48a42d3..5811b4e 100644
--- a/init.lua
+++ b/init.lua
@@ -18,4 +18,5 @@ dofile(advtrains.modpath.."/trackplacer.lua")
dofile(advtrains.modpath.."/tracks.lua")
dofile(advtrains.modpath.."/wagons.lua")
-dofile(advtrains.modpath.."/pseudoload.lua"); \ No newline at end of file
+dofile(advtrains.modpath.."/pseudoload.lua");
+dofile(advtrains.modpath.."/couple.lua"); \ No newline at end of file
diff --git a/textures/advtrains_couple.png b/textures/advtrains_couple.png
new file mode 100644
index 0000000..9e997e4
--- /dev/null
+++ b/textures/advtrains_couple.png
Binary files differ
diff --git a/textures/advtrains_discouple.png b/textures/advtrains_discouple.png
new file mode 100644
index 0000000..b27c4fb
--- /dev/null
+++ b/textures/advtrains_discouple.png
Binary files differ
diff --git a/textures/couple.png b/textures/couple.png
new file mode 100644
index 0000000..8d1c8b6
--- /dev/null
+++ b/textures/couple.png
@@ -0,0 +1 @@
+
diff --git a/trainlogic.lua b/trainlogic.lua
index 6bd8310..e226eab 100644
--- a/trainlogic.lua
+++ b/trainlogic.lua
@@ -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
diff --git a/wagons.lua b/wagons.lua
index 7dee4b1..5140dc2 100644
--- a/wagons.lua
+++ b/wagons.lua
@@ -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)