Jump to content

How to use `Container:WidgetSetup`?


Recommended Posts

I try to port Iron, Alloy and Smelter from Don't Starve to Don't Starve Together.

The version v1.0.7 of my mod works fine. But my subscriber said the game crashes when the Smelter is opened (error report can be found here).

I took a look and determined that maybe my mod is not compatible with some other mod because I overrode `scripts/containers.lua`:

-- https://github.com/WayOfModding/DST-Mod-Hamlet-Ironmaking/blob/master/scripts/containers.lua#L157
--------------------------------------------------------------------------
--[[ smelter ]]
--------------------------------------------------------------------------

params.smelter =
{
  widget =
  {
    slotpos =
    {
      Vector3(0, 64 + 32 + 8 + 4, 0),
      Vector3(0, 32 + 4, 0),
      Vector3(0, -(32 + 4), 0),
      Vector3(0, -(64 + 32 + 8 + 4), 0),
    },
    animbank = "ui_cookpot_1x4",
    animbuild = "ui_cookpot_1x4",
    pos = Vector3(200, 0, 0),
    side_align_tip = 100,
    buttoninfo = {
      text = STRINGS.ACTIONS.SMELT,
      position = Vector3(0, -165, 0),
    }
  },
  acceptsstacks = false,
  type = "cooker",
}

function params.smelter.itemtestfn(container, item, slot)
  return not container.inst:HasTag("burnt") and item.prefab == "iron"
end

function params.smelter.widget.buttoninfo.fn(inst)
  print("KK-TEST> Button down: SMELT/COOK ...")
  if inst.components.container ~= nil then
    BufferedAction(inst.components.container.opener, inst, ACTIONS.COOK):Do()
  elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
    SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.COOK.code, inst, ACTIONS.COOK.mod_name)
  end
end

function params.smelter.widget.buttoninfo.validfn(inst)
  return inst.replica.container ~= nil and inst.replica.container:IsFull()
end

 

-- https://github.com/WayOfModding/DST-Mod-Hamlet-Ironmaking/blob/v1.0.7/scripts/prefabs/smelter.lua#L265
inst.components.container:WidgetSetup("smelter")

 

To solve this problem, I removed `scripts/containers.lua` and modified `scripts/prefabs/smelter.lua`:

-- https://github.com/WayOfModding/DST-Mod-Hamlet-Ironmaking/blob/v1.0.9/scripts/prefabs/smelter.lua#L15
--------------------------------------------------------------------------
--[[ smelter ]]
--------------------------------------------------------------------------
local params = {}
params.smelter =
{
  widget =
  {
    slotpos =
    {
      Vector3(0, 64 + 32 + 8 + 4, 0),
      Vector3(0, 32 + 4, 0),
      Vector3(0, -(32 + 4), 0),
      Vector3(0, -(64 + 32 + 8 + 4), 0),
    },
    animbank = "ui_cookpot_1x4",
    animbuild = "ui_cookpot_1x4",
    pos = Vector3(200, 0, 0),
    side_align_tip = 100,
    buttoninfo =
    {
      text = STRINGS.ACTIONS.SMELT,
      position = Vector3(0, -165, 0),
    }
  },
  acceptsstacks = false,
  type = "cooker",
}

function params.smelter.itemtestfn(container, item, slot)
  return not container.inst:HasTag("burnt") and item.prefab == "iron"
end

function params.smelter.widget.buttoninfo.fn(inst)
  --print("KK-TEST> Button down: SMELT/COOK ...")
  if inst.components.container ~= nil then
    BufferedAction(inst.components.container.opener, inst, ACTIONS.COOK):Do()
  elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
    SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.COOK.code, inst, ACTIONS.COOK.mod_name)
  end
end

function params.smelter.widget.buttoninfo.validfn(inst)
  return inst.replica.container ~= nil and inst.replica.container:IsFull()
end
  
-- https://github.com/WayOfModding/DST-Mod-Hamlet-Ironmaking/blob/v1.0.9/scripts/prefabs/smelter.lua#L312
inst.components.container:WidgetSetup("smelter", params.smelter)

This version v1.0.9 works okay when I host a game directly with Don't Starve Together (TheWorld.ismastersim == true).

However, the game crashes (client side) when I host a game with Don't Starve Together Dedicated Server (TheWorld.ismastersim == false).

The following is the error log:

[00:02:57]: [string "scripts/widgets/containerwidget.lua"]:29: attempt to index local 'widget' (a nil value)
LUA ERROR stack traceback:
scripts/widgets/containerwidget.lua:29 in (method) Open (Lua) <24-143>
   self =
      callbacks = table: 638D0E10
      slotsperrow = 3
      inst = 102478 -  (valid:true)
      focus = false
      children = table: 638D0DC0
      focus_flow_args = table: 638D11A8
      focus_target = false
      isopen = false
      owner = 100038 - wickerbottom (valid:true)
      open = false
      can_fade_alpha = true
      inv = table: 638D11D0
      parent = 
      name = Container
      bgimage = Image - :
      focus_flow = table: 638D1180
      enabled = true
      bganim = UIAnim
      shown = true
   container = 101309 - smelter (valid:true)
   doer = 100038 - wickerbottom (valid:true)
   widget = nil
scripts/screens/playerhud.lua:247 in (upvalue) OpenContainerWidget (Lua) <244-249>
   self =
      fireover = FireOver
      sandover = SandOver
      beefbloodover = BeefBloodOver
      parent = screenroot
      overlayroot = overlays
      storm_overlays = storm_overlays
      mindcontrolover = UIAnim
      enabled = true
      under_root = under_root
      eventannouncer = EventAnnouncer
      name = HUD
      focus_flow = table: 587B0290
      bloodover = BloodOver
      storm_root = storm_root
      over_root = over_root
      callbacks = table: 587B0038
      popupstats_root = popupstats_root
      sanddustover = UIAnim
      inst = 100039 -  (valid:true)
      focus = true
      gogglesover = GogglesOver
      heatover = HeatOver
      focus_flow_args = table: 587B02B8
      focus_target = false
      vig = UIAnim
      _StatusAnnouncer = table: 1DDC83C8
      owner = 100038 - wickerbottom (valid:true)
      controls = Controls
      can_fade_alpha = true
      iceover = IceOver
      clouds = UIAnim
      is_screen = true
      fumeover = FumeOver
      shown = true
      handlers = table: 587B02E0
      children = table: 587AFFE8
      root = root
   container = 101309 - smelter (valid:true)
   side = false
   containerwidget = Container
scripts/screens/playerhud.lua:257 in (method) OpenContainer (Lua) <251-259>
   self =
      fireover = FireOver
      sandover = SandOver
      beefbloodover = BeefBloodOver
      parent = screenroot
      overlayroot = overlays
      storm_overlays = storm_overlays
      mindcontrolover = UIAnim
      enabled = true
      under_root = under_root
      eventannouncer = EventAnnouncer
      name = HUD
      focus_flow = table: 587B0290
      bloodover = BloodOver
      storm_root = storm_root
      over_root = over_root
      callbacks = table: 587B0038
      popupstats_root = popupstats_root
      sanddustover = UIAnim
      inst = 100039 -  (valid:true)
      focus = true
      gogglesover = GogglesOver
      heatover = HeatOver
      focus_flow_args = table: 587B02B8
      focus_target = false
      vig = UIAnim
      _StatusAnnouncer = table: 1DDC83C8
      owner = 100038 - wickerbottom (valid:true)
      controls = Controls
      can_fade_alpha = true
      iceover = IceOver
      clouds = UIAnim
      is_screen = true
      fumeover = FumeOver
      shown = true
      handlers = table: 587B02E0
      children = table: 587AFFE8
      root = root
   container = 101309 - smelter (valid:true)
   side = false
scripts/components/container_replica.lua:289 in (method) Open (Lua) <275-296>
   self =
      __craftPotPatched = true
      ondetachclassified = function - scripts/components/container_replica.lua:106
      acceptsstacks = true
      _numslots = 0
      inst = 101309 - smelter (valid:true)
      issidewidget = false
      _cannotbeopened = net_bool (34CA64B8)
      classified = 102477 - container_classified (valid:true)
      _isopen = false
   doer = 100038 - wickerbottom (valid:true)
scripts/components/container_replica.lua:95 in (field) fn (Lua) <87-101>
   inst = 101309 - smelter (valid:true)
   self =
      __craftPotPatched = true
      ondetachclassified = function - scripts/components/container_replica.lua:106
      acceptsstacks = true
 
