Jump to content

replicas... how to add itemtestfn to custom container?


Recommended Posts

Hi hate replica's, never know how to deal with them :D

I have a custom container (with that component) with an itemtestfn to decide what it can contain. It works for server, but clients have some problems. It looks like the item was accepted by the container, but this is fixed from the server shortly after.
So I guess I have to put this itemtestfn also into the replica? But how? replica does not exist on server, and I  cant add component container for clients. Should I add container_replica as component? Or how does it work?

And will the replcia itemtestfn only work with information available at clientside? So this function wont be able to see components of items?

edit:
ah I thought I have to do "inst.components.container_replica..." but it seems it is inst.replica.container...", will see if I can add the testfn this way and then see what options the replicas of other components have to test the titem proberly... will first try to simply replace the word "components" with "replica" and hope that it will work :D if it does not, I will look at the replica files. ... seems to work now...

hmm... it looks better now, but few items can still pass the funciton although they should not. No clue why =(


But in general:
How do I know in advance if something requires replica stuff or not? I can't test every single detail for client, I would like to know in advance if I need special replica code for something.

Edited by Serpens
Link to comment
Share on other sites

Can you post your code?  You shouldn't need to use replicas for the itemtestfn.  Are you doing this in your containers lua file?  I personally only ever done it in the modmain.lua.  An example of one of my containers itemtestfn looks like

function params.refinechest.itemtestfn(container, item, slot)

	return refinerecipe[item.prefab] and (slot == 1 or slot == 2 and container.inst.on)
end

 

Link to comment
Share on other sites

1 hour ago, Wolf_EX said:

Can you post your code?  You shouldn't need to use replicas for the itemtestfn.  Are you doing this in your containers lua file?  I personally only ever done it in the modmain.lua.  An example of one of my containers itemtestfn looks like


function params.refinechest.itemtestfn(container, item, slot)

	return refinerecipe[item.prefab] and (slot == 1 or slot == 2 and container.inst.on)
end

 

I saw this "params".... code within the containers.lua from the game, but was not sure how this works, I simply did within AddPrefabPostInit from an existing prefab:

            inst:AddComponent("container")
            inst.components.container.itemtestfn = ContainerShouldAcceptItem
            inst.components.container.onopenfn = ContainerOnOpen
            inst.components.container.onclosefn = ContainerOnClose


-- and the function looks like this:
local function ContainerShouldAcceptItem(self,item, slot)
    if item.components.equippable~=nil then
        return true
    end
    return false
end

So I have to use this params structure? Where and how?

Edited by Serpens
Link to comment
Share on other sites

This is the relevant code from my modmain.lua of my container mod

 

local require = GLOBAL.require
local Vector3 = GLOBAL.Vector3
local containers = require "containers"
local refinerecipe = require "refinerecipe"

Assets = {

	Asset("ANIM", "anim/ui_chest_3x1.zip"),
}

local params = {}

--refine chest
params.refinechest = 
{
	widget = 
	{
		slotpos =
		{
			Vector3(-72, 0, 0),
			Vector3(72, 0, 0), 
		},
		animbank = "ui_chest_3x1",
        animbuild = "ui_chest_3x1",
		pos = GLOBAL.Vector3(0, 200, 0),
        side_align_tip = 160,

	},
	type = "chest",
}

function params.refinechest.itemtestfn(container, item, slot)

	return refinerecipe[item.prefab] and (slot == 1 or slot == 2 and container.inst.on)
end

containers.MAXITEMSLOTS = math.max(containers.MAXITEMSLOTS, params.refinechest.widget.slotpos ~= nil and #params.refinechest.widget.slotpos or 0)

local containers_widgetsetup_base = containers.widgetsetup
function containers.widgetsetup(container, prefab, data)
    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
        containers_widgetsetup_base(container, prefab, data)
    end
end

You add this widget to your container with

inst.components.container:WidgetSetup("refinechest")

I'm pretty sure you can do all this in your containers lua file but most people do it in the modmain.  If you want to look at the code from the mod it's https://steamcommunity.com/sharedfiles/filedetails/?id=1567856396

 

Edited by Wolf_EX
Link to comment
Share on other sites

ok,thanks.

Why do you overwrite the containers.widget_setup function? It looks like it does exactly the same, so I see no reason to overwrite it?
Ah.. I think you do it to get the "params" into it, right? I think you should remoove it and use the "data" value instead.
And instead of doing:

inst.components.container:WidgetSetup("refinechest")

you do:

inst.components.container:WidgetSetup("refinechest",params.refinechest)


But I ran into an issue with my code, I simply want the chest/shadowchester Widget with a custom itemtestfn. So I copied most of this from containers.lua (there seems to be no other way than copying, since params are local ...)


My code:

Assets = {
    Asset("ANIM", "anim/ui_chester_shadow_3x4.zip"),
}
local containers = GLOBAL.require "containers"
local containerparams = {}
containerparams.shadowBMduelist = {
    widget =
    {
        slotpos = {},
        animbank = "ui_chester_shadow_3x4",
        animbuild = "ui_chester_shadow_3x4",
        pos = GLOBAL.Vector3(0, 220, 0),
        side_align_tip = 160,
        itemtestfn = ContainerShouldAcceptItem,
    },
    type = "chest",
}
for y = 2.5, -0.5, -1 do
    for x = 0, 2 do
        table.insert(containerparams.shadowBMduelist.widget.slotpos, GLOBAL.Vector3(75 * x - 75 * 2 + 75, 75 * y - 75 * 2 + 75, 0))
    end
end
containers.MAXITEMSLOTS = math.max(containers.MAXITEMSLOTS, containerparams.shadowBMduelist.widget.slotpos ~= nil and #containerparams.shadowBMduelist.widget.slotpos or 0)

AddPrefabPostInit("shadowduelist",function(inst)
    inst:AddComponent("container")
    inst.components.container.acceptsstacks = true
    inst.components.container.onopenfn = ContainerOnOpen
    inst.components.container.onclosefn = ContainerOnClose
    inst.components.container:WidgetSetup("shadowBMduelist",containerparams.shadowBMduelist)
end)

but I get error message:
 [string "scripts/components/container.lua"]:84: assertion failed!
this line 84 is:
assert(numslots >= self.numslots)
so sth with numslots is wrong, but I see nothing regarding numslots within containers.lua, why do they work without defining them?


edit:
if I do the same with the chester widget, everything works fine.
And it is the addtion of slotpos with those for loops that is the problem. Seems for shadow chester they aren't working, while for chester they do?!

Edited by Serpens
  • Health 1
Link to comment
Share on other sites

solution to the assert(numslots...) error message was to add numslots=12 into the widget params.

But when beign client, I got an error message that widget would be nil, from containerwidget.lua which was trying to get the replica widget... so again a problem with replicas. In another mod I saw this within addprefabpostinit

        if not GLOBAL.TheWorld.ismastersim then
            inst:DoTaskInTime(0, function(inst)  
                inst.replica.container:WidgetSetup("shadowBMduelist",containerparams.shadowBMduelist)                 
            end)
            return inst
        end

Also within the chester prefab this is called after morphing.

And I had to make my itemtestfn working for both, replica and components, because a check for a specific component does not work on clientside...

Now there is no error anymore... no clue why this replica stuff is needed while your mod seems to work without it. Maybe because you have your own prefab file, while I add it within AddPrefabPostInit.

My shadowmaxwell mod beta here:
https://forums.kleientertainment.com/files/file/1968-beta-ultimate-maxwell-shadows-better-maxwell-shadows/

Edited by Serpens
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...