public static OTBNode ParseOTBTree(byte[] serializedTreeData) { var treeBuilder = new OTBTreeBuilder(serializedTreeData); for (int i = 0; i < serializedTreeData.Length; i++) { var markupByte = (OTBMarkupByte)serializedTreeData[i]; switch (markupByte) { case OTBMarkupByte.Escape: i++; break; case OTBMarkupByte.Start: treeBuilder.AddNodeBegin(i + 1, OTBNodeType.NotSetYet); break; case OTBMarkupByte.End: treeBuilder.AddNodeEnd(i); break; } } return(treeBuilder.BuildTree()); }
public static World ParseWorld(byte[] serializedWorldData) { if (serializedWorldData.Length < MinimumWorldSize) { throw new TFSWorldLoadingException(); } //var otbTree = ExtractOTBTree(serializedWorldData); var otbTree = new OTBTreeBuilder(serializedWorldData).BuildTree(); var world = new World(); ParseOTBTreeRootNode(otbTree, world); Parse(otbTree.Children[0], world); throw new NotImplementedException(); }
private static OTBNode ExtractOTBTree(byte[] serializedWorldData) { var stream = new ReadOnlyMemoryStream(serializedWorldData); // Skipping the first 4 bytes coz they are used to store a... identifier? stream.Skip(IdentifierLength); var treeBuilder = new OTBTreeBuilder(serializedWorldData); while (!stream.IsOver) { var currentMark = (OTBMarkupByte)stream.ReadByte(); if (currentMark < OTBMarkupByte.Escape) { /// Since <see cref="OTBMarkupByte"/> can only have values Escape (0xFD), Start (0xFE) and /// End (0xFF), if currentMark < Escape, then it's just prop data /// and we can safely skip it. continue; } var nodeType = (OTBNodeType)stream.ReadByte(); switch (currentMark) { case OTBMarkupByte.Start: treeBuilder.AddNodeBegin( start: stream.Position, type: nodeType); break; case OTBMarkupByte.End: treeBuilder.AddNodeEnd(stream.Position); break; case OTBMarkupByte.Escape: stream.Skip(); break; default: throw new InvalidOperationException(); } } return(treeBuilder.BuildTree()); }
private static void LoadItemsFromOTB(string path) { var data = FileManager.ReadFileToByteArray(path); var tree = new OTBTreeBuilder(data).BuildTree(); // SKIP to nodes _items = new List <IBaseItemPrototype>(30000); foreach (var itemNode in tree.Children) { var itemStream = new ReadOnlyMemoryStream(itemNode.Data.Span); var flags = itemStream.ReadUInt32(); ushort serverId = 0; ushort clientId = 0; ushort wareId = 0; ushort speed = 0; byte lightLevel = 0; byte lightColor = 0; byte topOrder = 0; var toSkip = 0; bool escaped = false; while (!itemStream.IsOver) { var attr = itemStream.ReadByte(); var isEscape = (OTBMarkupByte)attr == OTBMarkupByte.Escape; if (toSkip > 0) { if (isEscape) { if (escaped) { toSkip++; escaped = false; } else { toSkip--; escaped = true; } } else { toSkip--; } if (toSkip == 0) { break; } continue; } var dataSize = itemStream.ReadUInt16(); switch (attr) { case 0x10: // ServerID 0x10 = 16 serverId = itemStream.ReadUInt16(); break; case 0x11: // ClientID 0x11 = 17 clientId = itemStream.ReadUInt16(); break; case 0x14: // Speed 0x14 = 20 speed = itemStream.ReadUInt16(); break; case 0x2A: // LightBlock 0x2A = 42 lightLevel = (byte)itemStream.ReadUInt16(); lightColor = (byte)itemStream.ReadUInt16(); break; case 0x2B: // TopOrder 0x2B = 43 topOrder = itemStream.ReadByte(); break; case 0x2D: // WareID 0x2D = 45 wareId = (byte)itemStream.ReadUInt16(); break; default: toSkip = dataSize; break; } } var blockSolid = HasFlag(flags, 1 << 0); var blockProjectile = HasFlag(flags, 1 << 1); var blockPathFind = HasFlag(flags, 1 << 2); //var hasElevation = HasFlag(flags, 1 << 3); // Irrelevant var isUsable = HasFlag(flags, 1 << 4); var isPickupable = HasFlag(flags, 1 << 5); var isMoveable = HasFlag(flags, 1 << 6); //var isStackable = HasFlag(flags, 1 << 7); var alwaysOnTop = HasFlag(flags, 1 << 13); // Maybe irrelevant var isReadable = HasFlag(flags, 1 << 14); var isRotatable = HasFlag(flags, 1 << 15); var isHangable = HasFlag(flags, 1 << 16); var isVertical = HasFlag(flags, 1 << 17); var isHorizontal = HasFlag(flags, 1 << 18); var allowDistRead = HasFlag(flags, 1 << 20); var lookTrough = HasFlag(flags, 1 << 21); var isAnimation = HasFlag(flags, 1 << 22); // Maybe irrelevant too? IBaseItemPrototype item = null; if (!isPickupable) // A world item { item = new WorldItemPrototype(serverId, clientId, isUsable, isMoveable, blockSolid, lookTrough, blockPathFind, blockProjectile); } else // An item { item = new ItemPrototype(serverId, clientId, isUsable); } if (item != null) { _items.Add(item); } } _items.TrimExcess(); }