reckfellENGINE

Скрипты C#: от сборки до проверенного результата

Запускаемый пример: динамический вызов, сигнал, формула и UTF-8-файл.

На этой странице

Запустить законченный пример

Нужен C#-проект Reckfell.NET.Sdk 1.0.0 с net10.0. Настройка C# описывает создание и сборку проекта.

  1. Сохраните четыре файла ниже в проект с точными именами.
  2. Выполните dotnet build в папке .csproj.
  3. Создайте уровень с корневым Entity, прикрепите ScriptToolsExample.cs и сохраните как script_tools.rscene.
  4. Запустите этот уровень. В Output ожидается SCRIPT_TOOLS count=5; signal=5; damage=25; ok=True.

Пример также записывает user://script-tools-note.txt со строкой Reckfell: 25. Это тестовая заметка, не состояние всей игры. CounterService удаляется после проверки.

NumericExpression.cs
C#
using System;
using Reckfell;

public sealed class NumericExpression : IDisposable
{
    private readonly Expression _expression = new();
    private bool _parsed;
    private int _inputCount;

    public bool TryParse(string formula, string[] names, out string error)
    {
        _parsed = false;
        error = "";
        if (_expression.Parse(formula, names) != Error.Ok)
        {
            error = _expression.GetErrorText();
            return false;
        }
        _inputCount = names.Length;
        _parsed = true;
        return true;
    }

    public bool TryEvaluate(double[] values, out double number, out string error)
    {
        number = 0;
        error = "";
        if (!_parsed || values.Length != _inputCount)
        {
            error = "Parse first and supply one value per input name.";
            return false;
        }
        using var inputs = new Reckfell.Collections.Array();
        foreach (double value in values)
        {
            if (!double.IsFinite(value))
            {
                error = "Inputs must be finite numbers.";
                return false;
            }
            inputs.Add(value);
        }
        using Variant result = _expression.Execute(inputs, null, false, true);
        if (_expression.HasExecuteFailed())
        {
            error = _expression.GetErrorText();
            return false;
        }
        if (result.VariantType is not (Variant.Type.Int or Variant.Type.Float) ||
            !double.IsFinite(result.AsDouble()))
        {
            error = "Expected a finite numeric result.";
            return false;
        }
        number = result.AsDouble();
        return true;
    }

    public void Dispose() => _expression.Dispose();
}
TextNoteStore.cs
C#
using System.Text;
using Reckfell;

public static class TextNoteStore
{
    public const string Path = "user://script-tools-note.txt";
    public const int MaximumBytes = 4096;

    public static bool TryWrite(string text, out Error error)
    {
        error = Error.InvalidParameter;
        if (Encoding.UTF8.GetByteCount(text) > MaximumBytes) return false;
        using var file = FileAccess.Open(Path, FileAccess.ModeFlags.Write);
        if (file is null)
        {
            error = FileAccess.GetOpenError();
            return false;
        }
        if (!file.StoreString(text))
        {
            error = file.GetError();
            return false;
        }
        file.Flush();
        error = file.GetError();
        return error == Error.Ok;
    }

    public static bool TryRead(out string text, out Error error)
    {
        text = "";
        using var file = FileAccess.Open(Path, FileAccess.ModeFlags.Read);
        if (file is null)
        {
            error = FileAccess.GetOpenError();
            return false;
        }
        if (file.GetLength() > MaximumBytes)
        {
            error = Error.InvalidData;
            return false;
        }
        string candidate = file.GetAsText();
        error = file.GetError();
        if (error != Error.Ok && error != Error.FileEof) return false;
        text = candidate;
        error = Error.Ok;
        return true;
    }
}
CounterService.cs
C#
using Reckfell;

public partial class CounterService : Entity
{
    [Signal] public delegate void CountChangedEventHandler(int count);
    private int _count;
    public int Count => _count;

    public bool TryAdd(int amount)
    {
        if (amount <= 0 || amount > 1000 - _count) return false;
        _count += amount;
        EmitSignal(SignalName.CountChanged, _count);
        return true;
    }
}
ScriptToolsExample.cs
C#
using Reckfell;

public partial class ScriptToolsExample : Entity
{
    public bool Succeeded { get; private set; }

    public override void _Ready()
    {
        var counter = new CounterService();
        AddChild(counter);
        int observed = 0;
        counter.CountChanged += value => observed = value;
        bool added = counter.Call(CounterService.MethodName.TryAdd, 5).AsBool();
        using var expression = new NumericExpression();
        bool parsed = expression.TryParse("base_damage * multiplier",
            new[] { "base_damage", "multiplier" }, out string error);
        double damage = 0;
        bool evaluated = parsed && expression.TryEvaluate(new[] { 20.0, 1.25 }, out damage, out error);
        bool saved = TextNoteStore.TryWrite("Reckfell: 25", out Error writeError);
        bool read = TextNoteStore.TryRead(out string text, out Error readError);
        Succeeded = added && counter.Count == 5 && observed == 5 && evaluated &&
            damage == 25 && saved && read && text == "Reckfell: 25";
        ReckfellApi.Print($"SCRIPT_TOOLS count={counter.Count}; signal={observed}; damage={damage}; ok={Succeeded}");
        if (!Succeeded) ReckfellApi.PrintErr($"SCRIPT_TOOLS failed: {error}; write={writeError}; read={readError}");
        counter.Free();
    }
}

Разобрать по отдельности

C# и Variant · Формулы · Файлы · Логи · Чтение API · Шаблоны

Если ok=False, разберите напечатанные ошибки по этапам: динамический вызов, разбор/вычисление, открытие/запись/чтение файла. Не продолжайте обработку результата, который уже вернул отказ.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.