Jump to content

[Help] Prefab spawning only for server host and not spawing with caves on


Recommended Posts

Hello, i found an odd problem, my prefab weapon only spawns when you select my character mod if you are the host. If you are not the host and you choose my character, the first slot from the inventory where the weapon should be is empy.

This is my prefab full code:

Spoiler

local assets=

    Asset("ANIM", "anim/chaosrevenge.zip"),
    Asset("ANIM", "anim/swap_chaosrevenge.zip"), 

    Asset("ATLAS", "images/inventoryimages/chaosrevenge.xml"),
    Asset("IMAGE", "images/inventoryimages/chaosrevenge.tex"),
}

local prefabs = 
{
    "caius"
}

--------Stund perk and sanity for hits

local stuntime = 4

local function ShowStunFX(target)
    local x, y, z = target.Transform:GetWorldPosition()
    local fx = SpawnPrefab("shock_fx")
    fx.Transform:SetPosition(x, y, z)
end

local function StartStun(target)
    if target.sg ~= nil and not target.sg:HasStateTag("frozen") and target.sg.sg.states.hit ~= nil then
        target.sg:GoToState("hit")
    end
    ShowStunFX(target)
    target:AddTag("discordstunned")
    target:StopBrain()
end

local function StopStun(target)
    target:RemoveTag("discordstunned")
    target:RestartBrain()
end

local function onattack(inst, attacker, target, owner)
    local owner = inst.components.inventoryitem and inst.components.inventoryitem.owner
    if not target:HasTag("wall") then
        owner.components.sanity:DoDelta(0.2)
    end
    local chance = math.random()
    if chance < 0.50 then
        if target ~= nil and target.components.health ~= nil and not target.components.health:IsDead() then
            if not target:HasTag("discordstunned") then
                StartStun(target)
                target:DoTaskInTime(stuntime, StopStun)
            end
        end
    end
end

---

----------Gaining sanity from killing

local function IsValidVictim(victim)
    return victim ~= nil
        and not ((victim:HasTag("prey") and not victim:HasTag("hostile")) or
                victim:HasTag("veggie") or
                victim:HasTag("structure") or
                victim:HasTag("wall") or
                victim:HasTag("companion"))
        and victim.components.health ~= nil
        and victim.components.combat ~= nil
end

local function onkill(owner, data)
    local victim = data and data.victim

    if IsValidVictim(victim) and not victim:HasTag("smallcreature") 
        or victim:HasTag("monster")then
        owner.components.sanity:DoDelta(2)
    end
end

----------------
--ice spell test

local function freezeSpell(inst, target, owner)
   local owner = inst.components.inventoryitem and inst.components.inventoryitem.owner    
        if owner and owner.components.sanity then
        owner.components.sanity:DoDelta(-2)
    end

    local attacker = inst.components.inventoryitem.owner
    if target.components.sleeper and target.components.sleeper:IsAsleep() then
        target.components.sleeper:WakeUp()
    end
    if target.components.burnable then
        if target.components.burnable:IsBurning() then
            target.components.burnable:Extinguish()
        end
    end
    if target.sg and target.components.combat then
        target.components.combat:SuggestTarget(attacker)
        if not target:HasTag("player") and not target.sg:HasStateTag("frozen") and target.sg.sg.states.hit then
            target.sg:GoToState("hit")
        end
    end
    if target.sg and not target.sg:HasStateTag("frozen") then
        target:PushEvent("attacked", {attacker = attacker, damage = 0})
    end
    if target.components.freezable then
        target.components.freezable:AddColdness(2)
        target.components.freezable:SpawnShatterFX()
    end
end

local function aoeSpell(inst, pos)
    local ents = TheSim:FindEntities(pos.x, pos.y, pos.z, 18, {"freezable"}, {"player"})
    for k, v in pairs(ents) do
        freezeSpell(inst, v)
    end
end

local function multiSpell(inst, target, pos)
    if not target then

        aoeSpell(inst, pos)
    end
end
-- end ice spell test

