Using composition, is relying on pcall considered wrong?

We are making a game where depending on the components you add to an object you will get one behaviour or another. Nothing fancy nor new here, that’s basically composition, right?

But in this situation, one usually does or does not something depending on whether a component is present or not. For instance, I might try to pick an object up, which I can only do if it is an ‘item’ - and I know it is an item if the item component is there. I could do it in a miriad other ways, but this one is simple and clean, usually.

Hence pcall. I don’t know if the thing I’m interacting with is an item or just an obstacle, so I can use pcall to try fetching the required component and its item_id, like this:

local function pick_object(self, object_id)
    local success, item_id = pcall(go.get, msg.url(nil, object_id, "item"), "item_id")
    if success then
        self.carried_object_id = object_id
        self.carried_item_id = item_id
        local item_weight = item_data[item_id].weight
        local speed_modifier = math.min(10 / item_weight, 1)
        go.set("#tile_physics", "speed_modifier", speed_modifier)
        go.set_parent(object_id, go.get_id())
        go.set_position(get_carried_object_position(), self.carried_object_id )
        local url = msg.url(nil, object_id, "tile_physics")
        msg.post(url, "disable_physics")
    end
end

Seems perfectly fine to me, but as I’m new to LUA I’m not sure if this is bad code smell. It’s certainly useful! Would love to read opinions.

So that’s just items and obstacles. What if you have hundreds of object types? Actually you can manage object data in a lua table. This is just another way to consider… Using pcall is still totally fine to me

Well, that’s precisely the thing, isn’t it? If a certain function needs a specific component from an object it’s interacting with, I can use pcall to check if it’s there, otherwise ignore it. You can create objects types by composing these components (true enough, I should create ‘pickable_component’ instead, though)

What do you mean with managing object data in a lua table? Indeed, that pcall is our first step. It’s an item, we can interact with it. Now, can we pick it up? For that each item has its own attributes, like

items[hashed.wheel] = {
    weight = 25,
    is_pickable = true
}
items[hashed.zip_pole] = {
    is_pickable = false
}
items[hashed.can] = {
    weight = 1,
    is_pickable = true
}

I think maybe part of the question is asking if pcall() is safe to rely on in production code? The answer is yes, it is safe. It is not stripped like assert() or something like that. Actually I’m pretty sure pcall() is Lua’s only method of stopping the propagation of errors, so it’s similar to using a try-catch block in C++ for example.

2 Likes

Oh, I didn’t even think of that, glad to know! Thanks!

1 Like