private byte[] GetProps(Node node, out long size) { if (buffer == null || buffer.Length < node.PropsSize) { buffer = new byte[node.PropsSize]; } fileStream.Seek(node.Start + 1, SeekOrigin.Begin); fileStream.Read(buffer, 0, (int)node.PropsSize); uint j = 0; bool escaped = false; for (uint i = 0; i < node.PropsSize; ++i, ++j) { if (buffer[i] == Constants.Escape) { ++i; buffer[j] = buffer[i]; escaped = true; } else if (escaped) { buffer[j] = buffer[i]; } } size = j; return buffer; }
public bool GetProps(Node node, out PropertyReader props) { long size; byte[] buff = GetProps(node, out size); if (buff == null) { props = null; return false; } else { props = new PropertyReader(new MemoryStream(buff, 0, (int)size)); return true; } }
public bool OpenFile(string fileName) { fileStream = File.Open(fileName, FileMode.Open); reader = new BinaryReader(fileStream); uint version = reader.ReadUInt32(); root = new Node(); root.Start = 4; if (reader.ReadByte() == Constants.NodeStart) { return ParseNode(root); } else { return false; } }
private bool ParseTowns(Map map, FileLoader loader, Node node) { PropertyReader props; Node nodeTown = node.Child; while (nodeTown != null) { if (!loader.GetProps(nodeTown, out props)) { lastError = "Could not read town data."; return false; } uint townid = props.ReadUInt32(); string townName = props.GetString(); ushort townTempleX = props.ReadUInt16(); ushort townTempleY = props.ReadUInt16(); byte townTempleZ = props.ReadByte(); Town town = new Town( townid, townName, new Location(townTempleX, townTempleY, townTempleZ)); map.Towns.Add(town); nodeTown = nodeTown.Next; } return true; }
private bool ParseTileArea(Map map, FileLoader loader, Node node) { PropertyReader props; if (!loader.GetProps(node, out props)) { lastError = "Invalid map node."; return false; } int baseX = props.ReadUInt16(); int baseY = props.ReadUInt16(); int baseZ = props.ReadByte(); Node nodeTile = node.Child; while (nodeTile != null) { if (nodeTile.Type == (long)OtbmNodeType.Tile || nodeTile.Type == (long)OtbmNodeType.HouseTile) { loader.GetProps(nodeTile, out props); int tileX = baseX + props.ReadByte(); int tileY = baseY + props.ReadByte(); int tileZ = baseZ; Tile tile = new Tile(); tile.Location = new Location(tileX, tileY, tileZ); // TODO: houses if (nodeTile.Type == (long)OtbmNodeType.HouseTile) { uint houseId = props.ReadUInt32(); } byte attribute; while (props.PeekChar() != -1) { attribute = props.ReadByte(); switch ((OtbmAttribute)attribute) { case OtbmAttribute.TileFlags: { TileFlags flags = (TileFlags)props.ReadUInt32(); if ((flags & TileFlags.ProtectionZone) == TileFlags.ProtectionZone) { tile.IsProtectionZone = true; } else if ((flags & TileFlags.NoPvpZone) == TileFlags.NoPvpZone) { tile.IsNoPvpZone = true; } else if ((flags & TileFlags.PvpZone) == TileFlags.PvpZone) { tile.IsPvpZone = true; } if ((flags & TileFlags.NoLogout) == TileFlags.NoLogout) { tile.IsNoLogoutZone = true; } if ((flags & TileFlags.Refresh) == TileFlags.Refresh) { // TODO: Warn about house tile.IsRefreshZone = true; } break; } case OtbmAttribute.Item: { ushort itemId = props.ReadUInt16(); Item item = Item.Create(itemId); // TODO: if isHouseTile && !item.Info.IsMoveable if (item.Info.Group == ItemGroup.Ground) { tile.Ground = item; } else { tile.AddItem(item); } break; } default: lastError = tile.Location + " Unknown tile attribute."; return false; } } Node nodeItem = nodeTile.Child; while (nodeItem != null) { if (nodeItem.Type == (long)OtbmNodeType.Item) { loader.GetProps(nodeItem, out props); ushort itemId = props.ReadUInt16(); // TODO: subclass item, different deserializations // for different types Item item = Item.Create(itemId); if (item.Info.Group == ItemGroup.Ground) { tile.Ground = item; } else { tile.AddItem(item); } } else { lastError += tile.Location + " Unknown node type."; return false; } nodeItem = nodeItem.Next; } map.SetTile(tile.Location, tile); } nodeTile = nodeTile.Next; } return true; }
private bool ParseNode(Node node) { Node currentNode = node; int val; while (true) { // read node type val = fileStream.ReadByte(); if (val != -1) { currentNode.Type = val; bool setPropSize = false; while (true) { // search child and next node val = fileStream.ReadByte(); if (val == -1) { break; } else if (val == Constants.NodeStart) { Node childNode = new Node(); childNode.Start = fileStream.Position; setPropSize = true; currentNode.PropsSize = fileStream.Position - currentNode.Start - 2; currentNode.Child = childNode; if (!ParseNode(childNode)) { return false; } } else if (val == Constants.NodeEnd) { if (!setPropSize) { currentNode.PropsSize = fileStream.Position - currentNode.Start - 2; } val = fileStream.ReadByte(); if (val != -1) { if (val == Constants.NodeStart) { // start next node Node nextNode = new Node(); nextNode.Start = fileStream.Position; currentNode.Next = nextNode; currentNode = nextNode; break; } else if (val == Constants.NodeEnd) { // up 1 level and move 1 position back // safeTell(pos) && safeSeek(pos) fileStream.Seek(-1, SeekOrigin.Current); return true; } else { // bad format return false; } } else { // end of file? return true; } } else if (val == Constants.Escape) { fileStream.ReadByte(); } } } else { return false; } } }