local function fn(colour)

    local function OnEquip(inst, owner) 
        owner.AnimState:OverrideSymbol("swap_object", "swap_chaosrevenge", "swap_chaosrevenge")
        owner.AnimState:Show("ARM_carry") 
        owner.AnimState:Hide("ARM_normal")    
        --owner.AnimState:SetHaunted(true)    ++++++++Sin haunted     
         owner:ListenForEvent("killed", onkill)
         --owner.discordnightvision:set(true) ++++++++++++++++++sin nightvision
    end

    local function OnUnequip(inst, owner) 
        owner.AnimState:Hide("ARM_carry") 
        owner.AnimState:Show("ARM_normal")
        --owner.AnimState:SetHaunted(false) +++++++++++sin haunted
         owner:RemoveEventCallback("killed", onkill)
         --owner.discordnightvision:set(false) ++++++++++++++++sin nightvision
    end

    local inst = CreateEntity()
    local trans = inst.entity:AddTransform()
    local anim = inst.entity:AddAnimState()
    MakeInventoryPhysics(inst)
    
    anim:SetBank("chaosrevenge")
    anim:SetBuild("chaosrevenge")
    anim:PlayAnimation("idle")
    
    if not TheWorld.ismastersim then
        return inst
    end
    
        ------ Glowing by haunted
    --inst.AnimState:SetHaunted(true) +++++++++++++sin haunted
    -------------------
    
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "chaosrevenge"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/chaosrevenge.xml"
    
    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip( OnEquip )
    inst.components.equippable:SetOnUnequip( OnUnequip )
    inst.components.equippable.walkspeedmult = 1.3 -------------era 1.5

    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(35)
    -- Electric stimuli on attack
    inst.components.weapon:SetElectric()
    -- Blinking
    inst.components.weapon.blinking = true
    -- Attack range, hit range
    inst.components.weapon:SetRange(7, 2)
    --Sanity by hit and stuning
    inst.components.weapon.onattack = onattack
    
    --Sanity drain on hold
    --inst.components.equippable.dapperness = TUNING.CRAZINESS_SMALL -- inactive while mod is on testing stage
    -----
    
    if not inst.components.characterspecific then
    inst:AddComponent("characterspecific")
    end
 
    inst.components.characterspecific:SetOwner("caius")
    inst.components.characterspecific:SetStorable(true)
    inst.components.characterspecific:SetComment("These seem heavier than they look.") 
    
        inst:AddComponent("tool")
    inst.components.tool:SetAction(ACTIONS.CHOP, 14)
    inst.components.tool:SetAction(ACTIONS.MINE, 8)
    
    --ice test
    inst:AddComponent("spellcaster")
    inst.components.spellcaster.canuseontargets = true
    inst.components.spellcaster.canuseonpoint = true
    inst.components.spellcaster:SetSpellFn(multiSpell)
    --end ic test
    
    return inst
end

return  Prefab("common/inventory/chaosrevenge", fn, assets, prefabs)

And of course, my character (named caius) has this:

Spoiler

local start_inv = {
    "chaosrevenge"

}

Do you guys see something on my weapon's prefab code that could cause this? The mod works perfectly for the host, this is really weird.

Additional info about the bug:

When i enable caves, even as a host i don't get my weapon.

I'm very close to publish my mod, basically the only thing missing is the character desing, but this new bug is a huge step back, i hope you guys can help me.

Edited by Jpianist
Link to comment
Share on other sites

42 minutes ago, Lumina said:

Is character specific still a thing in DST ? I don't think it's the cause of the problem but who knows...

I didn't know that it wasn't a thing now, i started this mod last year, then because of life related stuff i had to stop playing and modding don't starve together until just now.

Back to topic: I tried removing the character specific codes and still nothing, apparently that is not the reason of the problem. 

New discovery: As a host, i added caves and now i didn't get my weapon either.

Edited by Jpianist
Link to comment
Share on other sites

I've sought after a way to check character specific items, finding that DST does handle them differently; although I'm rather unsure how the system works in its purest form.

As I understand it, the host can read most if not all the code, but other areas of the same file aren't stored on the client side or even do not run. You need to give the client messages as to what is happening on the host so that it might exist on the client side; although again, I'm no expert on this.

Lucy is a good example of this I think, whereas before you could assign with DS:

inst:AddComponent("characterspecific")
inst.components.characterspecific:SetOwner("woodie")

DST together handles it differently, Lucy has a classified file (lucy_classified.lua) that handles the network related queries. The best resources I can link for you at this time are two threads that cover network related interactions, I hope these can help you.

Also from what I gather:

-- This initializes for both the server and client. Tags can be added here.
-- anything above the following command is initialised on both client and server/host 
-- (basically the functions do the exact same thing on both client and host)
 	inst.entity:SetPristine()

-- if I understand it correctly this command means that once the prefab reaches this point, 
-- that all data for the client has been reached and further
-- content does not need to be included for them.
	if not TheWorld.ismastersim then
        return inst
    end
	-- In a main fn of a prefab, anything after this tends to be host only.

-- This can be used and I'd hazard a guess it deals with either 
-- client or host uniquely, but I'm really not certain (wouldn't mind 
-- anyone with networking knowledge to set me straight on this matter)
    if TheWorld.ismastersim then
        return inst
    end

