-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathhardware_fw.lua
425 lines (375 loc) · 12.1 KB
/
hardware_fw.lua
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
laptop.node_config = {}
local have_technic = minetest.get_modpath("technic")
local have_generator = minetest.get_modpath("power_generators")
local function on_construct(pos)
laptop.mtos_cache:free(pos)
local mtos = laptop.os_get(pos)
local node = minetest.get_node(pos)
local hwdef = laptop.node_config[node.name]
if hwdef.custom_theme then -- initial only
mtos:set_theme(hwdef.custom_theme)
end
if hwdef.hw_state then
mtos[hwdef.hw_state](mtos)
else
mtos:power_off()
end
end
local function on_punch(pos, node, puncher)
local mtos = laptop.os_get(pos)
local punch_item = puncher:get_wielded_item()
local is_compatible = false
if punch_item then
local def = punch_item:get_definition()
for group, _ in pairs(def.groups) do
if mtos.bdev:is_hw_capability(group) then
is_compatible = true
end
end
end
if is_compatible then
local slot = mtos.bdev:get_removable_disk()
-- swap
puncher:set_wielded_item(slot.stack)
-- reload OS
slot:reload(punch_item)
laptop.mtos_cache:sync_and_free(mtos)
for k,v in pairs(laptop.os_get(mtos.pos)) do
mtos[k] = v
end
mtos:pass_to_app("punched_by_removable", true, puncher, punch_item)
return
end
local hwdef = laptop.node_config[node.name]
if hwdef.next_node then
local hwdef_next = laptop.node_config[hwdef.next_node]
if hwdef_next.hw_state then
mtos[hwdef_next.hw_state](mtos, hwdef.next_node)
else
mtos:swap_node(hwdef.next_node)
mtos:save()
end
end
end
local function on_receive_fields(pos, formname, fields, sender)
local mtos = laptop.os_get(pos)
mtos:pass_to_app("receive_fields_func", true, sender, fields)
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local mtos = laptop.os_get(pos)
return mtos:pass_to_app("allow_metadata_inventory_move", false, player, from_list, from_index, to_list, to_index, count) or 0
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
local mtos = laptop.os_get(pos)
local def = stack:get_definition()
local allowed_stacksize = 0
if def then
for group, _ in pairs(def.groups) do
if mtos.bdev:is_hw_capability(group) then
allowed_stacksize = 1
end
end
end
return mtos:pass_to_app("allow_metadata_inventory_put", false, player, listname, index, stack) or allowed_stacksize
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
local mtos = laptop.os_get(pos)
return mtos:pass_to_app("allow_metadata_inventory_take", false, player, listname, index, stack) or 1 -- by default removal allowed
end
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local mtos = laptop.os_get(pos)
mtos:pass_to_app("on_metadata_inventory_move", true, player, from_list, from_index, to_list, to_index, count)
end
local function on_metadata_inventory_put(pos, listname, index, stack, player)
local mtos = laptop.os_get(pos)
mtos:pass_to_app("on_metadata_inventory_put", true, player, listname, index, stack)
end
local function on_metadata_inventory_take(pos, listname, index, stack, player)
local mtos = laptop.os_get(pos)
mtos:pass_to_app("on_metadata_inventory_take", true, player, listname, index, stack)
end
local function on_timer(pos, elapsed)
local mtos = laptop.os_get(pos)
return mtos:pass_to_app("on_timer", true, nil, elapsed)
end
local function after_place_node(pos, placer, itemstack, pointed_thing)
local save = minetest.deserialize(itemstack:get_meta():get_string("laptop_metadata"))
if not save then
return
end
-- Backwards compatibility code
if save.fields then
laptop.mtos_cache:free(pos)
local meta = minetest.get_meta(pos)
meta:from_table({fields = save.fields})
for invname, inv in pairs(save.invlist) do
meta:get_inventory():set_list(invname, inv)
end
itemstack:clear()
return
end
-- Backwards compatibility code end
local mtos = laptop.os_get(pos)
mtos.bdev.ram_disk = save.ram_disk or mtos.bdev.ram_disk
mtos.bdev.hard_disk = save.hard_disk or mtos.bdev.hard_disk
if save.removable_disk then
local removable = mtos.bdev:get_removable_disk()
removable:reload(ItemStack(save.removable_disk))
end
-- battery support
if have_technic or have_generator then
local node = minetest.get_node(pos)
local hwdef = laptop.node_config[node.name]
if hwdef.battery_capacity then
local metadata = minetest.deserialize(itemstack:get_metadata())
if metadata and metadata.charge then
local meta = minetest.get_meta(pos)
meta:set_int("battery", metadata.charge)
end
end
end
mtos.bdev:sync()
itemstack:clear()
end
local function preserve_metadata(pos, oldnode, oldmetadata, drops)
local mtos = laptop.os_get(pos)
if not mtos then
return
end
laptop.mtos_cache:sync_and_free(mtos)
local removable = mtos.bdev:get_removable_disk()
local save = {
laptop_ram = mtos.bdev:get_ram_disk(),
hard_disk = mtos.bdev:get_hard_disk(),
removable_disk = removable.stack and removable.stack:to_string()
}
local item_name = minetest.registered_items[oldnode.name].drop or oldnode.name
for _, stack in pairs(drops) do
if stack:get_name() == item_name then
stack:get_meta():set_string("laptop_metadata", minetest.serialize(save))
if have_technic or have_generator then
local hwdef = laptop.node_config[oldnode.name]
if hwdef.battery_capacity then
stack:set_metadata(minetest.serialize({charge=tonumber(oldmetadata.battery or "0")}))
-- calculate wear manually for support power_generators without technic
local wear = 65534*(oldmetadata.battery or 0)/hwdef.battery_capacity
if wear<1 then
wear = 1
end
if wear>65534 then
wear = 65534
end
stack:set_wear(65534-wear)
end
end
end
end
end
local function laptop_run(pos, node, mtos)
local meta = minetest.get_meta(pos)
local hwdef = mtos.hwdef
local demand = hwdef.eu_demand or 0
-- support both technic and power_generators, demand should be always same, supply should be active only one
local supply = meta:get_int("LV_EU_input") + meta:get_int("generator_input")
if have_generator and (supply>0) then
meta:set_int("generator_input", 0)
end
-- powered off, nothing to do
if (demand==0) then
return
end
if (supply<demand) and (demand>0) then
local power_off = true
if hwdef.battery_capacity then
local battery = meta:get_int("battery")
if (battery>(demand-supply)) then
meta:set_int("battery", battery - (demand - supply))
power_off = false
else
meta:set_int("battery", 0)
end
end
if power_off then
local hwdef = laptop.node_config[node.name]
if hwdef.power_off_node then
local hwdef_next = laptop.node_config[hwdef.power_off_node]
if hwdef_next.hw_state then
mtos[hwdef_next.hw_state](mtos, hwdef.power_off_node)
else
mtos:power_off(hwdef.power_off_node)
mtos:save()
end
end
end
elseif (demand>0) then
local hwdef = laptop.node_config[node.name]
if hwdef.battery_capacity then
local battery = meta:get_int("battery")
battery = battery+(hwdef.battery_charge or 400)
battery = math.min(battery, hwdef.battery_capacity)
meta:set_int("battery", battery)
end
end
end
local function technic_run(pos, node)
local mtos = laptop.os_get(pos)
if not mtos then
return
end
laptop_run(pos, node, mtos)
end
local function technic_on_disable(pos, node)
local mtos = laptop.os_get(pos)
-- fix infotext for technic mod enable
mtos:set_infotext(mtos.hwdef.infotext)
laptop_run(pos, node, mtos)
end
local tubelib2_side = {
right = "R",
left = "L",
front = "F",
back = "B",
top = "U",
bottom = "D",
}
function laptop.register_hardware(name, hwdef)
local default_nodename = name.."_"..hwdef.sequence[1]
for idx, variant in ipairs(hwdef.sequence) do
local nodename = name.."_"..variant
local def = table.copy(hwdef.node_defs[variant])
def.description = hwdef.description
-- drop the item visible in inventory
if def.groups then
def.groups = table.copy(def.groups)
else
def.groups = {choppy=2, oddly_breakably_by_hand=2, dig_immediate = 2, laptop = 1}
end
if have_technic then
def.groups.technic_machine = 1
def.groups.technic_lv = 1
end
if have_generator then
if def._eu_demand then
def.groups.laptop_generator_powered = 1
end
end
if def.connect_sides then
def.connect_sides = table.copy(def.connect_sides)
else
def.connect_sides = {"back"}
end
def._generator_connect_sides = def.connect_sides
def._generator_powered_valid_sides = {}
for _,side in pairs(def.connect_sides) do
def._generator_powered_valid_sides[tubelib2_side[side]] = true
end
if nodename ~= default_nodename then
def.drop = default_nodename
def.groups.not_in_creative_inventory = 1
end
if def.paramtype2 == "colorfacedir" and not def.palette then
def.palette = "unifieddyes_palette_redviolets.png" --TODO: Replace by own laptop specific PNG file
end
-- needed to transfer content to item if place or dig laptop
def.stack_max = 1
def.after_place_node = after_place_node
def.preserve_metadata = preserve_metadata
def.on_punch = on_punch
def.on_construct = on_construct
def.on_receive_fields = on_receive_fields
def.allow_metadata_inventory_move = allow_metadata_inventory_move
def.allow_metadata_inventory_put = allow_metadata_inventory_put
def.allow_metadata_inventory_take = allow_metadata_inventory_take
def.on_metadata_inventory_move = on_metadata_inventory_move
def.on_metadata_inventory_put = on_metadata_inventory_put
def.on_metadata_inventory_take = on_metadata_inventory_take
def.on_timer = on_timer
def.technic_run = technic_run
def.technic_on_disable = technic_on_disable
if have_technic or have_generator then
if hwdef.battery_capacity then
def.groups.not_in_creative_inventory = 1
def.drop = name.."_item"
end
end
minetest.register_node(nodename, def)
if have_technic then
technic.register_machine("LV", nodename, technic.receiver)
end
if have_generator then
local cable = power_generators.electric_cable
local sides = {}
for _,side in pairs(def._generator_connect_sides) do
table.insert(sides, tubelib2_side[side])
end
cable:add_secondary_node_names({nodename})
cable:set_valid_sides(nodename, sides)
end
-- set node configuration for hooks
local merged_hwdef = table.copy(hwdef)
merged_hwdef.name = name
merged_hwdef.nodename = nodename
for k,v in pairs(hwdef.node_defs[variant]) do
merged_hwdef[k] = v
end
local next_seq = hwdef.sequence[idx+1] or hwdef.sequence[1]
local next_node = name.."_"..next_seq
if next_node ~= nodename then
merged_hwdef.next_node = next_node
end
-- power off node
if def._power_off_seq then
local power_off_node = name.."_"..def._power_off_seq
if power_off_node ~= nodename then
merged_hwdef.power_off_node = power_off_node
end
end
-- battery charge
if def._battery_charge then
merged_hwdef.battery_charge = def._battery_charge
end
-- eu demand
if def._eu_demand then
merged_hwdef.eu_demand = def._eu_demand
end
-- Defaults
merged_hwdef.hw_capabilities = merged_hwdef.hw_capabilities or {"hdd", "floppy", "usb", "net", "liveboot"}
laptop.node_config[nodename] = merged_hwdef
end
if hwdef.battery_capacity then
if have_technic or have_generator then
local on_refill = nil
if have_technic then
technic.register_power_tool(name.."_item", hwdef.battery_capacity)
on_refill = technic.refill_RE_charge
end
minetest.register_tool(name.."_item", {
description = hwdef.description,
inventory_image = hwdef.inventory_image,
stack_max = 1,
wear_represents = "technic_RE_charge",
on_refill = on_refill,
on_place = function(itemstack, placer, pointed_thing)
itemstack:set_name(default_nodename)
minetest.item_place_node(itemstack, placer, pointed_thing)
itemstack:clear()
return itemstack
end,
})
else
minetest.register_alias(name.."_item", default_nodename)
end
end
end
if have_generator and (not have_technic) then
minetest.register_abm({
label = "Update running laptops power.",
nodenames = {"group:laptop_generator_powered"},
interval = 1,
chance = 1,
action = function(pos, node)
local def = minetest.registered_nodes[node.name]
def.technic_run(pos, node)
end,
})
end