forked from mtcontrib/nether-pack
		
	change nether pearl and portal.lua
This commit is contained in:
		| @@ -19,3 +19,4 @@ If you got ideas or found bugs, please tell them to me. | ||||
|  | ||||
| TODO:   | ||||
| — find a way to get the perlin noise inside [-1; 1] or use another noise   | ||||
| — add something containing items to that buildings | ||||
|   | ||||
							
								
								
									
										236
									
								
								nether/pearl.lua
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								nether/pearl.lua
									
									
									
									
									
								
							| @@ -7,36 +7,60 @@ local function table_contains(t, v) | ||||
| 	return false | ||||
| end | ||||
|  | ||||
| local teleportball_player | ||||
| local creative = minetest.setting_getbool("creative_mode") | ||||
| local function throw_pearl(item, player) | ||||
| 	local playerpos = player:getpos() | ||||
| 	local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.625,z=playerpos.z}, "nether:pearl_entity") | ||||
| 	playerpos.y = playerpos.y+1.625 | ||||
| 	local obj = minetest.add_entity(playerpos, "nether:pearl_entity") | ||||
| 	local dir = player:get_look_dir() | ||||
| 	obj:setvelocity({x=dir.x*30, y=dir.y*30, z=dir.z*30}) | ||||
| 	obj:setvelocity(vector.multiply(dir, 30)) | ||||
| 	obj:setacceleration({x=dir.x*-3, y=-dir.y^8*80-10, z=dir.z*-3}) | ||||
| 	if not minetest.setting_getbool("creative_mode") then | ||||
| 	obj:get_luaentity().player = player:get_player_name() | ||||
| 	if not creative then | ||||
| 		item:take_item() | ||||
| 		return item | ||||
| 	end | ||||
| 	teleportball_player = player | ||||
| 	return item | ||||
| end | ||||
|  | ||||
| local ENTITY = { | ||||
| 	timer=0, | ||||
| 	collisionbox = {0,0,0,0,0,0}, --not pointable | ||||
| 	physical = false, -- Collides with things | ||||
| 	textures = {"nether_pearl.png"}, | ||||
| 	lastpos={}, | ||||
| 	player = "", | ||||
| } | ||||
| local function get_node(pos) | ||||
| 	local name = minetest.get_node(pos).name | ||||
| 	if name == "ignore" then | ||||
| 		minetest.get_voxel_manip():read_from_map(pos, pos) | ||||
| 		name = minetest.get_node_or_nil(pos) | ||||
| 		if not name then | ||||
| 			return | ||||
| 		end | ||||
| 		name = name.name | ||||
| 	end | ||||
| 	return name | ||||
| end | ||||
|  | ||||
| local allowed_nodes = {"air", "default:water_source"} | ||||
| local softs = {} | ||||
| local function is_soft(pos) | ||||
| 	local name = get_node(pos) | ||||
| 	if not name then | ||||
| 		return false | ||||
| 	end | ||||
| 	local is_soft = softs[name] | ||||
| 	if is_soft ~= nil then | ||||
| 		return is_soft | ||||
| 	end | ||||
| 	if not minetest.registered_nodes[name] then | ||||
| 		softs[name] = false | ||||
| 		return false | ||||
| 	end | ||||
| 	is_soft = minetest.registered_nodes[name].walkable == false | ||||
| 	softs[name] = is_soft | ||||
| 	return is_soft | ||||
| end | ||||
|  | ||||
| -- teleports the player there if there's free space | ||||
| local function teleport_player(pos, player) | ||||
| 	local nd2 = minetest.get_node(pos).name | ||||
| 	local nd2 = is_soft(pos) | ||||
| 	pos.y = pos.y+1 | ||||
| 	local nd3 = minetest.get_node(pos).name | ||||
| 	if table_contains(allowed_nodes, nd2) | ||||
| 	and table_contains(allowed_nodes, nd3) then | ||||
| 	local nd3 = is_soft(pos) | ||||
| 	if nd2 | ||||
| 	and nd3 then | ||||
| 		pos.y = pos.y-1.4 | ||||
| 		player:moveto(pos) | ||||
| 		pos.y = pos.y-0.6 | ||||
| @@ -45,70 +69,130 @@ local function teleport_player(pos, player) | ||||
| 	return false | ||||
| end | ||||
|  | ||||
| ENTITY.on_step = function(self, dtime) | ||||
| 	self.timer=self.timer+dtime | ||||
| --[[ | ||||
| local dg_ps = {} | ||||
| local function forceload(pos) | ||||
| 	dg_ps[#dg_ps+1] = pos | ||||
| 	minetest.forceload_block(pos) | ||||
| 	minetest.after(5, function(pos) | ||||
| 		minetest.forceload_free_block(pos) | ||||
| 		for i,p in pairs(dg_ps) do | ||||
| 			if vector.equals(p, pos) then | ||||
| 				dg_ps[i] = nil | ||||
| 				return | ||||
| 			end | ||||
| 		end | ||||
| 	end, pos) | ||||
| end | ||||
| minetest.register_on_shutdown(function() | ||||
| 	for _,p in pairs(dg_ps) do | ||||
| 		minetest.forceload_free_block(p) | ||||
| 	end | ||||
| end)--]] | ||||
|  | ||||
| minetest.register_entity("nether:pearl_entity", { | ||||
| 	timer = 0, | ||||
| 	collisionbox = {0,0,0,0,0,0}, --not pointable | ||||
| 	physical = false, -- Collides with things | ||||
| 	textures = {"nether_pearl.png"}, | ||||
| 	on_activate = function(self, staticdata) | ||||
| 		if not staticdata | ||||
| 		or staticdata == "" then | ||||
| 			return | ||||
| 		end | ||||
| 		local tmp = minetest.deserialize(staticdata) | ||||
| 		if not tmp then | ||||
| 			minetest.log("error", "[nether] pearl: invalid staticdata ") | ||||
| 			return | ||||
| 		end | ||||
| 		self.player = tmp.player | ||||
| 	end, | ||||
| 	get_staticdata = function(self) | ||||
| 		--forceload(vector.round(self.object:getpos())) | ||||
| 		return minetest.serialize({ | ||||
| 			player = self.player, | ||||
| 		}) | ||||
| 	end, | ||||
| 	on_step = function(self, dtime) | ||||
| 		self.timer = self.timer+dtime | ||||
|  | ||||
| 	--[[ | ||||
| 		local delay = self.delay | ||||
| 		if delay < 0.1 then | ||||
| 			self.delay = delay+dtime | ||||
| 			return | ||||
| 		end | ||||
| 		self.delay = 0--]] | ||||
|  | ||||
| 		if self.timer > 20 then | ||||
| 			self.object:remove() | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		local pos = self.object:getpos() | ||||
| 		local rpos = vector.round(pos) | ||||
| 		local lastpos = self.lastpos | ||||
| 		if not lastpos then | ||||
| 			self.lastpos = vector.new(rpos) | ||||
| 			return | ||||
| 		end | ||||
| 		if lastpos.x | ||||
| 		and vector.equals(vector.round(lastpos), rpos) then | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		local player = self.player | ||||
| 		if not player then | ||||
| 			minetest.log("error", "[nether] pearl: missing playername") | ||||
| 			self.object:remove() | ||||
| 			return | ||||
| 		end | ||||
| 		player = minetest.get_player_by_name(player) | ||||
| 		if not player then | ||||
| 			minetest.log("error", "[nether] pearl: missing player") | ||||
| 			self.object:remove() | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		if not get_node(rpos) then | ||||
| 			minetest.log("error", "[nether] pearl: missing node") | ||||
| 			self.object:remove() | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		self.lastpos = vector.new(pos) | ||||
|  | ||||
| --[[	local delay = self.delay | ||||
| 	if delay < 0.1 then | ||||
| 		self.delay = delay+dtime | ||||
| 		return | ||||
| 	end | ||||
| 	self.delay = 0]] | ||||
| 	local pos = self.object:getpos() | ||||
| 	local lastpos = self.lastpos | ||||
| 	if lastpos.x | ||||
| 	and vector.equals(vector.round(lastpos), vector.round(pos)) then | ||||
| 		return | ||||
| 	end | ||||
| 	local player = self.player | ||||
| 	if not player | ||||
| 	or player == "" then | ||||
| 		self.player = teleportball_player | ||||
| 		player = teleportball_player | ||||
| 	end | ||||
| 	if not player then | ||||
| 		self.object:remove() | ||||
| 		return | ||||
| 	end | ||||
| 	if lastpos.x then --If there is no lastpos for some reason. | ||||
| 		local free, p = minetest.line_of_sight(lastpos, pos) | ||||
| 		if not free then | ||||
| 			local nd1 = minetest.get_node(p).name | ||||
| 			if not table_contains(allowed_nodes, nd1) | ||||
| 			and nd1 ~= "ignore" then | ||||
| 				self.object:remove() | ||||
| 				minetest.after(0, function(p) --minetest.after us used that the sound is played after the teleportation | ||||
| 					minetest.sound_play("nether_pearl", {pos=p, max_hear_distance=10}) | ||||
| 				end, p) | ||||
| 				p.y = p.y+1 | ||||
| 				if teleport_player(p, player) then | ||||
| 		if free then | ||||
| 			return | ||||
| 		end | ||||
| 		if is_soft(p) then | ||||
| 			return | ||||
| 		end | ||||
| 		self.object:remove() | ||||
| 		minetest.after(0, function(p) --minetest.after is used that the sound is played after the teleportation | ||||
| 			minetest.sound_play("nether_pearl", {pos=p, max_hear_distance=10}) | ||||
| 		end, p) | ||||
| 		p.y = p.y+1 | ||||
| 		if teleport_player(p, player) then | ||||
| 			return | ||||
| 		end | ||||
| 		p.y = p.y-2 | ||||
| 		for i = -1,1,2 do | ||||
| 			for _,j in pairs({{i, 0}, {0, i}}) do | ||||
| 				if teleport_player({x=p.x+j[1], y=p.y, z=p.z+j[2]}, player) then | ||||
| 					return | ||||
| 				end | ||||
| 				p.y = p.y-2 | ||||
| 				for i = -1,1,2 do | ||||
| 					for _,j in pairs({{i, 0}, {0, i}}) do | ||||
| 						if teleport_player({x=p.x+j[1], y=p.y, z=p.z+j[2]}, player) then | ||||
| 							return | ||||
| 						end | ||||
| 					end | ||||
| 				end | ||||
| 				for i = -1,1,2 do | ||||
| 					for j = -1,1,2 do | ||||
| 						if teleport_player({x=p.x+j, y=p.y, z=p.z+i}, player) then | ||||
| 							return | ||||
| 						end | ||||
| 					end | ||||
| 			end | ||||
| 		end | ||||
| 		for i = -1,1,2 do | ||||
| 			for j = -1,1,2 do | ||||
| 				if teleport_player({x=p.x+j, y=p.y, z=p.z+i}, player) then | ||||
| 					return | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	if self.timer > 20 then | ||||
| 		self.object:remove() | ||||
| 		return | ||||
| 	end | ||||
| 	self.lastpos = vector.new(pos) | ||||
| end | ||||
|  | ||||
| minetest.register_entity("nether:pearl_entity", ENTITY) | ||||
| }) | ||||
|  | ||||
| minetest.override_item("nether:pearl", {on_use = throw_pearl}) | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| -- kills the player if he uses PilzAdam portal | ||||
| local obsidian_portal_kills = true | ||||
| local portal_target = nether.buildings+1 | ||||
| local damage_enabled = minetest.setting_getbool("enable_damage") | ||||
| local nether_prisons = minetest.setting_getbool("enable_damage") | ||||
|  | ||||
| local abm_allowed | ||||
| minetest.after(5, function() | ||||
| @@ -40,7 +40,7 @@ local function save_nether_players() | ||||
| end | ||||
|  | ||||
| local update_background | ||||
| if damage_enabled then | ||||
| if nether_prisons then | ||||
| 	function update_background(player, down) | ||||
| 		if down then | ||||
| 			player:set_sky({r=15, g=0, b=0}, "plain") | ||||
| @@ -84,372 +84,372 @@ local function player_from_nether(player) | ||||
| end | ||||
|  | ||||
|  | ||||
| if damage_enabled then | ||||
| local function player_exists(name) | ||||
| 	for _,player in pairs(minetest.get_connected_players()) do | ||||
| 		if player:get_player_name() == name then | ||||
| 			return true | ||||
| 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 | ||||
| 		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." | ||||
| 	-- 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." | ||||
| 		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." | ||||
| 	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." | ||||
| 	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 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 | ||||
| }) | ||||
| 	}) | ||||
|  | ||||
| minetest.register_on_respawnplayer(function(player) | ||||
| 	local pname = player:get_player_name() | ||||
| 	if not table.icontains(players_in_nether, pname) then | ||||
| 		return | ||||
| 	end | ||||
| 	local target = vector.add(player:getpos(), {x=math.random(-100,100), y=0, z=math.random(-100,100)}) | ||||
| 	target.y = portal_target + math.random(4) | ||||
| 	player:moveto(target) | ||||
| 	minetest.after(0, function(pname, target) | ||||
| 		local player = minetest.get_player_by_name(pname) | ||||
| 		if player then | ||||
| 			player:moveto(target) | ||||
| 		end | ||||
| 	end, pname, target) | ||||
| 	return true | ||||
| end) | ||||
|  | ||||
| local function update_players() | ||||
| 	for _,player in ipairs(minetest.get_connected_players()) do | ||||
| 	minetest.register_on_respawnplayer(function(player) | ||||
| 		local pname = player:get_player_name() | ||||
| 		local ppos = player:getpos() | ||||
| 		if table.icontains(players_in_nether, pname) then | ||||
| 			if ppos.y > nether.start then | ||||
| 				player:moveto({x=ppos.x, y=portal_target, z=ppos.z}) | ||||
| 				update_background(player, true) | ||||
| 				--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport out of the nether.".. | ||||
| 		if not table.icontains(players_in_nether, pname) then | ||||
| 			return | ||||
| 		end | ||||
| 		local target = vector.add(player:getpos(), {x=math.random(-100,100), y=0, z=math.random(-100,100)}) | ||||
| 		target.y = portal_target + math.random(4) | ||||
| 		player:moveto(target) | ||||
| 		minetest.after(0, function(pname, target) | ||||
| 			local player = minetest.get_player_by_name(pname) | ||||
| 			if player then | ||||
| 				player:moveto(target) | ||||
| 			end | ||||
| 		end, pname, target) | ||||
| 		return true | ||||
| 	end) | ||||
|  | ||||
| 	local function update_players() | ||||
| 		for _,player in ipairs(minetest.get_connected_players()) do | ||||
| 			local pname = player:get_player_name() | ||||
| 			local ppos = player:getpos() | ||||
| 			if table.icontains(players_in_nether, pname) then | ||||
| 				if ppos.y > nether.start then | ||||
| 					player:moveto({x=ppos.x, y=portal_target, z=ppos.z}) | ||||
| 					update_background(player, true) | ||||
| 					--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport out of the nether.".. | ||||
| 						"\n2. Maybe the server lagged.".. | ||||
| 						"\n3. please rejoin")]] | ||||
| 				end | ||||
| 			elseif ppos.y < nether.start then | ||||
| 				update_background(player) | ||||
| 				player:moveto({x=ppos.x, y=20, z=ppos.z}) | ||||
| 				--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport to the nether.".. | ||||
| 					"\n2. Maybe the server lagged.".. | ||||
| 					"\n3. please rejoin")]] | ||||
| 			end | ||||
| 		elseif ppos.y < nether.start then | ||||
| 			update_background(player) | ||||
| 			player:moveto({x=ppos.x, y=20, z=ppos.z}) | ||||
| 			--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport to the nether.".. | ||||
| 				"\n2. Maybe the server lagged.".. | ||||
| 				"\n3. please rejoin")]] | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local timer = 0	--doesn't work if the server lags | ||||
| minetest.register_globalstep(function(dtime) | ||||
| 	timer = timer + dtime; | ||||
| 	if timer >= 2 then | ||||
| 		--minetest.after(1, update_players) | ||||
| 		update_players() | ||||
| 		timer = 0 | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| minetest.register_on_joinplayer(function(player) | ||||
| 	minetest.after(0, function(player) | ||||
| 		if player:getpos().y < nether.start then | ||||
| 			update_background(player, true) | ||||
| 	local timer = 0	--doesn't work if the server lags | ||||
| 	minetest.register_globalstep(function(dtime) | ||||
| 		timer = timer + dtime; | ||||
| 		if timer >= 2 then | ||||
| 			--minetest.after(1, update_players) | ||||
| 			update_players() | ||||
| 			timer = 0 | ||||
| 		end | ||||
| 	end, player) | ||||
| end) | ||||
| 	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 | ||||
| 	minetest.register_on_joinplayer(function(player) | ||||
| 		minetest.after(0, function(player) | ||||
| 			if player:getpos().y < nether.start then | ||||
| 				update_background(player, true) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
| 		end, player) | ||||
| 	end) | ||||
|  | ||||
| minetest.register_abm({ | ||||
| 	nodenames = {"nether:portal"}, | ||||
| 	interval = 1, | ||||
| 	chance = 2, | ||||
| 	catch_up = false, | ||||
| 	action = function(pos, node) | ||||
| 		if not abm_allowed then | ||||
| 			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 | ||||
| 			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() | ||||
| 	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 | ||||
| 			return stack | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	minetest.register_abm({ | ||||
| 		nodenames = {"nether:portal"}, | ||||
| 		interval = 1, | ||||
| 		chance = 2, | ||||
| 		catch_up = false, | ||||
| 		action = function(pos, node) | ||||
| 			if not abm_allowed then | ||||
| 				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 | ||||
| 				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 | ||||
| 	}) | ||||
| 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) | ||||
| end | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user