Jump to content

Merm King shard syncing doesn't account for resyncing variables from secondary shards


hoxi
  • Pending

This causes Merm Kings in the caves to not count in the surface after a server restart, as the main shard never gets the data.

 

The issue lies here:

function Shard_OnShardConnected(world_id, tags, world_data, shard_name)
    -- NOTES(JBK): Only should be called when the shard state is REMOTESHARDSTATE.READY.
    if Shard_IsMaster() then
        Shard_SyncWorldSettings(world_id)
    else
        SendRPCToShard(SHARD_RPC.ResyncWorldSettings, SHARDID.MASTER)
    end
    if Shard_IsMaster() then
        if TheWorld then
            local shard_mermkingwatcher = TheWorld.shard.components.shard_mermkingwatcher
            if shard_mermkingwatcher then
                shard_mermkingwatcher:ResyncNetVars()
            end
        end
    end
    local shardtransactionsteps = TheWorld and TheWorld.components.shardtransactionsteps or nil
    if shardtransactionsteps then
        shardtransactionsteps:OnShardConnected(world_id)
    end
end

The ResyncNetVars call needs to happen in all shards instead of just master, and the function needs to be changed to account for secondary shards so that they sync using RPCs. You could potentially make a unique RPC for syncing all the variables in one go, rather than up to 4 separate RPCs.

 

 

On a slightly related note, since I don't think it's worth making a separate report for it:

    inst._wurtloadtask = inst:DoTaskInTime(0, (TheWorld.components.mermkingmanager ~= nil
            and TheWorld.components.mermkingmanager:HasKingAnywhere()
            and RoyalUpgrade)
        or RoyalDowngrade
    )

Wurt's loading task doesn't pass silent as true for neither RoyalUpgrade or RoyalDowngrade here when spawning in, this results in the animation and dialogue playing any time Wurt spawns and receives the "Merm King alive" upgrade, when joining a server or travelling from shard to shard.

It's a small thing, but I'm pretty sure it's a small oversight to not make use of the silent parameter.

 

Actually, now that I think about it as I was writing this, I realized it would also be cleaner to check for the King and which function to run after the task executes, rather than doing so before hand:

-- consider potentially blocking both royal functions from going through if the init task hasn't executed yet

--if inst._wurtinittask ~= nil then
--	return
--end

-- either that or just cancel it like how it works currently
-- I don't think there's any weird edge cases related to a king being throned or killed in the same frame a wurt spawns?


local function RoyalUpgrade(inst, silent)
    --if inst._wurtloadtask ~= nil then
    --    inst._wurtloadtask:Cancel()
    --    inst._wurtloadtask = nil
    --end
    inst.overrideskinmode = "powerup"
    inst.overrideskinmodebuild = "wurt_stage2"

    UpdateStats(inst, TUNING.WURT_HEALTH_KINGBONUS, TUNING.WURT_HUNGER_KINGBONUS, TUNING.WURT_SANITY_KINGBONUS)

    if not silent and not inst.royal then
        inst.royal = true
        inst.components.talker:Say(GetString(inst, "ANNOUNCE_KINGCREATED"))
        inst.sg:PushEvent("powerup_wurt")
        inst.SoundEmitter:PlaySound("dontstarve/characters/wurt/transform_to")
    end
end

local function RoyalDowngrade(inst, silent)
    --if inst._wurtloadtask ~= nil then
    --    inst._wurtloadtask:Cancel()
    --    inst._wurtloadtask = nil
    --end
    inst.overrideskinmode = nil
    inst.overrideskinmodebuild = nil

    UpdateStats(inst, TUNING.WURT_HEALTH, TUNING.WURT_HUNGER, TUNING.WURT_SANITY)

    if not silent and inst.royal then
        inst.royal = nil
        inst.components.talker:Say(GetString(inst, "ANNOUNCE_KINGDESTROYED"))
        inst.sg:PushEvent("powerdown_wurt")
        inst.SoundEmitter:PlaySound("dontstarve/characters/wurt/transform_from")
    end
end

local function OnInit(inst)
	inst._wurtinittask = nil

	local has_king = TheWorld.components.mermkingmanager ~= nil and TheWorld.components.mermkingmanager:HasKingAnywhere()
	local royal_fn = has_king and RoyalUpgrade or RoyalDowngrade
	royal_fn(inst, true)
end


-- in prefab constructor:

-- I feel like calling it an init task might be more intuitive to how it works
inst._wurtinittask = inst:DoTaskInTime(0, OnInit)

 


Steps to Reproduce

For the Merm King syncing issue:

  • Throne a Merm King in the caves and go to the surface.
  • Notice how things work as expected and the upgrades are available.
  • Now restart the server.
  • Notice how the upgrades are gone in the surface only, as the secondary shard never synced the variables after load.

 

For the Wurt loading task issue:

  • Throne a Merm King in the surface.
  • Spawn a Wurt player either via console command or by having someone travel between shards.
  • Notice how Wurt always plays her animation, sounds and dialogue right after spawning, instead of being silent as it was probably intended. Those things are supposed to only play when the first Merm King is put on a throne, or when all Merm Kings die.
  • Big Ups 1



User Feedback


There are no comments to display.



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