Skip to content

Instantly share code, notes, and snippets.

@PichotM
Created January 29, 2020 01:49
Show Gist options
  • Save PichotM/2b3dd445ba640a8867dfae84450fba48 to your computer and use it in GitHub Desktop.
Save PichotM/2b3dd445ba640a8867dfae84450fba48 to your computer and use it in GitHub Desktop.
using System;
using CodeWalker.GameFiles;
using System.IO;
using SharpDX;
using System.Collections.Generic;
using NodReader;
using CodeWalker;
namespace YNDMover
{
public partial class MainYND
{
private string basePath = "NODE_FOLDER";
private string targetPath = "NODE_DESTINATION";
private List<YndFile> AllYnds = new List<YndFile>();
private static Dictionary<int, List<Node>> NodeList = new Dictionary<int, List<Node>>();
private static Dictionary<int, NodeLink[]> LinkList = new Dictionary<int, NodeLink[]>();
private static List<NodeData> NodeDataList = new List<NodeData>();
private static List<YndFile> LegacyYndFileList = new List<YndFile>();
private static Dictionary<int, YndFile> YndFileList = new Dictionary<int, YndFile>();
private static Dictionary<int, YndFile> YndFileList2 = new Dictionary<int, YndFile>();
private static List<NewLink> NewLinkList = new List<NewLink>();
private static string logContent = "";
private void WriteLine(string text)
{
logContent += text + "\n";
}
private void DoNodeStuff(YndNode uselessNode, YndNode centerNode, YndNode outerNode, YndLink link)
{
NewLink newLink = new NewLink();
foreach (NodeData nodeData in NodeDataList)
{
if (nodeData.newNode.AreaID == uselessNode.AreaID && nodeData.newNode.NodeID == uselessNode.NodeID)
{
NodeList[nodeData.newNode.AreaID].Remove(nodeData.Node);
}
else if (nodeData.newNode == centerNode)
{
newLink.centerNode = nodeData.Node;
}
else if (nodeData.newNode == outerNode)
{
newLink.outerNode = nodeData.Node;
}
}
newLink.link = link;
NewLinkList.Add(newLink);
}
private static void Main()
{
MainYND mainYND = new MainYND();
mainYND.Launch();
}
private void BuildNodes(Dictionary<int, YndFile> yndList)
{
NodeDataList.Clear();
foreach (KeyValuePair<int, List<Node>> entry in NodeList)
{
YndFile ynd;
if (!yndList.ContainsKey(entry.Key))
{
ynd = new YndFile();
ynd.AreaID = (ushort)entry.Key;
ynd.NodeDictionary = new NodeDictionary();
yndList[entry.Key] = ynd;
}
else
{
ynd = yndList[entry.Key];
}
foreach (Node node in entry.Value)
{
YndNode newNode = ynd.AddNode();
newNode.AreaID = (ushort)ynd.AreaID;
newNode.SetPosition(new Vector3(node.PositionX / 4.0f, node.PositionY / 4.0f, node.PositionZ / 32.0f));
var flag = node.LinkCountFlags.Value & 7;
var flags5 = (uint)(flag);
if (BitUtil.IsBitSet(node.Flags2, 6)) // Freeway
{
flags5 = BitUtil.UpdateBit(flags5, 0, BitUtil.IsBitSet(flags5, 0));
flags5 = BitUtil.UpdateBit(flags5, 1, true);
flags5 = BitUtil.UpdateBit(flags5, 2, true);
}
if (BitUtil.IsBitSet(node.Flags2, 2) && !BitUtil.IsBitSet(flags5, 0)) // Junction
{
flags5 = BitUtil.UpdateBit(flags5, 0, true);
flags5 = BitUtil.UpdateBit(flags5, 1, BitUtil.IsBitSet(flags5, 1));
flags5 = BitUtil.UpdateBit(flags5, 2, true);
}
newNode.Flags0 = node.Flags0;
newNode.Flags1 = node.Flags1;
newNode.Flags2 = node.Flags2;
newNode.Flags3 = node.Flags3;
newNode.Flags4 = node.Flags4;
newNode.LinkCountUnk = (int)flags5;
//Console.WriteLine(newNode.LinkCountUnk);
bool IsPedNode = newNode.Flags4 > 100;
if (IsPedNode)
{
ynd.NodeDictionary.NodesCountPed++;
}
else
{
ynd.NodeDictionary.NodesCountVehicle++;
}
NodeData nodeData = new NodeData();
nodeData.Node = node;
nodeData.newNode = newNode;
nodeData.AreaID = newNode.AreaID;
NodeDataList.Add(nodeData);
}
}
}
private void BuildNodesLinks(Dictionary<int, YndFile> yndList)
{
foreach (KeyValuePair<int, YndFile> entry in yndList)
{
YndFile ynd = entry.Value;
foreach (YndNode yndNode in ynd.Nodes)
{
NodeData nodeData = new NodeData();
foreach (NodeData iindoe in NodeDataList)
{
if (iindoe.newNode == yndNode)
{
nodeData = iindoe;
break;
}
}
int links = nodeData.Node.LinkCountFlags.Value >> 3;
if (links != 0)
{
for (var i = 0; i < links; i++)
{
int linkArrayIndex = nodeData.Node.LinkID + i;
NodeLink targetLink = LinkList[nodeData.Node.AreaID][linkArrayIndex];
foreach (NodeData node2 in NodeDataList)
{
if (node2.Node.NodeID == targetLink.NodeID && node2.AreaID == targetLink.AreaID)
{
YndLink newLink = yndNode.AddLink(node2.newNode);
newLink.Flags0 = targetLink.Flags0;
newLink.Flags1 = targetLink.Flags1;
newLink.Flags2 = targetLink.Flags2;
newLink.UpdateLength();
}
}
}
}
}
}
if (NewLinkList != null && NewLinkList.Count != 0)
{
foreach(NewLink newLink in NewLinkList)
{
YndNode centerNode = null;
YndNode outerNode = null;
foreach(NodeData node in NodeDataList)
{
if (node.Node.AreaID == newLink.centerNode.AreaID && node.Node.NodeID == newLink.centerNode.NodeID)
{
centerNode = node.newNode;
}
else if (node.Node.AreaID == newLink.outerNode.AreaID && node.Node.NodeID == newLink.outerNode.NodeID)
{
outerNode = node.newNode;
}
if (outerNode != null && centerNode != null) { break; }
}
if (outerNode != null && centerNode != null)
{
YndLink n1 = outerNode.AddLink(centerNode);
n1.Flags0 = newLink.link.Flags0;
n1.Flags1 = newLink.link.Flags1;
n1.Flags2 = newLink.link.Flags2;
YndLink n2 = centerNode.AddLink(outerNode);
n2.Flags0 = newLink.link.Flags0;
n2.Flags1 = newLink.link.Flags1;
n2.Flags2 = newLink.link.Flags2;
n2.UpdateLength();
n1.UpdateLength();
}
else
{
WriteLine("ERROR.");
}
}
}
}
void Launch()
{
if (basePath == null || !Directory.Exists(basePath))
{
WriteLine("Wrong path");
Console.ReadKey(true);
return;
}
string[] yndFiles = Directory.GetFiles(basePath.Replace("\\", "//"), "*.ynd");
if (yndFiles == null || yndFiles.Length == 0)
{
WriteLine("0 ynd file in this folder.");
Console.ReadKey(true);
return;
}
foreach (string filePath in yndFiles)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
if (true || fileName == "nodes528")
{
YndFile ynd = new YndFile();
byte[] data = File.ReadAllBytes(filePath);
ynd.Load(data);
string pathDir = Path.GetDirectoryName(filePath);
string areaidstr = fileName.ToLowerInvariant().Replace("nodes", "");
int areaid = 0;
int.TryParse(areaidstr, out areaid);
ynd.AreaID = areaid;
LegacyYndFileList.Add(ynd);
Console.WriteLine(ynd.AreaID.ToString());
WriteLine("----------------" + ynd.AreaID.ToString() + "--------------");
if (ynd.NodeDictionary.Links != null)
WriteLine("Links " + ynd.NodeDictionary.Links.Length + " | " + (ynd.Links != null ? ynd.Links.Length.ToString() : "0"));
if (ynd.NodeDictionary.LinksCount != null)
WriteLine("LinksCount " + ynd.NodeDictionary.LinksCount);
if (ynd.NodeDictionary.Nodes != null)
WriteLine("Nodes " + ynd.NodeDictionary.Nodes.Length + " | " + ynd.Nodes.Length);
if (ynd.NodeDictionary.NodesCount != null)
WriteLine("NodesCount " + ynd.NodeDictionary.NodesCount);
if (ynd.NodeDictionary.NodesCountPed != null)
WriteLine("NodesCountPed " + ynd.NodeDictionary.NodesCountPed);
if (ynd.NodeDictionary.NodesCountVehicle != null)
WriteLine("NodesCountVehicle " + ynd.NodeDictionary.NodesCountVehicle);
if (ynd.NodeDictionary.NodesPointer != null)
WriteLine("NodesPointer " + ynd.NodeDictionary.NodesPointer);
WriteLine("------------------------------");
}
}
foreach(YndFile ynd in LegacyYndFileList)
{
NodeList[ynd.AreaID] = new List<Node>();
foreach (Node node in ynd.NodeDictionary.Nodes)
{
//if (node.AreaID == ynd.AreaID)
NodeList[ynd.AreaID].Add(node);
}
if (NodeList[ynd.AreaID] != null)
{
WriteLine("Total nodes " + NodeList[ynd.AreaID].Count + " in " + ynd.AreaID);
if (ynd.Junctions != null)
WriteLine("Total junctions " + ynd.Junctions.Length);
}
LinkList[ynd.AreaID] = ynd.NodeDictionary.Links;
}
BuildNodes(YndFileList);
BuildNodesLinks(YndFileList);
int removedNodes = 0;
foreach (KeyValuePair<int, YndFile> entry in YndFileList)
{
YndFile ynd = entry.Value;
foreach (YndNode node in ynd.Nodes)
{
if (node.Flags1 == 120 && node.LinkCount > 0)
{
foreach (YndLink nodeLink in node.Links)
{
if (nodeLink.Node1.LinkCountUnk != 7 && nodeLink.Node1.LinkCountUnk != 5 && !BitUtil.IsBitSet(nodeLink.Node1.Flags2, 2))
{
foreach (YndLink nodeLink1 in nodeLink.Node1.Links)
{
if ((nodeLink1.Node1.LinkCountUnk == 7 || nodeLink1.Node1.LinkCountUnk == 5) && !BitUtil.IsBitSet(nodeLink1.Node1.Flags2, 2))
{
DoNodeStuff(nodeLink1.Node2, nodeLink1.Node1, node, nodeLink1);
removedNodes++;
}
}
}
if (nodeLink.Node2.LinkCountUnk != 7 && nodeLink.Node2.LinkCountUnk != 5 && !BitUtil.IsBitSet(nodeLink.Node2.Flags2, 2))
{
foreach (YndLink nodeLink2 in nodeLink.Node2.Links)
{
if ((nodeLink2.Node2.LinkCountUnk == 7 || nodeLink2.Node2.LinkCountUnk == 5) && !BitUtil.IsBitSet(nodeLink2.Node1.Flags2, 2))
{
DoNodeStuff(nodeLink2.Node1, nodeLink2.Node2, node, nodeLink2);
removedNodes++;
}
}
}
}
}
}
}
WriteLine("Removed nodes : " + removedNodes);
BuildNodes(YndFileList2);
BuildNodesLinks(YndFileList2);
WriteLine(YndFileList2.Count.ToString());
foreach (KeyValuePair<int, YndFile> entry in YndFileList2)
{
YndFile ynd = entry.Value;
byte[] newData = ynd.Save();
if (ynd.NodeDictionary.Links != null)
WriteLine("Links " + ynd.NodeDictionary.Links.Length + " | " + (ynd.Links != null ? ynd.Links.Length.ToString() : "0"));
if (ynd.NodeDictionary.LinksCount != null)
WriteLine("LinksCount " + ynd.NodeDictionary.LinksCount);
if (ynd.NodeDictionary.Nodes != null)
WriteLine("Nodes " + ynd.NodeDictionary.Nodes.Length + " | " + ynd.Nodes.Length);
if (ynd.NodeDictionary.NodesCount != null)
WriteLine("NodesCount " + ynd.NodeDictionary.NodesCount);
if (ynd.NodeDictionary.NodesCountPed != null)
WriteLine("NodesCountPed " + ynd.NodeDictionary.NodesCountPed);
if (ynd.NodeDictionary.NodesCountVehicle != null)
WriteLine("NodesCountVehicle " + ynd.NodeDictionary.NodesCountVehicle);
if (ynd.NodeDictionary.NodesPointer != null)
WriteLine("NodesPointer " + ynd.NodeDictionary.NodesPointer);
WriteLine("------------------------------");
WriteLine("Successfully written " + ynd.AreaID + " node.");
Console.WriteLine("Successfully written " + ynd.AreaID + " node.");
File.WriteAllBytes(targetPath + "//nodes" + ynd.AreaID.ToString() + ".ynd", newData);
}
Console.Write("\nPress any key to exit...");
File.WriteAllText("log.txt", logContent);
Console.ReadKey(true);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment