public static bool open(string filename, ref OtbList items, bool outputDebug) { FileStream fileStream = new FileStream(filename, FileMode.Open); try { using (OtbLoader reader = new OtbLoader(fileStream)) { //get root node BinaryReader nodeReader = reader.getRootNode(); if (nodeReader == null) { return(false); } nodeReader.ReadByte(); //first byte of otb is 0 nodeReader.ReadUInt32(); //4 bytes flags, unused byte attr = nodeReader.ReadByte(); if ((rootattrib_t)attr == rootattrib_t.ROOT_ATTR_VERSION) { UInt16 datalen = nodeReader.ReadUInt16(); if (datalen != 4 + 4 + 4 + 1 * 128) { //error = wxT("items.otb: Size of version header is invalid, updated .otb version?"); if (outputDebug) { Trace.WriteLine(String.Format("Size of version header is invalid.")); } return(false); } items.dwMajorVersion = nodeReader.ReadUInt32(); //major, file version items.dwMinorVersion = nodeReader.ReadUInt32(); //minor, client version items.dwBuildNumber = nodeReader.ReadUInt32(); //build number, revision nodeReader.BaseStream.Seek(128, SeekOrigin.Current); } nodeReader = reader.getChildNode(); if (nodeReader == null) { return(false); } do { OtbItem item = new OtbItem(); byte itemGroup = nodeReader.ReadByte(); if (outputDebug) { Trace.WriteLine(String.Format("Node:ItemGroup {0}", (itemgroup_t)itemGroup)); } switch ((itemgroup_t)itemGroup) { case itemgroup_t.ITEM_GROUP_NONE: item.type = ItemType.None; break; case itemgroup_t.ITEM_GROUP_GROUND: item.type = ItemType.Ground; break; case itemgroup_t.ITEM_GROUP_SPLASH: item.type = ItemType.Splash; break; case itemgroup_t.ITEM_GROUP_FLUID: item.type = ItemType.Fluid; break; case itemgroup_t.ITEM_GROUP_CONTAINER: item.type = ItemType.Container; break; case itemgroup_t.ITEM_GROUP_DEPRECATED: item.type = ItemType.Deprecated; break; default: break; } itemflags_t flags = (itemflags_t)nodeReader.ReadUInt32(); if (outputDebug) { Trace.WriteLine(String.Format("Node:flags {0}", flags)); } item.blockObject = ((flags & itemflags_t.FLAG_BLOCK_SOLID) == itemflags_t.FLAG_BLOCK_SOLID); item.blockProjectile = ((flags & itemflags_t.FLAG_BLOCK_PROJECTILE) == itemflags_t.FLAG_BLOCK_PROJECTILE); item.blockPathFind = ((flags & itemflags_t.FLAG_BLOCK_PATHFIND) == itemflags_t.FLAG_BLOCK_PATHFIND); item.isPickupable = ((flags & itemflags_t.FLAG_PICKUPABLE) == itemflags_t.FLAG_PICKUPABLE); item.isMoveable = ((flags & itemflags_t.FLAG_MOVEABLE) == itemflags_t.FLAG_MOVEABLE); item.isStackable = ((flags & itemflags_t.FLAG_STACKABLE) == itemflags_t.FLAG_STACKABLE); item.alwaysOnTop = ((flags & itemflags_t.FLAG_ALWAYSONTOP) == itemflags_t.FLAG_ALWAYSONTOP); item.isVertical = ((flags & itemflags_t.FLAG_VERTICAL) == itemflags_t.FLAG_VERTICAL); item.isHorizontal = ((flags & itemflags_t.FLAG_HORIZONTAL) == itemflags_t.FLAG_HORIZONTAL); item.isHangable = ((flags & itemflags_t.FLAG_HANGABLE) == itemflags_t.FLAG_HANGABLE); item.isRotatable = ((flags & itemflags_t.FLAG_ROTABLE) == itemflags_t.FLAG_ROTABLE); item.isReadable = ((flags & itemflags_t.FLAG_READABLE) == itemflags_t.FLAG_READABLE); item.hasUseWith = ((flags & itemflags_t.FLAG_USEABLE) == itemflags_t.FLAG_USEABLE); item.hasHeight = ((flags & itemflags_t.FLAG_HAS_HEIGHT) == itemflags_t.FLAG_HAS_HEIGHT); item.lookThrough = ((flags & itemflags_t.FLAG_LOOKTHROUGH) == itemflags_t.FLAG_LOOKTHROUGH); item.allowDistRead = ((flags & itemflags_t.FLAG_ALLOWDISTREAD) == itemflags_t.FLAG_ALLOWDISTREAD); item.isAnimation = ((flags & itemflags_t.FLAG_ANIMATION) == itemflags_t.FLAG_ANIMATION); item.walkStack = ((flags & itemflags_t.FLAG_WALKSTACK) == itemflags_t.FLAG_WALKSTACK); while (nodeReader.PeekChar() != -1) { byte attribute = nodeReader.ReadByte(); UInt16 datalen = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node[{0}]:attribut {1}, size: {2}", reader.currentNodePos, ((itemattrib_t)attribute), datalen, reader.currentNodePos + nodeReader.BaseStream.Position)); } switch ((itemattrib_t)attribute) { case itemattrib_t.ITEM_ATTR_SERVERID: { if (datalen != sizeof(UInt16)) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of server id block (Should be 2 bytes)")); } return(false); } item.id = nodeReader.ReadUInt16(); if (outputDebug) { System.Diagnostics.Debug.WriteLine(String.Format("Node:attribute:data {0}", item.id)); } } break; case itemattrib_t.ITEM_ATTR_CLIENTID: { if (datalen != sizeof(UInt16)) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of client id block (Should be 2 bytes)")); } return(false); } item.spriteId = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.spriteId)); } } break; case itemattrib_t.ITEM_ATTR_WAREID: { if (datalen != sizeof(UInt16)) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of ware id block (Should be 2 bytes)")); } return(false); } item.wareId = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.wareId)); } } break; case itemattrib_t.ITEM_ATTR_SPEED: { if (datalen != sizeof(UInt16)) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of speed block (Should be 2 bytes)")); } return(false); } item.groundSpeed = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.groundSpeed)); } } break; case itemattrib_t.ITEM_ATTR_NAME: { item.name = new string(nodeReader.ReadChars(datalen)); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.name)); } } break; case itemattrib_t.ITEM_ATTR_SPRITEHASH: { if (datalen != 16) { return(false); } item.spriteHash = nodeReader.ReadBytes(16); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.alwaysOnTopOrder)); } } break; case itemattrib_t.ITEM_ATTR_MINIMAPCOLOR: { if (datalen != 2) { return(false); } item.minimapColor = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.minimapColor)); } } break; case itemattrib_t.ITEM_ATTR_07: { //read/write-able if (datalen != 2) { return(false); } item.maxReadWriteChars = nodeReader.ReadUInt16(); } break; case itemattrib_t.ITEM_ATTR_08: { //readable if (datalen != 2) { return(false); } item.maxReadChars = nodeReader.ReadUInt16(); } break; case itemattrib_t.ITEM_ATTR_LIGHT2: { if (datalen != sizeof(UInt16) * 2) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of item light (2) block")); } return(false); } item.lightLevel = nodeReader.ReadUInt16(); item.lightColor = nodeReader.ReadUInt16(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}, {1}", item.lightLevel, item.lightColor)); } } break; case itemattrib_t.ITEM_ATTR_TOPORDER: { if (datalen != sizeof(byte)) { if (outputDebug) { Trace.WriteLine(String.Format("Unexpected data length of item toporder block (Should be 1 byte)")); } return(false); } item.alwaysOnTopOrder = nodeReader.ReadByte(); if (outputDebug) { Trace.WriteLine(String.Format("Node:attribute:data {0}", item.alwaysOnTopOrder)); } } break; default: { //skip unknown attributes nodeReader.BaseStream.Seek(datalen, SeekOrigin.Current); if (outputDebug) { Trace.WriteLine(String.Format("Skipped unknown attribute")); } } break; } } items.Add(item); nodeReader = reader.getNextNode(); } while (nodeReader != null); } } finally { fileStream.Close(); } return(true); }
public static bool save(string filename, ref OtbList items) { FileStream fileStream = new FileStream(filename, FileMode.Create); try { using (OtbLoader writer = new OtbLoader(fileStream)) { writer.writeUInt32(0, false); //version, always 0 writer.createNode(0); //root node writer.writeUInt32(0, true); //flags, unused for root node VERSIONINFO vi = new VERSIONINFO(); vi.dwMajorVersion = items.dwMajorVersion; vi.dwMinorVersion = items.dwMinorVersion; vi.dwBuildNumber = items.dwBuildNumber; vi.CSDVersion = String.Format("OTB {0}.{1}.{2}-{3}.{4}", vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber, items.clientVersion / 100, items.clientVersion % 100); MemoryStream ms = new MemoryStream(); BinaryWriter property = new BinaryWriter(ms); property.Write(vi.dwMajorVersion); property.Write(vi.dwMinorVersion); property.Write(vi.dwBuildNumber); byte[] CSDVersion = System.Text.Encoding.ASCII.GetBytes(vi.CSDVersion); Array.Resize(ref CSDVersion, 128); property.Write(CSDVersion); writer.writeProp(rootattrib_t.ROOT_ATTR_VERSION, property); foreach (OtbItem item in items) { List <itemattrib_t> saveAttributeList = new List <itemattrib_t>(); saveAttributeList.Add(itemattrib_t.ITEM_ATTR_SERVERID); if (item.type == ItemType.Deprecated) { //no other attributes should be saved for this type } else { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_CLIENTID); saveAttributeList.Add(itemattrib_t.ITEM_ATTR_SPRITEHASH); if (item.minimapColor != 0) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_MINIMAPCOLOR); } if (item.maxReadWriteChars != 0) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_07); } if (item.maxReadChars != 0) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_08); } if (item.lightLevel != 0 || item.lightColor != 0) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_LIGHT2); } if (item.type == ItemType.Ground) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_SPEED); } if (item.alwaysOnTop) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_TOPORDER); } if (item.wareId != 0) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_WAREID); } if (!string.IsNullOrEmpty(item.name)) { saveAttributeList.Add(itemattrib_t.ITEM_ATTR_NAME); } } switch (item.type) { case ItemType.Container: writer.createNode((byte)itemgroup_t.ITEM_GROUP_CONTAINER); break; case ItemType.Fluid: writer.createNode((byte)itemgroup_t.ITEM_GROUP_FLUID); break; case ItemType.Ground: writer.createNode((byte)itemgroup_t.ITEM_GROUP_GROUND); break; case ItemType.Splash: writer.createNode((byte)itemgroup_t.ITEM_GROUP_SPLASH); break; case ItemType.Deprecated: writer.createNode((byte)itemgroup_t.ITEM_GROUP_DEPRECATED); break; default: writer.createNode((byte)itemgroup_t.ITEM_GROUP_NONE); break; } UInt32 flags = 0; if (item.blockObject) { flags |= (UInt32)itemflags_t.FLAG_BLOCK_SOLID; } if (item.blockProjectile) { flags |= (UInt32)itemflags_t.FLAG_BLOCK_PROJECTILE; } if (item.blockPathFind) { flags |= (UInt32)itemflags_t.FLAG_BLOCK_PATHFIND; } if (item.hasHeight) { flags |= (UInt32)itemflags_t.FLAG_HAS_HEIGHT; } if (item.hasUseWith) { flags |= (UInt32)itemflags_t.FLAG_USEABLE; } if (item.isPickupable) { flags |= (UInt32)itemflags_t.FLAG_PICKUPABLE; } if (item.isMoveable) { flags |= (UInt32)itemflags_t.FLAG_MOVEABLE; } if (item.isStackable) { flags |= (UInt32)itemflags_t.FLAG_STACKABLE; } if (item.alwaysOnTop) { flags |= (UInt32)itemflags_t.FLAG_ALWAYSONTOP; } if (item.isReadable) { flags |= (UInt32)itemflags_t.FLAG_READABLE; } if (item.isRotatable) { flags |= (UInt32)itemflags_t.FLAG_ROTABLE; } if (item.isHangable) { flags |= (UInt32)itemflags_t.FLAG_HANGABLE; } if (item.isVertical) { flags |= (UInt32)itemflags_t.FLAG_VERTICAL; } if (item.isHorizontal) { flags |= (UInt32)itemflags_t.FLAG_HORIZONTAL; } if (item.lookThrough) { flags |= (UInt32)itemflags_t.FLAG_LOOKTHROUGH; } if (item.allowDistRead) { flags |= (UInt32)itemflags_t.FLAG_ALLOWDISTREAD; } if (item.isAnimation) { flags |= (UInt32)itemflags_t.FLAG_ANIMATION; } if (item.walkStack) { flags |= (UInt32)itemflags_t.FLAG_WALKSTACK; } writer.writeUInt32(flags, true); foreach (itemattrib_t attribute in saveAttributeList) { switch (attribute) { case itemattrib_t.ITEM_ATTR_SERVERID: { property.Write((UInt16)item.id); writer.writeProp(itemattrib_t.ITEM_ATTR_SERVERID, property); break; } case itemattrib_t.ITEM_ATTR_WAREID: { property.Write((UInt16)item.wareId); writer.writeProp(itemattrib_t.ITEM_ATTR_WAREID, property); break; } case itemattrib_t.ITEM_ATTR_CLIENTID: { property.Write((UInt16)item.spriteId); writer.writeProp(itemattrib_t.ITEM_ATTR_CLIENTID, property); break; } case itemattrib_t.ITEM_ATTR_SPEED: { property.Write((UInt16)item.groundSpeed); writer.writeProp(itemattrib_t.ITEM_ATTR_SPEED, property); break; } case itemattrib_t.ITEM_ATTR_NAME: { for (UInt16 i = 0; i < item.name.Length; ++i) { property.Write((char)item.name[i]); } writer.writeProp(itemattrib_t.ITEM_ATTR_NAME, property); break; } case itemattrib_t.ITEM_ATTR_SPRITEHASH: { property.Write(item.spriteHash); writer.writeProp(itemattrib_t.ITEM_ATTR_SPRITEHASH, property); break; } case itemattrib_t.ITEM_ATTR_MINIMAPCOLOR: { property.Write((UInt16)item.minimapColor); writer.writeProp(itemattrib_t.ITEM_ATTR_MINIMAPCOLOR, property); break; } case itemattrib_t.ITEM_ATTR_07: { property.Write((UInt16)item.maxReadWriteChars); writer.writeProp(itemattrib_t.ITEM_ATTR_07, property); break; } case itemattrib_t.ITEM_ATTR_08: { property.Write((UInt16)item.maxReadChars); writer.writeProp(itemattrib_t.ITEM_ATTR_08, property); break; } case itemattrib_t.ITEM_ATTR_LIGHT2: { property.Write((UInt16)item.lightLevel); property.Write((UInt16)item.lightColor); writer.writeProp(itemattrib_t.ITEM_ATTR_LIGHT2, property); break; } case itemattrib_t.ITEM_ATTR_TOPORDER: { property.Write((byte)item.alwaysOnTopOrder); writer.writeProp(itemattrib_t.ITEM_ATTR_TOPORDER, property); break; } } } writer.closeNode(); } writer.closeNode(); } } finally { fileStream.Close(); } return(true); }
private bool compareItems() { if (System.IO.File.Exists(file1Text.Text) && System.IO.File.Exists(file2Text.Text)) { OtbList items1 = new OtbList(); OtbList items2 = new OtbList(); bool result; result = otb.open(file1Text.Text, ref items1, false); if (!result) { MessageBox.Show("Could not open {0}", file1Text.Text); return(false); } result = otb.open(file2Text.Text, ref items2, false); if (!result) { MessageBox.Show("Could not open {0}", file2Text.Text); return(false); } IEnumerator <OtbItem> enumerator1 = items1.GetEnumerator(); IEnumerator <OtbItem> enumerator2 = items2.GetEnumerator(); if (items1.Count != items2.Count) { resultTextBox.AppendText(string.Format("Item count: [{0}]/[{1}]" + Environment.NewLine, items1.Count, items2.Count)); } while (enumerator1.MoveNext()) { if (!enumerator2.MoveNext()) { return(false); } OtbItem item1 = enumerator1.Current; OtbItem item2 = enumerator2.Current; if (item1.spriteId != item2.spriteId) { resultTextBox.AppendText(string.Format("id: {0} Sprite changed [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.spriteId, item2.spriteId)); continue; } if (item1.spriteHash != null && item2.spriteHash != null && !Utils.ByteArrayCompare(item1.spriteHash, item2.spriteHash)) { resultTextBox.AppendText(string.Format("id: {0} Sprite updated" + Environment.NewLine, item1.id)); } if (item1.type != item2.type) { resultTextBox.AppendText(string.Format("id: {0} type [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.type, item2.type)); } if (item1.alwaysOnTop != item2.alwaysOnTop) { resultTextBox.AppendText(string.Format("id: {0} alwaysOnTop [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.alwaysOnTop, item2.alwaysOnTop)); } if (item1.alwaysOnTopOrder != item2.alwaysOnTopOrder) { resultTextBox.AppendText(string.Format("id: {0} alwaysOnTopOrder [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.alwaysOnTopOrder, item2.alwaysOnTopOrder)); } if (item1.blockObject != item2.blockObject) { resultTextBox.AppendText(string.Format("id: {0} blockObject [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.blockObject, item2.blockObject)); } if (item1.blockPathFind != item2.blockPathFind) { resultTextBox.AppendText(string.Format("id: {0} blockPathFind [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.blockPathFind, item2.blockPathFind)); } if (item1.blockProjectile != item2.blockProjectile) { resultTextBox.AppendText(string.Format("id: {0} blockProjectile [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.blockProjectile, item2.blockProjectile)); } if (item1.groundSpeed != item2.groundSpeed) { resultTextBox.AppendText(string.Format("id: {0} groundSpeed [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.groundSpeed, item2.groundSpeed)); } if (item1.hasHeight != item2.hasHeight) { resultTextBox.AppendText(string.Format("id: {0} hasHeight [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.hasHeight, item2.hasHeight)); } if (item1.hasUseWith != item2.hasUseWith) { resultTextBox.AppendText(string.Format("id: {0} Useable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.hasUseWith, item2.hasUseWith)); } if (item1.isHangable != item2.isHangable) { resultTextBox.AppendText(string.Format("id: {0} isHangable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isHangable, item2.isHangable)); } if (item1.isHorizontal != item2.isHorizontal) { resultTextBox.AppendText(string.Format("id: {0} isHorizontal [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isHorizontal, item2.isHorizontal)); } if (item1.isMoveable != item2.isMoveable) { resultTextBox.AppendText(string.Format("id: {0} isMoveable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isMoveable, item2.isMoveable)); } if (item1.isPickupable != item2.isPickupable) { resultTextBox.AppendText(string.Format("id: {0} isPickupable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isPickupable, item2.isPickupable)); } if (item1.isReadable != item2.isReadable) { resultTextBox.AppendText(string.Format("id: {0} isReadable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isReadable, item2.isReadable)); } if (item1.isRotatable != item2.isRotatable) { resultTextBox.AppendText(string.Format("id: {0} isRotatable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isRotatable, item2.isRotatable)); } if (item1.isStackable != item2.isStackable) { resultTextBox.AppendText(string.Format("id: {0} isStackable [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isStackable, item2.isStackable)); } if (item1.isVertical != item2.isVertical) { resultTextBox.AppendText(string.Format("id: {0} isVertical [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.isVertical, item2.isVertical)); } if (item1.lightColor != item2.lightColor) { resultTextBox.AppendText(string.Format("id: {0} lightColor [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.lightColor, item2.lightColor)); } if (item1.lightLevel != item2.lightLevel) { resultTextBox.AppendText(string.Format("id: {0} lightLevel [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.lightLevel, item2.lightLevel)); } if (item1.lookThrough != item2.lookThrough) { resultTextBox.AppendText(string.Format("id: {0} lookThrough [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.lookThrough, item2.lookThrough)); } if (item1.maxReadChars != item2.maxReadChars) { resultTextBox.AppendText(string.Format("id: {0} maxReadChars [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.maxReadChars, item2.maxReadChars)); } if (item1.maxReadWriteChars != item2.maxReadWriteChars) { resultTextBox.AppendText(string.Format("id: {0} maxReadWriteChars [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.maxReadWriteChars, item2.maxReadWriteChars)); } if (item1.minimapColor != item2.minimapColor) { resultTextBox.AppendText(string.Format("id: {0} minimapColor [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.minimapColor, item2.minimapColor)); } if (item1.name != item2.name) { resultTextBox.AppendText(string.Format("id: {0} name [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.name, item2.name)); } if (item1.walkStack != item2.walkStack) { resultTextBox.AppendText(string.Format("id: {0} walkstack [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.walkStack, item2.walkStack)); } if (item1.wareId != item2.wareId) { resultTextBox.AppendText(string.Format("id: {0} wareid [{1}]/[{2}]" + Environment.NewLine, item1.id, item1.wareId, item2.wareId)); } } if (resultTextBox.Text.Length == 0) { MessageBox.Show("No differences found!"); } return(true); } return(false); }