Is there an easy way to check whether there's a wagon at <pos>?
I'm currently looking to make the freight tracks more into a loading
ramp than (un)loading the entire train at once.
My current plan is an ABM/nodetimer/globalstep that raycasts to 1m above
the track to check for pointed_thing.type=="entity", getting the wagon
id and subsequent detatched inventory from the entity's id field.
After (un)loading the wagon, the
:set_textures(advtrains.wagons[wagon_id]) method would be called to
automagically update the model/texture on a per-wagon basis.
Of course this would be very laggy, so checking
advtrains.is_node_loaded(pos) would return functionality to the current
method of (un)loading if the area isn't loaded.
I know there's advtrains.get_train_at_pos(pos) but I need a little more
granularity for this than the entire train...
Example function:
function advtrains.get_wagon_at_pos(pos)
if wagon_at_pos then return wagon_id end
return nil
end
Just a thought :)
> Is there an easy way to check whether there's a wagon at <pos>?
You can check for the trains at a position using
advtrains.occ.get_trains_at(pos). The returned value is in the form of
{[id] = path_index}, so you can probably find the specific wagon by
iterating through train.trainparts until you find the wagon whose offset
(range) includes the particular index. Something along the lines of:
function get_wagon_at(pos)
local t = {}
for id, idx in pairs(advtrains.occ.get_trains_at(pos)) do
local bp, p
for _, wid in ipairs(advtrains.trains[id].trainparts) do
local w = advtrains.wagons[wid]
local wp = advtrains.wagon_prototypes[w.type]
p, bp = bp, bp+wp.wagon_span
if idx <= bp then
t[wid] = idx-p
break
end
end
end
return t
end
(Note: I have not yet tested the above code.)
[PATCH] Add API to get wagons at a specific position
---
advtrains/occupation.lua | 14 ++++++++++++++advtrains/trainlogic.lua | 17 +++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/advtrains/occupation.lua b/advtrains/occupation.lua
index db39991..18e3f2b 100644
--- a/advtrains/occupation.lua+++ b/advtrains/occupation.lua
@@ -186,6 +186,20 @@ function o.get_trains_at(ppos)
return r
end
+-- Gets a mapping of wagon id's to offsets of wagons that stand or drive over;+-- the offset is relative to the center of the wagon+-- returns (table with wagon_id->offset)+function o.get_wagons_at(pos)+ local r = {}+ for id, idx in pairs(o.get_trains_at(pos)) do+ local w, offset = advtrains.get_wagon_at_index(id, idx)+ if w then+ r[w.id] = offset+ end+ end+ return r+end+-- Gets a mapping of train id's to indexes of trains that have a path
-- generated over this node
-- returns (table with train_id->index)
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua
index 288e224..186a7ff 100644
--- a/advtrains/trainlogic.lua+++ b/advtrains/trainlogic.lua
@@ -1238,6 +1238,23 @@ function advtrains.get_train_at_pos(pos)
end
end
+function advtrains.get_wagon_at_index(train, index)+ if train == nil then+ return+ elseif type(train) ~= "table" then+ return advtrains.get_wagon_at_index(advtrains.trains[train], index)+ end+ local offset = train.index - index+ local p0, p1 = 0, 0+ for _, wid in ipairs(train.trainparts) do+ local wagon = advtrains.wagons[wid]+ local wp = advtrains.wagon_prototypes[wagon.type] or advtrains.wagon_prototypes["advtrains:wagon_placeholder"]+ p0, p1 = p1, p1+2*wp.wagon_span+ if offset <= p1 then+ return wagon, wagon.pos_in_train - offset+ end+ end+end-- ehm... I never adapted this function to the new path system ?!
function advtrains.invalidate_all_paths(pos)
--
2.40.1
Hi,
yes, generally this is the right way to do. However you need to be
careful because the index does not necessarily match the real position
(an index of 1 can be a distance greater than 1)
Since I have some time today, I added such a function in 283efc4. You
should be able to use it right away.
Regards,
orwell
Hi again,
Just noticed you added a patch here an hour ago... Which means we were
working in parallel.
My remark still holds though, and I believe my implementation is
correct.
Regards,
orwell
> Just noticed you added a patch here an hour ago... Which means we were> working in parallel.> > My remark still holds though, and I believe my implementation is> correct.
Agreed. I put together that patch based on reading some existing code
and my (limited) knowledge of the path system.
Anyway, I wrote that function as an auxiliary function for
occ.get_wagon_at(pos) since Maverick2797 wanted to get the wagon at a
speicific position; the idea is to use occ.get_trains_at(pos) and remap
the returned table to wagons (instead of trains).
A function to return a _single_ wagon at the position should IMO not be
necessary as a occ.get_trains_at(pos)-like function would allow you to
get it using next(occ.get_wagons_at(pos)).