summaryrefslogtreecommitdiff
path: root/ioexpander.lua
blob: 7e257720c190eac8cc78201bf4defe4ed9fb7399 (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
167
168
169
170
171
172
173
174
175
176
local explode_port_states = function(state)
	local port = {}
	port.a = state%2  == 1
	port.b = state%4  >= 2
	port.c = state%8  >= 4
	port.d = state%16 >= 8
	return port
end

local implode_port_states = function(port)
	local state = 0
	if port.a then state = state + 1 end
	if port.b then state = state + 2 end
	if port.c then state = state + 4 end
	if port.d then state = state + 8 end
	return state
end

local gettiles = function(state)
	tiles = {
		"digistuff_ioexp_top.png",
		"jeija_microcontroller_bottom.png",
		"jeija_microcontroller_sides.png",
		"jeija_microcontroller_sides.png",
		"jeija_microcontroller_sides.png",
		"jeija_microcontroller_sides.png"
	}
	local port = explode_port_states(state)
	for p,v in pairs(port) do
		if v then
			tiles[1] = tiles[1].."^jeija_luacontroller_LED_"..string.upper(p)..".png"
		end
	end
	return tiles
end

local ioexp_get_on_rules = function(state)
	local port = explode_port_states(state)
	local rules = {}
	if port.a then table.insert(rules,vector.new(-1,0,0)) end
	if port.b then table.insert(rules,vector.new(0,0,1)) end
	if port.c then table.insert(rules,vector.new(1,0,0)) end
	if port.d then table.insert(rules,vector.new(0,0,-1)) end
	return rules
end

local ioexp_get_off_rules = function(state)
	local port = explode_port_states(state)
	local rules = {}
	if not port.a then table.insert(rules,vector.new(-1,0,0)) end
	if not port.b then table.insert(rules,vector.new(0,0,1)) end
	if not port.c then table.insert(rules,vector.new(1,0,0)) end
	if not port.d then table.insert(rules,vector.new(0,0,-1)) end
	return rules
end

local ioexp_digiline_send = function(pos)
	local meta = minetest.get_meta(pos)
	local channel = meta:get_string("channel")
	local port = {
		a = meta:get_int("aon") == 1,
		b = meta:get_int("bon") == 1,
		c = meta:get_int("con") == 1,
		d = meta:get_int("don") == 1,
	}
	local outstate = explode_port_states(meta:get_int("outstate"))
	for k,v in pairs(outstate) do port[k] = port[k] or v end
	digiline:receptor_send(pos,digiline.rules.default,channel,port)
end

local ioexp_handle_digilines = function(pos,node,channel,msg)
	local meta = minetest.get_meta(pos)
	if channel ~= meta:get_string("channel") then return end
	if msg == "GET" then
		ioexp_digiline_send(pos)
		return
	end
	if type(msg) ~= "table" then return end
	local state = implode_port_states(msg)
	node.name = "digistuff:ioexpander_"..state
	meta:set_int("outstate",state)
	minetest.swap_node(pos,node)
	for _,i in ipairs(ioexp_get_on_rules(state)) do
		mesecon.receptor_on(pos,{i})
	end
	for _,i in ipairs(ioexp_get_off_rules(state)) do
		mesecon.receptor_off(pos,{i})
	end
end

local ioexp_rule_to_port = function(rule)
	if     rule.x < 0 then return "a"
	elseif rule.z > 0 then return "b"
	elseif rule.x > 0 then return "c"
	elseif rule.z < 0 then return "d" end
end

local ioexp_handle_mesecons = function(pos,_,rule,state)
	local meta = minetest.get_meta(pos)
	local port = ioexp_rule_to_port(rule)
	if not port then return end
	local meta = minetest.get_meta(pos)
	meta:set_int(port.."on",state == "on" and 1 or 0)
	ioexp_digiline_send(pos)
end

for i=0,15,1 do
	local offstate = i == 0
	minetest.register_node("digistuff:ioexpander_"..i, {
		description = offstate and "Digilines I/O Expander" or string.format("Digilines I/O Expander (on state %X - you hacker you!)",i),
		groups = offstate and {cracky = 3,} or {cracky = 3,not_in_creative_inventory = 1,},
		on_construct = function(pos)
			local meta = minetest.get_meta(pos)
			meta:set_string("formspec","field[channel;Channel;${channel}")
			meta:set_int("aon",0)
			meta:set_int("bon",0)
			meta:set_int("con",0)
			meta:set_int("don",0)
			meta:set_int("outstate",i)
		end,
		tiles = gettiles(i),
		inventory_image = "digistuff_ioexp_top.png",
		drawtype = "nodebox",
		drop = "digistuff:ioexpander_0",
		selection_box = {
			--From luacontroller
			type = "fixed",
			fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
		},
		node_box = {
			--From Luacontroller
			type = "fixed",
			fixed = {
				{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab
				{-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board
				{-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC
			}
		},
		paramtype = "light",
		sunlight_propagates = true,
		on_receive_fields = function(pos, formname, fields, sender)
			local name = sender:get_player_name()
			if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then
				minetest.record_protection_violation(pos,name)
				return
			end
			local meta = minetest.get_meta(pos)
			if fields.channel then meta:set_string("channel",fields.channel) end
		end,
		mesecons = {
			effector = {
				rules = ioexp_get_off_rules(i),
				action_change = ioexp_handle_mesecons,
			},
			receptor = {
				state = mesecon.state.on,
				rules = ioexp_get_on_rules(i),
			},
		},
		digiline = {
			receptor = {},
			effector = {
				action = ioexp_handle_digilines,
			},
		},
	})
end

minetest.register_craft({
	output = "digistuff:ioexpander_0",
	recipe = {
		{"","mesecons:wire_00000000_off","",},
		{"digilines:wire_std_00000000","basic_materials:silicon","mesecons:wire_00000000_off",},
		{"","mesecons:wire_00000000_off","",},
	}
})