Files
FoodFactory/src/VoxelGrid/VoxelGridNode.cs

151 lines
4.0 KiB
C#

namespace ChickenGameTest;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Arch.Core;
using Arch.Core.Extensions;
using Arch.LowLevel;
using Arch.System;
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using FoodFactory;
using FoodFactory.Recipes;
using Godot;
public class BacterialSystem : BaseSystem<World, float>
{
private QueryDescription _desc = new QueryDescription().WithAll<Bacteria, Temperature>();
public static Resources<List<BacteriaData>> Resources = new();
public BacterialSystem(World world) : base(world)
{
}
public override void Update(in float t)
{
var delta = t;
World.ParallelQuery(in _desc, (Entity entity, ref Bacteria bacteria, ref Temperature temperature) =>
{
var handle = bacteria.Data;
var data = Resources.Get(in handle);
for (int i = 0; i < data.Count; i++)
{
data[i] = data[i] with { Count = BacteriaModel.UpdatePopulation(data[i].Count, temperature.Celsius, delta) };
// GD.Print(data[i].Count);
if (data[i].Count <= 0.5)
{
data.RemoveAt(i);
i--;
}
}
});
}
}
//Will Liklely be the game instead of a node like this
[Meta(typeof(IAutoNode))]// [Tool]
public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridRegistry>, IProvide<IItemRenderer>, IProvide<IRecipes>, IProvide<IBlueprintManger>, IProvide<World>
{
public override void _Notification(int what) => this.Notify(what);
private World _world = default!;
World IProvide<World>.Value() => _world;
private IVoxelGridRegistry _voxelGridRegistry = default!;
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => _voxelGridRegistry;
private IBlueprintManger _blueprintManger = default!;
IBlueprintManger IProvide<IBlueprintManger>.Value() => _blueprintManger;
private Recipes _recipes = default!;
IRecipes IProvide<IRecipes>.Value() => _recipes;
private IItemRenderer _itemRenderer = default!;
IItemRenderer IProvide<IItemRenderer>.Value() => _itemRenderer;
Group<float> _systems;
public override void _Ready()
{
// GD.Print();
base._Ready();
_voxelGridRegistry = new VoxelRegistry();
_itemRenderer = new ItemRenderSimple();
_blueprintManger = new BlueprintManger();
_recipes = new Recipes();
_world = World.Create();
_systems = new Group<float>("Items", new BacterialSystem(_world));
AddChild(_itemRenderer as Node);
Timer timer = new Timer() { WaitTime = .25f, Autostart = true };//TEST
AddChild(timer);//TEST
// timer.Timeout += _itemRenderer.Tick;//TEST
timer.Timeout += () =>
{
_systems.BeforeUpdate(.25f);
_systems.Update(.25f);
_systems.AfterUpdate(.25f);
};
_systems.Initialize();
this.Provide();
}
public override void _Input(InputEvent @event)
{
if (@event.IsActionPressed("ui_up"))
{
foreach (var item in GetChildren())
{
if (item is ConveyorBeltStraight conveyor)
{
var node = conveyor.GetNode("Node") as TestItemConveyor;
node.IsReversed = !node.IsReversed;
}
}
}
}
public override void _ExitTree()
{
base._ExitTree();
_systems.Dispose();
_world.Dispose();
}
}
public static class BacteriaModel
{
// population = current bacteria count
// temperature = degrees Celsius
// deltaTime = elapsed time (hours)
public static double UpdatePopulation(
double population,
double temperature,
double deltaTime)
{
double rate;
// Very cold -> slight die-off
if (temperature <= 5)
{
rate = -0.1;
}
// Growth zone
else if (temperature < 35)
{
rate = 0.06 * (temperature - 5);
}
// Hot but still survivable
else if (temperature < 60)
{
rate = 1.8 - 0.08 * (temperature - 35);
}
// Dangerous heat -> bacteria die
else
{
rate = -0.8;
}
// Population update
double newPopulation =
population + (deltaTime * population * rate);
// Prevent negative bacteria counts
return Math.Max(0, newPopulation);
}
}