Пример #1
0
        // example serialized pokemon:
        //
        // 50 Butterfree (31)@"Silk Powder"
        // - "Stun Spore"
        // - "Super Sonic"
        // - "Aerial Ace"
        // - "Silver Wind"

        public IStreamRun DeserializeRun(string content, ModelDelta token)
        {
            var lines = content.Split(Environment.NewLine).Select(line => line.Trim()).ToArray();

            // step 1: parse it into some data containers
            var data = new TeamData(ModelCacheScope.GetCache(model), lines);

            // step 2: figure out what I need based on the data
            var elementLength = data.MovesIncluded ? 16 : 8;
            var totalLength   = elementLength * data.Pokemon.Count;
            var workingRun    = this;

            if (totalLength > workingRun.Length)
            {
                workingRun = (TrainerPokemonTeamRun)model.RelocateForExpansion(token, workingRun, totalLength);
            }

            // step 3: write the run data
            WriteData(token, workingRun.Start, data);

            // step 4: write the parent data
            var structType = (data.ItemsIncluded ? INCLUDE_ITEM : 0) ^ (data.MovesIncluded ? INCLUDE_MOVES : 0);

            UpdateParents(token, structType, data.Pokemon.Count, workingRun.PointerSources);

            return(new TrainerPokemonTeamRun(model, workingRun.Start, workingRun.PointerSources));
        }
Пример #2
0
        public PLMRun(IDataModel dataModel, int start)
        {
            model = dataModel;
            var moveNames = ModelCacheScope.GetCache(dataModel).GetOptions(EggMoveRun.MoveNamesTable);

            Start = start;
            for (int i = Start; i < model.Count; i += 2)
            {
                var value = model.ReadMultiByteValue(i, 2);
                if (value == 0xFFFF)
                {
                    Length = i - Start + 2;
                    break;
                }
                // validate value
                var(level, move) = SplitToken(value);
                if (level > 101 || level < 1)
                {
                    break;
                }
                if (move > moveNames.Count)
                {
                    break;
                }
            }
        }
Пример #3
0
      public IStreamRun DeserializeRun(string content, ModelDelta token) {
         var cache = ModelCacheScope.GetCache(model);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         var data = new List<int>();
         var pokemonNames = cachedPokenames.Select(name => $"{GroupStart}{name.Trim('"').ToLower()}{GroupEnd}").ToList();
         var moveNames = cachedMovenames.Select(name => name.Trim('"').ToLower()).ToList();
         var lines = content.ToLower().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
         foreach (var line in lines) {
            var index = pokemonNames.IndexOf(line);
            if (index != -1) { data.Add(index + MagicNumber); continue; }
            index = moveNames.IndexOf(line);
            if (index != -1) { data.Add(index); continue; }

            // didn't find an exact match... look for a partial pokemon match
            var matchFound = false;
            for (int i = 0; i < pokemonNames.Count; i++) {
               if (pokemonNames[i].Contains(line)) { data.Add(i + MagicNumber); matchFound = true; break; }
            }
            if (matchFound) continue;

            // look for a partial move match
            for (int i = 0; i < moveNames.Count; i++) {
               if (moveNames[i].Contains(line)) { data.Add(i); break; }
            }
         }
         var run = model.RelocateForExpansion(token, this, data.Count * 2 + 2);
         for (int i = 0; i < data.Count; i++) model.WriteMultiByteValue(run.Start + i * 2, 2, token, data[i]);
         model.WriteMultiByteValue(run.Start + data.Count * 2, 2, token, EndStream); // write the new end token
         for (int i = data.Count + 2; i < Length / 2; i++) model.WriteMultiByteValue(run.Start + i * 2, 2, token, EndStream); // fill any remaining old space with FF
         return new EggMoveRun(model, run.Start);
      }
Пример #4
0
      public int GetMoveNumber(string input) {
         var cache = ModelCacheScope.GetCache(model);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         input = input.Trim('"').ToLower();
         var names = cachedMovenames.Select(name => name.Trim('"').ToLower()).ToList();
         return names.IndexOfPartial(input);
      }
Пример #5
0
      public IEnumerable<string> GetAutoCompleteOptions() {
         var cache = ModelCacheScope.GetCache(model);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         var pokenames = cachedPokenames.Select(name => $"{GroupStart}{name}{GroupEnd}"); // closing brace, so no space needed
         var movenames = cachedMovenames.Select(name => name + " "); // autocomplete needs to complete after selection, so add a space
         return pokenames.Concat(movenames);
      }
Пример #6
0
      public int GetPokemonNumber(string input) {
         var cache = ModelCacheScope.GetCache(model);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);

         if (input.StartsWith(GroupStart)) input = input.Substring(1, input.Length - 2);
         input = input.ToLower();
         var names = cachedPokenames.Select(name => name.Trim('"').ToLower()).ToList();
         return names.IndexOfPartial(input);
      }
