From 86ad3e7c6a37699f7f8297a387bf08af74e36629 Mon Sep 17 00:00:00 2001
From: Vanessa Ezekowitz <vanessaezekowitz@gmail.com>
Date: Fri, 1 Apr 2016 22:10:20 -0400
Subject: Update all core mods

---
 README.md                                          |   1 -
 bedrock/bar.lua                                    | 114 ++++
 bedrock/mapgen.lua                                 |  33 ++
 bedrock/textures/bedrock_bar.png                   | Bin 0 -> 406 bytes
 bedrock/textures/bedrock_bar_half.png              | Bin 0 -> 470 bytes
 bedrock/textures/bedrock_bar_space.png             | Bin 0 -> 151 bytes
 bedrock/textures/bedrock_bar_white.png             | Bin 0 -> 150 bytes
 bedrock/textures/bedrock_concrete.png              | Bin 0 -> 191 bytes
 bedrock/textures/bedrock_pick.png                  | Bin 0 -> 239 bytes
 biome_lib/README.md                                |   6 +-
 biome_lib/description.txt                          |   1 +
 biome_lib/mod.conf                                 |   1 +
 carts/functions.lua                                |   2 +-
 carts/init.lua                                     |  20 +-
 castle/description.txt                             |   1 +
 castle/mod.conf                                    |   1 +
 caverealms/config.lua                              |   2 +
 caverealms/falling_ice.lua                         |   2 +-
 caverealms/functions.lua                           |  76 ++-
 caverealms/init.lua                                |  87 ++-
 caverealms/nodes.lua                               |  40 +-
 coloredwood/description.txt                        |   1 +
 coloredwood/mod.conf                               |   1 +
 computer/tetris.lua                                |   4 +
 concrete/init.lua                                  | 206 ++------
 currency/description.txt                           |   1 +
 currency/mod.conf                                  |   1 +
 digilines_inventory/init.lua                       |   4 +-
 display_blocks/LICENSE.txt                         |  29 +
 display_blocks/description.txt                     |   1 +
 display_blocks/mod.conf                            |   1 +
 gloopblocks/description.txt                        |   2 +
 gloopblocks/init.lua                               |  24 +-
 gloopblocks/mod.conf                               |   1 +
 gloopblocks/screenshot.png                         | Bin 0 -> 140425 bytes
 ilights/description.txt                            |   1 +
 ilights/mod.conf                                   |   1 +
 .../advanced_automatic_warning_device.lua          |   2 +-
 .../infrastructure_lane_control_lights_6.png       | Bin 4160 -> 4466 bytes
 item_tweaks/item_drop.lua                          |   8 +-
 maptools/default_nodes.lua                         |   2 +-
 maptools/description.txt                           |   1 +
 maptools/mod.conf                                  |   1 +
 maptools/nodes.lua                                 |   8 +-
 mesecons/actionqueue.lua                           |  23 +-
 mesecons/init.lua                                  |   8 +-
 mesecons/internal.lua                              |  89 ++--
 mesecons/services.lua                              |   2 +-
 mesecons/settings.lua                              |  30 +-
 mesecons/util.lua                                  |  88 +++-
 mesecons/wires.lua                                 |   6 +-
 mesecons_commandblock/init.lua                     | 390 +++++++-------
 mesecons_detector/init.lua                         | 210 ++++----
 mesecons_doors/init.lua                            | 111 ++--
 mesecons_extrawires/vertical.lua                   |  32 +-
 mesecons_hydroturbine/init.lua                     |   4 +-
 mesecons_luacontroller/init.lua                    |  46 +-
 mesecons_mvps/init.lua                             |  39 +-
 mesecons_noteblock/init.lua                        |   2 +-
 mesecons_pistons/init.lua                          |  28 +-
 mesecons_pressureplates/init.lua                   |   6 +-
 mesecons_random/init.lua                           |   8 +-
 mesecons_receiver/init.lua                         |   6 +-
 mesecons_torch/init.lua                            |   2 +-
 moreblocks/circular_saw.lua                        |   6 +-
 moreblocks/description.txt                         |   1 +
 moreblocks/mod.conf                                |   1 +
 moreblocks/stairsplus/init.lua                     |   2 +-
 moreblocks/stairsplus/registrations.lua            |   8 +-
 moreores/description.txt                           |   1 +
 moreores/init.lua                                  |  24 +-
 moreores/mod.conf                                  |   1 +
 moretrees/description.txt                          |   1 +
 moretrees/mod.conf                                 |   1 +
 moretrees/screenshot.png                           | Bin 0 -> 115537 bytes
 nixie_tubes/mod.conf                               |   1 +
 pipeworks/compat.lua                               |   8 +
 pipeworks/description.txt                          |   1 +
 pipeworks/mod.conf                                 |   1 +
 pipeworks/screenshot.png                           | Bin 0 -> 92579 bytes
 prefab/description.txt                             |   1 +
 prefab/init.lua                                    |   9 +-
 prefab/mod.conf                                    |   1 +
 quartz/LICENSE.txt                                 |  21 +
 quartz/README.txt                                  |  24 +-
 quartz/depends.txt                                 |   4 +-
 quartz/description.txt                             |   1 +
 quartz/init.lua                                    | 153 +++---
 quartz/screenshot.png                              | Bin 0 -> 108271 bytes
 quartz/textures/quartz_ore.png                     | Bin 291 -> 281 bytes
 signs_lib/description.txt                          |   1 +
 signs_lib/init.lua                                 |  39 +-
 signs_lib/mod.conf                                 |   1 +
 signs_lib/screenshot.png                           | Bin 0 -> 58372 bytes
 spawn/depends.txt                                  |   0
 spawn/init.lua                                     |  52 +-
 technic/helpers.lua                                | 133 +++--
 technic/init.lua                                   |  12 +-
 technic/legacy.lua                                 |   9 +-
 technic/machines/HV/battery_box.lua                |   2 +-
 technic/machines/HV/cables.lua                     |   4 +-
 technic/machines/HV/forcefield.lua                 |   7 +-
 technic/machines/HV/generator.lua                  |   2 +-
 technic/machines/HV/nuclear_reactor.lua            | 582 +++++++++++----------
 technic/machines/HV/quarry.lua                     |   5 +-
 technic/machines/HV/solar_array.lua                |   2 +-
 technic/machines/LV/alloy_furnace.lua              |   6 +-
 technic/machines/LV/battery_box.lua                |   6 +-
 technic/machines/LV/cables.lua                     |   4 +-
 technic/machines/LV/cnc.lua                        |  37 +-
 technic/machines/LV/compressor.lua                 |   6 +-
 technic/machines/LV/electric_furnace.lua           |   2 +-
 technic/machines/LV/extractor.lua                  |   2 +-
 technic/machines/LV/generator.lua                  |   2 +-
 technic/machines/LV/geothermal.lua                 |  10 +-
 technic/machines/LV/grinder.lua                    |   2 +-
 technic/machines/LV/music_player.lua               |   6 +-
 technic/machines/LV/solar_array.lua                |   2 +-
 technic/machines/LV/solar_panel.lua                |  26 +-
 technic/machines/LV/water_mill.lua                 |   8 +-
 technic/machines/MV/alloy_furnace.lua              |   2 +-
 technic/machines/MV/battery_box.lua                |   2 +-
 technic/machines/MV/cables.lua                     |  10 +-
 technic/machines/MV/centrifuge.lua                 |   6 +-
 technic/machines/MV/compressor.lua                 |   2 +-
 technic/machines/MV/electric_furnace.lua           |   4 +-
 technic/machines/MV/extractor.lua                  |   2 +-
 technic/machines/MV/generator.lua                  |   2 +-
 technic/machines/MV/grinder.lua                    |   4 +-
 technic/machines/MV/power_radiator.lua             |  19 +-
 technic/machines/MV/solar_array.lua                |   2 +-
 technic/machines/MV/tool_workshop.lua              |   6 +-
 technic/machines/MV/wind_mill.lua                  |   7 +-
 technic/machines/register/battery_box.lua          |   6 +-
 technic/machines/register/cables.lua               | 208 ++------
 technic/machines/register/generator.lua            |  10 +-
 technic/machines/register/machine_base.lua         |  12 +-
 technic/machines/register/solar_array.lua          |   5 +-
 technic/machines/supply_converter.lua              |  18 +-
 technic/machines/switching_station.lua             |  17 +-
 technic/tools/chainsaw.lua                         |  16 +-
 technic/tools/mining_lasers.lua                    |  63 +--
 trafficlight/init.lua                              |  14 +-
 trafficlight/textures/streets_tl_left_red.png      | Bin 941 -> 945 bytes
 ufos/furnace.lua                                   |  18 +-
 ufos/init.lua                                      |  14 +-
 unified_inventory/init.lua                         |   5 +-
 unified_inventory/item_names.lua                   |   3 +
 unified_inventory/register.lua                     |  10 +-
 unifieddyes/description.txt                        |   1 +
 unifieddyes/mod.conf                               |   1 +
 vines/bower.json                                   |  18 +
 worldedit/init.lua                                 |   1 +
 worldedit/serialization.lua                        |   6 +-
 worldedit/textures/worldedit_wand.png              | Bin 0 -> 442 bytes
 worldedit/wand.lua                                 |  51 ++
 worldedit_commands/init.lua                        |  24 +
 worldedit_gui/init.lua                             |  17 +-
 158 files changed, 2083 insertions(+), 1581 deletions(-)
 create mode 100644 bedrock/bar.lua
 create mode 100644 bedrock/mapgen.lua
 create mode 100644 bedrock/textures/bedrock_bar.png
 create mode 100644 bedrock/textures/bedrock_bar_half.png
 create mode 100644 bedrock/textures/bedrock_bar_space.png
 create mode 100644 bedrock/textures/bedrock_bar_white.png
 create mode 100644 bedrock/textures/bedrock_concrete.png
 create mode 100644 bedrock/textures/bedrock_pick.png
 create mode 100644 biome_lib/description.txt
 create mode 100644 biome_lib/mod.conf
 create mode 100644 castle/description.txt
 create mode 100644 castle/mod.conf
 create mode 100644 coloredwood/description.txt
 create mode 100644 coloredwood/mod.conf
 create mode 100644 currency/description.txt
 create mode 100644 currency/mod.conf
 create mode 100644 display_blocks/LICENSE.txt
 create mode 100644 display_blocks/description.txt
 create mode 100644 display_blocks/mod.conf
 create mode 100644 gloopblocks/description.txt
 create mode 100644 gloopblocks/mod.conf
 create mode 100644 gloopblocks/screenshot.png
 create mode 100644 ilights/description.txt
 create mode 100644 ilights/mod.conf
 create mode 100644 maptools/description.txt
 create mode 100644 maptools/mod.conf
 create mode 100644 moreblocks/description.txt
 create mode 100644 moreblocks/mod.conf
 create mode 100644 moreores/description.txt
 create mode 100644 moreores/mod.conf
 create mode 100644 moretrees/description.txt
 create mode 100644 moretrees/mod.conf
 create mode 100644 moretrees/screenshot.png
 create mode 100644 nixie_tubes/mod.conf
 create mode 100644 pipeworks/description.txt
 create mode 100644 pipeworks/mod.conf
 create mode 100644 pipeworks/screenshot.png
 create mode 100644 prefab/description.txt
 create mode 100644 prefab/mod.conf
 create mode 100644 quartz/LICENSE.txt
 create mode 100644 quartz/description.txt
 create mode 100644 quartz/screenshot.png
 create mode 100644 signs_lib/description.txt
 create mode 100644 signs_lib/mod.conf
 create mode 100644 signs_lib/screenshot.png
 create mode 100644 spawn/depends.txt
 create mode 100644 unifieddyes/description.txt
 create mode 100644 unifieddyes/mod.conf
 create mode 100644 vines/bower.json
 create mode 100644 worldedit/textures/worldedit_wand.png
 create mode 100644 worldedit/wand.lua

diff --git a/README.md b/README.md
index e95e7e2..1e4088e 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1 @@
 # dreambuilder_modpack
-# dreambuilder_modpack
diff --git a/bedrock/bar.lua b/bedrock/bar.lua
new file mode 100644
index 0000000..3ec545a
--- /dev/null
+++ b/bedrock/bar.lua
@@ -0,0 +1,114 @@
+-- xPanes mod by xyz
+-- made into xbars mod by Melkor
+-- and finaly made into bedrock mod by ShadowNinja
+
+local function rshift(x, by)
+  return math.floor(x / 2 ^ by)
+end
+
+local directions = {
+    {x = 1, y = 0, z = 0},
+    {x = 0, y = 0, z = 1},
+    {x = -1, y = 0, z = 0},
+    {x = 0, y = 0, z = -1},
+}
+
+local function update_bar(pos)
+    if minetest.env:get_node(pos).name:find("bedrock:bar") == nil then
+        return
+    end
+    local sum = 0
+    for i = 1, 4 do
+        local node = minetest.env:get_node({x = pos.x + directions[i].x, y = pos.y + directions[i].y, z = pos.z + directions[i].z})
+        if minetest.registered_nodes[node.name] and (minetest.registered_nodes[node.name].walkable ~= false) then
+            sum = sum + 2 ^ (i - 1)
+        end
+    end
+    if sum == 0 then
+        sum = 15
+    end
+    minetest.env:add_node(pos, {name = "bedrock:bar_"..sum})
+end
+
+local function update_nearby_bars(pos)
+    for i = 1,4 do
+        update_bar({x = pos.x + directions[i].x, y = pos.y + directions[i].y, z = pos.z + directions[i].z})
+    end
+end
+
+local half_blocks = {
+    {0, -0.5, -0.06, 0.5, 0.5, 0.06},
+    {-0.06, -0.5, 0, 0.06, 0.5, 0.5},
+    {-0.5, -0.5, -0.06, 0, 0.5, 0.06},
+    {-0.06, -0.5, -0.5, 0.06, 0.5, 0}
+}
+
+local full_blocks = {
+    {-0.5, -0.5, -0.06, 0.5, 0.5, 0.06},
+    {-0.06, -0.5, -0.5, 0.06, 0.5, 0.5}
+}
+
+for i = 1, 15 do
+    local need = {}
+    local cnt = 0
+    for j = 1, 4 do
+        if rshift(i, j - 1) % 2 == 1 then
+            need[j] = true
+            cnt = cnt + 1
+        end
+    end
+    local take = {}
+    if need[1] == true and need[3] == true then
+        need[1] = nil
+        need[3] = nil
+        table.insert(take, full_blocks[1])
+    end
+    if need[2] == true and need[4] == true then
+        need[2] = nil
+        need[4] = nil
+        table.insert(take, full_blocks[2])
+    end
+    for k in pairs(need) do
+        table.insert(take, half_blocks[k])
+    end
+    local texture = "bedrock_bar.png"
+    if cnt == 1 then
+        texture = "bedrock_bar_half.png"
+    end
+    minetest.register_node("bedrock:bar_"..i, {
+        drawtype = "nodebox",
+        tiles = {"bedrock_bar_white.png", "bedrock_bar_white.png", texture},
+        paramtype = "light",
+        groups = {unbreakable = 1},
+        drop = "bedrock:bar",
+        node_box = {
+            type = "fixed",
+            fixed = take
+        },
+        selection_box = {
+            type = "fixed",
+            fixed = take
+        }
+    })
+end
+
+minetest.register_node("bedrock:bar", {
+    description = "Bedrock Bar",
+    tiles = {"bedrock_bar.png"},
+    inventory_image = "bedrock_bar.png",
+    wield_image = "bedrock_bar.png",
+    node_placement_prediction = "",
+    on_construct = update_bar
+})
+
+minetest.register_on_placenode(update_nearby_bars)
+minetest.register_on_dignode(update_nearby_bars)
+
+minetest.register_craft({
+	output = 'bedrock:bar 16',
+	recipe = {
+		{'bedrock:bedrock', '', 'bedrock:bedrock'},
+        	{'bedrock:bedrock', '', 'bedrock:bedrock'},
+        	{'bedrock:bedrock', '', 'bedrock:bedrock'}		
+	}
+})
diff --git a/bedrock/mapgen.lua b/bedrock/mapgen.lua
new file mode 100644
index 0000000..995bfb0
--- /dev/null
+++ b/bedrock/mapgen.lua
@@ -0,0 +1,33 @@
+
+local bedrock_depth = tonumber(minetest.setting_get("bedrock_depth")) or -30912
+local bedrock_height = tonumber(minetest.setting_get("bedrock_height")) or 5
+
+minetest.register_on_generated(function(minp, maxp)
+	if minp.y > bedrock_depth + bedrock_height or maxp.y < bedrock_depth then
+		return
+	end
+
+	local vm, mine, maxe = minetest.get_mapgen_object("voxelmanip")
+	local area = VoxelArea:new({MinEdge=mine, MaxEdge=maxe})
+	local data = vm:get_data()
+
+	local random = math.random
+
+	local c_bedrock = minetest.get_content_id("bedrock:bedrock")
+
+	local highest = math.min(bedrock_depth + bedrock_height, maxe.y)
+	local lowest = math.max(bedrock_depth, mine.y)
+
+	for y = lowest, highest do
+	for x = mine.x, maxe.x do
+	for z = mine.z, maxe.z do
+		if random(0, y - bedrock_depth) == 0 then
+			data[area:index(x, y, z)] = c_bedrock
+		end
+	end
+	end
+	end
+	vm:set_data(data)
+	vm:write_to_map()
+end)
+
diff --git a/bedrock/textures/bedrock_bar.png b/bedrock/textures/bedrock_bar.png
new file mode 100644
index 0000000..fdf4acb
Binary files /dev/null and b/bedrock/textures/bedrock_bar.png differ
diff --git a/bedrock/textures/bedrock_bar_half.png b/bedrock/textures/bedrock_bar_half.png
new file mode 100644
index 0000000..6d384a9
Binary files /dev/null and b/bedrock/textures/bedrock_bar_half.png differ
diff --git a/bedrock/textures/bedrock_bar_space.png b/bedrock/textures/bedrock_bar_space.png
new file mode 100644
index 0000000..c2e8752
Binary files /dev/null and b/bedrock/textures/bedrock_bar_space.png differ
diff --git a/bedrock/textures/bedrock_bar_white.png b/bedrock/textures/bedrock_bar_white.png
new file mode 100644
index 0000000..5c6256c
Binary files /dev/null and b/bedrock/textures/bedrock_bar_white.png differ
diff --git a/bedrock/textures/bedrock_concrete.png b/bedrock/textures/bedrock_concrete.png
new file mode 100644
index 0000000..36c7fe6
Binary files /dev/null and b/bedrock/textures/bedrock_concrete.png differ
diff --git a/bedrock/textures/bedrock_pick.png b/bedrock/textures/bedrock_pick.png
new file mode 100644
index 0000000..d66b2e3
Binary files /dev/null and b/bedrock/textures/bedrock_pick.png differ
diff --git a/biome_lib/README.md b/biome_lib/README.md
index ce539d1..dc04a73 100644
--- a/biome_lib/README.md
+++ b/biome_lib/README.md
@@ -14,8 +14,8 @@ It is primarily intended for mapgen v6, but it should work fine when used with m
 
 **Dependencies**: default from minetest_game
 
