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

How to make a shared folder?

Started by tedjansen, 04 March 2012 - 09:03 AM
tedjansen #1
Posted 04 March 2012 - 10:03 AM
Can i make something like a central server where all my programs are stored? ( Wirelless please! )
Already thanks
Cookiebal #2
Posted 04 March 2012 - 11:03 AM
I think that's possible.

If you have a setup where each computer is connected to a disk drive which is then connected to a second computer, have the second computer listen for special rednet messages and automatically put the received messages in files on the disk drive, to send a file to the central server you have the first computer send a special rednet message to that computer (which then spreads it to the others again).
Liraal #3
Posted 04 March 2012 - 11:19 AM
i am working on net drives, but there are still some errors.
Espen #4
Posted 04 March 2012 - 11:34 AM
With the rednet API this should be relatively easy to realize.
You just make the file hosting computer listen for requests and when it gets a request for a certain file, it just sends the whole file as a string.
This should be pretty simple, because you can read a whole file into a variable with fileHandle:read("*a") (when using io.open)

The only catch is that you'd have to do this with wireless modems, because with bundled cables the rednet API actually uses redstone pulses to send messages, which can mess up you payload, especially if there's cross-talk on the cable. Just something to keep in mind. But otherwise it should be pretty straightforward. :unsure:/>/>
tedjansen #5
Posted 04 March 2012 - 05:32 PM
I'm not good in coding i use very simple redstone pulse software but i dont now how i can do that… Sorry can you make that for me?
Espen #6
Posted 04 March 2012 - 05:36 PM
I would if I didn't have an exam tomorrow, sorry. :unsure:/>/>
But I'm sure someone else will take on your request.
If by tomorrow there's still no answer, then I'll try to put something together. B)/>/>
tedjansen #7
Posted 04 March 2012 - 05:50 PM
Oke Thanks!
Liraal #8
Posted 04 March 2012 - 06:09 PM
I'll try to get something for you today, but only after I have watched a movie :unsure:/>/>
Liraal #9
Posted 04 March 2012 - 09:25 PM
Can someone look into this code?
Works almost perfectly, just doesn't return the file to the remote terminal.

function drive(id, pass)
while true do
local a,b,c=os.pullEvent()
while a~="rednet_message" or b~=id do a,b,c=os.pullEvent("rednet_message") print(a,b,c) end
print(a,b,c)
if c==pass then
local d,e,f=os.pullEvent("rednet_message")
print(d,e,f)
while e~=id do d,e,f=os.pullEvent("rednet_message") end
local tmp=io.open(f,"r") local tmp2=tmp:read() tmp:close()
print(tmp2)
rednet.send(id, tmp2)
end
end
return true
end
function driveGet(id,pass,file)
if not rednet.send(id, pass) then rednet.open(side) rednet.send(id, pass) end
sleep(2)
rednet.send(id, file)
local a,b,c=os.pullEvent("rednet_message")
print(a,b,c)
while b~=id do a,b,c=os.pullEvent("rednet_message") end
return c
end
Advert #10
Posted 04 March 2012 - 10:07 PM
Can someone look into this code?
Works almost perfectly, just doesn't return the file to the remote terminal.

function drive(id, pass)
while true do
local a,b,c=os.pullEvent()
while a~="rednet_message" or b~=id do a,b,c=os.pullEvent("rednet_message") print(a,b,c) end
print(a,b,c)
if c==pass then
local d,e,f=os.pullEvent("rednet_message")
print(d,e,f)
while e~=id do d,e,f=os.pullEvent("rednet_message") end
local tmp=io.open(f,"r") local tmp2=tmp:read() tmp:close()
print(tmp2)
rednet.send(id, tmp2)
end
end
return true
end
function driveGet(id,pass,file)
if not rednet.send(id, pass) then rednet.open(side) rednet.send(id, pass) end
sleep(2)
rednet.send(id, file)
local a,b,c=os.pullEvent("rednet_message")
print(a,b,c)
while b~=id do a,b,c=os.pullEvent("rednet_message") end
return c
end
You are sacrificing a lot of readability by using one-letter variable names, and putting multiple expressions on the same line.
And there is no indentation, but that may be the forum.
In addition to that, you're passing up on a good case of a repeat until loop:


function driveGet(id, pass, file)
if not rednet.send(id, pass) then
rednet.open(side) -- Side is undefined
rednet.send(id, pass)
end
sleep(2)
rednet.send(id, file)
local sEvent, p1, p2
repeat
sEvent, p1, p2 = os.pullEvent("rednet_message")
until p1 == id
return p2
end

It'd be easier to figure out why it isn't working, if you provided a runnable example, instead of two functions :unsure:/>/>
MysticT #11
Posted 04 March 2012 - 11:38 PM
I rewrote the code, I'm not sure if it works (I haven't tested it), but at least it's more readable :unsure:/>/>