Пример #7
0
        public static bool TrySearch(IDataModel data, ModelDelta changeToken, string originalFormat, out ArrayRun self, Func <IFormattedRun, bool> runFilter = null)
        {
            self = null;
            var format = originalFormat;
            var allowPointersToEntries = format.StartsWith(AnchorStart.ToString());

            if (allowPointersToEntries)
            {
                format = format.Substring(1);
            }
            var closeArray = format.LastIndexOf(ArrayEnd.ToString());

            if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1)
            {
                throw new ArrayRunParseException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}");
            }
            var segments       = format.Substring(1, closeArray - 1);
            var length         = format.Substring(closeArray + 1);
            var elementContent = ParseSegments(segments, data);

            if (elementContent.Count == 0)
            {
                return(false);
            }
            var elementLength = elementContent.Sum(e => e.Length);

            using (ModelCacheScope.CreateScope(data)) {
                if (string.IsNullOrEmpty(length))
                {
                    var bestAddress = StandardSearch(data, elementContent, elementLength, out int bestLength, runFilter);
                    if (bestAddress == Pointer.NULL)
                    {
                        return(false);
                    }
                    self = new ArrayRun(data, originalFormat + bestLength, string.Empty, bestAddress, bestLength, elementContent, data.GetNextRun(bestAddress).PointerSources, null);
                }
                else
                {
                    var bestAddress = KnownLengthSearch(data, elementContent, elementLength, length, out int bestLength, runFilter);
                    if (bestAddress == Pointer.NULL)
                    {
                        return(false);
                    }
                    var lengthFromAnchor = int.TryParse(length, out var _) ? string.Empty : length;
                    self = new ArrayRun(data, originalFormat, lengthFromAnchor, bestAddress, bestLength, elementContent, data.GetNextRun(bestAddress).PointerSources, null);
                }
            }

            if (allowPointersToEntries)
            {
                self = self.AddSourcesPointingWithinArray(changeToken);
            }
            return(true);
        }
Пример #8
0
        public static ErrorInfo TryParse(IDataModel data, string format, int start, IReadOnlyList <int> pointerSources, out ArrayRun self)
        {
            try {
                using (ModelCacheScope.CreateScope(data)) {
                    self = new ArrayRun(data, format, start, pointerSources);
                }
            } catch (ArrayRunParseException e) {
                self = null;
                return(new ErrorInfo(e.Message));
            }

            return(ErrorInfo.NoError);
        }
Пример #9
0
        public string SerializeRun()
        {
            var cache  = ModelCacheScope.GetCache(model);
            var buffer = new StringBuilder();

            for (int i = 0; i < ElementCount; i++)
            {
                var start    = Start + ElementLength * i;
                var ivSpread = model.ReadMultiByteValue(start + 0, 2);
                if (!showFullIVByteRange)
                {
                    ivSpread = (int)Math.Round(ivSpread * IV_Cap / 255.0);
                }
                var level        = model.ReadMultiByteValue(start + 2, 2);
                var pokeID       = model.ReadMultiByteValue(start + 4, 2);
                var pokemonNames = cache.GetOptions(HardcodeTablesModel.PokemonNameTable);
                var pokemon      = pokemonNames.Count > pokeID ? pokemonNames[pokeID] : pokeID.ToString();
                start += 6;

                var item = string.Empty;
                if ((StructType & INCLUDE_ITEM) != 0)
                {
                    var itemID    = model.ReadMultiByteValue(start, 2);
                    var itemNames = cache.GetOptions(HardcodeTablesModel.ItemsTableName);
                    item   = itemNames.Count > itemID ? itemNames[itemID] : itemID.ToString();
                    item   = "@" + item;
                    start += 2;
                }

                buffer.AppendLine($"{level} {pokemon} (IVs={ivSpread}){item}");
                if ((StructType & INCLUDE_MOVES) != 0)
                {
                    var moveNames = cache.GetOptions(HardcodeTablesModel.MoveNamesTable);
                    for (int j = 0; j < 4; j++)
                    {
                        var moveID = model.ReadMultiByteValue(start + j * 2, 2);
                        var move   = moveNames.Count > moveID ? moveNames[moveID] : moveID.ToString();
                        buffer.AppendLine($"- {move}");
                    }
                }
                else
                {
                    buffer.AppendLine();
                }
                if (i + 1 < ElementCount)
                {
                    buffer.AppendLine();
                }
            }
            return(buffer.ToString());
        }
