Jump to content

Refresh container after item drop


Recommended Posts

Hey, i have the following code:

owner.components.container:DropItem(inst)

owner is lets say a chest. When i use DropItem, it drops the item as expected, but the chest interface is not updated and the item image remains. How can i refresh it without closing the inferface?

Link to comment
Share on other sites

Of course. The following contains the code in which the function is called. I cut out some really unnecessary stuff:

require "prefabutil"

local assets =
{
    Asset("ANIM", "anim/voidgem_build.zip"),
    Asset("ATLAS", "images/inventoryimages/voidgem_normal.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_normal.tex"),
    Asset("ATLAS", "images/inventoryimages/voidgem_refined.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_refined.tex"),
    Asset("ATLAS", "images/inventoryimages/voidgem_purified.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_purified.tex"),
}

local function buildvoidgem(version)
    local current_owner = nil
    local range_indicator = nil

    local PLACER_SCALE = 1

    local function CheckVoidAmount(inst)
        local amount = 0
        return amount
    end

    local function TryInsert(inst, item)
    end

    local function IsEntityACandidate(owner, candidate)
        return false
    end

    local function RangeIndicator(inst, active)
    end

    local function fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddNetwork()

        MakeInventoryPhysics(inst)

        inst.AnimState:SetBank("voidgem")
        inst.AnimState:SetBuild("voidgem_build")

        if version == "normal" then
            inst.AnimState:PlayAnimation("idle_normal", true)
        elseif version == "refined" then
            inst.AnimState:PlayAnimation("idle_refined", true)
        elseif version == "purified" then
            inst.AnimState:PlayAnimation("idle_purified", true)
        end

        inst:AddTag("molebait")
        inst:AddTag("voidresist")

        inst.entity:SetPristine()

        RangeIndicator(inst, true)

        if not TheWorld.ismastersim then
                return inst
        end

        inst:AddComponent("inventoryitem")

        if version == "normal" then
            inst.components.inventoryitem.atlasname = "images/inventoryimages/voidgem_normal.xml"
        elseif version == "refined" then
            inst.components.inventoryitem.atlasname = "images/inventoryimages/voidgem_refined.xml"
            inst:AddComponent("container")
            inst.components.container:WidgetSetup("voidgem_refined")
            inst.components.container.onopenfn = function ()
                inst.components.inventoryitem.cangoincontainer = false
            end
            inst.components.container.onclosefn = function()
                inst.components.inventoryitem.cangoincontainer = true
            end
        elseif version == "purified" then
            inst.components.inventoryitem.atlasname = "images/inventoryimages/voidgem_purified.xml"
            inst:AddComponent("container")
            inst.components.container:WidgetSetup("voidgem_purified")
            inst.components.container.onopenfn = function ()
                inst.components.inventoryitem.cangoincontainer = false
            end
            inst.components.container.onclosefn = function()
                inst.components.inventoryitem.cangoincontainer = true
            end
        end

        inst.components.inventoryitem:SetOnPutInInventoryFn(function(_, owner)
            if not owner:HasTag("voidresist") then
                RangeIndicator(current_owner, false)
                RangeIndicator(owner, true)
                current_owner = owner
            else
                owner.components.container:DropItem(inst) -- HERE!!!
            end
        end)

        inst.components.inventoryitem:SetOnDroppedFn(function(_, owner)
            RangeIndicator(current_owner, false)
            current_owner = nil
        end)

        inst:AddComponent("tradable")
        inst:AddComponent("inspectable")

        MakeHauntableLaunchAndSmash(inst)
        return inst
    end
    return Prefab("voidgem_"..version, fn, assets)
end

return buildvoidgem("normal"),
    buildvoidgem("refined"),
    buildvoidgem("purified")

The widget setup gets overriden in the modmain.lua, where i define my own container:

local RECIPETABS = GLOBAL.RECIPETABS
local Vector3 = GLOBAL.Vector3
local TECH = GLOBAL.TECH
local require = GLOBAL.require
containers = require "containers"

Assets =
{
    Asset("ATLAS", "images/inventoryimages/voidgem_normal.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_normal.tex"),
    Asset("ATLAS", "images/inventoryimages/voidgem_refined.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_refined.tex"),
    Asset("ATLAS", "images/inventoryimages/voidgem_purified.xml"),
    Asset("IMAGE", "images/inventoryimages/voidgem_purified.tex"),
    Asset("ANIM", "anim/ui_chest_3x3.zip"),
}

PrefabFiles = 
{
    "voidgem",
}

-- Container --

local params = {}