function drive(nId, pass)
    while true do
        local evt, id, msg
        repeat
            evt, id, msg = os.pullEvent("rednet_message")
        until id == nId
        print(id, msg)
        if msg == pass then
            repeat
                evt, id, msg = os.pullEvent("rednet_message")
            until id == nId
            local file = io.open(msg, "r")
            if file then
                local s = file:read("*a")
                file:close()
                print(s)
                rednet.send(id, s)
            end
        end
    end
    return true
end

function driveGet(id, pass, file)
    rednet.open(side) -- side not defined
    rednet.send(id, pass)
    sleep(2)
    rednet.send(id, file)
    repeat
        local evt, _id, msg = os.pullEvent("rednet_message")
    until _id == id
    return c
end
ChaosBeing #12
Posted 05 March 2012 - 12:59 AM
If anyone's interested, I started writing something to do this a couple hours ago (before all these recent posts) and I've got it done. It hasn't been extensively bug tested, but I did make sure all the basics work fine.

Client API:
http://pastebin.com/8zTN0bcU

Server startup:
http://pastebin.com/V8JpW2Uf

Just make a terminal and put the server startup file as, well, its startup. Then put the client API on your client terminal and add a file called serverID that contains whatever the ID is of the terminal that you installed the server startup file on.

To use the api, just load it with os.loadAPI("client") in your program, and then you can do client.upload(*filepath*) and client.download(*filepath*) to upload and download from the server. Only one terminal can actively access the server at a time, but if multiple terminals try to access it, they'll get a busy message, and it shouldn't mess up the current upload/download.

Well, it's easier to experiment for yourself than for me to point out all of the details.
Edited on 05 March 2012 - 12:03 AM
tedjansen #13
Posted 05 March 2012 - 04:33 PM
Can i do with this send commands over like from ID #1 to ID #5 with the command booter?
ChaosBeing #14
Posted 05 March 2012 - 04:45 PM
Um, I'm not entirely sure what you mean by that, but if you're asking if you can send commands to/from the server the short answer to that would be no. (However this could very easily be implemented.) In it's current state, its only function is to send/receive files.

These files can be whatever you like of course, so if what you were asking was if you could overwrite startup, then yes.


Also, one thing I didn't mention above is that it was made with labelled computers in mind. Any labelled computer will have its files saved separately on the server. If you have one terminal labelled "control", one labelled "master", and a turtle labelled "miner", they'll all save their files separately. (So they could each have a separate startup, for example.) Unlabelled terminals/turtles all save their files to the same place, and so will overwrite each other. You could even overwrite the server startup file by accident. (Something that'd certainly need to be addressed if you'd planned on using this for multiplayer.)
tedjansen #15
Posted 05 March 2012 - 05:48 PM
How must i install this API?
ChaosBeing #16
Posted 06 March 2012 - 06:43 AM
Same way you get almost any code into your world. :unsure:/>/> First, figure out the ID of the server and the ID of the client(s). (Run lua, and type os.getComputerID() )