Пример #10
0
        public IDataFormat CreateDataFormat(IDataModel data, int index)
        {
            Debug.Assert(data == model);
            var moveNames  = ModelCacheScope.GetCache(model).GetOptions(EggMoveRun.MoveNamesTable);
            var position   = index - Start;
            var groupStart = position % 2 == 1 ? position - 1 : position;

            position -= groupStart;
            var value = data.ReadMultiByteValue(Start + groupStart, 2);

            var(level, move) = SplitToken(value);
            var moveName = moveNames.Count > move ? moveNames[move] : move.ToString();

            return(new PlmItem(groupStart + Start, position, level, move, moveName));
        }
Пример #11
0
        public IStreamRun DeserializeRun(string content, ModelDelta token)
        {
            var data      = new List <int>();
            var moveNames = ModelCacheScope.GetCache(model).GetOptions(EggMoveRun.MoveNamesTable);

            moveNames = moveNames.Select(name => name.Trim('"').ToLower()).ToList();

            var lines = content.ToLower().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var line in lines)
            {
                var parts = line.Split(new[] { ' ' }, 2);
                if (!int.TryParse(parts[0], out var level))
                {
                    level = 0;
                }
                var moveName = parts.Length == 1 ? "0" : parts[1];
                moveName = moveName.Trim().Trim('"');

                var index = moveNames.IndexOf(moveName);
                if (index != -1)
                {
                    data.Add(CombineToken(level, index)); continue;
                }

                // look for a partial move match
                for (int i = 0; i < moveNames.Count; i++)
                {
                    if (moveNames[i].MatchesPartial(moveName))
                    {
                        data.Add(CombineToken(level, i)); break;
                    }
                }
            }

            var run = model.RelocateForExpansion(token, this, data.Count * 2 + 2);

            for (int i = 0; i < data.Count; i++)
            {
                model.WriteMultiByteValue(run.Start + i * 2, 2, token, data[i]);
            }
            model.WriteMultiByteValue(run.Start + data.Count * 2, 2, token, EggMoveRun.EndStream); // write the new end token
            for (int i = data.Count + 2; i < Length / 2; i++)
            {
                model.WriteMultiByteValue(run.Start + i * 2, 2, token, EggMoveRun.EndStream);                                            // fill any remaining old space with FF
            }
            return(new PLMRun(model, run.Start));
        }
Пример #12
0
        public string SerializeRun()
        {
            var moveNames = ModelCacheScope.GetCache(model).GetOptions(EggMoveRun.MoveNamesTable);
            var builder   = new StringBuilder();

            for (int i = 0; i < Length - 2; i += 2)
            {
                var address = Start + i;
                var(level, move) = SplitToken(model.ReadMultiByteValue(address, 2));
                var moveName = moveNames.Count > move ? moveNames[move] : move.ToString();
                builder.Append($"{level} {moveName}");
                if (i < Length - 4)
                {
                    builder.AppendLine();
                }
            }
            return(builder.ToString());
        }