So what I think you're experiencing is that if you test it on your own on DST, you are essentially playing as the server; but the client version is where someone connects to your host game - or you join them. Caves are often a separate server, so when you enter that, even as a host I think you switch to being a client because the caves need another server system to host them.

In essence, if you're not the server you only receive a fraction of the prefabs descriptive code, which in turn can cause the prefab to lose data or not appear for the client at all.

Edited by MorickClive
Link to comment
Share on other sites

14 minutes ago, MorickClive said:

I've sought after a way to check character specific items, finding that DST does handle them differently; although I'm rather unsure how the system works in its purest form.

As I understand it, the host can read most if not all the code, but other areas of the same file aren't stored on the client side or even do not run. You need to give the client messages as to what is happening on the host so that it might exist on the client side; although again, I'm no expert on this.

Lucy is a good example of this I think, whereas before you could assign with DS:


inst:AddComponent("characterspecific")
inst.components.characterspecific:SetOwner("woodie")

DST together handles it differently, Lucy has a classified file (lucy_classified.lua) that handles the network related queries. The best resources I can link for you at this time are two threads that cover network related interactions, I hope these can help you.

Also from what I gather:


-- This initializes for both the server and client. Tags can be added here.
-- anything above the following command is initialised on both client and server/host 
-- (basically the functions do the exact same thing on both client and host)
 	inst.entity:SetPristine()

-- if I understand it correctly this command means that once the prefab reaches this point, 
-- that all data for the client has been reached and further
-- content does not need to be included for them.
	if not TheWorld.ismastersim then
        return inst
    end
	-- In a main fn of a prefab, anything after this tends to be host only.

-- This can be used and I'd hazard a guess it deals with either 
-- client or host uniquely, but I'm really not certain (wouldn't mind 
-- anyone with networking knowledge to set me straight on this matter)
    if TheWorld.ismastersim then
        return inst
    end

So what I think you're experiencing is that if you test it on your own on DST, you are essentially playing as the server; but the client version is where someone connects to your host game - or you join them. Caves are often a separate server, so when you enter that, even as a host I think you switch to being a client because the caves need another server system to host them.

In essence, if you're not the server you only receive a fraction of the prefabs descriptive code, which in turn can cause the prefab to lose data or not appear for the client at all.

I understand that character specific works different, i removed the character specific codes and i still got the bug. As a server there is no problem, but as a client the weapon won't spawn. For what i got from your message, anything under this does not go to the client: 

Spoiler

    if not TheWorld.ismastersim then
        return inst
    end

Yet in my second item i have a lot of stuff under that code and it works fine in both server and client side, below that code i have stuff like  Onequip and OnUnequip codes, so that doesn't seem to be the case. 

Long story short, i removed the character specific codes, problem continues. I'm lost    : (

Thanks a lot for writing @MorickClive, i appreciate it.

Link to comment
Share on other sites

Again, I'm not really much of an expert when it comes to this. I have noticed that the dependency for network related stuff can really effect prefabs quite badly; this sounds very similar to an issue I had with my nightmare ectoplasm asset not showing up for clients (although I have no strict character binding for it). The waffle is partly in hope that someone might be able to clarify any thing I've misunderstood. ^^'

The only things I really notice about your prefab code is about OnEquip() and OnUnequip() being contained within "local function fn(colour)" I've not really seen that initialise method, usually it's located above the main fn().

That and you appear to be also missing:

    inst.entity:AddNetwork() -- pretty important to client/network relationships.

Try adding below these lines and running it:

  local inst = CreateEntity()
  local trans = inst.entity:AddTransform()
  local anim = inst.entity:AddAnimState()

 

Edited by MorickClive
Link to comment
Share on other sites

23 hours ago, MorickClive said:

Again, I'm not really much of an expert when it comes to this. I have noticed that the dependency for network related stuff can really effect prefabs quite badly; this sounds very similar to an issue I had with my nightmare ectoplasm asset not showing up for clients (although I have no strict character binding for it). The waffle is partly in hope that someone might be able to clarify any thing I've misunderstood. ^^'

The only things I really notice about your prefab code is about OnEquip() and OnUnequip() being contained within "local function fn(colour)" I've not really seen that initialise method, usually it's located above the main fn().

That and you appear to be also missing:


    inst.entity:AddNetwork() -- pretty important to client/network relationships.

Try adding below these lines and running it:


  local inst = CreateEntity()
  local trans = inst.entity:AddTransform()
  local anim = inst.entity:AddAnimState()

 

I added this code into my weapon and then tested it with caves and the weapon works!

inst.entity:AddNetwork()

The problem seems to be fixed now, tomorrow i'll test it with a friend to make sure it's working 100%, but that seems to be the case since now i get the weapon with caves enabled. Thank you so much @MorickClive, you're awesome bro.

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