[00:02:57]: [string "scripts/widgets/containerwidget.lua"]:29: attempt to index local 'widget' (a nil value)
LUA ERROR stack traceback:
    scripts/widgets/containerwidget.lua:29 in (method) Open (Lua) <24-143>
    scripts/screens/playerhud.lua:247 in (upvalue) OpenContainerWidget (Lua) <244-249>
    scripts/screens/playerhud.lua:257 in (method) OpenContainer (Lua) <251-259>
    scripts/components/container_replica.lua:289 in (method) Open (Lua) <275-296>
    scripts/components/container_replica.lua:95 in (field) fn (Lua) <87-101>
    scripts/scheduler.lua:177 in (method) OnTick (Lua) <155-207>
    scripts/scheduler.lua:371 in (global) RunScheduler (Lua) <369-377>
    scripts/update.lua:170 in () ? (Lua) <149-228>
	
[00:02:57]: Warning: Widget:SetFocusFromChild is happening on a widget outside of the screen/widget hierachy. This will cause focus moves to fail. Is 	ScriptErrorWidget	not a screen?	
[00:02:57]: stack traceback:
	scripts/widgets/widget.lua:602 in (method) SetFocusFromChild (Lua) <599-624>
	scripts/widgets/widget.lua:649 in (method) SetFocus (Lua) <626-658>
	scripts/widgets/scripterrorwidget.lua:107 in (method) OnUpdate (Lua) <102-119>
	scripts/update.lua:90 in () ? (Lua) <33-129>	
[00:02:58]: Warning: Widget:SetFocusFromChild is happening on a widget outside of the screen/widget hierachy. This will cause focus moves to fail. Is 	ScriptErrorWidget	not a screen?	
[00:02:58]: stack traceback:
	scripts/widgets/widget.lua:602 in (method) SetFocusFromChild (Lua) <599-624>
	scripts/widgets/widget.lua:621 in (method) SetFocusFromChild (Lua) <599-624>
	scripts/widgets/widget.lua:621 in (method) SetFocusFromChild (Lua) <599-624>
	scripts/widgets/widget.lua:621 in (method) SetFocusFromChild (Lua) <599-624>
	scripts/widgets/widget.lua:649 in (method) SetFocus (Lua) <626-658>
	scripts/widgets/scripterrorwidget.lua:107 in (method) OnUpdate (Lua) <102-119>
	scripts/update.lua:90 in () ? (Lua) <33-129>	
[00:02:58]: Force aborting...

Again, my guess is that on client side, prefab Smelter didn't invoke `inst.components.container:WidgetSetup("smelter", params.smelter)` at all and because `params.smelter` is not registered in `scripts/containers` module, the client cannot figure it out what value `widget` has.

I don't know what to do now. Please help, many thanks. :)

Link to comment
Share on other sites

Replacing an original game file is a BIG no-no, sir. You have been a bad boy, mister! I'm glad to see that your 1.0.9 version doesn't do that :D

Now, this is a bit of a shot in the dark, but from how I'm reading the code in containers.lua, this line in your prefab

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

should be

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

 

Edited by Ultroman
Link to comment
Share on other sites

On 2019/2/3 at 10:24 PM, Ultroman said:

Replacing an original game file is a BIG no-no, sir. You have been a bad boy, mister! I'm glad to see that your 1.0.9 version doesn't do that :D

Now, this is a bit of a shot in the dark, but from how I'm reading the code in containers.lua, this line in your prefab


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

should be


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

 

Sir, thank you for your reply, but your solution would lead to an exception. Please, double check the following API:

In `Don't Starve Together/data/scripts/components/container.lua`:

function Container:WidgetSetup(prefab, data)
    for i, v in ipairs(widgetprops) do
        removesetter(self, v)
    end

    containers.widgetsetup(self, prefab, data)
    self.inst.replica.container:WidgetSetup(prefab, data)

    for i, v in ipairs(widgetprops) do
        makereadonly(self, v)
    end
end

In `Don't Starve Together/data/scripts/containers.lua`:

function containers.widgetsetup(container, prefab, data)
    local t = data or 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)
    end
end
Edited by KaiserKatze
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...