Skip to content

Conversation

@drakewill-CRL
Copy link
Contributor

@drakewill-CRL drakewill-CRL commented Sep 8, 2024

About the PR

This PR creates plants as their own Entities, instead of a bunch of properties on a PlantHolder. SeedData gets moved to the PlantComponent.

This is part 3 of my Botany refactor writeup. Part 2 covers growth components. This is in draft state while I work on this logic for early feedback. While I work on moving and testing code, I'm only going to test on wheat stalks. I'll move everything to the final setup in YAML when I get there.

Why / Balance

As mentioned in the core writeup and other PRs, botany can't really get any major changes because the backend system is mostly handled in one big function and adding anything to that only makes it more difficult to clean up. This strips the plant-specific part out so PlantHolder can just update its lights and resources and the Plant can handle its tasks. Between this, growth components, and the mutation rework, the Botany code will be in a much better state for future maintenance and additions.

This should have no bearings on game balance, because this is just a refactor. A few bugs might be fixed or created in the process of porting code rather than porting poor/broken behavior.

Technical details

Plants are now entities. They are connected to their PlantHolder, and they are spawned when seeds are planted and deleted when they're harvested (if single harvest) or when the shovel is used to pull them out. SeedData is moved to the PlantComponent now.

All the existing plant logic was moved into a single Update() on PlantSystem. Breaking that out to separate components and systems is done in Part 2. It may be too granular to break each stat into its own component/system pair. Merging these should mostly require operating on Plants instead of PlantHolders.

Plants still need a PlantHolder. PlantHolder still has the water/nutrients the plant needs so the plant still need to have a connection to that. I have helper functions that get the Plant, PlantHolder, and SeedData all at once because of how often all 3 get referenced. The 2 entities keep a reference to the other, and blank it out when the plant is removed from the tray.

Chemicals are still applied to and run by the PlantHolder. The code that increases the water/nutrient level in the PlantHolder is a PlantEffect, so those all need to be run on the PlantHolder and then determine if the plant needs to be involved on each. Splitting this up to make more logical sense is a future enhancement.

Plants should grow identically to before, almost entirely unnoticeable to players. As entities, you can see them instead of the tray and view them in the right-click menu. That's visibly different. You also need to apply different items to different entities (EX: clippers must be used on the plant, but spades and chemicals need to be used on the tray itself).

The Slippery mutation no longer applies to the plant itself. It continues to apply to the produce harvested. I could not work out a way to make the plant entity both correctly fixed to the PlantHolder and get it to register the stepOn collision correctly. Oddly, it could handle a StepOFF trigger correctly but that happens once you've completely walked off the entity and it didn't feel right when everything else slips you when you step on it. Making the plant itself not slippery is the simplest, lowest-impact change to be made for this.

Additional changes:

  • SplatPrototype, IdealLight, and LightTolerance were removed as a cleanup task, because they're unused stats, and now's as good a time as any to finish getting rid of unused code.

Media

image

image

image

Requirements

  • I have read and I am following the Pull Request Guidelines. I understand that not doing so may get my pr closed at maintainer’s discretion
  • I have added screenshots/videos to this PR showcasing its changes ingame, or this PR does not require an ingame showcase

Breaking changes

PlantHolder is pretty dramatically different.

Changelog

🆑

  • tweak: Botany plants are now their own entity. You may need to click on the tray or the plant to do what you want, depending on what you're holding.

@mirrorcult
Copy link
Contributor

🙏

@nymhole
Copy link

nymhole commented Sep 12, 2024

this would also fix every sentience mutation being either hydroponics tray or soil? and it would kill the sentience with the plant?

@drakewill-CRL
Copy link
Contributor Author

this would also fix every sentience mutation being either hydroponics tray or soil?

Yes, This would let the plant itself be sentient.

and it would kill the sentience with the plant?

As written right now, without merging any of the other pieces smartly, this kills the sentience when the plant is destroyed (on shovel use to uproot, or on harvest if its a single-harvest crop). Whether sentient plants should stop aging when possessed, or get an extended lifespan, or just be fully at the mercy of a botanist's skills and patience is an unasked question. I would like the refactors to avoid changing balance or features as much as possible, so I expect that this would go in with "dead plants can talk, talking plants die on harvest" as known side effects and a discussion on how/if to change sentient plants occurs then.

@github-actions github-actions bot added the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted label Sep 15, 2024
@github-actions
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot added Changes: UI Changes: Might require knowledge of UI design or code. Changes: Map Changes: Might require knowledge of mapping. Changes: Sprites Changes: Might require knowledge of spriting or visual design. and removed S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted labels Sep 18, 2024
@drakewill-CRL drakewill-CRL marked this pull request as ready for review September 19, 2024 23:51
@github-actions github-actions bot added the S: Needs Review Status: Requires additional reviews before being fully accepted. Not to be replaced by S: Approved. label Sep 19, 2024
@Partmedia Partmedia added the A: Service Area: Service department, including cooking, botany, etc label Sep 20, 2024
@DTSpawn
Copy link

