forked from KaBooMa/S1API
-
-
Notifications
You must be signed in to change notification settings - Fork 22
Refactor Item API: namespace and builder cleanup #82
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
Open
k073l
wants to merge
8
commits into
ifBars:stable
Choose a base branch
from
k073l:refactor/item-builders
base: stable
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
5ae1858
refactor(items): cleanup qualityitembuilder
k073l 7835ddb
refactor(items): cleanup additive, buildable, clothing builders
k073l 6517f04
feat(items): improve docstrings, add missing obsolete comments
k073l 836cf8d
Merge branch 'stable' into refactor/item-builders
k073l 9773925
refactor(items): move builder namespaces
k073l c69d01f
fix(items): guard against null in builders
k073l 477f459
refactor(items): remove unused requiredRank parameter
k073l 2b3efd0
fix(items): validate ID before lookup
k073l File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| #if (IL2CPPMELON) | ||
| using S1ItemFramework = Il2CppScheduleOne.ItemFramework; | ||
| #elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX) | ||
| using S1ItemFramework = ScheduleOne.ItemFramework; | ||
| #endif | ||
| using System; | ||
| using UnityEngine; | ||
|
|
||
| namespace S1API.Items.Additive | ||
| { | ||
| /// <summary> | ||
| /// Represents an additive item definition. | ||
| /// Extends <see cref="StorableItemDefinition"/> with additive-specific properties. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Builder-only: these properties are intentionally read-only to avoid runtime surprises from mutating | ||
| /// globally-registered ScriptableObject definitions mid-session. Use <see cref="AdditiveItemCreator"/> to create | ||
| /// additives with configured effects. | ||
| /// </remarks> | ||
| public sealed class AdditiveDefinition : Storable.StorableItemDefinition | ||
| { | ||
| /// <summary> | ||
| /// INTERNAL: Wraps an existing native additive definition. | ||
| /// </summary> | ||
| internal AdditiveDefinition(S1ItemFramework.AdditiveDefinition definition) | ||
| : base(definition) | ||
| { | ||
| S1AdditiveDefinition = definition; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// INTERNAL: A reference to the native game additive definition. | ||
| /// </summary> | ||
| internal S1ItemFramework.AdditiveDefinition S1AdditiveDefinition { get; } | ||
|
|
||
| /// <summary> | ||
| /// Display material used for the additive (if applicable). | ||
| /// </summary> | ||
| public Material DisplayMaterial => S1AdditiveDefinition.DisplayMaterial; | ||
|
|
||
| /// <summary> | ||
| /// Quality modifier applied by this additive. | ||
| /// </summary> | ||
| public float QualityChange => S1AdditiveDefinition.QualityChange; | ||
|
|
||
| /// <summary> | ||
| /// Yield multiplier applied by this additive. | ||
| /// </summary> | ||
| public float YieldMultiplier => S1AdditiveDefinition.YieldMultiplier; | ||
|
|
||
| /// <summary> | ||
| /// Instant growth fraction applied by this additive (0..1). | ||
| /// </summary> | ||
| public float InstantGrowth => S1AdditiveDefinition.InstantGrowth; | ||
| } | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| #if (IL2CPPMELON) | ||
| using S1ItemFramework = Il2CppScheduleOne.ItemFramework; | ||
| using S1CoreItemFramework = Il2CppScheduleOne.Core.Items.Framework; | ||
| #elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX) | ||
| using S1ItemFramework = ScheduleOne.ItemFramework; | ||
| using S1CoreItemFramework = ScheduleOne.Core.Items.Framework; | ||
| #endif | ||
| using S1API.Internal.Utils; | ||
| using S1API.Items.Storable; | ||
| using S1API.Logging; | ||
| using UnityEngine; | ||
|
|
||
| namespace S1API.Items.Additive | ||
| { | ||
| /// <summary> | ||
| /// Builder for composing additive definitions at runtime. | ||
| /// Use fluent methods to configure additive properties before calling <see cref="Build"/>. | ||
| /// </summary> | ||
| public sealed class AdditiveDefinitionBuilder | ||
| : StorableItemDefinitionBuilderBase<AdditiveDefinitionBuilder> | ||
| { | ||
| private static readonly Log Logger = new Log("AdditiveDefinitionBuilder"); | ||
|
|
||
| private S1ItemFramework.AdditiveDefinition AdditiveDefinition => | ||
| CrossType.As<S1ItemFramework.AdditiveDefinition>(Definition); | ||
|
|
||
| /// <summary> | ||
| /// INTERNAL: Creates a new builder instance with a fresh AdditiveDefinition. | ||
| /// Only <see cref="AdditiveItemCreator"/> can instantiate this. | ||
| /// </summary> | ||
| internal AdditiveDefinitionBuilder() | ||
| : base(ScriptableObject.CreateInstance<S1ItemFramework.AdditiveDefinition>) | ||
| { | ||
| Definition.Category = S1CoreItemFramework.EItemCategory.Agriculture; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// INTERNAL: Creates a builder instance initialized by cloning an existing additive. | ||
| /// </summary> | ||
| internal AdditiveDefinitionBuilder( | ||
| S1ItemFramework.AdditiveDefinition source) | ||
| : base(source, | ||
| ScriptableObject.CreateInstance<S1ItemFramework.AdditiveDefinition>) | ||
| { | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| protected override void CopyPropertiesFrom( | ||
| S1ItemFramework.StorableItemDefinition source) | ||
| { | ||
| base.CopyPropertiesFrom(source); | ||
|
|
||
| var additiveSource = CrossType.As<S1ItemFramework.AdditiveDefinition>(source); | ||
|
|
||
| // AdditiveDefinition properties (auto-properties with private set in Mono) | ||
| AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.DisplayMaterial), | ||
| additiveSource.DisplayMaterial); | ||
| AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.QualityChange), | ||
| additiveSource.QualityChange); | ||
| AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.YieldMultiplier), | ||
| additiveSource.YieldMultiplier); | ||
| AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.InstantGrowth), | ||
| additiveSource.InstantGrowth); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sets the display material for this additive. | ||
| /// </summary> | ||
| public AdditiveDefinitionBuilder WithDisplayMaterial(Material material) | ||
| { | ||
| if (!AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.DisplayMaterial), | ||
| material)) | ||
| { | ||
| Logger.Warning( | ||
| $"Failed to set DisplayMaterial on AdditiveDefinition '{AdditiveDefinition.ID ?? "<no id>"}'."); | ||
| } | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sets the effect values for this additive. | ||
| /// </summary> | ||
| public AdditiveDefinitionBuilder WithEffects(float yieldMultiplier, float instantGrowth, float qualityChange) | ||
| { | ||
| instantGrowth = Mathf.Clamp01(instantGrowth); | ||
| if (!AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.YieldMultiplier), | ||
| yieldMultiplier)) | ||
| { | ||
| Logger.Warning( | ||
| $"Failed to set YieldMultiplier on AdditiveDefinition '{AdditiveDefinition.ID ?? "<no id>"}'."); | ||
| } | ||
|
|
||
| if (!AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.InstantGrowth), | ||
| instantGrowth)) | ||
| { | ||
| Logger.Warning( | ||
| $"Failed to set InstantGrowth on AdditiveDefinition '{AdditiveDefinition.ID ?? "<no id>"}'."); | ||
| } | ||
|
|
||
| if (!AutoPropertySetter.TrySet(AdditiveDefinition, nameof(S1ItemFramework.AdditiveDefinition.QualityChange), | ||
| qualityChange)) | ||
| { | ||
| Logger.Warning( | ||
| $"Failed to set QualityChange on AdditiveDefinition '{AdditiveDefinition.ID ?? "<no id>"}'."); | ||
| } | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Builds the item definition, registers it with the game's registry, and returns a wrapper. | ||
| /// </summary> | ||
| /// <returns>A wrapper around the created additive definition.</returns> | ||
| public new AdditiveDefinition Build() | ||
| { | ||
| return (AdditiveDefinition)base.Build(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// INTERNAL: Builds and returns the raw game item definition without registering. | ||
| /// Used internally by S1API. Modders should use <see cref="Build"/> instead. | ||
| /// </summary> | ||
| internal new S1ItemFramework.AdditiveDefinition BuildInternal() | ||
| { | ||
| return AdditiveDefinition; | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| protected override Storable.StorableItemDefinition CreateWrapper( | ||
| S1ItemFramework.StorableItemDefinition definition) | ||
| { | ||
| return new AdditiveDefinition(AdditiveDefinition); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #if (IL2CPPMELON) | ||
| using S1ItemFramework = Il2CppScheduleOne.ItemFramework; | ||
| using S1Registry = Il2CppScheduleOne.Registry; | ||
| #elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX) | ||
| using S1ItemFramework = ScheduleOne.ItemFramework; | ||
| using S1Registry = ScheduleOne.Registry; | ||
| #endif | ||
| using System; | ||
| using S1API.Internal.Utils; | ||
|
|
||
| namespace S1API.Items.Additive | ||
| { | ||
| /// <summary> | ||
| /// Provides convenient static methods for creating custom additive items. | ||
| /// Use <see cref="CreateBuilder"/> for creating additives from scratch, or <see cref="CloneFrom"/> for variants. | ||
| /// </summary> | ||
| public static class AdditiveItemCreator | ||
| { | ||
| /// <summary> | ||
| /// Creates a new builder for composing an additive definition with full flexibility. | ||
| /// Use fluent methods to configure the additive, then call Build() to register it. | ||
| /// </summary> | ||
| public static AdditiveDefinitionBuilder CreateBuilder() | ||
| { | ||
| return new AdditiveDefinitionBuilder(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Creates a new additive builder by cloning an existing additive by ID. | ||
| /// </summary> | ||
| /// <param name="sourceItemId">The ID of the additive to clone.</param> | ||
| /// <returns>A builder pre-configured with the source additive's properties.</returns> | ||
| /// <exception cref="ArgumentException">Thrown if the source item does not exist or is not an additive.</exception> | ||
| public static AdditiveDefinitionBuilder CloneFrom(string sourceItemId) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(sourceItemId)) | ||
| { | ||
| throw new ArgumentException("Source item ID cannot be null or whitespace", nameof(sourceItemId)); | ||
| } | ||
|
|
||
| var sourceDefinition = S1Registry.GetItem(sourceItemId); | ||
| if (sourceDefinition == null) | ||
| { | ||
| throw new ArgumentException($"Source item with ID '{sourceItemId}' not found in registry", nameof(sourceItemId)); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| if (!CrossType.Is(sourceDefinition, out S1ItemFramework.AdditiveDefinition additiveDef)) | ||
| { | ||
| throw new ArgumentException($"Item '{sourceItemId}' is not an AdditiveDefinition", nameof(sourceItemId)); | ||
| } | ||
|
|
||
| return new AdditiveDefinitionBuilder(additiveDef); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Creates a new additive builder by cloning an existing additive wrapper. | ||
| /// </summary> | ||
| /// <param name="source">The additive definition to clone from.</param> | ||
| /// <returns>A builder pre-configured with the source additive's properties.</returns> | ||
| public static AdditiveDefinitionBuilder CloneFrom(AdditiveDefinition source) | ||
| { | ||
| if (source == null) | ||
| { | ||
| throw new ArgumentNullException(nameof(source), "Source additive definition cannot be null"); | ||
| } | ||
|
|
||
| return new AdditiveDefinitionBuilder(source.S1AdditiveDefinition); | ||
| } | ||
| } | ||
| } | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.