function OnEntitySleep(guid) local inst = Ents[guid] if inst then inst:PushEvent("entitysleep") if inst.OnEntitySleep then inst:OnEntitySleep() end inst:_DisableBrain_Internal() if inst.sg then SGManager:Hibernate(inst.sg) end inst.sleepstatepending = nil if inst.emitter then EmitterManager:Hibernate(inst.emitter) end for k,v in pairs(inst.components) do if v.OnEntitySleep then v:OnEntitySleep() end end end end
Same applies to OnEntityWake.
The way it's done right now results in OnEntitySleep and OnEntityWake functions on an entity instance, as well as "entitysleep" and "entitywake" event listeners, to not be able to check for it properly. This can mainly be an issue with making common functions or common functionality shared across a few functions.
Here's an example:
local function InitLocalSoundEmitter(proxy, from_wake) -- shouldn't be needed but just in case if proxy.local_sound_emitter ~= nil and proxy.local_sound_emitter:IsValid() then proxy.local_sound_emitter:Remove() proxy.local_sound_emitter = nil -- to account for the mastersim checks below stopping things there end -- need to handle this this way for now -- .sleepstatepending check is not reliable for "entitysleep" or "entitywake" events for now if TheWorld.ismastersim then if from_wake then if proxy:IsInLimbo() then return end elseif proxy.sleepstatepending or proxy:IsAsleep() then return end end -- non-networked entity creation stuff here end local function RemoveLocalSoundEmitter(inst) if inst.local_sound_emitter ~= nil and inst.local_sound_emitter:IsValid() then inst.local_sound_emitter:Remove() end inst.local_sound_emitter = nil end -- for context, clients spawn the sound emitter whenever the relevant entity spawns for them (after 1 tick) -- the server instead does the following: local function OnEntityWake(inst) InitLocalSoundEmitter(inst, true) -- this is the only outlier due to the .sleepstatepending issue end -- in prefab postinit inst:ListenForEvent("entitysleep", RemoveLocalSoundEmitter) inst:ListenForEvent("entitywake", OnEntityWake) inst:ListenForEvent("enterlimbo", RemoveLocalSoundEmitter) inst:ListenForEvent("exitlimbo", InitLocalSoundEmitter)
On a related note..
function EntityScript:IsAsleep() return not self.entity:IsAwake() end
Is there a reason this function doesn't check for .sleepstatepending?
If something checks for entity sleep, then you don't want it to go through during entity construction either (where entity:IsAwake() returns true as a false positive, but the entity is basically sleep and at 0, 0, 0), and there's plenty of cases like that that do it anyway.
Mostly, what's done because of it gets immediately undone right after on receiving sleep status, so it's just a waste of performance, but it could be worse and result in unintended behavior.
You can try logging if inst:IsAsleep() is called when .sleepstatepending is still true, and you'll see what I mean.
Keep in mind that there are some weird edge cases where entity:IsAwake() is checked instead of inst:IsAsleep(). Those should be updated to use the latter instead.
Self-explanatory.
-
1
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 accountSign in
Already have an account? Sign in here.
Sign In Now