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

help with me bridge

Started by ytwist, 13 January 2016 - 08:12 PM
ytwist #1
Posted 13 January 2016 - 09:12 PM
hi, so i am trying to make a script that gives me items when i say in chat: give (item name),

i could type them all 1 by 1 out but is there a way of making a list like: cobblestone = minecraft:cobblestone, dirt = minecraft:dirt, etc.
then say: give (cobblestone) and make it look through the list to see what code cobblestone is?

i am using peripherals++: me bridge & chatbox btw

thanks for replies and help !
Bomb Bloke #2
Posted 14 January 2016 - 12:38 AM
Sure, make a translation table:

local translate = {["cobblestone"] = "minecraft:cobblestone", ["dirt"] = "minecraft:dirt", etc}

print("Type something:")

local input = read()

input = translate[input] or input  -- if translate[input] exists, input gets set to that, otherwise it stays the same.

print(input)
ytwist #3
Posted 14 January 2016 - 08:42 PM
thanks for the reply, that helped me out alot allready.
seems to be working like this but i'd like to have something that tells it how much items i want instead of typing it in manually

local chatbox = peripheral.wrap("top")
local bridge = peripheral.wrap("left")

function listen()

event, player, message = os.pullEvent("chat")

local translate = {
["get stone"] = "minecraft:stone",
["get dirt"] = "minecraft:dirt" }

if message >= "get" then
input = message
input = translate[input] or input
bridge.retrieve((input), 1, "east") – 1 = amount
end

end

while true do
listen()
sleep(0.1)
end
Bomb Bloke #4
Posted 15 January 2016 - 01:47 AM
if message >= "get" then

This line here isn't doing what you think - it's checking whether message comes first alphabetically or not. If you wanted to compare lengths, you might do:

if #message >= 3 then

Anyway, to parse more complex messages, you'd want to break them up into words. This can be done like so:

local words = {}
for word in message:gmatch("%S+") do words[#words + 1] = word end

Let's say the message was "get stone 3" - words[1] would be "get", words[2] would be "stone", and words[3] would be "3".

So now we can do stuff like:

if words[1] == "get" then
  local item = translate[words[2]] or words[2]
  local amount = tonumber(words[3]) or 1

  bridge.retrieve(item, amount, "east")
end
ytwist #5
Posted 15 January 2016 - 03:10 AM
if message >= "get" then

This line here isn't doing what you think - it's checking whether message comes first alphabetically or not. If you wanted to compare lengths, you might do:

if #message >= 3 then

Anyway, to parse more complex messages, you'd want to break them up into words. This can be done like so:

local words = {}
for word in message:gmatch("%S+") do words[#words + 1] = word end

Let's say the message was "get stone 3" - words[1] would be "get", words[2] would be "stone", and words[3] would be "3".

So now we can do stuff like:

if words[1] == "get" then
  local item = translate[words[2]] or words[2]
  local amount = tonumber(words[3]) or 1

  bridge.retrieve(item, amount, "east")
end

Okay, thanks alot, again.
if it's not too much to ask i'd like to ask one more thing,
the bridge has a listAll(), it returns

{
amount = "(amount)"
meta = "(meta)"
display name = "Stone"
name = "minecraft:stone"
}

i was wondering if i could use this to make the translation table instead of adding all items i have in the AE system?
Bomb Bloke #6
Posted 15 January 2016 - 05:00 AM
Yes, most likely. What's it return if there's more than one item in the system?
ytwist #7
Posted 15 January 2016 - 05:13 AM
Yes, most likely. What's it return if there's more than one item in the system?

{
 { 
amount = "(amount)"
meta = "(meta)"
display name = "stone"
name = "minecraft:stone"
}
{ 
amount = "(amount)"
meta = "(meta)"
display name = "dirt"
name = "minecraft:dirt"
} 
etc 
}
Bomb Bloke #8
Posted 15 January 2016 - 08:26 AM
local translate = {}

for num, obj in ipairs( bridge.listAll() ) do                 -- For each index in the bridge.listAll() table, 
  translate[ obj["display name"]:lower() ] = obj["name"]      -- Get the "display name" and "name" keys from the subtables, stick them in the "translate" table.
end

Sticking :lower() after a string converts it to lowercase. This means that you can later do:

local item = translate[words[2]:lower()] or words[2]

… and it won't matter which case the message was typed in, it'll always match what's in the "translate" table.
ytwist #9
Posted 15 January 2016 - 09:38 PM
local translate = {}

for num, obj in ipairs( bridge.listAll() ) do				 -- For each index in the bridge.listAll() table,
  translate[ obj["display name"]:lower() ] = obj["name"]	  -- Get the "display name" and "name" keys from the subtables, stick them in the "translate" table.
end

Sticking :lower() after a string converts it to lowercase. This means that you can later do:

local item = translate[words[2]:lower()] or words[2]

… and it won't matter which case the message was typed in, it'll always match what's in the "translate" table.

seems to be a problem when i call for double named items, lets say: sticky piston.
probably because it thinks sticky is words[2] and piston is words[3](the amount), right?
give me the error:

Java Exception Thrown:
java.lang.ArrayIndexOutOfBoundsException : 1

sorry for the bother, normally i would just look it up but i couldn't find anything about the ME bridge.
anything i could help you out with? like rate you or something?
Thanks again for all the help tho !
Edited on 15 January 2016 - 10:00 PM
Bomb Bloke #10
Posted 16 January 2016 - 01:42 AM
The error is coming from the peripheral's code - the author is failing to handle a problem correctly. I'd guess that problem is you trying to get an item that isn't in the system. Dunno.

There are a number of ways to deal with the multiword item name thing.

Maybe the simplest one is to switch to a "get <amount> <item>" format, where <amount> is optional and <item> is taken to be all remaining words in the message.

First we need to determine if the second word of the message is a number or not. Then we concatenate whatever's left:

if words[1] == "get" then
  local amount = tonumber( words[2] )  -- Either returns a number, or if words[2] doesn't represent one, nil.

  local item
  if amount then  -- If amount is non-nil, then...
    item = table.concat( words, " ", 3 )

  else  -- If words[2] didn't represent a number, then...
    item = table.concat( words, " ", 2 )
    amount = 1

  end

  item = translate[ item:lower() ] or item

  bridge.retrieve(item, amount, "east")
end

So you might issue a command like "get stone", or "get 10 dirt", or "get 4 sticky piston".

See here regarding table.concat().
ytwist #11
Posted 16 January 2016 - 04:21 AM
The error is coming from the peripheral's code - the author is failing to handle a problem correctly. I'd guess that problem is you trying to get an item that isn't in the system. Dunno.

There are a number of ways to deal with the multiword item name thing.

Maybe the simplest one is to switch to a "get <amount> <item>" format, where <amount> is optional and <item> is taken to be all remaining words in the message.

First we need to determine if the second word of the message is a number or not. Then we concatenate whatever's left:

if words[1] == "get" then
  local amount = tonumber( words[2] )  -- Either returns a number, or if words[2] doesn't represent one, nil.

  local item
  if amount then  -- If amount is non-nil, then...
	item = table.concat( words, " ", 3 )

  else  -- If words[2] didn't represent a number, then...
	item = table.concat( words, " ", 2 )
	amount = 1

  end

  item = translate[ item:lower() ] or item

  bridge.retrieve(item, amount, "east")
end

So you might issue a command like "get stone", or "get 10 dirt", or "get 4 sticky piston".

See here regarding table.concat().

Yes, you we're right about the error, if the item i request is not in the system it crashes the program.
Is there any way to counter that by sending a message that the item is not in the system ?
if (item) is not in bridge.listAll() then
  chatbox.say("Item not in system")
end
I got it setup that startup runs my program, sleeps for couple of seconds and reboots, which works fine.
But it would be handy if it notifies me that im out of that item and or stops it from crashing the program.
Edited on 16 January 2016 - 03:21 AM