Пример #1
0
        /// <summary>
        /// Create and initialized UODataManager object, wich represent viewmodel and logic of UO data.
        /// </summary>
        /// <param name="uri">Folder path to client data or data-server address. At this momment only local path are supported.</param>
        /// <param name="type">Combination of flags to specify general behavior of UOEngine.
        /// * if you want to use _x version of maps and statics use UseExtFacet flag (only for SA and HS),
        /// * to use special abilities of UOEngine you need additional files, to do it use UseExtFiles flag.</param>
        /// <param name="language">Specify language that used in data files and server.</param>
        /// <param name="dataoptions">Additional options. Set it 'null' for autodetect.</param>
        /// <param name="realtime">If true, engine will save all data at realtime, otherwise it will caching them and save changes in local folder.</param>
        public UODataManager(Uri uri, UODataType type, Language language, UODataOptions dataoptions = null, bool realtime = true)
        {
            CheckValues(uri, type, language, dataoptions, realtime);

            Location        = uri;
            DataType        = type;
            Language        = language;
            RealTime        = realtime;
            m_Instanes[uri] = this;

            dataOptions = dataoptions ?? new UODataOptions(Location);
            dataFactory = (type.HasFlag(UODataType.UseMulFiles) || type.HasFlag(UODataType.UseUopFiles)) ? new ClassicFactory(this) : null;

            if (dataFactory == null)
            {
                return;
            }

            // Initialize data... its loading, wait, wait
            // TODO: We need separeted thread for data working
            _storageMaps = dataFactory.GetMapFacets();
            _storageLand = dataFactory.GetLandTiles();
            _storageItem = dataFactory.GetItemTiles();
            _storageGump = dataFactory.GetGumpSurfs();
            _storageAnim = dataFactory.GetAnimations();
        }
Пример #2
0
        /// <summary>
        /// Create and initialized UODataManager object, wich represent viewmodel and logic of UO data.
        /// </summary>
        /// <param name="uri">Folder path to client data or data-server address. At this momment only local path are supported.</param>
        /// <param name="type">Combination of flags to specify general behavior of UOEngine.
        /// * if you want to use _x version of maps and statics use UseExtFacet flag (only for SA and HS),
        /// * to use special abilities of UOEngine you need additional files, to do it use UseExtFiles flag.</param>
        /// <param name="language">Specify language that used in data files and server.</param>
        /// <param name="dataoptions">Additional options. Set it 'null' for autodetect.</param>
        /// <param name="realtime">If true, engine will save all data at realtime, otherwise it will caching them and save changes in local folder.</param>
        public UODataManager(Uri uri, UODataType type, Language language, UODataOptions dataoptions = null, bool realtime = true)
        {
            if (uri == null || type == 0 || language == null)
            {
                throw new ArgumentException("Bad parametre values");
            }
            if (m_Instanes.ContainsKey(uri))
            {
                throw new ArgumentException("Already inited with selected Uri");
            }

            Location        = uri;
            DataType        = type;
            Language        = language;
            RealTime        = realtime;
            m_Instanes[uri] = this;

            dataOptions = dataoptions ?? new UODataOptions(Location);
            dataFactory = (type.HasFlag(UODataType.UseMulFiles) || type.HasFlag(UODataType.UseUopFiles)) ? new ClassicFactory(this) : null;

            // Initialize data... its loading, wait, wait
            // TODO: We need separeted thread for data working
            StorageMaps = dataFactory.GetMapFacets();
            StorageLand = dataFactory.GetLandTiles();
            StorageItem = dataFactory.GetItemTiles();
            StorageGump = dataFactory.GetGumpSurfs();
            StorageAnim = dataFactory.GetAnimations();
        }
Пример #3
0
 private static void CheckValues(Uri uri, UODataType type, Language language, UODataOptions dataoptions = null, bool realtime = true)
 {
     if (uri == null || type == 0 || language == null)
     {
         throw new ArgumentException("Bad parametre values");
     }
     if (m_Instanes.ContainsKey(uri))
     {
         throw new ArgumentException("Already inited with selected Uri");
     }
 }
Пример #4
0
        public override void Dispose()
        {
            m_Instanes.Remove(Location);
            dataOptions = null;
            if (dataFactory != null)
            {
                dataFactory.Dispose();
            }

            _storageMaps = null;
            _storageLand = null;
            _storageItem = null;
            _storageGump = null;
            _storageAnim = null;
            GC.Collect();
        }
