1
+ -- ______
2
+ -- |
3
+ -- |
4
+ -- | __ ___ _ __ _ _
5
+ -- | | | | | |\ | | |_| | | | | |_ |_|
6
+ -- |___| |______ |__| | \| | | \ |__| |_ |_ |_ |\
7
+ -- |
8
+ -- |
9
+ --
10
+
1
11
-- Reference
2
- -- ports = get_real_portstates (pos): gets if inputs are powered from outside
3
- -- newport = merge_portstates (state1, state2): just does result = state1 or state2 for every port
4
- -- action_setports (pos, rule, state): activates/deactivates the mesecons according to the portstates (helper for action)
5
- -- action (pos, ports): Applies new portstates to a luacontroller at pos
6
- -- lc_update (pos): updates the controller at pos by executing the code
7
- -- reset_meta (pos, code, errmsg): performs a software-reset, installs new code and prints error messages
8
- -- reset (pos): performs a hardware reset, turns off all ports
12
+ -- ports = get_real_port_states (pos): gets if inputs are powered from outside
13
+ -- newport = merge_port_states (state1, state2): just does result = state1 or state2 for every port
14
+ -- set_port (pos, rule, state): activates/deactivates the mesecons according to the port states
15
+ -- set_port_states (pos, ports): Applies new port states to a LuaController at pos
16
+ -- run (pos): runs the code in the controller at pos
17
+ -- reset_meta(pos, code, errmsg): performs a software-reset, installs new code and prints error messages
18
+ -- resetn (pos): performs a hardware reset, turns off all ports
9
19
--
10
20
-- The Sandbox
11
21
-- The whole code of the controller runs in a sandbox,
20
30
21
31
local BASENAME = " mesecons_luacontroller:luacontroller"
22
32
23
- local rules = {}
24
- rules .a = {x = - 1 , y = 0 , z = 0 , name = " A" }
25
- rules .b = {x = 0 , y = 0 , z = 1 , name = " B" }
26
- rules .c = {x = 1 , y = 0 , z = 0 , name = " C" }
27
- rules .d = {x = 0 , y = 0 , z = - 1 , name = " D" }
33
+ local rules = {
34
+ a = {x = - 1 , y = 0 , z = 0 , name = " A" },
35
+ b = {x = 0 , y = 0 , z = 1 , name = " B" },
36
+ c = {x = 1 , y = 0 , z = 0 , name = " C" },
37
+ d = {x = 0 , y = 0 , z = - 1 , name = " D" },
38
+ }
39
+
28
40
29
41
---- --------------
30
42
-- Action stuff --
31
43
---- --------------
32
- -- These helpers are required to set the portstates of the luacontroller
44
+ -- These helpers are required to set the port states of the luacontroller
33
45
34
- function lc_update_real_portstates (pos , rulename , newstate )
46
+ local function update_real_port_states (pos , rule_name , new_state )
35
47
local meta = minetest .get_meta (pos )
36
- if rulename == nil then
48
+ if rule_name == nil then
37
49
meta :set_int (" real_portstates" , 1 )
38
50
return
39
51
end
40
52
local n = meta :get_int (" real_portstates" ) - 1
41
53
local L = {}
42
54
for i = 1 , 4 do
43
- L [i ] = n % 2
44
- n = math.floor (n / 2 )
55
+ L [i ] = n % 2
56
+ n = math.floor (n / 2 )
45
57
end
46
- if rulename .x == nil then
47
- for _ , rname in ipairs (rulename ) do
48
- local port = ({4 , 1 , nil , 3 , 2 })[rname .x + 2 * rname .z + 3 ]
58
+ -- (0,-1) (-1,0) (1,0) (0,1)
59
+ local pos_to_side = { 4 , 1 , nil , 3 , 2 }
60
+ if rule_name .x == nil then
61
+ for _ , rname in ipairs (rule_name ) do
62
+ local port = pos_to_side [rname .x + (2 * rname .z ) + 3 ]
49
63
L [port ] = (newstate == " on" ) and 1 or 0
50
64
end
51
65
else
52
- local port = ({ 4 , 1 , nil , 3 , 2 })[ rulename . x + 2 * rulename . z + 3 ]
53
- L [port ] = (newstate == " on" ) and 1 or 0
66
+ local port = pos_to_side [ rule_name . x + ( 2 * rule_name . z ) + 3 ]
67
+ L [port ] = (new_state == " on" ) and 1 or 0
54
68
end
55
- meta :set_int (" real_portstates" , 1 + L [1 ] + 2 * L [2 ] + 4 * L [3 ] + 8 * L [4 ])
69
+ meta :set_int (" real_portstates" ,
70
+ 1 +
71
+ 1 * L [1 ] +
72
+ 2 * L [2 ] +
73
+ 4 * L [3 ] +
74
+ 8 * L [4 ])
56
75
end
57
76
58
- local get_real_portstates = function (pos ) -- determine if ports are powered (by itself or from outside)
77
+
78
+ local port_names = {" a" , " b" , " c" , " d" }
79
+
80
+ local function get_real_port_states (pos )
81
+ -- Determine if ports are powered (by itself or from outside)
59
82
local meta = minetest .get_meta (pos )
60
83
local L = {}
61
84
local n = meta :get_int (" real_portstates" ) - 1
62
- for _ , index in ipairs ({ " a " , " b " , " c " , " d " } ) do
63
- L [index ] = ((n % 2 ) == 1 )
64
- n = math.floor (n / 2 )
85
+ for _ , name in ipairs (port_names ) do
86
+ L [name ] = ((n % 2 ) == 1 )
87
+ n = math.floor (n / 2 )
65
88
end
66
89
return L
67
90
end
68
91
69
- local merge_portstates = function (ports , vports )
70
- local npo = {a = false , b = false , c = false , d = false }
71
- npo .a = vports .a or ports .a
72
- npo .b = vports .b or ports .b
73
- npo .c = vports .c or ports .c
74
- npo .d = vports .d or ports .d
75
- return npo
92
+
93
+ local function merge_port_states (ports , vports )
94
+ return {
95
+ a = ports .a or vports .a ,
96
+ b = ports .b or vports .b ,
97
+ c = ports .c or vports .c ,
98
+ d = ports .d or vports .d ,
99
+ }
76
100
end
77
101
78
- local generate_name = function (ports )
102
+ local function generate_name (ports )
79
103
local d = ports .d and 1 or 0
80
104
local c = ports .c and 1 or 0
81
105
local b = ports .b and 1 or 0
82
106
local a = ports .a and 1 or 0
83
107
return BASENAME .. d .. c .. b .. a
84
108
end
85
109
86
- local setport = function (pos , rule , state )
110
+
111
+ local function set_port (pos , rule , state )
87
112
if state then
88
113
mesecon .receptor_on (pos , {rule })
89
114
else
90
115
mesecon .receptor_off (pos , {rule })
91
116
end
92
117
end
93
118
94
- local action = function (pos , ports )
119
+
120
+ local function clean_port_states (ports )
121
+ ports .a = ports .a and true or false
122
+ ports .b = ports .b and true or false
123
+ ports .c = ports .c and true or false
124
+ ports .d = ports .d and true or false
125
+ end
126
+
127
+
128
+ local function set_port_states (pos , ports )
95
129
local node = minetest .get_node (pos )
96
130
local name = node .name
131
+ clean_port_states (ports )
97
132
local vports = minetest .registered_nodes [name ].virtual_portstates
98
- local newname = generate_name (ports )
99
-
100
- if name ~= newname and vports then
101
- local rules_on = {}
102
- local rules_off = {}
133
+ local new_name = generate_name (ports )
103
134
104
- minetest .swap_node (pos , {name = newname , param2 = node .param2 })
135
+ if name ~= new_name and vports then
136
+ minetest .swap_node (pos , {name = new_name , param2 = node .param2 })
105
137
106
- if ports .a ~= vports .a then setport (pos , rules .a , ports .a ) end
107
- if ports .b ~= vports .b then setport (pos , rules .b , ports .b ) end
108
- if ports .c ~= vports .c then setport (pos , rules .c , ports .c ) end
109
- if ports .d ~= vports .d then setport (pos , rules .d , ports .d ) end
138
+ if ports .a ~= vports .a then set_port (pos , rules .a , ports .a ) end
139
+ if ports .b ~= vports .b then set_port (pos , rules .b , ports .b ) end
140
+ if ports .c ~= vports .c then set_port (pos , rules .c , ports .c ) end
141
+ if ports .d ~= vports .d then set_port (pos , rules .d , ports .d ) end
110
142
end
111
143
end
112
144
113
- ---- ----------------
114
- -- Overheat stuff --
115
- ---- ----------------
116
145
117
- local overheat_off = function (pos )
146
+ ---- -------------
147
+ -- Overheating --
148
+ ---- -------------
149
+
150
+ local function overheat_off (pos )
118
151
mesecon .receptor_off (pos , mesecon .rules .flat )
119
152
end
120
153
121
- ---- ---------------
122
- -- Parsing stuff --
123
- ---- ---------------
124
154
125
- local code_prohibited = function (code )
126
- -- Clean code
127
- local prohibited = {" while" , " for" , " repeat" , " until" , " function" , " goto" }
128
- for _ , p in ipairs (prohibited ) do
129
- if string.find (code , p ) then
130
- return " Prohibited command: " .. p
131
- end
155
+ local function overheat (pos , meta )
156
+ if mesecon .do_overheat (pos ) then -- If too hot
157
+ local node = minetest .get_node (pos )
158
+ node .name = BASENAME .. " _burnt"
159
+ minetest .swap_node (pos , node )
160
+ -- Wait for pending operations
161
+ minetest .after (0.2 , overheat_off , pos )
162
+ return true
132
163
end
133
164
end
134
165
135
- local safe_print = function (param )
166
+
167
+ ---- ---------------------
168
+ -- Parsing and running --
169
+ ---- ---------------------
170
+
171
+ local function safe_print (param )
136
172
print (dump (param ))
137
173
end
138
174
139
- deep_copy = function (original , visited ) -- deep copy that removes functions
140
- visited = visited or {}
141
- if visited [original ] ~= nil then -- already visited this node
142
- return visited [original ]
143
- end
144
- if type (original ) == ' table' then -- nested table
145
- local copy = {}
146
- visited [original ] = copy
147
- for key , value in next , original , nil do
148
- copy [deep_copy (key , visited )] = deep_copy (value , visited )
175
+ minetest .register_globalstep (function (dtime )
176
+ print_count = print_count - dtime
177
+ end )
178
+
179
+
180
+ local function remove_functions (x )
181
+ local tp = type (x )
182
+ if tp == " table" then
183
+ for key , value in pairs (x ) do
184
+ local key_t , val_t = type (key ), type (value )
185
+ if key_t == " function" or val_t == " function" then
186
+ x [key ] = nil
187
+ else
188
+ if key_t == " table" then
189
+ remove_functions (key )
190
+ end
191
+ if val_t == " table" then
192
+ remove_functions (value )
193
+ end
194
+ end
149
195
end
150
- setmetatable (copy , deep_copy (getmetatable (original ), visited ))
151
- return copy
152
- elseif type (original ) == ' function' then -- ignore functions
196
+ elseif tp == " function" then
153
197
return nil
154
- else -- by-value type
155
- return original
156
198
end
199
+ return x
157
200
end
158
201
159
- local safe_serialize = function (value )
160
- return minetest .serialize (deep_copy (value ))
161
- end
162
-
163
- mesecon .queue :add_function (" lc_interrupt" , function (pos , luac_id , iid )
164
- -- There is no luacontroller anymore / it has been reprogrammed / replaced
165
- if (minetest .get_meta (pos ):get_int (" luac_id" ) ~= luac_id ) then return end
166
- lc_update (pos , {type = " interrupt" , iid = iid })
167
- end )
168
-
169
- local getinterrupt = function (pos )
170
- local interrupt = function (time , iid ) -- iid = interrupt id
202
+ local function get_interrupt (pos )
203
+ -- iid = interrupt id
204
+ local function interrupt (time , iid )
171
205
if type (time ) ~= " number" then return end
172
206
local luac_id = minetest .get_meta (pos ):get_int (" luac_id" )
173
207
mesecon .queue :add_action (pos , " lc_interrupt" , {luac_id , iid }, time , iid , 1 )
174
208
end
175
209
return interrupt
176
210
end
177
211
178
- local getdigiline_send = function (pos )
212
+
213
+ local function get_digiline_send (pos )
179
214
if not digiline then return end
180
- -- Send messages on next serverstep
181
215
return function (channel , msg )
182
216
minetest .after (0 , function ()
183
217
digiline :receptor_send (pos , digiline .rules .default , channel , msg )
184
218
end )
185
219
end
186
220
end
187
221
188
- local create_environment = function (pos , mem , event )
222
+
223
+ local safe_globals = {
224
+ " assert" , " error" , " ipairs" , " next" , " pairs" , " pcall" , " select" ,
225
+ " tonumber" , " tostring" , " type" , " unpack" , " _VERSION" , " xpcall" ,
226
+ }
227
+ local function create_environment (pos , mem , event )
189
228
-- Gather variables for the environment
190
229
local vports = minetest .registered_nodes [minetest .get_node (pos ).name ].virtual_portstates
191
- vports = {a = vports .a , b = vports .b , c = vports .c , d = vports .d }
192
- local rports = get_real_portstates (pos )
193
-
194
- return {
195
- print = safe_print ,
196
- pin = merge_portstates (vports , rports ),
197
- port = vports ,
198
- interrupt = getinterrupt (pos ),
199
- digiline_send = getdigiline_send (pos ),
200
- mem = mem ,
201
- tostring = tostring ,
202
- tonumber = tonumber ,
203
- heat = minetest .get_meta (pos ):get_int (" heat" ),
204
- -- overheat_max Unit: actions per second, checks are every 1 second
205
- heat_max = mesecon .setting (" overheat_max" , 20 ),
206
- string = {
207
- byte = string.byte ,
208
- char = string.char ,
209
- find = string.find ,
210
- format = string.format ,
211
- gmatch = string.gmatch ,
212
- gsub = string.gsub ,
213
- len = string.len ,
214
- lower = string.lower ,
215
- upper = string.upper ,
216
- match = string.match ,
217
- rep = string.rep ,
218
- reverse = string.reverse ,
219
- sub = string.sub ,
220
- },
221
- math = {
222
- abs = math.abs ,
223
- acos = math.acos ,
224
- asin = math.asin ,
225
- atan = math.atan ,
226
- atan2 = math.atan2 ,
227
- ceil = math.ceil ,
228
- cos = math.cos ,
229
- cosh = math.cosh ,
230
- deg = math.deg ,
231
- exp = math.exp ,
232
- floor = math.floor ,
233
- fmod = math.fmod ,
234
- frexp = math.frexp ,
235
- huge = math.huge ,
236
- ldexp = math.ldexp ,
237
- log = math.log ,
238
- log10 = math.log10 ,
239
- max = math.max ,
240
- min = math.min ,
241
- modf = math.modf ,
242
- pi = math.pi ,
243
- pow = math.pow ,
244
- rad = math.rad ,
245
- random = math.random ,
246
- sin = math.sin ,
247
- sinh = math.sinh ,
248
- sqrt = math.sqrt ,
249
- tan = math.tan ,
250
- tanh = math.tanh ,
251
- },
252
- table = {
253
- insert = table.insert ,
254
- maxn = table.maxn ,
255
- remove = table.remove ,
256
- sort = table.sort
257
- },
258
- event = event ,
230
+ local vports_copy = {}
231
+ for k , v in pairs (vports ) do vports_copy [k ] = v end
232
+ local rports = get_real_port_states (pos )
233
+
234
+ -- Create new library tables on each call to prevent one LuaController
235
+ -- from breaking a library and messing up other LuaControllers.
236
+ local env = {
237
+ pin = merge_port_states (vports , rports ),
238
+ port = vports_copy ,
239
+ event = event ,
240
+ mem = mem ,
241
+ heat = minetest .get_meta (pos ):get_int (" heat" ),
242
+ heat_max = mesecon .setting (" overheat_max" , 20 ),
243
+ print = safe_print ,
244
+ interrupt = get_interrupt (pos ),
245
+ digiline_send = get_digiline_send (pos ),
246
+ string = {
247
+ byte = string.byte ,
248
+ char = string.char ,
249
+ format = string.format ,
250
+ gsub = string.gsub ,
251
+ len = string.len ,
252
+ lower = string.lower ,
253
+ upper = string.upper ,
254
+ rep = string.rep ,
255
+ reverse = string.reverse ,
256
+ sub = string.sub ,
257
+ },
258
+ math = {
259
+ abs = math.abs ,
260
+ acos = math.acos ,
261
+ asin = math.asin ,
262
+ atan = math.atan ,
263
+ atan2 = math.atan2 ,
264
+ ceil = math.ceil ,
265
+ cos = math.cos ,
266
+ cosh = math.cosh ,
267
+ deg = math.deg ,
268
+ exp = math.exp ,
269
+ floor = math.floor ,
270
+ fmod = math.fmod ,
271
+ frexp = math.frexp ,
272
+ huge = math.huge ,
273
+ ldexp = math.ldexp ,
274
+ log = math.log ,
275
+ log10 = math.log10 ,
276
+ max = math.max ,
277
+ min = math.min ,
278
+ modf = math.modf ,
279
+ pi = math.pi ,
280
+ pow = math.pow ,
281
+ rad = math.rad ,
282
+ random = math.random ,
283
+ sin = math.sin ,
284
+ sinh = math.sinh ,
285
+ sqrt = math.sqrt ,
286
+ tan = math.tan ,
287
+ tanh = math.tanh ,
288
+ },
289
+ table = {
290
+ concat = table.concat ,
291
+ insert = table.insert ,
292
+ maxn = table.maxn ,
293
+ remove = table.remove ,
294
+ sort = table.sort ,
295
+ },
296
+ os = {
297
+ clock = os.clock ,
298
+ difftime = os.difftime ,
299
+ time = os.time ,
300
+ },
259
301
}
302
+ env ._G = env
303
+
304
+ for _ , name in pairs (safe_globals ) do
305
+ env [name ] = _G [name ]
306
+ end
307
+
308
+ return env
260
309
end
261
310
262
- local create_sandbox = function (code , env )
263
- -- Create Sandbox
311
+
312
+ local function timeout ()
313
+ debug.sethook () -- Clear hook
314
+ error (" Code timed out!" )
315
+ end
316
+
317
+
318
+ local function code_prohibited (code )
319
+ -- LuaJIT doesn't increment the instruction counter when running
320
+ -- loops, so we have to sanitize inputs if we're using LuaJIT.
321
+ if not jit then
322
+ return false
323
+ end
324
+ local prohibited = {" while" , " for" , " do" , " repeat" , " until" , " goto" }
325
+ code = " " .. code .. " "
326
+ for _ , p in ipairs (prohibited ) do
327
+ if string.find (code , " [^%w_]" .. p .. " [^%w_]" ) then
328
+ return " Prohibited command: " .. p
329
+ end
330
+ end
331
+ end
332
+
333
+
334
+ local function create_sandbox (code , env )
264
335
if code :byte (1 ) == 27 then
265
- return _ , " You Hacker You! Don't use binary code! "
336
+ return nil , " Binary code prohibited. "
266
337
end
267
338
local f , msg = loadstring (code )
268
- if not f then return _ , msg end
339
+ if not f then return nil , msg end
269
340
setfenv (f , env )
270
- return f
271
- end
272
341
273
- local lc_overheat = function ( pos , meta )
274
- if mesecon . do_overheat ( pos ) then -- if too hot
275
- local node = minetest . get_node ( pos )
276
- minetest . swap_node ( pos , { name = BASENAME .. " _burnt " , param2 = node . param2 })
277
- minetest . after ( 0.2 , overheat_off , pos ) -- wait for pending operations
278
- return true
342
+ return function (... )
343
+ debug.sethook ( timeout , " " , 10000 )
344
+ local ok , ret = pcall ( f , ... )
345
+ debug.sethook () -- Clear hook
346
+ if not ok then error ( ret ) end
347
+ return ret
279
348
end
280
349
end
281
350
282
- local load_memory = function (meta )
351
+
352
+ local function load_memory (meta )
283
353
return minetest .deserialize (meta :get_string (" lc_memory" )) or {}
284
354
end
285
355
286
- local save_memory = function (meta , mem )
287
- meta :set_string (" lc_memory" , safe_serialize (mem ))
288
- end
289
356
290
- local ports_invalid = function (var )
291
- if type (var ) == " table" then
292
- return false
293
- end
294
- return " The ports you set are invalid"
357
+ local function save_memory (meta , mem )
358
+ meta :set_string (" lc_memory" ,
359
+ minetest .serialize (
360
+ remove_functions (mem )
361
+ )
362
+ )
295
363
end
296
364
297
- ---- ------------------
298
- -- Parsing function --
299
- ---- ------------------
300
365
301
- lc_update = function (pos , event )
366
+ local function run (pos , event )
302
367
local meta = minetest .get_meta (pos )
303
- if lc_overheat (pos ) then return end
368
+ if overheat (pos ) then return end
304
369
305
- -- load code & mem from memory
370
+ -- Load code & mem from meta
306
371
local mem = load_memory (meta )
307
372
local code = meta :get_string (" code" )
308
373
309
- -- make sure code is ok and create environment
310
- local prohibited = code_prohibited (code )
311
- if prohibited then return prohibited end
374
+ local err = code_prohibited (code )
375
+ if err then return err end
376
+
377
+ -- Create environment
312
378
local env = create_environment (pos , mem , event )
313
379
314
- -- create the sandbox and execute code
315
- local chunk , msg = create_sandbox (code , env )
316
- if not chunk then return msg end
317
- local success , msg = pcall (chunk )
380
+ -- Create the sandbox and execute code
381
+ local f , msg = create_sandbox (code , env )
382
+ if not f then return msg end
383
+ local success , msg = pcall (f )
318
384
if not success then return msg end
319
- if ports_invalid (env .port ) then return ports_invalid (env .port ) end
385
+ if type (env .port ) ~= " table" then
386
+ return " Ports set are invalid."
387
+ end
320
388
321
- save_memory (meta , mem )
389
+ save_memory (meta , env . mem )
322
390
323
391
-- Actually set the ports
324
- action (pos , env .port )
392
+ set_port_states (pos , env .port )
325
393
end
326
394
327
- local reset_meta = function (pos , code , errmsg )
395
+ mesecon .queue :add_function (" lc_interrupt" , function (pos , luac_id , iid )
396
+ -- There is no luacontroller anymore / it has been reprogrammed / replaced
397
+ if (minetest .get_meta (pos ):get_int (" luac_id" ) ~= luac_id ) then return end
398
+ run (pos , {type = " interrupt" , iid = iid })
399
+ end )
400
+
401
+ local function reset_meta (pos , code , errmsg )
328
402
local meta = minetest .get_meta (pos )
329
403
meta :set_string (" code" , code )
330
404
code = minetest .formspec_escape (code or " " )
@@ -336,172 +410,155 @@ local reset_meta = function(pos, code, errmsg)
336
410
" image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]" ..
337
411
" label[0.1,5;" .. errmsg .. " ]" )
338
412
meta :set_int (" heat" , 0 )
339
- meta :set_int (" luac_id" , math.random (1 , 1000000 ))
413
+ meta :set_int (" luac_id" , math.random (1 , 65535 ))
340
414
end
341
415
342
- local reset = function (pos )
343
- action (pos , {a = false , b = false , c = false , d = false })
416
+ local function reset (pos )
417
+ set_port_states (pos , {a = false , b = false , c = false , d = false })
344
418
end
345
419
346
- -- ______
347
- -- |
348
- -- |
349
- -- | __ ___ _ __ _ _
350
- -- | | | | | |\ | | |_| | | | | |_ |_|
351
- -- |___| |______ |__| | \| | | \ |__| |_ |_ |_ |\
352
- -- |
353
- -- |
354
- --
355
420
356
421
---- -------------------
357
422
-- Node Registration --
358
423
---- -------------------
359
424
360
- local output_rules = {}
361
- local input_rules = {}
425
+ local output_rules = {}
426
+ local input_rules = {}
362
427
363
- local nodebox = {
364
- type = " fixed" ,
365
- fixed = {
366
- { - 8 / 16 , - 8 / 16 , - 8 / 16 , 8 / 16 , - 7 / 16 , 8 / 16 }, -- bottom slab
367
- { - 5 / 16 , - 7 / 16 , - 5 / 16 , 5 / 16 , - 6 / 16 , 5 / 16 }, -- circuit board
368
- { - 3 / 16 , - 6 / 16 , - 3 / 16 , 3 / 16 , - 5 / 16 , 3 / 16 }, -- IC
369
- }
428
+ local node_box = {
429
+ type = " fixed" ,
430
+ fixed = {
431
+ {- 8 / 16 , - 8 / 16 , - 8 / 16 , 8 / 16 , - 7 / 16 , 8 / 16 }, -- Bottom slab
432
+ {- 5 / 16 , - 7 / 16 , - 5 / 16 , 5 / 16 , - 6 / 16 , 5 / 16 }, -- Circuit board
433
+ {- 3 / 16 , - 6 / 16 , - 3 / 16 , 3 / 16 , - 5 / 16 , 3 / 16 }, -- IC
370
434
}
435
+ }
371
436
372
- local selectionbox = {
373
- type = " fixed" ,
374
- fixed = { - 8 / 16 , - 8 / 16 , - 8 / 16 , 8 / 16 , - 5 / 16 , 8 / 16 },
375
- }
437
+ local selection_box = {
438
+ type = " fixed" ,
439
+ fixed = { - 8 / 16 , - 8 / 16 , - 8 / 16 , 8 / 16 , - 5 / 16 , 8 / 16 },
440
+ }
376
441
377
442
local digiline = {
378
443
receptor = {},
379
444
effector = {
380
- action = function (pos , node , channel , msg )
381
- lc_update (pos , {type = " digiline" , channel = channel , msg = msg })
445
+ action = function (pos , node , channel , msg )
446
+ run (pos , {type = " digiline" , channel = channel , msg = msg })
382
447
end
383
448
}
384
449
}
450
+ local function on_receive_fields (pos , form_name , fields )
451
+ if not fields .program then
452
+ return
453
+ end
454
+ reset (pos )
455
+ reset_meta (pos , fields .code )
456
+ local err = run (pos , {type = " program" })
457
+ if err then
458
+ print (err )
459
+ reset_meta (pos , fields .code , err )
460
+ end
461
+ end
385
462
386
- for a = 0 , 1 do -- 0 = off; 1 = on
463
+ for a = 0 , 1 do -- 0 = off 1 = on
387
464
for b = 0 , 1 do
388
465
for c = 0 , 1 do
389
466
for d = 0 , 1 do
467
+ local cid = tostring (d ).. tostring (c ).. tostring (b ).. tostring (a )
468
+ local node_name = BASENAME .. cid
469
+ local top = " jeija_luacontroller_top.png"
470
+ if a == 1 then
471
+ top = top .. " ^jeija_luacontroller_LED_A.png"
472
+ end
473
+ if b == 1 then
474
+ top = top .. " ^jeija_luacontroller_LED_B.png"
475
+ end
476
+ if c == 1 then
477
+ top = top .. " ^jeija_luacontroller_LED_C.png"
478
+ end
479
+ if d == 1 then
480
+ top = top .. " ^jeija_luacontroller_LED_D.png"
481
+ end
390
482
391
- local cid = tostring (d ).. tostring (c ).. tostring (b ).. tostring (a )
392
- local nodename = BASENAME .. cid
393
- local top = " jeija_luacontroller_top.png"
394
- if a == 1 then
395
- top = top .. " ^jeija_luacontroller_LED_A.png"
396
- end
397
- if b == 1 then
398
- top = top .. " ^jeija_luacontroller_LED_B.png"
399
- end
400
- if c == 1 then
401
- top = top .. " ^jeija_luacontroller_LED_C.png"
402
- end
403
- if d == 1 then
404
- top = top .. " ^jeija_luacontroller_LED_D.png"
405
- end
406
-
407
- if a + b + c + d ~= 0 then
408
- groups = {dig_immediate = 2 , not_in_creative_inventory = 1 , overheat = 1 }
409
- else
410
- groups = {dig_immediate = 2 , overheat = 1 }
411
- end
483
+ local groups
484
+ if a + b + c + d ~= 0 then
485
+ groups = {dig_immediate = 2 , not_in_creative_inventory = 1 , overheat = 1 }
486
+ else
487
+ groups = {dig_immediate = 2 , overheat = 1 }
488
+ end
412
489
413
- output_rules [cid ] = {}
414
- input_rules [cid ] = {}
415
- if (a == 1 ) then table.insert (output_rules [cid ], rules .a ) end
416
- if (b == 1 ) then table.insert (output_rules [cid ], rules .b ) end
417
- if (c == 1 ) then table.insert (output_rules [cid ], rules .c ) end
418
- if (d == 1 ) then table.insert (output_rules [cid ], rules .d ) end
419
-
420
- if (a == 0 ) then table.insert (input_rules [cid ], rules .a ) end
421
- if (b == 0 ) then table.insert (input_rules [cid ], rules .b ) end
422
- if (c == 0 ) then table.insert (input_rules [cid ], rules .c ) end
423
- if (d == 0 ) then table.insert (input_rules [cid ], rules .d ) end
424
-
425
- local mesecons = {
426
- effector =
427
- {
428
- rules = input_rules [cid ],
429
- action_change = function (pos , _ , rulename , newstate )
430
- lc_update_real_portstates (pos , rulename , newstate )
431
- lc_update (pos , {type = newstate , pin = rulename })
432
- end ,
433
- },
434
- receptor =
435
- {
436
- state = mesecon .state .on ,
437
- rules = output_rules [cid ]
490
+ output_rules [cid ] = {}
491
+ input_rules [cid ] = {}
492
+ if a == 1 then table.insert (output_rules [cid ], rules .a ) end
493
+ if b == 1 then table.insert (output_rules [cid ], rules .b ) end
494
+ if c == 1 then table.insert (output_rules [cid ], rules .c ) end
495
+ if d == 1 then table.insert (output_rules [cid ], rules .d ) end
496
+
497
+ if a == 0 then table.insert ( input_rules [cid ], rules .a ) end
498
+ if b == 0 then table.insert ( input_rules [cid ], rules .b ) end
499
+ if c == 0 then table.insert ( input_rules [cid ], rules .c ) end
500
+ if d == 0 then table.insert ( input_rules [cid ], rules .d ) end
501
+
502
+ local mesecons = {
503
+ effector = {
504
+ rules = input_rules [cid ],
505
+ action_change = function (pos , _ , rule_name , new_state )
506
+ update_real_port_states (pos , rule_name , new_state )
507
+ run (pos , {type = new_state , pin = rule_name })
508
+ end ,
509
+ },
510
+ receptor = {
511
+ state = mesecon .state .on ,
512
+ rules = output_rules [cid ]
513
+ }
438
514
}
439
- }
440
515
441
- minetest .register_node (nodename , {
442
- description = " Luacontroller " ,
443
- drawtype = " nodebox" ,
444
- tiles = {
445
- top ,
446
- " jeija_microcontroller_bottom.png" ,
447
- " jeija_microcontroller_sides.png" ,
448
- " jeija_microcontroller_sides.png" ,
449
- " jeija_microcontroller_sides.png" ,
450
- " jeija_microcontroller_sides.png"
516
+ minetest .register_node (node_name , {
517
+ description = " LuaController " ,
518
+ drawtype = " nodebox" ,
519
+ tiles = {
520
+ top ,
521
+ " jeija_microcontroller_bottom.png" ,
522
+ " jeija_microcontroller_sides.png" ,
523
+ " jeija_microcontroller_sides.png" ,
524
+ " jeija_microcontroller_sides.png" ,
525
+ " jeija_microcontroller_sides.png"
451
526
},
452
-
453
- inventory_image = top ,
454
- paramtype = " light" ,
455
- groups = groups ,
456
- drop = BASENAME .. " 0000" ,
457
- sunlight_propagates = true ,
458
- selection_box = selectionbox ,
459
- node_box = nodebox ,
460
- on_construct = reset_meta ,
461
- on_receive_fields = function (pos , formname , fields )
462
- if not fields .program then
463
- return
464
- end
465
- reset (pos )
466
- reset_meta (pos , fields .code )
467
- local err = lc_update (pos , {type = " program" })
468
- if err then
469
- print (err )
470
- reset_meta (pos , fields .code , err )
471
- end
472
- end ,
473
- sounds = default .node_sound_stone_defaults (),
474
- mesecons = mesecons ,
475
- digiline = digiline ,
476
- virtual_portstates = { a = a == 1 , -- virtual portstates are
477
- b = b == 1 , -- the ports the the
478
- c = c == 1 , -- controller powers itself
479
- d = d == 1 },-- so those that light up
480
- after_dig_node = function (pos , node )
481
- mesecon .receptor_off (pos , output_rules )
482
- end ,
483
- is_luacontroller = true ,
484
- })
527
+ inventory_image = top ,
528
+ paramtype = " light" ,
529
+ groups = groups ,
530
+ drop = BASENAME .. " 0000" ,
531
+ sunlight_propagates = true ,
532
+ selection_box = selection_box ,
533
+ node_box = node_box ,
534
+ on_construct = reset_meta ,
535
+ on_receive_fields = on_receive_fields ,
536
+ on_timer = handle_timer ,
537
+ sounds = default .node_sound_stone_defaults (),
538
+ mesecons = mesecons ,
539
+ digiline = digiline ,
540
+ -- Virtual portstates are the ports that
541
+ -- the node shows as powered up (light up).
542
+ virtual_portstates = {
543
+ a = a == 1 ,
544
+ b = b == 1 ,
545
+ c = c == 1 ,
546
+ d = d == 1 ,
547
+ },
548
+ after_dig_node = function (pos , node )
549
+ mesecon .receptor_off (pos , output_rules )
550
+ end ,
551
+ is_luacontroller = true ,
552
+ })
485
553
end
486
554
end
487
555
end
488
556
end
489
557
490
558
---- --------------------------
491
- -- overheated luacontroller --
559
+ -- Overheated LuaController --
492
560
---- --------------------------
493
561
494
- local mesecons_burnt = {
495
- effector =
496
- {
497
- rules = mesecon .rules .flat ,
498
- action_change = function (pos , _ , rulename , newstate )
499
- -- only update portstates when changes are triggered
500
- lc_update_real_portstates (pos , rulename , newstate )
501
- end
502
- }
503
- }
504
-
505
562
minetest .register_node (BASENAME .. " _burnt" , {
506
563
drawtype = " nodebox" ,
507
564
tiles = {
@@ -518,23 +575,19 @@ minetest.register_node(BASENAME .. "_burnt", {
518
575
drop = BASENAME .. " 0000" ,
519
576
sunlight_propagates = true ,
520
577
selection_box = selectionbox ,
521
- node_box = nodebox ,
578
+ node_box = node_box ,
522
579
on_construct = reset_meta ,
523
- on_receive_fields = function (pos , formname , fields )
524
- if fields .quit then
525
- return
526
- end
527
- reset (pos )
528
- reset_meta (pos , fields .code )
529
- local err = lc_update (pos , {type = " program" })
530
- if err then
531
- print (err )
532
- reset_meta (pos , fields .code , err )
533
- end
534
- end ,
580
+ on_receive_fields = on_receive_fields ,
535
581
sounds = default .node_sound_stone_defaults (),
536
582
virtual_portstates = {a = false , b = false , c = false , d = false },
537
- mesecons = mesecons_burnt ,
583
+ mesecons = {
584
+ effector = {
585
+ rules = mesecon .rules .flat ,
586
+ action_change = function (pos , _ , rule_name , new_state )
587
+ update_real_port_states (pos , rule_name , new_state )
588
+ end ,
589
+ },
590
+ },
538
591
})
539
592
540
593
---- --------------------
0 commit comments