MonoGame - загрузка JSON через конвейер контента - PullRequest
1 голос
/ 01 апреля 2019

Я создаю RPG-игру, и мне нужно загрузить карты с помощью Tiled.У меня есть черепичная часть (я использую MonoGame.Extended).Но мне нужны дополнительные данные о карте.Я планирую использовать файл JSON, который содержит необходимую информацию.Однако мне бы хотелось, чтобы он проходил через конвейер контента, поскольку он напрямую связан с картами плиток.

Я пытался использовать расширение собственного конвейера контента.Он использовал JSON.Net для десериализации файла JSON в Dictionary<string, dynamic>.Однако, когда я скомпилировал файл DLL и попытался ссылаться на него в инструмент конвейера, инструмент конвейера всегда зависал.

Импорт контента:

using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;

using Newtonsoft.Json;

namespace JsonExtension
{

    [ContentImporter(".json", DefaultProcessor = "JsonProcessor")]
    public class JsonImporter : ContentImporter<Dictionary<string, dynamic>>
    {

        public override Dictionary<string, dynamic> Import(string filename, ContentImporterContext context)
        {
            context.Logger.LogMessage("Importing JSON file: {0}", filename);

            using (var streamReader = new StreamReader(filename))
            {
                JsonSerializer serializer = new JsonSerializer();
                return (Dictionary<string, dynamic>)serializer.Deserialize(streamReader, typeof(Dictionary<string, dynamic>));
            }
        }

    }

}

Процессор контента:

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Content.Pipeline;

namespace JsonExtension
{
    [ContentProcessor]
    public class JsonProcessor : ContentProcessor<Dictionary<string, dynamic>, Dictionary<string, dynamic>>
    {
        public override Dictionary<string, dynamic> Process(Dictionary<string, dynamic> input, ContentProcessorContext context)
        {
            context.Logger.LogMessage("Processing JSON");

            return input;
        }
    }
}

Content Type Writer:

using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;

using Newtonsoft.Json;

namespace JsonExtension
{
    [ContentTypeWriter]
    class JsonTypeWriter : ContentTypeWriter<Dictionary<string, dynamic>>
    {
        protected override void Write(ContentWriter output, Dictionary<string, dynamic> value)
        {
            output.Write(JsonConvert.SerializeObject(value));
        }

        public override string GetRuntimeType(TargetPlatform targetPlatform)
        {
            return typeof(Dictionary<string, dynamic>).AssemblyQualifiedName;
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return "JsonExtension.JsonReader";
        }
    }
}

Есть ли лучший способ хранения метаданных карты Tiled?Или есть лучший способ импортировать его через конвейер?Или я что-то не так делаю со своим импортером контента?

1 Ответ

1 голос
/ 03 апреля 2019

Ошибка связана с типом dynamic.Конвейер требует, чтобы все типы были разрешаемыми и создаваемыми с помощью Reflection.

Для универсальных коллекций существует вторичный распознаватель для сериализации и десериализации каждого типа в универсальном.Строка Dictionary<string, dynamic> имеет два типа и с непознаваемым типом, связанным System.Collections.Generic.Dictionary, System.String и dynamic.dynamic не имеет подсказок относительно того, какой тип использовать, и не может быть разрешен, что приводит к ошибке.

Простое решение - сохранить данные в виде строки json (что вы уже делаете сейчас, за исключением типавы пытаетесь сохранить его в is dynamic) и десериализовать String в его объект после того, как Content.Load вернул данные.

Другими словами, используйте Dictionary<string, string> в качестве типа процессора контента.


Более простым решением было бы скопировать файл JSON в выходной каталог.Создайте действие «копировать, если новее» и используйте System.IO.File для его чтения и JSON.NET для десериализации его в объект в методе Initialize Game1.

...