Jump to content

Recommended Posts

Hi, I'm trying to fix this mod but can't seem to make it work. It's a disposal to get rid of junk. While it functions for me as a host, it crashes others and displays the message: "Attempt to index field 'container' (a nil value)"

which can be seen here: http://prnt.sc/c6nwbr

Does anyone know how I can fix this error?

All help is greatly appreciated. Thank you.

---------------------------------------------------------------------------------

params.disposal_box =
{
    widget =
    {
        slotpos =
        {
            _G.Vector3(0, 64 + 32 + 8 + 4, 0), 
            _G.Vector3(0, 32 + 4, 0),
            _G.Vector3(0, -(32 + 4), 0), 
            _G.Vector3(0, -(64 + 32 + 8 + 4), 0),
        },
        animbank = "ui_cookpot_1x4",
        animbuild = "ui_cookpot_1x4",
        pos = _G.Vector3(200, 0, 0),
        side_align_tip = 100,
        buttoninfo =
        {
            text = "Dispose",
            position = _G.Vector3(0, -165, 0),
        }
    },    
    type = "cooker",
}

function params.disposal_box.itemtestfn(container, item, slot)
        if item.prefab == "lucy" or           
           item:HasTag("irreplaceable")
        then    
           return false    
        end    
           return true        
end

function params.disposal_box.widget.buttoninfo.fn(inst)
        inst.components.container:DestroyContents()
        inst.SoundEmitter:PlaySound("dontstarve/common/destroy_stone")
end

function params.disposal_box.widget.buttoninfo.validfn(inst)
        if inst.components.container:IsEmpty()
        then
            return false
        end
            return true
end

On 8/17/2016 at 10:41 AM, Farxodor said:

What do you have at line 342 in your modmain? That's the line throwing the error. Look at that line and see if you've made a mistake somewhere.

Here are some screenshots:

https://gyazo.com/04b6e5c7e5d19618523acaed817a8260

and

https://gyazo.com/1758d7923f566e4c42f923cc10ef4eb8

The lines causing the crash for others are:

inst.components.container:DestroyContents()

and 

inst.components.container:IsEmpty()

I feel like the problem has something to do with me not putting "replica" in there somewhere but I'm not really sure if that is the problem or how to fix it myself.

Like I said the disposal structure works for me perfectly, but when others try to press the button "dispose" it causes them to crash and they get an error saying:

Attempt to index field 'container' (a nil value)

I still have not resolved this, so any help is much appreciated.

 

Edited by Luis95R

Components exist on the server side, usually. And the widget code is run by the clients, so no component means crash, because the components table is a nil value.

The container component is a replicatable component, which means that when the host adds the container component to something, clients will get the container replica on the prefab they see.

We can use the GetItems method of the container replica (since it doesn't have a IsEmpty).

When the widget button is clicked, you perform an action if you are the host. If you are a client, you send a RPC with information to perform the action.

local ACTIONS = GLOBAL.ACTIONS
local BufferedAction = GLOBAL.BufferedAction
local RPC = GLOBAL.RPC
local SendRPCToServer = GLOBAL.SendRPCToServer

local function disposefn(act)
	local inst = act.target
	if inst ~= nil then
		if inst.components.container ~= nil then
			inst.components.container:DestroyContents()
		end
		if inst.SoundEmitter ~= nil then
			inst.SoundEmitter:PlaySound("dontstarve/common/destroy_stone")
		end
	end
	return true
end
AddAction("BOXDISPOSE", "Dispose", disposefn)

function params.disposal_box.widget.buttoninfo.fn(inst)
    if inst.components.container ~= nil then
        BufferedAction(inst.components.container.opener, inst, ACTIONS.BOXDISPOSE):Do()
    elseif inst.replica.container ~= nil then
        SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.BOXDISPOSE.code, inst, ACTIONS.BOXDISPOSE.mod_name)
    end
end

function params.disposal_box.widget.buttoninfo.validfn(inst)
	if inst.replica.container ~= nil then
		local items = inst.replica.container:GetItems()
		if #items > 0 then
			return true
		end
	end
    return false
end

function params.disposal_box.itemtestfn(container, item, slot)
	if item.prefab == "lucy" or item:HasTag("irreplaceable") then    
		return false    
	end    
	return true    
end

 

Omg thank you so much DarkXero!

It was starting to become really frustrating for me. I also appreciate the information on how things are suppose to work.

One question though; is it possible to make it so that GetItems() is able to check every slot to see if there is something in there? It currently only detects items in the first slot. If I put 1 item in any other slot it doesn't count as if there is an item in there. If it's not possible or too complicated then don't sweat it. I'm just curious if it's possible or not.

function params.disposal_box.widget.buttoninfo.validfn(inst)
	if inst.replica.container ~= nil then
		local container = inst.replica.container
		local _numslots = container:GetNumSlots()
		for i = 1, _numslots, 1 do
			local iteminslot = container:GetItemInSlot(i)
			if iteminslot ~= nil then
				return true
			end
		end
	end
	return false
end

Try this.

GetItems() returns what GetItems() wants.

It is defined in the replica, but how it works is defined in the container_classified prefab.

Basically a prefab attached to containers that holds network info, don't look too hard into it.

Edited by DarkXero
14 hours ago, DarkXero said:

function params.disposal_box.widget.buttoninfo.validfn(inst)
	if inst.replica.container ~= nil then
		local container = inst.replica.container
		local _numslots = container:GetNumSlots()
		for i = 1, _numslots, 1 do
			local iteminslot = container:GetItemInSlot(i)
			if iteminslot ~= nil then
				return true
			end
		end
	end
	return false
end

Try this.

GetItems() returns what GetItems() wants.

It is defined in the replica, but how it works is defined in the container_classified prefab.

Basically a prefab attached to containers that holds network info, don't look too hard into it.

This worked perfectly. Thanks again for your help. You're amazing!

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
×
  • Create New...