Пример #13
0
      public string SerializeRun() {
         var cache = ModelCacheScope.GetCache(model);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         var builder = new StringBuilder();
         for (int i = 0; i < Length - 2; i += 2) {
            var address = Start + i;
            var value = model.ReadMultiByteValue(address, 2);
            if (value >= MagicNumber) {
               value -= MagicNumber;
               builder.Append($"{GroupStart}{cachedPokenames[value].Trim('"')}{GroupEnd}");
            } else {
               builder.Append(cachedMovenames[value].Trim('"'));
            }
            if (i < Length - 4) builder.AppendLine();
         }
         return builder.ToString();
      }
Пример #14
0
        public bool TryGetMoveNumber(string moveName, out int move)
        {
            moveName = moveName.Trim('"').ToLower();
            var moveNames = ModelCacheScope.GetCache(model).GetOptions(EggMoveRun.MoveNamesTable);
            var names     = moveNames.Select(name => name.Trim('"').ToLower()).ToList();

            // perfect match?
            move = names.IndexOf(moveName);
            if (move != -1)
            {
                return(true);
            }

            // partial match?
            move = names.IndexOfPartial(moveName);

            // last try: numeric match
            return(move != -1 || int.TryParse(moveName, out move));
        }
Пример #15
0
      public void AppendTo(IDataModel model, StringBuilder text, int start, int length, bool deep) {
         var cache = ModelCacheScope.GetCache(model);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         while (length > 0 && start < Start + Length) {
            var value = model.ReadMultiByteValue(start, 2);
            if (value == EndStream) {
               text.Append($"{GroupStart}{GroupEnd}");
            } else if (value >= MagicNumber) {
               value -= MagicNumber;
               if (value >= cachedPokenames.Count) text.Append($"{GroupStart}{value}{GroupEnd}");
               else text.Append($"{GroupStart}{cachedPokenames[value].Trim('"')}{GroupEnd}");
            } else {
               if (value >= cachedMovenames.Count) text.Append($"{value}");
               else text.Append($"{cachedMovenames[value]}");
            }
            start += 2;
            length -= 2;
            if (length > 0 && start < Start + Length) text.Append(" ");
         }
      }
Пример #16
0
      public override IDataFormat CreateDataFormat(IDataModel data, int dataIndex) {
         Debug.Assert(data == model);

         var cache = ModelCacheScope.GetCache(data);
         var cachedPokenames = cache.GetOptions(PokemonNameTable);
         var cachedMovenames = cache.GetOptions(MoveNamesTable);

         var position = dataIndex - Start;
         var groupStart = position % 2 == 1 ? position - 1 : position;
         position -= groupStart;
         var value = data.ReadMultiByteValue(Start + groupStart, 2);
         if (value >= MagicNumber) {
            value -= MagicNumber;
            string content = cachedPokenames.Count > value ? cachedPokenames[value] : value.ToString();
            if (value == EndStream - MagicNumber) content = string.Empty;
            if (content.StartsWith("\"")) content = content.Substring(1);
            if (content.EndsWith("\"")) content = content.Substring(0, content.Length - 1);
            return new EggSection(groupStart + Start, position, $"{GroupStart}{content}{GroupEnd}");
         } else {
            string content = cachedMovenames.Count > value ? cachedMovenames[value] : value.ToString();
            return new EggItem(groupStart + Start, position, content);
         }
      }
Пример #17
0
            public TeamData(ModelCacheScope cache, string[] lines)
            {
                var currentPokemonMoveCount = 0;
                var moveNames    = cache.GetOptions(HardcodeTablesModel.MoveNamesTable);
                var itemNames    = cache.GetOptions(HardcodeTablesModel.ItemsTableName);
                var pokemonNames = cache.GetOptions(HardcodeTablesModel.PokemonNameTable);

                foreach (var line in lines)
                {
                    if (line.Trim() is "")
                    {
                        continue;
                    }
                    if (line.StartsWith("-"))
                    {
                        if (pokemons.Count == 0)
                        {
                            continue;
                        }
                        if (currentPokemonMoveCount > 3)
                        {
                            continue;
                        }
                        MovesIncluded = true;
                        var move      = line.Substring(1).Trim();
                        var moveIndex = moveNames.IndexOfPartial(move);
                        if (moveIndex < 0)
                        {
                            moveIndex = 0;
                        }
                        moves[(pokemons.Count - 1) * 4 + currentPokemonMoveCount] = moveIndex;
                        currentPokemonMoveCount++;
                    }
                    else
                    {
                        if (pokemons.Count == 6)
                        {
                            continue;
                        }

                        var levelTokenized = line.Split(new[] { ' ' }, 2);
                        if (levelTokenized.Length != 2)
                        {
                            continue;
                        }
                        if (!int.TryParse(levelTokenized[0], out int level))
                        {
                            continue;
                        }
                        levels.Add(level);

                        var itemTokenized = levelTokenized[1].Split(new[] { '@' }, 2);
                        AddItem(itemNames, items, itemTokenized);

                        var ivTokenized = itemTokenized[0].Split(new[] { '(' }, 2);
                        AddIV(ivs, ivTokenized);

                        var pokemon      = ivTokenized[0].Trim();
                        var pokemonIndex = pokemonNames.IndexOfPartial(pokemon);
                        if (pokemonIndex < 0)
                        {
                            pokemonIndex = 0;
                        }
                        pokemons.Add(pokemonIndex);
                        moves.AddRange(new[] { 0, 0, 0, 0 });
                        currentPokemonMoveCount = 0;
                    }
                }
            }
Пример #18
0
        public IEnumerable <string> GetAutoCompleteOptions(string header)
        {
            var moveNames = ModelCacheScope.GetCache(model).GetOptions(EggMoveRun.MoveNamesTable);

            return(moveNames.Select(name => $"{header} {name}" + (name.EndsWith("\"") ? "" : " "))); // autocomplete needs to complete after selection, so add a space if there's no quotes
        }
Пример #19
0
        private static (ElementContentType format, int formatLength, int segmentLength) ExtractSingleFormat(string segments, IDataModel model)
        {
            if (segments.Length >= 2 && segments.Substring(0, 2) == PCSRun.SharedFormatString)
            {
                var format       = ElementContentType.PCS;
                var formatLength = 2;
                while (formatLength < segments.Length && char.IsDigit(segments[formatLength]))
                {
                    formatLength++;
                }
                if (int.TryParse(segments.Substring(2, formatLength - 2), out var segmentLength))
                {
                    return(format, formatLength, segmentLength);
                }
            }
            else if (segments.StartsWith(DoubleByteIntegerFormat + string.Empty + DoubleByteIntegerFormat))
            {
                return(ElementContentType.Integer, 2, 4);
            }
            else if (segments.StartsWith(DoubleByteIntegerFormat + string.Empty + SingleByteIntegerFormat) || segments.StartsWith(".:"))
            {
                return(ElementContentType.Integer, 2, 3);
            }
            else if (segments.StartsWith(DoubleByteIntegerFormat.ToString()))
            {
                return(ElementContentType.Integer, 1, 2);
            }
            else if (segments.StartsWith(SingleByteIntegerFormat.ToString()))
            {
                return(ElementContentType.Integer, 1, 1);
            }
            else if (segments.Length > 0 && segments[0] == PointerRun.PointerStart)
            {
                var openCount = 1;
                var endIndex  = 1;
                while (openCount > 0 && endIndex < segments.Length)
                {
                    if (segments[endIndex] == PointerRun.PointerStart)
                    {
                        openCount += 1;
                    }
                    else if (segments[endIndex] == PointerRun.PointerEnd)
                    {
                        openCount -= 1;
                    }
                    endIndex += 1;
                }
                if (openCount > 0)
                {
                    return(ElementContentType.Unknown, 0, 0);
                }
                return(ElementContentType.Pointer, endIndex, 4);
            }
            else if (segments.StartsWith(BitArray.SharedFormatString))
            {
                var endIndex = BitArray.SharedFormatString.Length;
                while (segments.Length > endIndex && char.IsLetterOrDigit(segments[endIndex]))
                {
                    endIndex++;
                }
                var format  = segments.Substring(0, endIndex);
                var name    = format.Substring(BitArray.SharedFormatString.Length);
                var options = ModelCacheScope.GetCache(model).GetBitOptions(name);
                var count   = options?.Count ?? 8;
                return(ElementContentType.BitArray, format.Length, (int)Math.Ceiling(count / 8.0));
            }

            return(ElementContentType.Unknown, 0, 0);
        }