summaryrefslogtreecommitdiff
path: root/nodes/node_item_ejector.lua
blob: 6f9c64e41c55db3bbb3d5612ee06fe0fab6662d9 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

--Build up the formspec, somewhat complicated due to multiple mod options
local pipeworks_path = minetest.get_modpath("pipeworks")
local doc_path = minetest.get_modpath("doc")
local formspec_width = 1.5

local ejector_formspec_string = 
	default.gui_bg ..
	default.gui_bg_img ..
	default.gui_slots

if doc_path then
	ejector_formspec_string = ejector_formspec_string ..
		"button_exit[".. 0.2 + formspec_width ..",0.5;1,0.1;help;" .. S("Help") .. "]" ..
		"tooltip[help;" .. S("Show documentation about this block") .. "]"
	formspec_width = formspec_width + 1.5
end

local ejector_formspec_string = "size[".. formspec_width .. ",1]" .. ejector_formspec_string

local ejector_formspec = function(pos, meta)
	local return_string = ejector_formspec_string
	if pipeworks_path then
		return_string = return_string .. "checkbox[0,0.5;nonpipe;"..S("Eject into world")..";"..meta:get_string("nonpipe").."]" ..
			"tooltip[nonpipe;" .. S("When checked, will eject items even if there's no pipe to accept it") .. "]"
	end
	return return_string .. "checkbox[0,0;autoeject;"..S("Automatic")..";"..meta:get_string("autoeject").."]" ..
		"tooltip[autoeject;" .. S("When checked, will eject items automatically with every Digtron cycle.\nItem ejectors can always be operated manually by punching them.") .. "]"
end

local function eject_items(pos, node, player, eject_even_without_pipeworks)
	local dir = minetest.facedir_to_dir(node.param2)
	local destination_pos = vector.add(pos, dir)
	local destination_node_name = minetest.get_node(destination_pos).name
	local destination_node_def = minetest.registered_nodes[destination_node_name]
	
	if not pipeworks_path then eject_even_without_pipeworks = true end -- if pipeworks is not installed, always eject into world (there's no other option)
	
	local insert_into_pipe = false
	local eject_into_world = false
	if pipeworks_path and minetest.get_node_group(destination_node_name, "tubedevice") > 0 then
		insert_into_pipe = true
	elseif eject_even_without_pipeworks then
		if destination_node_def and not destination_node_def.walkable then
			eject_into_world = true
		else
			minetest.sound_play("buzzer", {gain=0.5, pos=pos})
			return false
		end
	else
		return false
	end	

	local layout = DigtronLayout.create(pos, player)

	-- Build a list of all the items that builder nodes want to use.
	local filter_items = {}
	for _, node_image in pairs(layout.builders) do
		filter_items[node_image.meta.inventory.main[1]:get_name()] = true
	end
	
	-- Look through the inventories and find an item that's not on that list.
	local source_node = nil
	local source_index = nil
	local source_stack = nil
	for _, node_image in pairs(layout.inventories) do
		for index, item_stack in pairs(node_image.meta.inventory.main) do
			if item_stack:get_count() > 0 and not filter_items[item_stack:get_name()] then
				source_node = node_image
				source_index = index
				source_stack = item_stack
				break
			end
		end
		if source_node then break end
	end
	
	if source_node then
		local meta = minetest.get_meta(source_node.pos)
		local inv = meta:get_inventory()
		
		if insert_into_pipe then
			local from_pos = vector.add(pos, vector.multiply(dir, 0.5))
			local start_pos = pos
			inv:set_stack("main", source_index, nil)
			pipeworks.tube_inject_item(from_pos, start_pos, vector.multiply(dir, 1), source_stack, player:get_player_name())
			minetest.sound_play("steam_puff", {gain=0.5, pos=pos})
			return true
		elseif eject_into_world then
			minetest.add_item(destination_pos, source_stack)
			inv:set_stack("main", source_index, nil)
			minetest.sound_play("steam_puff", {gain=0.5, pos=pos})
			return true
		end
	end

	-- couldn't find an item to eject
	return false
end

minetest.register_node("digtron:inventory_ejector", {
	description = S("Digtron Inventory Ejector"),
	_doc_items_longdesc = digtron.doc.inventory_ejector_longdesc,
    _doc_items_usagehelp = digtron.doc.inventory_ejector_usagehelp,
	_digtron_formspec = ejector_formspec,
	groups = {cracky = 3,  oddly_breakable_by_hand=3, digtron = 9, tubedevice = 1},
	tiles = {"digtron_plate.png", "digtron_plate.png", "digtron_plate.png", "digtron_plate.png", "digtron_plate.png^digtron_output.png", "digtron_plate.png^digtron_output_back.png"},
	drawtype = "nodebox",
	sounds = digtron.metal_sounds,
	paramtype = "light",
	paramtype2 = "facedir",
	is_ground_content = false,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.5, 0.5, 0.5, 0.1875}, -- NodeBox1
			{-0.3125, -0.3125, 0.1875, 0.3125, 0.3125, 0.3125}, -- NodeBox2
			{-0.1875, -0.1875, 0.3125, 0.1875, 0.1875, 0.5}, -- NodeBox3
		}
	},
	
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("autoeject", "true")
		meta:set_string("formspec", ejector_formspec(pos, meta))
	end,
	
	tube = (function() if pipeworks_path then return {
		connect_sides = {back = 1}
	} end end)(),
	
	on_punch = function(pos, node, player)
		eject_items(pos, node, player, true)
	end,
	
	execute_eject = function(pos, node, player)
		local meta = minetest.get_meta(pos)
		eject_items(pos, node, player, meta:get_string("nonpipe") == "true")
	end,
	
	on_receive_fields = function(pos, formname, fields, sender)
		local meta = minetest.get_meta(pos)
		
		if fields.help and minetest.get_modpath("doc") then --check for mod in case someone disabled it after this digger was built
			local node_name = minetest.get_node(pos).name
			minetest.after(0.5, doc.show_entry, sender:get_player_name(), "nodes", node_name, true)
		end
		
		if fields.nonpipe then
			meta:set_string("nonpipe", fields.nonpipe)
		end
		
		if fields.autoeject then
			meta:set_string("autoeject", fields.autoeject)
		end
		
		meta:set_string("formspec", ejector_formspec(pos, meta))
		
	end,
	
	after_place_node = (function() if pipeworks_path then return pipeworks.after_place end end)(),
	after_dig_node = (function() if pipeworks_path then return pipeworks.after_dig end end)()
})