예제 #1
0
        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;
            }
        }
예제 #2
0
 public virtual void Deserialize(OtPropertyReader reader)
 {
     while (reader.PeekChar() != -1)
     {
         var attrType = (OtItemAttribute)reader.ReadByte();
         DeserializeAttribute(attrType, reader);
     }
 }
예제 #3
0
 public override void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader)
 {
     if (attribute == OtItemAttribute.CONTAINER_ITEMS)
     {
         SetAttribute(OtItemAttribute.CONTAINER_ITEMS, reader.ReadUInt32());
     }
     else
     {
         base.DeserializeAttribute(attribute, reader);
     }
 }
예제 #4
0
 public override void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader)
 {
     if (attribute == OtItemAttribute.TELE_DEST)
     {
         SetAttribute(OtItemAttribute.TELE_DEST, reader.ReadLocation());
     }
     else
     {
         base.DeserializeAttribute(attribute, reader);
     }
 }
예제 #5
0
 public override void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader)
 {
     if (attribute == OtItemAttribute.HOUSEDOORID)
     {
         SetAttribute(OtItemAttribute.HOUSEDOORID, reader.ReadByte());
     }
     else
     {
         base.DeserializeAttribute(attribute, reader);
     }
 }
예제 #6
0
 public override void DeserializeAttribute(OtItemAttribute attribute, OtPropertyReader reader)
 {
     if (attribute == OtItemAttribute.DEPOT_ID)
     {
         SetAttribute(OtItemAttribute.DEPOT_ID, reader.ReadUInt16());
     }
     else
     {
         base.DeserializeAttribute(attribute, reader);
     }
 }
예제 #7
0
        private void ParseTowns(OtFileReader reader, OtFileNode otbNode)
        {
            OtFileNode nodeTown = otbNode.Child;

            while (nodeTown != null)
            {
                OtPropertyReader props = reader.GetPropertyReader(nodeTown);

                uint   townid         = props.ReadUInt32();
                string townName       = props.GetString();
                var    templeLocation = props.ReadLocation();

                var town = new OtTown {
                    Id = townid, Name = townName, TempleLocation = templeLocation
                };
                towns[townid] = town;

                nodeTown = nodeTown.Next;
            }
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
        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;
                }
            }
        }
예제 #10
0
 public virtual void Deserialize(OtFileReader fileReader, OtFileNode itemNode, OtPropertyReader reader, OtItems items)
 {
     Deserialize(reader);
 }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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;
                }
            }
        }