using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using Intrepid.Gameplay.Journey; using UnityEditor; namespace Editor.GON.WorldEditor { public static class JourneyCommitter { public static List Commit(WorldLayoutSO layout, JGraphSO graph) { var messages = WorldLayoutValidator.Validate(layout); if (WorldLayoutValidator.HasErrors(messages) || graph is null) { if (graph is null) { messages.Add(new WorldValidationMessage(WorldValidationSeverity.Error, "No target JGraphSO selected.")); } return messages; } layout.EnsureDefaults(); graph.sourceWorldLayoutId = layout.id; graph.publishedAt = DateTime.UtcNow.ToString("O"); graph.schemaVersion = 1; graph.stages = BuildStages(layout); graph.endpoints = BuildEndpoints(layout); graph.connections = BuildConnections(layout); graph.contentHash = ComputeContentHash(graph); graph.EnsureDefaults(); EditorUtility.SetDirty(graph); AssetDatabase.SaveAssets(); return messages; } private static List BuildStages(WorldLayoutSO layout) { var stages = new List(); foreach (var source in layout.stages) { if (source is null) { continue; } source.EnsureDefaults(); var stage = new JStage { id = source.id, displayName = source.displayName, worldLayer = source.worldLayer, occupiedTiles = new List(source.occupiedTiles) }; stages.Add(stage); } return stages; } private static List BuildEndpoints(WorldLayoutSO layout) { var endpoints = new List(); foreach (var source in layout.endpoints) { if (source is null) { continue; } endpoints.Add(new JEndpoint { id = source.id, stageId = source.stageId, worldTile = source.worldTile, kind = source.kind, required = source.required, socketFace = source.socketFace }); } return endpoints; } private static List BuildConnections(WorldLayoutSO layout) { var connections = new List(); foreach (var source in layout.connections) { if (source is null) { continue; } connections.Add(new JConnection { id = source.id, endpointAId = source.endpointAId, endpointBId = source.endpointBId, directionality = source.directionality }); } return connections; } private static string ComputeContentHash(JGraphSO graph) { var builder = new StringBuilder(); builder.Append(graph.sourceWorldLayoutId).Append('|').Append(graph.schemaVersion).AppendLine(); foreach (var stage in graph.stages) { builder.Append("S|").Append(stage.id).Append('|').Append(stage.displayName).Append('|') .Append(stage.worldLayer).AppendLine(); foreach (var tile in stage.occupiedTiles) { builder.Append("T|").Append(tile.x).Append('|').Append(tile.y).AppendLine(); } } foreach (var endpoint in graph.endpoints) { builder.Append("E|").Append(endpoint.id).Append('|').Append(endpoint.stageId).Append('|') .Append(endpoint.worldTile.x).Append('|').Append(endpoint.worldTile.y).Append('|') .Append(endpoint.kind).Append('|').Append(endpoint.required).Append('|') .Append(endpoint.socketFace).AppendLine(); } foreach (var connection in graph.connections) { builder.Append("C|").Append(connection.id).Append('|').Append(connection.endpointAId).Append('|') .Append(connection.endpointBId).Append('|').Append(connection.directionality).AppendLine(); } using var sha = SHA256.Create(); var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString())); var result = new StringBuilder(bytes.Length * 2); foreach (var value in bytes) { result.Append(value.ToString("x2")); } return result.ToString(); } } }