ID:1528019
 
(See the best response by Ter13.)
Problem description:
So, I have been using a grid inventory system, and have ran into some issues as when I have moved onto the crafting segment. The crafting system consists of a 3x3 grid, where-as the user can move and relocate the objects through the mouse dragging and dropping. The issue I have ran into, is that I do not know how to delete, or remove objects inside of the crafting grid once they have activated the crafting command connected to a button on the interface. Furthermore, I do not know how to reference to specific objects inside of screen locations.
I understand the method I am using for the development of a crafting system may be silly, or time consuming, but it is what I understand. However, if there is an easier/more efficient way to do this, please elaborate.

Code:
obj

verb
CraftCheck1234abcd()
set hidden = 1


usr << "[src] [usr]"

usr << "Crafting Still being Implimented :D "
if(usr.cid1_1==58)
if(usr.cid1_2==0)
if(usr.cid1_3==0)
if(usr.cid2_1==58)
if(usr.cid2_2==0)
if(usr.cid2_3==0)
if(usr.cid3_1==58)
if(usr.cid3_2==0)
if(usr.cid3_3==0)
//The "cid" variables represent the different IDs set up for materials, in the different locations.
del (screen_loc==("Inventory.Crafting"))



Dear god what.

One thing you can do to identify things is the fact images can have tags or names. But you shouldn't be using the images to identify what's in the spot you should be somehow storing things into a list of the user.

You could force placement evne if the list is empty.

Also those if()'s are silly not only for the fact that can be indented and use &&'s but the fact it's a bad method to identify recipes.
Thanks. I'm going to scrap it, and look up more on lists. I'm still learning (Obviously) so the help is appreciated.
Best response
Protip:

1) Associate recipes by id arrangement serialized into a text string.

2) Place recipes in a global associative list

3) Grab component information from crafting area, compile into serialized text string, check if string exists in associative list as a key. Reference recipe from global associative list value.

#define WOOD_ID 1
#define COAL_ID 2
#define TORCH_ID 3
#define STEEL_ID 4
#define IRON_ID 5
#define IRON_ARMOR 6

obj
item
var
material_id = 0
wood
material_id = WOOD_ID
coal
material_id = COAL_ID
torch
material_id = TORCH_ID
steel_bar
material_id = STEEL_ID
iron_bar
material_id = IRON_ID
iron_armor
material_id = IRON_ARMOR

world
New()
build_recipes()

var
list/recipes
proc
build_recipes()
//define new recipes and add them to the global list here.
new/recipe(list("hands","workbench"),list(list(COAL_ID,WOOD_ID)),/obj/item/torch)
new/recipe(list("hands","workbench"),list(list(COAL_ID,0),list(0,STEEL_ID)),/obj/item/flint_steel)
new/recipe("workbench",list(list(IRON_ID,IRON_ID,IRON_ID),list(0,IRON_ID,IRON_ID),list(IRON_ID,IRON_ID,IRON_ID),/obj/item/iron_armor)

recipe
var
list/shape
result
create_x
create_y

New(workstation,list/shape=null,result=null)
if(shape)
src.shape = shape
if(result)
src.result = result

var/id = ""
var/list/l1 = src.shape
var/list/l2
var/x
var/y
var/separator = ""

for(x=1;x<=l1.len;x++)
l2 = l1[x]
for(y=1;y<=l2.len;y++)
id = "[id][separator][l2[y]]"
separator = ","
separator = ";"
if(istype(workstation,/list))
for(var/w in workstation)
global.recipes[w][id] = src
else
global.recipes[workstation][id] = src
proc
craft(mob/player/p,workshop/w)
w.clear()
w.create(result,create_x,create_y)

workshop
var
list/users = list()
workshop_type
list/table
width = 3
height = 3
screen_x = 1
screen_y = 1

New(t,w,h,sx,sy)
workshop_type = t
width = w
height = h
var/l[w][h]
table = l
screen_x = sx
screen_y = sy
proc
clear()
var/obj/item/i
for(var/x=1;x<=width;x++)
for(var/y=1;y<=width;y++)
i = table[x][y]
if(i)
del i

create(result_type,x,y)
var/obj/item/i = new result_type()
table[x][y] = i
//adjust this:
i.screen_loc = "[screen_x + x],[screen_y + y]"
for(var/mob/m in users)
m.client.screen += i

begin_use(mob/m)
users += m

end_use(mob/m)
users -= m

get_recipe()
var/start_x = width+1
var/start_y = height+1
var/end_x = 0
var/end_y = 0
var/x
var/y
//find the dimensions of the items on the table
for(x=1;x<=width;x++)
for(y=1;y<=width;y++)
if(table[x][y])
if(y<start_y)
start_y = y
else if(y>end_y)
end_y = y

if(x<start_x)
start_x = x
else if(x>end_x)
end_x = x

//provided we found an item, serialize the recipe
if(start_x<=width || start_y<=height || end_x>=1 || end_y>=1)
var/separator = null
var/recipe = ""
var/obj/item/i
for(x=start_x;x<=end_x;x++)
for(y=start_y;y<=end_y;y++)
i = table[x][y]
if(i)
recipe = "[recipe][separator][i.material_id]"
else
recipe = "[recipe][separator]0"
separator = ","
separator = ";"
//we now have our complete serialized recipe arrangement
if(recipe in global.recipes[workstation_type])
return global.recipes[workstation_type][recipe]


The above is more or less how Minecraft handles it. I wrote a mod a while back that hooked into Minecraft's recipe definition system and allowed me to author new recipes on the fly while the game was running using simple JSON. So... That's how I know about this stuff.

Anyway, the trick is to set up your recipes so that you can serialize any arrangement of items in a way that will generate a UNIQUE id for items. In my case, it involves some trickery given that I don't want to have to have a torch be placed in slots 1,1, and 1,2 in order to be made. I want to be able to define the shape of the torch regardless of where it goes in the menu, provided the coal is above the wood. Hence, why I had to write that tricky bit of code involving finding the maximum and minimum dimensions of the table's item list.

Another thing to note: To keep recipe searching down, we store the recipes by the workbench that they use. Technically speaking, workbenches all use the same code, they just have a different set of recipes available to them, and can be different sizes. This way, we can have a super-secret demon-forge somewhere in the world where you can make special items ala Terraria.