From 2a719d941a60bc2602e246a2c4cbb50fb4c5925b Mon Sep 17 00:00:00 2001 From: orwell96 Date: Tue, 31 May 2016 23:13:08 +0200 Subject: added couple entity, removed debug outputs and fixed code --- couple.lua | 120 +++++++++++++++++++++++++++++++++++++++ helpers.lua | 27 +++++++-- init.lua | 3 +- textures/advtrains_couple.png | Bin 0 -> 265 bytes textures/advtrains_discouple.png | Bin 0 -> 307 bytes textures/couple.png | 1 + trainlogic.lua | 111 +++++++++++++++++++++++++++++------- wagons.lua | 2 +- 8 files changed, 235 insertions(+), 29 deletions(-) create mode 100644 couple.lua create mode 100644 textures/advtrains_couple.png create mode 100644 textures/advtrains_discouple.png create mode 100644 textures/couple.png 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 Binary files /dev/null and b/textures/advtrains_couple.png differ diff --git a/textures/advtrains_discouple.png b/textures/advtrains_discouple.png new file mode 100644 index 0000000..b27c4fb Binary files /dev/null and b/textures/advtrains_discouple.png 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) -- cgit v1.2.3