diff options
Diffstat (limited to 'advtrains/trainlogic.lua')
-rw-r--r-- | advtrains/trainlogic.lua | 151 |
1 files changed, 110 insertions, 41 deletions
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index 129722a..feb35b5 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -176,29 +176,24 @@ end -- Occupation Callback system -- see occupation.lua -local callbacks_new_path = {} -local callbacks_update = {} - -function advtrains.te_register_on_new_path(func) - assertt(func, "function") - table.insert(callbacks_new_path, func) -end -function advtrains.te_register_on_update(func) - assertt(func, "function") - table.insert(callbacks_update, func) -end - -local function run_callbacks_new_path(id, train) - for _,f in ipairs(callbacks_new_path) do - f(id, train) - end -end -local function run_callbacks_update(id, train) - for _,f in ipairs(callbacks_new_path) do - f(id, train) +local function mkcallback(name) + local callt = {} + advtrains["te_register_on_"..name] = function(func) + assertt(func, "function") + table.insert(callt, func) + end + return callt, function(id, train) + for _,f in ipairs(callt) do + f(id, train) + end end end +local callbacks_new_path, run_callbacks_new_path = mkcallback("new_path") +local callbacks_update, run_callbacks_update = mkcallback("update") +local callbacks_create, run_callbacks_create = mkcallback("create") +local callbacks_remove, run_callbacks_remove = mkcallback("remove") + -- train_ensure_init: responsible for creating a state that we can work on, after one of the following events has happened: -- - the train's path got cleared @@ -385,7 +380,7 @@ function advtrains.train_step_b(id, train, dtime) --- 4. move train --- train.index=train.index and train.index+((train.velocity/(train.path_dist[math.floor(train.index)] or 1))*dtime) or 0 - recalc_end_index() + recalc_end_index(train) end @@ -420,22 +415,21 @@ if train.no_step or train.wait_for_path then return end if train_moves then - local collpos + local collided = false local coll_grace=1 - local collindex = advtrains.path_get_index_by_offset(train, train.index, coll_grace) - collpos = advtrains.path_get(train, atround(collindex)) + local collindex = advtrains.path_get_index_by_offset(train, train.index, -coll_grace) + local collpos = advtrains.path_get(train, atround(collindex)) if collpos then local rcollpos=advtrains.round_vector_floor_y(collpos) for x=-train.extent_h,train.extent_h do for z=-train.extent_h,train.extent_h do local testpos=vector.add(rcollpos, {x=x, y=0, z=z}) --- 8a Check collision --- - if advtrains.occ.check_collision(testpos, id) then + if not collided and advtrains.occ.check_collision(testpos, id) then --collides - --advtrains.collide_and_spawn_couple(id, testpos, advtrains.detector.get(testpos, id), train.movedir==-1) train.velocity = 0 train.tarvelocity = 0 - atwarn("Train",id,"collided!") + collided = true end --- 8b damage players --- if not minetest.settings:get_bool("creative_mode") then @@ -499,7 +493,9 @@ advtrains.te_register_on_new_path(function(id, train) old_index = atround(train.index), old_end_index = atround(train.end_index), } + atdebug(id,"tnc init",train.index,train.end_index) end) + advtrains.te_register_on_update(function(id, train) local new_index = atround(train.index) local new_end_index = atround(train.end_index) @@ -507,14 +503,38 @@ advtrains.te_register_on_update(function(id, train) local old_end_index = train.tnc.old_end_index while old_index < new_index do old_index = old_index + 1 - local pos = advtrains.round_vector_floor_y(advtrains.path_get(old_index)) + local pos = advtrains.round_vector_floor_y(advtrains.path_get(train,old_index)) tnc_call_enter_callback(pos, id) end - while old_end_index > new_end_index do - local pos = advtrains.round_vector_floor_y(advtrains.path_get(old_end_index)) + while old_end_index < new_end_index do + local pos = advtrains.round_vector_floor_y(advtrains.path_get(train,old_end_index)) tnc_call_leave_callback(pos, id) - old_end_index = old_end_index - 1 + old_end_index = old_end_index + 1 end + train.tnc.old_index = new_index + train.tnc.old_end_index = new_end_index +end) + +advtrains.te_register_on_create(function(id, train) + local index = atround(train.index) + local end_index = atround(train.end_index) + while end_index <= index do + local pos = advtrains.round_vector_floor_y(advtrains.path_get(train,end_index)) + tnc_call_enter_callback(pos, id) + end_index = end_index + 1 + end + atdebug(id,"tnc create",train.index,train.end_index) +end) + +advtrains.te_register_on_remove(function(id, train) + local index = atround(train.index) + local end_index = atround(train.end_index) + while end_index <= index do + local pos = advtrains.round_vector_floor_y(advtrains.path_get(train,end_index)) + tnc_call_leave_callback(pos, id) + end_index = end_index + 1 + end + atdebug(id,"tnc remove",train.index,train.end_index) end) -- Calculates the indices where the window borders of the occupation windows are. @@ -572,9 +592,10 @@ function advtrains.create_new_train_at(pos, connid, ioff, trainparts) advtrains.trains[new_id] = t atdebug("Created new train:",t) - advtrains.train_ensure_init(new_id, advtrains.trains[new_id]) + run_callbacks_create(new_id, advtrains.trains[new_id]) + return new_id end @@ -583,9 +604,13 @@ function advtrains.remove_train(id) advtrains.train_ensure_init(id, train) + run_callbacks_remove(id, train) + advtrains.path_invalidate(train) + advtrains.couple_invalidate(train) local tp = train.trainparts + atdebug("Removing train",id,"leftover trainparts:",tp) advtrains.trains[id] = nil @@ -661,6 +686,8 @@ function advtrains.update_trainpart_properties(train_id, invert_flipstate) train.locomotives_in_train = count_l end + +local ablkrng = minetest.settings:get("active_block_range")*16 -- This function checks whether entities need to be spawned for certain wagons, and spawns them. function advtrains.spawn_wagons(train_id) local train = advtrains.trains[train_id] @@ -668,12 +695,23 @@ function advtrains.spawn_wagons(train_id) for i, w_id in ipairs(train.trainparts) do local data = advtrains.wagons[w_id] if data then + if data.train_id ~= train_id then + atwarn("Train",train_id,"Wagon #",1,": Saved train ID",data.train_id,"did not match!") + data.train_id = train_id + end if not data.object or not data.object:getyaw() then -- eventually need to spawn new object. check if position is loaded. local index = advtrains.path_get_index_by_offset(train, train.index, -data.pos_in_train) local pos = advtrains.path_get(train, atfloor(index)) - if minetest.get_node_or_nil(pos) then + local spawn = false + for _,p in pairs(minetest.get_connected_players()) do + if vector.distance(p:get_pos(),pos)<=ablkrng then + spawn = true + end + end + + if spawn then local wt = advtrains.get_wagon_prototype(data) local wagon = minetest.add_entity(pos, wt):get_luaentity() wagon:set_id(w_id) @@ -693,16 +731,15 @@ function advtrains.split_train_at_wagon(wagon_id) advtrains.train_ensure_init(old_id, train) - local index=advtrains.path_get_index_by_offset(train, train.index, -(data.pos_in_train + wagon.wagon_span)) + local index=advtrains.path_get_index_by_offset(train, train.index, - data.pos_in_train + wagon.wagon_span) -- find new initial path position for this train local pos, connid, frac = advtrains.path_getrestore(train, index) - -- build trainparts table, passing it directly to the train constructor local tp = {} for k,v in ipairs(train.trainparts) do - if k>=wagon.pos_in_trainparts then + if k >= data.pos_in_trainparts then table.insert(tp, v) train.trainparts[k]=nil end @@ -728,7 +765,7 @@ function advtrains.split_train_at_wagon(wagon_id) end -- coupling -local CPL_CHK_DST = 1 +local CPL_CHK_DST = -1 local CPL_ZONE = 2 -- train.couple_* contain references to ObjectRefs of couple objects, which contain all relevant information @@ -739,11 +776,24 @@ local function createcouple(pos, train1, t1_is_front, train2, t2_is_front) local le=obj:get_luaentity() le.train_id_1=train1.id le.train_id_2=train2.id - le.train1_is_backpos=not t1_is_front - le.train2_is_backpos=not t2_is_front + le.t1_is_front=t1_is_front + le.t2_is_front=t2_is_front + atdebug("created couple between",train1.id,t1_is_front,train2.id,t2_is_front) + if t1_is_front then + train1.cpl_front = obj + else + train1.cpl_back = obj + end + if t2_is_front then + train2.cpl_front = obj + else + train2.cpl_back = obj + end + end function advtrains.train_check_couples(train) + atdebug("rechecking couples") if train.cpl_front then if not train.cpl_front:getyaw() then -- objectref is no longer valid. reset. @@ -756,6 +806,7 @@ function advtrains.train_check_couples(train) for tid, idx in pairs(front_trains) do local other_train = advtrains.trains[tid] advtrains.train_ensure_init(tid, other_train) + atdebug(train.id,"front: ",idx,"on",tid,atround(other_train.index),atround(other_train.end_index)) if other_train.velocity == 0 then if idx>=other_train.index and idx<=other_train.index + CPL_ZONE then createcouple(pos, train, true, other_train, true) @@ -794,7 +845,17 @@ function advtrains.train_check_couples(train) end end - +function advtrains.couple_invalidate(train) + if train.cpl_back then + train.cpl_back:remove() + train.cpl_back = nil + end + if train.cpl_front then + train.cpl_front:remove() + train.cpl_front = nil + end + train.was_standing = nil +end -- relevant code for this comment is in couple.lua @@ -833,6 +894,9 @@ function advtrains.do_connect_trains(first_id, second_id) first.velocity=0 first.tarvelocity=0 first.couple_lck_back=tmp_cpl_lck + + advtrains.update_trainpart_properties(first_id) + advtrains.couple_invalidate(first) return true end @@ -845,8 +909,12 @@ function advtrains.invert_train(train_id) -- rotate some other stuff train.couple_lck_back, train.couple_lck_front = train.couple_lck_front, train.couple_lck_back + if train.door_open then + train.door_open = - train.door_open + end advtrains.path_invalidate(train) + advtrains.couple_invalidate(train) local old_trainparts=train.trainparts train.trainparts={} @@ -857,7 +925,7 @@ function advtrains.invert_train(train_id) end function advtrains.get_train_at_pos(pos) - return advtrains.detector.get(pos) + return advtrains.occ.get_trains_at(pos)[1] end function advtrains.invalidate_all_paths(pos) @@ -883,6 +951,7 @@ function advtrains.invalidate_path(id) local v=advtrains.trains[id] if not v then return end advtrains.path_invalidate(v) + advtrains.couple_invalidate(v) v.dirty = true end |