I need a little help. Hearthlings can move items which have no player ID assigned but cannot undeploy them, probably because they need to know that so they can choose an inventory correctly (like if they couldn’t take their own player ID instead). I cannot find out which part of the code is responsible for that.
So I found the function responsible for the very behaviour in inventory.lua:
local function item_should_be_restocked(item, player_id) -- ignore invalid items.. if not item or not item:is_valid() then return false end -- always pick up items that we've looted... local task_tracker_component = item:get_component('stonehearth:task_tracker') if task_tracker_component and task_tracker_component:is_task_requested(player_id, nil, 'stonehearth:loot_item') then return true end -- ignore items that aren't ours... local item_player_id = radiant.entities.get_player_id(item) if item_player_id ~= player_id then log:spam('(item should be restocked) %s has player id does not match ours. returning false.', tostring(item)) return false end -- if an item is in storage, we only want to restock it if it does not pass -- the filter of that storage local inventory = stonehearth.inventory:get_inventory(item_player_id) if not inventory then log:spam('(item should be restocked) %s could not find an inventory. returning false.', item) return false end local storage = inventory:container_for(item) if storage then local sc = storage:get_component('stonehearth:storage') if sc then if sc:get_type() == 'backpack' then log:spam('(item should be restocked) %s is in a backpack. returning false.', item) return false end local items_in_filter = sc:get_passed_items() if items_in_filter[item:get_id()] ~= nil then log:spam('(item should be restocked) %s is fine in its current storage. returning false.', item) return false end end end --log:spam('(item should be restocked) item %s should be restocked. returning true.', item) return true end
Now the real problem arises. As of now we have Player 1 and the Goblins. Commenting out this part of the code is not an option because Goblin workers would attempt to restock every resource obtained by Player 1 and vice versa. This means restocking should not cover objects with different Player ID than ours. The question is: what to do with objects without player ID?
There are many ways to treat objects without player ID. The problem is gone when an objects is moved first and then undeployed. Why? Because when it is placed it is assigned the player’s player ID. The simplest possible trick would be to modify the undeploy command to begin with assigning player’s ID to an object if it has none. I tested it and it works flawlessly:
function modded_server_function:_undeploy_no_player() local PlaceItemCallHandler = radiant.mods.require('stonehearth.call_handlers.place_item_call_handler') PlaceItemCallHandler.undeploy_item = function(self, session, response, item) local efc = item:get_component('stonehearth:entity_forms') if efc then radiant.entities.set_player_id(item, session.player_id) local current_value = efc:get_should_restock() efc:set_should_restock(not current_value) end radiant.events.trigger_async(item, 'stonehearth:item_undeployed') return true end end