1 local aether_channels = {}
3 minetest.register_on_joinplayer(function(player)
4 local name = player:get_player_name()
5 aether_channels[name] = minetest.mod_channel_join(name..":aether_teleporters")
9 local path = minetest.get_modpath("aether")
10 dofile(path.."/schem.lua")
11 dofile(path.."/nodes.lua")
12 dofile(path.."/biomes.lua")
15 minetest.register_node("aether:portal", {
16 description = "Aether Portal",
20 name = "aether_portal.png",
21 backface_culling = true,
23 type = "vertical_frames",
30 name = "aether_portal.png",
31 backface_culling = true,
33 type = "vertical_frames",
42 --paramtype2 = "facedir",
43 sunlight_propagates = true,
44 use_texture_alpha = false,
49 is_ground_content = false,
52 --post_effect_color = {a = 180, r = 51, g = 7, b = 89},
58 connect_front = {0, -1/2, -1/2, 0, 1/2, 0 },
59 connect_left = {-1/2, -1/2, 0, 0, 1/2, 0},
60 connect_back = {0, -1/2, 0, 0, 1/2, 1/2 },
61 connect_right = { 0, -1/2, 0, 1/2, 1/2, 0},
63 connects_to = {"aether:portal","nether:glowstone"},
64 groups = {unbreakable=1},
65 --on_destruct = destroy_portal,
68 --branch out from center
70 local aether_portal_failure = false
71 local x_failed = false
73 --this can be used globally to create aether portals from obsidian
74 function create_aether_portal(pos,origin,axis)
75 --create the origin node for stored memory
78 aether_portal_failure = false
84 --2d virtual memory map creation (x axis)
88 --index only direct neighbors
89 if x_failed == false and (math.abs(x)+math.abs(y) == 1) then
90 local i = vector.add(pos,vector.new(x,y,0))
92 local execute_collection = true
94 if a_index[i.x] and a_index[i.x][i.y] then
95 if a_index[i.x][i.y][i.z] then
96 execute_collection = false
100 if execute_collection == true then
101 --print(minetest.get_node(i).name)
103 if minetest.get_node(i).name == "air" then
105 if vector.distance(i,origin) < 50 then
106 --add data to both maps
107 if not a_index[i.x] then a_index[i.x] = {} end
108 if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
109 a_index[i.x][i.y][i.z] = {aether_portal=1} --get_group(i,"redstone_power")}
110 --the data to the 3d array must be written to memory before this is executed
111 --or a stack overflow occurs!!!
112 --pass down info for activators
113 create_aether_portal(i,origin,"x")
118 create_aether_portal(origin,origin,"z")
120 elseif minetest.get_node(i).name ~= "nether:glowstone" then
123 create_aether_portal(origin,origin,"z")
129 --2d virtual memory map creation (z axis)
130 elseif axis == "z" then
133 --index only direct neighbors
134 if x_failed == true and aether_portal_failure == false and (math.abs(z)+math.abs(y) == 1) then
135 local i = vector.add(pos,vector.new(0,y,z))
137 local execute_collection = true
139 if a_index[i.x] and a_index[i.x][i.y] then
140 if a_index[i.x][i.y][i.z] then
141 execute_collection = false
145 if execute_collection == true then
146 --print(minetest.get_node(i).name)
148 if minetest.get_node(i).name == "air" then
149 if vector.distance(i,origin) < 50 then
150 --add data to both maps
151 if not a_index[i.x] then a_index[i.x] = {} end
152 if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
153 a_index[i.x][i.y][i.z] = {aether_portal=1} --get_group(i,"redstone_power")}
154 --the data to the 3d array must be written to memory before this is executed
155 --or a stack overflow occurs!!!
156 --pass down info for activators
157 create_aether_portal(i,origin,"z")
159 --print("portal failed")
160 aether_portal_failure = true
164 elseif minetest.get_node(i).name ~= "nether:glowstone" then
165 --print("portal failed")
166 aether_portal_failure = true
176 --creates a aether portal in the aether
177 --this essentially makes it so you have to move 30 away from one portal to another otherwise it will travel to an existing portal
178 local aether_origin_pos = nil
179 local function spawn_portal_into_aether_callback(blockpos, action, calls_remaining, param)
180 if calls_remaining == 0 then
181 local portal_exists = minetest.find_node_near(aether_origin_pos, 30, {"aether:portal"})
183 if not portal_exists then
184 local min = vector.subtract(aether_origin_pos,30)
185 local max = vector.add(aether_origin_pos,30)
186 local platform = minetest.find_nodes_in_area_under_air(min, max, {"aether:dirt","aether:grass"})
188 if platform and next(platform) then
189 --print("setting the platform")
190 local platform_location = platform[math.random(1,table.getn(platform))]
192 minetest.place_schematic(platform_location, aetherportalSchematic,"0",nil,true,"place_center_x, place_center_z")
194 --print("generate a portal within aetherrack")
195 minetest.place_schematic(aether_origin_pos, aetherportalSchematic,"0",nil,true,"place_center_x, place_center_z")
198 --print("portal exists, utilizing")
200 aether_origin_pos = nil
203 --creates aether portals in the overworld
204 local function spawn_portal_into_overworld_callback(blockpos, action, calls_remaining, param)
205 if calls_remaining == 0 then
206 local portal_exists = minetest.find_node_near(aether_origin_pos, 30, {"aether:portal"})
208 if not portal_exists then
209 local min = vector.subtract(aether_origin_pos,30)
210 local max = vector.add(aether_origin_pos,30)
211 local platform = minetest.find_nodes_in_area_under_air(min, max, {"main:stone","main:water","main:grass","main:sand","main:dirt"})
213 if platform and next(platform) then
214 --print("setting the platform")
215 local platform_location = platform[math.random(1,table.getn(platform))]
217 minetest.place_schematic(platform_location, aetherportalSchematic,"0",nil,true,"place_center_x, place_center_z")
219 --print("generate a portal within overworld stone")
220 minetest.place_schematic(aether_origin_pos, aetherportalSchematic,"0",nil,true,"place_center_x, place_center_z")
223 --print("portal exists, utilizing")
225 aether_origin_pos = nil
230 local function generate_aether_portal_in_aether(pos)
231 if pos.y < 20000 then
232 --center the location to the lava height
233 pos.y = 25000--+math.random(-30,30)
234 aether_origin_pos = pos
236 local min = vector.subtract(aether_origin_pos,30)
237 local max = vector.add(aether_origin_pos,30)
239 --force load the area
240 minetest.emerge_area(min, max, spawn_portal_into_aether_callback)
242 --center the location to the water height
243 pos.y = 0--+math.random(-30,30)
244 aether_origin_pos = pos
245 --prefer height for mountains
246 local min = vector.subtract(aether_origin_pos,vector.new(30,30,30))
247 local max = vector.add(aether_origin_pos,vector.new(30,120,30))
249 --force load the area
250 minetest.emerge_area(min, max, spawn_portal_into_overworld_callback)
255 --modify the map with the collected data
256 local function portal_modify_map(n_copy)
257 local sorted_table = {}
258 local created_portal = false
259 for x,datax in pairs(n_copy) do
260 for y,datay in pairs(datax) do
261 for z,index in pairs(datay) do
262 --try to create a return side aether portal
263 if created_portal == false then
264 created_portal = true
265 generate_aether_portal_in_aether(vector.new(x,y,z))
267 table.insert(sorted_table, vector.new(x,y,z))
271 minetest.bulk_set_node(sorted_table, {name="aether:portal"})
274 -------------------------------------------------------------------------------------------
275 --the teleporter parts - stored here for now so I can read from other functions
276 local teleporting_player = nil
277 local function teleport_to_overworld(blockpos, action, calls_remaining, param)
278 if calls_remaining == 0 then
279 local portal_exists = minetest.find_node_near(aether_origin_pos, 30, {"aether:portal"})
280 if portal_exists then
281 --print(teleporting_player)
282 if teleporting_player then
283 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
286 teleporting_player = nil
289 local function teleport_to_aether(blockpos, action, calls_remaining, param)
290 if calls_remaining == 0 then
291 local portal_exists = minetest.find_node_near(aether_origin_pos, 30, {"aether:portal"})
292 if portal_exists then
293 --print(teleporting_player)
294 if teleporting_player then
295 teleporting_player:set_pos(vector.new(portal_exists.x,portal_exists.y-0.5,portal_exists.z))
298 teleporting_player = nil
302 --this initializes all teleporter commands from the client
303 minetest.register_on_modchannel_message(function(channel_name, sender, message)
304 local channel_decyphered = channel_name:gsub(sender,"")
305 if channel_decyphered == ":aether_teleporters" then
306 local player = minetest.get_player_by_name(sender)
307 local pos = player:get_pos()
309 if pos.y < 20000 then
310 --center the location to the lava height
311 pos.y = 25000--+math.random(-30,30)
312 aether_origin_pos = pos
314 local min = vector.subtract(aether_origin_pos,30)
315 local max = vector.add(aether_origin_pos,30)
317 --force load the area
318 teleporting_player = player
319 minetest.emerge_area(min, max, teleport_to_aether)
321 --center the location to the water height
322 pos.y = 0--+math.random(-30,30)
323 aether_origin_pos = pos
324 --prefer height for mountains
325 local min = vector.subtract(aether_origin_pos,vector.new(30,30,30))
326 local max = vector.add(aether_origin_pos,vector.new(30,120,30))
328 --force load the area
329 teleporting_player = player
330 minetest.emerge_area(min, max, teleport_to_overworld)
334 -------------------------------------------------------------------------------------------
336 -------------------------------------------------------------------------------
338 local destroy_a_index = {}
339 local destroy_aether_portal_failure = false
340 local destroy_aether_portal_failed = false
342 --this can be used globally to create aether portals from obsidian
343 function destroy_aether_portal(pos,origin,axis)
344 --create the origin node for stored memory
348 --3d virtual memory map creation (x axis)
352 --index only direct neighbors
353 if (math.abs(x)+math.abs(z)+math.abs(y) == 1) then
354 local i = vector.add(pos,vector.new(x,y,z))
356 local execute_collection = true
358 if destroy_a_index[i.x] and destroy_a_index[i.x][i.y] then
359 if destroy_a_index[i.x][i.y][i.z] then
360 execute_collection = false
364 if execute_collection == true then
365 --print(minetest.get_node(i).name)
367 if minetest.get_node(i).name == "aether:portal" then
368 if vector.distance(i,origin) < 50 then
369 --add data to both maps
370 if not destroy_a_index[i.x] then destroy_a_index[i.x] = {} end
371 if not destroy_a_index[i.x][i.y] then destroy_a_index[i.x][i.y] = {} end
372 destroy_a_index[i.x][i.y][i.z] = {aether_portal=1} --get_group(i,"redstone_power")}
373 --the data to the 3d array must be written to memory before this is executed
374 --or a stack overflow occurs!!!
375 --pass down info for activators
376 destroy_aether_portal(i,origin,"z")
386 --modify the map with the collected data
387 local function destroy_portal_modify_map(destroy_n_copy)
388 local destroy_sorted_table = {}
389 for x,datax in pairs(destroy_n_copy) do
390 for y,datay in pairs(datax) do
391 for z,index in pairs(datay) do
392 table.insert(destroy_sorted_table, vector.new(x,y,z))
396 minetest.bulk_set_node(destroy_sorted_table, {name="air"})
399 minetest.register_globalstep(function(dtime)
400 --if indexes exist then calculate redstone
401 if a_index and next(a_index) and aether_portal_failure == false then
402 --create the old version to help with deactivation calculation
403 local n_copy = table.copy(a_index)
404 portal_modify_map(n_copy)
405 aether_portal_failure = false
407 if x_failed == true then
410 if aether_portal_failure == true then
411 aether_portal_failure = false
413 --clear the index to avoid cpu looping wasting processing power
417 --if indexes exist then calculate redstone
418 if destroy_a_index and next(destroy_a_index) and destroy_aether_portal_failure == false then
419 --create the old version to help with deactivation calculation
420 local destroy_n_copy = table.copy(destroy_a_index)
421 destroy_portal_modify_map(destroy_n_copy)
423 --clear the index to avoid cpu looping wasting processing power