local old_widgetsetup = containers.widgetsetup
function containers.widgetsetup(container, prefab, ...)
    local t = params[prefab or container.inst.prefab]
    if t ~= nil then
        for k, v in pairs(t) do
            container[k] = v
        end
    container:SetNumSlots(container.widget.slotpos ~= nil and #container.widget.slotpos or 0)
    else
        old_widgetsetup(container, prefab, ...)
    end
end

local function makeVoidGem()
    container = {
        widget =
        {
            slotpos = {},
            animbank = "ui_chest_3x3",
            animbuild = "ui_chest_3x3",
            pos = Vector3(0, 200, 0),
            side_align_tip = 160,
        },
        acceptsstacks = false,
        type = "chest",
    }

    for y = 2, 0, -1 do
        for x = 0, 2 do
            table.insert(container.widget.slotpos, Vector3(80 * x - 80 * 2 + 80, 80 * y - 80 * 2 + 80, 0))
        end
    end

    return container
end

params.voidgem_refined = makeVoidGem()
params.voidgem_purified = makeVoidGem()

for k, v in pairs(params) do
    containers.MAXITEMSLOTS = math.max(containers.MAXITEMSLOTS, v.widget.slotpos ~= nil and #v.widget.slotpos or 0)
end

AddRecipe("voidgem_normal", {Ingredient("purplegem", 1), Ingredient("nightmarefuel", 2)}, RECIPETABS.MAGIC, TECH.SCIENCE_ONE, nil, nil, nil, nil, nil, "images/inventoryimages/voidgem_normal.xml")
AddRecipe("voidgem_refined", {Ingredient("voidgem_normal", 1, "images/inventoryimages/voidgem_normal.xml", "voidgem_normal.tex"), Ingredient("goldnugget", 20)}, RECIPETABS.MAGIC, TECH.SCIENCE_ONE, nil, nil, nil, nil, nil, "images/inventoryimages/voidgem_refined.xml")
AddRecipe("voidgem_purified", {Ingredient("voidgem_normal", 1, "images/inventoryimages/voidgem_normal.xml", "voidgem_normal.tex"), Ingredient("opalpreciousgem", 1)}, RECIPETABS.MAGIC, TECH.SCIENCE_ONE, nil, nil, nil, nil, nil, "images/inventoryimages/voidgem_purified.xml")

 

Link to comment
Share on other sites

I tried to look at the function in game code and i found it used this way

        victim.components.container:DropItem(item)

(for thief code, like frog for example)

                    --inst.components.container:DropItem(item)

(in unused functions in the code).

But you use

 owner.components.container:DropItem(inst)

So what are you trying to drop ? The content of the container ? The container itself ?

Maybe you need to specify somewhere that you try to drop one item ?

 

Since i'm not sure about what you try to do and how your code is working i could totally be wrong.

Edited by Lumina
Link to comment
Share on other sites

inst is the item to which this code belongs. A void gem. It checks if it is placed inside a container and then tells the container in which it was placed to drop it. owner is the container in which the gem was placed. It is also strange that the code seems to work just fine for guests, but not the host of a server.

Link to comment
Share on other sites

I will take a look at the snippet you posted but I just wanted to state something:

The name of the variable doesn't matter. You could call it player if you want even though it has nothing to do with the player (That would just be confusing). That's why I asked for more details.

Link to comment
Share on other sites

OK, I just had time to look at what you posted.

So dont do that in general:

inst.components.container.onclosefn = function()
	inst.components.inventoryitem.cangoincontainer = true
end

This function takes an argument, even though here technically it doesn't matter so much it is a good idea to not take bad habits

inst.components.container.onclosefn = function(inst_)
	inst_.components.inventoryitem.cangoincontainer = true
end

 

Then for your problem, what happens is that you set the InventoryItem.onputininventoryfn

which is called inside InventoryItem:OnPutInInventory(owner)

which is called by a container when it receives an object in Container:GiveItem(item, slot, src_pos, drop_on_fail)

So your function will be called and DropItem will be executed, spawning the item and removing it from the container.

But right after that, the GiveItem function continues its execution and the next line is

self.inst:PushEvent("itemget", { slot = in_slot, item = item, src_pos = src_pos })

which triggers a function in the replica.container

        self._onitemget = function(inst, data)
            self.classified:SetSlotItem(data.slot, data.item, data.src_pos)
            if self.issidewidget and
                inst.components.inventoryitem.owner ~= nil and
                inst.components.inventoryitem.owner.HUD ~= nil then
                inst.components.inventoryitem.owner:PushEvent("refreshcrafting")
            end
        end

self.classified:SetSlotItem(data.slot, data.item, data.src_pos)

will set the item in the container to the item you just dropped and effectively duplicating the item.

 

BTW: I am almost certain that your code currently, even fixed to account for the issues I pointed out, will only work for the host. The client is not receiving the necessary information in the way it is written right now.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...