forked from mtcontrib/nether-pack
		
	add comments and begin making obsidian portal always work
This commit is contained in:
		| @@ -56,16 +56,16 @@ end | ||||
|  | ||||
| -- teleports the player there if there's free space | ||||
| local function teleport_player(pos, player) | ||||
| 	local nd2 = is_soft(pos) | ||||
| 	pos.y = pos.y+1 | ||||
| 	local nd3 = is_soft(pos) | ||||
| 	if nd2 | ||||
| 	and nd3 then | ||||
| 		pos.y = pos.y-1.4 | ||||
| 		player:moveto(pos) | ||||
| 		return true | ||||
| 	if not is_soft(pos) then | ||||
| 		return false | ||||
| 	end | ||||
| 	return false | ||||
| 	if not is_soft({x=pos.x, y=pos.y+1, z=pos.z}) | ||||
| 	and not is_soft({x=pos.x, y=pos.y-1, z=pos.z}) then | ||||
| 		return false | ||||
| 	end | ||||
| 	pos.y = pos.y+0.05 | ||||
| 	player:moveto(pos) | ||||
| 	return true | ||||
| end | ||||
|  | ||||
| --[[ | ||||
|   | ||||
| @@ -20,12 +20,15 @@ table.icontains = table.icontains or function(t, v) | ||||
| end | ||||
|  | ||||
| local players_in_nether = {} | ||||
| local file = io.open(minetest.get_worldpath()..'/nether_players', "r") | ||||
| if file then | ||||
| 	local contents = file:read('*all') | ||||
| 	io.close(file) | ||||
| 	if contents then | ||||
| 		players_in_nether = string.split(contents, " ") | ||||
| -- only get info from file if nether prisons | ||||
| if nether_prisons then | ||||
| 	local file = io.open(minetest.get_worldpath()..'/nether_players', "r") | ||||
| 	if file then | ||||
| 		local contents = file:read('*all') | ||||
| 		io.close(file) | ||||
| 		if contents then | ||||
| 			players_in_nether = string.split(contents, " ") | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -57,7 +60,7 @@ local function player_to_nether(player, safe) | ||||
| 	if table.icontains(players_in_nether, pname) then | ||||
| 		return | ||||
| 	end | ||||
| 	table.insert(players_in_nether, pname) | ||||
| 	players_in_nether[#players_in_nether+1] = pname | ||||
| 	save_nether_players() | ||||
| 	if not safe then | ||||
| 		minetest.chat_send_player(pname, "For any reason you arrived here. Type /nether_help to find out things like craft recipes.") | ||||
| @@ -84,59 +87,61 @@ local function player_from_nether(player) | ||||
| end | ||||
|  | ||||
|  | ||||
| if nether_prisons then | ||||
| 	local function player_exists(name) | ||||
| 		for _,player in pairs(minetest.get_connected_players()) do | ||||
| 			if player:get_player_name() == name then | ||||
| 				return true | ||||
| 			end | ||||
| local function player_exists(name) | ||||
| 	for _,player in pairs(minetest.get_connected_players()) do | ||||
| 		if player:get_player_name() == name then | ||||
| 			return true | ||||
| 		end | ||||
| 		return false | ||||
| 	end | ||||
| 	return false | ||||
| end | ||||
|  | ||||
| 	-- Chatcommands (edited) written by sss | ||||
| 	minetest.register_chatcommand("to_hell", { | ||||
| 		params = "[<player_name>]", | ||||
| 		description = "Send someone to hell", | ||||
| 		func = function(name, pname) | ||||
| 			if not minetest.check_player_privs(name, {nether=true}) then | ||||
| 				return false, "You need the nether priv to execute this chatcommand." | ||||
| 			end | ||||
| 			if not player_exists(pname) then | ||||
| 				pname = name | ||||
| 			end | ||||
| 			local player = minetest.get_player_by_name(pname) | ||||
| 			if not player then | ||||
| 				return false, "Something went wrong." | ||||
| 			end | ||||
| 			minetest.chat_send_player(pname, "Go to hell !!!") | ||||
| 			player_to_nether(player) | ||||
| 			return true, pname.." is now in the nether." | ||||
| -- Chatcommands (edited) written by sss | ||||
| minetest.register_chatcommand("to_hell", { | ||||
| 	params = "[<player_name>]", | ||||
| 	description = "Send someone to hell", | ||||
| 	func = function(name, pname) | ||||
| 		if not minetest.check_player_privs(name, {nether=true}) then | ||||
| 			return false, "You need the nether priv to execute this chatcommand." | ||||
| 		end | ||||
| 	}) | ||||
|  | ||||
| 	minetest.register_chatcommand("from_hell", { | ||||
| 		params = "[<player_name>]", | ||||
| 		description = "Extract from hell", | ||||
| 		func = function(name, pname) | ||||
| 			if not minetest.check_player_privs(name, {nether=true}) then | ||||
| 				return false, "You need the nether priv to execute this chatcommand." | ||||
| 			end | ||||
| 			if not player_exists(pname) then | ||||
| 				pname = name | ||||
| 			end | ||||
| 			local player = minetest.get_player_by_name(pname) | ||||
| 			if not player then | ||||
| 				return false, "Something went wrong." | ||||
| 			end | ||||
| 			minetest.chat_send_player(pname, "You are free now") | ||||
| 			player_from_nether(player) | ||||
| 			local pos = player:getpos() | ||||
| 			player:moveto({x=pos.x, y=100, z=pos.z}) | ||||
| 			return true, pname.." is now out of the nether." | ||||
| 		if not player_exists(pname) then | ||||
| 			pname = name | ||||
| 		end | ||||
| 	}) | ||||
| 		local player = minetest.get_player_by_name(pname) | ||||
| 		if not player then | ||||
| 			return false, "Something went wrong." | ||||
| 		end | ||||
| 		minetest.chat_send_player(pname, "Go to hell !!!") | ||||
| 		player_to_nether(player) | ||||
| 		return true, pname.." is now in the nether." | ||||
| 	end | ||||
| }) | ||||
|  | ||||
| minetest.register_chatcommand("from_hell", { | ||||
| 	params = "[<player_name>]", | ||||
| 	description = "Extract from hell", | ||||
| 	func = function(name, pname) | ||||
| 		if not minetest.check_player_privs(name, {nether=true}) then | ||||
| 			return false, "You need the nether priv to execute this chatcommand." | ||||
| 		end | ||||
| 		if not player_exists(pname) then | ||||
| 			pname = name | ||||
| 		end | ||||
| 		local player = minetest.get_player_by_name(pname) | ||||
| 		if not player then | ||||
| 			return false, "Something went wrong." | ||||
| 		end | ||||
| 		minetest.chat_send_player(pname, "You are free now") | ||||
| 		player_from_nether(player) | ||||
| 		local pos = player:getpos() | ||||
| 		player:moveto({x=pos.x, y=100, z=pos.z}) | ||||
| 		return true, pname.." is now out of the nether." | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| if nether_prisons then | ||||
| 	-- randomly set player position when he/she dies in nether | ||||
| 	minetest.register_on_respawnplayer(function(player) | ||||
| 		local pname = player:get_player_name() | ||||
| 		if not table.icontains(players_in_nether, pname) then | ||||
| @@ -154,8 +159,9 @@ if nether_prisons then | ||||
| 		return true | ||||
| 	end) | ||||
|  | ||||
| 	-- function for teleporting players where they belong to | ||||
| 	local function update_players() | ||||
| 		for _,player in ipairs(minetest.get_connected_players()) do | ||||
| 		for _,player in pairs(minetest.get_connected_players()) do | ||||
| 			local pname = player:get_player_name() | ||||
| 			local ppos = player:getpos() | ||||
| 			if table.icontains(players_in_nether, pname) then | ||||
| @@ -176,6 +182,7 @@ if nether_prisons then | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- fix wrong player positions | ||||
| 	local timer = 0	--doesn't work if the server lags | ||||
| 	minetest.register_globalstep(function(dtime) | ||||
| 		timer = timer + dtime; | ||||
| @@ -186,6 +193,7 @@ if nether_prisons then | ||||
| 		end | ||||
| 	end) | ||||
|  | ||||
| 	-- set background when player joins | ||||
| 	minetest.register_on_joinplayer(function(player) | ||||
| 		minetest.after(0, function(player) | ||||
| 			if player:getpos().y < nether.start then | ||||
| @@ -193,266 +201,297 @@ if nether_prisons then | ||||
| 			end | ||||
| 		end, player) | ||||
| 	end) | ||||
|  | ||||
| 	local function remove_portal_essence(pos) | ||||
| 		for z = -1,1 do | ||||
| 			for y = -2,2 do | ||||
| 				for x = -1,1 do | ||||
| 					local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z} | ||||
| 					if minetest.get_node(p).name == "nether:portal" then | ||||
| 						minetest.remove_node(p) | ||||
| 					end | ||||
| else | ||||
| 	-- test if player is in nether when he/she joins | ||||
| 	minetest.register_on_joinplayer(function(player) | ||||
| 		minetest.after(0, function(player) | ||||
| 			if player:getpos().y < nether.start then | ||||
| 				if table.icontains(players_in_nether, pname) then | ||||
| 					return | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	minetest.register_abm({ | ||||
| 		nodenames = {"nether:portal"}, | ||||
| 		interval = 1, | ||||
| 		chance = 2, | ||||
| 		catch_up = false, | ||||
| 		action = function(pos, node) | ||||
| 			if not abm_allowed then | ||||
| 				players_in_nether[#players_in_nether+1] = pname | ||||
| 				return | ||||
| 			end | ||||
| 			minetest.add_particlespawner({ | ||||
| 				amount = 32, | ||||
| 				time = 4, | ||||
| 				minpos = {x=pos.x-0.25, y=pos.y-0.5, z=pos.z-0.25}, | ||||
| 				maxpos = {x=pos.x+0.25, y=pos.y+0.34, z=pos.z+0.25}, | ||||
| 				minvel = {x=0, y=1, z=0}, | ||||
| 				maxvel = {x=0, y=2, z=0}, | ||||
| 				minacc = {x=-0.5,y=-3,z=-0.3}, | ||||
| 				maxacc = {x=0.5,y=-0.4,z=0.3}, | ||||
| 				minexptime = 1, | ||||
| 				maxexptime = 1, | ||||
| 				minsize = 0.4, | ||||
| 				maxsize = 3, | ||||
| 				collisiondetection = true, | ||||
| 				texture = "nether_portal_particle.png^[transform"..math.random(0,7), | ||||
| 			}) | ||||
| 			for _,obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do | ||||
| 				if obj:is_player() then | ||||
| 					local meta = minetest.get_meta(pos) | ||||
| 					local target = minetest.string_to_pos(meta:get_string("target")) | ||||
| 					if target then | ||||
| 						minetest.after(3, function(obj, pos, target) | ||||
| 							local pname = obj:get_player_name() | ||||
| 							if table.icontains(players_in_nether, pname) then | ||||
| 								return | ||||
| 							end | ||||
| 							local objpos = obj:getpos() | ||||
| 							objpos.y = objpos.y+0.1 -- Fix some glitches at -8000 | ||||
| 							if minetest.get_node(vector.round(objpos)).name ~= "nether:portal" then | ||||
| 								return | ||||
| 							end | ||||
|  | ||||
| 							remove_portal_essence(pos) | ||||
|  | ||||
| 							minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1}) | ||||
| 							player_to_nether(obj) | ||||
| 							--obj:setpos(target) | ||||
|  | ||||
| 						end, obj, pos, target) | ||||
| 					end | ||||
| 			for i,name in pairs(players_in_nether) do | ||||
| 				if name == pname then | ||||
| 					players_in_nether[i] = nil | ||||
| 					return | ||||
| 				end | ||||
| 			end | ||||
| 		end, | ||||
| 	}) | ||||
|  | ||||
| 	local function move_check(p1, max, dir) | ||||
| 		local p = {x=p1.x, y=p1.y, z=p1.z} | ||||
| 		local d = math.abs(max-p1[dir]) / (max-p1[dir]) | ||||
| 		while p[dir] ~= max do | ||||
| 			p[dir] = p[dir] + d | ||||
| 			if minetest.get_node(p).name ~= "default:obsidian" then | ||||
| 				return false | ||||
| 			end | ||||
| 		end | ||||
| 		return true | ||||
| 	end | ||||
|  | ||||
| 	local function check_portal(p1, p2) | ||||
| 		if p1.x ~= p2.x then | ||||
| 			if not move_check(p1, p2.x, "x") then | ||||
| 				return false | ||||
| 			end | ||||
| 			if not move_check(p2, p1.x, "x") then | ||||
| 				return false | ||||
| 			end | ||||
| 		elseif p1.z ~= p2.z then | ||||
| 			if not move_check(p1, p2.z, "z") then | ||||
| 				return false | ||||
| 			end | ||||
| 			if not move_check(p2, p1.z, "z") then | ||||
| 				return false | ||||
| 			end | ||||
| 		else | ||||
| 			return false | ||||
| 		end | ||||
|  | ||||
| 		if not move_check(p1, p2.y, "y") then | ||||
| 			return false | ||||
| 		end | ||||
| 		if not move_check(p2, p1.y, "y") then | ||||
| 			return false | ||||
| 		end | ||||
|  | ||||
| 		return true | ||||
| 	end | ||||
|  | ||||
| 	local function is_portal(pos) | ||||
| 		for d=-3,3 do | ||||
| 			for y=-4,4 do | ||||
| 				local px = {x=pos.x+d, y=pos.y+y, z=pos.z} | ||||
| 				local pz = {x=pos.x, y=pos.y+y, z=pos.z+d} | ||||
| 				if check_portal(px, {x=px.x+3, y=px.y+4, z=px.z}) then | ||||
| 					return px, {x=px.x+3, y=px.y+4, z=px.z} | ||||
| 				end | ||||
| 				if check_portal(pz, {x=pz.x, y=pz.y+4, z=pz.z+3}) then | ||||
| 					return pz, {x=pz.x, y=pz.y+4, z=pz.z+3} | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local function make_portal(pos) | ||||
| 		local p1, p2 = is_portal(pos) | ||||
| 		if not p1 | ||||
| 		or not p2 then | ||||
| 			print("[nether] something failed.") | ||||
| 			return false | ||||
| 		end | ||||
|  | ||||
| 		if p1.y < nether.start then | ||||
| 			print("[nether] aborted, obsidian portals can't be used to get out") | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		for d=1,2 do | ||||
| 		for y=p1.y+1,p2.y-1 do | ||||
| 			local p | ||||
| 			if p1.z == p2.z then | ||||
| 				p = {x=p1.x+d, y=y, z=p1.z} | ||||
| 			else | ||||
| 				p = {x=p1.x, y=y, z=p1.z+d} | ||||
| 			end | ||||
| 			if minetest.get_node(p).name ~= "air" then | ||||
| 				return false | ||||
| 			end | ||||
| 		end | ||||
| 		end | ||||
|  | ||||
| 		local param2 | ||||
| 		if p1.z == p2.z then | ||||
| 			param2 = 0 | ||||
| 		else | ||||
| 			param2 = 1 | ||||
| 		end | ||||
|  | ||||
| 		local target = {x=p1.x, y=p1.y, z=p1.z} | ||||
| 		target.x = target.x + 1 | ||||
| 		target.y = portal_target + math.random(4) | ||||
|  | ||||
| 		for d=0,3 do | ||||
| 		for y=p1.y,p2.y do | ||||
| 			local p = {} | ||||
| 			if param2 == 0 then | ||||
| 				p = {x=p1.x+d, y=y, z=p1.z} | ||||
| 			else | ||||
| 				p = {x=p1.x, y=y, z=p1.z+d} | ||||
| 			end | ||||
| 			if minetest.get_node(p).name == "air" then | ||||
| 				minetest.set_node(p, {name="nether:portal", param2=param2}) | ||||
| 			end | ||||
| 			local meta = minetest.get_meta(p) | ||||
| 			meta:set_string("p1", minetest.pos_to_string(p1)) | ||||
| 			meta:set_string("p2", minetest.pos_to_string(p2)) | ||||
| 			meta:set_string("target", minetest.pos_to_string(target)) | ||||
| 		end | ||||
| 		end | ||||
| 		print("[nether] construction accepted.") | ||||
| 		return true | ||||
| 	end | ||||
|  | ||||
| 	minetest.override_item("default:obsidian", { | ||||
| 		on_destruct = function(pos) | ||||
| 			local meta = minetest.get_meta(pos) | ||||
| 			local p1 = minetest.string_to_pos(meta:get_string("p1")) | ||||
| 			local p2 = minetest.string_to_pos(meta:get_string("p2")) | ||||
| 			local target = minetest.string_to_pos(meta:get_string("target")) | ||||
| 			if not p1 or not p2 then | ||||
| 				return | ||||
| 			end | ||||
| 			for x=p1.x,p2.x do | ||||
| 			for y=p1.y,p2.y do | ||||
| 			for z=p1.z,p2.z do | ||||
| 				local nn = minetest.get_node({x=x,y=y,z=z}).name | ||||
| 				if nn == "default:obsidian" or nn == "nether:portal" then | ||||
| 					if nn == "nether:portal" then | ||||
| 						minetest.remove_node({x=x,y=y,z=z}) | ||||
| 					end | ||||
| 					local m = minetest.get_meta({x=x,y=y,z=z}) | ||||
| 					m:set_string("p1", "") | ||||
| 					m:set_string("p2", "") | ||||
| 					m:set_string("target", "") | ||||
| 				end | ||||
| 			end | ||||
| 			end | ||||
| 			end | ||||
| 			meta = minetest.get_meta(target) | ||||
| 			if not meta then | ||||
| 				return | ||||
| 			end | ||||
| 			p1 = minetest.string_to_pos(meta:get_string("p1")) | ||||
| 			p2 = minetest.string_to_pos(meta:get_string("p2")) | ||||
| 			if not p1 or not p2 then | ||||
| 				return | ||||
| 			end | ||||
| 			for x=p1.x,p2.x do | ||||
| 			for y=p1.y,p2.y do | ||||
| 			for z=p1.z,p2.z do | ||||
| 				local nn = minetest.get_node({x=x,y=y,z=z}).name | ||||
| 				if nn == "default:obsidian" or nn == "nether:portal" then | ||||
| 					if nn == "nether:portal" then | ||||
| 						minetest.remove_node({x=x,y=y,z=z}) | ||||
| 					end | ||||
| 					local m = minetest.get_meta({x=x,y=y,z=z}) | ||||
| 					m:set_string("p1", "") | ||||
| 					m:set_string("p2", "") | ||||
| 					m:set_string("target", "") | ||||
| 				end | ||||
| 			end | ||||
| 			end | ||||
| 			end | ||||
| 		end | ||||
| 	}) | ||||
|  | ||||
| 	minetest.after(0.1, function() | ||||
| 		minetest.override_item("default:mese_crystal_fragment", { | ||||
| 			on_place = function(stack, player, pt) | ||||
| 				if pt.under | ||||
| 				and minetest.get_node(pt.under).name == "default:obsidian" then | ||||
| 					print("[nether] tries to enable a portal") | ||||
| 					local done = make_portal(pt.under) | ||||
| 					if done then | ||||
| 						minetest.chat_send_player( | ||||
| 							player:get_player_name(), | ||||
| 							"Warning: If you are in the nether you may not be able to find the way out!" | ||||
| 						) | ||||
| 						if not minetest.setting_getbool("creative_mode") then | ||||
| 							stack:take_item() | ||||
| 						end | ||||
| 					end | ||||
| 				end | ||||
| 				return stack | ||||
| 			end | ||||
| 		}) | ||||
| 		end, player) | ||||
| 	end) | ||||
| end | ||||
|  | ||||
| -- removes the violet stuff from the obsidian portal | ||||
| local function remove_portal_essence(pos) | ||||
| 	for z = -1,1 do | ||||
| 		for y = -2,2 do | ||||
| 			for x = -1,1 do | ||||
| 				local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z} | ||||
| 				if minetest.get_node(p).name == "nether:portal" then | ||||
| 					minetest.remove_node(p) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- change parts of the particledefinition instead of recreating it every time | ||||
| local particledef = { | ||||
| 	amount = 32, | ||||
| 	time = 4, | ||||
| 	minvel = {x=0, y=1, z=0}, | ||||
| 	maxvel = {x=0, y=2, z=0}, | ||||
| 	minacc = {x=-0.5,y=-3,z=-0.3}, | ||||
| 	maxacc = {x=0.5,y=-0.4,z=0.3}, | ||||
| 	minexptime = 1, | ||||
| 	maxexptime = 1, | ||||
| 	minsize = 0.4, | ||||
| 	maxsize = 3, | ||||
| 	collisiondetection = true, | ||||
| } | ||||
|  | ||||
| -- teleports player to neter (obsidian portal) | ||||
| local function obsi_teleport_player(obj, pos, target) | ||||
| 	local pname = obj:get_player_name() | ||||
| 	if table.icontains(players_in_nether, pname) then | ||||
| 		return | ||||
| 	end | ||||
| 	local objpos = obj:getpos() | ||||
| 	objpos.y = objpos.y+0.1 -- Fix some glitches at -8000 | ||||
| 	if minetest.get_node(vector.round(objpos)).name ~= "nether:portal" then | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	remove_portal_essence(pos) | ||||
|  | ||||
| 	minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1}) | ||||
| 	player_to_nether(obj) | ||||
| 	--obj:setpos(target) | ||||
| end | ||||
|  | ||||
| -- abm for particles of the obsidian portal essence and for teleporting | ||||
| minetest.register_abm({ | ||||
| 	nodenames = {"nether:portal"}, | ||||
| 	interval = 1, | ||||
| 	chance = 2, | ||||
| 	catch_up = false, | ||||
| 	action = function(pos, node) | ||||
| 		if not abm_allowed then | ||||
| 			return | ||||
| 		end | ||||
| 		particledef.minpos = {x=pos.x-0.25, y=pos.y-0.5, z=pos.z-0.25} | ||||
| 		particledef.maxpos = {x=pos.x+0.25, y=pos.y+0.34, z=pos.z+0.25} | ||||
| 		particledef.texture = "nether_portal_particle.png^[transform"..math.random(0,7) | ||||
| 		minetest.add_particlespawner(particledef) | ||||
| 		for _,obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do | ||||
| 			if obj:is_player() then | ||||
| 				local meta = minetest.get_meta(pos) | ||||
| 				local target = minetest.string_to_pos(meta:get_string("target")) | ||||
| 				if target then | ||||
| 					minetest.after(3, obsi_teleport_player, obj, pos, target) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end, | ||||
| }) | ||||
|  | ||||
| local function move_check(p1, max, dir) | ||||
| 	local p = {x=p1.x, y=p1.y, z=p1.z} | ||||
| 	local d = math.abs(max-p1[dir]) / (max-p1[dir]) | ||||
| 	while p[dir] ~= max do | ||||
| 		p[dir] = p[dir] + d | ||||
| 		if minetest.get_node(p).name ~= "default:obsidian" then | ||||
| 			return false | ||||
| 		end | ||||
| 	end | ||||
| 	return true | ||||
| end | ||||
|  | ||||
| local function check_portal(p1, p2) | ||||
| 	if p1.x ~= p2.x then | ||||
| 		if not move_check(p1, p2.x, "x") then | ||||
| 			return false | ||||
| 		end | ||||
| 		if not move_check(p2, p1.x, "x") then | ||||
| 			return false | ||||
| 		end | ||||
| 	elseif p1.z ~= p2.z then | ||||
| 		if not move_check(p1, p2.z, "z") then | ||||
| 			return false | ||||
| 		end | ||||
| 		if not move_check(p2, p1.z, "z") then | ||||
| 			return false | ||||
| 		end | ||||
| 	else | ||||
| 		return false | ||||
| 	end | ||||
|  | ||||
| 	if not move_check(p1, p2.y, "y") then | ||||
| 		return false | ||||
| 	end | ||||
| 	if not move_check(p2, p1.y, "y") then | ||||
| 		return false | ||||
| 	end | ||||
|  | ||||
| 	return true | ||||
| end | ||||
|  | ||||
| -- tests if it's an obsidian portal | ||||
| local function is_portal(pos) | ||||
| 	for d=-3,3 do | ||||
| 		for y=-4,4 do | ||||
| 			local px = {x=pos.x+d, y=pos.y+y, z=pos.z} | ||||
| 			local pz = {x=pos.x, y=pos.y+y, z=pos.z+d} | ||||
| 			if check_portal(px, {x=px.x+3, y=px.y+4, z=px.z}) then | ||||
| 				return px, {x=px.x+3, y=px.y+4, z=px.z} | ||||
| 			end | ||||
| 			if check_portal(pz, {x=pz.x, y=pz.y+4, z=pz.z+3}) then | ||||
| 				return pz, {x=pz.x, y=pz.y+4, z=pz.z+3} | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- adds the violed portal essence | ||||
| local function make_portal(pos) | ||||
| 	local p1, p2 = is_portal(pos) | ||||
| 	if not p1 | ||||
| 	or not p2 then | ||||
| 		print("[nether] something failed.") | ||||
| 		return false | ||||
| 	end | ||||
|  | ||||
| 	if p1.y < nether.start then | ||||
| 		print("[nether] aborted, obsidian portals can't be used to get out") | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	for d=1,2 do | ||||
| 	for y=p1.y+1,p2.y-1 do | ||||
| 		local p | ||||
| 		if p1.z == p2.z then | ||||
| 			p = {x=p1.x+d, y=y, z=p1.z} | ||||
| 		else | ||||
| 			p = {x=p1.x, y=y, z=p1.z+d} | ||||
| 		end | ||||
| 		if minetest.get_node(p).name ~= "air" then | ||||
| 			return false | ||||
| 		end | ||||
| 	end | ||||
| 	end | ||||
|  | ||||
| 	local param2 | ||||
| 	if p1.z == p2.z then | ||||
| 		param2 = 0 | ||||
| 	else | ||||
| 		param2 = 1 | ||||
| 	end | ||||
|  | ||||
| 	local target = {x=p1.x, y=p1.y, z=p1.z} | ||||
| 	target.x = target.x + 1 | ||||
| 	target.y = portal_target + math.random(4) | ||||
|  | ||||
| 	for d=0,3 do | ||||
| 	for y=p1.y,p2.y do | ||||
| 		local p = {} | ||||
| 		if param2 == 0 then | ||||
| 			p = {x=p1.x+d, y=y, z=p1.z} | ||||
| 		else | ||||
| 			p = {x=p1.x, y=y, z=p1.z+d} | ||||
| 		end | ||||
| 		if minetest.get_node(p).name == "air" then | ||||
| 			minetest.set_node(p, {name="nether:portal", param2=param2}) | ||||
| 		end | ||||
| 		local meta = minetest.get_meta(p) | ||||
| 		meta:set_string("p1", minetest.pos_to_string(p1)) | ||||
| 		meta:set_string("p2", minetest.pos_to_string(p2)) | ||||
| 		meta:set_string("target", minetest.pos_to_string(target)) | ||||
| 	end | ||||
| 	end | ||||
| 	print("[nether] construction accepted.") | ||||
| 	return true | ||||
| end | ||||
|  | ||||
| -- destroy the portal when destroying obsidian | ||||
| minetest.override_item("default:obsidian", { | ||||
| 	on_destruct = function(pos) | ||||
| 		local meta = minetest.get_meta(pos) | ||||
| 		local p1 = minetest.string_to_pos(meta:get_string("p1")) | ||||
| 		local p2 = minetest.string_to_pos(meta:get_string("p2")) | ||||
| 		local target = minetest.string_to_pos(meta:get_string("target")) | ||||
| 		if not p1 or not p2 then | ||||
| 			return | ||||
| 		end | ||||
| 		for x=p1.x,p2.x do | ||||
| 		for y=p1.y,p2.y do | ||||
| 		for z=p1.z,p2.z do | ||||
| 			local nn = minetest.get_node({x=x,y=y,z=z}).name | ||||
| 			if nn == "default:obsidian" or nn == "nether:portal" then | ||||
| 				if nn == "nether:portal" then | ||||
| 					minetest.remove_node({x=x,y=y,z=z}) | ||||
| 				end | ||||
| 				local m = minetest.get_meta({x=x,y=y,z=z}) | ||||
| 				m:set_string("p1", "") | ||||
| 				m:set_string("p2", "") | ||||
| 				m:set_string("target", "") | ||||
| 			end | ||||
| 		end | ||||
| 		end | ||||
| 		end | ||||
| 		meta = minetest.get_meta(target) | ||||
| 		if not meta then | ||||
| 			return | ||||
| 		end | ||||
| 		p1 = minetest.string_to_pos(meta:get_string("p1")) | ||||
| 		p2 = minetest.string_to_pos(meta:get_string("p2")) | ||||
| 		if not p1 or not p2 then | ||||
| 			return | ||||
| 		end | ||||
| 		for x=p1.x,p2.x do | ||||
| 		for y=p1.y,p2.y do | ||||
| 		for z=p1.z,p2.z do | ||||
| 			local nn = minetest.get_node({x=x,y=y,z=z}).name | ||||
| 			if nn == "default:obsidian" or nn == "nether:portal" then | ||||
| 				if nn == "nether:portal" then | ||||
| 					minetest.remove_node({x=x,y=y,z=z}) | ||||
| 				end | ||||
| 				local m = minetest.get_meta({x=x,y=y,z=z}) | ||||
| 				m:set_string("p1", "") | ||||
| 				m:set_string("p2", "") | ||||
| 				m:set_string("target", "") | ||||
| 			end | ||||
| 		end | ||||
| 		end | ||||
| 		end | ||||
| 	end | ||||
| }) | ||||
|  | ||||
| -- override mese crystal fragment for making an obsidian portal | ||||
| minetest.after(0.1, function() | ||||
| 	minetest.override_item("default:mese_crystal_fragment", { | ||||
| 		on_place = function(stack, player, pt) | ||||
| 			if pt.under | ||||
| 			and minetest.get_node(pt.under).name == "default:obsidian" then | ||||
| 				--print("[nether] tries to enable a portal") | ||||
| 				local done = make_portal(pt.under) | ||||
| 				if done then | ||||
| 					minetest.chat_send_player( | ||||
| 						player:get_player_name(), | ||||
| 						"Warning: If you are in the nether you may not be able to find the way out!" | ||||
| 					) | ||||
| 					if not minetest.setting_getbool("creative_mode") then | ||||
| 						stack:take_item() | ||||
| 					end | ||||
| 				end | ||||
| 			end | ||||
| 			return stack | ||||
| 		end | ||||
| 	}) | ||||
| end) | ||||
|  | ||||
|  | ||||
| -- a not filled square | ||||
| vector.square = vector.square or | ||||
| function(r) | ||||
| 	local tab, n = {}, 1 | ||||
| @@ -467,6 +506,7 @@ function(r) | ||||
| 	return tab | ||||
| end | ||||
|  | ||||
| -- detects if it's a portal | ||||
| local function netherport(pos) | ||||
| 	local x, y, z = pos.x, pos.y, pos.z | ||||
| 	for _,i in ipairs({-1, 3}) do | ||||
|   | ||||
		Reference in New Issue
	
	Block a user