DTSpawn commented Nov 2, 2024

Please keep idealLight. I'm using it on my fork on some plants (they need to glow in dark places)

@github-actions github-actions bot added the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted label Nov 4, 2024
@github-actions
Copy link
Contributor

github-actions bot commented Nov 4, 2024

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted label Nov 4, 2024
@SlamBamActionman SlamBamActionman added the S: Untriaged Status: Indicates an item has not been triaged and doesn't have appropriate labels. label Nov 14, 2024
@eoineoineoin eoineoineoin added P2: Raised Priority: Item has a raised priority, indicating it might get increased maintainer attention. T: Refactor Type: Refactor of notable amount of codebase D2: Medium Difficulty: A good amount of codebase knowledge required. and removed S: Untriaged Status: Indicates an item has not been triaged and doesn't have appropriate labels. labels Nov 22, 2024
@Qwazori
Copy link

Qwazori commented Jan 7, 2025

Still in progress?

@drakewill-CRL
Copy link
Contributor Author

Still in progress?

Yes. I haven't made a big deal of trying to push my changes through. The maintainers have had a pretty big pile of nonsense to deal with since I started this, and I don't want to add any additional pressure on them for a refactor PR.

@slarticodefast
Copy link
Member

Yeah, I'm sorry for the wait, things have been really busy recently. I still got the review for this on my ToDo list and hope I can do it soon. But for a review this size I need at least half a day of free time.

@Emisse Emisse removed the Changes: Map Changes: Might require knowledge of mapping. label Jan 19, 2025
Copy link
Contributor

@MilonPL MilonPL left a comment

Choose a reason for hiding this comment

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

Okay some thoughts: I really don't like the GetEverything method and how we're overwritting the PlantComponent in a lot of cases, it seems really pointless. You could really play around with the Entity and Entity<T?> patterns for signatures, some of this seems like it could be replaced with queries, especially stuff called from inside of Update(), and then passed on to other methods (which I think would be a better way of getting that data)

namespace Content.Client.Botany.Components;

[RegisterComponent]
public sealed partial class PlantVisualsComponent : Component
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't need a body declared.

SubscribeLocalEvent<PlantVisualsComponent, ComponentInit>(OnComponentInit);
}

private void OnComponentInit(EntityUid uid, PlantVisualsComponent component, ComponentInit args)
Copy link
Contributor

Choose a reason for hiding this comment

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

Entity<T> ent, ref event args pattern.

[Access(typeof(BotanySystem), typeof(PlantSystem), typeof(PlantHolderSystem), typeof(EntityEffect))]
public sealed partial class PlantComponent : Component
{
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
Copy link
Contributor

Choose a reason for hiding this comment

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

Add the AutoPausedField attribute.

[DataField]
public int LastProduce;

[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
Copy link
Contributor

Choose a reason for hiding this comment

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

Add the AutoPausedField attribute.

/// The time between growth ticks.
/// </summary>
[DataField]
public TimeSpan CycleDelay = TimeSpan.FromSeconds(15f);
Copy link
Contributor

Choose a reason for hiding this comment

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

Just 15.

/// <summary>
/// Cease the growth and harvesting of a plant through the conclusion of biological processes.
/// </summary>
public void Die(EntityUid uid, PlantComponent? plant = null)
Copy link
Contributor

Choose a reason for hiding this comment

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

Overwritten.

/// </summary>
public void Die(EntityUid uid, PlantComponent? plant = null)
{
if (!GetEverything(uid, out plant, out var seed, out var holder) || plant == null)
Copy link
Contributor

Choose a reason for hiding this comment

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

seed can be discarded.

/// </summary>
public void UpdateSprite(EntityUid uid, PlantComponent? component = null)
{
GetEverything(uid, out var plant, out _, out _);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need two separate plant components?

/// </summary>
[DataField("packetPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
[DataField(customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string PacketPrototype = "SeedBase";
Copy link
Contributor

Choose a reason for hiding this comment

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

EntProtoId

/// </summary>
[DataField("productPrototypes", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
[DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> ProductPrototypes = new();
Copy link
Contributor

Choose a reason for hiding this comment

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

EntProtoId

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2025

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot added the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted label Feb 8, 2025
@MilonPL
Copy link
Contributor

MilonPL commented Apr 18, 2025

Thank you for your contribution! Due to this PR being having no activity and unresolved review comments, we've decided to close it. If you ever come back to it, feel free to open a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A: Service Area: Service department, including cooking, botany, etc Changes: Sprites Changes: Might require knowledge of spriting or visual design. D2: Medium Difficulty: A good amount of codebase knowledge required. P2: Raised Priority: Item has a raised priority, indicating it might get increased maintainer attention. S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted S: Needs Review Status: Requires additional reviews before being fully accepted. Not to be replaced by S: Approved. T: Refactor Type: Refactor of notable amount of codebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.