Пример #5
0
        /// <summary>
        /// Create and initialized UODataManager object, wich represent viewmodel and logic of UO data.
        /// </summary>
        /// <param name="uri">Folder path to client data or data-server address. At this momment only local path are supported.</param>
        /// <param name="type">Combination of flags to specify general behavior of UOEngine. 
        /// * if you want to use _x version of maps and statics use UseExtFacet flag (only for SA and HS),
        /// * to use special abilities of UOEngine you need additional files, to do it use UseExtFiles flag.</param>
        /// <param name="language">Specify language that used in data files and server.</param>
        /// <param name="dataoptions">Additional options. Set it 'null' for autodetect.</param>
        /// <param name="realtime">If true, engine will save all data at realtime, otherwise it will caching them and save changes in local folder.</param>
        public UODataManager(Uri uri, UODataType type, Language language, UODataOptions dataoptions = null, bool realtime = true)
        {
            if (uri == null || type == 0 || language == null)
                throw new ArgumentException("Bad parametre values");
            if (m_Instanes.ContainsKey(uri))
                throw new ArgumentException("Already inited with selected Uri");

            Location = uri;
            DataType = type;
            Language = language;
            RealTime = realtime;
            m_Instanes[uri] = this;

            dataOptions = dataoptions ?? new UODataOptions(Location);
            dataFactory = (type.HasFlag(UODataType.UseMulFiles) || type.HasFlag(UODataType.UseUopFiles)) ? new ClassicFactory(this) : null;

            // Initialize data... its loading, wait, wait
            // TODO: We need separeted thread for data working
            StorageMaps = dataFactory.GetMapFacets();
            StorageLand = dataFactory.GetLandTiles();
            StorageItem = dataFactory.GetItemTiles();
            StorageGump = dataFactory.GetGumpSurfs();
            StorageAnim = dataFactory.GetAnimations();
        }
Пример #6
0
        public static UODataManager GetInstance(Uri uri, UODataType type, Language language, UODataOptions dataoptions = null, bool realtime = true)
        {
            if (uri == null || type == 0 || language == null)
            {
                throw new ArgumentException("Bad parametre values");
            }
            if (!m_Instanes.ContainsKey(uri))
            {
                return(new UODataManager(uri, type, language, dataoptions, realtime));
            }


            var result = m_Instanes[uri] as UODataManager;

            if (result != null)
            {
                result.Dispose();
            }

            return(new UODataManager(uri, type, language, dataoptions, realtime));
        }
Пример #7
0
 private void btnLoadMuls_Click(object sender, RoutedEventArgs e)
 {
     try {
         UOManager = null;
         var datauri = new Uri(tbPath.Text);
         var dataopt = new UODataOptions();
         dataopt.majorFacet[0] = new FacetDesc("FacetMap-0", (ushort)nudM0W.Value, (ushort)nudM0H.Value, (ushort)nudM0W.Value, (ushort)nudM0H.Value);
         dataopt.majorFacet[1] = new FacetDesc("FacetMap-1", (ushort)nudM1W.Value, (ushort)nudM1H.Value, (ushort)nudM1W.Value, (ushort)nudM1H.Value);
         dataopt.majorFacet[2] = new FacetDesc("FacetMap-2", (ushort)nudM2W.Value, (ushort)nudM2H.Value, (ushort)nudM2W.Value, (ushort)nudM2H.Value);
         dataopt.majorFacet[3] = new FacetDesc("FacetMap-3", (ushort)nudM3W.Value, (ushort)nudM3H.Value, (ushort)nudM3W.Value, (ushort)nudM3H.Value);
         dataopt.majorFacet[4] = new FacetDesc("FacetMap-4", (ushort)nudM4W.Value, (ushort)nudM4H.Value, (ushort)nudM4W.Value, (ushort)nudM4H.Value);
         dataopt.majorFacet[5] = new FacetDesc("FacetMap-5", (ushort)nudM5W.Value, (ushort)nudM5H.Value, (ushort)nudM5W.Value, (ushort)nudM5H.Value);
         var _manager = new UODataManager(datauri,
             cbUT.SelectedIndex == 0 ? UODataType.ClassicMondainsLegacy :
             cbUT.SelectedIndex == 1 ? UODataType.ClassicStygianAbyss   : 
             UODataType.ClassicAdventuresOnHighSeas, UOLang.Russian, dataopt, true);
         UOManager = _manager;
     } catch (Exception ex) {
         UOManager = null;
         MessageBox.Show("While loading data exception was raised.\nCheck path, map sizes and make sure that all data muls are present.");
     }
 }
