1 local nether_channels = {}
3 minetest.register_on_joinplayer(function(player)
4 local name = player:get_player_name()
5 nether_channels[name] = minetest.mod_channel_join(name..":nether_teleporters")
8 local path = minetest.get_modpath("nether")
9 dofile(path.."/schem.lua")
10 dofile(path.."/nodes.lua")
11 dofile(path.."/biomes.lua")
12 dofile(path.."/craft_recipes.lua")
13 dofile(path.."/ore.lua")
14 dofile(path.."/items.lua")
17 minetest.register_node("nether:portal", {
18 description = "Nether Portal",
22 name = "nether_portal.png",
23 backface_culling = true,
25 type = "vertical_frames",
32 name = "nether_portal.png",
33 backface_culling = true,
35 type = "vertical_frames",
44 --paramtype2 = "facedir",
45 sunlight_propagates = true,
46 use_texture_alpha = false,
51 is_ground_content = false,
54 --post_effect_color = {a = 180, r = 51, g = 7, b = 89},
60 connect_front = {0, -1/2, -1/2, 0, 1/2, 0 },
61 connect_left = {-1/2, -1/2, 0, 0, 1/2, 0},
62 connect_back = {0, -1/2, 0, 0, 1/2, 1/2 },
63 connect_right = { 0, -1/2, 0, 1/2, 1/2, 0},
65 connects_to = {"nether:portal","nether:obsidian"},
66 groups = {unbreakable=1},
67 --on_destruct = destroy_portal,
70 --branch out from center
72 local portal_failure = false
73 local x_failed = false
75 --this can be used globally to create nether portals from obsidian
76 function create_nether_portal(pos,origin,axis)
77 --create the origin node for stored memory
80 portal_failure = false
86 --2d virtual memory map creation (x axis)
90 --index only direct neighbors
91 if x_failed == false and (math.abs(x)+math.abs(y) == 1) then
92 local i = vector.add(pos,vector.new(x,y,0))
94 local execute_collection = true
96 if n_index[i.x] and n_index[i.x][i.y] then
97 if n_index[i.x][i.y][i.z] then
98 execute_collection = false
102 if execute_collection == true then
103 --print(minetest.get_node(i).name)
105 if minetest.get_node(i).name == "air" then
107 if vector.distance(i,origin) < 50 then
108 --add data to both maps
109 if not n_index[i.x] then n_index[i.x] = {} end
110 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
111 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
112 --the data to the 3d array must be written to memory before this is executed
113 --or a stack overflow occurs!!!
114 --pass down info for activators
115 create_nether_portal(i,origin,"x")
120 create_nether_portal(origin,origin,"z")
122 elseif minetest.get_node(i).name ~= "nether:obsidian" then
125 create_nether_portal(origin,origin,"z")
131 --2d virtual memory map creation (z axis)
132 elseif axis == "z" then
135 --index only direct neighbors
136 if x_failed == true and portal_failure == false and (math.abs(z)+math.abs(y) == 1) then
137 local i = vector.add(pos,vector.new(0,y,z))
139 local execute_collection = true
141 if n_index[i.x] and n_index[i.x][i.y] then
142 if n_index[i.x][i.y][i.z] then
143 execute_collection = false
147 if execute_collection == true then
148 --print(minetest.get_node(i).name)
150 if minetest.get_node(i).name == "air" then
151 if vector.distance(i,origin) < 50 then
152 --add data to both maps
153 if not n_index[i.x] then n_index[i.x] = {} end
154 if not n_index[i.x][i.y] then n_index[i.x][i.y] = {} end
155 n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
156 --the data to the 3d array must be written to memory before this is executed
157 --or a stack overflow occurs!!!
158 --pass down info for activators
159 create_nether_portal(i,origin,"z")
161 --print("portal failed")
162 portal_failure = true
166 elseif minetest.get_node(i).name ~= "nether:obsidian" then
167 --print("portal failed")
168 portal_failure = true
178 --creates a nether portal in the nether
179 --this essentially makes it so you have to move 30 away from one portal to another otherwise it will travel to an existing portal
180 local nether_origin_pos = nil
181 local function spawn_portal_into_nether_callback(blockpos, action, calls_remaining, param)
182 if calls_remaining == 0 then
183 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
185 if not portal_exists then
186 local min = vector.subtract(nether_origin_pos,30)
187 local max = vector.add(nether_origin_pos,30)
188 local platform = minetest.find_nodes_in_area_under_air(min, max, {"nether:netherrack","main:lava"})
190 if platform and next(platform) then
191 --print("setting the platform")
192 local platform_location = platform[math.random(1,table.getn(platform))]
194 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
196 --print("generate a portal within netherrack")
197 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
200 --print("portal exists, utilizing")
202 nether_origin_pos = nil
205 --creates nether portals in the overworld
206 local function spawn_portal_into_overworld_callback(blockpos, action, calls_remaining, param)
207 if calls_remaining == 0 then
208 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
210 if not portal_exists then
211 local min = vector.subtract(nether_origin_pos,30)
212 local max = vector.add(nether_origin_pos,30)
213 local platform = minetest.find_nodes_in_area_under_air(min, max, {"main:stone","main:water","main:grass","main:sand","main:dirt"})
215 if platform and next(platform) then
216 --print("setting the platform")
217 local platform_location = platform[math.random(1,table.getn(platform))]
219 minetest.place_schematic(platform_location, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
221 --print("generate a portal within overworld stone")
222 minetest.place_schematic(nether_origin_pos, portalSchematic,"0",nil,true,"place_center_x, place_center_z")
225 --print("portal exists, utilizing")
227 nether_origin_pos = nil
232 local function generate_nether_portal_in_nether(pos)
233 if pos.y > -10033 then
234 --center the location to the lava height
235 pos.y = -15000--+math.random(-30,30)
236 nether_origin_pos = pos
238 local min = vector.subtract(nether_origin_pos,30)
239 local max = vector.add(nether_origin_pos,30)
241 --force load the area
242 minetest.emerge_area(min, max, spawn_portal_into_nether_callback)
244 --center the location to the water height
245 pos.y = 0--+math.random(-30,30)
246 nether_origin_pos = pos
247 --prefer height for mountains
248 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
249 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
251 --force load the area
252 minetest.emerge_area(min, max, spawn_portal_into_overworld_callback)
257 --modify the map with the collected data
258 local function portal_modify_map(n_copy)
259 local sorted_table = {}
260 local created_portal = false
261 for x,datax in pairs(n_copy) do
262 for y,datay in pairs(datax) do
263 for z,index in pairs(datay) do
264 --try to create a return side nether portal
265 if created_portal == false then
266 created_portal = true
267 generate_nether_portal_in_nether(vector.new(x,y,z))
269 table.insert(sorted_table, vector.new(x,y,z))
273 minetest.bulk_set_node(sorted_table, {name="nether:portal"})
276 -------------------------------------------------------------------------------------------
277 --the teleporter parts - stored here for now so I can read from other functions
278 local teleporting_player = nil
279 local function teleport_to_overworld(blockpos, action, calls_remaining, param)
280 if calls_remaining == 0 then
281 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
282 if portal_exists then
283 --print(teleporting_player)
284 if teleporting_player then
285 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
288 teleporting_player = nil
291 local function teleport_to_nether(blockpos, action, calls_remaining, param)
292 if calls_remaining == 0 then
293 local portal_exists = minetest.find_node_near(nether_origin_pos, 30, {"nether:portal"})
294 if portal_exists then
295 --print(teleporting_player)
296 if teleporting_player then
297 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
300 teleporting_player = nil
304 --this initializes all teleporter commands from the client
305 minetest.register_on_modchannel_message(function(channel_name, sender, message)
306 local channel_decyphered = channel_name:gsub(sender,"")
307 if channel_decyphered == ":nether_teleporters" then
308 local player = minetest.get_player_by_name(sender)
309 local pos = player:get_pos()
311 if pos.y > -10033 then
312 --center the location to the lava height
313 pos.y = -15000--+math.random(-30,30)
314 nether_origin_pos = pos
316 local min = vector.subtract(nether_origin_pos,30)
317 local max = vector.add(nether_origin_pos,30)
319 --force load the area
320 teleporting_player = player
321 minetest.emerge_area(min, max, teleport_to_nether)
323 --center the location to the water height
324 pos.y = 0--+math.random(-30,30)
325 nether_origin_pos = pos
326 --prefer height for mountains
327 local min = vector.subtract(nether_origin_pos,vector.new(30,30,30))
328 local max = vector.add(nether_origin_pos,vector.new(30,120,30))
330 --force load the area
331 teleporting_player = player
332 minetest.emerge_area(min, max, teleport_to_overworld)
336 -------------------------------------------------------------------------------------------
338 -------------------------------------------------------------------------------
340 local destroy_n_index = {}
341 local destroy_portal_failure = false
342 local destroy_x_failed = false
344 --this can be used globally to create nether portals from obsidian
345 function destroy_nether_portal(pos,origin,axis)
346 --create the origin node for stored memory
350 --3d virtual memory map creation (x axis)
354 --index only direct neighbors
355 if (math.abs(x)+math.abs(z)+math.abs(y) == 1) then
356 local i = vector.add(pos,vector.new(x,y,z))
358 local execute_collection = true
360 if destroy_n_index[i.x] and destroy_n_index[i.x][i.y] then
361 if destroy_n_index[i.x][i.y][i.z] then
362 execute_collection = false
366 if execute_collection == true then
367 --print(minetest.get_node(i).name)
369 if minetest.get_node(i).name == "nether:portal" then
370 if vector.distance(i,origin) < 50 then
371 --add data to both maps
372 if not destroy_n_index[i.x] then destroy_n_index[i.x] = {} end
373 if not destroy_n_index[i.x][i.y] then destroy_n_index[i.x][i.y] = {} end
374 destroy_n_index[i.x][i.y][i.z] = {nether_portal=1} --get_group(i,"redstone_power")}
375 --the data to the 3d array must be written to memory before this is executed
376 --or a stack overflow occurs!!!
377 --pass down info for activators
378 destroy_nether_portal(i,origin,"z")
388 --modify the map with the collected data
389 local function destroy_portal_modify_map(destroy_n_copy)
390 local destroy_sorted_table = {}
391 for x,datax in pairs(destroy_n_copy) do
392 for y,datay in pairs(datax) do
393 for z,index in pairs(datay) do
394 table.insert(destroy_sorted_table, vector.new(x,y,z))
398 minetest.bulk_set_node(destroy_sorted_table, {name="air"})
401 minetest.register_globalstep(function(dtime)
402 --if indexes exist then calculate redstone
403 if n_index and next(n_index) and portal_failure == false then
404 --create the old version to help with deactivation calculation
405 local n_copy = table.copy(n_index)
406 portal_modify_map(n_copy)
407 portal_failure = false
409 if x_failed == true then
412 if portal_failure == true then
413 portal_failure = false
415 --clear the index to avoid cpu looping wasting processing power
419 --if indexes exist then calculate redstone
420 if destroy_n_index and next(destroy_n_index) and destroy_portal_failure == false then
421 --create the old version to help with deactivation calculation
422 local destroy_n_copy = table.copy(destroy_n_index)
423 destroy_portal_modify_map(destroy_n_copy)
425 --clear the index to avoid cpu looping wasting processing power