This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
MayContainVennom's profile picture

Broken Player Detector

Started by MayContainVennom, 14 November 2013 - 10:43 AM
MayContainVennom #1
Posted 14 November 2013 - 11:43 AM
On a multiplayer server, I have been creating a system whereby each door in a building has a player detector attached, and thereby only allowed players can open them. Each door has a computer which talks to a main server, holding the disk, and then the server returns either true/false if the user is allowed. The code appears to work, however it will only read the first line of the 'Allowed Users' file. I think this is a simple fix, however I cannot for the life of me see where it is. Any help would be much appreciated.

Client (Computer on Door):

rednet.open("bottom")
function allowed(player,authServer)
		rednet.send(authServer,player)
		id, message, distance = rednet.receive()
		if message then
				return true
		else
				return false
		end
end
function door(player,authServer)
		if allowed(player,authServer) then
				redstone.setOutput("top",true)
				sleep(4)
				redstone.setOutput("top",false)
				return true
		else
				return false
		end
end
function logger(player,logServer,state)
		if state then
				rednet.send(logServer,player.." was granted access "..os.time.." via computer "..os.getComputerID())
		else
				rednet.send(logServer,player.." tried to get in at "..os.time.." via computer "..os.getComputerID())
		end
end
function getPlayer()
		event, name = os.pullEvent("player")
		return name
end
function main()
		local authServer = 330
		local logServer = 331
		local player = getPlayer()
		if door(player,authServer) then
				logger(player,logServer,true)
		else
				logger(player,logServer,false)
		end
end
while true do
		main()
end

Server (With disk):

rednet.open("bottom")
function authorise(request)
		players = fs.open("disk/allowed","r")
		for player in players:lines() do
				if request == player then
						return true
				else
						return false
				end
		end
end
function receiveRequest()
		id, request, distance = rednet.receive()
		return id, request
end
function allowPlayer(door,state)
		rednet.send(door,state)
end
function main()
		local id, player = receiveRequest()
		if authorise(player) then
				allowPlayer(id,true)
		else
				allowPlayer(id,false)
		end
end
while true do
		main()
end
MysticT #2
Posted 14 November 2013 - 11:47 AM
The problem is in the "authorise" function:

function authorise(request)
		players = fs.open("disk/allowed","r")
		for player in players:lines() do
				if request == player then
						return true
				else
						return false
				end
		end
end
You check the first line of the file, and if it matches return true, if it doesn't returns false without checking the other lines.
Change it to this and it should work:

function authorise(request)
		players = fs.open("disk/allowed","r")
		for player in players:lines() do
				if request == player then
						return true
				end
		end
	    return false
end
MayContainVennom #3
Posted 14 November 2013 - 11:52 AM
Ah crap, I knew it would be simple! Thanks a tonne, I'll go test it out now
MayContainVennom #4
Posted 14 November 2013 - 05:03 PM
*UPDATE*

Now it's just plain jiggered, error code:

startup:5: attempt to call nil

It's getting requests from the door, however it appears to be having trouble reading from the file? I tried moving it from a disk to computer storage, however it still came up with the same error. The file is named correctly, and just contains a list of the players. Loading it manually in the lua console just returns an empty table.
Bomb Bloke #5
Posted 15 November 2013 - 01:53 AM
Assuming your fifth line is currently:

for player in players:lines() do

… this probably means that you have a version of ComputerCraft that's prior to 1.55 (which added "io.lines()").

If this is the case, you can use something like:

local function authorise(request)
  local players = fs.open("disk/allowed","r")
  local readIn=""
  while readIn do
    readIn = players.readLine()
    if readIn == request then
	  players.close()
	  return true
    end
  end
  players.close()
  return false
end

Otherwise, please elaborate on which line of code is actually erroring out.

Edit: Suppose your original code would've errored out in the same way if it were the case. So yeah, please provide details on where your current problem actually is.
Edited on 15 November 2013 - 12:55 AM
Lyqyd #6
Posted 15 November 2013 - 01:28 PM
Your information is incorrect. io.lines(file) was added recently, but handle:lines() with io-opened handles has been around for many versions. The problem is that MysticT's code opens a file handle with fs.open instead of io.open and does not close the handle. Try this:


function authorise(request)
  local players = io.open("disk/allowed","r")
  if players then
    for player in players:lines() do
      if request == player then
        players:close()
        return true
      end
    end
    players:close()
    return false
  else
    error("File Not Found")
  end
end
MayContainVennom #7
Posted 15 November 2013 - 02:36 PM
Sorry about the delay, been at college all day. Will try out the new code and report back asap.

Thanks for your help

You guys are awesome! Got it all working perfectly, thanks so much! Turns out I'm a bit rusty on the whole programming lark haha