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")
11 minetest.register_node("nether:portal", {
12 description = "Nether Portal",
16 name = "nether_portal.png",
17 backface_culling = true,
19 type = "vertical_frames",
26 name = "nether_portal.png",
27 backface_culling = true,
29 type = "vertical_frames",
38 --paramtype2 = "facedir",
39 sunlight_propagates = true,
40 use_texture_alpha = false,
45 is_ground_content = false,
48 --post_effect_color = {a = 180, r = 51, g = 7, b = 89},
54 connect_front = {0, -1/2, -1/2, 0, 1/2, 0 },
55 connect_left = {-1/2, -1/2, 0, 0, 1/2, 0},
56 connect_back = {0, -1/2, 0, 0, 1/2, 1/2 },
57 connect_right = { 0, -1/2, 0, 1/2, 1/2, 0},
59 connects_to = {"nether:portal","nether:obsidian"},
60 groups = {unbreakable=1},
61 --on_destruct = destroy_portal,
64 --branch out from center
66 local portal_failure = false
67 local x_failed = false
69 --this can be used globally to create nether portals from obsidian
70 function create_nether_portal(pos,origin,axis)
71 --create the origin node for stored memory
74 portal_failure = false
80 --2d virtual memory map creation (x axis)
84 --index only direct neighbors
85 if x_failed == false and (math.abs(x)+math.abs(y) == 1) then
86 local i = vector.add(pos,vector.new(x,y,0))
88 local execute_collection = true
90 if n_index[i.x] and n_index[i.x][i.y] then
91 if n_index[i.x][i.y][i.z] then
92 execute_collection = false
96 if execute_collection == true then
97 --print(minetest.get_node(i).name)
99 if minetest.get_node(i).name == "air" then
101 if vector.distance(i,origin) < 50 then
102 --add data to both maps
103 if not n_index[i.x] then n_index[i.x] = {} end
104 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
105 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
106 --the data to the 3d array must be written to memory before this is executed
107 --or a stack overflow occurs!!!
108 --pass down info for activators
109 create_nether_portal(i,origin,"x")
114 create_nether_portal(origin,origin,"z")
116 elseif minetest.get_node(i).name ~= "nether:obsidian" then
119 create_nether_portal(origin,origin,"z")
125 --2d virtual memory map creation (z axis)
126 elseif axis == "z" then
129 --index only direct neighbors
130 if x_failed == true and portal_failure == false and (math.abs(z)+math.abs(y) == 1) then
131 local i = vector.add(pos,vector.new(0,y,z))
133 local execute_collection = true
135 if n_index[i.x] and n_index[i.x][i.y] then
136 if n_index[i.x][i.y][i.z] then
137 execute_collection = false
141 if execute_collection == true then
142 --print(minetest.get_node(i).name)
144 if minetest.get_node(i).name == "air" then
145 if vector.distance(i,origin) < 50 then
146 --add data to both maps
147 if not n_index[i.x] then n_index[i.x] = {} end
148 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
149 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
150 --the data to the 3d array must be written to memory before this is executed
151 --or a stack overflow occurs!!!
152 --pass down info for activators
153 create_nether_portal(i,origin,"z")
155 --print("portal failed")
156 portal_failure = true
160 elseif minetest.get_node(i).name ~= "nether:obsidian" then
161 --print("portal failed")
162 portal_failure = true
172 --creates a nether portal in the nether
173 --this essentially makes it so you have to move 30 away from one portal to another otherwise it will travel to an existing portal
174 local nether_origin_pos = nil
175 local function spawn_portal_into_nether_callback(blockpos, action, calls_remaining, param)
176 if calls_remaining == 0 then
177 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
179 if not portal_exists then
180 local min = vector.subtract(nether_origin_pos,30)
181 local max = vector.add(nether_origin_pos,30)
182 local platform = minetest.find_nodes_in_area_under_air(min, max, {"nether:netherrack","main:lava"})
184 if platform and next(platform) then
185 --print("setting the platform")
186 local platform_location = platform[math.random(1,table.getn(platform))]
188 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
190 --print("generate a portal within netherrack")
191 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
194 --print("portal exists, utilizing")
196 nether_origin_pos = nil
199 --creates nether portals in the overworld
200 local function spawn_portal_into_overworld_callback(blockpos, action, calls_remaining, param)
201 if calls_remaining == 0 then
202 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
204 if not portal_exists then
205 local min = vector.subtract(nether_origin_pos,30)
206 local max = vector.add(nether_origin_pos,30)
207 local platform = minetest.find_nodes_in_area_under_air(min, max, {"main:stone","main:water","main:grass","main:sand","main:dirt"})
209 if platform and next(platform) then
210 --print("setting the platform")
211 local platform_location = platform[math.random(1,table.getn(platform))]
213 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
215 --print("generate a portal within overworld stone")
216 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
219 --print("portal exists, utilizing")
221 nether_origin_pos = nil
226 local function generate_nether_portal_in_nether(pos)
227 if pos.y > -10033 then
228 --center the location to the lava height
229 pos.y = -15000--+math.random(-30,30)
230 nether_origin_pos = pos
232 local min = vector.subtract(nether_origin_pos,30)
233 local max = vector.add(nether_origin_pos,30)
235 --force load the area
236 minetest.emerge_area(min, max, spawn_portal_into_nether_callback)
238 --center the location to the water height
239 pos.y = 0--+math.random(-30,30)
240 nether_origin_pos = pos
241 --prefer height for mountains
242 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
243 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
245 --force load the area
246 minetest.emerge_area(min, max, spawn_portal_into_overworld_callback)
251 --modify the map with the collected data
252 local function portal_modify_map(n_copy)
253 local sorted_table = {}
254 local created_portal = false
255 for x,datax in pairs(n_copy) do
256 for y,datay in pairs(datax) do
257 for z,index in pairs(datay) do
258 --try to create a return side nether portal
259 if created_portal == false then
260 created_portal = true
261 generate_nether_portal_in_nether(vector.new(x,y,z))
263 table.insert(sorted_table, vector.new(x,y,z))
267 minetest.bulk_set_node(sorted_table, {name="nether:portal"})
270 -------------------------------------------------------------------------------------------
271 --the teleporter parts - stored here for now so I can read from other functions
272 local teleporting_player = nil
273 local function teleport_to_overworld(blockpos, action, calls_remaining, param)
274 if calls_remaining == 0 then
275 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
276 if portal_exists then
277 print(teleporting_player)
278 if teleporting_player then
279 teleporting_player:set_pos(portal_exists)
282 teleporting_player = nil
285 local function teleport_to_nether(blockpos, action, calls_remaining, param)
286 if calls_remaining == 0 then
287 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
288 if portal_exists then
289 print(teleporting_player)
290 if teleporting_player then
291 teleporting_player:set_pos(portal_exists)
294 teleporting_player = nil
298 --this initializes all teleporter commands from the client
299 minetest.register_on_modchannel_message(function(channel_name, sender, message)
300 if channel_name == "nether_teleporters" then
301 local player = minetest.get_player_by_name(sender)
302 local pos = player:get_pos()
304 if pos.y > -10033 then
305 --center the location to the lava height
306 pos.y = -15000--+math.random(-30,30)
307 nether_origin_pos = pos
309 local min = vector.subtract(nether_origin_pos,30)
310 local max = vector.add(nether_origin_pos,30)
312 --force load the area
313 teleporting_player = player
314 minetest.emerge_area(min, max, teleport_to_nether)
316 --center the location to the water height
317 pos.y = 0--+math.random(-30,30)
318 nether_origin_pos = pos
319 --prefer height for mountains
320 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
321 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
323 --force load the area
324 teleporting_player = player
325 minetest.emerge_area(min, max, teleport_to_overworld)
329 -------------------------------------------------------------------------------------------
331 -------------------------------------------------------------------------------
333 local destroy_n_index = {}
334 local destroy_portal_failure = false
335 local destroy_x_failed = false
337 --this can be used globally to create nether portals from obsidian
338 function destroy_nether_portal(pos,origin,axis)
339 --create the origin node for stored memory
343 --3d virtual memory map creation (x axis)
347 --index only direct neighbors
348 if (math.abs(x)+math.abs(z)+math.abs(y) == 1) then
349 local i = vector.add(pos,vector.new(x,y,z))
351 local execute_collection = true
353 if destroy_n_index[i.x] and destroy_n_index[i.x][i.y] then
354 if destroy_n_index[i.x][i.y][i.z] then
355 execute_collection = false
359 if execute_collection == true then
360 --print(minetest.get_node(i).name)
362 if minetest.get_node(i).name == "nether:portal" then
363 if vector.distance(i,origin) < 50 then
364 --add data to both maps
365 if not destroy_n_index[i.x] then destroy_n_index[i.x] = {} end
366 if not destroy_n_index[i.x][i.y] then destroy_n_index[i.x][i.y] = {} end
367 destroy_n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
368 --the data to the 3d array must be written to memory before this is executed
369 --or a stack overflow occurs!!!
370 --pass down info for activators
371 destroy_nether_portal(i,origin,"z")
381 --modify the map with the collected data
382 local function destroy_portal_modify_map(destroy_n_copy)
383 local destroy_sorted_table = {}
384 for x,datax in pairs(destroy_n_copy) do
385 for y,datay in pairs(datax) do
386 for z,index in pairs(datay) do
387 table.insert(destroy_sorted_table, vector.new(x,y,z))
391 minetest.bulk_set_node(destroy_sorted_table, {name="air"})
394 minetest.register_globalstep(function(dtime)
395 --if indexes exist then calculate redstone
396 if n_index and next(n_index) and portal_failure == false then
397 --create the old version to help with deactivation calculation
398 local n_copy = table.copy(n_index)
399 portal_modify_map(n_copy)
400 portal_failure = false
402 if x_failed == true then
405 if portal_failure == true then
406 portal_failure = false
408 --clear the index to avoid cpu looping wasting processing power
412 --if indexes exist then calculate redstone
413 if destroy_n_index and next(destroy_n_index) and destroy_portal_failure == false then
414 --create the old version to help with deactivation calculation
415 local destroy_n_copy = table.copy(destroy_n_index)
416 destroy_portal_modify_map(destroy_n_copy)
418 --clear the index to avoid cpu looping wasting processing power