Jump to content

Recommended Posts

I'm creating a mod that converts killer bees into regular bees when caught. Unfortunately, it seems to mess up the inventory slot where the bee is spawned. You can't see the bee, and trying to move anything into that slot fails. My best guess is that the client isn't replicating something. I think I had it working before, but I removed some debug code and now it isn't. Any thoughts?

Code:

Spoiler


if not GLOBAL.TheNet:GetIsServer() then
	return
end

local function Beeify(inst)
	if not inst:IsValid() then
		return nil
	end
	
	local bee = GLOBAL.SpawnPrefab("bee")
	if bee then
		bee.Transform:SetPosition(inst.Transform:GetWorldPosition())
		if bee.components.stackable and inst.components.stackable then
			bee.components.stackable:SetStackSize(inst.components.stackable.stacksize)
		end
		if bee.components.perishable and inst.components.perishable then
			bee.components.perishable:SetPercent(inst.components.perishable:GetPercent())
		end
		
		if inst.components.homeseeker and inst.components.homeseeker.home then
			inst:PushEvent("detachchild")
		end
		
		if bee.components.inventoryitem and inst.components.inventoryitem then
			bee.components.inventoryitem:InheritMoisture(inst.components.inventoryitem:GetMoisture(), inst.components.inventoryitem:IsWet())
			
			local owner = inst.components.inventoryitem.owner
			local holder = owner and (owner.components.inventory or owner.components.container)
			local slot = holder and holder:GetItemSlot(inst)
			if slot then
				inst:Remove()
				holder:GiveItem(bee, slot)
				return bee
			end
		end
		inst.persists = false
		inst.entity:Hide()
		inst:DoTaskInTime(0, inst.Remove)
	end
	return bee
end

AddPrefabPostInit("killerbee", function(inst)
	local oldfn = inst.components.inventoryitem.onputininventoryfn
	inst.components.inventoryitem:SetOnPutInInventoryFn(function(inst)
		if oldfn then
			oldfn(inst)
		end
		local new_bee = Beeify(inst)
		local newfn = new_bee and new_bee.components.inventoryitem and new_bee.components.inventoryitem.onputininventoryfn
		if newfn then
			newfn(new_bee)
		end
	end)
end)

 

 

 

AddPrefabPostInit("killerbee", function(inst)
	if GLOBAL.TheWorld.ismastersim then
		local function OnPutInInventory(inst,owner)
        		owner = owner or inst.components.inventoryitem.owner
			local new_bee = GLOBAL.ReplacePrefab(inst,"bee")
			if owner then
				owner.components.inventory:GiveItem(new_bee)
			end
		end
		inst:ListenForEvent("onputininventory",OnPutInInventory)
	end
end)

Try it with this, this was working for me.

Edited by Monti18

That's right, I forgot to test it without a bee already in the inventory.

AddPrefabPostInit("killerbee", function(inst)
	if GLOBAL.TheWorld.ismastersim then
		local function OnPutInInventory(inst,owner)
			local new_bee = GLOBAL.ReplacePrefab(inst,"bee")
			owner = owner or inst.components.inventoryitem.owner
			if owner then
				inst:DoTaskInTime(0,function() owner.components.inventory:GiveItem(new_bee) end)
			end
		end
		inst:ListenForEvent("onputininventory",OnPutInInventory)
	end
end)

By adding the taskintime, at least for me the bee appeared correctly in the same place. But if you try to catch it with a full inventory, the killerbee will fall on the ground without being transformed.

@Monti18

No good, I'm afraid. I'm still getting phantom killerbees in my inventory after the first one caught. Or if I catch one with all my slots full, I end up with a phantom killerbee in my hand, I can't perform any actions with the cursor, and the server crashes on right-click (due to nil inventoryitem of the non-existent killerbee.) This occurs even when the OnPutInInventory function contains nothing but GLOBAL.ReplacePrefab(inst, "bee").

Additional information:

--client_log.txt says:
"Don't Starve Together: 490729 WIN32_STEAM"

--modinfo.lua:
api_version = 10
dst_compatible = true
all_clients_require_mod = false --also tried "true"
clients_only_mod = false


Addendum:

Looks like ReplacePrefab is just this:

function ReplacePrefab(original_inst, name, skin, skin_id, creator)
    local x,y,z = original_inst.Transform:GetWorldPosition()

    local replacement_inst = SpawnPrefab(name, skin, skin_id, creator)
    replacement_inst.Transform:SetPosition(x,y,z)

    original_inst:Remove()

    return replacement_inst
end

Going to try using "original_inst:DoTaskInTime(0, original_inst.Remove)" and see if that makes any difference.


No more phantom bees, but it's back to putting them into the wrong slot (or releasing them as bees when inventory isn't full if I add a 0.01 delay to GiveItem task.)

Edited by Bumber64
Addendum

You also did it with the ListenForEvent right? As then the function takes a bit more time to start so that the rest can be loaded. I retried it, for me it's still working. You may want to delay the ListenForEvent a bit further:

AddPrefabPostInit("killerbee", function(inst)
	if GLOBAL.TheWorld.ismastersim then
		local function OnPutInInventory(inst,owner)
			local new_bee = GLOBAL.ReplacePrefab(inst,"bee")
			owner = owner or inst.components.inventoryitem.owner
			if owner then
				inst:DoTaskInTime(0,function() owner.components.inventory:GiveItem(new_bee) end)
			end
		end
		inst:ListenForEvent("onputininventory",function(inst,owner) inst:DoTaskInTime(0,function() OnPutInInventory(inst,owner) end) end)
	end
end)

That is also working on my side.

  • Like 1

@Monti18

Yes, I was using ListenForEvent.

I got it working just now by putting the Remove in the same function as the GiveItem:

AddPrefabPostInit("killerbee", function(inst)
	if GLOBAL.TheWorld.ismastersim then
		local function OnPutInInventory(inst, owner)
			local new_bee = ReplacePrefab(inst, "bee")
			owner = owner or inst.components.inventoryitem.owner
			if owner then
				inst:DoTaskInTime(0, function() inst:Remove(); owner.components.inventory:GiveItem(new_bee) end)
			else
				inst:DoTaskInTime(0, inst.Remove)
			end
		end
		inst:ListenForEvent("onputininventory", OnPutInInventory)
	end
end)

Where ReplacePrefab is a local function without "original_inst:Remove()".

Not sure why your code wasn't working for me, other than maybe CPU differences. In any case, thanks for your help solving this!

Addendum: Your most recent code works too.

Edited by Bumber64
Addendum
  • Like 1

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...