html; charset=UTF-8 Last-Modified: Tue, 20 Oct 2026 12:28:50 GMT Expires: Fri, 17 Oct 2036 12:28:50 GMT crafting.lua « advtrains - advtrains.git - Advtrains mod for minetest.
aboutsummaryrefslogtreecommitdiff
path: root/advtrains/crafting.lua
blob: 9f804566a4ff904d0515924b1647c16bd8d1d988 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
--advtrains by orwell96, see readme.txt and license.txt
--crafting.lua
--registers crafting recipes

--tracks: see advtrains_train_track
--signals
minetest.register_craft({
	output = 'advtrains:retrosignal_off 2',
	recipe = {
		{'dye:red', 'default:steel_ingot', 'default:steel_ingot'},
		{'', '', 'default:steel_ingot'},
		{'', '', 'default:steel_ingot'},
	},
})
minetest.register_craft({
	output = 'advtrains:signal_off 2',
	recipe = {
		{'', 'dye:red', 'default:steel_ingot'},
		{'', 'dye:dark_green', 'default:steel_ingot'},
		{'', '', 'default:steel_ingot'},
	},
})
--Wallmounted Signal
minetest.register_craft({
	output = 'advtrains:signal_wall_l_off 2',
	recipe = {
		{'default:steel_ingot', 'default:steel_ingot', 'dye:red'},
		{'', 'default:steel_ingot', ''},
		{'default:steel_ingot', 'default:steel_ingot', 'dye:dark_green'},
	},
})
minetest.register_craft({
	output = 'advtrains:signal_wall_r_off 2',
	recipe = {
		{'dye:red', 'default:steel_ingot', 'default:steel_ingot'},
		{'', 'default:steel_ingot', ''},
		{'dye:dark_green', 'default:steel_ingot', 'default:steel_ingot'},
	},
})
minetest.register_craft({
	output = 'advtrains:signal_wall_t_off 2',
	recipe = {
		{'default:steel_ingot', '', 'default:steel_ingot'},
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
		{'dye:dark_green', '', 'dye:red'},
	},
})


--Wallmounted Signals can be converted into every orientation by shapeless crafting
minetest.register_craft({
	output = 'advtrains:signal_wall_l_off',
	type = "shapeless",
	recipe = {'advtrains:signal_wall_r_off'},
})
minetest.register_craft({
	output = 'advtrains:signal_wall_t_off',
	type = "shapeless",
	recipe = {'advtrains:signal_wall_l_off'},
})
minetest.register_craft({
	output = 'advtrains:signal_wall_r_off',
	type = "shapeless",
	recipe = {'advtrains:signal_wall_t_off'},
})

--trackworker
minetest.register_craft({
	output = 'advtrains:trackworker',
	recipe = {
		{'default:diamond'},
		{'screwdriver:screwdriver'},
		{'default:steel_ingot'},
	},
})

--boiler
minetest.register_craft({
	output = 'advtrains:boiler',
	recipe = {
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
		{'doors:trapdoor_steel', '', 'default:steel_ingot'},
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
	},
})

--drivers'cab
minetest.register_craft({
	output = 'advtrains:driver_cab',
	recipe = {
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
		{'', '', 'default:glass'},
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
	},
})

