diff options
| author | ShadowNinja <shadowninja@minetest.net> | 2013-11-18 21:01:24 -0500 | 
|---|---|---|
| committer | ShadowNinja <shadowninja@minetest.net> | 2013-11-18 21:12:09 -0500 | 
| commit | f096fb4dbbfae72d4669f6ea3a25823c16e2934d (patch) | |
| tree | 914993a930937fcadadf258e32d8606ed0586a09 | |
| parent | f98312fe10b168eb4ba40c567075661e2f0060bf (diff) | |
Use table indices as IDs
This significantly optimizes a lot of operations and removes redundancy.
| -rw-r--r-- | api.lua | 5 | ||||
| -rw-r--r-- | chatcommands.lua | 89 | ||||
| -rw-r--r-- | init.lua | 11 | ||||
| -rw-r--r-- | internal.lua | 93 | ||||
| -rw-r--r-- | legacy.lua | 35 | ||||
| -rw-r--r-- | pos.lua | 21 | 
6 files changed, 124 insertions, 130 deletions
| @@ -1,4 +1,3 @@ ---TODO Less code duplication  -- Checks if the area is unprotected or owned by you  function areas:canInteract(pos, name) @@ -28,9 +27,7 @@ function areas:getNodeOwners(pos)  		if pos.x >= area.pos1.x and pos.x <= area.pos2.x and  		   pos.y >= area.pos1.y and pos.y <= area.pos2.y and  		   pos.z >= area.pos1.z and pos.z <= area.pos2.z then -			if area.owner ~= nil then -				table.insert(owners, area.owner) -			end +			table.insert(owners, area.owner)  		end  	end  	return owners diff --git a/chatcommands.lua b/chatcommands.lua index 58978f1..e951142 100644 --- a/chatcommands.lua +++ b/chatcommands.lua @@ -1,3 +1,4 @@ +  minetest.register_chatcommand("protect", {  	params = "<AreaName>",  	description = "Protect your own area", @@ -7,10 +8,8 @@ minetest.register_chatcommand("protect", {  			minetest.chat_send_player(name, 'Invalid usage, see /help protect')  			return  		end -		local pos1, pos2 = {}, {} -		if areas:getPos1(name) and areas:getPos2(name) then -			pos1 = areas:getPos1(name) -			pos2 = areas:getPos2(name) +		local pos1, pos2 = areas:getPos1(name), areas:getPos2(name) +		if pos1 and pos2 then  			pos1, pos2 = areas:sortPos(pos1, pos2)  		else  			minetest.chat_send_player(name, 'You need to select an area first') @@ -30,10 +29,10 @@ minetest.register_chatcommand("protect", {  			return  		end -		areas:add(name, param, pos1, pos2, nil) +		local id = areas:add(name, param, pos1, pos2, nil)  		areas:save() -		minetest.chat_send_player(name, "Area protected") +		minetest.chat_send_player(name, "Area protected. ID: "..id)  end}) @@ -51,10 +50,8 @@ minetest.register_chatcommand("set_owner", {  			return  		end -		local pos1, pos2 = {}, {} -		if areas:getPos1(name) and areas:getPos2(name) then -			pos1 = areas:getPos1(name) -			pos2 = areas:getPos2(name) +		local pos1, pos2 = areas:getPos1(name), areas:getPos2(name) +		if pos1 and pos2 then  			pos1, pos2 = areas:sortPos(pos1, pos2)  		else  			minetest.chat_send_player(name, "You need to select an area first") @@ -67,18 +64,18 @@ minetest.register_chatcommand("set_owner", {  			return  		end -		minetest.log("action", name.." runs /set_owner. Owner="..ownername.. -				" AreaName="..areaname.. -				" StartPos="..minetest.pos_to_string(pos1).. -				" EndPos="  ..minetest.pos_to_string(pos2)) +		minetest.log("action", name.." runs /set_owner. Owner = "..ownername.. +				" AreaName = "..areaname.. +				" StartPos = "..minetest.pos_to_string(pos1).. +				" EndPos = "  ..minetest.pos_to_string(pos2)) -		areas:add(ownername, areaname, pos1, pos2, nil) +		local id = areas:add(ownername, areaname, pos1, pos2, nil)  		areas:save()  		minetest.chat_send_player(ownername, -				"You have been granted control over an area." -				.." Type /list_areas to show your areas.") -		minetest.chat_send_player(name, "Area protected") +				"You have been granted control over area #".. +				id..". Type /list_areas to show your areas.") +		minetest.chat_send_player(name, "Area protected. ID: "..id)  end}) @@ -97,10 +94,8 @@ minetest.register_chatcommand("add_owner", {  			return  		end -		local pos1, pos2 = {}, {} -		if areas:getPos1(name) and areas:getPos2(name) then -			pos1 = areas:getPos1(name) -			pos2 = areas:getPos2(name) +		local pos1, pos2 = areas:getPos1(name), areas:getPos2(name) +		if pos1 and pos2 then  			pos1, pos2 = areas:sortPos(pos1, pos2)  		else  			minetest.chat_send_player(name, 'You need to select an area first') @@ -127,13 +122,13 @@ minetest.register_chatcommand("add_owner", {  			return  		end -		areas:add(ownername, areaname, pos1, pos2, pid) +		local id = areas:add(ownername, areaname, pos1, pos2, pid)  		areas:save()  		minetest.chat_send_player(ownername, -				"You have been granted control over an area." -				.." Type /list_areas to show your areas.") -		minetest.chat_send_player(name, "Area protected.") +				"You have been granted control over area #".. +				id..". Type /list_areas to show your areas.") +		minetest.chat_send_player(name, "Area protected. ID: "..id)  end}) @@ -150,9 +145,7 @@ minetest.register_chatcommand("rename_area", {  		end  		id = tonumber(id) -		index = areas:getIndexById(id) - -		if not index then +		if not id then  			minetest.chat_send_player(name, "That area doesn't exist.")  			return  		end @@ -162,7 +155,7 @@ minetest.register_chatcommand("rename_area", {  			return  		end -		areas.areas[index].name = newName +		areas.areas[id].name = newName  		areas:save()  		minetest.chat_send_player(name, "Area renamed.")  end}) @@ -178,11 +171,12 @@ minetest.register_chatcommand("find_areas", {  					"A regular expression is required.")  			return  		end +  		local found = false -		for _, area in pairs(areas.areas) do -			if areas:isAreaOwner(area.id, name) and -			   areas:toString(area):find(param) then -				minetest.chat_send_player(name, areas:toString(area)) +		for id, area in pairs(areas.areas) do +			if areas:isAreaOwner(id, name) and +			   areas:toString(id):find(param) then +				minetest.chat_send_player(name, areas:toString(id))  				found = true  			end  		end @@ -205,10 +199,10 @@ minetest.register_chatcommand("list_areas", {  			minetest.chat_send_player(name,  					"Showing your areas.")  		end -		for _, area in pairs(areas.areas) do -			if admin or areas:isAreaOwner(area.id, name) then +		for id, area in pairs(areas.areas) do +			if admin or areas:isAreaOwner(id, name) then  				minetest.chat_send_player(name, -						areas:toString(area)) +						areas:toString(id))  			end  		end  end}) @@ -227,16 +221,15 @@ minetest.register_chatcommand("recursive_remove_areas", {  			return  		end -		if areas:isAreaOwner(id, name) then -			areas:remove(id, true) -			areas:sort() -			areas:save() -		else +		if not areas:isAreaOwner(id, name) then  			minetest.chat_send_player(name, "Area "..id  					.." does not exist or is"  					.." not owned by you.")  			return  		end + +		areas:remove(id, true) +		areas:save()  		minetest.chat_send_player(name, "Removed area "..id  				.." and it's sub areas.")  end}) @@ -254,16 +247,15 @@ minetest.register_chatcommand("remove_area", {  			return  		end -		if areas:isAreaOwner(id, name) then -			areas:remove(id, false) -			areas:sort() -			areas:save() -		else +		if not areas:isAreaOwner(id, name) then  			minetest.chat_send_player(name, "Area "..id  					.." does not exist or"  					.." is not owned by you")  			return  		end + +		areas:remove(id) +		areas:save()  		minetest.chat_send_player(name, 'Removed area '..id)  end}) @@ -296,8 +288,7 @@ minetest.register_chatcommand("change_owner", {  					.." or is not owned by you.")  			return  		end -		local index = areas:getIndexById(id) -		areas.areas[index].owner = new_owner +		areas.areas[id].owner = new_owner  		areas:save()  		minetest.chat_send_player(name, 'Owner changed.')  		minetest.chat_send_player(new_owner, @@ -21,12 +21,17 @@ areas:load()  minetest.register_privilege("areas", {description = "Can administer areas"})  if not minetest.registered_privileges[areas.self_protection_privilege] then -	minetest.register_privilege(areas.self_protection_privilege, -		{description = "Can protect areas"}) +	minetest.register_privilege(areas.self_protection_privilege, { +		description = "Can protect areas", +	}) +end + +for _, area in pairs(areas.areas) do +	area.id = nil  end  if minetest.setting_getbool("log_mod") then  	local diffTime = os.clock() - areas.startTime -	print("[areas] loaded in "..diffTime.."s.") +	minetest.log("action", "areas loaded in "..diffTime.."s.")  end diff --git a/internal.lua b/internal.lua index e57cfd8..f52b954 100644 --- a/internal.lua +++ b/internal.lua @@ -1,3 +1,4 @@ +  function areas:player_exists(name)  	return minetest.auth_table[name] ~= nil  end @@ -20,45 +21,59 @@ function areas:load()  		return err  	end  	self.areas = minetest.deserialize(file:read("*a")) -	if type(self.areas) ~= "table" then self.areas = {} end +	if type(self.areas) ~= "table" then +		self.areas = {} +	end  	file:close()  end --- Shorter than the table function +-- Finds the first usable index in a table +-- Eg: {[1]=false,[4]=true} -> 2 +local function findFirstUnusedIndex(t) +	for i = 1, #t + 1 do +		if t[i] == nil then +			return i +		end +	end +end + +-- Add a area, returning the new area's id.  function areas:add(owner, name, pos1, pos2, parent) -	table.insert(areas.areas, {id=table.maxn(self.areas)+1, name=name, -			pos1=pos1, pos2=pos2, owner=owner, parent=parent}) +	local id = findFirstUnusedIndex(self.areas) +	self.areas[id] = {name=name, pos1=pos1, pos2=pos2, owner=owner, +			parent=parent} +	return id  end  -- Remove a area, and optionally it's children recursively.  -- If a area is deleted non-recursively the children will  -- have the removed area's parent as their new parent. -function areas:remove(id, recurse) +function areas:remove(id, recurse, secondrun)  	if recurse then  		-- Recursively find child entries and remove them  		local cids = self:getChildren(id)  		for _, cid in pairs(cids) do -			self:remove(cid, true) +			self:remove(cid, true, true)  		end  	else  		-- Update parents -		local parent = self:getAreaById(id).parent +		local parent = self.areas[id].parent  		local children = self:getChildren(id) -		for _, child in pairs(children) do +		for _, cid in pairs(children) do  			-- The subarea parent will be niled out if the  			-- removed area does not have a parent -			areas.areas[self:getIndexById(child)].parent = parent +			self.areas[cid].parent = parent  		end  	end  	-- Remove main entry -	table.remove(self.areas, self:getIndexById(id)) +	self.areas[id] = nil  end  -- Checks if a area between two points is entirely contained by another area  function areas:isSubarea(pos1, pos2, id) -	local area = areas:getAreaById(id) +	local area = self.areas[id]  	if not area then  		return false  	end @@ -76,9 +91,9 @@ end  -- Returns a table (list) of children of an area given it's identifier  function areas:getChildren(id)  	local children = {} -	for _, area in pairs(self.areas) do +	for cid, area in pairs(self.areas) do  		if area.parent and area.parent == id then -			table.insert(children, area.id) +			table.insert(children, cid)  		end  	end  	return children @@ -140,57 +155,43 @@ function areas:canPlayerAddArea(pos1, pos2, name)  	return true, ""  end --- Given a area returns a string in the format: +-- Given a id returns a string in the format:  -- "name [id]: owner (x1, y1, z1) (x2, y2, z2) -> children" -function areas:toString(area) -	local message = area.name.. -		" ["..area.id.."]: "..area.owner.." ".. -		minetest.pos_to_string(area.pos1).." ".. -		minetest.pos_to_string(area.pos2) +function areas:toString(id) +	local area = self.areas[id] +	local message = ("%s [%d]: %s %s %s"):format( +		area.name, id, area.owner, +		minetest.pos_to_string(area.pos1), +		minetest.pos_to_string(area.pos2))  	local children = areas:getChildren(id)  	if #children > 0 then -		message = message.. -		" -> "..table.concat(children, ", ") +		message = message.." -> "..table.concat(children, ", ")  	end -	return message		 -end - --- Returns a area given it's identifier -function areas:getAreaById(id) -	if not self.areas[id] then -		return nil -	end -	assert(self.areas[id].id == id) -	return self.areas[id] -end - --- Returns a table index for an area given it's identifier -function areas:getIndexById(id) -	if not self.areas[id] then -		return nil -	end -	assert(self.areas[id].id == id) -	return id +	return message  end  -- Re-order areas in table by their identifiers  function areas:sort() +	local sa = {}  	for k, area in pairs(self.areas) do -		if area.id ~= k then +		if not area.parent then +			table.insert(sa, area) +			local newid = #sa  			for _, subarea in pairs(self.areas) do -				if subarea.parent == area.id then -					subarea.parent = k +				if subarea.parent == k then +					subarea.parent = newid +					table.insert(sa, subarea)  				end  			end -			area.id = k  		end  	end +	self.areas = sa  end  -- Checks if a player owns an area or a parent of it  function areas:isAreaOwner(id, name) -	local cur = self:getAreaById(id) +	local cur = self.areas[id]  	if cur and minetest.check_player_privs(name, {areas=true}) then  		return true  	end @@ -198,7 +199,7 @@ function areas:isAreaOwner(id, name)  		if cur.owner == name then  			return true  		elseif cur.parent then -			cur = self:getAreaById(cur.parent) +			cur = self.areas[cur.parent]  		else  			return false  		end @@ -22,21 +22,22 @@ minetest.register_chatcommand("legacy_load_areas", {  		minetest.chat_send_player(name, "Legacy file loaded.")  		for k, area in pairs(areas.areas) do -			--New position format -			areas.areas[k].pos1 = {x=area.x1, y=area.y1, z=area.z1} -			areas.areas[k].pos2 = {x=area.x2, y=area.y2, z=area.z2} +			-- New position format +			area.pos1 = {x=area.x1, y=area.y1, z=area.z1} +			area.pos2 = {x=area.x2, y=area.y2, z=area.z2} -			areas.areas[k].x1, areas.areas[k].y1, -			areas.areas[k].z1, areas.areas[k].x2, -			areas.areas[k].y2, areas.areas[k].z2 = +			area.x1, area.y1, area.z1, +			area.x2, area.y2, area.z2 =  				nil, nil, nil, nil, nil, nil -			--Area positions sorting -			areas.areas[k].pos1, areas.areas[k].pos2 = -				areas:sortPos(areas.areas[k].pos1, areas.areas[k].pos2) +			-- Area positions sorting +			area.pos1, area.pos2 = areas:sortPos(area.pos1, area.pos2) -			--Add name -			areas.areas[k].name = "unnamed" +			-- Add name +			area.name = "unnamed" + +			-- Remove ID +			area.id = nil  		end  		minetest.chat_send_player(name, "Table format updated.") @@ -81,9 +82,7 @@ function areas.getNodeOwnerName(pos)  		if pos.x >= p1.x and pos.x <= p2.x and  		   pos.y >= p1.y and pos.y <= p2.y and  		   pos.z >= p1.z and pos.z <= p2.z then -			if area.owner ~= nil then -				return area.owner -			end +			return area.owner  		end  	end  	return false @@ -138,6 +137,7 @@ if areas.legacy_table then  				a.y2 = a.pos2.y  				a.z2 = a.pos2.z  				a.pos1, a.pos2 = nil, nil +				a.id = key  			end  			return a  		end, @@ -151,10 +151,11 @@ if areas.legacy_table then  				a.pos2.x = a.x2  				a.pos2.y = a.y2  				a.pos2.z = a.z2 -				a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 -				= nil, nil, nil, nil, nil, nil +				a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 = +					nil, nil, nil, nil, nil, nil  				a.name = a.name or "unnamed" -				return rawset(areas.areas, key, a); +				a.id = nil +				return rawset(areas.areas, key, a)  			end  		end  	}) @@ -22,19 +22,18 @@ minetest.register_chatcommand("select_area", {  					"Invalid usage, see /help select_area.")  			return  		end - -		for k, area in pairs(areas.areas) do -			if area.id == id then -				areas:setPos1(name, area.pos1) -				areas:setPos2(name, area.pos2) -				minetest.chat_send_player(name, -						"Area "..id.." selected.") -				return -			end +		if not areas.areas[id] then +			minetest.chat_send_player(name, +					"The area "..id.." does not exist.") +			return  		end + +		areas:setPos1(name, areas.areas[id].pos1) +		areas:setPos2(name, areas.areas[id].pos2)  		minetest.chat_send_player(name, -				"The area "..id.." does not exist.") -end}) +				"Area "..id.." selected.") +	end, +})  minetest.register_chatcommand("area_pos1", {  	params = "[X Y Z|X,Y,Z]", | 
