Spite up project, added BeltData, some asoited compoents, remvoed unused usings, and removed uneeded comment code.
This commit is contained in:
231
src/Recipes/Recipe.cs
Normal file
231
src/Recipes/Recipe.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
namespace FoodFactory.Recipes;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Arch.Core;
|
||||
using Arch.Core.Extensions;
|
||||
using Arch.Core.Extensions.Dangerous;
|
||||
using FoodFactory.Items;
|
||||
using Godot;
|
||||
|
||||
public abstract record Recipe(string Name, BlueprintId[]? BlueprintIds, bool[] RequireAll, Tags[] Inputs, Tags[] Exclude, RecipeOutput RecipeOutput, RecipeAction Action = default, bool InputsOrdered = true)
|
||||
{
|
||||
public abstract bool CanProcess(in RecipeContext context);
|
||||
public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder);
|
||||
}
|
||||
public readonly record struct RecipeOutput
|
||||
{
|
||||
public int? Min { get; }
|
||||
public int? Max { get; }
|
||||
[MemberNotNullWhen(true, nameof(Min), nameof(Max))]
|
||||
public bool IsExact => Min.HasValue && Max.HasValue && Min == Max;
|
||||
[MemberNotNullWhen(true, nameof(Min), nameof(Max))]
|
||||
public bool IsRange => Min.HasValue && Max.HasValue && Min != Max;
|
||||
public bool IsUnbounded => Min == null && Max == null;
|
||||
|
||||
public RecipeOutput(int exact)
|
||||
{
|
||||
Min = exact;
|
||||
Max = exact;
|
||||
}
|
||||
|
||||
public RecipeOutput(int min, int max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
private RecipeOutput(int? min, int? max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
public static RecipeOutput Any => new(null, null);
|
||||
}
|
||||
public struct CompiledRecipe
|
||||
{
|
||||
|
||||
public Recipe RecipeRef;
|
||||
// public BlueprintId[] InputBlueprints;
|
||||
public ItemEntry[] ItemEntries;
|
||||
public bool IsOrdered;
|
||||
}
|
||||
public struct ItemEntry
|
||||
{
|
||||
public bool RequireAll;
|
||||
public Tags InputTags;
|
||||
public Tags ExcludeTags;
|
||||
public BlueprintId? Blueprint;
|
||||
}
|
||||
public static class RecipeCompiler
|
||||
{
|
||||
public static CompiledRecipe Compile(Recipe recipe) => new()
|
||||
{
|
||||
RecipeRef = recipe,
|
||||
ItemEntries = BuildEntries(recipe),
|
||||
// IsOrdered = recipe.InputsOrdered,
|
||||
};
|
||||
private static ItemEntry[] BuildEntries(Recipe recipe)
|
||||
{
|
||||
var entries = new ItemEntry[recipe.Inputs.Length];
|
||||
|
||||
for (var i = 0; i < entries.Length; i++)
|
||||
{
|
||||
entries[i] = new ItemEntry
|
||||
{
|
||||
RequireAll = recipe.RequireAll[i],
|
||||
InputTags = recipe.Inputs[i],
|
||||
ExcludeTags = recipe.Exclude[i],
|
||||
// Blueprint = recipe.BlueprintIds?[i],
|
||||
};
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
public record BurnItemRecipe : Recipe
|
||||
{
|
||||
public BurnItemRecipe() : base("Burn_item",
|
||||
BlueprintIds: null,
|
||||
RequireAll: [false],
|
||||
Inputs: [new Tags("burnable")],
|
||||
Exclude: [new Tags("burned")],
|
||||
RecipeOutput: RecipeOutput.Any,
|
||||
Action: new RecipeAction("cook"),
|
||||
InputsOrdered: true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override bool CanProcess(in RecipeContext context)
|
||||
{
|
||||
if (context.Items[0].TryGet<Temperature>(out var temp) && context.Items[0].TryGet<BurnableTemp>(out var burnableTemp) && temp > burnableTemp.Temperature)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder) => new(BurnItem);
|
||||
|
||||
private void BurnItem(RecipeContext context)
|
||||
{
|
||||
// context.Entity[0].Remove<BurnableTemp>();
|
||||
context.Items[0].Add(new BurnedItem(context.Items[0].Get<Temperature>(), "Was Burned as some time thing"));
|
||||
context.Items[0].Set(context.Items[0].Get<Tags>().WithOut("burnable").With("burned"));
|
||||
context.Items[0].Set($"Burned_{context.Items[0].Get<Name>().Value}");
|
||||
if (context.Items[0].Has<Color>())
|
||||
{
|
||||
context.Items[0].Set(context.Items[0].Get<Color>() * Colors.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Items[0].Add(Colors.Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
public record OnionSliceRecipe() : Recipe(Name: "Onion_Slice",
|
||||
BlueprintIds: null,
|
||||
RequireAll: [false],
|
||||
Inputs: [new Tags("onion", "sliceable")],
|
||||
Exclude: [new Tags()],
|
||||
Action: "slice",
|
||||
RecipeOutput: new RecipeOutput(2)
|
||||
)
|
||||
{
|
||||
public override bool CanProcess(in RecipeContext context) => true;
|
||||
|
||||
public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder)
|
||||
{
|
||||
builder.AddRemove(true);
|
||||
builder.AddCreate(Slice);
|
||||
builder.AddCreate(Slice);
|
||||
return builder.Build();
|
||||
}
|
||||
private Entity Slice(in RecipeContext context)
|
||||
{
|
||||
Span<Entity> span = stackalloc Entity[1];
|
||||
var signature = context.World.GetSignature(context.Items[0]);
|
||||
context.World.Create(span, signature, 1);
|
||||
PotatoCookRecipe.CopyEntities(context.Items, span, context.World);
|
||||
span[0].Set(new Name("Sliced " + context.Items[0].Get<Name>().Value));
|
||||
span[0].Set(new Mass(context.Items[0].Get<Mass>().Value * .5));
|
||||
span[0].Set(span[0].Get<Tags>().With("sliced"));
|
||||
return span[0];
|
||||
}
|
||||
}
|
||||
public record PotatoCookRecipe() : Recipe(Name: "Potato_Cook",
|
||||
BlueprintIds: null,
|
||||
RequireAll: [false],
|
||||
Inputs: [new Tags("potato", "raw")],
|
||||
Exclude: [new Tags()],
|
||||
InputsOrdered: true,
|
||||
Action: "cook",
|
||||
RecipeOutput: new RecipeOutput(1))
|
||||
{
|
||||
public override bool CanProcess(in RecipeContext context)
|
||||
{
|
||||
if (!(context.Items[0].TryGet<Temperature>(out var temp) && temp.Fahrenheit > 350))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder)
|
||||
{
|
||||
builder.AddRemove(true);
|
||||
builder.AddCreate(NewPotato);
|
||||
return builder.Build();
|
||||
}
|
||||
private Entity NewPotato(in RecipeContext context)
|
||||
{
|
||||
Span<Entity> span = stackalloc Entity[1];
|
||||
var signature = context.World.GetSignature(context.Items[0]);
|
||||
context.World.Create(span, signature, 1);
|
||||
CopyEntity(context.Items[0], span[0], context.World);
|
||||
|
||||
span[0].Set(new Name("Cooked_Potato"));
|
||||
span[0].Set(context.Items[0].Get<Tags>().With("cooked").WithOut("raw"));
|
||||
// span[0].Set(context.Entity[0].Get<Temperature>());
|
||||
if (context.Items[0].Has<Color>())
|
||||
{
|
||||
context.Items[0].Set(context.Items[0].Get<Color>() * Colors.Brown);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Items[0].Add(Colors.Brown);
|
||||
}
|
||||
return span[0];
|
||||
}
|
||||
public static void CopyEntities(Span<Entity> from, Span<Entity> to, World world)
|
||||
{
|
||||
Debug.Assert(from.Length == to.Length);
|
||||
for (int i = 0; i < from.Length; i++)
|
||||
{
|
||||
CopyEntity(from[i], to[i], world);
|
||||
}
|
||||
|
||||
}
|
||||
public static void CopyEntity(Entity src, Entity dst, World world)
|
||||
{
|
||||
var srcData = world.GetEntityData(src);
|
||||
var dstData = world.GetEntityData(dst);
|
||||
|
||||
var components = srcData.Archetype
|
||||
.GetChunk(srcData.Slot.ChunkIndex)
|
||||
.Components;
|
||||
var componentsDst = dstData.Archetype
|
||||
.GetChunk(dstData.Slot.ChunkIndex)
|
||||
.Components;
|
||||
|
||||
int srcIndex = srcData.Slot.Index;
|
||||
int dstIndex = dstData.Slot.Index;
|
||||
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
componentsDst[i].SetValue(components[i].GetValue(srcIndex), dstIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user