public override void Deserialize(OtFileReader fileReader, OtFileNode node, OtPropertyReader reader, OtItems items) { base.Deserialize(fileReader, node, reader, items); var itemNode = node.Child; while (itemNode != null) { if ((OtMap.OtMapNodeTypes)itemNode.Type != OtMap.OtMapNodeTypes.ITEM) { throw new Exception("Invalid item node inside container."); } OtPropertyReader props = fileReader.GetPropertyReader(itemNode); var itemId = props.ReadUInt16(); var itemType = items.GetItem(itemId); if (itemType == null) { throw new Exception("Unkonw item type " + itemId + " inside container."); } var item = OtItem.Create(itemType); item.Deserialize(fileReader, itemNode, props, items); Items.Add(item); itemNode = itemNode.Next; } }
public override void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader) { if (attribute == OtItemAttribute.DEPOT_ID) { SetAttribute(OtItemAttribute.DEPOT_ID, reader.ReadUInt16()); } else { base.DeserializeAttribute(attribute, reader); } }
private void ParseTileArea(OtFileReader reader, OtFileNode otbNode, bool replaceTiles, ISet <ulong> tileLocations) { OtPropertyReader props = reader.GetPropertyReader(otbNode); int baseX = props.ReadUInt16(); int baseY = props.ReadUInt16(); int baseZ = props.ReadByte(); OtFileNode nodeTile = otbNode.Child; while (nodeTile != null) { if (nodeTile.Type == (long)OtMapNodeTypes.TILE || nodeTile.Type == (long)OtMapNodeTypes.HOUSETILE) { props = reader.GetPropertyReader(nodeTile); var tileLocation = new Location(baseX + props.ReadByte(), baseY + props.ReadByte(), baseZ); var tile = new OtTile(tileLocation); if (nodeTile.Type == (long)OtMapNodeTypes.HOUSETILE) { tile.HouseId = props.ReadUInt32(); } while (props.PeekChar() != -1) { byte attribute = props.ReadByte(); switch ((OtMapAttribute)attribute) { case OtMapAttribute.TILE_FLAGS: { tile.Flags = props.ReadUInt32(); break; } case OtMapAttribute.ITEM: { ushort itemId = props.ReadUInt16(); var itemType = Items.GetItem(itemId); if (itemType == null) { throw new Exception("Unkonw item type " + itemId + " in position " + tileLocation + "."); } var item = OtItem.Create(itemType); tile.InternalAddItem(item); break; } default: throw new Exception(string.Format("{0} Unknown tile attribute.", tileLocation)); } } OtFileNode nodeItem = nodeTile.Child; while (nodeItem != null) { if (nodeItem.Type == (long)OtMapNodeTypes.ITEM) { props = reader.GetPropertyReader(nodeItem); ushort itemId = props.ReadUInt16(); var itemType = Items.GetItem(itemId); if (itemType == null) { throw new Exception("Unkonw item type " + itemId + " in position " + tileLocation + "."); } var item = OtItem.Create(itemType); item.Deserialize(reader, nodeItem, props, Items); tile.InternalAddItem(item); } else { throw new Exception(string.Format("{0} Unknown node type.", tileLocation)); } nodeItem = nodeItem.Next; } var index = tileLocation.ToIndex(); var hasTile = HasTile(index); if (!hasTile) { SetTile(tile); tileLocations.Add(tileLocation.ToIndex()); } else if (replaceTiles) { SetTile(tile); } } nodeTile = nodeTile.Next; } }
public void Load(string fileName, bool replaceTiles) { if (!File.Exists(fileName)) { throw new Exception(string.Format("File not found {0}.", fileName)); } string spawnFile = null; string houseFile = null; var tileLocations = new HashSet <ulong>(); using (var reader = new OtFileReader(fileName)) { OtFileNode node = reader.GetRootNode(); OtPropertyReader props = reader.GetPropertyReader(node); props.ReadByte(); // junk? var version = props.ReadUInt32(); props.ReadUInt16(); props.ReadUInt16(); var majorVersionItems = props.ReadUInt32(); var minorVersionItems = props.ReadUInt32(); if (version <= 0) { //In otbm version 1 the count variable after splashes/fluidcontainers and stackables //are saved as attributes instead, this solves alot of problems with items //that is changed (stackable/charges/fluidcontainer/splash) during an update. throw new Exception( "This map needs to be upgraded by using the latest map editor version to be able to load correctly."); } if (version > 3) { throw new Exception("Unknown OTBM version detected."); } if (majorVersionItems < 3) { throw new Exception( "This map needs to be upgraded by using the latest map editor version to be able to load correctly."); } if (majorVersionItems > Items.MajorVersion) { throw new Exception("The map was saved with a different items.otb version, an upgraded items.otb is required."); } if (minorVersionItems > Items.MinorVersion) { Trace.WriteLine("This map needs an updated items.otb."); } node = node.Child; if ((OtMapNodeTypes)node.Type != OtMapNodeTypes.MAP_DATA) { throw new Exception("Could not read data node."); } props = reader.GetPropertyReader(node); while (props.PeekChar() != -1) { byte attribute = props.ReadByte(); switch ((OtMapAttribute)attribute) { case OtMapAttribute.DESCRIPTION: var description = props.GetString(); //Descriptions.Add(description); break; case OtMapAttribute.EXT_SPAWN_FILE: spawnFile = props.GetString(); break; case OtMapAttribute.EXT_HOUSE_FILE: houseFile = props.GetString(); break; default: throw new Exception("Unknown header node."); } } OtFileNode nodeMapData = node.Child; while (nodeMapData != null) { switch ((OtMapNodeTypes)nodeMapData.Type) { case OtMapNodeTypes.TILE_AREA: ParseTileArea(reader, nodeMapData, replaceTiles, tileLocations); break; case OtMapNodeTypes.TOWNS: ParseTowns(reader, nodeMapData); break; } nodeMapData = nodeMapData.Next; } } }
public virtual void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader) { switch (attribute) { case OtItemAttribute.COUNT: SetAttribute(OtItemAttribute.COUNT, reader.ReadByte()); break; case OtItemAttribute.ACTION_ID: SetAttribute(OtItemAttribute.ACTION_ID, reader.ReadUInt16()); break; case OtItemAttribute.UNIQUE_ID: SetAttribute(OtItemAttribute.UNIQUE_ID, reader.ReadUInt16()); break; case OtItemAttribute.NAME: SetAttribute(OtItemAttribute.NAME, reader.ReadString()); break; case OtItemAttribute.PLURALNAME: SetAttribute(OtItemAttribute.PLURALNAME, reader.ReadString()); break; case OtItemAttribute.ARTICLE: SetAttribute(OtItemAttribute.ARTICLE, reader.ReadString()); break; case OtItemAttribute.ATTACK: SetAttribute(OtItemAttribute.ATTACK, reader.ReadInt32()); break; case OtItemAttribute.EXTRAATTACK: SetAttribute(OtItemAttribute.EXTRAATTACK, reader.ReadInt32()); break; case OtItemAttribute.DEFENSE: SetAttribute(OtItemAttribute.DEFENSE, reader.ReadInt32()); break; case OtItemAttribute.EXTRADEFENSE: SetAttribute(OtItemAttribute.EXTRADEFENSE, reader.ReadInt32()); break; case OtItemAttribute.ARMOR: SetAttribute(OtItemAttribute.ARMOR, reader.ReadInt32()); break; case OtItemAttribute.ATTACKSPEED: SetAttribute(OtItemAttribute.ATTACKSPEED, reader.ReadInt32()); break; case OtItemAttribute.HITCHANCE: SetAttribute(OtItemAttribute.HITCHANCE, reader.ReadInt32()); break; case OtItemAttribute.SCRIPTPROTECTED: SetAttribute(OtItemAttribute.SCRIPTPROTECTED, reader.ReadByte() != 0); break; case OtItemAttribute.DUALWIELD: SetAttribute(OtItemAttribute.DUALWIELD, reader.ReadByte() != 0); break; case OtItemAttribute.TEXT: SetAttribute(OtItemAttribute.TEXT, reader.ReadString()); break; case OtItemAttribute.WRITTENDATE: SetAttribute(OtItemAttribute.WRITTENDATE, reader.ReadInt32()); break; case OtItemAttribute.WRITTENBY: SetAttribute(OtItemAttribute.WRITTENBY, reader.ReadString()); break; case OtItemAttribute.DESC: SetAttribute(OtItemAttribute.DESC, reader.ReadString()); break; case OtItemAttribute.RUNE_CHARGES: SetAttribute(OtItemAttribute.RUNE_CHARGES, reader.ReadByte()); break; case OtItemAttribute.CHARGES: SetAttribute(OtItemAttribute.CHARGES, reader.ReadUInt16()); break; case OtItemAttribute.DURATION: SetAttribute(OtItemAttribute.DURATION, reader.ReadInt32()); break; case OtItemAttribute.DECAYING_STATE: SetAttribute(OtItemAttribute.DECAYING_STATE, reader.ReadByte()); break; //specific item properties //case OtItemAttribute.DEPOT_ID: // SetAttribute(OtItemAttribute.DEPOT_ID, reader.ReadUInt16()); // break; //case OtItemAttribute.HOUSEDOORID: // SetAttribute(OtItemAttribute.HOUSEDOORID, reader.ReadByte()); // break; //case OtItemAttribute.TELE_DEST: // SetAttribute(OtItemAttribute.TELE_DEST, reader.ReadLocation()); // break; //case OtItemAttribute.SLEEPERGUID: // SetAttribute(OtItemAttribute.SLEEPERGUID, reader.ReadUInt32()); // break; //case OtItemAttribute.SLEEPSTART: // SetAttribute(OtItemAttribute.SLEEPSTART, reader.ReadUInt32()); // break; default: throw new Exception("Unkonw item attribute: " + (byte)attribute); } }
public void LoadOtb(string fileName) { if (!File.Exists(fileName)) { throw new Exception(string.Format("File not found {0}.", fileName)); } using (var reader = new OtFileReader(fileName)) { var node = reader.GetRootNode(); OtPropertyReader props = reader.GetPropertyReader(node); props.ReadByte(); //junk? props.ReadUInt32(); byte attr = props.ReadByte(); if ((RootAttr)attr == RootAttr.ROOT_ATTR_VERSION) { var datalen = props.ReadUInt16(); if (datalen != 140) { throw new Exception("Size of version header is invalid."); } MajorVersion = props.ReadUInt32(); MinorVersion = props.ReadUInt32(); BuildNumber = props.ReadUInt32(); } if (MajorVersion == 0xFFFFFFFF) { Trace.WriteLine("[Warning] items.otb using generic client version."); } node = node.Child; while (node != null) { props = reader.GetPropertyReader(node); OtItemType item = new OtItemType(); byte itemGroup = (byte)node.Type; switch ((OtbItemGroup)itemGroup) { case OtbItemGroup.NONE: item.Group = OtItemGroup.None; break; case OtbItemGroup.GROUND: item.Group = OtItemGroup.Ground; break; case OtbItemGroup.SPLASH: item.Group = OtItemGroup.Splash; break; case OtbItemGroup.FLUID: item.Group = OtItemGroup.FluidContainer; break; case OtbItemGroup.CONTAINER: item.Group = OtItemGroup.Container; break; case OtbItemGroup.DEPRECATED: item.Group = OtItemGroup.Deprecated; break; default: break; } OtbItemFlags flags = (OtbItemFlags)props.ReadUInt32(); item.BlockObject = ((flags & OtbItemFlags.BLOCK_SOLID) == OtbItemFlags.BLOCK_SOLID); item.BlockProjectile = ((flags & OtbItemFlags.BLOCK_PROJECTILE) == OtbItemFlags.BLOCK_PROJECTILE); item.BlockPathFind = ((flags & OtbItemFlags.BLOCK_PATHFIND) == OtbItemFlags.BLOCK_PATHFIND); item.IsPickupable = ((flags & OtbItemFlags.PICKUPABLE) == OtbItemFlags.PICKUPABLE); item.IsMoveable = ((flags & OtbItemFlags.MOVEABLE) == OtbItemFlags.MOVEABLE); item.IsStackable = ((flags & OtbItemFlags.STACKABLE) == OtbItemFlags.STACKABLE); item.AlwaysOnTop = ((flags & OtbItemFlags.ALWAYSONTOP) == OtbItemFlags.ALWAYSONTOP); item.IsVertical = ((flags & OtbItemFlags.VERTICAL) == OtbItemFlags.VERTICAL); item.IsHorizontal = ((flags & OtbItemFlags.HORIZONTAL) == OtbItemFlags.HORIZONTAL); item.IsHangable = ((flags & OtbItemFlags.HANGABLE) == OtbItemFlags.HANGABLE); item.IsRotatable = ((flags & OtbItemFlags.ROTABLE) == OtbItemFlags.ROTABLE); item.IsReadable = ((flags & OtbItemFlags.READABLE) == OtbItemFlags.READABLE); item.HasUseWith = ((flags & OtbItemFlags.USEABLE) == OtbItemFlags.USEABLE); item.HasHeight = ((flags & OtbItemFlags.HAS_HEIGHT) == OtbItemFlags.HAS_HEIGHT); item.LookThrough = ((flags & OtbItemFlags.LOOKTHROUGH) == OtbItemFlags.LOOKTHROUGH); item.AllowDistRead = ((flags & OtbItemFlags.ALLOWDISTREAD) == OtbItemFlags.ALLOWDISTREAD); item.IsAnimation = ((flags & OtbItemFlags.ANIMATION) == OtbItemFlags.ANIMATION); item.WalkStack = ((flags & OtbItemFlags.WALKSTACK) == OtbItemFlags.WALKSTACK); while (props.PeekChar() != -1) { byte attribute = props.ReadByte(); UInt16 datalen = props.ReadUInt16(); switch ((OtbItemAttr)attribute) { case OtbItemAttr.ITEM_ATTR_SERVERID: if (datalen != sizeof(UInt16)) { throw new Exception("Unexpected data length of server id block (Should be 2 bytes)"); } item.Id = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_CLIENTID: if (datalen != sizeof(UInt16)) { throw new Exception("Unexpected data length of client id block (Should be 2 bytes)"); } item.SpriteId = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_WAREID: if (datalen != sizeof(UInt16)) { throw new Exception("Unexpected data length of ware id block (Should be 2 bytes)"); } item.WareId = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_SPEED: if (datalen != sizeof(UInt16)) { throw new Exception("Unexpected data length of speed block (Should be 2 bytes)"); } item.GroundSpeed = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_NAME: item.Name = new string(props.ReadChars(datalen)); break; case OtbItemAttr.ITEM_ATTR_SPRITEHASH: if (datalen != 16) { throw new Exception("Unexpected data length of sprite hash (Should be 16 bytes)"); } item.SpriteHash = props.ReadBytes(16); break; case OtbItemAttr.ITEM_ATTR_MINIMAPCOLOR: if (datalen != 2) { throw new Exception("Unexpected data length of minimap color (Should be 2 bytes)"); } item.MinimapColor = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_07: //read/write-able if (datalen != 2) { throw new Exception("Unexpected data length of attr 07 (Should be 2 bytes)"); } item.MaxReadWriteChars = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_08: //readable if (datalen != 2) { throw new Exception("Unexpected data length of attr 08 (Should be 2 bytes)"); } item.MaxReadChars = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_LIGHT2: if (datalen != sizeof(UInt16) * 2) { throw new Exception("Unexpected data length of item light (2) block"); } item.LightLevel = props.ReadUInt16(); item.LightColor = props.ReadUInt16(); break; case OtbItemAttr.ITEM_ATTR_TOPORDER: if (datalen != sizeof(byte)) { throw new Exception("Unexpected data length of item toporder block (Should be 1 byte)"); } item.AlwaysOnTopOrder = props.ReadByte(); break; default: //skip unknown attributes props.ReadBytes(datalen); break; } } AddItem(item); node = node.Next; } } }