-**Recommends**: [Plantlife Modpack](https://github.com/VanessaE/plantlife_modpack), 
-[More Trees](https://github.com/VanessaE/moretrees)
+**Recommends**: [Plantlife Modpack](https://github.com/minetest-mods/plantlife_modpack), 
+[More Trees](https://github.com/minetest-mods/moretrees)
 
 **License**: WTFPL
 
@@ -27,4 +27,4 @@ It is primarily intended for mapgen v6, but it should work fine when used with m
 * biome_lib:find_valid_wall()
 * biome_lib:is_node_loaded()
 
-For a complete description of these functions as well as several of the internal variables within the mod, [read the API.txt document](https://raw.githubusercontent.com/VanessaE/biome_lib/master/API.txt) included in this package.
+For a complete description of these functions as well as several of the internal variables within the mod, [read the API.txt document](https://raw.githubusercontent.com/minetest-mods/biome_lib/master/API.txt) included in this package.
diff --git a/biome_lib/description.txt b/biome_lib/description.txt
new file mode 100644
index 0000000..0412661
--- /dev/null
+++ b/biome_lib/description.txt
@@ -0,0 +1 @@
+The biome spawning and management library for Plantlife, Moretrees, Tiny Trees, and other mods that originally depended on plants_lib from the plantlife modpack.
diff --git a/biome_lib/mod.conf b/biome_lib/mod.conf
new file mode 100644
index 0000000..7742141
--- /dev/null
+++ b/biome_lib/mod.conf
@@ -0,0 +1 @@
+name = biome_lib
diff --git a/carts/functions.lua b/carts/functions.lua
index 8a7da47..1a50d76 100644
--- a/carts/functions.lua
+++ b/carts/functions.lua
@@ -24,7 +24,7 @@ function cart_func:velocity_to_dir(v)
 end
 
 function cart_func:is_rail(p)
-	local nn = minetest.env:get_node(p).name
+	local nn = minetest.get_node(p).name
 	return minetest.get_item_group(nn, "rail") ~= 0
 end
 
diff --git a/carts/init.lua b/carts/init.lua
index a372203..90b6c5e 100644
--- a/carts/init.lua
+++ b/carts/init.lua
@@ -240,7 +240,7 @@ function cart:on_step(dtime)
 	if dir.y == 0 then
 		if math.abs(self.velocity.x) < 0.1 and  math.abs(self.velocity.z) < 0.1 then
 			-- Start the cart if powered from mesecons
-			local a = tonumber(minetest.env:get_meta(pos):get_string("cart_acceleration"))
+			local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
 			if a and a ~= 0 then
 				if self.pre_stop_dir and cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), self.pre_stop_dir), self.pre_stop_dir) then
 					self.velocity = {
@@ -333,7 +333,7 @@ function cart:on_step(dtime)
 	dir = cart_func:velocity_to_dir(self.velocity)
 	
 	-- Accelerate or decelerate the cart according to the pitch and acceleration of the rail node
-	local a = tonumber(minetest.env:get_meta(pos):get_string("cart_acceleration"))
+	local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
 	if not a then
 		a = 0
 	end
@@ -443,13 +443,13 @@ minetest.register_craftitem("carts:cart", {
 			return
 		end
 		if cart_func:is_rail(pointed_thing.under) then
-			minetest.env:add_entity(pointed_thing.under, "carts:cart")
+			minetest.add_entity(pointed_thing.under, "carts:cart")
 			if not minetest.setting_getbool("creative_mode") then
 				itemstack:take_item()
 			end
 			return itemstack
 		elseif cart_func:is_rail(pointed_thing.above) then
-			minetest.env:add_entity(pointed_thing.above, "carts:cart")
+			minetest.add_entity(pointed_thing.above, "carts:cart")
 			if not minetest.setting_getbool("creative_mode") then
 				itemstack:take_item()
 			end
@@ -506,18 +506,18 @@ minetest.register_node("carts:powerrail", {
 	
 	after_place_node = function(pos, placer, itemstack)
 		if not mesecon then
-			minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
+			minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
 		end
 	end,
 	
 	mesecons = {
 		effector = {
 			action_on = function(pos, node)
-				minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
+				minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
 			end,
 			
 			action_off = function(pos, node)
-				minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
+				minetest.get_meta(pos):set_string("cart_acceleration", "0")
 			end,
 		},
 	},
@@ -541,18 +541,18 @@ minetest.register_node("carts:brakerail", {
 	
 	after_place_node = function(pos, placer, itemstack)
 		if not mesecon then
-			minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
+			minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
 		end
 	end,
 	
 	mesecons = {
 		effector = {
 			action_on = function(pos, node)
-				minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
+				minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
 			end,
 			
 			action_off = function(pos, node)
-				minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
+				minetest.get_meta(pos):set_string("cart_acceleration", "0")
 			end,
 		},
 	},
diff --git a/castle/description.txt b/castle/description.txt
new file mode 100644
index 0000000..2399226
--- /dev/null
+++ b/castle/description.txt
@@ -0,0 +1 @@
+This is a mod all about creating castles and castle dungeons. Many of the nodes are used for the outer-walls or dungeons.
diff --git a/castle/mod.conf b/castle/mod.conf
new file mode 100644
index 0000000..759a5cf
--- /dev/null
+++ b/castle/mod.conf
@@ -0,0 +1 @@
+name = castle
diff --git a/caverealms/config.lua b/caverealms/config.lua
index 15b23d0..c4deaf2 100644
--- a/caverealms/config.lua
+++ b/caverealms/config.lua
@@ -24,6 +24,8 @@ end
 setting("number", "ymin", -33000) --bottom realm limit
 setting("number", "ymax", -700) --top realm limit
 setting("number", "tcave", 0.5) --cave threshold
+setting("number", "deepcaves_ymax", -10000) -- depth when deepcave biomes start
+setting("number", "deepdeepcaves_ymax", -20000)
 
 --falling icicles
 setting("bool", "falling_icicles", true) --enable/disable falling icicles
diff --git a/caverealms/falling_ice.lua b/caverealms/falling_ice.lua
index 4e04b5f..46b704b 100644
--- a/caverealms/falling_ice.lua
+++ b/caverealms/falling_ice.lua
@@ -177,7 +177,7 @@ function caverealms:nodeupdate_single(p, delay)
 			if delay then
 				minetest.after(0.1, caverealms.nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
 			else
-				n.level = minetest.env:get_node_level(p)
+				n.level = minetest.get_node_level(p)
 				minetest.remove_node(p)
 				caverealms:spawn_falling_node(p, n)
 				caverealms:nodeupdate(p)
diff --git a/caverealms/functions.lua b/caverealms/functions.lua
index 6c62a93..17beda7 100644
--- a/caverealms/functions.lua
+++ b/caverealms/functions.lua
@@ -119,6 +119,13 @@ function caverealms:crystal_stalagmite(x,y,z, area, data, biome)
 	local c_meseore = minetest.get_content_id("default:stone_with_mese")
 	local c_ice = minetest.get_content_id("default:ice")
 	local c_thinice = minetest.get_content_id("caverealms:thin_ice")
+	local c_obsidian = {
+		minetest.get_content_id("caverealms:obsidian"),
+		minetest.get_content_id("caverealms:obsidian_2"),
+		minetest.get_content_id("caverealms:obsidian_3"),
+		minetest.get_content_id("caverealms:obsidian_4"),
+	}
+	local c_embers = minetest.get_content_id("fake_fire:embers");
 
 	--for randomness
 	local mode = 1
@@ -132,7 +139,7 @@ function caverealms:crystal_stalagmite(x,y,z, area, data, biome)
 			mode = 1
 		end
 	end
-	if biome == 4 or biome == 5 then
+	if biome > 4 then
 		if math.random(3) == 1 then
 			mode = 2
 		end
@@ -149,22 +156,33 @@ function caverealms:crystal_stalagmite(x,y,z, area, data, biome)
  	local nid_b
 	local nid_s = c_stone --stone base, will be rewritten to ice in certain biomes
 
+	local hell = false
+
  	if biome > 3 then
- 		if mode == 1 then
- 			nid_a = c_ice
-			nid_b = c_thinice
-			nid_s = c_ice
+		if biome == 6 then
+			nid_s = c_obsidian[math.random(1, #c_obsidian)]
+			biome = 1
+			hell = true
  		else
- 			nid_a = c_crystore
-			nid_b = c_crystal
- 		end
- 	elseif mode == 1 then
- 		nid_a = stalids[biome][1][1]
- 		nid_b = stalids[biome][1][2]
- 	else
- 		nid_a = stalids[biome][2][1]
- 		nid_b = stalids[biome][2][2]
- 	end
+			if mode == 1 then
+				nid_s = c_ice
+			end
+			biome = 4
+		end
+	end
+
+	if (hell) then
+		nid_a = c_embers
+		nid_b = c_embers
+	else
+		if mode == 1 then
+			nid_a = stalids[biome][1][1]
+			nid_b = stalids[biome][1][2]
+		else
+			nid_a = stalids[biome][2][1]
+			nid_b = stalids[biome][2][2]
+		end
+	end
 
 	local top = math.random(5,H_CRY) --grab a random height for the stalagmite
 	for j = 0, top do --y
@@ -211,6 +229,13 @@ function caverealms:crystal_stalactite(x,y,z, area, data, biome)
 	local c_meseore = minetest.get_content_id("default:stone_with_mese")
 	local c_ice = minetest.get_content_id("default:ice")
 	local c_thinice = minetest.get_content_id("caverealms:hanging_thin_ice")
+	local c_obsidian = {
+		minetest.get_content_id("caverealms:obsidian"),
+		minetest.get_content_id("caverealms:obsidian_2"),
+		minetest.get_content_id("caverealms:obsidian_3"),
+		minetest.get_content_id("caverealms:obsidian_4"),
+		minetest.get_content_id("caverealms:obsidian_5"),
+	}
 
 	--for randomness
 	local mode = 1
@@ -242,15 +267,18 @@ function caverealms:crystal_stalactite(x,y,z, area, data, biome)
 	local nid_s = c_stone --stone base, will be rewritten to ice in certain biomes
 
  	if biome > 3 then
- 		if mode == 1 then
- 			nid_a = c_ice
-			nid_b = c_thinice
-			nid_s = c_ice
+		if biome == 6 then
+			nid_s = c_obsidian[math.random(1, #c_obsidian)]
+			biome = 1
  		else
- 			nid_a = c_crystore
-			nid_b = c_crystal
- 		end
- 	elseif mode == 1 then
+			if mode == 1 then
+				nid_s = c_ice
+			end
+			biome = 4
+		end
+	end
+
+ 	if mode == 1 then
  		nid_a = stalids[biome][1][1]
  		nid_b = stalids[biome][1][2]
  	else
@@ -375,4 +403,4 @@ function caverealms:legacy_giant_shroom(x, y, z, area, data) --leftovers :P
 			end
 		end
 	end
-end
\ No newline at end of file
+end
diff --git a/caverealms/init.lua b/caverealms/init.lua
index c13671b..f3b968a 100644
--- a/caverealms/init.lua
+++ b/caverealms/init.lua
@@ -25,6 +25,8 @@ end
 
 local YMIN = caverealms.config.ymin -- Approximate realm limits.
 local YMAX = caverealms.config.ymax
+local DEEPCAVES_YMAX = caverealms.config.deepcaves_ymax
+local DEEP_DEEP_CAVES_YMAZ = caverealms.config.deepdeepcaves_ymax
 local TCAVE = caverealms.config.tcave --0.5 -- Cave threshold. 1 = small rare caves, 0.5 = 1/3rd ground volume, 0 = 1/2 ground volume
 local BLEND = 128 -- Cave blend distance near YMIN, YMAX
 
@@ -87,7 +89,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	end
 
 	--easy reference to commonly used values
-	local t1 = os.clock()
+	--local t1 = os.clock()
 	local x1 = maxp.x
 	local y1 = maxp.y
 	local z1 = maxp.z
@@ -95,7 +97,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	local y0 = minp.y
 	local z0 = minp.z
 
-	print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
+	--print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
 
 	local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
 	local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
@@ -106,6 +108,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	local c_stone = minetest.get_content_id("default:stone")
 	local c_water = minetest.get_content_id("default:water_source")
 	local c_lava = minetest.get_content_id("default:lava_source")
+	local c_lava_flowing = minetest.get_content_id("default:lava_flowing")
 	local c_ice = minetest.get_content_id("default:ice")
 	local c_thinice = minetest.get_content_id("caverealms:thin_ice")
 	local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
@@ -122,6 +125,37 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	local c_worm = minetest.get_content_id("caverealms:glow_worm")
 	local c_iciu = minetest.get_content_id("caverealms:icicle_up")
 	local c_icid = minetest.get_content_id("caverealms:icicle_down")
+	local c_coal_block = minetest.get_content_id("default:coalblock")
+	local c_diamond_block = minetest.get_content_id("default:diamondblock")
+
+
+	local c_obsidian = {
+		minetest.get_content_id("caverealms:obsidian"),
+		minetest.get_content_id("caverealms:obsidian_2"),
+		minetest.get_content_id("caverealms:obsidian_3"),
+		minetest.get_content_id("caverealms:obsidian_4"),
+	}
+
+	local allow_deep_cave_biomes = false
+	if minp.y <= DEEPCAVES_YMAX then
+		allow_deep_cave_biomes = true
+	end
+
+	local c_hard_rock
+	if minetest.get_modpath("morestones") then
+		if (minp.y <= DEEP_DEEP_CAVES_YMAZ) then
+			c_hard_rock = minetest.get_content_id("morestones:travertine")
+		else
+			c_hard_rock = minetest.get_content_id("morestones:comendite")
+		end
+	elseif minetest.get_modpath("gloopblocks") then
+		c_hard_rock = minetest.get_content_id("default:basalt")
+	else
+		c_hard_rock = minetest.get_content_id("default:stone_with_diamond")
+	end
+
+
+	local deep_cave_shell_type = math.random()
 
 	--mandatory values
 	local sidelen = x1 - x0 + 1 --length of a mapblock
@@ -137,6 +171,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	local nixz = 1 --2D node index
 	local nixyz2 = 1 --second 3D index for second loop
 
+
 	for z = z0, z1 do -- for each xy plane progressing northwards
 		--structure loop
 		for y = y0, y1 do -- for each x row progressing upwards
@@ -178,14 +213,18 @@ minetest.register_on_generated(function(minp, maxp, seed)
 				n_biome = nvals_biome[nixz] --make an easier reference to the noise
 				--compare noise values to determine a biome
 				if n_biome >= 0 and n_biome < 0.5 then
-					biome = 1 --moss
+					if allow_deep_cave_biomes then --and n_biome >= 0.25 then
+						biome = 6 -- obsidian
+					else
+						biome = 1 --moss
+					end
 				elseif n_biome <= -0.5 then
 					biome = 2 --fungal
 				elseif n_biome >= 0.5 then
 					if n_biome >= 0.7 then
-						biome = 5 --deep glaciated
+						biome = 5 -- deep glaciated
 					else
-						biome = 4 --glaciated
+						biome = 4 -- glaciated
 					end
 				else
 					biome = 3 --algae
@@ -195,6 +234,22 @@ minetest.register_on_generated(function(minp, maxp, seed)
 					--ceiling
 					local ai = area:index(x,y+1,z) --above index
 					if data[ai] == c_stone and data[vi] == c_air then --ceiling
+						if biome == 6 then
+							if deep_cave_shell_type > 0.65 then
+								data[ai] = c_obsidian[math.random(1, #c_obsidian)]
+								data[vi] = c_obsidian[math.random(1, #c_obsidian)]
+							elseif deep_cave_shell_type > 0.35 then
+								data[ai] = c_coal_block
+								data[vi] = c_coal_block
+							elseif deep_cave_shell_type > 0.15 then
+								data[ai] = c_hard_rock
+								data[vi] = c_hard_rock
+							else
+								data[ai] = c_diamond_block
+								data[vi] = c_diamond_block
+							end
+						end
+
 						if math.random() < ICICHA and (biome == 4 or biome == 5) then
 							data[vi] = c_icid
 						end
@@ -261,12 +316,26 @@ minetest.register_on_generated(function(minp, maxp, seed)
 							if math.random() < ICICHA then --if glaciated, place icicles
 								data[ai] = c_iciu
 							end
+						elseif biome == 6 then
+							local bi = area:index(x,y-1,z)
+							if deep_cave_shell_type > 0.65 then
+								data[bi] = c_obsidian[math.random(1, #c_obsidian)]
+								data[vi] = c_obsidian[math.random(1, #c_obsidian)]
+							elseif deep_cave_shell_type > 0.35 then
+								data[bi] = c_coal_block
+								data[vi] = c_coal_block
+							else
+								data[bi] = c_hard_rock
+								data[vi] = c_hard_rock
+							end
+						else
+							print("[caverealms] Unknown cave biome")
 						end
 
 						if math.random() < STAGCHA then
 							caverealms:stalagmite(x,y,z, area, data)
 						end
-						if math.random() < CRYSTAL then
+						if math.random() < CRYSTAL or (biome == 6 and math.random() < CRYSTAL*1.5) then
 							caverealms:crystal_stalagmite(x,y,z, area, data, biome)
 						end
 					end
@@ -287,10 +356,10 @@ minetest.register_on_generated(function(minp, maxp, seed)
 	vm:set_lighting({day=0, night=0})
 	vm:calc_lighting()
 	--write it to world
-	vm:write_to_map(data)
+	vm:write_to_map()
 
-	local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
-	print ("[caverealms] "..chugent.." ms") --tell people how long
+	--local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
+	--print ("[caverealms] "..chugent.." ms") --tell people how long
 end)
 
 
diff --git a/caverealms/nodes.lua b/caverealms/nodes.lua
index 7588234..a1e819c 100644
--- a/caverealms/nodes.lua
+++ b/caverealms/nodes.lua
@@ -55,7 +55,7 @@ minetest.register_node("caverealms:glow_ore", {
 	is_ground_content = true,
 	groups = {cracky=2},
 	sounds = default.node_sound_glass_defaults(),
-	light_source = 10,
+	light_source = 12,
 	paramtype = "light",
 })
 
@@ -66,7 +66,7 @@ minetest.register_node("caverealms:glow_emerald_ore", {
 	is_ground_content = true,
 	groups = {cracky=2},
 	sounds = default.node_sound_glass_defaults(),
-	light_source = 10,
+	light_source = 12,
 	paramtype = "light",
 })
 
@@ -144,7 +144,7 @@ for i in ipairs(glow_gem_size) do
 		is_ground_content = true,
 		groups = {cracky=3, oddly_breakable_by_hand=1},
 		sounds = default.node_sound_glass_defaults(),
-		light_source = 11,
+		light_source = 12,
 		paramtype = "light",
 		drawtype = "plantlike",
 		walkable = false,
@@ -204,7 +204,7 @@ minetest.register_node("caverealms:stone_with_moss", {
 	description = "Cave Stone with Moss",
 	tiles = {"default_cobble.png^caverealms_moss.png", "default_cobble.png", "default_cobble.png^caverealms_moss_side.png"},
 	is_ground_content = true,
-	groups = {crumbly=3},
+	groups = {crumbly=3, soil=1},
 	drop = 'default:cobble',
 	sounds = default.node_sound_dirt_defaults({
 		footstep = {name="default_grass_footstep", gain=0.25},
@@ -216,8 +216,10 @@ minetest.register_node("caverealms:stone_with_lichen", {
 	description = "Cave Stone with Lichen",
 	tiles = {"default_cobble.png^caverealms_lichen.png", "default_cobble.png", "default_cobble.png^caverealms_lichen_side.png"},
 	is_ground_content = true,
-	groups = {crumbly=3},
+	groups = {crumbly=3, soil=1},
 	drop = 'default:cobble',
+	light_source = 2,
+	paramtype = "light",
 	sounds = default.node_sound_dirt_defaults({
 		footstep = {name="default_grass_footstep", gain=0.25},
 	}),
@@ -228,7 +230,9 @@ minetest.register_node("caverealms:stone_with_algae", {
 	description = "Cave Stone with Algae",
 	tiles = {"default_cobble.png^caverealms_algae.png", "default_cobble.png", "default_cobble.png^caverealms_algae_side.png"},
 	is_ground_content = true,
-	groups = {crumbly=3},
+	groups = {crumbly=3, soil=1},
+	light_source = 2,
+	paramtype = "light",
 	drop = 'default:cobble',
 	sounds = default.node_sound_dirt_defaults({
 		footstep = {name="default_grass_footstep", gain=0.25},
@@ -285,7 +289,7 @@ minetest.register_node("caverealms:mycena", {
 	wield_image = "caverealms_mycena.png",
 	is_ground_content = true,
 	groups = {oddly_breakable_by_hand=3},
-	light_source = 6,
+	light_source = 8,
 	paramtype = "light",
 	drawtype = "plantlike",
 	walkable = false,
@@ -323,3 +327,25 @@ minetest.register_node("caverealms:mushroom_gills", {
 	drawtype = "plantlike",
 	paramtype = "light",
 })
+
+local obsidian_glow = {7, 5, 2, 0}
+
+for i in ipairs(obsidian_glow) do
+	if i == 1 then
+		nodename = "caverealms:obsidian"
+	else
+		nodename = "caverealms:obsidian_" .. i
+	end
+	minetest.register_node(nodename, {
+		description = "Obsidian",
+		tiles = {"default_obsidian.png"},
+		is_ground_content = true,
+		sounds = default.node_sound_stone_defaults(),
+		groups = {
+			cracky=1, level=2, not_in_creative_inventory = 1
+		},
+		light_source = obsidian_glow[i],
+		drop = "default:obsidian",
+		paramtype = "light",
+	})
+end
diff --git a/coloredwood/description.txt b/coloredwood/description.txt
new file mode 100644
index 0000000..e0b1dd5
--- /dev/null
+++ b/coloredwood/description.txt
@@ -0,0 +1 @@
+This mod provides a multitude of colors of wood, sticks, and fences to Minetest, as per the palette outlined by my Unified Dyes mod.
diff --git a/coloredwood/mod.conf b/coloredwood/mod.conf
new file mode 100644
index 0000000..dc263d8
--- /dev/null
+++ b/coloredwood/mod.conf
@@ -0,0 +1 @@
+name = coloredwood
diff --git a/computer/tetris.lua b/computer/tetris.lua
index 32a0239..5a9ffed 100644
--- a/computer/tetris.lua
+++ b/computer/tetris.lua
@@ -270,6 +270,10 @@ minetest.register_node("computer:tetris_arcade", {
 	end,
 	on_place = function(itemstack, placer, pointed_thing)
 		local pos = pointed_thing.above
+		if minetest.is_protected(pos, placer:get_player_name()) or
+			minetest.is_protected({x=pos.x, y=pos.y+1, z=pos.z}, placer:get_player_name()) then
+			return itemstack
+		end
 		if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name ~= "air" then
 			minetest.chat_send_player(placer:get_player_name(), "No room for place the Arcade!")
 		return end
diff --git a/concrete/init.lua b/concrete/init.lua
index d1fa1aa..4d5e781 100644
--- a/concrete/init.lua
+++ b/concrete/init.lua
@@ -7,11 +7,14 @@ technic.concrete_posts = {}
 -- Boilerplate to support localized strings if intllib mod is installed.
 local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end
 
-minetest.register_alias("technic:concrete_post",   "technic:concrete_post0")
-minetest.register_alias("technic:concrete_post32", "technic:concrete_post12")
-minetest.register_alias("technic:concrete_post33", "technic:concrete_post3")
-minetest.register_alias("technic:concrete_post34", "technic:concrete_post28")
-minetest.register_alias("technic:concrete_post35", "technic:concrete_post19")
+for i = 0, 31 do
+	minetest.register_alias("technic:concrete_post"..i,
+			"technic:concrete_post")
+end
+for i = 32, 63 do
+	minetest.register_alias("technic:concrete_post"..i,
+			"technic:concrete_post_with_platform")
+end
 
 local steel_ingot
 if minetest.get_modpath("technic_worldgen") then
@@ -41,17 +44,17 @@ minetest.register_craft({
 minetest.register_craft({
 	output = 'technic:concrete_post_platform 6',
 	recipe = {
-		{'technic:concrete','technic:concrete_post0','technic:concrete'},
+		{'technic:concrete','technic:concrete_post','technic:concrete'},
 	}
 })
 
 minetest.register_craft({
-	output = 'technic:concrete_post0 12',
+	output = 'technic:concrete_post 12',
 	recipe = {
 		{'default:stone','technic:rebar','default:stone'},
 		{'default:stone','technic:rebar','default:stone'},
 		{'default:stone','technic:rebar','default:stone'},
-}
+	}
 })
 
 minetest.register_craft({
@@ -63,13 +66,6 @@ minetest.register_craft({
 	}
 })
 
-local box_platform = {-0.5,  0.3,  -0.5,  0.5,  0.5, 0.5}
-local box_center   = {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}
-local box_x1       = {0,     -0.3, -0.1,  0.5,  0.3, 0.1}
-local box_z1       = {-0.1,  -0.3, 0,     0.1,  0.3, 0.5}
-local box_x2       = {0,     -0.3, -0.1,  -0.5, 0.3, 0.1}
-local box_z2       = {-0.1,  -0.3, 0,     0.1,  0.3, -0.5}
-
 minetest.register_craftitem(":technic:rebar", {
 	description = S("Rebar"),
 	inventory_image = "technic_rebar.png",
@@ -80,27 +76,29 @@ minetest.register_node(":technic:concrete", {
 	tiles = {"technic_concrete_block.png",},
 	groups = {cracky=1, level=2, concrete=1},
 	sounds = default.node_sound_stone_defaults(),
-	after_place_node = function(pos, placer, itemstack)
-		technic.update_posts(pos, false)
-	end,
-	after_dig_node = function (pos, oldnode, oldmetadata, digger)
-		technic.update_posts(pos, false)
-	end,
 })
 
 minetest.register_node(":technic:blast_resistant_concrete", {
 	description = S("Blast-resistant Concrete Block"),
 	tiles = {"technic_blast_resistant_concrete_block.png",},
-	groups={cracky=1, level=3, concrete=1},
+	groups = {cracky=1, level=3, concrete=1},
 	sounds = default.node_sound_stone_defaults(),
-	after_place_node = function(pos, player, itemstack)
-		technic.update_posts(pos, false)
-	end,
-	after_dig_node = function (pos, oldnode, oldmetadata, digger)
-		technic.update_posts(pos, false)
+	on_blast = function(pos, intensity)
+		if intensity > 1 then
+			minetest.remove_node(pos)
+			minetest.add_item(pos, "technic:blast_resistant_concrete")
+		end
 	end,
 })
 
+
+local box_platform = {-0.5,  0.3,  -0.5,  0.5,  0.5, 0.5}
+local box_post     = {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}
+local box_front    = {-0.1,  -0.3, 0,     0.1,  0.3, -0.5}
+local box_back     = {-0.1,  -0.3, 0,     0.1,  0.3, 0.5}
+local box_left     = {0,     -0.3, -0.1,  -0.5, 0.3, 0.1}
+local box_right    = {0,     -0.3, -0.1,  0.5,  0.3, 0.1}
+
 minetest.register_node(":technic:concrete_post_platform", {
 	description = S("Concrete Post Platform"),
 	tiles = {"technic_concrete_block.png",},
@@ -114,161 +112,45 @@ minetest.register_node(":technic:concrete_post_platform", {
 	},
 	on_place = function (itemstack, placer, pointed_thing)
 		local node = minetest.get_node(pointed_thing.under)
-		if not technic.concrete_posts[node.name] then 
+		if node.name ~= "technic:concrete_post" then 
 			return minetest.item_place_node(itemstack, placer, pointed_thing) 
 		end
-		local links = technic.concrete_posts[node.name]
-		if links[6] ~= 0 then -- The post already has a platform
-			return minetest.item_place_node(itemstack, placer, pointed_thing) 
-		end
-		local id = technic.get_post_id({links[1], links[2], links[3], links[4], links[5], 1})
-		minetest.set_node(pointed_thing.under, {name="technic:concrete_post"..id})
+		minetest.set_node(pointed_thing.under, {name="technic:concrete_post_with_platform"})
 		itemstack:take_item()
 		placer:set_wielded_item(itemstack)
 		return itemstack
 	end,
 })
 
-local function gen_post_nodebox(x1, x2, z1, z2, y, platform)
-	local box
-	local xx = x1 + x2
-	local zz = z1 + z2
-	if ((xx == 2 and zz == 0) or (xx == 0 and zz == 2)) and y == 0 then
-		box = {}
-	else 
-		box = {box_center}
-	end
-	if x1 ~= 0 then
-		table.insert(box, box_x1)
-	end
-	if x2 ~= 0 then
-		table.insert(box, box_x2)
-	end
-	if z1 ~= 0 then
-		table.insert(box, box_z1)
-	end
-	if z2 ~= 0 then
-		table.insert(box, box_z2)
-	end
-	if platform ~= 0 then
-		table.insert(box, box_platform)
-	end
-	return box
-end
-
-local function dig_post_with_platform(pos, oldnode, oldmetadata)
-	oldnode.name = "technic:concrete_post0"
-	minetest.set_node(pos, oldnode)
-	technic.update_posts(pos, true)
-end
-
-function technic.posts_should_connect(pos)
-	local node = minetest.get_node(pos)
-	if technic.concrete_posts[node.name] then
-		return "post"
-	elseif minetest.get_item_group(node.name, "concrete") ~= 0 then
-		return "block"
-	end
-end
-
-function technic.get_post_id(links)
-	return (links[1] * 1) + (links[2] * 2)
-		+ (links[3] * 4) + (links[4] * 8)
-		+ (links[5] * 16) + (links[6] * 32)
-end
-
-function technic.update_posts(pos, set, secondrun)
-	local node = minetest.get_node(pos)
-	local link_positions = {
-		{x=pos.x+1, y=pos.y,   z=pos.z},
-		{x=pos.x-1, y=pos.y,   z=pos.z},
-		{x=pos.x,   y=pos.y,   z=pos.z+1},
-		{x=pos.x,   y=pos.y,   z=pos.z-1},
-		{x=pos.x,   y=pos.y-1,   z=pos.z},
-		{x=pos.x,   y=pos.y+1,   z=pos.z},
-	}
-
-	local links = {0, 0, 0, 0, 0, 0}
-
-	for i, link_pos in pairs(link_positions) do
-		local connecttype = technic.posts_should_connect(link_pos)
-		if connecttype then
-			links[i] = 1
-			-- Have posts next to us update theirselves,
-			-- but only once. (We don't want to start an
-			-- infinite loop of updates)
-			if not secondrun and connecttype == "post" then
-				technic.update_posts(link_pos, true, true)
-			end
-		end
-	end
-
-	if links[5] == 1 or links[6] == 1 then
-		links[5] = 1
-		links[6] = 0
-	end
-
-	-- We don't want to set ourselves if we have been removed or we are
-	-- updating a concrete node
-	if set then
-		-- Preserve platform
-		local oldlinks = technic.concrete_posts[node.name]
-		if oldlinks then
-			links[6] = oldlinks[6]
-		end
-		minetest.set_node(pos, {name="technic:concrete_post"
-				..technic.get_post_id(links)})
-	end
-end
-
-for x1 = 0, 1 do
-for x2 = 0, 1 do
-for z1 = 0, 1 do
-for z2 = 0, 1 do
-for y = 0, 1 do
 for platform = 0, 1 do
-	local links = {x1, x2, z1, z2, y, platform}
-	local id = technic.get_post_id(links)
-	technic.concrete_posts["technic:concrete_post"..id] = links
-
-	local groups = {cracky=1, level=2, concrete_post=1}
-	if id ~= 0 then
-		groups.not_in_creative_inventory = 1
-	end
-	
-	local drop = "technic:concrete_post0"
-	local after_dig_node = function(pos, oldnode, oldmetadata, digger)
-		technic.update_posts(pos, false)
-	end
-	if platform ~= 0 then
-		drop = "technic:concrete_post_platform"
-		after_dig_node = function(pos, oldnode, oldmetadata, digger)
-			dig_post_with_platform(pos, oldnode, oldmetadata)
+	local after_dig_node = nil
+	if platform == 1 then
+		after_dig_node = function(pos, old_node)
+			old_node.name = "technic:concrete_post"
+			minetest.set_node(pos, old_node)
 		end
 	end
 
-	minetest.register_node(":technic:concrete_post"..id, {
+	minetest.register_node(":technic:concrete_post"..(platform == 1 and "_with_platform" or ""), {
 		description = S("Concrete Post"),
 		tiles = {"technic_concrete_block.png"},
-		groups = groups,
+		groups = {cracky=1, level=2, concrete_post=1, not_in_creative_inventory=platform},
 		sounds = default.node_sound_stone_defaults(),
-		drop = drop,
+		drop = (platform == 1 and "technic:concrete_post_platform" or
+				"technic:concrete_post"),
 		paramtype = "light",
 		sunlight_propagates = true,
-		drawtype = "nodebox", 
+		drawtype = "nodebox",
+		connects_to = {"group:concrete", "group:concrete_post"},
 		node_box = {
-			type = "fixed",
-			fixed = gen_post_nodebox(x1, x2, z1, z2, y, platform),
+			type = "connected",
+			fixed = {box_post, (platform == 1 and box_platform or nil)},
+			connect_front = box_front,
+			connect_back  = box_back,
+			connect_left  = box_left,
+			connect_right = box_right,
 		},
-		after_place_node = function(pos, placer, itemstack)
-			technic.update_posts(pos, true)
-		end,
 		after_dig_node = after_dig_node,
 	})
 end
-end
-end
-end
-end
-end
 
diff --git a/currency/description.txt b/currency/description.txt
new file mode 100644
index 0000000..aca9890
--- /dev/null
+++ b/currency/description.txt
@@ -0,0 +1 @@
+Provides shops, barter tables, safes, and three denominations of currency, called "Minegeld".
diff --git a/currency/mod.conf b/currency/mod.conf
new file mode 100644
index 0000000..6679a26
--- /dev/null
+++ b/currency/mod.conf
@@ -0,0 +1 @@
+name = currency
diff --git a/digilines_inventory/init.lua b/digilines_inventory/init.lua
index 89aaabc..a8e7ecf 100644
--- a/digilines_inventory/init.lua
+++ b/digilines_inventory/init.lua
@@ -127,7 +127,9 @@ minetest.register_node("digilines_inventory:chest", {
 		minetest.log("action", player:get_player_name().." puts stuff into chest at "..minetest.pos_to_string(pos))
 	end,
 	on_metadata_inventory_take = function(pos, listname, index, stack, player)
-		local inv = minetest.get_meta(pos):get_inventory()
+		local meta = minetest.get_meta(pos)
+		local channel = meta:get_string("channel")
+		local inv = meta:get_inventory()
 		if inv:is_empty(listname) then
 			sendMessage(pos, "empty", channel)
 		end
diff --git a/display_blocks/LICENSE.txt b/display_blocks/LICENSE.txt
new file mode 100644
index 0000000..ff49e2d
--- /dev/null
+++ b/display_blocks/LICENSE.txt
@@ -0,0 +1,29 @@
+
+License:
+
+Copyright (C) 2016 - VanessaE, cheapie, jojoa1997
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject
+to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the authors shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the authors.
+
diff --git a/display_blocks/description.txt b/display_blocks/description.txt
new file mode 100644
index 0000000..af7e923
--- /dev/null
+++ b/display_blocks/description.txt
@@ -0,0 +1 @@
+This mod adds blocks that create crystals on top. Some have different light levels others can be seen through and i hope i can make them do other things too.
diff --git a/display_blocks/mod.conf b/display_blocks/mod.conf
new file mode 100644
index 0000000..2ccbba4
--- /dev/null
+++ b/display_blocks/mod.conf
@@ -0,0 +1 @@
+name = display_blocks
diff --git a/gloopblocks/description.txt b/gloopblocks/description.txt
new file mode 100644
index 0000000..c514a8e
--- /dev/null
+++ b/gloopblocks/description.txt
@@ -0,0 +1,2 @@
+Adds decorative and functional blocks, including cement, rainbow blocks, "evil" blocks and sticks, 
+and the usual collection of tools of various strengths and speeds made from either cement or "evil" components.
diff --git a/gloopblocks/init.lua b/gloopblocks/init.lua
index e806118..0d14764 100644
--- a/gloopblocks/init.lua
+++ b/gloopblocks/init.lua
@@ -753,18 +753,18 @@ if minetest.setting_getbool("gloopblocks_lavacooling") ~= false then
 		return false
 	end
 
-	default.cool_lava_source = function(pos)
-		if gloopblocks_search_nearby_nodes(pos,"default:water_source")
-		or gloopblocks_search_nearby_nodes(pos,"default:water_flowing") then
-			minetest.set_node(pos, {name="gloopblocks:obsidian_cooled"})
-		end
-	end
-
-	default.cool_lava_flowing = function(pos)
-		if gloopblocks_search_nearby_nodes(pos,"default:water_source") then
-			minetest.set_node(pos, {name="gloopblocks:basalt_cooled"})
-		elseif gloopblocks_search_nearby_nodes(pos,"default:water_flowing") then
-			minetest.set_node(pos, {name="gloopblocks:pumice_cooled"})
+	default.cool_lava = function(pos, node)
+		if node.name == "default:lava_source" then
+			if gloopblocks_search_nearby_nodes(pos,"default:water_source")
+			or gloopblocks_search_nearby_nodes(pos,"default:water_flowing") then
+				minetest.set_node(pos, {name="gloopblocks:obsidian_cooled"})
+			end
+		else -- Lava flowing
+			if gloopblocks_search_nearby_nodes(pos,"default:water_source") then
+				minetest.set_node(pos, {name="gloopblocks:basalt_cooled"})
+			elseif gloopblocks_search_nearby_nodes(pos,"default:water_flowing") then
+				minetest.set_node(pos, {name="gloopblocks:pumice_cooled"})
+			end
 		end
 	end
 end
diff --git a/gloopblocks/mod.conf b/gloopblocks/mod.conf
new file mode 100644
index 0000000..e68d383
--- /dev/null
+++ b/gloopblocks/mod.conf
@@ -0,0 +1 @@
+name = gloopblocks
diff --git a/gloopblocks/screenshot.png b/gloopblocks/screenshot.png
new file mode 100644
index 0000000..edec75a
Binary files /dev/null and b/gloopblocks/screenshot.png differ
diff --git a/ilights/description.txt b/ilights/description.txt
new file mode 100644
index 0000000..18f81db
--- /dev/null
+++ b/ilights/description.txt
@@ -0,0 +1 @@
+Adds various lights.
diff --git a/ilights/mod.conf b/ilights/mod.conf
new file mode 100644
index 0000000..3ce7bed
--- /dev/null
+++ b/ilights/mod.conf
@@ -0,0 +1 @@
+name = ilights
diff --git a/infrastructure/advanced_automatic_warning_device.lua b/infrastructure/advanced_automatic_warning_device.lua
index b938c07..786f527 100644
--- a/infrastructure/advanced_automatic_warning_device.lua
+++ b/infrastructure/advanced_automatic_warning_device.lua
@@ -226,7 +226,7 @@ minetest.register_node("infrastructure:automatic_warning_device_middle_center_on
 	drawtype = "nodebox",
 	paramtype = "light",
 	paramtype2 = "facedir",
-	light_source = LIGHT_SOURCE,
+	light_source = AUTOMATIC_WARNING_DEVICE_LIGHT_RANGE,
 	node_box = {
 		type = "fixed",
 		fixed = {
diff --git a/infrastructure/textures/infrastructure_lane_control_lights_6.png b/infrastructure/textures/infrastructure_lane_control_lights_6.png
index 6e149d7..0838d91 100644
Binary files a/infrastructure/textures/infrastructure_lane_control_lights_6.png and b/infrastructure/textures/infrastructure_lane_control_lights_6.png differ
diff --git a/item_tweaks/item_drop.lua b/item_tweaks/item_drop.lua
index beed1c7..aa0e9d0 100644
--- a/item_tweaks/item_drop.lua
+++ b/item_tweaks/item_drop.lua
@@ -56,7 +56,7 @@ local function pickup(player, inv, object, pickupRadius)
 
 	-- itemstring is serialized item so includes metadata
 	local lua = object:get_luaentity()
-	item = ItemStack(lua.itemstring)
+	local item = ItemStack(lua.itemstring)
 	if inv and inv:room_for_item("main", item) then
 		inv:add_item("main", item)
 		if object:get_luaentity().itemstring ~= "" then
@@ -126,8 +126,8 @@ local function moveTowards(object, player, pickupRadius, attractRadius)
 	pos1.y = pos1.y+0.5 -- head towards player's belt
 	local direct = vector.subtract(pos1, pos2)
 	local R = vector.length(direct)
-	v = object:getvelocity()
-	stopped = v.x == 0 and v.y == 0 and v.z == 0
+	local v = object:getvelocity()
+	local stopped = v.x == 0 and v.y == 0 and v.z == 0
 	-- when direction(X) = direction(V) we passed the player
 	-- so project V onto X. If same, passed. If not, approaching.
 	-- projection = norm(X) * (length(V) * cos(theta))
@@ -209,7 +209,7 @@ if minetest.setting_get("enable_item_pickup") == "true" then
 								minetest.after(30, function(object)
 									-- only if it's still moving
 									-- but what if it started moving a second time?
-									pair = movers[object]
+									local pair = movers[object]
 									if pair and pair[2] == ticket then
 										stop(object)
 									end
diff --git a/maptools/default_nodes.lua b/maptools/default_nodes.lua
index 7c1e135..0432306 100644
--- a/maptools/default_nodes.lua
+++ b/maptools/default_nodes.lua
@@ -372,7 +372,7 @@ minetest.register_node("maptools:soil_wet", {
 	description = "Wet Soil",
 	range = 12,
 	stack_max = 10000,
-	tiles = {"farming_soil_wet.png", "farming_soil_wet_side.png"},
+	tiles = {"default_dirt.png^farming_soil_wet.png", "default_dirt.png^farming_soil_wet_side.png"},
 	drop = "",
 	groups = {unbreakable = 1, not_in_creative_inventory = maptools.creative, soil = 3, wet = 1, grassland = 1},
 	sounds = default.node_sound_dirt_defaults(),
diff --git a/maptools/description.txt b/maptools/description.txt
new file mode 100644
index 0000000..43bbfde
--- /dev/null
+++ b/maptools/description.txt
@@ -0,0 +1 @@
+Adds various special versions of normal blocks, tools, and other map maintainer tools.
diff --git a/maptools/mod.conf b/maptools/mod.conf
new file mode 100644
index 0000000..a77ffe2
--- /dev/null
+++ b/maptools/mod.conf
@@ -0,0 +1 @@
+name = maptools
diff --git a/maptools/nodes.lua b/maptools/nodes.lua
index 8ceef64..744f105 100644
--- a/maptools/nodes.lua
+++ b/maptools/nodes.lua
@@ -280,7 +280,7 @@ minetest.register_node("maptools:climb", {
 	description = S("Climb Block"),
 	range = 12,
 	stack_max = 10000,
-	inventory_image = "default_steel_block.png^default_ladder.png",
+	inventory_image = "default_steel_block.png^default_ladder_wood.png",
 	drawtype = "airlike",
 	walkable = false,
 	climbable = true,
@@ -341,9 +341,9 @@ minetest.register_node("maptools:ladder", {
 	range = 12,
 	stack_max = 10000,
 	drawtype = "signlike",
-	tiles = {"default_ladder.png"},
-	inventory_image = "default_ladder.png",
-	wield_image = "default_ladder.png",
+	tiles = {"default_ladder_wood.png"},
+	inventory_image = "default_ladder_wood.png",
+	wield_image = "default_ladder_wood.png",
 	paramtype = "light",
 	paramtype2 = "wallmounted",
 	walkable = false,
diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua
index fa4079f..e300ea7 100644
--- a/mesecons/actionqueue.lua
+++ b/mesecons/actionqueue.lua
@@ -23,7 +23,7 @@ function mesecon.queue:add_action(pos, func, params, time, overwritecheck, prior
 	-- Otherwise, add the action to the queue
 	if overwritecheck then -- check if old action has to be overwritten / removed:
 		for i, ac in ipairs(mesecon.queue.actions) do
-			if(mesecon.cmpPos(pos, ac.pos)
+			if(vector.equals(pos, ac.pos)
 			and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
 				toremove = i
 				break
@@ -94,25 +94,8 @@ end
 -- Store and read the ActionQueue to / from a file
 -- so that upcoming actions are remembered when the game
 -- is restarted
-
-local wpath = minetest.get_worldpath()
-local function file2table(filename)
-	local f = io.open(filename, "r")
-	if f==nil then return {} end
-	local t = f:read("*all")
-	f:close()
-	if t=="" or t==nil then return {} end
-	return minetest.deserialize(t)
-end
-
-local function table2file(filename, table)
-	local f = io.open(filename, "w")
-	f:write(minetest.serialize(table))
-	f:close()
-end
-
-mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue")
+mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue")
 
 minetest.register_on_shutdown(function()
-	mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions)
+	mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions)
 end)
diff --git a/mesecons/init.lua b/mesecons/init.lua
index 8645f03..3ab4f4a 100644
--- a/mesecons/init.lua
+++ b/mesecons/init.lua
@@ -74,7 +74,7 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
 
 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = mesecon.addPosRule(pos, rule)
+		local np = vector.add(pos, rule)
 		-- if area is not loaded, keep trying
 		if minetest.get_node_or_nil(np) == nil then
 			mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
@@ -84,7 +84,7 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
 
 	-- execute action
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = mesecon.addPosRule(pos, rule)
+		local np = vector.add(pos, rule)
 		local rulenames = mesecon.rules_link_rule_all(pos, rule)
 		for _, rulename in ipairs(rulenames) do
 			mesecon.turnon(np, rulename)
@@ -101,7 +101,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
 
 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = mesecon.addPosRule(pos, rule)
+		local np = vector.add(pos, rule)
 		if minetest.get_node_or_nil(np) == nil then
 			mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
 			return
@@ -109,7 +109,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
 	end
 
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = mesecon.addPosRule(pos, rule)
+		local np = vector.add(pos, rule)
 		local rulenames = mesecon.rules_link_rule_all(pos, rule)
 		for _, rulename in ipairs(rulenames) do
 			if not mesecon.connected_to_receptor(np, mesecon.invertRule(rule)) then
diff --git a/mesecons/internal.lua b/mesecons/internal.lua
index 741abf1..d479852 100644
--- a/mesecons/internal.lua
+++ b/mesecons/internal.lua
@@ -77,6 +77,8 @@ function mesecon.get_conductor(nodename)
 end
 
 function mesecon.get_any_outputrules (node)
+	if not node then return nil end
+
 	if mesecon.is_conductor(node.name) then
 		return mesecon.conductor_get_rules(node)
 	elseif mesecon.is_receptor(node.name) then
@@ -85,6 +87,8 @@ function mesecon.get_any_outputrules (node)
 end
 
 function mesecon.get_any_inputrules (node)
+	if not node then return nil end
+
 	if mesecon.is_conductor(node.name) then
 		return mesecon.conductor_get_rules(node)
 	elseif mesecon.is_effector(node.name) then
@@ -182,7 +186,9 @@ end
 
 -- Activation:
 mesecon.queue:add_function("activate", function (pos, rulename)
-	local node = minetest.get_node(pos)
+	local node = mesecon.get_node_force(pos)
+	if not node then return end
+
 	local effector = mesecon.get_effector(node.name)
 
 	if effector and effector.action_on then
@@ -203,7 +209,9 @@ end
 
 -- Deactivation
 mesecon.queue:add_function("deactivate", function (pos, rulename)
-	local node = minetest.get_node(pos)
+	local node = mesecon.get_node_force(pos)
+	if not node then return end
+
 	local effector = mesecon.get_effector(node.name)
 
 	if effector and effector.action_off then
@@ -224,7 +232,9 @@ end
 
 -- Change
 mesecon.queue:add_function("change", function (pos, rulename, changetype)
-	local node = minetest.get_node(pos)
+	local node = mesecon.get_node_force(pos)
+	if not node then return end
+
 	local effector = mesecon.get_effector(node.name)
 
 	if effector and effector.action_change then
@@ -249,6 +259,8 @@ end
 -- Conductors
 
 function mesecon.is_conductor_on(node, rulename)
+	if not node then return false end
+
 	local conductor = mesecon.get_conductor(node.name)
 	if conductor then
 		if conductor.state then
@@ -263,10 +275,13 @@ function mesecon.is_conductor_on(node, rulename)
 			return mesecon.get_bit(binstate, bit)
 		end
 	end
+
 	return false
 end
 
 function mesecon.is_conductor_off(node, rulename)
+	if not node then return false end
+
 	local conductor = mesecon.get_conductor(node.name)
 	if conductor then
 		if conductor.state then
@@ -281,6 +296,7 @@ function mesecon.is_conductor_off(node, rulename)
 			return not mesecon.get_bit(binstate, bit)
 		end
 	end
+
 	return false
 end
 
@@ -340,16 +356,16 @@ end
 -- some more general high-level stuff
 
 function mesecon.is_power_on(pos, rulename)
-	local node = minetest.get_node(pos)
-	if mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name) then
+	local node = mesecon.get_node_force(pos)
+	if node and (mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name)) then
 		return true
 	end
 	return false
 end
 
 function mesecon.is_power_off(pos, rulename)
-	local node = minetest.get_node(pos)
-	if mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name) then
+	local node = mesecon.get_node_force(pos)
+	if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then
 		return true
 	end
 	return false
@@ -361,7 +377,7 @@ function mesecon.turnon(pos, link)
 	local depth = 1
 	while frontiers[depth] do
 		local f = frontiers[depth]
-		local node = minetest.get_node_or_nil(f.pos)
+		local node = mesecon.get_node_force(f.pos)
 
 		-- area not loaded, postpone action
 		if not node then
@@ -374,10 +390,10 @@ function mesecon.turnon(pos, link)
 
 			-- call turnon on neighbors: normal rules
 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
-				local np = mesecon.addPosRule(f.pos, r)
+				local np = vector.add(f.pos, r)
 
 				-- area not loaded, postpone action
-				if not minetest.get_node_or_nil(np) then
+				if not mesecon.get_node_force(np) then
 					mesecon.queue:add_action(np, "turnon", {rulename},
 						nil, true)
 				else
@@ -407,7 +423,7 @@ function mesecon.turnoff(pos, link)
 	local depth = 1
 	while frontiers[depth] do
 		local f = frontiers[depth]
-		local node = minetest.get_node_or_nil(f.pos)
+		local node = mesecon.get_node_force(f.pos)
 
 		-- area not loaded, postpone action
 		if not node then
@@ -420,10 +436,10 @@ function mesecon.turnoff(pos, link)
 
 			-- call turnoff on neighbors: normal rules
 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
-				local np = mesecon.addPosRule(f.pos, r)
+				local np = vector.add(f.pos, r)
 
 				-- area not loaded, postpone action
-				if not minetest.get_node_or_nil(np) then
+				if not mesecon.get_node_force(np) then
 					mesecon.queue:add_action(np, "turnoff", {rulename},
 						nil, true)
 				else
@@ -449,7 +465,8 @@ end)
 
 
 function mesecon.connected_to_receptor(pos, link)
-	local node = minetest.get_node(pos)
+	local node = mesecon.get_node_force(pos)
+	if not node then return false end
 
 	-- Check if conductors around are connected
 	local rules = mesecon.get_any_inputrules(node)
@@ -458,7 +475,7 @@ function mesecon.connected_to_receptor(pos, link)
 	for _, rule in ipairs(mesecon.rule2meta(link, rules)) do
 		local links = mesecon.rules_link_rule_all_inverted(pos, rule)
 		for _, l in ipairs(links) do
-			local np = mesecon.addPosRule(pos, l)
+			local np = vector.add(pos, l)
 			if mesecon.find_receptor_on(np, mesecon.invertRule(l)) then
 				return true
 			end
@@ -476,7 +493,7 @@ function mesecon.find_receptor_on(pos, link)
 	local depth = 1
 	while frontiers[depth] do
 		local f = frontiers[depth]
-		local node = minetest.get_node_or_nil(f.pos)
+		local node = mesecon.get_node_force(f.pos)
 
 		if not node then return false end
 		if mesecon.is_receptor_on(node.name) then return true end
@@ -485,7 +502,7 @@ function mesecon.find_receptor_on(pos, link)
 
 			-- call turnoff on neighbors: normal rules
 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
-				local np = mesecon.addPosRule(f.pos, r)
+				local np = vector.add(f.pos, r)
 
 				local links = mesecon.rules_link_rule_all_inverted(f.pos, r)
 				for _, l in ipairs(links) do
@@ -503,8 +520,9 @@ function mesecon.find_receptor_on(pos, link)
 end
 
 function mesecon.rules_link(output, input, dug_outputrules) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule
-	local outputnode = minetest.get_node(output)
-	local inputnode = minetest.get_node(input)
+	local outputnode = mesecon.get_node_force(output)
+	local inputnode = mesecon.get_node_force(input)
+
 	local outputrules = dug_outputrules or mesecon.get_any_outputrules (outputnode)
 	local inputrules = mesecon.get_any_inputrules (inputnode)
 	if not outputrules or not inputrules then
@@ -513,21 +531,22 @@ function mesecon.rules_link(output, input, dug_outputrules) --output/input are p
 
 	for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
 		-- Check if output sends to input
-		if mesecon.cmpPos(mesecon.addPosRule(output, outputrule), input) then
+		if vector.equals(vector.add(output, outputrule), input) then
 			for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
 				-- Check if input accepts from output
-				if  mesecon.cmpPos(mesecon.addPosRule(input, inputrule), output) then
+				if  vector.equals(vector.add(input, inputrule), output) then
 					return true, inputrule
 				end
 			end
 		end
 	end
+
 	return false
 end
 
 function mesecon.rules_link_rule_all(output, rule)
-	local input = mesecon.addPosRule(output, rule)
-	local inputnode = minetest.get_node(input)
+	local input = vector.add(output, rule)
+	local inputnode = mesecon.get_node_force(input)
 	local inputrules = mesecon.get_any_inputrules (inputnode)
 	if not inputrules then
 		return {}
@@ -536,17 +555,18 @@ function mesecon.rules_link_rule_all(output, rule)
 
 	for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
 		-- Check if input accepts from output
-		if  mesecon.cmpPos(mesecon.addPosRule(input, inputrule), output) then
+		if  vector.equals(vector.add(input, inputrule), output) then
 			table.insert(rules, inputrule)
 		end
 	end
+
 	return rules
 end
 
 function mesecon.rules_link_rule_all_inverted(input, rule)
 	--local irule = mesecon.invertRule(rule)
-	local output = mesecon.addPosRule(input, rule)
-	local outputnode = minetest.get_node(output)
+	local output = vector.add(input, rule)
+	local outputnode = mesecon.get_node_force(output)
 	local outputrules = mesecon.get_any_outputrules (outputnode)
 	if not outputrules then
 		return {}
@@ -554,7 +574,7 @@ function mesecon.rules_link_rule_all_inverted(input, rule)
 	local rules = {}
 
 	for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
-		if  mesecon.cmpPos(mesecon.addPosRule(output, outputrule), input) then
+		if  vector.equals(vector.add(output, outputrule), input) then
 			table.insert(rules, mesecon.invertRule(outputrule))
 		end
 	end
@@ -566,7 +586,7 @@ function mesecon.rules_link_anydir(pos1, pos2)
 end
 
 function mesecon.is_powered(pos, rule)
-	local node = minetest.get_node(pos)
+	local node = mesecon.get_node_force(pos)
 	local rules = mesecon.get_any_inputrules(node)
 	if not rules then return false end
 
@@ -577,10 +597,11 @@ function mesecon.is_powered(pos, rule)
 		for _, rule in ipairs(mesecon.flattenrules(rules)) do
 			local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
 			for _, rname in ipairs(rulenames) do
-				local np = mesecon.addPosRule(pos, rname)
-				local nn = minetest.get_node(np)
-				if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname))
-				or mesecon.is_receptor_on (nn.name)) then
+				local np = vector.add(pos, rname)
+				local nn = mesecon.get_node_force(np)
+
+				if (mesecon.is_conductor_on(nn, mesecon.invertRule(rname))
+				or mesecon.is_receptor_on(nn.name)) then
 					table.insert(sourcepos, np)
 				end
 			end
@@ -588,8 +609,8 @@ function mesecon.is_powered(pos, rule)
 	else
 		local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
 		for _, rname in ipairs(rulenames) do
-			local np = mesecon.addPosRule(pos, rname)
-			local nn = minetest.get_node(np)
+			local np = vector.add(pos, rname)
+			local nn = mesecon.get_node_force(np)
 			if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname))
 			or mesecon.is_receptor_on (nn.name)) then
 				table.insert(sourcepos, np)
diff --git a/mesecons/services.lua b/mesecons/services.lua
index 215fb31..5d0f81e 100644
--- a/mesecons/services.lua
+++ b/mesecons/services.lua
@@ -16,7 +16,7 @@ mesecon.on_placenode = function (pos, node)
 			-- also call receptor_on if itself is powered already, so that neighboring
 			-- conductors will be activated (when pushing an on-conductor with a piston)
 			for _, s in ipairs(sources) do
-				local rule = {x = pos.x - s.x, y = pos.y - s.y, z = pos.z - s.z}
+				local rule = vector.subtract(pos, s)
 				mesecon.turnon(pos, rule)
 			end
 			--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
diff --git a/mesecons/settings.lua b/mesecons/settings.lua
index 50240c3..1ebbfde 100644
--- a/mesecons/settings.lua
+++ b/mesecons/settings.lua
@@ -1,15 +1,15 @@
--- SETTINGS
-function mesecon.setting(setting, default)
-	if type(default) == "boolean" then
-		local read = minetest.setting_getbool("mesecon."..setting)
-		if read == nil then
-			return default
-		else
-			return read
-		end
-	elseif type(default) == "string" then
-		return minetest.setting_get("mesecon."..setting) or default
-	elseif type(default) == "number" then
-		return tonumber(minetest.setting_get("mesecon."..setting) or default)
-	end
-end
+-- SETTINGS
+function mesecon.setting(setting, default)
+	if type(default) == "boolean" then
+		local read = minetest.setting_getbool("mesecon."..setting)
+		if read == nil then
+			return default
+		else
+			return read
+		end
+	elseif type(default) == "string" then
+		return minetest.setting_get("mesecon."..setting) or default
+	elseif type(default) == "number" then
+		return tonumber(minetest.setting_get("mesecon."..setting) or default)
+	end
+end
diff --git a/mesecons/util.lua b/mesecons/util.lua
index dd33f1c..3827dce 100644
--- a/mesecons/util.lua
+++ b/mesecons/util.lua
@@ -2,7 +2,7 @@ function mesecon.move_node(pos, newpos)
 	local node = minetest.get_node(pos)
 	local meta = minetest.get_meta(pos):to_table()
 	minetest.remove_node(pos)
-	minetest.add_node(newpos, node)
+	minetest.set_node(newpos, node)
 	minetest.get_meta(pos):from_table(meta)
 end
 
@@ -50,7 +50,7 @@ function mesecon.rule2bit(findrule, allrules)
 	end
 	for m,metarule in ipairs( allrules) do
 	for _,    rule in ipairs(metarule ) do
-		if mesecon.cmpPos(findrule, rule) then
+		if vector.equals(findrule, rule) then
 			return m
 		end
 	end
@@ -69,7 +69,7 @@ function mesecon.rule2metaindex(findrule, allrules)
 
 	for m, metarule in ipairs( allrules) do
 	for _,     rule in ipairs(metarule ) do
-		if mesecon.cmpPos(findrule, rule) then
+		if vector.equals(findrule, rule) then
 			return m
 		end
 	end
@@ -133,15 +133,7 @@ function mesecon.set_bit(binary,bit,value)
 end
 
 function mesecon.invertRule(r)
-	return {x = -r.x, y = -r.y, z = -r.z}
-end
-
-function mesecon.addPosRule(p, r)
-	return {x = p.x + r.x, y = p.y + r.y, z = p.z + r.z}
-end
-
-function mesecon.cmpPos(p1, p2)
-	return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z)
+	return vector.multiply(r, -1)
 end
 
 function mesecon.tablecopy(table) -- deep table copy
@@ -209,3 +201,75 @@ function mesecon.flipstate(pos, node)
 
 	return newstate
 end
+
+-- File writing / reading utilities
+local wpath = minetest.get_worldpath()
+function mesecon.file2table(filename)
+	local f = io.open(wpath..DIR_DELIM..filename, "r")
+	if f == nil then return {} end
+	local t = f:read("*all")
+	f:close()
+	if t == "" or t == nil then return {} end
+	return minetest.deserialize(t)
+end
+
+function mesecon.table2file(filename, table)
+	local f = io.open(wpath..DIR_DELIM..filename, "w")
+	f:write(minetest.serialize(table))
+	f:close()
+end
+
+-- Forceloading: Force server to load area if node is nil
+local BLOCKSIZE = 16
+
+-- convert node position --> block hash
+local function hash_blockpos(pos)
+	return minetest.hash_node_position({
+		x = math.floor(pos.x/BLOCKSIZE),
+		y = math.floor(pos.y/BLOCKSIZE),
+		z = math.floor(pos.z/BLOCKSIZE)
+	})
+end
+
+-- convert block hash --> node position
+local function unhash_blockpos(hash)
+	return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
+end
+
+mesecon.forceloaded_blocks = {}
+
+-- get node and force-load area
+function mesecon.get_node_force(pos)
+	local hash = hash_blockpos(pos)
+
+	if mesecon.forceloaded_blocks[hash] == nil then
+		-- if no more forceload spaces are available, try again next time
+		if minetest.forceload_block(pos) then
+			mesecon.forceloaded_blocks[hash] = 0
+		end
+	else
+		mesecon.forceloaded_blocks[hash] = 0
+	end
+
+	return minetest.get_node_or_nil(pos)
+end
+
+minetest.register_globalstep(function (dtime)
+	for hash, time in pairs(mesecon.forceloaded_blocks) do
+		-- unload forceloaded blocks after 10 minutes without usage
+		if (time > mesecon.setting("forceload_timeout", 600)) then
+			minetest.forceload_free_block(unhash_blockpos(hash))
+			mesecon.forceloaded_blocks[hash] = nil
+		else
+			mesecon.forceloaded_blocks[hash] = time + dtime
+		end
+	end
+end)
+
+-- Store and read the forceloaded blocks to / from a file
+-- so that those blocks are remembered when the game
+-- is restarted
+mesecon.forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
+minetest.register_on_shutdown(function()
+	mesecon.table2file("mesecon_forceloaded", mesecon.forceloaded_blocks)
+end)
diff --git a/mesecons/wires.lua b/mesecons/wires.lua
index 18ae8f5..d77904e 100644
--- a/mesecons/wires.lua
+++ b/mesecons/wires.lua
@@ -22,7 +22,7 @@ local wire_getconnect = function (from_pos, self_pos)
 		end
 
 		for _, r in ipairs(mesecon.flattenrules(rules)) do
-			if (mesecon.cmpPos(mesecon.addPosRule(self_pos, r), from_pos)) then
+			if (vector.equals(vector.add(self_pos, r), from_pos)) then
 				return true
 			end
 		end
@@ -35,7 +35,7 @@ local wire_updateconnect = function (pos)
 	local connections = {}
 
 	for _, r in ipairs(mesecon.rules.default) do
-		if wire_getconnect(pos, mesecon.addPosRule(pos, r)) then
+		if wire_getconnect(pos, vector.add(pos, r)) then
 			table.insert(connections, r)
 		end
 	end
@@ -83,7 +83,7 @@ local update_on_place_dig = function (pos, node)
 	if (not rules) then return end
 
 	for _, r in ipairs(mesecon.flattenrules(rules)) do
-		local np = mesecon.addPosRule(pos, r)
+		local np = vector.add(pos, r)
 		if minetest.registered_nodes[minetest.get_node(np).name]
 		and minetest.registered_nodes[minetest.get_node(np).name].mesecon_wire then
 			wire_updateconnect(np)
diff --git a/mesecons_commandblock/init.lua b/mesecons_commandblock/init.lua
index 8fd23f6..9cf9b13 100644
--- a/mesecons_commandblock/init.lua
+++ b/mesecons_commandblock/init.lua
@@ -1,195 +1,195 @@
-minetest.register_chatcommand("say", {
-	params = "<text>",
-	description = "Say <text> as the server",
-	privs = {server=true},
-	func = function(name, param)
-		minetest.chat_send_all(name .. ": " .. param)
-	end
-})
-
-minetest.register_chatcommand("tell", {
-	params = "<name> <text>",
-	description = "Say <text> to <name> privately",
-	func = function(name, param)
-		local found, _, target, message = param:find("^([^%s]+)%s+(.*)$")
-		if found == nil then
-			minetest.chat_send_player(name, "Invalid usage: " .. param)
-			return
-		end
-		if not minetest.get_player_by_name(target) then
-			minetest.chat_send_player(name, "Invalid target: " .. target)
-		end
-		minetest.chat_send_player(target, name .. " whispers: " .. message, false)
-	end
-})
-
-minetest.register_chatcommand("hp", {
-	params = "<name> <value>",
-	description = "Set health of <name> to <value> hitpoints",
-	privs = {ban=true},
-	func = function(name, param)
-		local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$")
-		if found == nil then
-			minetest.chat_send_player(name, "Invalid usage: " .. param)
-			return
-		end
-		local player = minetest.get_player_by_name(target)
-		if player then
-			player:set_hp(value)
-		else
-			minetest.chat_send_player(name, "Invalid target: " .. target)
-		end
-	end
-})
-
-local function initialize_data(meta)
-	local commands = meta:get_string("commands")
-	meta:set_string("formspec",
-		"invsize[9,5;]" ..
-		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" ..
-		"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" ..
-		"button_exit[3.3,4.5;2,1;submit;Submit]")
-	local owner = meta:get_string("owner")
-	if owner == "" then
-		owner = "not owned"
-	else
-		owner = "owned by " .. owner
-	end
-	meta:set_string("infotext", "Command Block\n" ..
-		"(" .. owner .. ")\n" ..
-		"Commands: "..commands)
-end
-
-local function construct(pos)
-	local meta = minetest.get_meta(pos)
-
-	meta:set_string("commands", "tell @nearest Commandblock unconfigured")
-
-	meta:set_string("owner", "")
-
-	initialize_data(meta)
-end
-
-local function after_place(pos, placer)
-	if placer then
-		local meta = minetest.get_meta(pos)
-		meta:set_string("owner", placer:get_player_name())
-		initialize_data(meta)
-	end
-end
-
-local function receive_fields(pos, formname, fields, sender)
-	if not fields.submit then
-		return
-	end
-	local meta = minetest.get_meta(pos)
-	local owner = meta:get_string("owner")
-	if owner ~= "" and sender:get_player_name() ~= owner then
-		return
-	end
-	meta:set_string("commands", fields.commands)
-
-	initialize_data(meta)
-end
-
-local function resolve_commands(commands, pos)
-	local nearest, farthest = nil, nil
-	local min_distance, max_distance = math.huge, -1
-	local players = minetest.get_connected_players()
-	for index, player in pairs(players) do
-		local distance = vector.distance(pos, player:getpos())
-		if distance < min_distance then
-			min_distance = distance
-			nearest = player:get_player_name()
-		end
-		if distance > max_distance then
-			max_distance = distance
-			farthest = player:get_player_name()
-		end
-	end
-	local random = players[math.random(#players)]:get_player_name()
-	commands = commands:gsub("@nearest", nearest)
-	commands = commands:gsub("@farthest", farthest)
-	commands = commands:gsub("@random", random)
-	return commands
-end
-
-local function commandblock_action_on(pos, node)
-	if node.name ~= "mesecons_commandblock:commandblock_off" then
-		return
-	end
-
-	minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
-
-	local meta = minetest.get_meta(pos)
-	local owner = meta:get_string("owner")
-	if owner == "" then
-		return
-	end
-
-	local commands = resolve_commands(meta:get_string("commands"), pos)
-	for _, command in pairs(commands:split("\n")) do
-		local pos = command:find(" ")
-		local cmd, param = command, ""
-		if pos then
-			cmd = command:sub(1, pos - 1)
-			param = command:sub(pos + 1)
-		end
-		local cmddef = minetest.chatcommands[cmd]
-		if not cmddef then
-			minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
-			return
-		end
-		local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
-		if not has_privs then
-			minetest.chat_send_player(owner, "You don't have permission "
-					.."to run "..cmd
-					.." (missing privileges: "
-					..table.concat(missing_privs, ", ")..")")
-			return
-		end
-		cmddef.func(owner, param)
-	end
-end
-
-local function commandblock_action_off(pos, node)
-	if node.name == "mesecons_commandblock:commandblock_on" then
-		minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
-	end
-end
-
-local function can_dig(pos, player)
-	local meta = minetest.get_meta(pos)
-	local owner = meta:get_string("owner")
-	return owner == "" or owner == player:get_player_name()
-end
-
-minetest.register_node("mesecons_commandblock:commandblock_off", {
-	description = "Command Block",
-	tiles = {"jeija_commandblock_off.png"},
-	inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
-	groups = {cracky=2, mesecon_effector_off=1},
-	on_construct = construct,
-	after_place_node = after_place,
-	on_receive_fields = receive_fields,
-	can_dig = can_dig,
-	sounds = default.node_sound_stone_defaults(),
-	mesecons = {effector = {
-		action_on = commandblock_action_on
-	}}
-})
-
-minetest.register_node("mesecons_commandblock:commandblock_on", {
-	tiles = {"jeija_commandblock_on.png"},
-	groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
-	light_source = 10,
-	drop = "mesecons_commandblock:commandblock_off",
-	on_construct = construct,
-	after_place_node = after_place,
-	on_receive_fields = receive_fields,
-	can_dig = can_dig,
-	sounds = default.node_sound_stone_defaults(),
-	mesecons = {effector = {
-		action_off = commandblock_action_off
-	}}
-})
+minetest.register_chatcommand("say", {
+	params = "<text>",
+	description = "Say <text> as the server",
+	privs = {server=true},
+	func = function(name, param)
+		minetest.chat_send_all(name .. ": " .. param)
+	end
+})
+
+minetest.register_chatcommand("tell", {
+	params = "<name> <text>",
+	description = "Say <text> to <name> privately",
+	func = function(name, param)
+		local found, _, target, message = param:find("^([^%s]+)%s+(.*)$")
+		if found == nil then
+			minetest.chat_send_player(name, "Invalid usage: " .. param)
+			return
+		end
+		if not minetest.get_player_by_name(target) then
+			minetest.chat_send_player(name, "Invalid target: " .. target)
+		end
+		minetest.chat_send_player(target, name .. " whispers: " .. message, false)
+	end
+})
+
+minetest.register_chatcommand("hp", {
+	params = "<name> <value>",
+	description = "Set health of <name> to <value> hitpoints",
+	privs = {ban=true},
+	func = function(name, param)
+		local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$")
+		if found == nil then
+			minetest.chat_send_player(name, "Invalid usage: " .. param)
+			return
+		end
+		local player = minetest.get_player_by_name(target)
+		if player then
+			player:set_hp(value)
+		else
+			minetest.chat_send_player(name, "Invalid target: " .. target)
+		end
+	end
+})
+
+local function initialize_data(meta)
+	local commands = meta:get_string("commands")
+	meta:set_string("formspec",
+		"invsize[9,5;]" ..
+		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" ..
+		"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" ..
+		"button_exit[3.3,4.5;2,1;submit;Submit]")
+	local owner = meta:get_string("owner")
+	if owner == "" then
+		owner = "not owned"
+	else
+		owner = "owned by " .. owner
+	end
+	meta:set_string("infotext", "Command Block\n" ..
+		"(" .. owner .. ")\n" ..
+		"Commands: "..commands)
+end
+
+local function construct(pos)
+	local meta = minetest.get_meta(pos)
+
+	meta:set_string("commands", "tell @nearest Commandblock unconfigured")
+
+	meta:set_string("owner", "")
+
+	initialize_data(meta)
+end
+
+local function after_place(pos, placer)
+	if placer then
+		local meta = minetest.get_meta(pos)
+		meta:set_string("owner", placer:get_player_name())
+		initialize_data(meta)
+	end
+end
+
+local function receive_fields(pos, formname, fields, sender)
+	if not fields.submit then
+		return
+	end
+	local meta = minetest.get_meta(pos)
+	local owner = meta:get_string("owner")
+	if owner ~= "" and sender:get_player_name() ~= owner then
+		return
+	end
+	meta:set_string("commands", fields.commands)
+
+	initialize_data(meta)
+end
+
+local function resolve_commands(commands, pos)
+	local nearest, farthest = nil, nil
+	local min_distance, max_distance = math.huge, -1
+	local players = minetest.get_connected_players()
+	for index, player in pairs(players) do
+		local distance = vector.distance(pos, player:getpos())
+		if distance < min_distance then
+			min_distance = distance
+			nearest = player:get_player_name()
+		end
+		if distance > max_distance then
+			max_distance = distance
+			farthest = player:get_player_name()
+		end
+	end
+	local random = players[math.random(#players)]:get_player_name()
+	commands = commands:gsub("@nearest", nearest)
+	commands = commands:gsub("@farthest", farthest)
+	commands = commands:gsub("@random", random)
+	return commands
+end
+
+local function commandblock_action_on(pos, node)
+	if node.name ~= "mesecons_commandblock:commandblock_off" then
+		return
+	end
+
+	minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
+
+	local meta = minetest.get_meta(pos)
+	local owner = meta:get_string("owner")
+	if owner == "" then
+		return
+	end
+
+	local commands = resolve_commands(meta:get_string("commands"), pos)
+	for _, command in pairs(commands:split("\n")) do
+		local pos = command:find(" ")
+		local cmd, param = command, ""
+		if pos then
+			cmd = command:sub(1, pos - 1)
+			param = command:sub(pos + 1)
+		end
+		local cmddef = minetest.chatcommands[cmd]
+		if not cmddef then
+			minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
+			return
+		end
+		local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
+		if not has_privs then
+			minetest.chat_send_player(owner, "You don't have permission "
+					.."to run "..cmd
+					.." (missing privileges: "
+					..table.concat(missing_privs, ", ")..")")
+			return
+		end
+		cmddef.func(owner, param)
+	end
+end
+
+local function commandblock_action_off(pos, node)
+	if node.name == "mesecons_commandblock:commandblock_on" then
+		minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
+	end
+end
+
+local function can_dig(pos, player)
+	local meta = minetest.get_meta(pos)
+	local owner = meta:get_string("owner")
+	return owner == "" or owner == player:get_player_name()
+end
+
+minetest.register_node("mesecons_commandblock:commandblock_off", {
+	description = "Command Block",
+	tiles = {"jeija_commandblock_off.png"},
+	inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
+	groups = {cracky=2, mesecon_effector_off=1},
+	on_construct = construct,
+	after_place_node = after_place,
+	on_receive_fields = receive_fields,
+	can_dig = can_dig,
+	sounds = default.node_sound_stone_defaults(),
+	mesecons = {effector = {
+		action_on = commandblock_action_on
+	}}
+})
+
+minetest.register_node("mesecons_commandblock:commandblock_on", {
+	tiles = {"jeija_commandblock_on.png"},
+	groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
+	light_source = 10,
+	drop = "mesecons_commandblock:commandblock_off",
+	on_construct = construct,
+	after_place_node = after_place,
+	on_receive_fields = receive_fields,
+	can_dig = can_dig,
+	sounds = default.node_sound_stone_defaults(),
+	mesecons = {effector = {
+		action_off = commandblock_action_off
+	}}
+})
diff --git a/mesecons_detector/init.lua b/mesecons_detector/init.lua
index 084535b..65e5c6e 100644
--- a/mesecons_detector/init.lua
+++ b/mesecons_detector/init.lua
@@ -4,16 +4,15 @@ local GET_COMMAND = "GET"
 -- Detects players in a certain radius
 -- The radius can be specified in mesecons/settings.lua
 
-local object_detector_make_formspec = function (pos)
-	local meta = minetest.get_meta(pos)
-	meta:set_string("formspec", "size[9,2.5]" ..
+local function object_detector_make_formspec(pos)
+	minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
 		"field[0.3,  0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]"..
 		"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
 		"button_exit[7,0.75;2,3;;Save]")
 end
 
-local object_detector_on_receive_fields = function(pos, formname, fields)
-	if not fields.scanname or not fields.digiline_channel then return end;
+local function object_detector_on_receive_fields(pos, _, fields)
+	if not fields.scanname or not fields.digiline_channel then return end
 
 	local meta = minetest.get_meta(pos)
 	meta:set_string("scanname", fields.scanname)
@@ -22,25 +21,35 @@ local object_detector_on_receive_fields = function(pos, formname, fields)
 end
 
 -- returns true if player was found, false if not
-local object_detector_scan = function (pos)
+local function object_detector_scan(pos)
 	local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6))
-	for k, obj in pairs(objs) do
-		local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil!
-		local scanname = minetest.get_meta(pos):get_string("scanname")
-		if (isname == scanname and isname ~= "") or (isname  ~= "" and scanname == "") then -- player with scanname found or not scanname specified
-			return true
+
+	-- abort if no scan results were found
+	if next(objs) == nil then return false end
+
+	local scanname = minetest.get_meta(pos):get_string("scanname")
+	local every_player = scanname == ""
+	for _, obj in pairs(objs) do
+		-- "" is returned if it is not a player; "" ~= nil; so only handle objects with foundname ~= ""
+		local foundname = obj:get_player_name()
+
+		if foundname ~= "" then
+			-- return true if scanning for any player or if specific playername was detected
+			if scanname == "" or foundname == scanname then
+				return true
+			end
 		end
 	end
+
 	return false
 end
 
 -- set player name when receiving a digiline signal on a specific channel
 local object_detector_digiline = {
 	effector = {
-		action = function (pos, node, channel, msg)
+		action = function(pos, node, channel, msg)
 			local meta = minetest.get_meta(pos)
-			local active_channel = meta:get_string("digiline_channel")
-			if channel == active_channel then
+			if channel == meta:get_string("digiline_channel") then
 				meta:set_string("scanname", msg)
 				object_detector_make_formspec(pos)
 			end
@@ -89,43 +98,44 @@ minetest.register_craft({
 	}
 })
 
-minetest.register_abm(
-	{nodenames = {"mesecons_detector:object_detector_off"},
-	interval = 1.0,
+minetest.register_abm({
+	nodenames = {"mesecons_detector:object_detector_off"},
+	interval = 1,
 	chance = 1,
-	action = function(pos)
-		if object_detector_scan(pos) then
-			minetest.swap_node(pos, {name = "mesecons_detector:object_detector_on"})
-			mesecon.receptor_on(pos, mesecon.rules.pplate)
-		end
+	action = function(pos, node)
+		if not object_detector_scan(pos) then return end
+
+		node.name = "mesecons_detector:object_detector_on"
+		minetest.swap_node(pos, node)
+		mesecon.receptor_on(pos, mesecon.rules.pplate)
 	end,
 })
 
-minetest.register_abm(
-	{nodenames = {"mesecons_detector:object_detector_on"},
-	interval = 1.0,
+minetest.register_abm({
+	nodenames = {"mesecons_detector:object_detector_on"},
+	interval = 1,
 	chance = 1,
-	action = function(pos)
-		if not object_detector_scan(pos) then
-			minetest.swap_node(pos, {name = "mesecons_detector:object_detector_off"})
-			mesecon.receptor_off(pos, mesecon.rules.pplate)
-		end
+	action = function(pos, node)
+		if object_detector_scan(pos) then return end
+
+		node.name = "mesecons_detector:object_detector_off"
+		minetest.swap_node(pos, node)
+		mesecon.receptor_off(pos, mesecon.rules.pplate)
 	end,
 })
 
 -- Node detector
 -- Detects the node in front of it
 
-local node_detector_make_formspec = function (pos)
-	local meta = minetest.get_meta(pos)
-	meta:set_string("formspec", "size[9,2.5]" ..
+local function node_detector_make_formspec(pos)
+	minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
 		"field[0.3,  0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]"..
 		"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
 		"button_exit[7,0.75;2,3;;Save]")
 end
 
-local node_detector_on_receive_fields = function(pos, formname, fields)
-	if not fields.scanname or not fields.digiline_channel then return end;
+local function node_detector_on_receive_fields(pos, _, fields)
+	if not fields.scanname or not fields.digiline_channel then return end
 
 	local meta = minetest.get_meta(pos)
 	meta:set_string("scanname", fields.scanname)
@@ -133,41 +143,59 @@ local node_detector_on_receive_fields = function(pos, formname, fields)
 	node_detector_make_formspec(pos)
 end
 
--- returns true if player was found, false if not
-local node_detector_scan = function (pos)
-	if not pos then return end
+-- returns true if node was found, false if not
+local function node_detector_scan(pos)
 	local node = minetest.get_node_or_nil(pos)
 	if not node then return end
-	local scandir = minetest.facedir_to_dir(node.param2)
-	if not scandir then return end
-	local frontpos = vector.subtract(pos, scandir)
-	local frontnode = minetest.get_node(frontpos)
-	local meta = minetest.get_meta(pos)
-	return (frontnode.name == meta:get_string("scanname")) or
-		(frontnode.name ~= "air" and frontnode.name ~= "ignore" and meta:get_string("scanname") == "")
+
+	local frontname = minetest.get_node(
+		vector.subtract(pos, minetest.facedir_to_dir(node.param2))
+	).name
+	local scanname = minetest.get_meta(pos):get_string("scanname")
+
+	return (frontname == scanname) or
+		(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
 end
 
 -- set player name when receiving a digiline signal on a specific channel
 local node_detector_digiline = {
 	effector = {
-		action = function (pos, node, channel, msg)
+		action = function(pos, node, channel, msg)
 			local meta = minetest.get_meta(pos)
-			local active_channel = meta:get_string("digiline_channel")
-			if channel == active_channel then
-				if msg == GET_COMMAND then
-					local frontpos = vector.subtract(pos, minetest.facedir_to_dir(node.param2))
-					local name = minetest.get_node(frontpos).name
-					digiline:receptor_send(pos, digiline.rules.default, channel, name)
-				else
-					meta:set_string("scanname", msg)
-					node_detector_make_formspec(pos)
-				end
+			if channel ~= meta:get_string("digiline_channel") then return end
+
+			if msg == GET_COMMAND then
+				local nodename = minetest.get_node(
+					vector.subtract(pos, minetest.facedir_to_dir(node.param2))
+				).name
+
+				digiline:receptor_send(pos, digiline.rules.default, channel, nodename)
+			else
+				meta:set_string("scanname", msg)
+				node_detector_make_formspec(pos)
 			end
 		end,
 	},
 	receptor = {}
 }
 
+local function after_place_node_detector(pos, placer)
+	local placer_pos = placer:getpos()
+	if not placer_pos then
+		return
+	end
+
+	--correct for the player's height
+	if placer:is_player() then
+		placer_pos.y = placer_pos.y + 1.625
+	end
+
+	--correct for 6d facedir
+	local node = minetest.get_node(pos)
+	node.param2 = minetest.dir_to_facedir(vector.subtract(pos, placer_pos), true)
+	minetest.set_node(pos, node)
+end
+
 minetest.register_node("mesecons_detector:node_detector_off", {
 	tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"},
 	paramtype = "light",
@@ -180,25 +208,7 @@ minetest.register_node("mesecons_detector:node_detector_off", {
 	}},
 	on_construct = node_detector_make_formspec,
 	on_receive_fields = node_detector_on_receive_fields,
-	after_place_node = function (pos, placer)
-		local placer_pos = placer:getpos()
-
-		--correct for the player's height
-		if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end
-
-		--correct for 6d facedir
-		if placer_pos then
-			local dir = {
-				x = pos.x - placer_pos.x,
-				y = pos.y - placer_pos.y,
-				z = pos.z - placer_pos.z
-			}
-			local node = minetest.get_node(pos)
-			node.param2 = minetest.dir_to_facedir(dir, true)
-			minetest.set_node(pos, node)
-			minetest.log("action", "real (6d) facedir: " .. node.param2)
-		end
-	end,
+	after_place_node = after_place_node_detector,
 	sounds = default.node_sound_stone_defaults(),
 	digiline = node_detector_digiline
 })
@@ -215,25 +225,7 @@ minetest.register_node("mesecons_detector:node_detector_on", {
 	}},
 	on_construct = node_detector_make_formspec,
 	on_receive_fields = node_detector_on_receive_fields,
-	after_place_node = function (pos, placer)
-		local placer_pos = placer:getpos()
-
-		--correct for the player's height
-		if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end
-
-		--correct for 6d facedir
-		if placer_pos then
-			local dir = {
-				x = pos.x - placer_pos.x,
-				y = pos.y - placer_pos.y,
-				z = pos.z - placer_pos.z
-			}
-			local node = minetest.get_node(pos)
-			node.param2 = minetest.dir_to_facedir(dir, true)
-			minetest.set_node(pos, node)
-			minetest.log("action", "real (6d) facedir: " .. node.param2)
-		end
-	end,
+	after_place_node = after_place_node_detector,
 	sounds = default.node_sound_stone_defaults(),
 	digiline = node_detector_digiline
 })
@@ -247,26 +239,28 @@ minetest.register_craft({
 	}
 })
 
-minetest.register_abm(
-	{nodenames = {"mesecons_detector:node_detector_off"},
-	interval = 1.0,
+minetest.register_abm({
+	nodenames = {"mesecons_detector:node_detector_off"},
+	interval = 1,
 	chance = 1,
 	action = function(pos, node)
-		if node_detector_scan(pos) then
-			minetest.swap_node(pos, {name = "mesecons_detector:node_detector_on", param2 = node.param2})
-			mesecon.receptor_on(pos)
-		end
+		if not node_detector_scan(pos) then return end
+
+		node.name = "mesecons_detector:node_detector_on"
+		minetest.swap_node(pos, node)
+		mesecon.receptor_on(pos)
 	end,
 })
 
-minetest.register_abm(
-	{nodenames = {"mesecons_detector:node_detector_on"},
-	interval = 1.0,
+minetest.register_abm({
+	nodenames = {"mesecons_detector:node_detector_on"},
+	interval = 1,
 	chance = 1,
 	action = function(pos, node)
-		if not node_detector_scan(pos) then
-			minetest.swap_node(pos, {name = "mesecons_detector:node_detector_off", param2 = node.param2})
-			mesecon.receptor_off(pos)
-		end
+		if node_detector_scan(pos) then return end
+
+		node.name = "mesecons_detector:node_detector_off"
+		minetest.swap_node(pos, node)
+		mesecon.receptor_off(pos)
 	end,
 })
diff --git a/mesecons_doors/init.lua b/mesecons_doors/init.lua
index 7346128..52d6c17 100644
--- a/mesecons_doors/init.lua
+++ b/mesecons_doors/init.lua
@@ -20,31 +20,53 @@ local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
 end
 
 local function meseconify_door(name)
-	if not minetest.registered_items[name] then return end
+	if minetest.registered_items[name .. "_b_1"] then
+		-- old style double-node doors
+		local function toggle_state1 (pos, node)
+			on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
+		end
 
-	local function toggle_state1 (pos, node)
-		on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
-	end
-
-	local function toggle_state2 (pos, node)
-		on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
-	end
+		local function toggle_state2 (pos, node)
+			on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
+		end
 
-	minetest.override_item(name.."_b_1", {
-		mesecons = {effector = {
-			action_on = toggle_state1,
-			action_off = toggle_state1,
-			rules = mesecon.rules.pplate
-		}},
-	})
+		minetest.override_item(name.."_b_1", {
+			mesecons = {effector = {
+				action_on = toggle_state1,
+				action_off = toggle_state1,
+				rules = mesecon.rules.pplate
+			}}
+		})
 
-	minetest.override_item(name.."_b_2", {
-		mesecons = {effector = {
-			action_on = toggle_state2,
-			action_off = toggle_state2,
-			rules = mesecon.rules.pplate
-		}},
-	})
+		minetest.override_item(name.."_b_2", {
+			mesecons = {effector = {
+				action_on = toggle_state2,
+				action_off = toggle_state2,
+				rules = mesecon.rules.pplate
+			}}
+		})
+	elseif minetest.registered_items[name .. "_a"] then
+		-- new style mesh node based doors
+		local override = {
+			mesecons = {effector = {
+				action_on = function(pos, node)
+					local door = doors.get(pos)
+					if door then
+						door:open()
+					end
+				end,
+				action_off = function(pos, node)
+					local door = doors.get(pos)
+					if door then
+						door:close()
+					end
+				end,
+				rules = mesecon.rules.pplate
+			}}
+		}
+		minetest.override_item(name .. "_a", override)
+		minetest.override_item(name .. "_b", override)
+	end
 end
 
 meseconify_door("doors:door_wood")
@@ -67,18 +89,41 @@ local function trapdoor_switch(pos, node)
 	minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1)
 end
 
-if minetest.registered_nodes["doors:trapdoor"] then
-	minetest.override_item("doors:trapdoor", {
+if doors and doors.get then
+	local override = {
 		mesecons = {effector = {
-			action_on = trapdoor_switch,
-			action_off = trapdoor_switch
+			action_on = function(pos, node)
+				local door = doors.get(pos)
+				if door then
+					door:open()
+				end
+			end,
+			action_off = function(pos, node)
+				local door = doors.get(pos)
+				if door then
+					door:close()
+				end
+			end,
 		}},
-	})
+	}
+	minetest.override_item("doors:trapdoor", override)
+	minetest.override_item("doors:trapdoor_open", override)
+	minetest.override_item("doors:trapdoor_steel", override)
+	minetest.override_item("doors:trapdoor_steel_open", override)
+else
+	if minetest.registered_nodes["doors:trapdoor"] then
+		minetest.override_item("doors:trapdoor", {
+			mesecons = {effector = {
+				action_on = trapdoor_switch,
+				action_off = trapdoor_switch
+			}},
+		})
 
-	minetest.override_item("doors:trapdoor_open", {
-		mesecons = {effector = {
-			action_on = trapdoor_switch,
-			action_off = trapdoor_switch
-		}},
-	})
+		minetest.override_item("doors:trapdoor_open", {
+			mesecons = {effector = {
+				action_on = trapdoor_switch,
+				action_off = trapdoor_switch
+			}},
+		})
+	end
 end
diff --git a/mesecons_extrawires/vertical.lua b/mesecons_extrawires/vertical.lua
index cac2ae2..f3232d8 100644
--- a/mesecons_extrawires/vertical.lua
+++ b/mesecons_extrawires/vertical.lua
@@ -42,33 +42,37 @@ local vertical_updatepos = function (pos)
 	local node = minetest.get_node(pos)
 	if minetest.registered_nodes[node.name]
 	and minetest.registered_nodes[node.name].is_vertical_conductor then
-		local node_above = minetest.get_node(mesecon.addPosRule(pos, vertical_rules[1]))
-		local node_below = minetest.get_node(mesecon.addPosRule(pos, vertical_rules[2]))
-		local namestate = minetest.registered_nodes[node.name].vertical_conductor_state
+		local node_above = minetest.get_node(vector.add(pos, vertical_rules[1]))
+		local node_below = minetest.get_node(vector.add(pos, vertical_rules[2]))
 
 		local above = minetest.registered_nodes[node_above.name]
 			and minetest.registered_nodes[node_above.name].is_vertical_conductor
 		local below = minetest.registered_nodes[node_below.name]
 			and minetest.registered_nodes[node_below.name].is_vertical_conductor
 
-		local basename = "mesecons_extrawires:vertical_"
+		mesecon.on_dignode(pos, node)
+
+		-- Always place offstate conductor and let mesecon.on_placenode take care
+		local newname = "mesecons_extrawires:vertical_"
 		if above and below then -- above and below: vertical mesecon
-			minetest.add_node(pos, {name = basename .. namestate})
+			newname = newname .. "off"
 		elseif above and not below then -- above only: bottom
-			minetest.add_node(pos, {name = basename .. "bottom_" .. namestate})
+			newname = newname .. "bottom_off"
 		elseif not above and below then -- below only: top
-			minetest.add_node(pos, {name = basename .. "top_" .. namestate})
+			newname = newname .. "top_off"
 		else -- no vertical wire above, no vertical wire below: use bottom
-			minetest.add_node(pos, {name = basename .. "bottom_" .. namestate})
+			newname = newname .. "bottom_off"
 		end
-		mesecon.update_autoconnect(pos)
+
+		minetest.set_node(pos, {name = newname})
+		mesecon.on_placenode(pos, {name = newname})
 	end
 end
 
 local vertical_update = function (pos, node)
 	vertical_updatepos(pos) -- this one
-	vertical_updatepos(mesecon.addPosRule(pos, vertical_rules[1])) -- above
-	vertical_updatepos(mesecon.addPosRule(pos, vertical_rules[2])) -- below
+	vertical_updatepos(vector.add(pos, vertical_rules[1])) -- above
+	vertical_updatepos(vector.add(pos, vertical_rules[2])) -- below
 end
 
 -- Vertical wire
@@ -87,7 +91,6 @@ mesecon.register_node("mesecons_extrawires:vertical", {
 },{
 	tiles = {"mesecons_wire_off.png"},
 	groups = {dig_immediate=3},
-	vertical_conductor_state = "off",
 	mesecons = {conductor = {
 		state = mesecon.state.off,
 		onstate = "mesecons_extrawires:vertical_on",
@@ -96,7 +99,6 @@ mesecon.register_node("mesecons_extrawires:vertical", {
 },{
 	tiles = {"mesecons_wire_on.png"},
 	groups = {dig_immediate=3, not_in_creative_inventory=1},
-	vertical_conductor_state = "on",
 	mesecons = {conductor = {
 		state = mesecon.state.on,
 		offstate = "mesecons_extrawires:vertical_off",
@@ -120,7 +122,6 @@ mesecon.register_node("mesecons_extrawires:vertical_top", {
 	after_dig_node = vertical_update
 },{
 	tiles = {"mesecons_wire_off.png"},
-	vertical_conductor_state = "off",
 	mesecons = {conductor = {
 		state = mesecon.state.off,
 		onstate = "mesecons_extrawires:vertical_top_on",
@@ -128,7 +129,6 @@ mesecon.register_node("mesecons_extrawires:vertical_top", {
 	}}
 },{
 	tiles = {"mesecons_wire_on.png"},
-	vertical_conductor_state = "on",
 	mesecons = {conductor = {
 		state = mesecon.state.on,
 		offstate = "mesecons_extrawires:vertical_top_off",
@@ -152,7 +152,6 @@ mesecon.register_node("mesecons_extrawires:vertical_bottom", {
 	after_dig_node = vertical_update
 },{
 	tiles = {"mesecons_wire_off.png"},
-	vertical_conductor_state = "off",
 	mesecons = {conductor = {
 		state = mesecon.state.off,
 		onstate = "mesecons_extrawires:vertical_bottom_on",
@@ -160,7 +159,6 @@ mesecon.register_node("mesecons_extrawires:vertical_bottom", {
 	}}
 },{
 	tiles = {"mesecons_wire_on.png"},
-	vertical_conductor_state = "on",
 	mesecons = {conductor = {
 		state = mesecon.state.on,
 		offstate = "mesecons_extrawires:vertical_bottom_off",
diff --git a/mesecons_hydroturbine/init.lua b/mesecons_hydroturbine/init.lua
index d1c08f7..f1292e9 100644
--- a/mesecons_hydroturbine/init.lua
+++ b/mesecons_hydroturbine/init.lua
@@ -60,7 +60,7 @@ nodenames = {"mesecons_hydroturbine:hydro_turbine_off"},
 	action = function(pos, node, active_object_count, active_object_count_wider)
 		local waterpos={x=pos.x, y=pos.y+1, z=pos.z}
 		if minetest.get_node(waterpos).name=="default:water_flowing" then
-			minetest.add_node(pos, {name="mesecons_hydroturbine:hydro_turbine_on"})
+			minetest.set_node(pos, {name="mesecons_hydroturbine:hydro_turbine_on"})
 			nodeupdate(pos)
 			mesecon.receptor_on(pos)
 		end
@@ -74,7 +74,7 @@ nodenames = {"mesecons_hydroturbine:hydro_turbine_on"},
 	action = function(pos, node, active_object_count, active_object_count_wider)
 		local waterpos={x=pos.x, y=pos.y+1, z=pos.z}
 		if minetest.get_node(waterpos).name~="default:water_flowing" then
-			minetest.add_node(pos, {name="mesecons_hydroturbine:hydro_turbine_off"})
+			minetest.set_node(pos, {name="mesecons_hydroturbine:hydro_turbine_off"})
 			nodeupdate(pos)
 			mesecon.receptor_off(pos)
 		end
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua
index 839d150..7df2bdc 100644
--- a/mesecons_luacontroller/init.lua
+++ b/mesecons_luacontroller/init.lua
@@ -205,6 +205,17 @@ local function safe_date()
 	return(os.date("*t",os.time()))
 end
 
+-- string.rep(str, n) with a high value for n can be used to DoS
+-- the server. Therefore, limit max. length of generated string.
+local function safe_string_rep(str, n)
+	if #str * n > mesecon.setting("luacontroller_string_rep_max", 64000) then
+		debug.sethook() -- Clear hook
+		error("string.rep: string length overflow", 2)
+	end
+
+	return string.rep(str, n)
+end
+
 local function remove_functions(x)
 	local tp = type(x)
 	if tp == "table" then
@@ -249,8 +260,8 @@ end
 
 
 local safe_globals = {
-	"assert", "error", "ipairs", "next", "pairs", "pcall", "select",
-	"tonumber", "tostring", "type", "unpack", "_VERSION", "xpcall",
+	"assert", "error", "ipairs", "next", "pairs", "select",
+	"tonumber", "tostring", "type", "unpack", "_VERSION"
 }
 local function create_environment(pos, mem, event)
 	-- Gather variables for the environment
@@ -275,11 +286,10 @@ local function create_environment(pos, mem, event)
 			byte = string.byte,
 			char = string.char,
 			format = string.format,
-			gsub = string.gsub,
 			len = string.len,
 			lower = string.lower,
 			upper = string.upper,
-			rep = string.rep,
+			rep = safe_string_rep,
 			reverse = string.reverse,
 			sub = string.sub,
 		},
@@ -339,18 +349,18 @@ end
 
 
 local function timeout()
-	debug.sethook()  -- Clear hook
-	error("Code timed out!")
+	debug.sethook() -- Clear hook
+	error("Code timed out!", 2)
 end
 
 
 local function code_prohibited(code)
 	-- LuaJIT doesn't increment the instruction counter when running
 	-- loops, so we have to sanitize inputs if we're using LuaJIT.
-	if not jit then
+	if not rawget(_G, "jit") then
 		return false
 	end
-	local prohibited = {"while", "for", "do", "repeat", "until", "goto"}
+	local prohibited = {"while", "for", "repeat", "until", "goto"}
 	code = " "..code.." "
 	for _, p in ipairs(prohibited) do
 		if string.find(code, "[^%w_]"..p.."[^%w_]") then
@@ -369,10 +379,26 @@ local function create_sandbox(code, env)
 	setfenv(f, env)
 
 	return function(...)
-		debug.sethook(timeout, "", 10000)
+		-- Normal Lua: Use instruction counter to stop execution
+		-- after luacontroller_maxevents.
+		-- LuaJIT: Count function calls instead of instructions, allows usage
+		-- of function keyword. However, LuaJIT still doesn't trigger
+		-- lines events when using infinite loops.
+		local maxevents = mesecon.setting("luacontroller_maxevents", 10000)
+		if not rawget(_G, "jit") then
+			debug.sethook(timeout, "", maxevents)
+		else
+			local events = 0
+			debug.sethook(function ()
+				events = events + 1
+				if events > maxevents then
+					timeout()
+				end
+			end, "c")
+		end
 		local ok, ret = pcall(f, ...)
 		debug.sethook()  -- Clear hook
-		if not ok then error(ret) end
+		if not ok then error(ret, 0) end
 		return ret
 	end
 end
diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua
index beec94b..1707408 100644
--- a/mesecons_mvps/init.lua
+++ b/mesecons_mvps/init.lua
@@ -15,10 +15,16 @@ end
 
 -- Nodes that cannot be pushed / pulled by movestones, pistons
 function mesecon.is_mvps_stopper(node, pushdir, stack, stackid)
+	-- unknown nodes are always stoppers
+	if not minetest.registered_nodes[node.name] then
+		return true
+	end
+
 	local get_stopper = mesecon.mvps_stoppers[node.name]
 	if type (get_stopper) == "function" then
 		get_stopper = get_stopper(node, pushdir, stack, stackid)
 	end
+
 	return get_stopper
 end
 
@@ -47,6 +53,17 @@ function mesecon.mvps_process_stack(stack)
 	end
 end
 
+-- tests if the node can be pushed into, e.g. air, water, grass
+local function node_replaceable(name)
+	if name == "ignore" then return true end
+
+	if minetest.registered_nodes[name] then
+		return minetest.registered_nodes[name].buildable_to or false
+	end
+
+	return false
+end
+
 function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
 	-- determine the number of nodes to be pushed
 	local nodes = {}
@@ -56,9 +73,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
 		local np = frontiers[1]
 		local nn = minetest.get_node(np)
 
-		if nn.name ~= "air"
-		and minetest.registered_nodes[nn.name]
-		and minetest.registered_nodes[nn.name].liquidtype == "none" then
+		if not node_replaceable(nn.name) then
 			table.insert(nodes, {node = nn, pos = np})
 			if #nodes > maximum then return nil end
 
@@ -160,9 +175,9 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
 
 	-- add nodes
 	for _, n in ipairs(nodes) do
-		local np = mesecon.addPosRule(n.pos, movedir)
+		local np = vector.add(n.pos, movedir)
 
-		minetest.add_node(np, n.node)
+		minetest.set_node(np, n.node)
 		minetest.get_meta(np):from_table(n.meta)
 	end
 
@@ -171,7 +186,7 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
 	for i in ipairs(nodes) do
 		moved_nodes[i] = {}
 		moved_nodes[i].oldpos = nodes[i].pos
-		nodes[i].pos = mesecon.addPosRule(nodes[i].pos, movedir)
+		nodes[i].pos = vector.add(nodes[i].pos, movedir)
 		moved_nodes[i].pos = nodes[i].pos
 		moved_nodes[i].node = nodes[i].node
 		moved_nodes[i].meta = nodes[i].meta
@@ -192,12 +207,8 @@ end)
 function mesecon.mvps_move_objects(pos, dir, nodestack)
 	local objects_to_move = {}
 
-	-- Move object at tip of stack
-	local pushpos = mesecon.addPosRule(pos, -- get pos at tip of stack
-		{x = dir.x * #nodestack,
-		 y = dir.y * #nodestack,
-		 z = dir.z * #nodestack})
-
+	-- Move object at tip of stack, pushpos is position at tip of stack
+	local pushpos = vector.add(pos, vector.multiply(dir, #nodestack))
 
 	local objects = minetest.get_objects_inside_radius(pushpos, 1)
 	for _, obj in ipairs(objects) do
@@ -208,7 +219,7 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
 	if tonumber(minetest.setting_get("movement_gravity")) > 0 and dir.y == 0 then
 		-- If gravity positive and dir horizontal, push players standing on the stack
 		for _, n in ipairs(nodestack) do
-			local p_above = mesecon.addPosRule(n.pos, {x=0, y=1, z=0})
+			local p_above = vector.add(n.pos, {x=0, y=1, z=0})
 			local objects = minetest.get_objects_inside_radius(p_above, 1)
 			for _, obj in ipairs(objects) do
 				table.insert(objects_to_move, obj)
@@ -219,7 +230,7 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
 	for _, obj in ipairs(objects_to_move) do
 		local entity = obj:get_luaentity()
 		if not entity or not mesecon.is_mvps_unmov(entity.name) then
-			local np = mesecon.addPosRule(obj:getpos(), dir)
+			local np = vector.add(obj:getpos(), dir)
 
 			--move only if destination is not solid
 			local nn = minetest.get_node(np)
diff --git a/mesecons_noteblock/init.lua b/mesecons_noteblock/init.lua
index d5e49ff..d5e365c 100644
--- a/mesecons_noteblock/init.lua
+++ b/mesecons_noteblock/init.lua
@@ -5,7 +5,7 @@ minetest.register_node("mesecons_noteblock:noteblock", {
 	on_punch = function(pos, node) -- change sound when punched
 		node.param2 = (node.param2+1)%12
 		mesecon.noteblock_play(pos, node.param2)
-		minetest.add_node(pos, node)
+		minetest.set_node(pos, node)
 	end,
 	sounds = default.node_sound_wood_defaults(),
 	mesecons = {effector = { -- play sound when activated
diff --git a/mesecons_pistons/init.lua b/mesecons_pistons/init.lua
index bad061a..474f621 100644
--- a/mesecons_pistons/init.lua
+++ b/mesecons_pistons/init.lua
@@ -57,7 +57,7 @@ end
 local piston_remove_pusher = function(pos, node)
 	local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
 	local dir = piston_get_direction(pistonspec.dir, node)
-	local pusherpos = mesecon.addPosRule(pos, dir)
+	local pusherpos = vector.add(pos, dir)
 	local pushername = minetest.get_node(pusherpos).name
 
 	-- make sure there actually is a pusher (for compatibility reasons mainly)
@@ -78,12 +78,12 @@ local piston_on = function(pos, node)
 	local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
 
 	local dir = piston_get_direction(pistonspec.dir, node)
-	local np = mesecon.addPosRule(pos, dir)
+	local np = vector.add(pos, dir)
 	local maxpush = mesecon.setting("piston_max_push", 15)
 	local success, stack, oldstack = mesecon.mvps_push(np, dir, maxpush)
 	if success then
-		minetest.add_node(pos, {param2 = node.param2, name = pistonspec.onname})
-		minetest.add_node(np,  {param2 = node.param2, name = pistonspec.pusher})
+		minetest.set_node(pos, {param2 = node.param2, name = pistonspec.onname})
+		minetest.set_node(np,  {param2 = node.param2, name = pistonspec.pusher})
 		minetest.sound_play("piston_extend", {
 			pos = pos,
 			max_hear_distance = 20,
@@ -96,7 +96,7 @@ end
 
 local piston_off = function(pos, node)
 	local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
-	minetest.add_node(pos, {param2 = node.param2, name = pistonspec.offname})
+	minetest.set_node(pos, {param2 = node.param2, name = pistonspec.offname})
 	piston_remove_pusher(pos, node)
 
 	if pistonspec.sticky then
@@ -117,10 +117,16 @@ local piston_orientate = function(pos, placer)
 
 	local node = minetest.get_node(pos)
 	local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
-	if pitch > 55 then --looking upwards
-		minetest.add_node(pos, {name=pistonspec.piston_down})
-	elseif pitch < -55 then --looking downwards
-		minetest.add_node(pos, {name=pistonspec.piston_up})
+
+	-- looking upwards (pitch > 55) / looking downwards (pitch < -55)
+	local nn = nil
+	if pitch > 55 then nn = {name = pistonspec.piston_down} end
+	if pitch < -55 then nn = {name = pistonspec.piston_up} end
+
+	if nn then
+		minetest.set_node(pos, nn)
+		-- minetest.after, because on_placenode for unoriented piston must be processed first
+		minetest.after(0, mesecon.on_placenode, pos, nn)
 	end
 end
 
@@ -719,12 +725,12 @@ end
 local piston_get_stopper = function (node, dir, stack, stackid)
 	pistonspec = minetest.registered_nodes[node.name].mesecons_piston
 	dir = piston_get_direction(pistonspec.dir, node)
-	local pusherpos  = mesecon.addPosRule(stack[stackid].pos, dir)
+	local pusherpos  = vector.add(stack[stackid].pos, dir)
 	local pushernode = minetest.get_node(pusherpos)
 
 	if minetest.registered_nodes[node.name].mesecons_piston.pusher == pushernode.name then
 		for _, s in ipairs(stack) do
-			if  mesecon.cmpPos(s.pos, pusherpos) -- pusher is also to be pushed
+			if  vector.equals(s.pos, pusherpos) -- pusher is also to be pushed
 			and s.node.param2 == node.param2 then
 				return false
 			end
diff --git a/mesecons_pressureplates/init.lua b/mesecons_pressureplates/init.lua
index b00db9a..858f6ab 100644
--- a/mesecons_pressureplates/init.lua
+++ b/mesecons_pressureplates/init.lua
@@ -17,16 +17,16 @@ pp_on_timer = function (pos, elapsed)
 	if not basename then return end
 
 	local objs   = minetest.get_objects_inside_radius(pos, 1)
-	local two_below = mesecon.addPosRule(pos, {x = 0, y = -2, z = 0})
+	local two_below = vector.add(pos, vector.new(0, -2, 0))
 
 	if objs[1] == nil and node.name == basename .. "_on" then
-		minetest.add_node(pos, {name = basename .. "_off"})
+		minetest.set_node(pos, {name = basename .. "_off"})
 		mesecon.receptor_off(pos, mesecon.rules.pplate)
 	elseif node.name == basename .. "_off" then
 		for k, obj in pairs(objs) do
 			local objpos = obj:getpos()
 			if objpos.y > pos.y-1 and objpos.y < pos.y then
-				minetest.add_node(pos, {name = basename .. "_on"})
+				minetest.set_node(pos, {name = basename .. "_on"})
 				mesecon.receptor_on(pos, mesecon.rules.pplate )
 			end
 		end
diff --git a/mesecons_random/init.lua b/mesecons_random/init.lua
index 0136309..9e0e333 100644
--- a/mesecons_random/init.lua
+++ b/mesecons_random/init.lua
@@ -66,10 +66,10 @@ minetest.register_node("mesecons_random:ghoststone_active", {
 		offstate = "mesecons_random:ghoststone"
 	}},
 	on_construct = function(pos)
-		--remove shadow
-		pos2 = {x = pos.x, y = pos.y + 1, z = pos.z}
-		if ( minetest.get_node(pos2).name == "air" ) then
-			minetest.dig_node(pos2)
+		-- remove shadow
+		shadowpos = vector.add(pos, vector.new(0, 1, 0))
+		if (minetest.get_node(shadowpos).name == "air") then
+			minetest.dig_node(shadowpos)
 		end
 	end
 })
diff --git a/mesecons_receiver/init.lua b/mesecons_receiver/init.lua
index 4d60365..36f4659 100644
--- a/mesecons_receiver/init.lua
+++ b/mesecons_receiver/init.lua
@@ -105,10 +105,10 @@ function mesecon.receiver_place(rcpt_pos)
 	if string.find(nn.name, "mesecons:wire_") ~= nil then
 		minetest.dig_node(pos)
 		if mesecon.is_power_on(rcpt_pos) then
-			minetest.add_node(pos, {name = "mesecons_receiver:receiver_on", param2 = node.param2})
+			minetest.set_node(pos, {name = "mesecons_receiver:receiver_on", param2 = node.param2})
 			mesecon.receptor_on(pos, receiver_get_rules(node))
 		else
-			minetest.add_node(pos, {name = "mesecons_receiver:receiver_off", param2 = node.param2})
+			minetest.set_node(pos, {name = "mesecons_receiver:receiver_off", param2 = node.param2})
 		end
 		mesecon.update_autoconnect(pos)
 	end
@@ -120,7 +120,7 @@ function mesecon.receiver_remove(rcpt_pos, dugnode)
 	if string.find(nn.name, "mesecons_receiver:receiver_") ~=nil then
 		minetest.dig_node(pos)
 		local node = {name = "mesecons:wire_00000000_off"}
-		minetest.add_node(pos, node)
+		minetest.set_node(pos, node)
 		mesecon.update_autoconnect(pos)
 		mesecon.on_placenode(pos, node)
 	end
diff --git a/mesecons_torch/init.lua b/mesecons_torch/init.lua
index 5d1ad8f..8b1632b 100644
--- a/mesecons_torch/init.lua
+++ b/mesecons_torch/init.lua
@@ -91,7 +91,7 @@ minetest.register_abm({
 	action = function(pos, node)
 		local is_powered = false
 		for _, rule in ipairs(torch_get_input_rules(node)) do
-			local src = mesecon.addPosRule(pos, rule)
+			local src = vector.add(pos, rule)
 			if mesecon.is_power_on(src) then
 				is_powered = true
 			end
diff --git a/moreblocks/circular_saw.lua b/moreblocks/circular_saw.lua
index dd945b8..09fbd90 100644
--- a/moreblocks/circular_saw.lua
+++ b/moreblocks/circular_saw.lua
@@ -283,7 +283,11 @@ function circular_saw.on_metadata_inventory_put(
 	elseif listname == "recycle" then
 		-- Lets look which shape this represents:
 		local cost = circular_saw:get_cost(inv, stackname)
-		circular_saw:update_inventory(pos, cost * count)
+		local input_stack = inv:get_stack("input", 1)
+		-- check if this would not exceed input itemstack max_stacks
+		if input_stack:get_count() + ((cost * count) / 8) <= input_stack:get_stack_max() then
+			circular_saw:update_inventory(pos, cost * count)
+		end
 	end
 end
 
diff --git a/moreblocks/description.txt b/moreblocks/description.txt
new file mode 100644
index 0000000..95d7a92
--- /dev/null
+++ b/moreblocks/description.txt
@@ -0,0 +1 @@
+Adds various miscellaneous blocks to the game.
diff --git a/moreblocks/mod.conf b/moreblocks/mod.conf
new file mode 100644
index 0000000..b634ba9
--- /dev/null
+++ b/moreblocks/mod.conf
@@ -0,0 +1 @@
+name = moreblocks
diff --git a/moreblocks/stairsplus/init.lua b/moreblocks/stairsplus/init.lua
index 2a959c0..44f5972 100644
--- a/moreblocks/stairsplus/init.lua
+++ b/moreblocks/stairsplus/init.lua
@@ -18,7 +18,7 @@ and minetest.setting_getbool("creative_mode") then
 end
 
 function stairsplus:prepare_groups(groups)
-	result = {}
+	local result = {}
 	if groups then
 		for k, v in pairs(groups) do
 			if k ~= "wood" and k ~= "stone" then
diff --git a/moreblocks/stairsplus/registrations.lua b/moreblocks/stairsplus/registrations.lua
index 3e08565..c87e06b 100644
--- a/moreblocks/stairsplus/registrations.lua
+++ b/moreblocks/stairsplus/registrations.lua
@@ -44,12 +44,18 @@ for _, name in pairs(default_nodes) do
 		if type(ndef.drop) == "string" then
 			drop = ndef.drop:sub(9)
 		end
+
+		local tiles = ndef.tiles
+		if #ndef.tiles > 1 and ndef.drawtype:find("glass") then
+			tiles = { ndef.tiles[1] }
+		end
+
 		stairsplus:register_all("moreblocks", name, nodename, {
 			description = ndef.description,
 			drop = drop,
 			groups = ndef.groups,
 			sounds = ndef.sounds,
-			tiles = ndef.tiles,
+			tiles = tiles,
 			sunlight_propagates = true,
 			light_source = ndef.light_source
 		})
diff --git a/moreores/description.txt b/moreores/description.txt
new file mode 100644
index 0000000..6bd1c7c
--- /dev/null
+++ b/moreores/description.txt
@@ -0,0 +1 @@
+Adds new Ore types.
diff --git a/moreores/init.lua b/moreores/init.lua
index ff5f94e..72bd0a1 100644
--- a/moreores/init.lua
+++ b/moreores/init.lua
@@ -38,21 +38,21 @@ local function hoe_on_use(itemstack, user, pointed_thing, uses)
 	if pt.type ~= "node" then
 		return
 	end
-	
+
 	local under = minetest.get_node(pt.under)
 	local pos = {x = pt.under.x, y = pt.under.y + 1, z = pt.under.z}
 	local above = minetest.get_node(pos)
-	
+
 	-- Return if any of the nodes is not registered:
 	if not minetest.registered_nodes[under.name] then return end
 	if not minetest.registered_nodes[above.name] then return end
-	
+
 	-- Check if the node above the pointed thing is air:
 	if above.name ~= "air" then return end
-	
+
 	-- Check if pointing at dirt:
 	if minetest.get_item_group(under.name, "soil") ~= 1 then return end
-	
+
 	-- Turn the node into soil, wear out item and play sound:
 	minetest.set_node(pt.under, {name ="farming:soil"})
 	minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5})
@@ -149,7 +149,7 @@ local function add_ore(modname, description, mineral_name, oredef)
 		})
 		minetest.register_alias(mineral_name .. "_ingot", ingot)
 	end
-	
+
 	if oredef.makes.chest then
 		minetest.register_craft( {
 			output = "default:chest_locked",
@@ -163,11 +163,11 @@ local function add_ore(modname, description, mineral_name, oredef)
 			recipe = get_recipe(ingot, "lockedchest")
 		})
 	end
-	
+
 	oredef.oredef.ore_type = "scatter"
 	oredef.oredef.ore = modname .. ":mineral_" .. mineral_name
 	oredef.oredef.wherein = "default:stone"
-	
+
 	minetest.register_ore(oredef.oredef)
 
 	for tool_name, tooldef in pairs(oredef.tools) do
@@ -179,19 +179,19 @@ local function add_ore(modname, description, mineral_name, oredef)
 				groupcaps = tooldef
 			}
 		}
-		
+
 		if tool_name == "sword" then
 			tdef.tool_capabilities.full_punch_interval = oredef.full_punch_interval
 			tdef.tool_capabilities.damage_groups = oredef.damage_groups
 			tdef.description = S("%s Sword"):format(S(description))
 		end
-	
+
 		if tool_name == "pick" then
 			tdef.tool_capabilities.full_punch_interval = oredef.full_punch_interval
 			tdef.tool_capabilities.damage_groups = oredef.damage_groups
 			tdef.description = S("%s Pickaxe"):format(S(description))
 		end
-		  
+
 		if tool_name == "axe" then
 			tdef.tool_capabilities.full_punch_interval = oredef.full_punch_interval
 			tdef.tool_capabilities.damage_groups = oredef.damage_groups
@@ -203,7 +203,7 @@ local function add_ore(modname, description, mineral_name, oredef)
 			tdef.tool_capabilities.damage_groups = oredef.damage_groups
 			tdef.description = S("%s Shovel"):format(S(description))
 		end
-		
+
 		if tool_name == "hoe" then
 			tdef.description = S("%s Hoe"):format(S(description))
 			local uses = tooldef.uses
diff --git a/moreores/mod.conf b/moreores/mod.conf
new file mode 100644
index 0000000..5a9f1e2
--- /dev/null
+++ b/moreores/mod.conf
@@ -0,0 +1 @@
+name = moreores
diff --git a/moretrees/description.txt b/moretrees/description.txt
new file mode 100644
index 0000000..7c86723
--- /dev/null
+++ b/moretrees/description.txt
@@ -0,0 +1 @@
+This mod adds a whole bunch of new types of trees to the game
diff --git a/moretrees/mod.conf b/moretrees/mod.conf
new file mode 100644
index 0000000..b95f3e8
--- /dev/null
+++ b/moretrees/mod.conf
@@ -0,0 +1 @@
+name = moretrees
diff --git a/moretrees/screenshot.png b/moretrees/screenshot.png
new file mode 100644
index 0000000..cae4346
Binary files /dev/null and b/moretrees/screenshot.png differ
diff --git a/nixie_tubes/mod.conf b/nixie_tubes/mod.conf
new file mode 100644
index 0000000..2ead58f
--- /dev/null
+++ b/nixie_tubes/mod.conf
@@ -0,0 +1 @@
+name = nixie_tubes
diff --git a/pipeworks/compat.lua b/pipeworks/compat.lua
index c89e492..9c956e6 100644
--- a/pipeworks/compat.lua
+++ b/pipeworks/compat.lua
@@ -15,6 +15,10 @@ minetest.override_item("default:furnace", {
 		insert_object = function(pos, node, stack, direction)
 			local meta = minetest.get_meta(pos)
 			local inv = meta:get_inventory()
+			local timer = minetest.get_node_timer(pos)
+			if not timer:is_started() then
+				timer:start(1.0)
+			end
 			if direction.y == 1 then
 				return inv:add_item("fuel",stack)
 			else
@@ -60,6 +64,10 @@ minetest.override_item("default:furnace_active", {
 		insert_object = function(pos,node,stack,direction)
 			local meta = minetest.get_meta(pos)
 			local inv = meta:get_inventory()
+			local timer = minetest.get_node_timer(pos)
+			if not timer:is_started() then
+				timer:start(1.0)
+			end
 			if direction.y == 1 then
 				return inv:add_item("fuel", stack)
 			else
diff --git a/pipeworks/description.txt b/pipeworks/description.txt
new file mode 100644
index 0000000..9e6e800
--- /dev/null
+++ b/pipeworks/description.txt
@@ -0,0 +1 @@
+This mod uses nodeboxes to supply a complete set of 3D pipes and tubes, along devices that work with them.
diff --git a/pipeworks/mod.conf b/pipeworks/mod.conf
new file mode 100644
index 0000000..d9d2984
--- /dev/null
+++ b/pipeworks/mod.conf
@@ -0,0 +1 @@
+name = pipeworks
diff --git a/pipeworks/screenshot.png b/pipeworks/screenshot.png
new file mode 100644
index 0000000..686d955
Binary files /dev/null and b/pipeworks/screenshot.png differ
diff --git a/prefab/description.txt b/prefab/description.txt
new file mode 100644
index 0000000..74d899a
--- /dev/null
+++ b/prefab/description.txt
@@ -0,0 +1 @@
+Adds pre-fabricated concrete elements.
diff --git a/prefab/init.lua b/prefab/init.lua
index d1c7918..abc88bd 100644
--- a/prefab/init.lua
+++ b/prefab/init.lua
@@ -7,6 +7,11 @@ dofile(minetest.get_modpath("prefab").."/other.lua")
 print("Prefab Other loaded!")
 print("Prefab Loaded!")
 
+local creative = minetest.setting_getbool("creative_mode")
+
+local damage = 30
+if creative then damage = 0 end
+
 minetest.register_node("prefab:concrete", {
         drawtype = "normal",
 	description = "Block of Prefab Concrete",
@@ -333,7 +338,7 @@ minetest.register_node("prefab:electric_fence", {
 	sunlight_propagates = true,
 	paramtype = "light",
 	paramtype2 = "facedir",
-	
+	damage_per_second = damage,
 	node_box = {
 		type = "fixed",
 		fixed = {
@@ -358,7 +363,7 @@ minetest.register_node("prefab:electric_fence_corner", {
 	sunlight_propagates = true,
 	paramtype = "light",
 	paramtype2 = "facedir",
-	
+	damage_per_second = damage,
 	node_box = {
 		type = "fixed",
 		fixed = {
diff --git a/prefab/mod.conf b/prefab/mod.conf
new file mode 100644
index 0000000..3843864
--- /dev/null
+++ b/prefab/mod.conf
@@ -0,0 +1 @@
+name = prefab
diff --git a/quartz/LICENSE.txt b/quartz/LICENSE.txt
new file mode 100644
index 0000000..cce7753
--- /dev/null
+++ b/quartz/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 EvergreenTree
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/quartz/README.txt b/quartz/README.txt
index 8e6fd5d..e8674ad 100644
--- a/quartz/README.txt
+++ b/quartz/README.txt
@@ -1,12 +1,21 @@
-   ___                   _         __  __           _ 
+   ___                   _         __  __           _
   / _ \ _   _  __ _ _ __| |_ ____ |  \/  | ___   __| |
  | | | | | | |/ _` | '__| __|_  / | |\/| |/ _ \ / _` |
  | |_| | |_| | (_| | |  | |_ / /  | |  | | (_) | (_| |
   \__\_\\__,_|\__,_|_|   \__/___| |_|  |_|\___/ \__,_|
-    
 
 This mod adds quartz ore and some decorative blocks to minetest.
-                                                
+
+Version: 1.0.0
+License: MIT (see LICENSE.txt)
+
+Dependencies:
+default (found in minetest_game)
+stairs (found in minetest_game)
+moreblocks (optional, for stairsplus support)
+
+Please report bugs at the github issue tracker:
+https://github.com/4Evergreen4/quartz/issues/
 
 Crafting:
 
@@ -71,12 +80,3 @@ x|x|x
 x|c|x
 -----
 x|x|x
-
-
-License:
-
-CC BY-SA 3.0
-
-More info at http://creativecommons.org/licenses/by-sa/3.0/
-
-
diff --git a/quartz/depends.txt b/quartz/depends.txt
index 40c22ed..4451908 100644
--- a/quartz/depends.txt
+++ b/quartz/depends.txt
@@ -1,3 +1,3 @@
-default, 
-stairs,
+default
+stairs
 moreblocks?
diff --git a/quartz/description.txt b/quartz/description.txt
new file mode 100644
index 0000000..adc7fc2
--- /dev/null
+++ b/quartz/description.txt
@@ -0,0 +1 @@
+Adds quartz ore and some decorative quartz blocks
diff --git a/quartz/init.lua b/quartz/init.lua
index 6b1f7e8..6b0a41b 100644
--- a/quartz/init.lua
+++ b/quartz/init.lua
@@ -1,8 +1,10 @@
 dofile(minetest.get_modpath("quartz").."/settings.txt")
 
---Node Registration
+--
+--  Item Registration
+--
 
---Quartz Crystal
+--  Quartz Crystal
 minetest.register_craftitem("quartz:quartz_crystal", {
 	description = "Quartz Crystal",
 	inventory_image = "quartz_crystal_full.png",
@@ -12,27 +14,31 @@ minetest.register_craftitem("quartz:quartz_crystal_piece", {
 	inventory_image = "quartz_crystal_piece.png",
 })
 
---Ore
+--
+-- Node Registration
+--
+
+--  Ore
 minetest.register_node("quartz:quartz_ore", {
-         description = "Quartz Ore",
- 	 tiles = {"default_stone.png^quartz_ore.png"},
-	 groups = {cracky=3, stone=1},
-	 drop = 'quartz:quartz_crystal',
-         sounds = default.node_sound_stone_defaults(),
+	description = "Quartz Ore",
+	tiles = {"default_stone.png^quartz_ore.png"},
+	groups = {cracky=3, stone=1},
+	drop = 'quartz:quartz_crystal',
+	sounds = default.node_sound_stone_defaults(),
 })
-	 
+
 minetest.register_ore({
-    ore_type       = "scatter",
-    ore            = "quartz:quartz_ore",
-    wherein        = "default:stone",
-    clust_scarcity = 10*10*10,
-    clust_num_ores = 6,
-    clust_size     = 5,
-    y_min     = -31000,
-    y_max     = -5,
+	ore_type = "scatter",
+	ore = "quartz:quartz_ore",
+	wherein = "default:stone",
+	clust_scarcity = 10*10*10,
+	clust_num_ores = 6,
+	clust_size = 5,
+	y_min = -31000,
+	y_max = -5,
 })
 
---Quartz Block
+-- Quartz Block
 minetest.register_node("quartz:block", {
 	description = "Quartz Block",
 	tiles = {"quartz_block.png"},
@@ -40,7 +46,7 @@ minetest.register_node("quartz:block", {
 	sounds = default.node_sound_glass_defaults(),
 })
 
---Chiseled Quartz
+-- Chiseled Quartz
 minetest.register_node("quartz:chiseled", {
 	description = "Chiseled Quartz",
 	tiles = {"quartz_chiseled.png"},
@@ -48,7 +54,7 @@ minetest.register_node("quartz:chiseled", {
 	sounds = default.node_sound_glass_defaults(),
 })
 
---Quartz Pillar
+-- Quartz Pillar
 minetest.register_node("quartz:pillar", {
 	description = "Quartz Pillar",
 	paramtype2 = "facedir",
@@ -58,8 +64,7 @@ minetest.register_node("quartz:pillar", {
 	on_place = minetest.rotate_node
 })
 
-
---Stairs & Slabs
+-- Stairs & Slabs
 stairs.register_stair_and_slab("quartzblock", "quartz:block",
 		{cracky=3, oddly_breakable_by_hand=1},
 		{"quartz_block.png"},
@@ -72,17 +77,13 @@ stairs.register_slab("quartzstair", "quartz:pillar",
 		{"quartz_pillar_top.png", "quartz_pillar_top.png", "quartz_pillar_side.png"},
 		"Quartz Pillar stair",
 		"Quartz Pillar slab",
-		default.node_sound_glass_defaults())		
+		default.node_sound_glass_defaults())
 
-		
-		
-		
-		
-		
-		
---Crafting
+--
+-- Crafting
+--
 
---Quartz Crystal Piece
+-- Quartz Crystal Piece
 minetest.register_craft({
 	output = '"quartz:quartz_crystal_piece" 3',
 	recipe = {
@@ -90,7 +91,7 @@ minetest.register_craft({
 	}
 })
 
---Quartz Block
+-- Quartz Block
 minetest.register_craft({
 	output = '"quartz:block" 4',
 	recipe = {
@@ -99,8 +100,8 @@ minetest.register_craft({
 		{'', '', ''}
 	}
 })
-	
---Chiseled Quartz
+
+-- Chiseled Quartz
 minetest.register_craft({
 	output = 'quartz:chiseled 2',
 	recipe = {
@@ -110,7 +111,7 @@ minetest.register_craft({
 	}
 })
 
---Chiseled Quartz(for stairsplus)
+-- Chiseled Quartz (for stairsplus)
 minetest.register_craft({
 	output = 'quartz:chiseled 2',
 	recipe = {
@@ -120,7 +121,7 @@ minetest.register_craft({
 	}
 })
 
---Quartz Pillar
+-- Quartz Pillar
 minetest.register_craft({
 	output = 'quartz:pillar 2',
 	recipe = {
@@ -130,11 +131,15 @@ minetest.register_craft({
 	}
 })
 
---abms
-local dirs2 = { 12, 9, 18, 7, 12 }
+--
+-- ABMS
+--
+
+local dirs2 = {12, 9, 18, 7, 12}
 
+-- Replace all instances of the horizontal quartz pillar with the
 minetest.register_abm({
-	nodenames = { "quartz:pillar_horizontal" },
+	nodenames = {"quartz:pillar_horizontal"},
 	interval = 1,
 	chance = 1,
 	action = function(pos, node, active_object_count, active_object_count_wider)
@@ -144,10 +149,46 @@ minetest.register_abm({
 	end,
 })
 
---These are deprecated, don't use them
+--
+-- Compatibility with stairsplus
+--
+
+if minetest.get_modpath("moreblocks") and enable_stairsplus then
+	register_stair_slab_panel_micro("quartz", "block", "quartz:block",
+		{cracky=3},
+		{"quartz_block.png"},
+		"Quartz Block",
+		"block",
+		0
+	)
+
+	register_stair_slab_panel_micro("quartz", "chiseled", "quartz:chiseled",
+		{cracky=3},
+		{"quartz_chiseled.png"},
+		"Chiseled Quartz",
+		"chiseled",
+		0
+	)
+
+	register_stair_slab_panel_micro("quartz", "pillar", "quartz:pillar",
+		{cracky=3},
+		{"quartz_pillar_top.png", "quartz_pillar_top.png", "quartz_pillar_side.png"},
+		"Quartz Pillar",
+		"pillar",
+		0
+	)
+
+	table.insert(circular_saw.known_stairs, "quartz:block")
+	table.insert(circular_saw.known_stairs, "quartz:chiseled")
+	table.insert(circular_saw.known_stairs, "quartz:pillar")
+end
+
+--
+-- Deprecated
+--
 
 if enable_horizontal_pillar then
-	--Quartz Pillar (horizontal)
+	-- Quartz Pillar (horizontal)
 	minetest.register_node("quartz:pillar_horizontal", {
 			description = "Quartz Pillar Horizontal",
 			tiles = {"quartz_pillar_side.png", "quartz_pillar_side.png", "quartz_pillar_side.png^[transformR90",
@@ -158,33 +199,3 @@ if enable_horizontal_pillar then
 			sounds = default.node_sound_glass_defaults(),
 	})
 end
-
-
---Compatibility with stairsplus
-
-if minetest.get_modpath("moreblocks") and enable_stairsplus then
-	register_stair_slab_panel_micro("quartz", "block", "quartz:block",
-	{cracky=3},
-	{"quartz_block.png"},
-	"Quartz Block",
-	"block",
-	0)
-	
-	register_stair_slab_panel_micro("quartz", "chiseled", "quartz:chiseled",
-	{cracky=3},
-	{"quartz_chiseled.png"},
-	"Chiseled Quartz",
-	"chiseled",
-	0)
-	
-	register_stair_slab_panel_micro("quartz", "pillar", "quartz:pillar",
-	{cracky=3},
-	{"quartz_pillar_top.png", "quartz_pillar_top.png", "quartz_pillar_side.png"},
-	"Quartz Pillar",
-	"pillar",
-	0)
-	
-	table.insert(circular_saw.known_stairs, "quartz:block")
-	table.insert(circular_saw.known_stairs, "quartz:chiseled")
-	table.insert(circular_saw.known_stairs, "quartz:pillar")
-end	
diff --git a/quartz/screenshot.png b/quartz/screenshot.png
new file mode 100644
index 0000000..3d3cba9
Binary files /dev/null and b/quartz/screenshot.png differ
diff --git a/quartz/textures/quartz_ore.png b/quartz/textures/quartz_ore.png
index 805666a..69d5ec4 100644
Binary files a/quartz/textures/quartz_ore.png and b/quartz/textures/quartz_ore.png differ
diff --git a/signs_lib/description.txt b/signs_lib/description.txt
new file mode 100644
index 0000000..d157852
--- /dev/null
+++ b/signs_lib/description.txt
@@ -0,0 +1 @@
+Adds signs with readable text.
diff --git a/signs_lib/init.lua b/signs_lib/init.lua
index ce3e37a..1f43453 100644
--- a/signs_lib/init.lua
+++ b/signs_lib/init.lua
@@ -116,7 +116,7 @@ signs_lib.gettext = S
 -- the list of standard sign nodes
 
 signs_lib.sign_node_list = {
-		"default:sign_wall",
+		"default:sign_wall_wood",
 		"signs:sign_yard",
 		"signs:sign_hanging",
 		"signs:sign_wall_green",
@@ -130,6 +130,17 @@ signs_lib.sign_node_list = {
 		"locked_sign:sign_wall_locked"
 }
 
+local default_sign, default_sign_image
+
+-- Default sign was renamed in 0.4.14. Support both & old versions.
+if minetest.registered_nodes["default:sign_wall_wood"] then
+	default_sign = "default:sign_wall_wood"
+	default_sign_image = "default_sign_wood.png"
+else
+	default_sign = "default:sign_wall"
+	default_sign_image = "default_sign_wall.png"
+end
+
 --table copy
 
 function signs_lib.table_copy(t)
@@ -501,7 +512,7 @@ signs_lib.update_sign = function(pos, fields, owner)
 	elseif signnode.name == "signs:sign_hanging" then
 		sign_info = signs_lib.hanging_sign_model.textpos[minetest.get_node(pos).param2 + 1]
 	elseif string.find(signnode.name, "sign_wall") then
-		if signnode.name == "default:sign_wall" 
+		if signnode.name == default_sign
 		  or signnode.name == "locked_sign:sign_wall_locked" then
 			sign_info = signs_lib.regular_wall_sign_model.textpos[minetest.get_node(pos).param2 + 1]
 		else
@@ -570,13 +581,13 @@ function signs_lib.determine_sign_type(itemstack, placer, pointed_thing, locked)
 		local pt_name = minetest.get_node(under).name
 		local signname = itemstack:get_name()
 
-		if fences_with_sign[pt_name] and signname == "default:sign_wall" then
+		if fences_with_sign[pt_name] and signname == default_sign then
 			minetest.add_node(under, {name = fences_with_sign[pt_name], param2 = fdir})
-		elseif wdir == 0 and signname == "default:sign_wall" then
+		elseif wdir == 0 and signname == default_sign then
 			minetest.add_node(above, {name = "signs:sign_hanging", param2 = fdir})
-		elseif wdir == 1 and signname == "default:sign_wall" then
+		elseif wdir == 1 and signname == default_sign then
 			minetest.add_node(above, {name = "signs:sign_yard", param2 = fdir})
-		elseif signname ~= "default:sign_wall"
+		elseif signname ~= default_sign
 		  and signname ~= "locked_sign:sign_wall_locked" then -- it's a metal wall sign.
 			minetest.add_node(above, {name = signname, param2 = fdir})
 		else -- it must be a default or locked wooden wall sign
@@ -616,10 +627,10 @@ function signs_lib.receive_fields(pos, formname, fields, sender, lock)
 	end
 end
 
-minetest.register_node(":default:sign_wall", {
+minetest.register_node(":"..default_sign, {
 	description = S("Sign"),
-	inventory_image = "default_sign_wall.png",
-	wield_image = "default_sign_wall.png",
+	inventory_image = default_sign_image,
+	wield_image = default_sign_image,
 	node_placement_prediction = "",
 	sunlight_propagates = true,
 	paramtype = "light",
@@ -659,7 +670,7 @@ minetest.register_node(":signs:sign_yard", {
 	},
     tiles = {"signs_top.png", "signs_bottom.png", "signs_side.png", "signs_side.png", "signs_back.png", "signs_front.png"},
     groups = {choppy=2, dig_immediate=2},
-    drop = "default:sign_wall",
+    drop = default_sign,
 
     on_construct = function(pos)
         signs_lib.construct_sign(pos)
@@ -694,7 +705,7 @@ minetest.register_node(":signs:sign_hanging", {
 		"signs_hanging_front.png"
 	},
     groups = {choppy=2, dig_immediate=2},
-    drop = "default:sign_wall",
+    drop = default_sign,
 
     on_construct = function(pos)
         signs_lib.construct_sign(pos)
@@ -728,7 +739,7 @@ minetest.register_node(":signs:sign_post", {
     drop = {
 		max_items = 2,
 		items = {
-			{ items = { "default:sign_wall" }},
+			{ items = { default_sign }},
 			{ items = { "default:fence_wood" }},
 		},
     },
@@ -909,7 +920,7 @@ function signs_lib.register_fence_with_sign(fencename, fencewithsignname)
 	    node.name = fencename
 	    minetest.add_node(pos, node)
 	end
-    def_sign.drop = "default:sign_wall"
+    def_sign.drop = default_sign
 	minetest.register_node(":"..fencename, def)
 	minetest.register_node(":"..fencewithsignname, def_sign)
 	table.insert(signs_lib.sign_node_list, fencewithsignname)
@@ -950,7 +961,7 @@ minetest.register_craft({
 minetest.register_craft({
     	output = "locked_sign:sign_wall_locked",
     	recipe = {
-        	{"default:sign_wall"},
+        	{default_sign},
         	{"default:steel_ingot"},
     },
 })
diff --git a/signs_lib/mod.conf b/signs_lib/mod.conf
new file mode 100644
index 0000000..c8937d0
--- /dev/null
+++ b/signs_lib/mod.conf
@@ -0,0 +1 @@
+name = signs_lib
diff --git a/signs_lib/screenshot.png b/signs_lib/screenshot.png
new file mode 100644
index 0000000..17229a3
Binary files /dev/null and b/signs_lib/screenshot.png differ
diff --git a/spawn/depends.txt b/spawn/depends.txt
new file mode 100644
index 0000000..e69de29
diff --git a/spawn/init.lua b/spawn/init.lua
index 09eec7b..e4a55df 100644
--- a/spawn/init.lua
+++ b/spawn/init.lua
@@ -1,5 +1,9 @@
+--a Fusion of cheapies and Zeno's spawn mode with extra CWz flavored goodness
+--Originally written by VanessaE (I think), rewritten by cheapie
+--WTFPL
 
--- Some modified from: Minetest: builtin/static_spawn.lua
+
+-- Some modified from: Minetest: builtin/static_spawn.lua LGPL
 
 local function check_spawnpoint(config_setting)
 	if not minetest.setting_get(config_setting) then
@@ -48,6 +52,7 @@ end
 
 minetest.register_chatcommand("spawn", {
 	description = "Teleport to the spawn location",
+	privs = {},
 	func = function(name, _)
 		local ok = put_player_at_spawn(minetest.get_player_by_name(name))
 		if ok then
@@ -65,3 +70,48 @@ end)
 minetest.register_on_respawnplayer(function(obj)
 	return put_player_at_spawn(obj)
 end)
+
+
+minetest.register_chatcommand("setspawn", {
+	params = "",
+	description = "Sets the spawn point to your current position",
+	privs = { server=true },
+	func = function(name, param)
+		local player = minetest.get_player_by_name(name)
+		if not player then
+			return false, "Player not found"
+		end
+		local pos = player:getpos()
+		local x = pos.x
+		local y = pos.y
+		local z = pos.z
+		local pos_string = x..","..y..","..z
+		local pos_string_2 = "Setting spawn point to ("..x..", "..y..", "..z..")"
+		minetest.setting_set("static_spawnpoint",pos_string)
+		spawn_spawnpos = pos
+		minetest.setting_save()
+		return true, pos_string_2
+	end,
+})
+-- alt_spawnpoint
+minetest.register_chatcommand("setaltspawn", {
+	params = "",
+	description = "Sets the alt spawn point to your current position",
+	privs = { server=true },
+	func = function(name, param)
+		local player = minetest.get_player_by_name(name)
+		if not player then
+			return false, "Player not found"
+		end
+		local pos = player:getpos()
+		local x = pos.x
+		local y = pos.y
+		local z = pos.z
+		local pos_string = x..","..y..","..z
+		local pos_string_2 = "Setting alt spawn point to ("..x..", "..y..", "..z..")"
+		minetest.setting_set("alt_spawnpoint",pos_string)
+		spawn_spawnpos = pos
+		minetest.setting_save()
+		return true, pos_string_2
+	end,
+})
diff --git a/technic/helpers.lua b/technic/helpers.lua
index e8efcf3..164cf7e 100644
--- a/technic/helpers.lua
+++ b/technic/helpers.lua
@@ -1,27 +1,38 @@
---load config
-local sepchar = nil
+local digit_sep_esc
 do
-	local sepcode = technic.config:get("thousand_separator")
-	--default is SI style
-	sepchar = sepcode and string.char(sepcode) or " "
-	baresepchar = sepchar
-	--handling if sepchar is magic...
-	for magic in string.gmatch("().%+-*?[^$", ".") do
-		if sepchar == magic then sepchar = "%"..sepchar end
+	local sep = technic.config:get("digit_separator")
+	sep = tonumber(sep) and string.char(sep) or sep or " "
+	-- Escape for gsub
+	for magic in ("().%+-*?[^$"):gmatch(".") do
+		if sep == magic then
+			sep = "%"..sep
+		end
 	end
+	digit_sep_esc = sep
+end
+
+
+function technic.pretty_num(num)
+	local str, k = tostring(num), nil
+	repeat
+		str, k = str:gsub("^(-?%d+)(%d%d%d)", "%1"..digit_sep_esc.."%2")
+	until k == 0
+	return str
 end
 
--- Only changes name, keeps other params
+
+--- Same as minetest.swap_node, but only changes name
+-- and doesn't re-set if already set.
 function technic.swap_node(pos, name)
 	local node = minetest.get_node(pos)
 	if node.name ~= name then
 		node.name = name
 		minetest.swap_node(pos, node)
 	end
-	return node.name
 end
 
--- Fully charge RE chargeable item.
+
+--- Fully charge RE chargeable item.
 -- Must be defined early to reference in item definitions.
 function technic.refill_RE_charge(stack)
 	local max_charge = technic.power_tools[stack:get_name()]
@@ -33,35 +44,83 @@ function technic.refill_RE_charge(stack)
 	return stack
 end
 
-local function resolve_name(function_name)
-	local a = _G
-	for key in string.gmatch(function_name, "([^%.]+)(%.?)") do
-		if a[key] then
-			a = a[key]
-		else
-			return nil
-		end
-	end
-	return a
-end
 
-function technic.function_exists(function_name)
-	return type(resolve_name(function_name)) == 'function'
-end
-
--- if the node is loaded, returns it. If it isn't loaded, load it and return nil.
+-- If the node is loaded, returns it.  If it isn't loaded, load it and return nil.
 function technic.get_or_load_node(pos)
-	local node_or_nil = minetest.get_node_or_nil(pos)
-	if node_or_nil then return node_or_nil end
+	local node = minetest.get_node_or_nil(pos)
+	if node then return node end
 	local vm = VoxelManip()
 	local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
 	return nil
 end
 
-function technic.prettynum(num)
-	local str, k = tostring(num), nil
-	repeat
-		str, k = str:gsub("^(-?%d+)(%d%d%d)", "%1"..sepchar.."%2")
-	until k == 0
-	return str
-end
\ No newline at end of file
+
+technic.tube_inject_item = pipeworks.tube_inject_item or function(pos, start_pos, velocity, item)
+	local tubed = pipeworks.tube_item(vector.new(pos), item)
+	tubed:get_luaentity().start_pos = vector.new(start_pos)
+	tubed:setvelocity(velocity)
+	tubed:setacceleration(vector.new(0, 0, 0))
+end
+
+
+-- Based on code by Uberi: https://gist.github.com/Uberi/3125280
+function technic.trace_node_ray(pos, dir, range)
+	local p = vector.round(pos)
+	local x_step,      y_step,      z_step      = 0, 0, 0
+	local x_component, y_component, z_component = 0, 0, 0
+	local x_intersect, y_intersect, z_intersect = 0, 0, 0
+
+	if dir.x == 0 then
+		x_intersect = math.huge
+	elseif dir.x > 0 then
+		x_step = 1
+		x_component = 1 / dir.x
+		x_intersect = x_component
+	else
+		x_step = -1
+		x_component = 1 / -dir.x
+	end
+	if dir.y == 0 then
+		y_intersect = math.huge
+	elseif dir.y > 0 then
+		y_step = 1
+		y_component = 1 / dir.y
+		y_intersect = y_component
+	else
+		y_step = -1
+		y_component = 1 / -dir.y
+	end
+	if dir.z == 0 then
+		z_intersect = math.huge
+	elseif dir.z > 0 then
+		z_step = 1
+		z_component = 1 / dir.z
+		z_intersect = z_component
+	else
+		z_step = -1
+		z_component = 1 / -dir.z
+	end
+
+	return function()
+		if x_intersect < y_intersect then
+			if x_intersect < z_intersect then
+				p.x = p.x + x_step
+				x_intersect = x_intersect + x_component
+			else
+				p.z = p.z + z_step
+				z_intersect = z_intersect + z_component
+			end
+		elseif y_intersect < z_intersect then
+			p.y = p.y + y_step
+			y_intersect = y_intersect + y_component
+		else
+			p.z = p.z + z_step
+			z_intersect = z_intersect + z_component
+		end
+		if vector.distance(pos, p) > range then
+			return nil
+		end
+		return p
+	end
+end
+
diff --git a/technic/init.lua b/technic/init.lua
index 25361af..70ad848 100644
--- a/technic/init.lua
+++ b/technic/init.lua
@@ -2,22 +2,18 @@
 -- namespace: technic
 -- (c) 2012-2013 by RealBadAngel <mk@realbadangel.pl>
 
+local load_start = os.clock()
+
 technic = rawget(_G, "technic") or {}
 technic.creative_mode = minetest.setting_getbool("creative_mode")
 
-technic.tube_inject_item = pipeworks.tube_inject_item or function (pos, start_pos, velocity, item)
-	local tubed = pipeworks.tube_item(vector.new(pos), item)
-	tubed:get_luaentity().start_pos = vector.new(start_pos)
-	tubed:setvelocity(velocity)
-	tubed:setacceleration(vector.new(0, 0, 0))
-end
 
-local load_start = os.clock()
 local modpath = minetest.get_modpath("technic")
 technic.modpath = modpath
 
+
 -- Boilerplate to support intllib
-if minetest.get_modpath("intllib") then
+if rawget(_G, "intllib") then
 	technic.getter = intllib.Getter()
 else
 	technic.getter = function(s,a,...)if a==nil then return s end a={a,...}return s:gsub("(@?)@(%(?)(%d+)(%)?)",function(e,o,n,c)if e==""then return a[tonumber(n)]..(o==""and c or"")else return"@"..o..n..c end end) end
diff --git a/technic/legacy.lua b/technic/legacy.lua
index 8360a71..6a080e1 100644
--- a/technic/legacy.lua
+++ b/technic/legacy.lua
@@ -22,9 +22,6 @@ technic.legacy_nodenames = {
 	["technic:compressor"]        = "technic:lv_compressor",
 	["technic:compressor_active"] = "technic:lv_compressor_active",
 	["technic:hv_battery_box"] = "technic:hv_battery_box0",
-	["technic:hv_cable"] = "technic:hv_cable0",
-	["technic:lv_cable"] = "technic:lv_cable0",
-	["technic:mv_cable"] = "technic:mv_cable0",
 	["technic:mv_battery_box"] = "technic:mv_battery_box0",
 	["technic:generator"]        = "technic:lv_generator",
 	["technic:generator_active"] = "technic:lv_generator_active",
@@ -36,3 +33,9 @@ for old, new in pairs(technic.legacy_nodenames) do
 	minetest.register_alias(old, new)
 end
 
+for i = 0, 64 do
+	minetest.register_alias("technic:hv_cable"..i, "technic:hv_cable")
+	minetest.register_alias("technic:mv_cable"..i, "technic:mv_cable")
+	minetest.register_alias("technic:lv_cable"..i, "technic:lv_cable")
+end
+
diff --git a/technic/machines/HV/battery_box.lua b/technic/machines/HV/battery_box.lua
index 1e054ec..9093ba9 100644
--- a/technic/machines/HV/battery_box.lua
+++ b/technic/machines/HV/battery_box.lua
@@ -4,7 +4,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:mv_battery_box0', 'technic:mv_battery_box0', 'technic:mv_battery_box0'},
 		{'technic:mv_battery_box0', 'technic:hv_transformer',  'technic:mv_battery_box0'},
-		{'',                        'technic:hv_cable0',       ''},
+		{'',                        'technic:hv_cable',        ''},
 	}
 })
 
diff --git a/technic/machines/HV/cables.lua b/technic/machines/HV/cables.lua
index 25297c8..0b86a23 100644
--- a/technic/machines/HV/cables.lua
+++ b/technic/machines/HV/cables.lua
@@ -1,9 +1,9 @@
 
 minetest.register_craft({
-	output = 'technic:hv_cable0 3',
+	output = 'technic:hv_cable 3',
 	recipe = {
 		{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
-		{'technic:mv_cable0',          'technic:mv_cable0',          'technic:mv_cable0'},
+		{'technic:mv_cable',           'technic:mv_cable',           'technic:mv_cable'},
 		{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
 	}
 }) 
diff --git a/technic/machines/HV/forcefield.lua b/technic/machines/HV/forcefield.lua
index 0f0836d..3bf93b0 100644
--- a/technic/machines/HV/forcefield.lua
+++ b/technic/machines/HV/forcefield.lua
@@ -15,7 +15,7 @@ minetest.register_craft({
 	recipe = {
 			{"default:mese",         "technic:motor",          "default:mese"        },
 			{"technic:deployer_off", "technic:machine_casing", "technic:deployer_off"},
-			{"default:mese",         "technic:hv_cable0",      "default:mese"        },
+			{"default:mese",         "technic:hv_cable",       "default:mese"        },
 	}
 })
 
@@ -195,7 +195,7 @@ end
 minetest.register_node("technic:forcefield_emitter_off", {
 	description = S("%s Forcefield Emitter"):format("HV"),
 	tiles = {"technic_forcefield_emitter_off.png"},
-	groups = {cracky = 1, technic_machine = 1},
+	groups = {cracky = 1, technic_machine = 1, technic_hv = 1},
 	on_receive_fields = forcefield_receive_fields,
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
@@ -215,7 +215,8 @@ minetest.register_node("technic:forcefield_emitter_off", {
 minetest.register_node("technic:forcefield_emitter_on", {
 	description = S("%s Forcefield Emitter"):format("HV"),
 	tiles = {"technic_forcefield_emitter_on.png"},
-	groups = {cracky = 1, technic_machine = 1, not_in_creative_inventory=1},
+	groups = {cracky = 1, technic_machine = 1, technic_hv = 1,
+			not_in_creative_inventory=1},
 	drop = "technic:forcefield_emitter_off",
 	on_receive_fields = forcefield_receive_fields,
 	on_destruct = function(pos)
diff --git a/technic/machines/HV/generator.lua b/technic/machines/HV/generator.lua
index aa83590..3fb494b 100644
--- a/technic/machines/HV/generator.lua
+++ b/technic/machines/HV/generator.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:carbon_plate',          'technic:mv_generator',   'technic:composite_plate'},
 		{'pipeworks:tube_1',              'technic:hv_transformer', 'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:hv_cable0',      'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:hv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/HV/nuclear_reactor.lua b/technic/machines/HV/nuclear_reactor.lua
index 3aa1ba8..c7951ab 100644
--- a/technic/machines/HV/nuclear_reactor.lua
+++ b/technic/machines/HV/nuclear_reactor.lua
@@ -1,34 +1,34 @@
--- 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 (one week))
--- 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   = 7 * 24 * 60 * 60       -- (seconds).
-local power_supply = 100000                 -- EUs
-local fuel_type    = "technic:uranium_fuel" -- The reactor burns this stuff
+--[[
+ 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.
+Provides 10000 HV EUs for one week (only counted when loaded).
+
+The nuclear reactor core requires a casing of water and a protective
+shield to work.  This is checked now and then and if the casing is not
+intact the reactor will melt down!
+--]]
+
+local burn_ticks = 7 * 24 * 60 * 60  -- Seconds
+local power_supply = 100000  -- EUs
+local fuel_type = "technic:uranium_fuel"  -- The reactor burns this
 
 local S = technic.getter
 
-if not vector.length_square then
-	vector.length_square = function (v)
-		return v.x*v.x + v.y*v.y + v.z*v.z
-	end
-end
+local reactor_desc = S("@1 Nuclear Reactor Core", S("HV")),
 
--- FIXME: recipe must make more sense like a rod recepticle, steam chamber, HV generator?
+
+-- FIXME: Recipe should make more sense like a rod recepticle, steam chamber, HV generator?
 minetest.register_craft({
 	output = 'technic:hv_nuclear_reactor_core',
 	recipe = {
 		{'technic:carbon_plate',          'default:obsidian_glass', 'technic:carbon_plate'},
 		{'technic:composite_plate',       'technic:machine_casing', 'technic:composite_plate'},
-		{'technic:stainless_steel_ingot',      'technic:hv_cable0', 'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:hv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
-local generator_formspec =
+local reactor_formspec =
 	"invsize[8,9;]"..
 	"label[0,0;"..S("Nuclear Reactor Rod Compartment").."]"..
 	"list[current_name;src;2,1;3,2;]"..
@@ -36,103 +36,111 @@ local generator_formspec =
 	"listring[]"
 
 -- "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 },
+local node_box = {
+	{-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},
 }
 
+local SS_OFF = 0
+local SS_DANGER = 1
+local SS_CLEAR = 2
+
 local reactor_siren = {}
-local function siren_set_state(pos, newstate)
+local function siren_set_state(pos, state)
 	local hpos = minetest.hash_node_position(pos)
 	local siren = reactor_siren[hpos]
 	if not siren then
-		if newstate == "off" then return end
-		siren = {state="off"}
+		if state == SS_OFF then return end
+		siren = {state=SS_OFF}
 		reactor_siren[hpos] = siren
 	end
-	if newstate == "danger" and siren.state ~= "danger" then
+	if state == SS_DANGER and siren.state ~= SS_DANGER then
 		if siren.handle then minetest.sound_stop(siren.handle) end
-		siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop", {pos=pos, gain=1.5, loop=true, max_hear_distance=48})
-		siren.state = "danger"
-	elseif newstate == "clear" then
+		siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop",
+				{pos=pos, gain=1.5, loop=true, max_hear_distance=48})
+		siren.state = SS_DANGER
+	elseif state == SS_CLEAR then
 		if siren.handle then minetest.sound_stop(siren.handle) end
-		local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear", {pos=pos, gain=1.5, loop=false, max_hear_distance=48})
+		local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear",
+				{pos=pos, gain=1.5, loop=false, max_hear_distance=48})
 		siren.handle = clear_handle
-		siren.state = "clear"
-		minetest.after(10, function ()
-			if siren.handle == clear_handle then
-				minetest.sound_stop(clear_handle)
-				if reactor_siren[hpos] == siren then
-					reactor_siren[hpos] = nil
-				end
+		siren.state = SS_CLEAR
+		minetest.after(10, function()
+			if siren.handle ~= clear_handle then return end
+			minetest.sound_stop(clear_handle)
+			if reactor_siren[hpos] == siren then
+				reactor_siren[hpos] = nil
 			end
 		end)
-	elseif newstate == "off" and siren.state ~= "off" then
+	elseif state == SS_OFF and siren.state ~= SS_OFF then
 		if siren.handle then minetest.sound_stop(siren.handle) end
-		siren.handle = nil
 		reactor_siren[hpos] = nil
 	end
 end
+
 local function siren_danger(pos, meta)
 	meta:set_int("siren", 1)
-	siren_set_state(pos, "danger")
+	siren_set_state(pos, SS_DANGER)
 end
+
 local function siren_clear(pos, meta)
 	if meta:get_int("siren") ~= 0 then
-		siren_set_state(pos, "clear")
+		siren_set_state(pos, SS_CLEAR)
 		meta:set_int("siren", 0)
 	end
 end
 
--- The standard reactor structure consists of a 9x9x9 cube.  A cross
--- section through the middle:
---
---     CCCC CCCC
---     CBBB BBBC
---     CBSS SSBC
---     CBSWWWSBC
---     CBSW#WSBC
---     CBSW|WSBC
---     CBSS|SSBC
---     CBBB|BBBC
---     CCCC|CCCC
---     C = Concrete, B = Blast-resistant concrete, S = Stainless Steel,
---     W = water node, # = reactor core, | = HV cable
---
--- The man-hole and the HV cable are only in the middle, and the man-hole
--- is optional.
---
--- For the reactor to operate and not melt down, it insists on the inner
--- 7x7x7 portion (from the core out to the blast-resistant concrete)
--- being intact.  Intactness only depends on the number of nodes of the
--- right type in each layer.  The water layer must have water in all but
--- at most one node; the steel and blast-resistant concrete layers must
--- have the right material in all but at most two nodes.  The permitted
--- gaps are meant for the cable and man-hole, but can actually be anywhere
--- and contain anything.  For the reactor to be useful, a cable must
--- connect to the core, but it can go in any direction.
---
--- The outer concrete layer of the standard structure is not required
--- for the reactor to operate.  It is noted here because it used to
--- be mandatory, and for historical reasons (that it predates the
--- implementation of radiation) it needs to continue being adequate
--- shielding of legacy reactors.  If it ever ceases to be adequate
--- shielding for new reactors, legacy ones should be grandfathered.
-local reactor_structure_badness = function(pos)
+--[[
+The standard reactor structure consists of a 9x9x9 cube.  A cross
+section through the middle:
+
+	CCCC CCCC
+	CBBB BBBC
+	CBSS SSBC
+	CBSWWWSBC
+	CBSW#WSBC
+	CBSW|WSBC
+	CBSS|SSBC
+	CBBB|BBBC
+	CCCC|CCCC
+	C = Concrete, B = Blast-resistant concrete, S = Stainless Steel,
+	W = water node, # = reactor core, | = HV cable
+
+The man-hole and the HV cable are only in the middle, and the man-hole
+is optional.
+
+For the reactor to operate and not melt down, it insists on the inner
+7x7x7 portion (from the core out to the blast-resistant concrete)
+being intact.  Intactness only depends on the number of nodes of the
+right type in each layer.  The water layer must have water in all but
+at most one node; the steel and blast-resistant concrete layers must
+have the right material in all but at most two nodes.  The permitted
+gaps are meant for the cable and man-hole, but can actually be anywhere
+and contain anything.  For the reactor to be useful, a cable must
+connect to the core, but it can go in any direction.
+
+The outer concrete layer of the standard structure is not required
+for the reactor to operate.  It is noted here because it used to
+be mandatory, and for historical reasons (that it predates the
+implementation of radiation) it needs to continue being adequate
+shielding of legacy reactors.  If it ever ceases to be adequate
+shielding for new reactors, legacy ones should be grandfathered.
+--]]
+local function reactor_structure_badness(pos)
 	local vm = VoxelManip()
 	local pos1 = vector.subtract(pos, 3)
 	local pos2 = vector.add(pos, 3)
@@ -179,14 +187,16 @@ local reactor_structure_badness = function(pos)
 	return (25 - waterlayer) + (96 - steellayer) + (216 - blastlayer)
 end
 
-local function meltdown_reactor(pos)
-	print("A reactor melted down at "..minetest.pos_to_string(pos))
+
+local function melt_down_reactor(pos)
+	minetest.log("action", "A reactor melted down at "..minetest.pos_to_string(pos))
 	minetest.set_node(pos, {name="technic:corium_source"})
 end
 
+
 minetest.register_abm({
 	nodenames = {"technic:hv_nuclear_reactor_core_active"},
-	interval = 1,
+	interval = 4,
 	chance = 1,
 	action = function (pos, node)
 		local meta = minetest.get_meta(pos)
@@ -194,14 +204,14 @@ minetest.register_abm({
 		local accum_badness = meta:get_int("structure_accumulated_badness")
 		if badness == 0 then
 			if accum_badness ~= 0 then
-				meta:set_int("structure_accumulated_badness", accum_badness - 1)
+				meta:set_int("structure_accumulated_badness", accum_badness - 4)
 				siren_clear(pos, meta)
 			end
 		else
 			siren_danger(pos, meta)
 			accum_badness = accum_badness + badness
-			if accum_badness >= 100 then
-				meltdown_reactor(pos)
+			if accum_badness >= 25 then
+				melt_down_reactor(pos)
 			else
 				meta:set_int("structure_accumulated_badness", accum_badness)
 			end
@@ -209,40 +219,36 @@ minetest.register_abm({
 	end,
 })
 
-local run = function(pos, node)
+local function run(pos, node)
 	local meta = minetest.get_meta(pos)
-	local machine_name = S("Nuclear %s Generator Core"):format("HV")
 	local burn_time = meta:get_int("burn_time") or 0
 
 	if burn_time >= burn_ticks or burn_time == 0 then
 		local inv = meta:get_inventory()
 		if not inv:is_empty("src") then 
-			local srclist = inv:get_list("src")
+			local src_list = inv:get_list("src")
 			local correct_fuel_count = 0
-			for _, srcstack in pairs(srclist) do
-				if srcstack then
-					if  srcstack:get_name() == fuel_type then
-						correct_fuel_count = correct_fuel_count + 1
-					end
+			for _, src_stack in pairs(src_list) do
+				if src_stack and src_stack:get_name() == fuel_type then
+					correct_fuel_count = correct_fuel_count + 1
 				end
 			end
-			-- Check that the reactor is complete as well
-			-- as the correct number of correct fuel
+			-- Check that the reactor is complete and has the correct fuel
 			if correct_fuel_count == 6 and
-			   reactor_structure_badness(pos) == 0 then
+					reactor_structure_badness(pos) == 0 then
 				meta:set_int("burn_time", 1)
 				technic.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)
+				for idx, src_stack in pairs(src_list) do
+					src_stack:take_item()
+					inv:set_stack("src", idx, src_stack)
 				end
 				return
 			end
 		end
 		meta:set_int("HV_EU_supply", 0)
 		meta:set_int("burn_time", 0)
-		meta:set_string("infotext", S("%s Idle"):format(machine_name))
+		meta:set_string("infotext", S("%s Idle"):format(reactor_desc))
 		technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
 		meta:set_int("structure_accumulated_badness", 0)
 		siren_clear(pos, meta)
@@ -250,40 +256,33 @@ local run = function(pos, node)
 		burn_time = burn_time + 1
 		meta:set_int("burn_time", burn_time)
 		local percent = math.floor(burn_time / burn_ticks * 100)
-		meta:set_string("infotext", machine_name.." ("..percent.."%)")
+		meta:set_string("infotext", reactor_desc.." ("..percent.."%)")
 		meta:set_int("HV_EU_supply", power_supply)
 	end
 end
 
 minetest.register_node("technic:hv_nuclear_reactor_core", {
-	description = S("Nuclear %s Generator Core"):format("HV"),
-	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 = {cracky=1, technic_machine=1},
+	description = reactor_desc,
+	tiles = {"technic_hv_nuclear_reactor_core.png"},
+	groups = {cracky=1, technic_machine=1, technic_hv=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
-	drawtype="nodebox",
+	drawtype = "nodebox",
 	paramtype = "light",
 	stack_max = 1,
 	node_box = {
 		type = "fixed",
-		fixed = nodebox
+		fixed = node_box
 	},
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
-		meta:set_string("infotext", S("Nuclear %s Generator Core"):format("HV"))
-		meta:set_int("HV_EU_supply", 0)
-		-- Signal to the switching station that this device burns some
-		-- sort of fuel and needs special handling
-		meta:set_int("HV_EU_from_fuel", 1)
-		meta:set_int("burn_time", 0)
-		meta:set_string("formspec", generator_formspec)
+		meta:set_string("infotext", reactor_desc)
+		meta:set_string("formspec", reactor_formspec)
 		local inv = meta:get_inventory()
 		inv:set_size("src", 6)
-	end,	
+	end,
 	can_dig = technic.machine_can_dig,
-	on_destruct = function(pos) siren_set_state(pos, "off") end,
+	on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
 	allow_metadata_inventory_put = technic.machine_inventory_put,
 	allow_metadata_inventory_take = technic.machine_inventory_take,
 	allow_metadata_inventory_move = technic.machine_inventory_move,
@@ -291,23 +290,22 @@ minetest.register_node("technic:hv_nuclear_reactor_core", {
 })
 
 minetest.register_node("technic:hv_nuclear_reactor_core_active", {
-	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 = {cracky=1, technic_machine=1, radioactive=11000, not_in_creative_inventory=1},
+	tiles = {"technic_hv_nuclear_reactor_core.png"},
+	groups = {cracky=1, technic_machine=1, technic_hv=1,
+		radioactive=11000, 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,
+	drop = "technic:hv_nuclear_reactor_core",
+	drawtype = "nodebox",
+	light_source = 14,
 	paramtype = "light",
 	node_box = {
 		type = "fixed",
-		fixed = nodebox
+		fixed = node_box
 	},
 	can_dig = technic.machine_can_dig,
-	after_dig_node = meltdown_reactor,
-	on_destruct = function(pos) siren_set_state(pos, "off") end,
+	after_dig_node = melt_down_reactor,
+	on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
 	allow_metadata_inventory_put = technic.machine_inventory_put,
 	allow_metadata_inventory_take = technic.machine_inventory_take,
 	allow_metadata_inventory_move = technic.machine_inventory_move,
@@ -318,10 +316,10 @@ minetest.register_node("technic:hv_nuclear_reactor_core_active", {
         end,
 	on_timer = function(pos, node)
 		local meta = minetest.get_meta(pos)
-		
+
 		-- Connected back?
 		if meta:get_int("HV_EU_timeout") > 0 then return false end
-		
+
 		local burn_time = meta:get_int("burn_time") or 0
 
 		if burn_time >= burn_ticks or burn_time == 0 then
@@ -332,7 +330,7 @@ minetest.register_node("technic:hv_nuclear_reactor_core_active", {
 			siren_clear(pos, meta)
 			return false
 		end
-		
+
 		meta:set_int("burn_time", burn_time + 1)
 		return true
 	end,
@@ -341,34 +339,36 @@ minetest.register_node("technic:hv_nuclear_reactor_core_active", {
 technic.register_machine("HV", "technic:hv_nuclear_reactor_core",        technic.producer)
 technic.register_machine("HV", "technic:hv_nuclear_reactor_core_active", technic.producer)
 
--- radioactivity
-
--- Radiation resistance represents the extent to which a material
--- attenuates radiation passing through it; i.e., how good a radiation
--- shield it is.  This is identified per node type.  For materials that
--- exist in real life, the radiation resistance value that this system
--- uses for a node type consisting of a solid cube of that material is the
--- (approximate) number of halvings of ionising radiation that is achieved
--- by a metre of the material in real life.  This is approximately
--- proportional to density, which provides a good way to estimate it.
--- Homogeneous mixtures of materials have radiation resistance computed
--- by a simple weighted mean.  Note that the amount of attenuation that
--- a material achieves in-game is not required to be (and is not) the
--- same as the attenuation achieved in real life.
---
--- Radiation resistance for a node type may be specified in the node
--- definition, under the key "radiation_resistance".  As an interim
--- measure, until node definitions widely include this, this code
--- knows a bunch of values for particular node types in several mods,
--- and values for groups of node types.  The node definition takes
--- precedence if it specifies a value.  Nodes for which no value at
--- all is known are taken to provide no radiation resistance at all;
--- this is appropriate for the majority of node types.  Only node types
--- consisting of a fairly homogeneous mass of material should report
--- non-zero radiation resistance; anything with non-uniform geometry
--- or complex internal structure should show no radiation resistance.
--- Fractional resistance values are permitted; two significant figures
--- is the recommended precision.
+--[[
+Radioactivity
+
+Radiation resistance represents the extent to which a material
+attenuates radiation passing through it; i.e., how good a radiation
+shield it is.  This is identified per node type.  For materials that
+exist in real life, the radiation resistance value that this system
+uses for a node type consisting of a solid cube of that material is the
+(approximate) number of halvings of ionising radiation that is achieved
+by a meter of the material in real life.  This is approximately
+proportional to density, which provides a good way to estimate it.
+Homogeneous mixtures of materials have radiation resistance computed
+by a simple weighted mean.  Note that the amount of attenuation that
+a material achieves in-game is not required to be (and is not) the
+same as the attenuation achieved in real life.
+
+Radiation resistance for a node type may be specified in the node
+definition, under the key "radiation_resistance".  As an interim
+measure, until node definitions widely include this, this code
+knows a bunch of values for particular node types in several mods,
+and values for groups of node types.  The node definition takes
+precedence if it specifies a value.  Nodes for which no value at
+all is known are taken to provide no radiation resistance at all;
+this is appropriate for the majority of node types.  Only node types
+consisting of a fairly homogeneous mass of material should report
+non-zero radiation resistance; anything with non-uniform geometry
+or complex internal structure should show no radiation resistance.
+Fractional resistance values are permitted.
+--]]
+
 local default_radiation_resistance_per_node = {
 	["default:brick"] = 13,
 	["default:bronzeblock"] = 45,
@@ -505,12 +505,13 @@ local default_radiation_resistance_per_group = {
 	wood = 1.7,
 }
 local cache_radiation_resistance = {}
-local function node_radiation_resistance(nodename)
-	local eff = cache_radiation_resistance[nodename]
+local function node_radiation_resistance(node_name)
+	local eff = cache_radiation_resistance[node_name]
 	if eff then return eff end
-	local def = minetest.registered_nodes[nodename] or {groups={}}
-	eff = def.radiation_resistance or default_radiation_resistance_per_node[nodename]
-	if not eff then
+	local def = minetest.registered_nodes[node_name]
+	eff = def and def.radiation_resistance or
+			default_radiation_resistance_per_node[node_name]
+	if def and not eff then
 		for g, v in pairs(def.groups) do
 			if v > 0 and default_radiation_resistance_per_group[g] then
 				eff = default_radiation_resistance_per_group[g]
@@ -519,112 +520,114 @@ local function node_radiation_resistance(nodename)
 		end
 	end
 	if not eff then eff = 0 end
-	cache_radiation_resistance[nodename] = eff
+	cache_radiation_resistance[node_name] = eff
 	return eff
 end
 
--- Radioactive nodes cause damage to nearby players.  The damage
--- effect depends on the intrinsic strength of the radiation source,
--- the distance between the source and the player, and the shielding
--- effect of the intervening material.  These determine a rate of damage;
--- total damage caused is the integral of this over time.
---
--- In the absence of effective shielding, for a specific source the
--- damage rate varies realistically in inverse proportion to the square
--- of the distance.  (Distance is measured to the player's abdomen,
--- not to the nominal player position which corresponds to the foot.)
--- However, if the player is inside a non-walkable (liquid or gaseous)
--- radioactive node, the nominal distance could go to zero, yielding
--- infinite damage.  In that case, the player's body is displacing the
--- radioactive material, so the effective distance should remain non-zero.
--- We therefore apply a lower distance bound of sqrt(0.75) m, which is
--- the maximum distance one can get from the node centre within the node.
---
--- A radioactive node is identified by being in the "radioactive" group,
--- and the group value signifies the strength of the radiation source.
--- The group value is the distance in millimetres from a node at which
--- an unshielded player will be damaged by 0.25 HP/s.  Or, equivalently,
--- it is 2000 times the square root of the damage rate in HP/s that an
--- unshielded player 1 m away will take.
---
--- Shielding is assessed by sampling every 0.25 m along the path
--- from the source to the player, ignoring the source node itself.
--- The summed shielding values from the sampled nodes yield a measure
--- of the total amount of shielding on the path.  As in reality,
--- shielding causes exponential attenuation of radiation.  However, the
--- effect is scaled down relative to real life.  A metre of a node with
--- radiation resistance value R yields attenuation of sqrt(R)*0.1 nepers.
--- (In real life it would be about R*0.69 nepers, by the definition
--- of the radiation resistance values.)  The sqrt part of this formula
--- scales down the differences between shielding types, reflecting the
--- game's simplification of making expensive materials such as gold
--- readily available in cubic metres.  The multiplicative factor in the
--- formula scales down the difference between shielded and unshielded
--- safe distances, avoiding the latter becoming impractically large.
---
--- Damage is processed at rates down to 0.25 HP/s, which in the absence of
--- shielding is attained at the distance specified by the "radioactive"
--- group value.  Computed damage rates below 0.25 HP/s result in no
--- damage at all to the player.  This gives the player an opportunity
--- to be safe, and limits the range at which source/player interactions
--- need to be considered.
-local assumed_abdomen_offset = vector.new(0, 1, 0)
-local assumed_abdomen_offset_length = vector.length(assumed_abdomen_offset)
+--[[
+Radioactive nodes cause damage to nearby players.  The damage
+effect depends on the intrinsic strength of the radiation source,
+the distance between the source and the player, and the shielding
+effect of the intervening material.  These determine a rate of damage;
+total damage caused is the integral of this over time.
+
+In the absence of effective shielding, for a specific source the
+damage rate varies realistically in inverse proportion to the square
+of the distance.  (Distance is measured to the player's abdomen,
+not to the nominal player position which corresponds to the foot.)
+However, if the player is inside a non-walkable (liquid or gaseous)
+radioactive node, the nominal distance could go to zero, yielding
+infinite damage.  In that case, the player's body is displacing the
+radioactive material, so the effective distance should remain non-zero.
+We therefore apply a lower distance bound of sqrt(0.75), which is
+the maximum distance one can get from the node center within the node.
+
+A radioactive node is identified by being in the "radioactive" group,
+and the group value signifies the strength of the radiation source.
+The group value is 1000 times the distance from a node at which
+an unshielded player will be damaged by 0.25 HP/s.  Or, equivalently,
+it is 2000 times the square root of the damage rate in HP/s that an
+unshielded player 1 node away will take.
+
+Shielding is assessed by adding the shielding values of all nodes
+between the source node and the player, ignoring the source node itself.
+As in reality, shielding causes exponential attenuation of radiation.
+However, the effect is scaled down relative to real life.  A node with
+radiation resistance value R yields attenuation of sqrt(R) * 0.1 nepers.
+(In real life it would be about R * 0.69 nepers, by the definition
+of the radiation resistance values.)  The sqrt part of this formula
+scales down the differences between shielding types, reflecting the
+game's simplification of making expensive materials such as gold
+readily available in cubes.  The multiplicative factor in the
+formula scales down the difference between shielded and unshielded
+safe distances, avoiding the latter becoming impractically large.
+
+Damage is processed at rates down to 0.25 HP/s, which in the absence of
+shielding is attained at the distance specified by the "radioactive"
+group value.  Computed damage rates below 0.25 HP/s result in no
+damage at all to the player.  This gives the player an opportunity
+to be safe, and limits the range at which source/player interactions
+need to be considered.
+--]]
+local abdomen_offset = vector.new(0, 1, 0)
+local abdomen_offset_length = vector.length(abdomen_offset)
 local cache_scaled_shielding = {}
 
-local damage_enabled = minetest.setting_getbool("enable_damage")
+local function dmg_player(pos, o, strength)
+	local pl_pos = vector.add(o:getpos(), abdomen_offset)
+	local shielding = 0
+	local dist = vector.distance(pos, pl_pos)
+	for ray_pos in technic.trace_node_ray(pos,
+			vector.direction(pos, pl_pos), dist) do
+		if not vector.equals(ray_pos, pos) then
+			local shield_name = minetest.get_node(ray_pos).name
+			local shield_val = cache_scaled_shielding[sname]
+			if not shield_val then
+				shield_val = math.sqrt(node_radiation_resistance(shield_name)) * 0.025
+				cache_scaled_shielding[shield_name] = shield_val
+			end
+			shielding = shielding + shield_val
+		end
+	end
+	local dmg = (0.25e-6 * strength * strength) /
+		(math.max(0.75, dist * dist) * math.exp(shielding))
+	if dmg >= 0.25 then
+		local dmg_int = math.floor(dmg)
+		-- The closer you are to getting one more damage point,
+		-- the more likely it will be added.
+		if math.random() < dmg - dmg_int then
+			dmg_int = dmg_int + 1
+		end
+		if dmg_int > 0 then
+			o:set_hp(math.max(o:get_hp() - dmg_int, 0))
+		end
+	end
+end
 
-if damage_enabled then
+local function dmg_abm(pos, node)
+	local strength = minetest.get_item_group(node.name, "radioactive")
+	for _, o in pairs(minetest.get_objects_inside_radius(pos,
+			strength * 0.001 + abdomen_offset_length)) do
+		if o:is_player() then
+			dmg_player(pos, o, strength)
+		end
+	end
+end
+
+
+if minetest.setting_getbool("enable_damage") then
 	minetest.register_abm({
 		nodenames = {"group:radioactive"},
 		interval = 1,
 		chance = 1,
-		action = function (pos, node)
-			local strength = minetest.registered_nodes[node.name].groups.radioactive
-			for _, o in ipairs(minetest.get_objects_inside_radius(pos, strength*0.001 + assumed_abdomen_offset_length)) do
-				if o:is_player() then
-					local rel = vector.subtract(vector.add(o:getpos(), assumed_abdomen_offset), pos)
-					local dist_sq = vector.length_square(rel)
-					local dist = math.sqrt(dist_sq)
-					local dirstep = dist == 0 and vector.new(0,0,0) or vector.divide(rel, dist*4)
-					local intpos = pos
-					local shielding = 0
-					for intdist = 0.25, dist, 0.25 do
-						intpos = vector.add(intpos, dirstep)
-						local intnodepos = vector.round(intpos)
-						if not vector.equals(intnodepos, pos) then
-							local sname = minetest.get_node(intnodepos).name
-							local sval = cache_scaled_shielding[sname]
-							if not sval then
-								sval = math.sqrt(node_radiation_resistance(sname)) * -0.025
-								cache_scaled_shielding[sname] = sval
-							end
-							shielding = shielding + sval
-						end
-					end
-					local dmg_rate = 0.25e-6 * strength*strength * math.exp(shielding) / math.max(0.75, dist_sq)
-					if dmg_rate >= 0.25 then
-						local dmg_int = math.floor(dmg_rate)
-						if math.random() < dmg_rate-dmg_int then
-							dmg_int = dmg_int + 1
-						end
-						if dmg_int > 0 then
-							o:set_hp(math.max(o:get_hp() - dmg_int, 0))
-						end
-					end
-				end
-			end
-		end,
+		action = dmg_abm,
 	})
 end
 
--- radioactive materials that can result from destroying a reactor
-local corium_griefing = 1 
-if (not technic.config:get_bool("enable_corium_griefing")) then
-	corium_griefing = 0
-end
+-- Radioactive materials that can result from destroying a reactor
+local griefing = technic.config:get_bool("enable_corium_griefing")
 
-for _, state in ipairs({ "flowing", "source" }) do
+for _, state in pairs({"flowing", "source"}) do
 	minetest.register_node("technic:corium_"..state, {
 		description = S(state == "source" and "Corium Source" or "Flowing Corium"),
 		drawtype = (state == "source" and "liquid" or "flowingliquid"),
@@ -652,18 +655,18 @@ for _, state in ipairs({ "flowing", "source" }) do
 		liquid_viscosity = LAVA_VISC,
 		liquid_renewable = false,
 		damage_per_second = 6,
-		post_effect_color = { a=192, r=80, g=160, b=80 },
+		post_effect_color = {a=192, r=80, g=160, b=80},
 		groups = {
 			liquid = 2,
 			hot = 3,
-			igniter = corium_griefing,
+			igniter = (griefing and 1 or 0),
 			radioactive = (state == "source" and 32000 or 16000),
 			not_in_creative_inventory = (state == "flowing" and 1 or nil),
 		},
 	})
 end
 
-if bucket and bucket.register_liquid then
+if rawget(_G, "bucket") and bucket.register_liquid then
 	bucket.register_liquid(
 		"technic:corium_source",
 		"technic:corium_flowing",
@@ -675,12 +678,11 @@ end
 
 minetest.register_node("technic:chernobylite_block", {
         description = S("Chernobylite Block"),
-	tiles = { "technic_chernobylite_block.png" },
+	tiles = {"technic_chernobylite_block.png"},
 	is_ground_content = true,
-	groups = { cracky=1, radioactive=5000, level=2 },
+	groups = {cracky=1, radioactive=5000, level=2},
 	sounds = default.node_sound_stone_defaults(),
 	light_source = 2,
-
 })
 
 minetest.register_abm({
@@ -688,25 +690,36 @@ minetest.register_abm({
 	neighbors = {"technic:corium_source"},
 	interval = 1,
 	chance = 1,
-	action = function (pos, node)
+	action = function(pos, node)
 		minetest.remove_node(pos)
 	end,
 })
 
-if (corium_griefing == 1) then
-	minetest.register_abm({
-		nodenames = {"technic:corium_flowing"},
-		interval = 5,
-		chance = 10,
-		action = function (pos, node)
-			minetest.set_node(pos, {name="technic:chernobylite_block"})
-		end,
-	})
+minetest.register_abm({
+	nodenames = {"technic:corium_flowing"},
+	neighbors = {"group:water"},
+	interval = 1,
+	chance = 1,
+	action = function(pos, node)
+		minetest.set_node(pos, {name="technic:chernobylite_block"})
+	end,
+})
+
+minetest.register_abm({
+	nodenames = {"technic:corium_flowing"},
+	interval = 5,
+	chance = (griefing and 10 or 1),
+	action = function(pos, node)
+		minetest.set_node(pos, {name="technic:chernobylite_block"})
+	end,
+})
+
+if griefing then
 	minetest.register_abm({
-		nodenames = { "technic:corium_source", "technic:corium_flowing" },
+		nodenames = {"technic:corium_source", "technic:corium_flowing"},
 		interval = 4,
 		chance = 4,
-		action = function (pos, node)
+		action = function(pos, node)
 			for _, offset in ipairs({
 				vector.new(1,0,0),
 				vector.new(-1,0,0),
@@ -721,3 +734,4 @@ if (corium_griefing == 1) then
 		end,
 	})
 end
+
diff --git a/technic/machines/HV/quarry.lua b/technic/machines/HV/quarry.lua
index 60805cc..8255676 100644
--- a/technic/machines/HV/quarry.lua
+++ b/technic/machines/HV/quarry.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{"technic:carbon_plate",       "pipeworks:filter",       "technic:composite_plate"},
 		{"technic:motor",              "technic:machine_casing", "technic:diamond_drill_head"},
-		{"technic:carbon_steel_block", "technic:hv_cable0",      "technic:carbon_steel_block"}},
+		{"technic:carbon_steel_block", "technic:hv_cable",       "technic:carbon_steel_block"}},
 	output = "technic:quarry",
 })
 
@@ -213,7 +213,8 @@ minetest.register_node("technic:quarry", {
 	         "technic_carbon_steel_block.png^default_tool_mesepick.png",
 	         "technic_carbon_steel_block.png"),
 	paramtype2 = "facedir",
-	groups = {cracky=2, tubedevice=1, technic_machine = 1},
+	groups = {cracky=2, tubedevice=1, technic_machine=1, technic_hv=1},
+	connect_sides = {"bottom", "front", "left", "right"},
 	tube = {
 		connect_sides = {top = 1},
 	},
diff --git a/technic/machines/HV/solar_array.lua b/technic/machines/HV/solar_array.lua
index 414291a..c7de7c8 100644
--- a/technic/machines/HV/solar_array.lua
+++ b/technic/machines/HV/solar_array.lua
@@ -6,7 +6,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:solar_array_mv',     'technic:solar_array_mv', 'technic:solar_array_mv'},
 		{'technic:carbon_plate',       'technic:hv_transformer', 'technic:composite_plate'},
-		{'',                           'technic:hv_cable0',      ''},
+		{'',                           'technic:hv_cable',       ''},
 	}
 })
 
diff --git a/technic/machines/LV/alloy_furnace.lua b/technic/machines/LV/alloy_furnace.lua
index bdf2f31..5e4f7c4 100644
--- a/technic/machines/LV/alloy_furnace.lua
+++ b/technic/machines/LV/alloy_furnace.lua
@@ -4,9 +4,9 @@
 minetest.register_craft({
 	output = 'technic:lv_alloy_furnace',
 	recipe = {
-		{'default:brick',           'default:brick',          'default:brick'},
-		{'default:brick',           'technic:machine_casing', 'default:brick'},
-		{'default:brick',           'technic:lv_cable0',      'default:brick'},
+		{'default:brick', 'default:brick',          'default:brick'},
+		{'default:brick', 'technic:machine_casing', 'default:brick'},
+		{'default:brick', 'technic:lv_cable',       'default:brick'},
 	}
 })
 
diff --git a/technic/machines/LV/battery_box.lua b/technic/machines/LV/battery_box.lua
index 429bcd6..066bc9d 100644
--- a/technic/machines/LV/battery_box.lua
+++ b/technic/machines/LV/battery_box.lua
@@ -2,9 +2,9 @@
 minetest.register_craft({
 	output = 'technic:lv_battery_box0',
 	recipe = {
-		{'group:wood',              'group:wood',              'group:wood'},
-		{'technic:battery',         'technic:machine_casing',  'technic:battery'},
-		{'technic:battery',         'technic:lv_cable0',       'technic:battery'},
+		{'group:wood',      'group:wood',             'group:wood'},
+		{'technic:battery', 'technic:machine_casing', 'technic:battery'},
+		{'technic:battery', 'technic:lv_cable',       'technic:battery'},
 	}
 })
 
diff --git a/technic/machines/LV/cables.lua b/technic/machines/LV/cables.lua
index e18eae1..d4ed880 100644
--- a/technic/machines/LV/cables.lua
+++ b/technic/machines/LV/cables.lua
@@ -1,8 +1,8 @@
 
-minetest.register_alias("lv_cable", "technic:lv_cable0")
+minetest.register_alias("lv_cable", "technic:lv_cable")
 
 minetest.register_craft({
-	output = 'technic:lv_cable0 6',
+	output = 'technic:lv_cable 6',
 	recipe = {
 		{'default:paper',        'default:paper',        'default:paper'},
 		{'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'},
diff --git a/technic/machines/LV/cnc.lua b/technic/machines/LV/cnc.lua
index dd67e9b..58ec6ba 100644
--- a/technic/machines/LV/cnc.lua
+++ b/technic/machines/LV/cnc.lua
@@ -9,6 +9,17 @@
 
 local S = technic.getter
 
+
+minetest.register_craft({
+	output = 'technic:cnc',
+	recipe = {
+		{'default:glass',              'technic:diamond_drill_head', 'default:glass'},
+		{'technic:control_logic_unit', 'technic:machine_casing',     'technic:motor'},
+		{'technic:carbon_steel_ingot', 'technic:lv_cable',           'technic:carbon_steel_ingot'},
+	},
+})
+
+
 local shape = {}
 local onesize_products = {
 	slope                    = 2,
@@ -174,16 +185,9 @@ minetest.register_node("technic:cnc", {
 	description = S("%s CNC Machine"):format("LV"),
 	tiles       = {"technic_cnc_top.png", "technic_cnc_bottom.png", "technic_cnc_side.png",
 	               "technic_cnc_side.png", "technic_cnc_side.png", "technic_cnc_front.png"},
-	drawtype    = "nodebox",
-	paramtype   = "light",
+	groups = {cracky=2, technic_machine=1, technic_lv=1},
+	connect_sides = {"bottom", "back", "left", "right"},
 	paramtype2  = "facedir",
-	node_box    = {
-		type  = "fixed",
-		fixed = {
-			{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
-		},
-	},
-	groups = {cracky=2, technic_machine=1},
 	legacy_facedir_simple = true,
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
@@ -207,9 +211,10 @@ minetest.register_node("technic:cnc_active", {
 	description = S("%s CNC Machine"):format("LV"),
 	tiles       = {"technic_cnc_top_active.png", "technic_cnc_bottom.png", "technic_cnc_side.png",
 	               "technic_cnc_side.png",       "technic_cnc_side.png",   "technic_cnc_front_active.png"},
+	groups = {cracky=2, technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
+	connect_sides = {"bottom", "back", "left", "right"},
 	paramtype2 = "facedir",
 	drop = "technic:cnc",
-	groups = {cracky=2, technic_machine=1, not_in_creative_inventory=1},
 	legacy_facedir_simple = true,
 	can_dig = technic.machine_can_dig,
 	allow_metadata_inventory_put = technic.machine_inventory_put,
@@ -223,15 +228,3 @@ minetest.register_node("technic:cnc_active", {
 technic.register_machine("LV", "technic:cnc",        technic.receiver)
 technic.register_machine("LV", "technic:cnc_active", technic.receiver)
 
--------------------------
--- CNC Machine Recipe
--------------------------
-minetest.register_craft({
-	output = 'technic:cnc',
-	recipe = {
-		{'default:glass',              'technic:diamond_drill_head', 'default:glass'},
-		{'technic:control_logic_unit', 'technic:machine_casing',     'technic:motor'},
-		{'technic:carbon_steel_ingot', 'technic:lv_cable0',          'technic:carbon_steel_ingot'},
-	},
-})
-
diff --git a/technic/machines/LV/compressor.lua b/technic/machines/LV/compressor.lua
index e2bde40..67b9f79 100644
--- a/technic/machines/LV/compressor.lua
+++ b/technic/machines/LV/compressor.lua
@@ -4,9 +4,9 @@ minetest.register_alias("compressor", "technic:lv_compressor")
 minetest.register_craft({
 	output = 'technic:lv_compressor',
 	recipe = {
-		{'default:stone',		'technic:motor',		'default:stone'},
-		{'mesecons:piston',		'technic:machine_casing',	'mesecons:piston'},
-		{'technic:fine_silver_wire',	'technic:lv_cable0',		'technic:fine_silver_wire'},
+		{'default:stone',            'technic:motor',          'default:stone'},
+		{'mesecons:piston',          'technic:machine_casing', 'mesecons:piston'},
+		{'technic:fine_silver_wire', 'technic:lv_cable',       'technic:fine_silver_wire'},
 	}
 })
 
diff --git a/technic/machines/LV/electric_furnace.lua b/technic/machines/LV/electric_furnace.lua
index cc4daff..768f04a 100644
--- a/technic/machines/LV/electric_furnace.lua
+++ b/technic/machines/LV/electric_furnace.lua
@@ -7,7 +7,7 @@ minetest.register_craft({
 	recipe = {
 		{'default:cobble', 'default:cobble',         'default:cobble'},
 		{'default:cobble', 'technic:machine_casing', 'default:cobble'},
-		{'default:cobble', 'technic:lv_cable0',      'default:cobble'},
+		{'default:cobble', 'technic:lv_cable',       'default:cobble'},
 	}
 })
 
diff --git a/technic/machines/LV/extractor.lua b/technic/machines/LV/extractor.lua
index 363d2e3..55d0140 100644
--- a/technic/machines/LV/extractor.lua
+++ b/technic/machines/LV/extractor.lua
@@ -6,7 +6,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:treetap', 'technic:motor',          'technic:treetap'},
 		{'technic:treetap', 'technic:machine_casing', 'technic:treetap'},
-		{'',                'technic:lv_cable0',      ''},
+		{'',                'technic:lv_cable',       ''},
 	}
 })
 
diff --git a/technic/machines/LV/generator.lua b/technic/machines/LV/generator.lua
index 999dbc5..dc9815f 100644
--- a/technic/machines/LV/generator.lua
+++ b/technic/machines/LV/generator.lua
@@ -10,7 +10,7 @@ minetest.register_craft({
 	recipe = {
 		{'default:stone', 'default:furnace',        'default:stone'},
 		{'default:stone', 'technic:machine_casing', 'default:stone'},
-		{'default:stone', 'technic:lv_cable0',      'default:stone'},
+		{'default:stone', 'technic:lv_cable',       'default:stone'},
 	}
 })
 
diff --git a/technic/machines/LV/geothermal.lua b/technic/machines/LV/geothermal.lua
index e88d3c9..27f4abc 100644
--- a/technic/machines/LV/geothermal.lua
+++ b/technic/machines/LV/geothermal.lua
@@ -10,9 +10,9 @@ local S = technic.getter
 minetest.register_craft({
 	output = 'technic:geothermal',
 	recipe = {
-		{'technic:granite', 'default:diamond', 'technic:granite'},
+		{'technic:granite',          'default:diamond',        'technic:granite'},
 		{'technic:fine_copper_wire', 'technic:machine_casing', 'technic:fine_copper_wire'},
-		{'technic:granite', 'technic:lv_cable0', 'technic:granite'},
+		{'technic:granite',          'technic:lv_cable',       'technic:granite'},
 	}
 })
 
@@ -82,8 +82,9 @@ minetest.register_node("technic:geothermal", {
 	description = S("Geothermal %s Generator"):format("LV"),
 	tiles = {"technic_geothermal_top.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
 	         "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1},
 	paramtype2 = "facedir",
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
 	on_construct = function(pos)
@@ -99,7 +100,8 @@ minetest.register_node("technic:geothermal_active", {
 	tiles = {"technic_geothermal_top_active.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
 	         "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
 	paramtype2 = "facedir",
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
 	drop = "technic:geothermal",
diff --git a/technic/machines/LV/grinder.lua b/technic/machines/LV/grinder.lua
index da9ea29..9e45bf4 100644
--- a/technic/machines/LV/grinder.lua
+++ b/technic/machines/LV/grinder.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'default:desert_stone', 'default:diamond',        'default:desert_stone'},
 		{'default:desert_stone', 'technic:machine_casing', 'default:desert_stone'},
-		{'technic:granite',      'technic:lv_cable0',      'technic:granite'},
+		{'technic:granite',      'technic:lv_cable',       'technic:granite'},
 	}
 })
 
diff --git a/technic/machines/LV/music_player.lua b/technic/machines/LV/music_player.lua
index dc7e2d0..262fe5f 100644
--- a/technic/machines/LV/music_player.lua
+++ b/technic/machines/LV/music_player.lua
@@ -9,7 +9,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:chromium_ingot', 'default:diamond',        'technic:chromium_ingot'},
 		{'default:diamond',        'technic:machine_casing', 'default:diamond'},
-		{'default:mossycobble',    'technic:lv_cable0',      'default:mossycobble'},
+		{'default:mossycobble',    'technic:lv_cable',       'default:mossycobble'},
 	}
 })
 
@@ -94,7 +94,9 @@ minetest.register_node("technic:music_player", {
 	description = S("%s Music Player"):format("LV"),
 	tiles = {"technic_music_player_top.png", "technic_machine_bottom.png", "technic_music_player_side.png",
 	         "technic_music_player_side.png", "technic_music_player_side.png", "technic_music_player_side.png"},
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1},
+	connect_sides = {"bottom"},
 	sounds = default.node_sound_wood_defaults(),
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
diff --git a/technic/machines/LV/solar_array.lua b/technic/machines/LV/solar_array.lua
index 4d2c3b3..8c1b8f4 100644
--- a/technic/machines/LV/solar_array.lua
+++ b/technic/machines/LV/solar_array.lua
@@ -10,7 +10,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:solar_panel',        'technic:solar_panel',    'technic:solar_panel'},
 		{'technic:carbon_steel_ingot', 'technic:lv_transformer', 'technic:carbon_steel_ingot'},
-		{'',                           'technic:lv_cable0',      ''},
+		{'',                           'technic:lv_cable',       ''},
 	}
 })
 
diff --git a/technic/machines/LV/solar_panel.lua b/technic/machines/LV/solar_panel.lua
index 41dff95..a06ddb8 100644
--- a/technic/machines/LV/solar_panel.lua
+++ b/technic/machines/LV/solar_panel.lua
@@ -4,6 +4,17 @@
 
 local S = technic.getter
 
+
+minetest.register_craft({
+	output = 'technic:solar_panel',
+	recipe = {
+		{'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer'},
+		{'technic:fine_silver_wire',    'technic:lv_cable',            'mesecons_materials:glue'},
+
+	}
+})
+
+
 local run = function(pos, node)
 	-- The action here is to make the solar panel prodice power
 	-- Power is dependent on the light level and the height above ground
@@ -24,7 +35,7 @@ local run = function(pos, node)
 		local charge_to_give = math.floor((light + pos1.y) * 3)
 		charge_to_give = math.max(charge_to_give, 0)
 		charge_to_give = math.min(charge_to_give, 200)
-		meta:set_string("infotext", S("@1 Active (@2 EU)", machine_name, technic.prettynum(charge_to_give)))
+		meta:set_string("infotext", S("@1 Active (@2 EU)", machine_name, technic.pretty_num(charge_to_give)))
 		meta:set_int("LV_EU_supply", charge_to_give)
 	else
 		meta:set_string("infotext", S("%s Idle"):format(machine_name))
@@ -35,7 +46,9 @@ end
 minetest.register_node("technic:solar_panel", {
 	tiles = {"technic_solar_panel_top.png",  "technic_solar_panel_bottom.png", "technic_solar_panel_side.png",
 	         "technic_solar_panel_side.png", "technic_solar_panel_side.png",   "technic_solar_panel_side.png"},
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1},
+	connect_sides = {"bottom"},
 	sounds = default.node_sound_wood_defaults(),
     	description = S("Small Solar %s Generator"):format("LV"),
 	active = false,
@@ -54,14 +67,5 @@ minetest.register_node("technic:solar_panel", {
 	technic_run = run,
 })
 
-minetest.register_craft({
-	output = 'technic:solar_panel',
-	recipe = {
-		{'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer'},
-		{'technic:fine_silver_wire',    'technic:lv_cable0',           'mesecons_materials:glue'},
-
-	}
-})
-
 technic.register_machine("LV", "technic:solar_panel", technic.producer)
 
diff --git a/technic/machines/LV/water_mill.lua b/technic/machines/LV/water_mill.lua
index 9088d1d..c853310 100644
--- a/technic/machines/LV/water_mill.lua
+++ b/technic/machines/LV/water_mill.lua
@@ -11,7 +11,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:marble', 'default:diamond',        'technic:marble'},
 		{'group:wood',     'technic:machine_casing', 'group:wood'},
-		{'technic:marble', 'technic:lv_cable0',      'technic:marble'},
+		{'technic:marble', 'technic:lv_cable',       'technic:marble'},
 	}
 })
 
@@ -72,7 +72,8 @@ minetest.register_node("technic:water_mill", {
 	         "technic_water_mill_side.png", "technic_water_mill_side.png",
 	         "technic_water_mill_side.png", "technic_water_mill_side.png"},
 	paramtype2 = "facedir",
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
 	on_construct = function(pos)
@@ -89,7 +90,8 @@ minetest.register_node("technic:water_mill_active", {
 	         "technic_water_mill_side.png",       "technic_water_mill_side.png",
 	         "technic_water_mill_side.png",       "technic_water_mill_side.png"},
 	paramtype2 = "facedir",
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, not_in_creative_inventory=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
 	drop = "technic:water_mill",
diff --git a/technic/machines/MV/alloy_furnace.lua b/technic/machines/MV/alloy_furnace.lua
index a1918fd..eaddee0 100644
--- a/technic/machines/MV/alloy_furnace.lua
+++ b/technic/machines/MV/alloy_furnace.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_alloy_furnace', 'technic:stainless_steel_ingot'},
 		{'pipeworks:tube_1',              'technic:mv_transformer',   'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',        'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',         'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/battery_box.lua b/technic/machines/MV/battery_box.lua
index 45437c1..d84ec15 100644
--- a/technic/machines/MV/battery_box.lua
+++ b/technic/machines/MV/battery_box.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:lv_battery_box0', 'technic:lv_battery_box0', 'technic:lv_battery_box0'},
 		{'technic:lv_battery_box0', 'technic:mv_transformer',  'technic:lv_battery_box0'},
-		{'',                        'technic:mv_cable0',       ''},
+		{'',                        'technic:mv_cable',        ''},
 	}
 })
 
diff --git a/technic/machines/MV/cables.lua b/technic/machines/MV/cables.lua
index b1a34c8..0c1f457 100644
--- a/technic/machines/MV/cables.lua
+++ b/technic/machines/MV/cables.lua
@@ -1,12 +1,12 @@
 
-minetest.register_alias("mv_cable", "technic:mv_cable0")
+minetest.register_alias("mv_cable", "technic:mv_cable")
 
 minetest.register_craft({
-	output = 'technic:mv_cable0 3',
+	output = 'technic:mv_cable 3',
 	recipe ={
-		{'technic:rubber',    'technic:rubber',    'technic:rubber'},
-		{'technic:lv_cable0', 'technic:lv_cable0', 'technic:lv_cable0'},
-		{'technic:rubber',    'technic:rubber',    'technic:rubber'},
+		{'technic:rubber',   'technic:rubber',   'technic:rubber'},
+		{'technic:lv_cable', 'technic:lv_cable', 'technic:lv_cable'},
+		{'technic:rubber',   'technic:rubber',   'technic:rubber'},
 	}
 }) 
 
diff --git a/technic/machines/MV/centrifuge.lua b/technic/machines/MV/centrifuge.lua
index 5bf24bf..a0aad64 100644
--- a/technic/machines/MV/centrifuge.lua
+++ b/technic/machines/MV/centrifuge.lua
@@ -1,9 +1,9 @@
 minetest.register_craft({
 	output = "technic:mv_centrifuge",
 	recipe = {
-		{ "technic:motor",          "technic:copper_plate",   "technic:diamond_drill_head" },
-		{ "technic:copper_plate",   "technic:machine_casing", "technic:copper_plate"       },
-		{ "pipeworks:one_way_tube", "technic:mv_cable0",      "pipeworks:mese_filter"      },
+		{"technic:motor",          "technic:copper_plate",   "technic:diamond_drill_head"},
+		{"technic:copper_plate",   "technic:machine_casing", "technic:copper_plate"      },
+		{"pipeworks:one_way_tube", "technic:mv_cable",       "pipeworks:mese_filter"     },
 	}
 })
 
diff --git a/technic/machines/MV/compressor.lua b/technic/machines/MV/compressor.lua
index 5b36cc5..d97739e 100644
--- a/technic/machines/MV/compressor.lua
+++ b/technic/machines/MV/compressor.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_compressor',  'technic:stainless_steel_ingot'},
 		{'pipeworks:tube_1',              'technic:mv_transformer', 'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',      'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/electric_furnace.lua b/technic/machines/MV/electric_furnace.lua
index 1f6b1c2..b1d2dee 100644
--- a/technic/machines/MV/electric_furnace.lua
+++ b/technic/machines/MV/electric_furnace.lua
@@ -9,8 +9,8 @@ minetest.register_craft({
 	output = 'technic:mv_electric_furnace',
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_electric_furnace', 'technic:stainless_steel_ingot'},
-		{'pipeworks:tube_1',         'technic:mv_transformer',      'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',           'technic:stainless_steel_ingot'},
+		{'pipeworks:tube_1',              'technic:mv_transformer',      'pipeworks:tube_1'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',            'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/extractor.lua b/technic/machines/MV/extractor.lua
index fdef5b2..9066bca 100644
--- a/technic/machines/MV/extractor.lua
+++ b/technic/machines/MV/extractor.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_extractor',   'technic:stainless_steel_ingot'},
 		{'pipeworks:tube_1',              'technic:mv_transformer', 'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',      'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/generator.lua b/technic/machines/MV/generator.lua
index 4ae24b8..db9d59f 100644
--- a/technic/machines/MV/generator.lua
+++ b/technic/machines/MV/generator.lua
@@ -5,7 +5,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_generator',   'technic:stainless_steel_ingot'},
 		{'pipeworks:tube_1',              'technic:mv_transformer', 'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',      'technic:stainless_steel_ingot'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/grinder.lua b/technic/machines/MV/grinder.lua
index dac536c..19ab372 100644
--- a/technic/machines/MV/grinder.lua
+++ b/technic/machines/MV/grinder.lua
@@ -4,8 +4,8 @@ minetest.register_craft({
 	output = 'technic:mv_grinder',
 	recipe = {
 		{'technic:stainless_steel_ingot', 'technic:lv_grinder',     'technic:stainless_steel_ingot'},
-		{'pipeworks:tube_1',         'technic:mv_transformer', 'pipeworks:tube_1'},
-		{'technic:stainless_steel_ingot', 'technic:mv_cable0',      'technic:stainless_steel_ingot'},
+		{'pipeworks:tube_1',              'technic:mv_transformer', 'pipeworks:tube_1'},
+		{'technic:stainless_steel_ingot', 'technic:mv_cable',       'technic:stainless_steel_ingot'},
 	}
 })
 
diff --git a/technic/machines/MV/power_radiator.lua b/technic/machines/MV/power_radiator.lua
index 560f8a9..9349e66 100644
--- a/technic/machines/MV/power_radiator.lua
+++ b/technic/machines/MV/power_radiator.lua
@@ -12,6 +12,16 @@
 
 local power_radius = 12
 
+
+minetest.register_craft({
+	output = 'technic:power_radiator 1',
+	recipe = {
+		{'technic:stainless_steel_ingot', 'technic:mv_transformer', 'technic:stainless_steel_ingot'},
+		{'technic:copper_coil',           'technic:machine_casing', 'technic:copper_coil'},
+		{'technic:rubber',                'technic:mv_cable',       'technic:rubber'},
+	}
+})
+
 ------------------------------------------------------------------
 -- API for inductive powered nodes:
 -- Use the functions below to set the corresponding callbacks
@@ -135,15 +145,6 @@ minetest.register_node("technic:power_radiator", {
 	end
 })
 
-minetest.register_craft({
-	output = 'technic:power_radiator 1',
-	recipe = {
-		{'technic:stainless_steel_ingot', 'technic:mv_transformer', 'technic:stainless_steel_ingot'},
-		{'technic:copper_coil',           'technic:machine_casing', 'technic:copper_coil'},
-		{'technic:rubber',                'technic:mv_cable0',      'technic:rubber'},
-	}
-})
-
 minetest.register_abm({
 	nodenames = {"technic:power_radiator"},
 	interval   = 1,
diff --git a/technic/machines/MV/solar_array.lua b/technic/machines/MV/solar_array.lua
index 227d8ee..4077a5c 100644
--- a/technic/machines/MV/solar_array.lua
+++ b/technic/machines/MV/solar_array.lua
@@ -4,7 +4,7 @@ minetest.register_craft({
 	recipe = {
 		{'technic:solar_array_lv',     'technic:solar_array_lv', 'technic:solar_array_lv'},
 		{'technic:carbon_steel_ingot', 'technic:mv_transformer', 'technic:carbon_steel_ingot'},
-		{'',                           'technic:mv_cable0',      ''},
+		{'',                           'technic:mv_cable',       ''},
 	}
 })
 
diff --git a/technic/machines/MV/tool_workshop.lua b/technic/machines/MV/tool_workshop.lua
index 318b1ec..4076cc1 100644
--- a/technic/machines/MV/tool_workshop.lua
+++ b/technic/machines/MV/tool_workshop.lua
@@ -10,7 +10,7 @@ minetest.register_craft({
 	recipe = {
 		{'group:wood',                         'default:diamond',        'group:wood'},
 		{'mesecons_pistons:piston_sticky_off', 'technic:machine_casing', 'technic:carbon_cloth'},
-		{'default:obsidian',                   'technic:mv_cable0',      'default:obsidian'},
+		{'default:obsidian',                   'technic:mv_cable',       'default:obsidian'},
 	}
 })
 
@@ -85,7 +85,9 @@ minetest.register_node("technic:tool_workshop", {
 	paramtype2 = "facedir",
 	tiles = {"technic_workshop_top.png", "technic_machine_bottom.png", "technic_workshop_side.png",
 	         "technic_workshop_side.png", "technic_workshop_side.png", "technic_workshop_side.png"},
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, tubedevice=1, tubedevice_receiver=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_mv=1, tubedevice=1, tubedevice_receiver=1},
+	connect_sides = {"bottom", "back", "left", "right"},
 	sounds = default.node_sound_wood_defaults(),
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
diff --git a/technic/machines/MV/wind_mill.lua b/technic/machines/MV/wind_mill.lua
index c553051..1377c67 100644
--- a/technic/machines/MV/wind_mill.lua
+++ b/technic/machines/MV/wind_mill.lua
@@ -15,7 +15,7 @@ minetest.register_craft({
 	recipe = {
 		{'',                           'technic:motor',              ''},
 		{'technic:carbon_steel_ingot', 'technic:carbon_steel_block', 'technic:carbon_steel_ingot'},
-		{'',                           'technic:mv_cable0',          ''},
+		{'',                           'technic:mv_cable',           ''},
 	}
 })
 
@@ -55,14 +55,15 @@ local run = function(pos, node)
 		meta:set_int("MV_EU_supply", power)
 	end
 
-	meta:set_string("infotext", S("@1 (@2 EU)", machine_name, technic.prettynum(power)))
+	meta:set_string("infotext", S("@1 (@2 EU)", machine_name, technic.pretty_num(power)))
 end
 
 minetest.register_node("technic:wind_mill", {
 	description = S("Wind %s Generator"):format("MV"),
 	tiles = {"technic_carbon_steel_block.png"},
 	paramtype2 = "facedir",
-	groups = {cracky=1, technic_machine=1},
+	groups = {cracky=1, technic_machine=1, technic_mv=1},
+	connect_sides = {"top", "bottom", "back", "left", "right"},
 	sounds = default.node_sound_stone_defaults(),
 	drawtype = "nodebox",
 	paramtype = "light",
diff --git a/technic/machines/register/battery_box.lua b/technic/machines/register/battery_box.lua
index 82edca0..953f7af 100644
--- a/technic/machines/register/battery_box.lua
+++ b/technic/machines/register/battery_box.lua
@@ -151,7 +151,7 @@ function technic.register_battery_box(data)
 			..":technic_power_meter_fg.png]")
 
 		local infotext = S("@1 Battery Box: @2/@3", tier,
-				technic.prettynum(current_charge), technic.prettynum(max_charge))
+				technic.pretty_num(current_charge), technic.pretty_num(max_charge))
 		if eu_input == 0 then
 			infotext = S("%s Idle"):format(infotext)
 		end
@@ -159,7 +159,8 @@ function technic.register_battery_box(data)
 	end
 	
 	for i = 0, 8 do
-		local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1}
+		local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+				technic_machine=1, ["technic_"..ltier]=1}
 		if i ~= 0 then
 			groups.not_in_creative_inventory = 1
 		end
@@ -178,6 +179,7 @@ function technic.register_battery_box(data)
 				 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png",
 				 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png"},
 			groups = groups,
+			connect_sides = {"bottom"},
 			tube = data.tube and tube or nil,
 			paramtype2 = "facedir",
 			sounds = default.node_sound_wood_defaults(),
diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua
index a1e7bc8..28984c0 100644
--- a/technic/machines/register/cables.lua
+++ b/technic/machines/register/cables.lua
@@ -1,177 +1,65 @@
 
 local S = technic.getter
 
-local cable_itstr_to_tier = {}
-
-function technic.register_cable(tier, size)
-	local ltier = string.lower(tier)
-
-	for x1 = 0, 1 do
-	for x2 = 0, 1 do
-	for y1 = 0, 1 do
-	for y2 = 0, 1 do
-	for z1 = 0, 1 do
-	for z2 = 0, 1 do
-		local id = technic.get_cable_id({x1, x2, y1, y2, z1, z2})
-
-		cable_itstr_to_tier["technic:"..ltier.."_cable"..id] = tier
-
-		local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2}
-		if id ~= 0 then
-			groups.not_in_creative_inventory = 1
-		end
-
-		minetest.register_node("technic:"..ltier.."_cable"..id, {
-			description = S("%s Cable"):format(tier),
-			tiles = {"technic_"..ltier.."_cable.png"},
-			inventory_image = "technic_"..ltier.."_cable_wield.png",
-			wield_image = "technic_"..ltier.."_cable_wield.png",
-			groups = groups,
-			sounds = default.node_sound_wood_defaults(),
-			drop = "technic:"..ltier.."_cable0",
-			paramtype = "light",
-			sunlight_propagates = true,
-			drawtype = "nodebox",
-			node_box = {
-				type = "fixed",
-				fixed = technic.gen_cable_nodebox(x1, y1, z1, x2, y2, z2, size)
-			},
-			on_construct = function()
-				technic.networks = {}
-			end,
-			on_destruct = function()
-				technic.networks = {}
-			end,
-			after_place_node = function(pos)
-				local node = minetest.get_node(pos)
-				technic.update_cables(pos, technic.get_cable_tier(node.name))
-			end,
-			after_dig_node = function(pos, oldnode)
-				local tier = technic.get_cable_tier(oldnode.name)
-				technic.update_cables(pos, tier, true)
-			end
-		})
-	end
-	end
-	end
-	end
-	end
-	end
-end
-
-minetest.register_on_placenode(function(pos, node)
-	for tier, machine_list in pairs(technic.machines) do
-		if machine_list[node.name] ~= nil then
-			technic.update_cables(pos, tier, true)
-			technic.networks = {}
-		end
-	end
-end)
-
-
-minetest.register_on_dignode(function(pos, node)
-	for tier, machine_list in pairs(technic.machines) do
-		if machine_list[node.name] ~= nil then
-			technic.update_cables(pos, tier, true)
-			technic.networks = {}
-		end
-	end
-end)
-
-function technic.get_cable_id(links)
-	return (links[6] * 1) + (links[5] * 2)
-			+ (links[4] * 4)  + (links[3] * 8)
-			+ (links[2] * 16) + (links[1] * 32)
-end
-
-function technic.update_cables(pos, tier, no_set, secondrun)
-	local link_positions = {
-		{x=pos.x+1, y=pos.y,   z=pos.z},
-		{x=pos.x-1, y=pos.y,   z=pos.z},
-		{x=pos.x,   y=pos.y+1, z=pos.z},
-		{x=pos.x,   y=pos.y-1, z=pos.z},
-		{x=pos.x,   y=pos.y,   z=pos.z+1},
-		{x=pos.x,   y=pos.y,   z=pos.z-1}}
-
-	local links = {0, 0, 0, 0, 0, 0}
-
-	for i, link_pos in pairs(link_positions) do
-		local connect_type = technic.cables_should_connect(pos, link_pos, tier)
-		if connect_type then
-			links[i] = 1
-			-- Have cables next to us update theirselves,
-			-- but only once. (We don't want to update the entire
-			-- network or start an infinite loop of updates)
-			if not secondrun and connect_type == "cable" then
-				technic.update_cables(link_pos, tier, false, true)
-			end
-		end
-	end
-	-- We don't want to set ourselves if we have been removed or we are
-	-- updating a machine
-	if not no_set then
-		minetest.set_node(pos, {name="technic:"..string.lower(tier)
-				.."_cable"..technic.get_cable_id(links)})
-
-	end
-end
-
+local cable_tier = {}
 
 function technic.is_tier_cable(name, tier)
-	return cable_itstr_to_tier[name] and cable_itstr_to_tier[name] == tier
+	return cable_tier[name] == tier
 end
 
-
 function technic.get_cable_tier(name)
-	return cable_itstr_to_tier[name]
+	return cable_tier[name]
 end
 
-
-function technic.cables_should_connect(pos1, pos2, tier)
-	local name = minetest.get_node(pos2).name
-
-	if name == "technic:switching_station" then
-		return pos2.y == pos1.y + 1 and "machine" or false
-	elseif name == "technic:supply_converter" then
-		return math.abs(pos2.y - pos1.y) == 1 and "machine" or false
-	elseif technic.is_tier_cable(name, tier) then
-		return "cable"
-	elseif technic.machines[tier][name] then
-		return "machine"
-	end
-	return false
+local function clear_networks()
+	technic.networks = {}
 end
 
+function technic.register_cable(tier, size)
+	local ltier = string.lower(tier)
+	cable_tier["technic:"..ltier.."_cable"] = tier
+
+	local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2}
+
+	local node_box = {
+		type = "connected",
+		fixed          = {-size, -size, -size, size,  size, size},
+		connect_top    = {-size, -size, -size, size,  0.5,  size}, -- y+
+		connect_bottom = {-size, -0.5,  -size, size,  size, size}, -- y-
+		connect_front  = {-size, -size, -0.5,  size,  size, size}, -- z-
+		connect_back   = {-size, -size,  size, size,  size, 0.5 }, -- z+
+		connect_left   = {-0.5,  -size, -size, size,  size, size}, -- x-
+		connect_right  = {-size, -size, -size, 0.5,   size, size}, -- x+
+	}
+
+	minetest.register_node("technic:"..ltier.."_cable", {
+		description = S("%s Cable"):format(tier),
+		tiles = {"technic_"..ltier.."_cable.png"},
+		inventory_image = "technic_"..ltier.."_cable_wield.png",
+		wield_image = "technic_"..ltier.."_cable_wield.png",
+		groups = groups,
+		sounds = default.node_sound_wood_defaults(),
+		drop = "technic:"..ltier.."_cable",
+		paramtype = "light",
+		sunlight_propagates = true,
+		drawtype = "nodebox",
+		node_box = node_box,
+		connects_to = {"technic:"..ltier.."_cable",
+			"group:technic_"..ltier, "group:technic_all_tiers"},
+		on_construct = clear_networks,
+		on_destruct = clear_networks,
+	})
+end
 
-function technic.gen_cable_nodebox(x1, y1, z1, x2, y2, z2, size)
-	-- Nodeboxes
-	local box_center = {-size, -size, -size, size,  size, size}
-	local box_y1 =     {-size, -size, -size, size,  0.5,  size} -- y+
-	local box_x1 =     {-size, -size, -size, 0.5,   size, size} -- x+
-	local box_z1 =     {-size, -size,  size, size,  size, 0.5}  -- z+
-	local box_z2 =     {-size, -size, -0.5,  size,  size, size} -- z-
-	local box_y2 =     {-size, -0.5,  -size, size,  size, size} -- y-
-	local box_x2 =     {-0.5,  -size, -size, size,  size, size} -- x-
 
-	local box = {box_center}
-	if x1 == 1 then
-		table.insert(box, box_x1)
-	end
-	if y1 == 1 then
-		table.insert(box, box_y1)
-	end
-	if z1 == 1 then
-		table.insert(box, box_z1)
-	end
-	if x2 == 1 then
-		table.insert(box, box_x2)
-	end
-	if y2 == 1 then
-		table.insert(box, box_y2)
-	end
-	if z2 == 1 then
-		table.insert(box, box_z2)
+local function clear_nets_if_machine(pos, node)
+	for tier, machine_list in pairs(technic.machines) do
+		if machine_list[node.name] ~= nil then
+			return clear_networks()
+		end
 	end
-	return box
 end
 
+minetest.register_on_placenode(clear_nets_if_machine)
+minetest.register_on_dignode(clear_nets_if_machine)
+
diff --git a/technic/machines/register/generator.lua b/technic/machines/register/generator.lua
index 31c1cef..2cdc336 100644
--- a/technic/machines/register/generator.lua
+++ b/technic/machines/register/generator.lua
@@ -18,14 +18,14 @@ function technic.register_generator(data)
 	local tier = data.tier
 	local ltier = string.lower(tier)
 
-	local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1}
-	local active_groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, not_in_creative_inventory=1}
+	local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, ["technic_"..ltier]=1}
 	if data.tube then
 		groups.tubedevice = 1
 		groups.tubedevice_receiver = 1
-		active_groups.tubedevice = 1
-		active_groups.tubedevice_receiver = 1
 	end
+	local active_groups = {not_in_creative_inventory = 1}
+	for k, v in pairs(groups) do active_groups[k] = v end
 
 	local generator_formspec =
 		"invsize[8,9;]"..
@@ -93,6 +93,7 @@ function technic.register_generator(data)
 		         "technic_"..ltier.."_generator_side.png", "technic_"..ltier.."_generator_front.png"}, 
 		paramtype2 = "facedir",
 		groups = groups,
+		connect_sides = {"bottom", "back", "left", "right"},
 		legacy_facedir_simple = true,
 		sounds = default.node_sound_wood_defaults(),
 		tube = data.tube and tube or nil,
@@ -122,6 +123,7 @@ function technic.register_generator(data)
 		         "technic_"..ltier.."_generator_side.png", "technic_"..ltier.."_generator_front_active.png"},
 		paramtype2 = "facedir",
 		groups = active_groups,
+		connect_sides = {"bottom"},
 		legacy_facedir_simple = true,
 		sounds = default.node_sound_wood_defaults(),
 		tube = data.tube and tube or nil,
diff --git a/technic/machines/register/machine_base.lua b/technic/machines/register/machine_base.lua
index 0c46261..8cf851b 100644
--- a/technic/machines/register/machine_base.lua
+++ b/technic/machines/register/machine_base.lua
@@ -15,6 +15,8 @@ local tube = {
 	connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1},
 }
 
+local connect_default = {"bottom", "back", "left", "right"}
+
 local function round(v)
 	return math.floor(v + 0.5)
 end
@@ -27,15 +29,13 @@ function technic.register_base_machine(data)
 	local tier = data.tier
 	local ltier = string.lower(tier)
 
-	local groups = {cracky = 2, technic_machine = 1}
-	local active_groups = {cracky = 2, technic_machine = 1, not_in_creative_inventory = 1}
+	local groups = {cracky = 2, technic_machine = 1, ["technic_"..ltier] = 1}
 	if data.tube then
 		groups.tubedevice = 1
 		groups.tubedevice_receiver = 1
-		active_groups.tubedevice = 1
-		active_groups.tubedevice_receiver = 1
 	end
-
+	local active_groups = {not_in_creative_inventory = 1}
+	for k, v in pairs(groups) do active_groups[k] = v end
 
 	local formspec =
 		"invsize[8,9;]"..
@@ -145,6 +145,7 @@ function technic.register_base_machine(data)
 		paramtype2 = "facedir",
 		groups = groups,
 		tube = data.tube and tube or nil,
+		connect_sides = data.connect_sides or connect_default,
 		legacy_facedir_simple = true,
 		sounds = default.node_sound_wood_defaults(),
 		on_construct = function(pos)
@@ -179,6 +180,7 @@ function technic.register_base_machine(data)
 		paramtype2 = "facedir",
 		drop = "technic:"..ltier.."_"..machine_name,
 		groups = active_groups,
+		connect_sides = data.connect_sides or connect_default,
 		legacy_facedir_simple = true,
 		sounds = default.node_sound_wood_defaults(),
 		tube = data.tube and tube or nil,
diff --git a/technic/machines/register/solar_array.lua b/technic/machines/register/solar_array.lua
index 39f50d2..422bfcf 100644
--- a/technic/machines/register/solar_array.lua
+++ b/technic/machines/register/solar_array.lua
@@ -30,7 +30,7 @@ function technic.register_solar_array(data)
 			local charge_to_give = math.floor((light + pos.y) * data.power)
 			charge_to_give = math.max(charge_to_give, 0)
 			charge_to_give = math.min(charge_to_give, data.power * 50)
-			meta:set_string("infotext", S("@1 Active (@2 EU)", machine_name, technic.prettynum(charge_to_give)))
+			meta:set_string("infotext", S("@1 Active (@2 EU)", machine_name, technic.pretty_num(charge_to_give)))
 			meta:set_int(tier.."_EU_supply", charge_to_give)
 		else
 			meta:set_string("infotext", S("%s Idle"):format(machine_name))
@@ -42,7 +42,8 @@ function technic.register_solar_array(data)
 		tiles = {"technic_"..ltier.."_solar_array_top.png",  "technic_"..ltier.."_solar_array_bottom.png",
 			 "technic_"..ltier.."_solar_array_side.png", "technic_"..ltier.."_solar_array_side.png",
 			 "technic_"..ltier.."_solar_array_side.png", "technic_"..ltier.."_solar_array_side.png"},
-		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
+		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, ["technic_"..ltier]=1},
+		connect_sides = {"bottom"},
 		sounds = default.node_sound_wood_defaults(),
 		description = S("Arrayed Solar %s Generator"):format(tier),
 		active = false,
diff --git a/technic/machines/supply_converter.lua b/technic/machines/supply_converter.lua
index ffcd40d..32597de 100644
--- a/technic/machines/supply_converter.lua
+++ b/technic/machines/supply_converter.lua
@@ -30,7 +30,7 @@ local run = function(pos, node)
 		meta:set_int(from.."_EU_supply", 0)
 		meta:set_int(to.."_EU_demand", 0)
 		meta:set_int(to.."_EU_supply", input * remain)
-		meta:set_string("infotext", S("@1 (@2 @3 -> @4 @5)", machine_name, technic.prettynum(input), from, technic.prettynum(input * remain), to))
+		meta:set_string("infotext", S("@1 (@2 @3 -> @4 @5)", machine_name, technic.pretty_num(input), from, technic.pretty_num(input * remain), to))
 	else
 		meta:set_string("infotext", S("%s Has Bad Cabling"):format(machine_name))
 		if to then
@@ -49,14 +49,10 @@ minetest.register_node("technic:supply_converter", {
 	tiles  = {"technic_supply_converter_top.png", "technic_supply_converter_bottom.png",
 	          "technic_supply_converter_side.png", "technic_supply_converter_side.png",
 	          "technic_supply_converter_side.png", "technic_supply_converter_side.png"},
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
+		technic_machine=1, technic_all_tiers=1},
+	connect_sides = {"top", "bottom"},
 	sounds = default.node_sound_wood_defaults(),
-	drawtype = "nodebox",
-	paramtype = "light",
-	node_box = {
-		type = "fixed",
-		fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
-	},
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
 		meta:set_string("infotext", S("Supply Converter"))
@@ -68,9 +64,9 @@ minetest.register_node("technic:supply_converter", {
 minetest.register_craft({
 	output = 'technic:supply_converter 1',
 	recipe = {
-		{'technic:fine_gold_wire',        'technic:rubber',         'technic:doped_silicon_wafer'},
-		{'technic:mv_transformer',        'technic:machine_casing', 'technic:lv_transformer'},
-		{'technic:mv_cable0',             'technic:rubber',         'technic:lv_cable0'},
+		{'technic:fine_gold_wire', 'technic:rubber',         'technic:doped_silicon_wafer'},
+		{'technic:mv_transformer', 'technic:machine_casing', 'technic:lv_transformer'},
+		{'technic:mv_cable',       'technic:rubber',         'technic:lv_cable'},
 	}
 })
 
diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua
index d6f23a3..f7ec0b6 100644
--- a/technic/machines/switching_station.lua
+++ b/technic/machines/switching_station.lua
@@ -38,9 +38,9 @@ local S = technic.getter
 minetest.register_craft({
 	output = "technic:switching_station",
 	recipe = {
-		{"",                        "technic:lv_transformer", ""},
-		{"default:copper_ingot",    "technic:machine_casing", "default:copper_ingot"},
-		{"technic:lv_cable0",       "technic:lv_cable0",      "technic:lv_cable0"}
+		{"",                     "technic:lv_transformer", ""},
+		{"default:copper_ingot", "technic:machine_casing", "default:copper_ingot"},
+		{"technic:lv_cable",     "technic:lv_cable",       "technic:lv_cable"}
 	}
 })
 
@@ -49,14 +49,9 @@ minetest.register_node("technic:switching_station",{
 	tiles  = {"technic_water_mill_top_active.png", "technic_water_mill_top_active.png",
                   "technic_water_mill_top_active.png", "technic_water_mill_top_active.png",
 	          "technic_water_mill_top_active.png", "technic_water_mill_top_active.png"},
-	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
+	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_all_tiers=1},
+	connect_sides = {"bottom"},
 	sounds = default.node_sound_wood_defaults(),
-	drawtype = "nodebox",
-	paramtype = "light",
-	node_box = {
-		type = "fixed",
-		fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
-	},
 	on_construct = function(pos)
 		local meta = minetest.get_meta(pos)
 		meta:set_string("infotext", S("Switching Station"))
@@ -294,7 +289,7 @@ minetest.register_abm({
 
 		meta:set_string("infotext",
 				S("@1. Supply: @2 Demand: @3",
-				machine_name, technic.prettynum(PR_eu_supply), technic.prettynum(RE_eu_demand)))
+				machine_name, technic.pretty_num(PR_eu_supply), technic.pretty_num(RE_eu_demand)))
 
 		-- If the PR supply is enough for the RE demand supply them all
 		if PR_eu_supply >= RE_eu_demand then
diff --git a/technic/tools/chainsaw.lua b/technic/tools/chainsaw.lua
index bf4efff..3653d2d 100644
--- a/technic/tools/chainsaw.lua
+++ b/technic/tools/chainsaw.lua
@@ -9,15 +9,19 @@ local chainsaw_leaves = true
 
 -- The default trees
 local timber_nodenames = {
-	["default:jungletree"] = true,
-	["default:papyrus"]    = true,
-	["default:cactus"]     = true,
-	["default:tree"]       = true,
-	["default:apple"]      = true,
-	["default:pinetree"]   = true,
+	["default:acacia_tree"] = true,
+	["default:aspen_tree"]  = true,
+	["default:jungletree"]  = true,
+	["default:papyrus"]     = true,
+	["default:cactus"]      = true,
+	["default:tree"]        = true,
+	["default:apple"]       = true,
+	["default:pine_tree"]    = true,
 }
 
 if chainsaw_leaves then
+	timber_nodenames["default:acacia_leaves"] = true
+	timber_nodenames["default:aspen_leaves"] = true
 	timber_nodenames["default:leaves"] = true
 	timber_nodenames["default:jungleleaves"] = true
 	timber_nodenames["default:pine_needles"] = true
diff --git a/technic/tools/mining_lasers.lua b/technic/tools/mining_lasers.lua
index 4c83ae9..c09aa92 100644
--- a/technic/tools/mining_lasers.lua
+++ b/technic/tools/mining_lasers.lua
@@ -32,67 +32,6 @@ minetest.register_craft({
 	}
 })
 
--- Based on code by Uberi: https://gist.github.com/Uberi/3125280
-local function rayIter(pos, dir, range)
-	local p = vector.round(pos)
-	local x_step,      y_step,      z_step      = 0, 0, 0
-	local x_component, y_component, z_component = 0, 0, 0
-	local x_intersect, y_intersect, z_intersect = 0, 0, 0
-
-	if dir.x == 0 then
-		x_intersect = math.huge
-	elseif dir.x > 0 then
-		x_step = 1
-		x_component = 1 / dir.x
-		x_intersect = x_component
-	else
-		x_step = -1
-		x_component = 1 / -dir.x
-	end
-	if dir.y == 0 then
-		y_intersect = math.huge
-	elseif dir.y > 0 then
-		y_step = 1
-		y_component = 1 / dir.y
-		y_intersect = y_component
-	else
-		y_step = -1
-		y_component = 1 / -dir.y
-	end
-	if dir.z == 0 then
-		z_intersect = math.huge
-	elseif dir.z > 0 then
-		z_step = 1
-		z_component = 1 / dir.z
-		z_intersect = z_component
-	else
-		z_step = -1
-		z_component = 1 / -dir.z
-	end
-
-	return function()
-		if x_intersect < y_intersect then
-			if x_intersect < z_intersect then
-				p.x = p.x + x_step
-				x_intersect = x_intersect + x_component
-			else
-				p.z = p.z + z_step
-				z_intersect = z_intersect + z_component
-			end
-		elseif y_intersect < z_intersect then
-			p.y = p.y + y_step
-			y_intersect = y_intersect + y_component
-		else
-			p.z = p.z + z_step
-			z_intersect = z_intersect + z_component
-		end
-		if vector.distance(pos, p) > range then
-			return nil
-		end
-		return p
-	end
-end
-
 local function laser_node(pos, node, player)
 	local def = minetest.registered_nodes[node.name]
 	if def and def.liquidtype ~= "none" then
@@ -132,7 +71,7 @@ local function laser_shoot(player, range, particle_texture, sound)
 		texture = particle_texture .. "^[transform" .. math.random(0, 7),
 	})
 	minetest.sound_play(sound, {pos = player_pos, max_hear_distance = range})
-	for pos in rayIter(start_pos, dir, range) do
+	for pos in technic.trace_node_ray(start_pos, dir, range) do
 		if minetest.is_protected(pos, player_name) then
 			minetest.record_protection_violation(pos, player_name)
 			break
diff --git a/trafficlight/init.lua b/trafficlight/init.lua
index 38b18c4..7f472e0 100644
--- a/trafficlight/init.lua
+++ b/trafficlight/init.lua
@@ -207,7 +207,7 @@ for _,i in pairs({"","_left","_right"}) do
 	})
 
 	minetest.register_node(":streets:trafficlight_top"..i.."_red",{
-		drop = "streets:trafficlight_top_off",
+		drop = "streets:trafficlight_top"..i.."_off",
 		groups = {cracky = 1, not_in_creative_inventory = 1},
 		paramtype = "light",
 		paramtype2 = "facedir",
@@ -230,7 +230,7 @@ for _,i in pairs({"","_left","_right"}) do
 	})
 
 	minetest.register_node(":streets:trafficlight_top"..i.."_yellow",{
-		drop = "streets:trafficlight_top_off",
+		drop = "streets:trafficlight_top"..i.."_off",
 		groups = {cracky = 1, not_in_creative_inventory = 1},
 		paramtype = "light",
 		paramtype2 = "facedir",
@@ -255,7 +255,7 @@ for _,i in pairs({"","_left","_right"}) do
 	minetest.register_alias("streets:trafficlight_top"..i.."_redyellow","streets:trafficlight_top"..i.."_green")
 
 	minetest.register_node(":streets:trafficlight_top"..i.."_green",{
-		drop = "streets:trafficlight_top_off",
+		drop = "streets:trafficlight_top"..i.."_off",
 		groups = {cracky = 1, not_in_creative_inventory = 1},
 		paramtype = "light",
 		paramtype2 = "facedir",
@@ -278,7 +278,7 @@ for _,i in pairs({"","_left","_right"}) do
 	})
 
 	minetest.register_node(":streets:trafficlight_top"..i.."_warn",{
-		drop = "streets:trafficlight_top_off",
+		drop = "streets:trafficlight_top"..i.."_off",
 		groups = {cracky = 1, not_in_creative_inventory = 1},
 		paramtype = "light",
 		paramtype2 = "facedir",
@@ -286,7 +286,7 @@ for _,i in pairs({"","_left","_right"}) do
 		drawtype = "nodebox",
 		tiles = {"streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png",{
 			name="streets_tl"..i.."_warn.png",
-			animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.5},
+			animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.2},
 		}},
 		node_box = {
 			type = "fixed",
@@ -304,7 +304,7 @@ for _,i in pairs({"","_left","_right"}) do
 	})
 
 	minetest.register_node(":streets:trafficlight_top"..i.."_flashred",{
-		drop = "streets:trafficlight_top_off",
+		drop = "streets:trafficlight_top"..i.."_off",
 		groups = {cracky = 1, not_in_creative_inventory = 1},
 		paramtype = "light",
 		paramtype2 = "facedir",
@@ -312,7 +312,7 @@ for _,i in pairs({"","_left","_right"}) do
 		drawtype = "nodebox",
 		tiles = {"streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png","streets_tl_bg.png",{
 			name="streets_tl"..i.."_flashred.png",
-			animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.5},
+			animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.2},
 		}},
 		node_box = {
 			type = "fixed",
diff --git a/trafficlight/textures/streets_tl_left_red.png b/trafficlight/textures/streets_tl_left_red.png
index db0694c..85e9b71 100644
Binary files a/trafficlight/textures/streets_tl_left_red.png and b/trafficlight/textures/streets_tl_left_red.png differ
diff --git a/ufos/furnace.lua b/ufos/furnace.lua
index 6e3d2a1..bde74ae 100644
--- a/ufos/furnace.lua
+++ b/ufos/furnace.lua
@@ -20,14 +20,14 @@ minetest.register_node("ufos:furnace", {
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_stone_defaults(),
 	on_construct = function(pos)
-		local meta = minetest.env:get_meta(pos)
+		local meta = minetest.get_meta(pos)
 		meta:set_string("formspec", ufos.furnace_inactive_formspec)
 		meta:set_string("infotext", "UFO charging device")
 		local inv = meta:get_inventory()
 		inv:set_size("fuel", 1)
 	end,
 	can_dig = function(pos,player)
-		local meta = minetest.env:get_meta(pos);
+		local meta = minetest.get_meta(pos);
 		local inv = meta:get_inventory()
 		if not inv:is_empty("fuel") then
 			return false
@@ -47,14 +47,14 @@ minetest.register_node("ufos:furnace_active", {
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_stone_defaults(),
 	on_construct = function(pos)
-		local meta = minetest.env:get_meta(pos)
+		local meta = minetest.get_meta(pos)
 		meta:set_string("formspec", ufos.furnace_inactive_formspec)
 		meta:set_string("infotext", "UFO charging device")
 		local inv = meta:get_inventory()
 		inv:set_size("fuel", 1)
 	end,
 	can_dig = function(pos,player)
-		local meta = minetest.env:get_meta(pos);
+		local meta = minetest.get_meta(pos);
 		local inv = meta:get_inventory()
 		if not inv:is_empty("fuel") then
 			return false
@@ -64,16 +64,16 @@ minetest.register_node("ufos:furnace_active", {
 })
 
 function hacky_swap_node(pos,name)
-	local node = minetest.env:get_node(pos)
-	local meta = minetest.env:get_meta(pos)
+	local node = minetest.get_node(pos)
+	local meta = minetest.get_meta(pos)
 	local meta0 = meta:to_table()
 	if node.name == name then
 		return
 	end
 	node.name = name
 	local meta0 = meta:to_table()
-	minetest.env:set_node(pos,node)
-	meta = minetest.env:get_meta(pos)
+	minetest.set_node(pos,node)
+	meta = minetest.get_meta(pos)
 	meta:from_table(meta0)
 end
 
@@ -82,7 +82,7 @@ minetest.register_abm({
 	interval = .25,
 	chance = 1,
 	action = function(pos, node, active_object_count, active_object_count_wider)
-		local meta = minetest.env:get_meta(pos)
+		local meta = minetest.get_meta(pos)
 		local inv = meta:get_inventory()
 		local stack = inv:get_stack("fuel",1)
 		if stack:get_name() == ufos.fuel then
diff --git a/ufos/init.lua b/ufos/init.lua
index cb68e65..40fd241 100644
--- a/ufos/init.lua
+++ b/ufos/init.lua
@@ -1,6 +1,8 @@
 
 ufos = {}
 
+local e
+
 local floor_pos = function(pos)
 	return {x=math.floor(pos.x),y=math.floor(pos.y),z=math.floor(pos.z)}
 end
@@ -46,7 +48,7 @@ ufos.ufo_from_item = function(itemstack,placer,pointed_thing)
 	local wear = itemstack:get_wear()
 	ufos.set_fuel(ufos.ufo,ufos.fuel_from_wear(wear))
 	-- add the entity
-	e = minetest.env:add_entity(pointed_thing.above, "ufos:ufo")
+	e = minetest.add_entity(pointed_thing.above, "ufos:ufo")
 	-- remove the item
 	itemstack:take_item()
 	-- reset owner for next ufo
@@ -162,8 +164,8 @@ function ufos.ufo:on_step (dtime)
 			local t = {{x=2,z=0},{x=-2,z=0},{x=0,z=2},{x=0,z=-2}}
 			for _, i in ipairs(t) do
 				pos.x = pos.x + i.x; pos.z = pos.z + i.z;
-				if minetest.env:get_node(pos).name == "ufos:furnace" then
-					meta = minetest.env:get_meta(pos)
+				if minetest.get_node(pos).name == "ufos:furnace" then
+					meta = minetest.get_meta(pos)
 					if fuel < 100 and meta:get_int("charge") > 0 then
 						fuel = fuel + 1
 						meta:set_int("charge",meta:get_int("charge")-1)
@@ -235,16 +237,16 @@ minetest.register_node("ufos:box", {
 	tiles = {"ufos_box.png"},
 	groups = {not_in_creative_inventory=1},
 	on_rightclick = function(pos, node, clicker, itemstack)
-		meta = minetest.env:get_meta(pos)
+		meta = minetest.get_meta(pos)
 		if meta:get_string("owner") == clicker:get_player_name() then
 			-- set owner
 			ufos.next_owner = meta:get_string("owner")
 			-- restore the fuel inside the node
 			ufos.set_fuel(ufos.ufo,meta:get_int("fuel"))
 			-- add the entity
-			e = minetest.env:add_entity(pos, "ufos:ufo")
+			e = minetest.add_entity(pos, "ufos:ufo")
 			-- remove the node
-			minetest.env:remove_node(pos)
+			minetest.remove_node(pos)
 			-- reset owner for next ufo
 			ufos.next_owner = ""
 		end
diff --git a/unified_inventory/init.lua b/unified_inventory/init.lua
index b327ecd..d311ace 100644
--- a/unified_inventory/init.lua
+++ b/unified_inventory/init.lua
@@ -48,8 +48,9 @@ unified_inventory = {
 }
 
 -- Disable default creative inventory
-if rawget(_G, "creative_inventory") then
-	function creative_inventory.set_creative_formspec(player, start_i, pagenum)
+local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory")
+if creative then
+	function creative.set_creative_formspec(player, start_i, pagenum)
 		return
 	end
 end
diff --git a/unified_inventory/item_names.lua b/unified_inventory/item_names.lua
index 2c92d65..243b938 100644
--- a/unified_inventory/item_names.lua
+++ b/unified_inventory/item_names.lua
@@ -6,12 +6,15 @@ local dtimes = {}
 local dlimit = 3  -- HUD element will be hidden after this many seconds
 local air_hud_mod = minetest.get_modpath("4air")
 local hud_mod = minetest.get_modpath("hud")
+local hudbars_mod = minetest.get_modpath("hudbars")
 
 local function set_hud(player)
 	local player_name = player:get_player_name() 
 	local off = {x=0, y=-70}
 	if air_hud_mod or hud_mod then
 		off.y = off.y - 20
+	elseif hudbars_mod then
+		off.y = off.y + 13
 	end
 	huds[player_name] = player:hud_add({
 		hud_elem_type = "text",
diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua
index b47b1c6..7042849 100644
--- a/unified_inventory/register.lua
+++ b/unified_inventory/register.lua
@@ -168,11 +168,6 @@ unified_inventory.register_page("craft", {
 
 -- stack_image_button(): generate a form button displaying a stack of items
 --
--- Normally a simple item_image_button[] is used.  If the stack contains
--- more than one item, item_image_button[] doesn't have an option to
--- display an item count in the way that an inventory slot does, so
--- we have to fake it using the label facility.
---
 -- The specified item may be a group.  In that case, the group will be
 -- represented by some item in the group, along with a flag indicating
 -- that it's a group.  If the group contains only one item, it will be
@@ -182,7 +177,7 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
 	local name = item:get_name()
 	local count = item:get_count()
 	local show_is_group = false
-	local displayitem = name
+	local displayitem = name.." "..count
 	local selectitem = name
 	if name:sub(1, 6) == "group:" then
 		local group_name = name:sub(7)
@@ -191,8 +186,7 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
 		displayitem = group_item.item or "unknown"
 		selectitem = group_item.sole and displayitem or name
 	end
-	local label = string.format("\n\n%s%7d", show_is_group and "  G\n" or "  ", count):gsub(" 1$", " .")
-	if label == "\n\n        ." then label = "" end
+	local label = show_is_group and "G" or ""
 	return string.format("item_image_button[%f,%f;%u,%u;%s;%s;%s]",
 			x, y, w, h,
 			minetest.formspec_escape(displayitem),
diff --git a/unifieddyes/description.txt b/unifieddyes/description.txt
new file mode 100644
index 0000000..ef5380e
--- /dev/null
+++ b/unifieddyes/description.txt
@@ -0,0 +1 @@
+Unified Dyes expands the standard dye set from 15 to 90 colors.
diff --git a/unifieddyes/mod.conf b/unifieddyes/mod.conf
new file mode 100644
index 0000000..861cb26
--- /dev/null
+++ b/unifieddyes/mod.conf
@@ -0,0 +1 @@
+name = unifieddyes
diff --git a/vines/bower.json b/vines/bower.json
new file mode 100644
index 0000000..108a7c1
--- /dev/null
+++ b/vines/bower.json
@@ -0,0 +1,18 @@
+{
+  "name": "vines",
+  "description": "Vines that spawn on trees and rope",
+  "keywords": [
+    "vines",
+    "trees",
+    "rope",
+    "jungle"
+  ],
+  "homepage": "https://github.com/bas080/vines/",
+  "screenshots": [
+    "https://raw.githubusercontent.com/bas080/vines/forum/screenshot.png"
+  ],
+  "authors": [
+    "bas080"
+  ],
+  "license": "WTFPL"
+}
diff --git a/worldedit/init.lua b/worldedit/init.lua
index e193454..ec6e99d 100644
--- a/worldedit/init.lua
+++ b/worldedit/init.lua
@@ -36,6 +36,7 @@ load_module(path .. "/visualization.lua")
 load_module(path .. "/serialization.lua")
 load_module(path .. "/code.lua")
 load_module(path .. "/compatibility.lua")
+load_module(path .. "/wand.lua")
 
 
 if minetest.setting_getbool("log_mods") then
diff --git a/worldedit/serialization.lua b/worldedit/serialization.lua
index 00d984d..a0848e2 100644
--- a/worldedit/serialization.lua
+++ b/worldedit/serialization.lua
@@ -144,9 +144,9 @@ local function load_schematic(value)
 				"([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do
 			param1, param2 = tonumber(param1), tonumber(param2)
 			table.insert(nodes, {
-				x = originx + tonumber(x),
-				y = originy + tonumber(y),
-				z = originz + tonumber(z),
+				x = tonumber(x),
+				y = tonumber(y),
+				z = tonumber(z),
 				name = name,
 				param1 = param1 ~= 0 and param1 or nil,
 				param2 = param2 ~= 0 and param2 or nil,
diff --git a/worldedit/textures/worldedit_wand.png b/worldedit/textures/worldedit_wand.png
new file mode 100644
index 0000000..13eb121
Binary files /dev/null and b/worldedit/textures/worldedit_wand.png differ
diff --git a/worldedit/wand.lua b/worldedit/wand.lua
new file mode 100644
index 0000000..415e7ca
--- /dev/null
+++ b/worldedit/wand.lua
@@ -0,0 +1,51 @@
+minetest.register_tool("worldedit:wand", {
+	description = "WorldEdit wand tool. Left-click to set the 1st position, Right-click to set the 2nd position.",
+	groups = {},
+	inventory_image = "worldedit_wand.png",
+	wield_image = "",
+	wield_scale = {x=1,y=1,z=1},
+	stack_max = 1, -- there is no need to have more than one
+	liquids_pointable = true, -- ground with only water on can be selected as well
+	-- the tool_capabilities are completely irrelevant here - no need to dig
+	tool_capabilities = {
+		full_punch_interval = 1.0,
+		max_drop_level=0,
+		groupcaps={
+			fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
+			snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
+			choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
+		}
+	},
+	node_placement_prediction = nil,
+
+	on_use = function(itemstack, placer, pointed_thing)
+	   if placer ~= nil and pointed_thing ~= nil then
+		  local name = placer:get_player_name()
+		  local pos  = minetest.get_pointed_thing_position( pointed_thing, false ) -- not above
+
+		  if not pos then
+			 return itemstack
+		  end
+
+		  worldedit.pos1[name] = pos
+		  worldedit.mark_pos1(name)
+
+	   end
+	   return itemstack -- nothing consumed, nothing changed
+	end,
+
+	on_place = function(itemstack, placer, pointed_thing) -- Left Click
+	   if placer ~= nil and pointed_thing ~= nil then
+		  local name = placer:get_player_name()
+		  local pos  = minetest.get_pointed_thing_position( pointed_thing, false ) -- not above
+
+		  if not pos then
+			 return itemstack
+		  end
+
+		  worldedit.pos2[name] = pos
+		  worldedit.mark_pos2(name)
+	   end
+	   return itemstack -- nothing consumed, nothing changed
+	end,
+})
diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua
index 83a127e..c93a760 100644
--- a/worldedit_commands/init.lua
+++ b/worldedit_commands/init.lua
@@ -838,6 +838,30 @@ minetest.register_chatcommand("/fixlight", {
 	end),
 })
 
+minetest.register_chatcommand("/drain", {
+	params = "",
+	description = "Remove any fluid node within the current WorldEdit region",
+	privs = {worldedit=true},
+	func = safe_region(function(name, param)
+		-- TODO: make an API function for this
+		local count = 0
+		local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name])
+		for x = pos1.x, pos2.x do
+		for y = pos1.y, pos2.y do
+		for z = pos1.z, pos2.z do
+			local n = minetest.get_node({x=x, y=y, z=z}).name
+			local d = minetest.registered_nodes[n]
+			if d ~= nil and (d["drawtype"] == "liquid" or d["drawtype"] == "flowingliquid") then
+				minetest.remove_node({x=x, y=y, z=z})
+				count = count + 1
+			end
+		end
+		end
+		end
+		worldedit.player_notify(name, count .. " nodes updated")
+	end),
+})
+
 minetest.register_chatcommand("/hide", {
 	params = "",
 	description = "Hide all nodes in the current WorldEdit region non-destructively",
diff --git a/worldedit_gui/init.lua b/worldedit_gui/init.lua
index da54f7b..5f602ac 100644
--- a/worldedit_gui/init.lua
+++ b/worldedit_gui/init.lua
@@ -143,8 +143,21 @@ else --fallback button
 		if not player then --this is in case the player signs off while the media is loading
 			return
 		end
-		if (minetest.check_player_privs(name, {creative=true}) or minetest.setting_getbool("creative_mode")) and creative_inventory then --creative_inventory is active, add button to modified formspec
-			formspec = player:get_inventory_formspec() .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
+		if (minetest.check_player_privs(name, {creative=true}) or
+				minetest.setting_getbool("creative_mode")) and
+				creative then --creative is active, add button to modified formspec
+			local creative_formspec = player:get_inventory_formspec()
+			local tab_id = tonumber(creative_formspec:match("tabheader%[.-;(%d+)%;"))
+
+			if tab_id == 1 then
+				formspec = creative_formspec ..
+					"image_button[0,1;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
+			elseif not tab_id then
+				formspec = creative_formspec ..
+					"image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
+			else
+				return
+			end
 		else
 			formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
 		end
-- 
cgit v1.2.3