Compare commits
5 Commits
5912f778e1
...
3cb21a80dc
Author | SHA1 | Date |
---|---|---|
orwell96 | 3cb21a80dc | |
orwell96 | ef8391a60d | |
Maverick2797 | 78e0c650e3 | |
Maverick2797 | 7db61e9890 | |
Maverick2797 | 23d524df71 |
|
@ -85,6 +85,13 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
|
|||
wagon_span=2,
|
||||
^- How far this wagon extends from its base position. Is the half of the wagon length.
|
||||
^- Used to determine in which distance the other wagons have to be positioned. Will require tweaking.
|
||||
wheel_positions = {1.5, -1.5},
|
||||
^- Optional: if defined, the wagon will be placed so that these 2 wheel positions are on the track
|
||||
^- This parameter is recommended for long wagons (wagon_span >= 2).
|
||||
^- The position is a distance relative to the center of the wagon.
|
||||
^- Must have exactly 2 entries, corresponding to the front (1) and rear (2) wheel of the wagon object. 1st must be greater than 2nd.
|
||||
^- If not provided, the simple 1-position positioning logic will be used (wagon is positioned with the center on the track)
|
||||
|
||||
extent_h = 1,
|
||||
^- Determines the collision box extent in x/z direction. Defaults to 1 (=3x3)
|
||||
^- The actual bounding box size is (extent_h*2)+1, so 0 means 1x1, 1 means 3x3 and 2 means 5x5
|
||||
|
|
|
@ -93,6 +93,7 @@ function atc.train_reset_command(train, keep_tarvel)
|
|||
train.atc_delay=nil
|
||||
train.atc_brake_target=nil
|
||||
train.atc_wait_finish=nil
|
||||
train.atc_wait_autocouple=nil
|
||||
train.atc_arrow=nil
|
||||
if not keep_tarvel then
|
||||
train.tarvelocity=nil
|
||||
|
|
|
@ -413,13 +413,36 @@ function wagon:on_step(dtime)
|
|||
end
|
||||
|
||||
-- Calculate new position, yaw and direction vector
|
||||
-- note: "index" is needed to be the center index, required by door code
|
||||
local index = advtrains.path_get_index_by_offset(train, train.index, -data.pos_in_train)
|
||||
local pos, yaw, npos, npos2 = advtrains.path_get_interpolated(train, index)
|
||||
local vdir = vector.normalize(vector.subtract(npos2, npos))
|
||||
local pos, yaw, npos, npos2, vdir
|
||||
|
||||
-- use new position logic?
|
||||
if self.wheel_positions then
|
||||
-- request two positions, calculate difference and yaw from this
|
||||
-- depending on flipstate, need to invert wheel pos indices -> wheelpos * fct
|
||||
local index1 = advtrains.path_get_index_by_offset(train, index, self.wheel_positions[1] * fct)
|
||||
local index2 = advtrains.path_get_index_by_offset(train, index, self.wheel_positions[2] * fct)
|
||||
local pos1 = advtrains.path_get_interpolated(train, index1)
|
||||
local pos2 = advtrains.path_get_interpolated(train, index2)
|
||||
npos = advtrains.path_get(train, atfloor(index)) -- need npos just for node loaded check
|
||||
-- calculate center of 2 positions and vdir vector
|
||||
pos = advtrains.pos_median(pos1, pos2)
|
||||
if data.wagon_flipped then
|
||||
vdir = vector.normalize(vector.subtract(pos2, pos1))
|
||||
else
|
||||
vdir = vector.normalize(vector.subtract(pos1, pos2))
|
||||
end
|
||||
yaw = math.atan2(-vdir.x, vdir.z)
|
||||
else
|
||||
--old position logic (for small wagons): use center index and just get position
|
||||
pos, yaw, npos, npos2 = advtrains.path_get_interpolated(train, index)
|
||||
vdir = vector.normalize(vector.subtract(npos2, npos))
|
||||
end
|
||||
|
||||
--automatic get_on
|
||||
--needs to know index and path
|
||||
if self.door_entry and train.door_open and train.door_open~=0 and train.velocity==0 then
|
||||
if train.velocity==0 and self.door_entry and train.door_open and train.door_open~=0 then
|
||||
--using the mapping created by the trainlogic globalstep
|
||||
for i, ino in ipairs(self.door_entry) do
|
||||
--fct is the flipstate flag from door animation above
|
||||
|
@ -470,29 +493,34 @@ function wagon:on_step(dtime)
|
|||
end
|
||||
end
|
||||
|
||||
--DisCouple
|
||||
-- Spawn discouple object when train stands, in all other cases remove it.
|
||||
-- FIX: Need to do this after the yaw calculation
|
||||
if is_in_loaded_area and data.pos_in_trainparts and data.pos_in_trainparts>1 then
|
||||
if train.velocity==0 then
|
||||
if not self.discouple or not self.discouple.object:get_yaw() then
|
||||
atprint(self.id,"trying to spawn discouple")
|
||||
local dcpl_pos = vector.add(pos, {y=0, x=-math.sin(yaw)*self.wagon_span, z=math.cos(yaw)*self.wagon_span})
|
||||
local object=minetest.add_entity(dcpl_pos, "advtrains:discouple")
|
||||
if object then
|
||||
local le=object:get_luaentity()
|
||||
le.wagon=self
|
||||
--box is hidden when attached, so unuseful.
|
||||
--object:set_attach(self.object, "", {x=0, y=0, z=self.wagon_span*10}, {x=0, y=0, z=0})
|
||||
self.discouple=le
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.discouple and self.discouple.object:get_yaw() then
|
||||
self.discouple.object:remove()
|
||||
atprint(self.id," removing discouple")
|
||||
if train.velocity==0 and is_in_loaded_area and data.pos_in_trainparts and data.pos_in_trainparts>1 then
|
||||
if not self.discouple or not self.discouple.object:get_yaw() then
|
||||
atprint(self.id,"trying to spawn discouple")
|
||||
local dcpl_pos = vector.add(pos, {y=0, x=-math.sin(yaw)*self.wagon_span, z=math.cos(yaw)*self.wagon_span})
|
||||
local object=minetest.add_entity(dcpl_pos, "advtrains:discouple")
|
||||
if object then
|
||||
local le=object:get_luaentity()
|
||||
le.wagon=self
|
||||
--box is hidden when attached, so unuseful.
|
||||
--object:set_attach(self.object, "", {x=0, y=0, z=self.wagon_span*10}, {x=0, y=0, z=0})
|
||||
self.discouple=le
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.discouple and self.discouple.object:get_yaw() then
|
||||
self.discouple.object:remove()
|
||||
atprint(self.id," removing discouple")
|
||||
end
|
||||
end
|
||||
|
||||
-- object yaw (corrected by flipstate)
|
||||
local oyaw = yaw
|
||||
if data.wagon_flipped then
|
||||
oyaw = yaw + math.pi
|
||||
end
|
||||
train.debug = "yaw "..yaw.." oyaw "..oyaw.." flip "..(data.wagon_flipped and "yes" or "no")
|
||||
|
||||
--FIX: use index of the wagon, not of the train.
|
||||
local velocity = train.velocity * advtrains.global_slowdown
|
||||
|
@ -500,10 +528,6 @@ function wagon:on_step(dtime)
|
|||
local velocityvec = vector.multiply(vdir, velocity)
|
||||
local accelerationvec = vector.multiply(vdir, acceleration)
|
||||
|
||||
if data.wagon_flipped then
|
||||
yaw=yaw+math.pi
|
||||
end
|
||||
|
||||
-- this timer runs off every 2 seconds.
|
||||
self.updatepct_timer=(self.updatepct_timer or 0)-dtime
|
||||
local updatepct_timer_elapsed = self.updatepct_timer<=0
|
||||
|
@ -540,19 +564,19 @@ function wagon:on_step(dtime)
|
|||
or not vector.equals(velocityvec, self.old_velocity_vector)
|
||||
or not self.old_acceleration_vector
|
||||
or not vector.equals(accelerationvec, self.old_acceleration_vector)
|
||||
or self.old_yaw~=yaw
|
||||
or self.old_yaw~=oyaw
|
||||
or updatepct_timer_elapsed then--only send update packet if something changed
|
||||
|
||||
self.object:set_pos(pos)
|
||||
self.object:set_velocity(velocityvec)
|
||||
self.object:set_acceleration(accelerationvec)
|
||||
|
||||
if #self.seats > 0 and self.old_yaw ~= yaw then
|
||||
if #self.seats > 0 and self.old_yaw ~= oyaw then
|
||||
if not self.player_yaw then
|
||||
self.player_yaw = {}
|
||||
end
|
||||
if not self.old_yaw then
|
||||
self.old_yaw=yaw
|
||||
self.old_yaw=oyaw
|
||||
end
|
||||
for _,name in pairs(data.seatp) do
|
||||
local p = minetest.get_player_by_name(name)
|
||||
|
@ -562,11 +586,11 @@ function wagon:on_step(dtime)
|
|||
self.player_yaw[name] = p:get_look_horizontal()-self.old_yaw
|
||||
end
|
||||
-- set player looking direction using calculated offset
|
||||
p:set_look_horizontal((self.player_yaw[name] or 0)+yaw)
|
||||
p:set_look_horizontal((self.player_yaw[name] or 0)+oyaw)
|
||||
end
|
||||
end
|
||||
self.turning = true
|
||||
elseif self.old_yaw == yaw then
|
||||
elseif self.old_yaw == oyaw then
|
||||
-- train is no longer turning
|
||||
self.turning = false
|
||||
end
|
||||
|
@ -576,9 +600,9 @@ function wagon:on_step(dtime)
|
|||
if data.wagon_flipped then
|
||||
pitch = -pitch
|
||||
end
|
||||
self.object:set_rotation({x=pitch, y=yaw, z=0})
|
||||
self.object:set_rotation({x=pitch, y=oyaw, z=0})
|
||||
else
|
||||
self.object:set_yaw(yaw)
|
||||
self.object:set_yaw(oyaw)
|
||||
end
|
||||
|
||||
if self.update_animation then
|
||||
|
@ -597,7 +621,7 @@ function wagon:on_step(dtime)
|
|||
self.old_velocity_vector=velocityvec
|
||||
self.old_velocity = train.velocity
|
||||
self.old_acceleration_vector=accelerationvec
|
||||
self.old_yaw=yaw
|
||||
self.old_yaw=oyaw
|
||||
atprintbm("wagon step", t)
|
||||
end
|
||||
|
||||
|
@ -1316,14 +1340,23 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
|
|||
minetest.register_entity(":"..sysname,prototype)
|
||||
advtrains.wagon_prototypes[sysname] = prototype
|
||||
|
||||
--group classification to make recipe searching easier
|
||||
local wagon_groups = { not_in_creative_inventory = nincreative and 1 or 0}
|
||||
if prototype.is_locomotive then wagon_groups['at_loco'] = 1 end
|
||||
if prototype.seat_groups then
|
||||
if prototype.seat_groups.dstand then wagon_groups['at_control'] = 1 end
|
||||
if prototype.seat_groups.pass then wagon_groups['at_pax'] = 1 end
|
||||
end
|
||||
if prototype.has_inventory then wagon_groups['at_freight'] = 1 end
|
||||
|
||||
minetest.register_craftitem(":"..sysname, {
|
||||
description = desc,
|
||||
inventory_image = inv_img,
|
||||
wield_image = inv_img,
|
||||
stack_max = 1,
|
||||
|
||||
groups = { not_in_creative_inventory = nincreative and 1 or 0},
|
||||
|
||||
groups = wagon_groups,
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if not pointed_thing.type == "node" then
|
||||
return
|
||||
|
|
|
@ -314,13 +314,16 @@ Deprecated:
|
|||
|
||||
|
||||
#### Interlocking
|
||||
This additional function is available when advtrains_interlocking is enabled:
|
||||
These additional functions are available when advtrains_interlocking is enabled:
|
||||
|
||||
- `atc_set_ars_disable(boolean)`
|
||||
Disables (true) or enables (false) the use of ARS for this train. The train will not trigger ARS (automatic route setting) on signals then.
|
||||
|
||||
Note: If you want to disable ARS from an approach callback, the call to `atc_set_ars_disable(true)` *must* happen during the approach callback, and may not be deferred to an interrupt(). Else the train might trigger an ARS before the interrupt fires.
|
||||
|
||||
- `section_occupancy(section_id)`
|
||||
Returns a table of train ids for the specified section, nil if no section id is provided, false if the section id is invalid, an empty table if the section id is valid but empty of trains.
|
||||
|
||||
#### Approach callbacks
|
||||
The LuaATC interface provides a way to hook into the approach callback system, which is for example used in the TSR rails (provided by advtrains_interlocking) or the station tracks (provided by advtrains_lines). However, for compatibility reasons, this behavior needs to be explicitly enabled.
|
||||
|
||||
|
|
|
@ -130,9 +130,8 @@ function r.fire_event(pos, evtdata, appr_internal)
|
|||
get_rc = function()
|
||||
return train.routingcode
|
||||
end,
|
||||
atc_reset = function(cmd)
|
||||
atc_reset = function()
|
||||
if not train_id then return false end
|
||||
assertt(cmd, "string")
|
||||
advtrains.atc.train_reset_command(train)
|
||||
return true
|
||||
end,
|
||||
|
|
|
@ -223,6 +223,18 @@ if advtrains.interlocking then
|
|||
local pos = atlatc.pcnaming.resolve_pos(signal)
|
||||
return advtrains.interlocking.signal_set_aspect(pos)
|
||||
end
|
||||
|
||||
--section_occupancy()
|
||||
static_env.section_occupancy = function(ts_id)
|
||||
if not ts_id then return nil end
|
||||
ts_id = tostring(ts_id)
|
||||
local response = advtrains.interlocking.db.get_ts(ts_id)
|
||||
if response == nil then
|
||||
return false
|
||||
else
|
||||
return response.trains
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Lines-specific:
|
||||
|
|
|
@ -216,39 +216,95 @@ local function get_far_node(pos)
|
|||
return node
|
||||
end
|
||||
|
||||
|
||||
local function show_fc_formspec(pos,player)
|
||||
local pname = player:get_player_name()
|
||||
if minetest.is_protected(pos,pname) then
|
||||
minetest.chat_send_player(pname, "Position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local fc = meta:get_string("fc") or ""
|
||||
|
||||
local form = 'formspec_version[4]'..
|
||||
'size[10,5]'..
|
||||
'label[0.5,0.4;Advtrains Loading/Unloading Track]'..
|
||||
'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'..
|
||||
'label[0.5,1.6;A blank field matches all wagons (default)]'..
|
||||
'label[0.5,2.1;Use code # to disable the track section]'..
|
||||
'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'..
|
||||
'button[6.5,3;3,1;save;Submit]'
|
||||
minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form)
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
local pe = string.match(formname, "^at_load_unload_(............)$")
|
||||
local pos = advtrains.decode_pos(pe)
|
||||
if pos then
|
||||
if minetest.is_protected(pos, pname) then
|
||||
minetest.chat_send_player(pname, "Position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
if fields.save then
|
||||
minetest.get_meta(pos):set_string("fc",tostring(fields.fc))
|
||||
minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc))
|
||||
show_fc_formspec(pos,player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local function train_load(pos, train_id, unload)
|
||||
local train=advtrains.trains[train_id]
|
||||
local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
|
||||
if not string.match(below.name, "chest") then
|
||||
atprint("this is not a chest! at "..minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
|
||||
if inv and train.velocity < 2 then
|
||||
for k, v in ipairs(train.trainparts) do
|
||||
|
||||
local train=advtrains.trains[train_id]
|
||||
local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
|
||||
if not string.match(below.name, "chest") then
|
||||
atprint("this is not a chest! at "..minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
local node_fc = minetest.get_meta(pos):get_string("fc") or ""
|
||||
if node_fc == "#" then
|
||||
--track section is disabled
|
||||
return
|
||||
end
|
||||
|
||||
local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
|
||||
if inv and train.velocity < 2 then
|
||||
for k, v in ipairs(train.trainparts) do
|
||||
local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v})
|
||||
if i and i:get_list("box") then
|
||||
if not unload then
|
||||
for _, item in ipairs(inv:get_list("main")) do
|
||||
if i:get_list("box") and i:room_for_item("box", item) then
|
||||
i:add_item("box", item)
|
||||
inv:remove_item("main", item)
|
||||
|
||||
local wagon_data = advtrains.wagons[v]
|
||||
local wagon_fc
|
||||
if wagon_data.fc then
|
||||
if not wagon_data.fcind then wagon_data.fcind = 1 end
|
||||
wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or ""
|
||||
end
|
||||
|
||||
if node_fc == "" or wagon_fc == node_fc then
|
||||
if not unload then
|
||||
for _, item in ipairs(inv:get_list("main")) do
|
||||
if i:get_list("box") and i:room_for_item("box", item) then
|
||||
i:add_item("box", item)
|
||||
inv:remove_item("main", item)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, item in ipairs(i:get_list("box")) do
|
||||
if inv:get_list("main") and inv:room_for_item("main", item) then
|
||||
i:remove_item("box", item)
|
||||
inv:add_item("main", item)
|
||||
else
|
||||
for _, item in ipairs(i:get_list("box")) do
|
||||
if inv:get_list("main") and inv:room_for_item("main", item) then
|
||||
i:remove_item("box", item)
|
||||
inv:add_item("main", item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -262,15 +318,18 @@ advtrains.register_tracks("default", {
|
|||
formats={},
|
||||
get_additional_definiton = function(def, preset, suffix, rotation)
|
||||
return {
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.ndb.clear(pos)
|
||||
end,
|
||||
advtrains = {
|
||||
on_train_enter = function(pos, train_id)
|
||||
train_load(pos, train_id, true)
|
||||
end,
|
||||
},
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.ndb.clear(pos)
|
||||
end,
|
||||
on_rightclick = function(pos, node, player)
|
||||
show_fc_formspec(pos, player)
|
||||
end,
|
||||
advtrains = {
|
||||
on_train_enter = function(pos, train_id)
|
||||
train_load(pos, train_id, true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
end
|
||||
}, advtrains.trackpresets.t_30deg_straightonly)
|
||||
|
@ -284,16 +343,18 @@ advtrains.register_tracks("default", {
|
|||
formats={},
|
||||
get_additional_definiton = function(def, preset, suffix, rotation)
|
||||
return {
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.ndb.clear(pos)
|
||||
end,
|
||||
|
||||
advtrains = {
|
||||
on_train_enter = function(pos, train_id)
|
||||
train_load(pos, train_id, false)
|
||||
end,
|
||||
},
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.ndb.clear(pos)
|
||||
end,
|
||||
on_rightclick = function(pos, node, player)
|
||||
show_fc_formspec(pos, player)
|
||||
end,
|
||||
advtrains = {
|
||||
on_train_enter = function(pos, train_id)
|
||||
train_load(pos, train_id, false)
|
||||
end,
|
||||
},
|
||||
}
|
||||
end
|
||||
}, advtrains.trackpresets.t_30deg_straightonly)
|
||||
|
|
Loading…
Reference in New Issue