--drivers'cab
minetest.register_craft({
	output = 'advtrains:wheel',
	recipe = {
		{'', 'default:steel_ingot', ''},
		{'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
		{'', 'default:steel_ingot', ''},
	},
})

--chimney
minetest.register_craft({
	output = 'advtrains:chimney',
	recipe = {
		{'', 'default:steel_ingot', ''},ute.entry, sigd) then
			-- Train entered not from the route. Locate origin and cancel route!
			atwarn("Train",tid,"hit route",ts.route.rsn,"!")
			advtrains.interlocking.route.cancel_route_from(ts.route.origin)
			atwarn("Route was cancelled.")
		else
			-- train entered route regularily.
		end
		ts.route = nil
	end
	if tcbs and tcbs.signal then
		-- Reset route and signal
		-- Note that the hit-route case is already handled by cancel_route_from
		-- this code only handles signal at entering tcb and also triggers for non-route ts
		tcbs.route_committed = nil
		tcbs.route_aspect = nil
		tcbs.route_remote = nil
		tcbs.route_origin = nil
		tcbs.route_rsn = nil
		if not tcbs.route_auto then
			tcbs.routeset = nil
		end
		advtrains.interlocking.signal.update_route_aspect(tcbs)
		advtrains.interlocking.route.update_route(sigd, tcbs)
	end
end

local function freesection(tid, train, ts_id, ts, clear_all)
	-- train
	if not train.il_sections then train.il_sections = {} end
	itkremove(train.il_sections, "ts_id", ts_id, not clear_all)
	
	-- ts
	if not ts.trains then ts.trains = {} end
	itremove(ts.trains, tid, not clear_all)
	
	-- route locks
	if ts.route_post then
		advtrains.interlocking.route.free_route_locks(ts_id, ts.route_post.locks)
		if ts.route_post.next then
			--this does nothing when the train went the right way, because
			-- "route" info is already cleared.
			advtrains.interlocking.route.cancel_route_from(ts.route_post.next)
		end
		ts.route_post = nil
	end
	-- This must be delayed, because this code is executed in-between a train step
	-- TODO use luaautomation timers?
	minetest.after(0, advtrains.interlocking.route.update_waiting, "ts", ts_id)
end


-- This is regular operation
-- The train is on a track and drives back and forth

-- This sets the section for both directions, to be failsafe
advtrains.tnc_register_on_enter(function(pos, id, train, index)
	local tcb = ildb.get_tcb(pos)
	if tcb and train.path_cp[index] and train.path_cn[index] then
		-- forward conn
		local connid = train.path_cn[index]
		local ts = tcb[connid] and tcb[connid].ts_id and ildb.get_ts(tcb[connid].ts_id)
		if ts then
			setsection(id, train, tcb[connid].ts_id, ts, {p=pos, s=connid})
		end
		-- backward conn (safety only)
		connid = train.path_cp[index]
		ts = tcb[connid] and tcb[connid].ts_id and ildb.get_ts(tcb[connid].ts_id)
		if ts then
			setsection(id, train, tcb[connid].ts_id, ts, {p=pos, s=connid}, true)
		end
	end
end)


-- this time, of course, only clear the backside (cp connid)
advtrains.tnc_register_on_leave(function(pos, id, train, index)
	local tcb = ildb.get_tcb(pos)
	if tcb and train.path_cp[index] then
		-- backward conn
		local connid = train.path_cp[index]
		local ts = tcb[connid] and tcb[connid].ts_id and ildb.get_ts(tcb[connid].ts_id)
		if ts then
			freesection(id, train, tcb[connid].ts_id, ts)
		end
	end
end)

-- those callbacks are needed to account for created and removed trains (also regarding coupling)

advtrains.te_register_on_create(function(id, train)
	-- let's see what track sections we find here
	local index = atround(train.index)
	local pos = advtrains.round_vector_floor_y(advtrains.path_get(train, index))
	local ts_id = ildb.check_and_repair_ts_at_pos(pos, 1) -- passing connid 1 - that always exists
	if ts_id then
		local ts = ildb.get_ts(ts_id)
		if ts then
			setsection(id, train, ts_id, ts, nil, true)
		else
			atwarn("While placing train, TS didnt exist ",ts_id)
		end
		-- Make train a shunt move
		train.is_shunt = true
	elseif ts_id==nil then
		atlog("Train",id,": Unable to determine whether to block a track section!")
	else
		--atdebug("Train",id,": Outside of interlocked area!")
	end
end)

advtrains.te_register_on_remove(function(id, train)
	if train.il_sections then
		for idx, item in ipairs(train.il_sections) do
			
			local ts = item.ts_id and ildb.get_ts(item.ts_id)
			
			if ts and ts.trains then
				itremove(ts.trains, id)
			end
		end
		train.il_sections = nil
	end
end)