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

Shop - Detect Itemname or Item-ID

Started by Mining_Pickaxe, 10 April 2015 - 06:48 PM
Mining_Pickaxe #1
Posted 10 April 2015 - 08:48 PM
Hey Guys, i have a question: Im coding a Shopsystem in CC. Now i need some Adminshops where people can sell their stuff to get money. I thought i can just use a computer where you log in and then put the Items in a Chest. Now i have the problem of detecting a item. I want to know what item it is so i can transfer the money to the account at the database server. A diamond is worth 8192 money, a iron ingot only 256. i know how to push the items but i dont know if there is a block or a API with that you can read the Item-ID from a Item. That you have some context, here are pastebins of the system:

T0gDxdDi for a register program to log into the Main Server

askx56NW for the program for the Users to transfer money etc.

T1UYjvFw for the program of the Database Server

rCDPMrDU for the Master Server

P7tBBadV for repeater(router)


Can somebody help me with that?
Give me a example how to detect the Item-ID or even just write a structure of the code :rolleyes:/> ?
I hope you can help me

MiningPickaxe


Ps: Sorry for my bad English, im german ^^ some parts of the codes (mostly print()) is also german, but i hope thats not a big problem :)/>
Lupus590 #2
Posted 10 April 2015 - 10:46 PM
use a turtle for the item detecting and use turtle.getItemDetail
Edited on 10 April 2015 - 08:47 PM
Mining_Pickaxe #3
Posted 11 April 2015 - 10:16 AM
So i could put a Turtle down and do it like this?

c = peripheral.wrap("bottom")
local data = turtle.getItemDetail
for a = 1,27 do
  c.pushItemIntoSlot("top",a,1,1)
 
-- And then? how can i extract the Type of the item and print it out?
-- Sorry, im realitvely new with CC
wieselkatze #4
Posted 11 April 2015 - 10:32 AM
turtle.getItemDetail() only works for items in the turtle's inventory - not external ones. pushItemIntoSlot really sounds like OpenPeripheral - that also probably is, what you're looking for.

Let's say you've got a chest connected to your wired network called "container_chest_0"; the following code would print out the display names of the items:


local stacks = peripheral.call( "container_chest_0", "getAllStacks" )

for k, v in pairs( stacks ) do
  print( "Slot " .. k .. ": " .. v.display_name )
end

Do note though that in later versions of OpenPeripheral the getAllStacks method got somewhat changed - means that there is no actual return of the item in the slot itself ( which will somewhat look like this:

{
  display_name = "Cobblestone",
  id = "minecraft:cobblestone",
}
) but instead a table with methods. To work with newer versions you could alter the code like this:


local stacks = peripheral.call( "container_chest_0", "getAllStacks" )

for k, v in pairs( stacks ) do
  v = type( v.all ) == "function" and v.all() or v --# If the newer version is installed it'll call the all function to get the actual item in the slot
  print( "Slot " .. k .. ": " .. v.display_name )
end

You should be able to use "openp/docs <yourchest or whatever>" on your computer though and get all the methods available for that chest.
Edited on 11 April 2015 - 08:35 AM
Mining_Pickaxe #5
Posted 11 April 2015 - 01:44 PM
Your Code works, i can see what item is in Slot <X> but how can i count them?

So if i put 32 Diamonds in Slot 1 and 42 Dirt in Slot 2 it only prints out the Slot and the type of the Item. How can it print out the amount of diamonds and dirt?
wieselkatze #6
Posted 11 April 2015 - 04:24 PM
The table with the information about the items does not only contain informations about the name - there are multiple other ones as enchantments, damage value etc..
To see how the tables look you could serialize them with textutils.serialize() - that'll print out the keys and the values.
The amount key, which you're looking for, should be qty - so v.qty would return the amount of items in that slot.
A relatively easy code to display all the amounts of items in the chest would for example be the following:


local stacks, items = peripheral.call( "container_chest_0", "getAllStacks" ), {}

for k, v in pairs( stacks ) do
    v = type( v.all ) == "function" and v.all() or v
    items[ v.display_name ] = items[ v.display_name ] and items[ v.display_name ] + v.qty or v.qty
end

for k, v in pairs( items ) do
    print( v .. " items of type " .. k .. " in that chest." )
end

No guarantee for it to work as I haven't tested it.
Mining_Pickaxe #7
Posted 11 April 2015 - 05:01 PM
It works beautifully! Thank you so much!

Maybe i will do a English version of the fully working Shop and Money System and post it in the Media-Forum for Download.
Mining_Pickaxe #8
Posted 12 April 2015 - 07:41 PM
Now im stuck… It sounds really easy (and i think its really easy too)
But when i want to check for Diamonds in that chest he skips the checking part (ln 24) and gets a error: attempt to perform arithmetic __mul on nil and nil. That means that both variables are not specified (nil) right?



