ShadowNinja
2013-07-13 187015e0733e5e0bfa5efba215319c7d9d86f072
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
-- The enriched uranium rod driven EU generator.
-- A very large and advanced machine providing vast amounts of power.
-- Very efficient but also expensive to run as it needs uranium. (10000EU 86400 ticks (24h))
-- Provides HV EUs that can be down converted as needed.
--
-- The nuclear reactor core needs water and a protective shield to work.
-- This is checked now and then and if the machine is tampered with... BOOM!
 
local burn_ticks   = 24*60                      -- [minutes]. How many minutes does the power plant burn per serving?
local power_supply = 10000                      -- [HV] EUs
local fuel_type    = "technic:enriched_uranium" -- The reactor burns this stuff
 
 
-- FIXME: recipe must make more sense like a rod recepticle, steam chamber, HV generator?
minetest.register_craft({
    output = 'technic:hv_nuclear_reactor_core',
    recipe = {
        {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'},
        {'technic:stainless_steel_ingot',                              '', 'technic:stainless_steel_ingot'},
        {'technic:stainless_steel_ingot',              'technic:hv_cable', 'technic:stainless_steel_ingot'},
    }
})
 
minetest.register_craftitem("technic:hv_nuclear_reactor_core",{
    description = "Uranium Rod Driven HV Reactor",
    stack_max = 1,
}) 
 
local generator_formspec =
    "invsize[8,9;]"..
    --"image[0,0;5,5;technic_generator_menu.png]"..
    "label[0,0;Nuclear Reactor Rod Compartment]"..
    "list[current_name;src;2,1;3,2;]"..
    "list[current_player;main;0,5;8,4;]"
 
-- "Boxy sphere"
local nodebox = {
    { -0.353, -0.353, -0.353, 0.353, 0.353, 0.353 }, -- Box
    { -0.495, -0.064, -0.064, 0.495, 0.064, 0.064 }, -- Circle +-x
    { -0.483, -0.128, -0.128, 0.483, 0.128, 0.128 },
    { -0.462, -0.191, -0.191, 0.462, 0.191, 0.191 },
    { -0.433, -0.249, -0.249, 0.433, 0.249, 0.249 },
    { -0.397, -0.303, -0.303, 0.397, 0.303, 0.303 },
    { -0.305, -0.396, -0.305, 0.305, 0.396, 0.305 }, -- Circle +-y
    { -0.250, -0.432, -0.250, 0.250, 0.432, 0.250 },
    { -0.191, -0.461, -0.191, 0.191, 0.461, 0.191 },
    { -0.130, -0.482, -0.130, 0.130, 0.482, 0.130 },
    { -0.066, -0.495, -0.066, 0.066, 0.495, 0.066 },
    { -0.064, -0.064, -0.495, 0.064, 0.064, 0.495 }, -- Circle +-z
    { -0.128, -0.128, -0.483, 0.128, 0.128, 0.483 },
    { -0.191, -0.191, -0.462, 0.191, 0.191, 0.462 },
    { -0.249, -0.249, -0.433, 0.249, 0.249, 0.433 },
    { -0.303, -0.303, -0.397, 0.303, 0.303, 0.397 },
}
 
minetest.register_node("technic:hv_nuclear_reactor_core", {
    description = "Nuclear Reactor",
    tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
             "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
             "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
    groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
    legacy_facedir_simple = true,
    sounds = default.node_sound_wood_defaults(),
    drawtype="nodebox",
    paramtype = "light",
    node_box = {
        type = "fixed",
        fixed = nodebox
    },
    on_construct = function(pos)
        local meta = minetest.env:get_meta(pos)
        meta:set_string("infotext", "Nuclear Reactor Core")
        meta:set_float("technic_hv_power_machine", 1)
        meta:set_int("HV_EU_supply", 0)
        meta:set_int("HV_EU_from_fuel", 1) -- Signal to the switching station that this device burns some sort of fuel and needs special handling
        meta:set_int("burn_time", 0)
        meta:set_string("formspec", generator_formspec)
        local inv = meta:get_inventory()
        inv:set_size("src", 6)
    end,    
    can_dig = function(pos,player)
        local meta = minetest.env:get_meta(pos);
        local inv = meta:get_inventory()
        if not inv:is_empty("src") then
            minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
            return false
        else
            return true
        end
    end,
})
 
minetest.register_node("technic:hv_nuclear_reactor_core_active", {
    description = "Uranium Rod Driven HV Reactor",
    tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
             "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
         "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
    groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
    legacy_facedir_simple = true,
    sounds = default.node_sound_wood_defaults(),
    drop="technic:hv_nuclear_reactor_core",
    drawtype="nodebox",
    light_source = 15,
    paramtype = "light",
    node_box = {
        type = "fixed",
        fixed = nodebox
    },
    can_dig = function(pos,player)
        local meta = minetest.env:get_meta(pos);
        local inv = meta:get_inventory()
        if not inv:is_empty("src") then
            minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
            return false
        else
            return true
        end
    end,
})
 
local check_reactor_structure = function(pos)
    -- The reactor consists of an 11x11x11 cube structure
    -- A cross section through the middle:
    --  CCCCC CCCCC
    --  CCCCC CCCCC
    --  CCSSS SSSCC
    --  CCSCC CCSCC
    --  CCSCWWWCSCC
    --  CCSCW#WCSCC
    --  CCSCW|WCSCC
    --  CCSCC|CCSCC
    --  CCSSS|SSSCC
    --  CCCCC|CCCCC
    --  C = Concrete, S = Stainless Steel, W = water node (not floating), #=reactor core, |=HV cable
    --  The man-hole and the HV cable is only in the middle
    --  The man-hole is optional
 
    local source_water_nodes = minetest.find_nodes_in_area(
        {x=pos.x-1, y=pos.y-1, z=pos.z-1},
        {x=pos.x+1, y=pos.y+1, z=pos.z+1},
        "default:water_source")
    local flowing_water_nodes = minetest.find_nodes_in_area(
        {x=pos.x-1, y=pos.y-1, z=pos.z-1},
        {x=pos.x+1, y=pos.y+1, z=pos.z+1},
        "default:water_flowing")
    if not ((#source_water_nodes + #flowing_water_nodes) >= 25) then
        return false
    end
 
    local inner_shield_nodes = minetest.find_nodes_in_area(
        {x=pos.x-2, y=pos.y-2, z=pos.z-2},
        {x=pos.x+2, y=pos.y+2, z=pos.z+2},
        "technic:concrete")
    if not (#inner_shield_nodes >= 96) then
        return false
    end
 
    local steel_shield_nodes = minetest.find_nodes_in_area(
        {x=pos.x-3, y=pos.y-3, z=pos.z-3},
        {x=pos.x+3, y=pos.y+3, z=pos.z+3},
        "default:steelblock")
    if not (#steel_shield_nodes >= 216) then
        return false
    end
 
    local outer_shield_nodes = minetest.find_nodes_in_area(
        {x=pos.x-5, y=pos.y-5, z=pos.z-5},
        {x=pos.x+5, y=pos.y+5, z=pos.z+5},
        "technic:concrete")
    if not (#outer_shield_nodes >= (984 + #inner_shield_nodes)) then
        return false
    end
    return true
end
 
local explode_reactor = function(pos)
    print("BOOM A reactor exploded!")
end
 
minetest.register_abm({
    nodenames = {"technic:hv_nuclear_reactor_core", "technic:hv_nuclear_reactor_core_active"},
    interval = 1,
    chance   = 1,
    action = function(pos, node, active_object_count, active_object_count_wider)
        local meta = minetest.env:get_meta(pos)
        local burn_time = meta:get_int("burn_time")
 
        -- If more to burn and the energy produced was used: produce some more
        if burn_time > 0 then
            if not check_reactor_structure(pos) then
                explode_reactor(pos)
            end
            if meta:get_int("HV_EU_supply") == 0 then
                -- We did not use the power
                meta:set_int("HV_EU_supply", power_supply)
            else
                burn_time = burn_time - 1
                meta:set_int("burn_time", burn_time)
                local percent = math.floor(burn_time / (burn_ticks * 60) * 100)
                meta:set_string("infotext", "Nuclear Reactor Core ("..percent.."%)")
            end
        end
 
        -- Burn another piece of coal
        if burn_time <= 0 then
            local inv = meta:get_inventory()
            local correct_fuel_count = 0
            if not inv:is_empty("src") then 
                local srclist = inv:get_list("src")
                for _, srcstack in pairs(srclist) do
                    if srcstack then
                        local src_item=srcstack:to_table()
                        if src_item and src_item["name"] == fuel_type then
                            correct_fuel_count = correct_fuel_count + 1
                        end
                    end
                end
                -- Check that the reactor is complete as well as the correct number of correct fuel
                if correct_fuel_count == 6 then
                    if not check_reactor_structure(pos) then
                        burn_time = burn_ticks * 60
                        meta:set_int("burn_time", burn_time)
                        hacky_swap_node (pos,"technic:hv_nuclear_reactor_core_active") 
                        meta:set_int("HV_EU_supply", power_supply)
                        for idx, srcstack in pairs(srclist) do
                            srcstack:take_item()
                            inv:set_stack("src", idx, srcstack)
                        end
                    end
                else
                    meta:set_int("HV_EU_supply", 0)
                end
            end
        end
 
        -- Nothing left to burn
        if burn_time == 0 then
            meta:set_string("infotext", "Nuclear Reactor Core (idle)")
            hacky_swap_node(pos,"technic:hv_nuclear_reactor_core")
        end
    end
})
 
technic.register_HV_machine ("technic:hv_nuclear_reactor_core","PR")
technic.register_HV_machine ("technic:hv_nuclear_reactor_core_active","PR")