Help with some ComputerCraft coding :\

  • The FTB Forum is now read-only, and is here as an archive. To participate in our community discussions, please join our Discord! https://ftb.team/discord

efraina alvarez

New Member
Jul 29, 2019
10
0
0
Hey, everyone! I just got into coding with ComputerCraft and I need some help with printing. It's very basic, but I can't seem to work it out. Here is part of the coding that I'm not getting right

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
spawner=peripheral.wrap("top")
x = spawner.getTankInfo()
print(x)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So basically I'm trying to get an Advanced Computer to check what's inside the Auto-Spawner from MFR, and display it. But every time I run it, I get "table: 4110bb08". Am i going to have to do something with tables? If anyone knows what the problem is, please let me know :p

btw, this is what I get with "spawner.getTankInfo()"

{
{
capacity = 4000,
contents = {
rawName = "Essence",
amount = 2000,
name = "mobessence",
id = 152,
},
},
}

That's what I'm trying to print ^^^
Thanks!
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
The problem is that the print function doesn't print what is inside the table and only prints that it is a table.
Now, lets make a function that will do what you want (Note, I don't have time to test this inside minecraft therefor I went on memory as to how the data is stored of the tanks. Also this means that in this example I used the table you gave rather then use the function to get one.)
Code:
--first lets break the table down so I can more easily explain what the code does
--It starts with a table that holds all the tanks inside a block. In the case of the autospawner that is only one but inb other blocks it might be more
local exampleBlock={
   --this table is the acctuall tank.
   {
     --this is the capacity of said tank and by the looks of it in MB
     capacity = 4000,
     --this is what the tank holds
     contents = {
       --this is probably the ID of the liquid
       rawName = "Essence",
       --this is how much there is, by the looks of it also in MB
       amount = 2000,
       --this is the normal name
       name = "mobessence",
       --this is the numeric ID this can be diffrent in other worlds not sure why you would want to use it as a result of that
       id = 152,
     },
   },
}
--now lets make a function that loops over all the tanks and prints some usefull data
local function printTanks(tankTable)
   --loop over all the tanks inside the block
   for key, value in pairs(tankTable) do
     print("This tank holds: " .. value.capacity .. " MB")
     print("It has ".. value.contents.amount .. " MB stored of ".. value.contents.name)
   end
end

--to use it get the table. I use the table from before as I can't be bothered to open minecraft right now and then run the function
printTanks(exampleBlock)
The result:
Code:
This tank holds: 4000 MB
It has 2000 MB stored of mobessence
Some more explanation, I used the single dot (thus the ".") to get a specific value inside a table and I use 2 dots next to each other to concatenate the strings. They can and probably should be replaced with comma's as this will make the program run a bit faster (though in this case it won't be noticeable) however every lua interpreter handles that different and some then places tabs in between the diffrent values and I forgot how CC handles it (It won't crash, the output just might look different )

Also, when posting code please use code tags, they make your code a bit easier to read as it makes sure the tabs and spaces at the start stay.
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
The problem is that the print function doesn't print what is inside the table and only prints that it is a table.
Now, lets make a function that will do what you want (Note, I don't have time to test this inside minecraft therefor I went on memory as to how the data is stored of the tanks. Also this means that in this example I used the table you gave rather then use the function to get one.)
Code:
--first lets break the table down so I can more easily explain what the code does
--It starts with a table that holds all the tanks inside a block. In the case of the autospawner that is only one but inb other blocks it might be more
local exampleBlock={
   --this table is the acctuall tank.
   {
     --this is the capacity of said tank and by the looks of it in MB
     capacity = 4000,
     --this is what the tank holds
     contents = {
       --this is probably the ID of the liquid
       rawName = "Essence",
       --this is how much there is, by the looks of it also in MB
       amount = 2000,
       --this is the normal name
       name = "mobessence",
       --this is the numeric ID this can be diffrent in other worlds not sure why you would want to use it as a result of that
       id = 152,
     },
   },
}
--now lets make a function that loops over all the tanks and prints some usefull data
local function printTanks(tankTable)
   --loop over all the tanks inside the block
   for key, value in pairs(tankTable) do
     print("This tank holds: " .. value.capacity .. " MB")
     print("It has ".. value.contents.amount .. " MB stored of ".. value.contents.name)
   end
end

--to use it get the table. I use the table from before as I can't be bothered to open minecraft right now and then run the function
printTanks(exampleBlock)
The result:
Code:
This tank holds: 4000 MB
It has 2000 MB stored of mobessence
Some more explanation, I used the single dot (thus the ".") to get a specific value inside a table and I use 2 dots next to each other to concatenate the strings. They can and probably should be replaced with comma's as this will make the program run a bit faster (though in this case it won't be noticeable) however every lua interpreter handles that different and some then places tabs in between the diffrent values and I forgot how CC handles it (It won't crash, the output just might look different )

Also, when posting code please use code tags, they make your code a bit easier to read as it makes sure the tabs and spaces at the start stay.

Wow, thanks! But you got me even more confused now :p I'm confused as to how your coding will receive the data it needs. I tried testing it..
Code:
x = spawner.getTankInfo()
print(x)
local function printTanks(tankTable)
for key, value in pairs(tankTable) do
print("This tank holds: "..value.contents.amount .. " MB stored of "..value.contents.name)
end
end
I don't quite understand what "printTanks" is and just how it will receive it. I only put the
Code:
spawner.getTankInfo()
print(x)
because I just don't know how, again, it will receive the data. Sorry if I'm asking for too much. I'm just very curious. Thanks again btw.
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
It gains data the sameway you give data to for example the print function. Thus something like
Local blockInfo=spawner.getTankInfo ()
printTanks(blockInfo)
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
If it crashes then please post the error. If it doesn't print anything I suggest to look up how functions work. I would have explained it but currently am on a phone
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
If it crashes then please post the error. If it doesn't print anything I suggest to look up how functions work. I would have explained it but currently am on a phone
Ok, well, now I seem to be getting closer to actually getting it, but there is still another problem :\

Code:
tankTable=spawner.getTankInfo()
print(tankTable)
for key, value in pairs(tankTable) do
print("This tank holds: "..value.contents.amount .. " MB stored of "..value.contents.name)
end

This code gives me

Code:
table:e905375
This tank holds: 2000 MB stored of mobessence

I ended up changing your coding a bit because it didn't want to work with it. Like "prints", but I might have messed it up a bit because it doesn't complete it.

Edit* I changed the coding and this worked

Code:
tankTable=spawner.getTankInfo()
print(tankTable)
for key, value in pairs(tankTable) do
print("This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name)
end
This gives me

Code:
table : 5z23b0d5
  This tank holds 4000 MB: It has 2000 MB stored of mobessence

:D :D So it seems I just had to tweak your coding a bit, and add some things (capacity). Now, is there a way for me to not have the table id come up? Thanks
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
Simple
Code:
tankTable=spawner.getTankInfo()
for key, value in pairs(tankTable) do
    print("This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name)
end
I removed the print between
tankTable=spawner.getTankInfo()
and my code

Also, I made it like that as it would make it easier to use it multiple times through out the script.
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
Simple
Code:
tankTable=spawner.getTankInfo()
for key, value in pairs(tankTable) do
    print("This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name)
end
I removed the print between
tankTable=spawner.getTankInfo()
and my code

Also, I made it like that as it would make it easier to use it multiple times through out the script.

Awesome!! Works like a charm. If you wouldn't mind, I want to try and learn how to send/receive message/programs using rednet. I've learned quite a bit now because of you. So, I would have a computer connected to the spawner, then have that computer transfer the data wirelessly to the main computer, and have that computer output the data into a monitor. I would have to use this code to send the data

Code:
rednet.send(27, "DATASTERF")

and this code to receive the data

Code:
local senderId, message, protocol = rednet.receive()
print(message)

Now I know I'm going to have to change these a lot, or even use other methods. Like instead of it waiting for the message once, then stopping, like have it in a loop so it constantly updates the data, and mon.write() to put the data onto the monitors. As for the send, I'm stuck in a corner for that one :\ lol. If you would like to help me, that would be grand. Thank you :)
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
I know using wired cables would be so much easier, but I want to learn more so that I know what to do in the future
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
Haven't tested them but I think they will work :)
The first piece of code is the one that will run on the computer near the spawner and the second one will run on the one with the monitor. I also added as much comments as I could think of to help you understand how the code works (and assuming the scripts work I let in a nice exercise for you. What? Did you really taught I would do all the work ;) (It is actually because I don't want to start minecraft right now and the code I write to work with monitors never work the first time as I always forget something :p ) )
Code:
--this is the one near the spawner. First I am going to set all the peripherals up.
--I am assuming the tank is to at the top and the modem is on the right
--Also note the use of "local" for now its not that importand but when you start to make functions they will become.
--Its also a good practice to use them when making variables or functions.
local spawner = peripheral.wrap("top")
local modem = peripheral.wrap("right")

--Now I am going to declare some variables that are used later. I do it now as that is generally good practice to declare your variables all in a nice place.
local blockInfo, message   =   nil --blockInfo will be used just as before. message will hold the text that will be displayed on the monitor.

--now lets make the loop. I am going to use a while loop.
--While loops need a value or statement and will loop for as long as that is true.
--you use loops like this while STATEMENT do
while true do --as I used true for the STATEMENT it will run forever
--first we are going to get the contents of the spawner
local blockInfo = spawner.getTankInfo()
--Now we are going to read what is inside the spawner
blockInfo=spawner.getTankInfo()
--Now we are going to generate the message that will end up on the monitor
--first we are going to clear the previous message.
message   =""
for key, value in pairs(blockInfo) do
   message= message.."This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name.."\n"
end
--the \n is a special character that will be displayed as a new line (like as if you pressed enter).
--Now that we have the message lets send it.
--1 is the channel that is used to send it.
--2 is normally used to let the reciever know what channel to use to reply.
--However I only set this as the function requires a value and it isn't acctually used.
--message is of course the variable that holds our message
modem.transmit(1,2,message)  
sleep(5) --this function let the loop wait for a bit. The number is the amount pf seconds before the code continous.
--it is recomended to have while loops sleep for a bit to prevent laggy situations especially as CC has protection against that and will in certain situations stop the program.
end --this is used to let lua know where the code stops that is part of the loop
The code to run on the computer with the monitor
Code:
--just like before I first wrap all the peripherals.
--Again I assume the modem is on the right and I will also asume that the monitor is on the left
local modem   =   peripheral.wrap("right")
local modem   =   peripheral.wrap("left")
--and once again I declare the variables that I am going to use
local event,side,senderChannel,replyChannel,message,distance
--now lets tell the computer that it can recieve messages on channel 1. Note that this won't yet tell the computer to wait for messages that comes later
modem.open(1)
--now the loop
while true do
--Now we are going to tell the computer to wait until it recieves a message.
--to do this we use the function os.pullEvent() this lets the computer wait until an event occurs.
--an event can be a redstone signal, the pressing of an key or recieving a message which is what we want.
--by giving it some text we can have it wait for a specicic event in our case we let it wait until it recieves the event modem_message
--Note that even though it sets a lot of variables that we won't use they can't be removed as the order won't be what the function expects anymore
   event,side,senderChannel,replyChannel,message,distance=os.pullEvent("modem_message")
   print(message)
   --note that this code does not yet uses an monitor. You can probably work out how to do that yourself by reading the computercraft wiki :)
   --also note that this code does not need a sleep function that is because it already waits during the os.pullEvent.
end
 
  • Like
Reactions: efraina alvarez

efraina alvarez

New Member
Jul 29, 2019
10
0
0
Haven't tested them but I think they will work :)
The first piece of code is the one that will run on the computer near the spawner and the second one will run on the one with the monitor. I also added as much comments as I could think of to help you understand how the code works (and assuming the scripts work I let in a nice exercise for you. What? Did you really taught I would do all the work ;) (It is actually because I don't want to start minecraft right now and the code I write to work with monitors never work the first time as I always forget something :p ) )
Code:
--this is the one near the spawner. First I am going to set all the peripherals up.
--I am assuming the tank is to at the top and the modem is on the right
--Also note the use of "local" for now its not that importand but when you start to make functions they will become.
--Its also a good practice to use them when making variables or functions.
local spawner = peripheral.wrap("top")
local modem = peripheral.wrap("right")

--Now I am going to declare some variables that are used later. I do it now as that is generally good practice to declare your variables all in a nice place.
local blockInfo, message   =   nil --blockInfo will be used just as before. message will hold the text that will be displayed on the monitor.

--now lets make the loop. I am going to use a while loop.
--While loops need a value or statement and will loop for as long as that is true.
--you use loops like this while STATEMENT do
while true do --as I used true for the STATEMENT it will run forever
--first we are going to get the contents of the spawner
local blockInfo = spawner.getTankInfo()
--Now we are going to read what is inside the spawner
blockInfo=spawner.getTankInfo()
--Now we are going to generate the message that will end up on the monitor
--first we are going to clear the previous message.
message   =""
for key, value in pairs(blockInfo) do
   message= message.."This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name.."\n"
end
--the \n is a special character that will be displayed as a new line (like as if you pressed enter).
--Now that we have the message lets send it.
--1 is the channel that is used to send it.
--2 is normally used to let the reciever know what channel to use to reply.
--However I only set this as the function requires a value and it isn't acctually used.
--message is of course the variable that holds our message
modem.transmit(1,2,message) 
sleep(5) --this function let the loop wait for a bit. The number is the amount pf seconds before the code continous.
--it is recomended to have while loops sleep for a bit to prevent laggy situations especially as CC has protection against that and will in certain situations stop the program.
end --this is used to let lua know where the code stops that is part of the loop
The code to run on the computer with the monitor
Code:
--just like before I first wrap all the peripherals.
--Again I assume the modem is on the right and I will also asume that the monitor is on the left
local modem   =   peripheral.wrap("right")
local modem   =   peripheral.wrap("left")
--and once again I declare the variables that I am going to use
local event,side,senderChannel,replyChannel,message,distance
--now lets tell the computer that it can recieve messages on channel 1. Note that this won't yet tell the computer to wait for messages that comes later
modem.open(1)
--now the loop
while true do
--Now we are going to tell the computer to wait until it recieves a message.
--to do this we use the function os.pullEvent() this lets the computer wait until an event occurs.
--an event can be a redstone signal, the pressing of an key or recieving a message which is what we want.
--by giving it some text we can have it wait for a specicic event in our case we let it wait until it recieves the event modem_message
--Note that even though it sets a lot of variables that we won't use they can't be removed as the order won't be what the function expects anymore
   event,side,senderChannel,replyChannel,message,distance=os.pullEvent("modem_message")
   print(message)
   --note that this code does not yet uses an monitor. You can probably work out how to do that yourself by reading the computercraft wiki :)
   --also note that this code does not need a sleep function that is because it already waits during the os.pullEvent.
end

Awesome! I'll try this out when I have time and report back to you :] also, I do quite understand while loops, if else statements, etc, as I have an engeering class which is currently teaching us on coding with RobotC. Although I do not like how that program is set up. I also don't know whether or not it will be the same with this language, I'll be sure to read up on the Lua manual. Thanks again for everything.
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
Haven't tested them but I think they will work :)
The first piece of code is the one that will run on the computer near the spawner and the second one will run on the one with the monitor. I also added as much comments as I could think of to help you understand how the code works (and assuming the scripts work I let in a nice exercise for you. What? Did you really taught I would do all the work ;) (It is actually because I don't want to start minecraft right now and the code I write to work with monitors never work the first time as I always forget something :p ) )
Code:
--this is the one near the spawner. First I am going to set all the peripherals up.
--I am assuming the tank is to at the top and the modem is on the right
--Also note the use of "local" for now its not that importand but when you start to make functions they will become.
--Its also a good practice to use them when making variables or functions.
local spawner = peripheral.wrap("top")
local modem = peripheral.wrap("right")

--Now I am going to declare some variables that are used later. I do it now as that is generally good practice to declare your variables all in a nice place.
local blockInfo, message   =   nil --blockInfo will be used just as before. message will hold the text that will be displayed on the monitor.

--now lets make the loop. I am going to use a while loop.
--While loops need a value or statement and will loop for as long as that is true.
--you use loops like this while STATEMENT do
while true do --as I used true for the STATEMENT it will run forever
--first we are going to get the contents of the spawner
local blockInfo = spawner.getTankInfo()
--Now we are going to read what is inside the spawner
blockInfo=spawner.getTankInfo()
--Now we are going to generate the message that will end up on the monitor
--first we are going to clear the previous message.
message   =""
for key, value in pairs(blockInfo) do
   message= message.."This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of ".. value.contents.name.."\n"
end
--the \n is a special character that will be displayed as a new line (like as if you pressed enter).
--Now that we have the message lets send it.
--1 is the channel that is used to send it.
--2 is normally used to let the reciever know what channel to use to reply.
--However I only set this as the function requires a value and it isn't acctually used.
--message is of course the variable that holds our message
modem.transmit(1,2,message) 
sleep(5) --this function let the loop wait for a bit. The number is the amount pf seconds before the code continous.
--it is recomended to have while loops sleep for a bit to prevent laggy situations especially as CC has protection against that and will in certain situations stop the program.
end --this is used to let lua know where the code stops that is part of the loop
The code to run on the computer with the monitor
Code:
--just like before I first wrap all the peripherals.
--Again I assume the modem is on the right and I will also asume that the monitor is on the left
local modem   =   peripheral.wrap("right")
local modem   =   peripheral.wrap("left")
--and once again I declare the variables that I am going to use
local event,side,senderChannel,replyChannel,message,distance
--now lets tell the computer that it can recieve messages on channel 1. Note that this won't yet tell the computer to wait for messages that comes later
modem.open(1)
--now the loop
while true do
--Now we are going to tell the computer to wait until it recieves a message.
--to do this we use the function os.pullEvent() this lets the computer wait until an event occurs.
--an event can be a redstone signal, the pressing of an key or recieving a message which is what we want.
--by giving it some text we can have it wait for a specicic event in our case we let it wait until it recieves the event modem_message
--Note that even though it sets a lot of variables that we won't use they can't be removed as the order won't be what the function expects anymore
   event,side,senderChannel,replyChannel,message,distance=os.pullEvent("modem_message")
   print(message)
   --note that this code does not yet uses an monitor. You can probably work out how to do that yourself by reading the computercraft wiki :)
   --also note that this code does not need a sleep function that is because it already waits during the os.pullEvent.
end

Cool so I finished the programs and they both work.

Computer connected to Monitor
Code:
local mon  =   peripheral.wrap("right")
local modem   =   peripheral.wrap("left")
local event,side,senderChannel,replyChannel,message,distance
modem.open(1)
while true do
    event,side,senderChannel,replyChannel,message,distance=os.pullEvent("modem_message")
    mon.clear()
    mon.setCursorPos(1,1)
    mon.setTextColor(16384)
    mon.setTextScale(1)
    mon.write(message)
end
--pastebin get HLR56PgB T

Turtle connected to spawner
Code:
local spawner = peripheral.wrap("top")
local modem = peripheral.wrap("left")
local blockInfo, message   =   nil
    while true do
        local blockInfo = spawner.getTankInfo()
        blockInfo=spawner.getTankInfo()
        message   =""
        for key, value in pairs(blockInfo) do
        message= message.."This tank holds: "..value.capacity .. " MB: It has "..value.contents.amount .. " MB stored of "..             value.contents.name.."\n"
    end
    modem.transmit(1,2,message)
    sleep(5)
end
--pastebin get R0TBj8qT T

k... so LAST thing I promise :p So everything works, but because it's sending the message in only one line (1,1) it takes up too much space. I would like to split it so that i get
Code:
(1,1)This tank holds: 4000 MB:
(1,2)It has 2000 MB stored of mobessence

I tried using /n or "/n" but they don't seem to work, unless it's not for that. This would help me out when I start working more with Text and Buttons to make everything compact. Any advise would be great!
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
Make sure to use \n and not /n
Another thing you could do is some string "magic" and only send the values with a certain symbol to separate them and have the receiver put the message together getting the values it needs by splitting the received message.
 

efraina alvarez

New Member
Jul 29, 2019
10
0
0
Make sure to use \n and not /n
Another thing you could do is some string "magic" and only send the values with a certain symbol to separate them and have the receiver put the message together getting the values it needs by splitting the received message.

When I add a \n to this
Code:
message= message.."This tank holds: "..value.capacity .. " MB: \n It has "..value.contents.amount .. " MB stored of "..             value.contents.name.."\n"
all it does it do a small space gap, no new line
 

lenscas

Over-Achiever
Jul 31, 2013
2,015
1,801
248
Does the same thing happen when using print?
I suspect that the function you use to write to the monitor won't properly display newlines as you usually set at which lines you print.

If that is the case you have 3 options left
bigger monitor
smaller font size
Another thing you could do is some string "magic" and only send the values with a certain symbol to separate them and have the receiver put the message together getting the values it needs by splitting the received message.

Take a look at the string library it surely has what you need. (Alternative you could load an json api in and use that to send the data and receive it but I feel that that is kind of overkill)