m = peripheral.wrap("top")
side = "back"

local stacks, items = peripheral.call("container_chest_3", "getAllStacks"), {}
for k, v in pairs(stacks) do
  v = type(v.all) == "function" and v.all() or v
  items[v.display_name] = items[v.display_name] and items[v.display_name] + v.qty or v.qty
end
term.clear()
term.setCursorPos(1,1)
for k,v in pairs(items) do
  print("Es wurden "..v.." Items der Art "..k.." eingezahlt")
end

-- Ueberweisung
-- Menge berechnen
function getAmount()
if k==Diamond then
  local emcValue = 8192
else
  error("Keine Diamanten")
end

local amt = emcValue*v
end


function getTransferInfo()
-- term.clear()
-- term.setCursorPos(1,1)
 
  print("Bitte Accountname eingeben: ")
  account1 = read()
  print("Bitte wiederholen: ")
  account2 = read()
  print("Ihre Items einlegen. Wenn getan, ENTER druecken")
  read()
  getAmount()
  sendTransferRequest()
end
function sendTransferRequest()
  getPrefs()
  term.clear()
  term.setCursorPos(1,1)
  rednet.open(side)
  local newemail = "$SERVERMONEY$MONEY$TRANSFER"
    .."-Shop"
    .."-Shop"
    .."-"..account1
    .."-"..amt
  rednet.send(serverid, newemail)
  rednet.close(side)
  --printMenu()
end
function getPrefs()
  local file = io.open("/pref")
  if not file then
    print("Pref Datei nicht gefunden. Ueberpruefe ob du register gestartet hast")
    return false
  end
  local sidl = file:read()
  sidl = string.gsub(sidl, "routerid=", "")
  print(sidl)
  sidl = tonumber(sidl)
  if sidl==0 then
    print("Clientprefs nicht Initialisiert. Wende dich an Mining_Pickaxe")
    return false
  end
  serverid = sidl
  sidl = file:read()
  sidl = string.gsub(sidl, "side=", "")
  side = sidl
  return true
end
getPrefs()
getTransferInfo()


Maybe a really silly question, but im stuck at it.
wieselkatze #9
Posted 12 April 2015 - 11:12 PM
Okay - so line 24 is the following:

local amt = emcValue*v

Do note that 5 lines above it you localized your variable emcValue - means that it's only accessible in your if statement ( from line 18 tp 20 ). As it was never used before in that program, on line 24 it'll be nil of course.
Secondly v is localized to the previous for loop - meaning it's only accessible inbetween lines 5 and 8 or 11 and 13; do note though that these v's are different from each other as they're localized to their matching loop.
Also i think you did not exactly understand my code - it saves a key in the items table that is named after the item display name. As there could be multiple types of items in that chest, for each item it'll create a new key in that table.
For example if we have 32 Cobblestone and 132 Diamonds in that chest, the table would look like this:


{
  [ "Diamond" ] = 132,
  [ "Cobblestone" ] = 32,
}

That means that the different item amounts are stored in that table and you could, for example, access them with items.Diamond or items.Cobblestone .
I'd recommend you to create a table with all your EMC values stored in it and the matching item names as keys.
The code could then look like this:


local itemValues = {
	[ "Diamond" ] = 8192,
	[ "Iron Ingot" ] = 32,
	[ "Iron Ore" ] = 64,
}

local stacks, valueInChest = peripheral.call( "container_chest_3", "getAllStacks" ), 0

for k, v in pairs( stacks ) do
	v = type( v.all ) == "function" and v.all() or v
	
	if itemValues[ v.display_name ] then --# That item is registered in our database
		valueInChest = valueInChest + itemValues[ v.display_name ]*v.qty --# Consider the amount, of course
	else
		print( "Item called '" .. v.display_name .. "' is not yet registered in database." )
	end
end

Now you have your total item value stored in valueInChest - it'll not only work with diamonds, but also with all other kinds of items.
You could also set up a table with all the unknown items, so that they won't get pulled from the chestand the user may take them back.
As you're german, too, I could also offer you to send me a PM with your Skype username or a TeamSpeak address so we could meet up and discuss that whole thing in our native language ;)/>
Edited on 12 April 2015 - 09:15 PM
Mining_Pickaxe #10
Posted 12 April 2015 - 11:26 PM
Thats a good idea:) Thank you. It would be kinda easier for both :D/>
Bomb Bloke #11
Posted 12 April 2015 - 11:32 PM
Correct, they are. The reason is variable localisation - if you define a variable as local to an "if" block, for example, then as soon as that block ends the variable is discarded. The "counter" variables used in "for" loops are automatically made local to those loops, too.

Edit: Argh I left this tab open too long before typing into it. Oh well.
Edited on 12 April 2015 - 09:33 PM