Пример #8
0
        static void Main(string[] args)
        {
            #if !DEBUG
            try {
            #endif
                int from = 1;
                if (String.Compare(args[0], "--fsutil", true) == 0) {
                    var srsdir = String.Empty;
                    var trgdir = String.Empty;
                    var lspath = String.Empty;
                    var imgcls = String.Empty;
                    var lminid = 0x00000000;
                    var lmaxid = 0x0FFFFFFF;
                    var lcount = 0;
                    var dcount = 0;
                    var trimsp = (int)0;
                    var shmove = (int)0;
                    var outhex = false;
                    var outdel = false;
                    List<uint[]> inrule = null;

                    args = args.Select(a => a.ToLower()).Skip(1).ToArray();
                    var enumerator = args.GetEnumerator();
                    while (enumerator.MoveNext()) {
                        var arg = enumerator.Current as String;
                        if (arg == "-pfx" && enumerator.MoveNext()) {
                            imgcls = enumerator.Current as String;
                        } else

                        if (arg == "-min" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            lminid = arg.StartsWith("0x") ? Int32.Parse(arg.Substring(2), NumberStyles.AllowHexSpecifier) : Int32.Parse(arg, NumberStyles.None);
                        } else
                        if (arg == "-max" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            lmaxid = arg.StartsWith("0x") ? Int32.Parse(arg.Substring(2), NumberStyles.AllowHexSpecifier) : Int32.Parse(arg, NumberStyles.None);
                        } else

                        if (arg == "-ren" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            if (arg != "beg" && arg != "end") {
                                int f = 0;
                                inrule = GetMultiDimentionList(new [] {arg}, ref f);
                            } else
                                trimsp = (arg == "beg") ? 1 : (arg == "end") ? -1 : 0;
                        } else

                        if (arg == "-mov" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            if ((shmove = arg[0] == '-' ? -1 : arg[0] == '+' ? +1 : 0) != 0)
                                arg = arg.Substring(1); else shmove = +1;
                            shmove *= arg.StartsWith("0x") ? Int32.Parse(arg.Substring(2), NumberStyles.AllowHexSpecifier) : Int32.Parse(arg, NumberStyles.None);
                        } else

                        if (arg == "-len" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            lcount = arg.StartsWith("0x") ? Int32.Parse(arg.Substring(2), NumberStyles.AllowHexSpecifier) : Int32.Parse(arg, NumberStyles.None);
                        } else
                        if (arg == "-dcn" && enumerator.MoveNext()) {
                            arg = enumerator.Current as String;
                            dcount = arg.StartsWith("0x") ? Int32.Parse(arg.Substring(2), NumberStyles.AllowHexSpecifier) : Int32.Parse(arg, NumberStyles.None);
                        } else
                        if (arg == "-hex") {
                            outhex = true;
                        } else
                        if (arg == "-del") {
                            outdel = true;
                        } else

                        if (String.IsNullOrWhiteSpace(srsdir)) {
                            srsdir = GetFullPath(arg);
                        } else
                        if (String.IsNullOrWhiteSpace(trgdir)) {
                            trgdir = GetFullPath(arg);
                        } else
                        if (String.IsNullOrWhiteSpace(lspath)) {
                            lspath = GetFullPath(arg);
                        } else

                        continue;
                    }
                    if (lcount == 0)
                        lcount = outhex ? 4 : 5;
                    if (dcount == 0)
                        dcount = lcount;
 
                    if (String.IsNullOrWhiteSpace(srsdir) || String.IsNullOrWhiteSpace(trgdir)) 
                        throw new ArgumentException();

                    var searchPattern = new Regex((!String.IsNullOrEmpty(imgcls) ? (@"[\\/][" + imgcls + @"]") : @"[\\/]") + @"(0x[A-F0-9\-]{" + lcount + @"}|[0-9\-]{" + lcount + @"})\.(mde|bmp|png|tif|tiff|gif|wav|vd)$", RegexOptions.IgnoreCase);
                    var lfiles = Directory.GetFiles(srsdir, "*", SearchOption.TopDirectoryOnly).Where(f => searchPattern.IsMatch(f)).Select(f => f.Substring(f.LastIndexOf('\\') + 1).ToLower()).ToArray();
                    var entries = lfiles.Select(f => {
                        var _ext = f.Substring(f.LastIndexOf(@"."));
                        var _nam = f.Substring(0, f.Length - _ext.Length);
                        var _hex = _nam.Contains("0x");
                        var _str = _hex ? _nam.LastIndexOf('x') + 1 : (_nam.Length - _nam.Reverse().SkipWhile(c => !Char.IsDigit(c)).Count());
                        var _len = f.Length - _ext.Length - _str;
                        var _idx = UInt32.Parse(f.Substring(_str, _len), _hex ? NumberStyles.AllowHexSpecifier : NumberStyles.None);
                        return new FileDesc(_ext, _hex, (ushort)_len, (ushort)_idx);
                    }).ToList();
                    if (inrule != null) {
                        for (int i = entries.Count - 1; i >= 0; --i) {
                            var id = entries[i].OrigIndex;
                            var nr = inrule.FirstOrDefault(r => r[0] == id);
                            if (nr == null)
                                entries.RemoveAt(i);
                            else
                                entries[i].SetMoveIndex((int)nr[1]);
                        }
                    }
                    entries = entries.Where(e => e.OrigIndex >= lminid && e.OrigIndex <= lmaxid).ToList();
                    entries.Sort(FileDesc.CompareFileDescByOrigIndex);

                    if (shmove != 0)
                        for (int i = 0; i < entries.Count; ++i)
                            entries[i].SetMoveIndex(entries[i].OrigIndex + shmove);
                    if (trimsp > 0)
                        for (int idx = (int)entries.First().MoveIndex, i = 0; i < entries.Count; ++i)
                            entries[i].SetMoveIndex(idx++);
                    if (trimsp < 0)
                        for (int idx = (int)entries.Last().MoveIndex, i = entries.Count - 1; i >= 0; --i)
                            entries[i].SetMoveIndex(idx--);                

                    var list = String.Empty;
                    enumerator = entries.GetEnumerator();
                    while (enumerator.MoveNext()) {
                        var entry = (FileDesc)enumerator.Current;
                        var path1 = Path.Combine(srsdir, String.Format("{0}{1}{2}", imgcls.ToUpper(), String.Format((entry.HexFormat ? "0x{0:X" : "{0:D") + entry.OrigCount + "}", entry.OrigIndex), entry.Extension));
                        var path2 = Path.Combine(trgdir, String.Format("{0}{1}{2}", imgcls.ToUpper(), String.Format((outhex ? "0x{0:X" : "{0:D") + dcount + "}", entry.MoveIndex), entry.Extension));
                        list += String.Format("0x{0:X5} -> 0x{1:X5}{2}", entry.OrigIndex, entry.MoveIndex, Environment.NewLine);
                        File.Copy(path1, path2);
                        if (outdel)
                            File.Delete(path1);
                    }
                    if (!String.IsNullOrWhiteSpace(lspath))
                        File.WriteAllText(lspath, list);
                } else

                if (String.Compare(args[0], "--create", true) == 0) {
                    ResetProcessStatus(1, "Creating container ");
                    var leng = StringToUint(args[from++]);
                    uint size = 0; string fidx = null;
                    try { size = StringToUint(args[from++]); }
                    catch (Exception e) { --from; fidx = GetFullPath(args[from++]); }
                    var fmul = GetFullPath(args[from++]);
                    var smul = new FileStream(fmul, FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, false);
                    if (fidx == null) {
                        smul.SetLength(leng * size);
                    } else {
                        smul.SetLength(4);
                        var sidx = new FileStream(fidx, FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, false);
                        var identry = new byte[12] { 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF,   0x00, 0x00, 0x00, 0x00 };
                        for (int i = 0; i < leng; ++i)
                            sidx.Write(identry, 0, 12);
                        sidx.Flush();
                        sidx.Close();
                    }
                    smul.Flush();
                    smul.Close();
                    UpdateProcessStatus(1);
                } else
                if (String.Compare(args[0], "--resize", true) == 0) {
                    var leng = StringToUint(args[from++]);
                    var mulc = GetMulContainer(args, ref from);
                    ResetProcessStatus(mulc.EntryLength, "Resizing container ");
                    mulc.Resize(leng);
                    UpdateProcessStatus(mulc.EntryLength);
                } else
                if (String.Compare(args[0], "--defrag", true) == 0) {
                    var mulc = GetMulContainer(args, ref from);
                    ResetProcessStatus(mulc.EntryLength, "Defragmentating container ");
                    mulc.Defrag();
                    UpdateProcessStatus(mulc.EntryLength);
                } else
                if (String.Compare(args[0], "--export", true) == 0) {
                    var fold = GetFullPath(args[from++]);
                    var mulc = GetMulContainer(args, ref from);
                    ResetProcessStatus(mulc.EntryLength * mulc.EntryItemsCount, "Export data ");
                    for (uint it = 0, i = 0; i < mulc.EntryLength; ++i) {
                        if (!mulc.IsValid(i))
                            continue;
                        for (uint c = 0; c < mulc.EntryItemsCount; ++c) {
                            var id = i * mulc.EntryItemsCount + c;
                            var file = Path.Combine(fold, String.Format("{0:000000}.mde", id));
                            var stream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, false);
                            if (mulc.IsIndexBased)
                                stream.Write(Utils.StructToBuff(mulc.GetExtra(i)), 0, 4);
                            var data = mulc[id, mulc.EntryItemsCount > 1];
                            stream.Write(data, 0, data.Length);
                            stream.Flush();
                            stream.Close();
                            UpdateProcessStatus(++it);
                        }
                        
                    }
                } else
                if (String.Compare(args[0], "--import", true) == 0) {
                    var fold = GetFullPath(args[from++]);
                    var mulc = GetMulContainer(args, ref from);
                    var fils = Directory.GetFiles(fold, "??????.mde", SearchOption.TopDirectoryOnly);
                    uint it = 0;
                    ResetProcessStatus((uint)fils.Length, "Import data ");
                    foreach (var file in fils) {
                        uint i;
                        if (!uint.TryParse(Path.GetFileNameWithoutExtension(file), out i))
                            continue;
                        var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000, false);
                        if (mulc.IsIndexBased) {
                            var edat = new byte[4];
                            stream.Read(edat, 0, 4);
                            mulc.SetExtra(i, Utils.BuffToStruct<uint>(edat, 0, 1)[0]);
                        }
                        var data = new byte[stream.Length - stream.Position];
                        stream.Read(data, 0, data.Length);
                        mulc[i, mulc.EntryItemsCount > 1] = data;
                        UpdateProcessStatus(++it);
                    }
                } else
                if (String.Compare(args[0], "--merger", true) == 0) {
                    var fol1 = GetFullPath(args[from++]);
                    var mul1 = GetMulContainer(args, ref from);
                    var fol2 = GetFullPath(args[from++]);
                    var mul2 = GetMulContainer(args, ref from);
                    if (mul1.EntryItemsCount != mul2.EntryItemsCount || mul1.EntryLength != mul2.EntryLength)
                        throw new Exception("Both mul containers must be same type.");
                    var cmpr = Math.Min(mul1.EntryLength, mul2.EntryLength);
                    var item = mul1.EntryItemsCount > 1;
                    ResetProcessStatus(cmpr * mul1.EntryItemsCount, "Merging data ");
                    for (uint it = 0, i = 0; i < cmpr; ++i) {
                        byte[] dat1 = null; 
                        byte[] dat2 = null;
                        if (!mul1.IsValid(i) && !mul2.IsValid(i)) {
                            //if (mul1.IsValid(i))
                            //    dat1 = mul1[i];
                            //else if (mul2.IsValid(i))
                            //    dat2 = mul2[i];
                            //else {
                                it += mul1.EntryItemsCount;
                                continue;
                            //}
                        }
                        for (uint c = 0; c < mul1.EntryItemsCount; ++c) {
                            var id = i * mul1.EntryItemsCount + c;
                            dat1 = dat1 ?? mul1[id, item];
                            dat2 = dat2 ?? mul2[id, item];
                            if (dat1 != null && dat2 != null && Utils.ArrayIdentical(dat1, dat2)) {
                                ++it;
                                continue;
                            }
                            for (int m = 1; m < 3; ++m) {
                                var data = (m == 1) ? dat1 : dat2;
                                if (data == null)
                                    continue;
                                var mulc = (m == 1) ? mul1 : mul2;
                                var file = Path.Combine((m == 1) ? fol1 : fol2, String.Format("{0:000000}.mde", i));
                                var stream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, false);
                                if (mulc.IsIndexBased)
                                    stream.Write(Utils.StructToBuff(mulc.GetExtra(i)), 0, 4);
                                stream.Write(data, 0, data.Length);
                                stream.Flush();
                                stream.Close();
                            }
                            dat1 = dat2 = null;
                            UpdateProcessStatus(++it);
                        }
                    }   
                } else
                if (String.Compare(args[0], "--convtd", true) == 0) {
                    var file = GetFullPath(args[from++]);
                    var fnew = Boolean.Parse(args[from++]);
                    var mulf = GetFullPath(args[from++]);
                    var virt = ContainerFactory.CreateVirtualMul(null, mulf);
                    var land = ContainerFactory.CreateMul(virt, fnew ? 964u : 836u, 0, 0x4000 >> 5);
                    var item = ContainerFactory.CreateMul(virt, fnew ? 1316u : 1188u, (0x4000 >> 5) * (fnew ? 964u : 836u), 0);
                    var tile = new[] {land, item};
                    var dest = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, 0x1000, false);
                    var cons = new byte[4] {0x00, 0x00, 0x00, 0x00};
                    ResetProcessStatus(land.EntryLength + item.EntryLength, "Converting tiledata ");
                    for (int it = 0, t = 0; t < 2; ++t) {
                        var size = (t == 0) ? (fnew ? 30 : 26) : (fnew ? 41 : 37);
                        for (uint i = 0; i < tile[t].EntryLength; ++i) {
                            var data = tile[t][i];
                            dest.Write(data, 0, 4);
                            if (fnew) // from new to old
                                for (int offs = 4, e = 0; e < 32; ++e, offs += size) {
                                    dest.Write(data, offs, 4);
                                    dest.Write(data, offs + 8, size - 8);
                                }
                            else // from old to new
                                for (int offs = 4, e = 0; e < 32; ++e, offs += size) {
                                    dest.Write(data, offs, 4);
                                    dest.Write(cons, 0, 4);
                                    dest.Write(data, offs + 4, size - 4);
                                }
                            UpdateProcessStatus((uint)++it);
                        } 
                    }
                    dest.Flush();
                    dest.Close();
                } else
                if (String.Compare(args[0], "--convmt", true) == 0) {
                    var fnew = Boolean.Parse(args[from++]);
                    var idxf = GetFullPath(args[from++]);
                    var mulf = GetFullPath(args[from++]);
                    var mult = ContainerFactory.CreateMul(idxf, mulf);
                    var cons = new byte[4] {0x00, 0x00, 0x00, 0x00};
                    ResetProcessStatus(mult.EntryLength, "Converting multi ");
                    for (uint it = 0, i = 0; i < mult.EntryLength; ++i) {
                        var dbuf = mult[i];
                        var data = new byte[(dbuf.Length / (fnew ? 16 : 12)) * (fnew ? 12 : 16)];
                        if (fnew) // from new to old
                            for (int t = 0, s = 0; s < dbuf.Length; s += 16, t += 12) {
                                Array.Copy(dbuf, s, data, t, 12);
                            }
                        else // from old to new
                            for (int t = 0, s = 0; s < dbuf.Length; s += 12, t += 16) {
                                Array.Copy(dbuf, s, data, t, 12);
                                Array.Copy(cons, 0, data, t + 12, 4);
                            }
                        mult[i] = data;
                        UpdateProcessStatus(++it);
                    }
                } else

                // --------------------------------------------------------------------------
                if (String.Compare(args[0], "--copyid", true) == 0) {
                    var list = GetMultiDimentionList(args, ref from);
                    var mulc = GetMulContainer(args, ref from);
                    var virt = mulc.EntryItemsCount > 1;
                    ResetProcessStatus((uint)list.Count, "Copying entries ");
                    for (int it = 0, i = 0; i < list.Count; ++i) {
                        var sors = list[i][0];
                        var dest = list[i][1];
                        if (mulc.IsIndexBased)
                            mulc.SetExtra(dest, mulc.GetExtra(sors));
                        mulc[dest, virt] = mulc[sors, virt];
                        UpdateProcessStatus((uint)++it);
                    }
                } else
                if (String.Compare(args[0], "--moveid", true) == 0) {
                    var list = GetMultiDimentionList(args, ref from);
                    var mulc = GetMulContainer(args, ref from);
                    var virt = mulc.EntryItemsCount > 1;
                    ResetProcessStatus((uint)list.Count, "Moving entries ");
                    for (int it = 0, i = 0; i < list.Count; ++i) {
                        var sors = list[i][0];
                        var dest = list[i][1];
                        if (mulc.IsIndexBased)
                            mulc.SetExtra(dest, mulc.GetExtra(sors));
                        mulc[dest, virt] = mulc[sors, virt];
                        if (mulc.IsIndexBased)
                            mulc[sors] = null;
                        UpdateProcessStatus((uint)++it);
                    }
                } else
                if (String.Compare(args[0], "--remove", true) == 0) {
                    var list = GetSingleDimentionList(args, ref from);
                    var mulc = GetMulContainer(args, ref from);
                    ResetProcessStatus((uint)list.Count, "Deleting entries ");
                    for (int it = 0, i = 0; i < list.Count; ++i) {
                        mulc[list[i]] = null;
                        UpdateProcessStatus((uint)++it);
                    }
                } else

                // --------------------------------------------------------------------------
                if (String.Compare(args[0], "--facetm", true) == 0) {
                    var folder = GetFullPath(args[from++]);
                    var uodata = (UODataType)StringToUint(args[from++]);
                    var uoopta = args[from++].Split(new []{'|'}, StringSplitOptions.RemoveEmptyEntries).Select(s => (ushort)StringToUint(s)).ToArray();
                    var uoopts = new UODataOptions();
                    for (int a = 0; a < uoopta.Length; a+=3)
                        uoopts.majorFacet[uoopta[a]] = new FacetDesc(String.Format("Facet0{0}", uoopta[a]), uoopta[a+1], uoopta[a+2], uoopta[a+1], uoopta[a+2]);
                    var manager = new UODataManager(new Uri(folder), uodata, Language.English, uoopts, true);
                    var dwriter = manager.DataFactory as IDataFactoryWriter;

                    var frarg = from++;
                    if (String.Compare(args[frarg], "-replid", true) == 0) {
                        byte m; uint x1, y1, x2, y2;
                        var  f = GetMapFacet(args, ref from, manager, out m, out x1, out y1, out x2, out y2);
                        var list = GetMultiDimentionList(args, ref from);
                        ResetProcessStatus((x2 - x1 + 1) * (y2 - y1 + 1), "Replacing land tiles in map ");
                        for (uint it = 1, x = x1; x <= x2; ++x) {
                            for (uint y = y1; y <= y2; ++y, ++it) {
                                var i = f.GetBlockId(x, y);
                                var b = f[i];
                                var c = false;
                                for (uint k = 0; k < 64; ++k) {
                                    var srs = b[k].Land.TileId;
                                    var ent = list.FirstOrDefault(e => e[0] == srs);
                                    if (ent == null)
                                        continue;
                                    b[k].Land.TileId = (ushort)ent[1];
                                    c = true;
                                }
                                if (c) {
                                    var d = b.GetData();
                                    dwriter.SetMapBlock((byte)m, i, d);
                                }
                                UpdateProcessStatus(it);
                                b.Dispose(); 
                            }
                        }
                    } else
                    if (String.Compare(args[frarg], "-reptid", true) == 0) {
                        byte m; uint x1, y1, x2, y2;
                        var  f = GetMapFacet(args, ref from, manager, out m, out x1, out y1, out x2, out y2);
                        var list = GetMultiDimentionList(args, ref from);
                        ResetProcessStatus((x2 - x1 + 1) * (y2 - y1 + 1), "Replacing item tiles in map ");
                        for (uint it = 1, x = x1; x <= x2; ++x) {
                            for (uint y = y1; y <= y2; ++y, ++it) {
                                var i = f.GetBlockId(x, y);
                                var b = f[i];
                                if (b == null) {
                                    UpdateProcessStatus(it);
                                    continue;
                                }
                                var c = false;
                                for (uint k = 0; k < 64; ++k) {
                                    for (int t = 0; t < b[k].Count; ++t) {
                                        var srs = b[k][t].TileId;
                                        var ent = list.FirstOrDefault(e => e[0] == srs);
                                        if (ent == null)
                                            continue;
                                        b[k][t].TileId = (ushort)ent[1];
                                        c = true;
                                    } 
                                }
                                if (c) {
                                    var d = b.GetData();
                                    dwriter.SetMapBlock((byte)m, i, d);
                                }
                                UpdateProcessStatus(it);
                                b.Dispose();
                            }
                        }
                    } else
                    if (String.Compare(args[frarg], "-rephid", true) == 0) {
                        byte m; uint x1, y1, x2, y2;
                        var  f = GetMapFacet(args, ref from, manager, out m, out x1, out y1, out x2, out y2);
                        var list = GetMultiDimentionList(args, ref from);
                        ResetProcessStatus((x2 - x1 + 1) * (y2 - y1 + 1), "Replacing item colors in map ");
                        for (uint it = 1, x = x1; x <= x2; ++x) {
                            for (uint y = y1; y <= y2; ++y, ++it) {
                                var i = f.GetBlockId(x, y);
                                var b = f[i];
                                if (b == null) {
                                    UpdateProcessStatus(it);
                                    continue;
                                }
                                var c = false;
                                for (uint k = 0; k < 64; ++k) {
                                    for (int t = 0; t < b[k].Count; ++t) {
                                        var srs = b[k][t].Palette;
                                        var ent = list.FirstOrDefault(e => e[0] == srs);
                                        if (ent == null)
                                            continue;
                                        b[k][t].Palette = (ushort)ent[1];
                                        c = true;
                                    } 
                                }
                                if (c) {
                                    var d = b.GetData();
                                    dwriter.SetMapBlock((byte)m, i, d);
                                }
                                UpdateProcessStatus(it);
                                b.Dispose();
                            }
                        }
                    } else
                    if (String.Compare(args[frarg], "-render", true) == 0) {
                        byte m; uint x1, y1, x2, y2;
                        var f = GetMapFacet(args, ref from, manager, out m, out x1, out y1, out x2, out y2);
                        var ppt = (byte)  2;
                        var alt = (short)-45;
                        var min = (sbyte)-128;
                        var max = (sbyte)+127;
                        var outpath = "render_out.png";
                        args = args.Skip(from).Select(a => a.ToLower()).ToArray();
                        var enumerator = args.GetEnumerator();
                        while (enumerator.MoveNext()) {
                            var arg = enumerator.Current as String;
                            if (arg == "-ppt" && enumerator.MoveNext()) {
                                arg = enumerator.Current as String;
                                ppt = (byte)Int32.Parse(arg);
                                ++from;
                            } else
                            if (arg == "-alt" && enumerator.MoveNext()) {
                                arg = enumerator.Current as String;
                                alt = (short)Int32.Parse(arg);
                                ++from;
                            } else
                            if (arg == "-min" && enumerator.MoveNext()) {
                                arg = enumerator.Current as String;
                                min = (sbyte)Int32.Parse(arg);
                                ++from;
                            } else
                            if (arg == "-max" && enumerator.MoveNext()) {
                                arg = enumerator.Current as String;
                                max = (sbyte)Int32.Parse(arg);
                                ++from;
                            } else
                                outpath = enumerator.Current as String;
                        }

                        ISurface surf;
                        ResetProcessStatus((x2 - x1 + 1) * (y2 - y1 + 1), "Render flat scaled facet ");
                        manager.FacetRender.SaveFlatMap(out surf, ppt, m, x1, y1, ++x2, ++y2, alt, min, max, SaveFacetCallback);
                        surf.GetSurface().SavePNG(outpath);

                    } else

                        throw new Exception();

                } else


                // --------------------------------------------------------------------------
                if ((String.Compare(args[0], "--help", true) == 0) || (String.Compare(args[0], "-help", true) == 0) 
                    || (String.Compare(args[0], "--h", true) == 0) || (String.Compare(args[0], "-h", true) == 0)
                    || (String.Compare(args[0], "--?", true) == 0) || (String.Compare(args[0], "-?", true) == 0)
                    || (String.Compare(args[0], "\\?", true) == 0) || (String.Compare(args[0], "/?", true) == 0)
                    || (String.Compare(args[0], "help", true) == 0)) {
                    Console.WriteLine(usage);
                } else
                    throw new Exception();
            #if !DEBUG
            } catch(Exception e) {
                Console.WriteLine("Proccess aborted: Ither bad agruments or something real very very bad happened..");
                Console.WriteLine("Run application wiht \"--help\" argumnet for additional info.");              
                var exception = e;
                while (exception != null) {
                    Console.WriteLine("\n\nError: {0}\n\n{1}", exception.Message, exception.StackTrace);
                    exception = exception.InnerException;
                }
            }
            #endif
        }