Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating fire over to the new entity system and improving the experience #2012

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Sunrunner37
Copy link
Member

Currently fires in Nitrox are entirely hit and miss. Players will douse fires in the aurora but the behavior doesn't sync correctly due to prefab spawning issues. Similarly, fires in the cyclops will spawn about 50% of the time and have no ability to persist after a server reset or reconnect. The smoke would also hang around for some players.

This PR migrates fires to the new entity system and deprecates 8 fire-specific classes.

Fires put out after reconnection:

image

Cooperative fire fighting:

image

Fires in the cyclops:

image

Smoke clearing after the fire:

image

Copy link
Member

@Jannify Jannify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorldPersistenceTest is missing checks for CyclopsFireEntity and FireMetadata.


if (existingFire && NitroxEntity.GetId(existingFire.gameObject) != id)
{
Log.Error($"Fire already exists at node index {nodeIndex}! Updating id to {id}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an actual error or more a warning?

NitroxServiceLocator.LocateService<Fires>().OnDouse(__instance, amount);
}
#if DEBUG
Log.Error($"Fire instance is unknown to the server {__instance.gameObject.name}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server?

Resolve<Entities>().EntityMetadataChanged(__instance, nitroxId);

// Then tell the serve to delete the entity as it is now extinguished.
Resolve<IPacketSender>().Send(new EntityDestroyed(nitroxId));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a chance for race conditions and could it cause problems? Maybe we want to wait a little before deleting the entity?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like this packet to be the only one sent because the metadata update is an useless operation on a soon-to-be-destroyed entity. In exchange, you could add a new case in NitroxClient's EntityDestroyedProcessor for the Fire component and make it extinguished.
Therefore it'll avoid a weird case in which a metadata has 0 life in FireMetadataProcessor (which can be therefore be removed).

NitroxId subRootId = NitroxEntity.GetId(fire.fireSubRoot.gameObject);
NitroxId fireId = NitroxEntity.GetId(fire.gameObject);

CyclopsFireEntity cyclopsFireEntity = new((int)startInRoom.roomLinks.room, nodeIndex, fireId, TechType.None.ToDto(), null, subRootId, new());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CyclopsFireEntity cyclopsFireEntity = new((int)startInRoom.roomLinks.room, nodeIndex, fireId, TechType.None.ToDto(), null, subRootId, new());
CyclopsFireEntity cyclopsFireEntity = new((int)startInRoom.roomLinks.room, nodeIndex, fireId, NitroxTechType.None, null, subRootId, new());

Copy link
Collaborator

@tornac1234 tornac1234 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs rebase, modifications from #2063 (patches) and #1908 (replacing Nitrox.GetId) should be applied.


public override string ToString()
{
return $"[CyclopsFireEntity RoomIndex:{RoomIndex} NodeIndex:{NodeIndex} {base.ToString()}]";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return $"[CyclopsFireEntity RoomIndex:{RoomIndex} NodeIndex:{NodeIndex} {base.ToString()}]";
return $"[CyclopsFireEntity RoomIndex: {RoomIndex} NodeIndex: {NodeIndex} {base.ToString()}]";

Resolve<ThrottledPacketSender>().RemovePendingPackets(nitroxId);
Resolve<Entities>().EntityMetadataChanged(__instance, nitroxId);

// Then tell the serve to delete the entity as it is now extinguished.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Then tell the serve to delete the entity as it is now extinguished.
// Then tell the server to delete the entity as it is now extinguished.

Resolve<Entities>().EntityMetadataChanged(__instance, nitroxId);

// Then tell the serve to delete the entity as it is now extinguished.
Resolve<IPacketSender>().Send(new EntityDestroyed(nitroxId));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like this packet to be the only one sent because the metadata update is an useless operation on a soon-to-be-destroyed entity. In exchange, you could add a new case in NitroxClient's EntityDestroyedProcessor for the Fire component and make it extinguished.
Therefore it'll avoid a weird case in which a metadata has 0 life in FireMetadataProcessor (which can be therefore be removed).

Comment on lines +52 to +66
NitroxEntity currentEntity = fire.GetComponent<NitroxEntity>();

if (currentEntity)
{
return currentEntity.Id;
}

NitroxEntity parentEntity = fire.transform.parent.GetComponent<NitroxEntity>();

if (parentEntity)
{
return parentEntity.Id;
}

return null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After rebase, would use TryGetIdFrom to make it smaller yet understandable and also make sure the parent is still alive to avoid any possible issue.

using NitroxModel.Helper;
using NitroxModel.Packets;
using NitroxModel_Subnautica.DataStructures;
using UnityEngine;

namespace NitroxPatcher.Patches.Dynamic
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would convert to file-scoped and rework the file entirely:

  • Should use Resolve<> in Prefix.
  • Should replace all occurences of NitroxEntity.GetId in this file by something more relevant (after rebase).
  • Would be way better to replace the Postfix by a Transpiler (I'm not sure if we can rely that much on this hacky solution).

// If a fire already exists at the node, replace the old Id with the new one
if (fireTransform.childCount > 0)
{
Fire existingFire = fireTransform.GetComponentInChildren<Fire>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fire existingFire = fireTransform.GetComponentInChildren<Fire>();
Fire existingFire = fireTransform.GetComponentInChildren<Fire>(true);

{
Fire existingFire = fireTransform.GetComponentInChildren<Fire>();

if (existingFire && NitroxEntity.GetId(existingFire.gameObject) != id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change GetId to something more relevant (after rebase)


yield return new WaitUntil(() => newFireGameObject);

Fire fire = newFireGameObject.GetComponentInChildren<Fire>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fire fire = newFireGameObject.GetComponentInChildren<Fire>();
Fire fire = newFireGameObject.GetComponentInChildren<Fire>(true);

@tornac1234 tornac1234 added Area: persistence Related to serialization for long term storage (i.e. files and databases) Area: player Related to player character actions labels Dec 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: persistence Related to serialization for long term storage (i.e. files and databases) Area: player Related to player character actions
Projects
None yet
4 participants