Second, go into your minecraft/saves/*yourworld* folder and look for the computer folder. Inside is yet more folders, this time all named numbers. These numbers correspond to the computer ID.

Server:
Just paste my server startup code into a file right here, and call it startup.

Client:
Again, just paste my client API code into a file in your client computer(s) folder. You can call this file whatever you like. I'll use client as my example.

You'll want to make one more file in here and call it serverID. Just put your server's ID in it, and you're all done.


Now in any programs that you make you can use os.loadAPI("client") at the top of your program to load the API and call its functions. Here's an example of how to use the API in a program:


os.loadAPI("client")

--Your program

client.upload("fileToSend")   --Send a file to the server
client.download("fileToRetrieve")   --Retrieve a file from the server
tedjansen #17
Posted 06 March 2012 - 09:01 AM
Thanks!
tedjansen #18
Posted 06 March 2012 - 09:47 AM
Do you know how to start a program after downloading the file?
Advert #19
Posted 06 March 2012 - 09:55 AM
Do you know how to start a program after downloading the file?
You can still use shell.run().
Type 'help shellapi' ingame.
jpiolho #20
Posted 06 March 2012 - 09:56 AM
shell.run(program,arguments)

Example:
shell.run("adventure","") -- Starts the adventure game from Computercraft
tedjansen #21
Posted 06 March 2012 - 10:14 AM
Thanks now my hole system works!
tedjansen #22
Posted 06 March 2012 - 10:26 AM
I get the error : client:74: attempt to index ? (a nil value)
Espen #23
Posted 06 March 2012 - 11:24 AM
Thanks now my hole system works!
I get the error : client:74: attempt to index ? (a nil value)
Hehe, it seems you were absolutely right about that hole in your system. :unsure:/>/>

Hmm, it looks like it's trying to access 'msg' on that line, which doesn't seem to have at least 6 characters for the program to be able to iterate through.
You should be able to fix this by checking its length first, before trying to access its characters.
So instead of…

rednet.send(server, "dl." .. path2)
ignore, msg = rednet.receive(1)

if msg:sub(1, 6) == "ERROR:" then
  print(msg)
  return
end
…try something like this…

rednet.send(server, "dl." .. path2)
ignore, msg = rednet.receive(1)

if ( #msg >= 6 ) and ( msg:sub(1, 6) == "ERROR:" ) then
  print(msg)
  return
end

Disclaimer: Haven't acutally tried it in-game, but it should work. Also didn't look at the rest of the code, only concentrated on your reported error.
If there's more after this, just holler like a madman. ( No, just kidding, ask nicely^^ )
tedjansen #24
Posted 06 March 2012 - 11:32 AM
now its giving this error : client:77 attempt to get length of nil
Espen #25
Posted 06 March 2012 - 12:22 PM
now its giving this error : client:77 attempt to get length of nil
Hmm, that means 'msg' is not assigned when we try to get its length, even tough the code looks like it will receive content from above. *headscratch*
Did you by any chance type this all manually or did you copy'n'paste the file into your CC folder?

I'm going to take a look at it ingame to see what's wrong.

EDIT: Ah, ok, *derp*. Now I see what's going on.
When it's waiting one second for an incoming message in line 72, it doesn't check afterwards it a message has indeed arrived.
That means that both 'id' and 'msg' will be nil / not defined.
So instead of the original function download, try this instead:
function download(path)

  name = os.getComputerLabel()

  if name then
	path2 = name .. "/" .. path
  end

  path2 = path2 or path

  rednet.send(server, "dl." .. path2)
  ignore, msg = rednet.receive(1)

  if msg ~= nil then
	if (#msg >= 6) and (msg:sub(1, 6) == "ERROR:") then
	  print(msg)
	  return
	end
	
	if fs.exists(path) then
	  print("File exists. Overwrite? (y/n): ")
	  
	  overwrite = read()
	  overwrite:lower()
	  rednet.send(server, overwrite)
	  
	  if overwrite ~= "y" then
		print("Transfer Aborted.")
		return
	  end
	end
	
	file = io.open(path, "w")
	file:write(msg)
	file:close()
	print("Transfer completed successfully.")
  else
	print("Error: Didn't receive anything.")
  end
end

Still haven't tried it ingame, only took a look at the return values of rednet.receive when nothing is being sent and then basically inserted some lines to check for msg ~= nil.

EDIT: Forgot fix from earlier post. Included it now. :unsure:/>/>
Edited on 06 March 2012 - 01:47 PM
tedjansen #26
Posted 06 March 2012 - 12:28 PM
Copy And Paste
ChaosBeing #27
Posted 06 March 2012 - 02:40 PM
Sorry 'bout that, looks like I goofed a little bit.

Have you had any problems after Espen's fix?
Mads #28
Posted 06 March 2012 - 03:21 PM
With some clever use of the http API, you should be able to upload files to a webserver, I saw you(jpiolho) had made a program that uploads a paste to tinypaste.com. Just saying that this would be amazing! That would allow for some kind of quote-on-quote "Internet" in Minecraft. Also it would make "chatting" alot easier! :unsure:/>/>
ENET #29
Posted 06 March 2012 - 11:32 PM
I actually made a ftp in computercraft sorta. You run the program, then any dos cmd you type in your computer is ran on the other one and sends you the output.
tedjansen #30
Posted 07 March 2012 - 01:52 PM
now theres a problem with my download script whats wrong here?

error : startup:3 attempt to call nil

startup script :


os.loadAPI("client")

client.download("mineshaft")

shell.run("mineshaft","")
Advert #31
Posted 07 March 2012 - 04:07 PM
You don't need to specify empty arguments with shell.run; you can use shell.run("program").

I'm thinking that this may be what's causing the error (in which case shell.run is bugged), or that shell.run isn't a function, for some reason.

Try putting print(shell.run) before you use it, and it'll tell you if it's a function or not.
tedjansen #32
Posted 07 March 2012 - 04:35 PM
its the client.download function not the shell
Advert #33
Posted 07 March 2012 - 04:42 PM
its the client.download function not the shell

Then, the download function doesn't exist in client, but the API *seems* to be loaded, since the table exists.
ChaosBeing #34
Posted 08 March 2012 - 11:53 AM
^ What he said.

Could you try looking in the API and making sure that everything's still alright? If nothing else, you could try restarting and seeing if it'll work after it's unloaded/reloaded the API.

EDIT:
The thought occurred to me right as I pressed post, but that is the entire error, right? (I just had to make sure. :mellow:/>/>) If not, it could be another error occuring within download itself. Even if that is the whole error I guess it still could be. I've had similar errors when trying to use shell.run in the past, where an error in the code called seems to show up in the code doing the calling.
tedjansen #35
Posted 16 March 2012 - 11:36 AM
It's the entire error and the API is still right…