1 local nether_channel = minetest.mod_channel_join("nether_teleporters")
3 local path = minetest.get_modpath("nether")
4 dofile(path.."/schem.lua")
5 dofile(path.."/nodes.lua")
6 dofile(path.."/biomes.lua")
7 dofile(path.."/craft_recipes.lua")
8 dofile(path.."/ore.lua")
9 dofile(path.."/items.lua")
12 minetest.register_node("nether:portal", {
13 description = "Nether Portal",
17 name = "nether_portal.png",
18 backface_culling = true,
20 type = "vertical_frames",
27 name = "nether_portal.png",
28 backface_culling = true,
30 type = "vertical_frames",
39 --paramtype2 = "facedir",
40 sunlight_propagates = true,
41 use_texture_alpha = false,
46 is_ground_content = false,
49 --post_effect_color = {a = 180, r = 51, g = 7, b = 89},
55 connect_front = {0, -1/2, -1/2, 0, 1/2, 0 },
56 connect_left = {-1/2, -1/2, 0, 0, 1/2, 0},
57 connect_back = {0, -1/2, 0, 0, 1/2, 1/2 },
58 connect_right = { 0, -1/2, 0, 1/2, 1/2, 0},
60 connects_to = {"nether:portal","nether:obsidian"},
61 groups = {unbreakable=1},
62 --on_destruct = destroy_portal,
65 --branch out from center
67 local portal_failure = false
68 local x_failed = false
70 --this can be used globally to create nether portals from obsidian
71 function create_nether_portal(pos,origin,axis)
72 --create the origin node for stored memory
75 portal_failure = false
81 --2d virtual memory map creation (x axis)
85 --index only direct neighbors
86 if x_failed == false and (math.abs(x)+math.abs(y) == 1) then
87 local i = vector.add(pos,vector.new(x,y,0))
89 local execute_collection = true
91 if n_index[i.x] and n_index[i.x][i.y] then
92 if n_index[i.x][i.y][i.z] then
93 execute_collection = false
97 if execute_collection == true then
98 --print(minetest.get_node(i).name)
100 if minetest.get_node(i).name == "air" then
102 if vector.distance(i,origin) < 50 then
103 --add data to both maps
104 if not n_index[i.x] then n_index[i.x] = {} end
105 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
106 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
107 --the data to the 3d array must be written to memory before this is executed
108 --or a stack overflow occurs!!!
109 --pass down info for activators
110 create_nether_portal(i,origin,"x")
115 create_nether_portal(origin,origin,"z")
117 elseif minetest.get_node(i).name ~= "nether:obsidian" then
120 create_nether_portal(origin,origin,"z")
126 --2d virtual memory map creation (z axis)
127 elseif axis == "z" then
130 --index only direct neighbors
131 if x_failed == true and portal_failure == false and (math.abs(z)+math.abs(y) == 1) then
132 local i = vector.add(pos,vector.new(0,y,z))
134 local execute_collection = true
136 if n_index[i.x] and n_index[i.x][i.y] then
137 if n_index[i.x][i.y][i.z] then
138 execute_collection = false
142 if execute_collection == true then
143 --print(minetest.get_node(i).name)
145 if minetest.get_node(i).name == "air" then
146 if vector.distance(i,origin) < 50 then
147 --add data to both maps
148 if not n_index[i.x] then n_index[i.x] = {} end
149 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
150 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
151 --the data to the 3d array must be written to memory before this is executed
152 --or a stack overflow occurs!!!
153 --pass down info for activators
154 create_nether_portal(i,origin,"z")
156 --print("portal failed")
157 portal_failure = true
161 elseif minetest.get_node(i).name ~= "nether:obsidian" then
162 --print("portal failed")
163 portal_failure = true
173 --creates a nether portal in the nether
174 --this essentially makes it so you have to move 30 away from one portal to another otherwise it will travel to an existing portal
175 local nether_origin_pos = nil
176 local function spawn_portal_into_nether_callback(blockpos, action, calls_remaining, param)
177 if calls_remaining == 0 then
178 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
180 if not portal_exists then
181 local min = vector.subtract(nether_origin_pos,30)
182 local max = vector.add(nether_origin_pos,30)
183 local platform = minetest.find_nodes_in_area_under_air(min, max, {"nether:netherrack","main:lava"})
185 if platform and next(platform) then
186 --print("setting the platform")
187 local platform_location = platform[math.random(1,table.getn(platform))]
189 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
191 --print("generate a portal within netherrack")
192 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
195 --print("portal exists, utilizing")
197 nether_origin_pos = nil
200 --creates nether portals in the overworld
201 local function spawn_portal_into_overworld_callback(blockpos, action, calls_remaining, param)
202 if calls_remaining == 0 then
203 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
205 if not portal_exists then
206 local min = vector.subtract(nether_origin_pos,30)
207 local max = vector.add(nether_origin_pos,30)
208 local platform = minetest.find_nodes_in_area_under_air(min, max, {"main:stone","main:water","main:grass","main:sand","main:dirt"})
210 if platform and next(platform) then
211 --print("setting the platform")
212 local platform_location = platform[math.random(1,table.getn(platform))]
214 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
216 --print("generate a portal within overworld stone")
217 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
220 --print("portal exists, utilizing")
222 nether_origin_pos = nil
227 local function generate_nether_portal_in_nether(pos)
228 if pos.y > -10033 then
229 --center the location to the lava height
230 pos.y = -15000--+math.random(-30,30)
231 nether_origin_pos = pos
233 local min = vector.subtract(nether_origin_pos,30)
234 local max = vector.add(nether_origin_pos,30)
236 --force load the area
237 minetest.emerge_area(min, max, spawn_portal_into_nether_callback)
239 --center the location to the water height
240 pos.y = 0--+math.random(-30,30)
241 nether_origin_pos = pos
242 --prefer height for mountains
243 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
244 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
246 --force load the area
247 minetest.emerge_area(min, max, spawn_portal_into_overworld_callback)
252 --modify the map with the collected data
253 local function portal_modify_map(n_copy)
254 local sorted_table = {}
255 local created_portal = false
256 for x,datax in pairs(n_copy) do
257 for y,datay in pairs(datax) do
258 for z,index in pairs(datay) do
259 --try to create a return side nether portal
260 if created_portal == false then
261 created_portal = true
262 generate_nether_portal_in_nether(vector.new(x,y,z))
264 table.insert(sorted_table, vector.new(x,y,z))
268 minetest.bulk_set_node(sorted_table, {name="nether:portal"})
271 -------------------------------------------------------------------------------------------
272 --the teleporter parts - stored here for now so I can read from other functions
273 local teleporting_player = nil
274 local function teleport_to_overworld(blockpos, action, calls_remaining, param)
275 if calls_remaining == 0 then
276 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
277 if portal_exists then
278 --print(teleporting_player)
279 if teleporting_player then
280 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
283 teleporting_player = nil
286 local function teleport_to_nether(blockpos, action, calls_remaining, param)
287 if calls_remaining == 0 then
288 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
289 if portal_exists then
290 --print(teleporting_player)
291 if teleporting_player then
292 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
295 teleporting_player = nil
299 --this initializes all teleporter commands from the client
300 minetest.register_on_modchannel_message(function(channel_name, sender, message)
301 if channel_name == "nether_teleporters" then
302 local player = minetest.get_player_by_name(sender)
303 local pos = player:get_pos()
305 if pos.y > -10033 then
306 --center the location to the lava height
307 pos.y = -15000--+math.random(-30,30)
308 nether_origin_pos = pos
310 local min = vector.subtract(nether_origin_pos,30)
311 local max = vector.add(nether_origin_pos,30)
313 --force load the area
314 teleporting_player = player
315 minetest.emerge_area(min, max, teleport_to_nether)
317 --center the location to the water height
318 pos.y = 0--+math.random(-30,30)
319 nether_origin_pos = pos
320 --prefer height for mountains
321 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
322 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
324 --force load the area
325 teleporting_player = player
326 minetest.emerge_area(min, max, teleport_to_overworld)
330 -------------------------------------------------------------------------------------------
332 -------------------------------------------------------------------------------
334 local destroy_n_index = {}
335 local destroy_portal_failure = false
336 local destroy_x_failed = false
338 --this can be used globally to create nether portals from obsidian
339 function destroy_nether_portal(pos,origin,axis)
340 --create the origin node for stored memory
344 --3d virtual memory map creation (x axis)
348 --index only direct neighbors
349 if (math.abs(x)+math.abs(z)+math.abs(y) == 1) then
350 local i = vector.add(pos,vector.new(x,y,z))
352 local execute_collection = true
354 if destroy_n_index[i.x] and destroy_n_index[i.x][i.y] then
355 if destroy_n_index[i.x][i.y][i.z] then
356 execute_collection = false
360 if execute_collection == true then
361 --print(minetest.get_node(i).name)
363 if minetest.get_node(i).name == "nether:portal" then
364 if vector.distance(i,origin) < 50 then
365 --add data to both maps
366 if not destroy_n_index[i.x] then destroy_n_index[i.x] = {} end
367 if not destroy_n_index[i.x][i.y] then destroy_n_index[i.x][i.y] = {} end
368 destroy_n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
369 --the data to the 3d array must be written to memory before this is executed
370 --or a stack overflow occurs!!!
371 --pass down info for activators
372 destroy_nether_portal(i,origin,"z")
382 --modify the map with the collected data
383 local function destroy_portal_modify_map(destroy_n_copy)
384 local destroy_sorted_table = {}
385 for x,datax in pairs(destroy_n_copy) do
386 for y,datay in pairs(datax) do
387 for z,index in pairs(datay) do
388 table.insert(destroy_sorted_table, vector.new(x,y,z))
392 minetest.bulk_set_node(destroy_sorted_table, {name="air"})
395 minetest.register_globalstep(function(dtime)
396 --if indexes exist then calculate redstone
397 if n_index and next(n_index) and portal_failure == false then
398 --create the old version to help with deactivation calculation
399 local n_copy = table.copy(n_index)
400 portal_modify_map(n_copy)
401 portal_failure = false
403 if x_failed == true then
406 if portal_failure == true then
407 portal_failure = false
409 --clear the index to avoid cpu looping wasting processing power
413 --if indexes exist then calculate redstone
414 if destroy_n_index and next(destroy_n_index) and destroy_portal_failure == false then
415 --create the old version to help with deactivation calculation
416 local destroy_n_copy = table.copy(destroy_n_index)
417 destroy_portal_modify_map(destroy_n_copy)
419 --clear the index to avoid cpu looping wasting processing power