From 989c2dc07177147fa74637841de278b8aeba13a3 Mon Sep 17 00:00:00 2001 From: Evin Jaff Date: Mon, 8 Jul 2024 22:28:18 -0500 Subject: [PATCH] Gen 5 and conversion interface added --- .../pkhex-egglocke-tests/SaveWriterTest.cs | 23 ++ .../testSources/LegendaryTrio.json | 9 +- .../testSources/Mareep.json | 3 +- .../testSources/MareepShiny.json | 3 +- .../pkhex-egglocke/EggCreator.cs | 247 +++++++++++++----- .../pkhex-egglocke/HTTPRoutes.cs | 7 + .../pkhex-egglocke/SaveWriter.cs | 130 +++++---- .../pkhex-egglocke/pkhexEgglocke.csproj | 3 + .../pkhex-egglocke/support/Blank_Black2.sav | Bin 0 -> 524288 bytes server/pokepoll/views.py | 2 + 10 files changed, 284 insertions(+), 143 deletions(-) create mode 100644 pkhex/pkhex-egglocke/pkhex-egglocke/support/Blank_Black2.sav diff --git a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/SaveWriterTest.cs b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/SaveWriterTest.cs index 59fda37..cd06a4e 100644 --- a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/SaveWriterTest.cs +++ b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/SaveWriterTest.cs @@ -113,8 +113,31 @@ public void TestShinyCorrect() Assert.IsTrue(isShiny); + } + [TestMethod] + public void TestNotShinyCorrect() + { + SaveWriter sw = new SaveWriter(testConstants.JOHTO_PLUS_SOUL_SILVER_SAVE); + + EggCreator ec = EggCreator.decodeJSON(testConstants.BLANK_GEN4_MAREEP_VALID, true); + + sw.addEgg(ec, 1); + + // get egg at box index 1 + IList boxData = sw.getBox(); + + bool isShiny = boxData[1].IsShiny; + + Assert.IsFalse(isShiny); + + + } + + + + } } \ No newline at end of file diff --git a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/LegendaryTrio.json b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/LegendaryTrio.json index 0ca5c31..1733ea3 100644 --- a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/LegendaryTrio.json +++ b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/LegendaryTrio.json @@ -13,7 +13,8 @@ "EV": [ 252, 252, 0, 0, 0, 0 ], "moves": [ 425, 262 ], "movespp": [ 30, 40 ], - "isShiny": true + "isShiny": true, + "generation": 4 }, { "dexNumber": 484, @@ -29,7 +30,8 @@ "EV": [ 252, 252, 0, 0, 0, 0 ], "moves": [ 425, 262 ], "movespp": [ 30, 40 ], - "isShiny": true + "isShiny": true, + "generation": 4 }, { "dexNumber": 487, @@ -45,6 +47,7 @@ "EV": [ 252, 252, 0, 0, 0, 0 ], "moves": [ 425, 262 ], "movespp": [ 30, 40 ], - "isShiny": true + "isShiny": true, + "generation": 4 } ] \ No newline at end of file diff --git a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/Mareep.json b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/Mareep.json index 9594ba2..87d8a98 100644 --- a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/Mareep.json +++ b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/Mareep.json @@ -12,5 +12,6 @@ "moves": [ 344, 1, 124, 26 ], "movespp": [ 0, 0, 0, 0 ], "heldItem": 135, - "isShiny": false + "isShiny": false, + "generation": 4 } \ No newline at end of file diff --git a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/MareepShiny.json b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/MareepShiny.json index 70fa354..264d1fc 100644 --- a/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/MareepShiny.json +++ b/pkhex/pkhex-egglocke-tests/pkhex-egglocke-tests/testSources/MareepShiny.json @@ -12,5 +12,6 @@ "moves": [ 344, 1, 124, 26 ], "movespp": [ 0, 0, 0, 0 ], "heldItem": 135, - "isShiny": true + "isShiny": true, + "generation": 4 } \ No newline at end of file diff --git a/pkhex/pkhex-egglocke/pkhex-egglocke/EggCreator.cs b/pkhex/pkhex-egglocke/pkhex-egglocke/EggCreator.cs index 6dae9be..97fbede 100644 --- a/pkhex/pkhex-egglocke/pkhex-egglocke/EggCreator.cs +++ b/pkhex/pkhex-egglocke/pkhex-egglocke/EggCreator.cs @@ -10,6 +10,7 @@ using PKHeX.Core; using Newtonsoft.Json; using System.Text.RegularExpressions; +using System.Security.Cryptography; namespace pkhexEgglocke { @@ -20,71 +21,175 @@ namespace pkhexEgglocke // Parameters // These parameters mostly allow you to set rules around what user submissions you'd like to include (ex. allow user-supplied IVs) - + internal class EggCreator { // TODO: refactor to get/set - protected bool allowUserIVs => true; - protected bool allowUserShiny => true; - protected bool allowUser => true; + protected bool allowUserIVs { get; set; } = true; + protected bool allowUserShiny { get; set; } = true; + protected bool allowUser { get; set; } = true; + + public int generation { get; set; } = 4; + // Egg Parameters that are always true - public bool IsEgg = true; - public ushort EggLocationDP = Locations.Daycare4; - public byte MetLevel = 0; + public bool IsEgg { get; set; } = true; + public ushort EggLocationDP { get; set; } = Locations.Daycare4; + public byte MetLevel { get; set; } = 0; //Other constant fields - public int language = (int)LanguageID.English; + public int language { get; set; } = (int)LanguageID.English; // Mutable fields - public byte ball = (int)Ball.Dive; + public byte ball { get; set; } = (int)Ball.Dive; - public ushort dexNumber = 1; - public int Language = 1; - public int Ability = 2; - public Nature Nature = Nature.Adamant; - public int heldItem = 0; + public ushort dexNumber { get; set; } = 1; + public int Language { get; set; } = 1; + public int Ability { get; set; } = 2; + public Nature Nature { get; set; } = Nature.Adamant; + public int heldItem { get; set; } = 0; //Misc creator stuff - public string OT = "Default"; - public byte OTGender = (int)Gender.Female; - public string nickname = "Hello"; + public string OT { get; set; } = "Default"; + public byte OTGender { get; set; } = (int)Gender.Female; + public string nickname { get; set; } = "Hello"; - public int[] IV = [31, 31, 31, 31, 31, 31]; - public int[] EV = [0, 0, 0, 0, 0, 0]; + public int[] IV { get; set; } = new int[] { 31, 31, 31, 31, 31, 31 }; + public int[] EV { get; set; } = new int[] { 0, 0, 0, 0, 0, 0 }; - public ushort [] moves = {425, 262 }; - public ushort[] movespp = { 30, 40 }; + public ushort[] moves { get; set; } = new ushort[] { 425, 262 }; + public ushort[] movespp { get; set; } = new ushort[] { 30, 40 }; - public bool isShiny = true; + public bool isShiny { get; set; } = true; - public EggCreator(byte ball, ushort dexNumber, int language, int ability, Nature Nature, string OT, byte OTGender, string nickname, int[] IV, int[] EV, ushort[] moves, ushort[] movespp, int HeldItem, bool isShiny) { - - this.ball = ball; - this.dexNumber = dexNumber; - this.language = language; - this.Ability = ability; - this.Nature = Nature; - this.OT = OT; - this.OTGender = OTGender; - this.nickname = nickname; - this.IV = IV; - this.EV = EV; - this.moves = moves; - this.movespp = movespp; - this.heldItem = HeldItem; - this.isShiny = isShiny; + public EggCreator() + { } + internal void MakeShiny(PK4 pokemon) + { + // Get IDs + ushort trainer_id = pokemon.TID16; + ushort secret_id = pokemon.SID16; + uint pid = ShinyUtil.GetShinyPID(trainer_id, secret_id, pokemon.PID, 0); + + pokemon.PID = pid; + + + } + + public PK4 exportPK4(uint trainerID, uint secretID) { + + // create default + PK4 mew = new PK4 + { + TrainerTID7 = trainerID, + TrainerSID7 = secretID, + IsEgg = true, + MetLevel = 1, + Ball = 4, + Species = 1, + Nickname = "Egg", + Language = 1, + OriginalTrainerName = "PKHeX", + OriginalTrainerGender = 0, + HeldItem = 0, + Ability = 0, + Nature = 0, + Move1 = 0, + Move1_PP = 0, + Move2 = 0, + Move2_PP = 0, + Move3 = 0, + Move3_PP = 0, + Move4 = 0, + Move4_PP = 0, + IVs = new int[] { 31, 31, 31, 31, 31, 31 } + }; + + // Set the trainer ID according to the save file + mew.TrainerTID7 = trainerID; + mew.TrainerSID7 = secretID; + + // Standard Egg attributes + mew.IsEgg = this.IsEgg; + mew.EggLocationDP = this.EggLocationDP; + mew.MetLevel = this.MetLevel; + mew.Ball = this.ball; + + + // Pokemon Info + mew.Species = this.dexNumber; + mew.Nickname = this.nickname; + mew.Language = this.language; + mew.OriginalTrainerName = this.OT; + mew.OriginalTrainerGender = this.OTGender; + + mew.HeldItem = this.heldItem; + mew.Version = GameVersion.HG; + + + + mew.Ability = this.Ability; + + Console.WriteLine(this.moves); + // Moveset + + // Based on number of moves, set the moves + for (int i = 0; i < this.moves.Length; i++) + { + mew.SetMove(i, this.moves[i]); + } + + mew.IVs = this.IV; + + + + // Logic to confirm that the PID matches the nature and shininess + for (; !((Nature)(mew.PID % 25) == this.Nature) && (this.isShiny == this.isShiny);) + { + // Attempt to set the nature + mew.SetPIDNature(this.Nature); + + if (this.isShiny) + { + MakeShiny(mew); + } + + } - public static EggCreator decodeJSON(string filepath, bool is_filepath) { + Console.WriteLine("Nature after setting"); + Console.WriteLine(mew.Nature); + +#if DEBUG + // Check legality of the pokemon + LegalityAnalysis legalitychecker = new LegalityAnalysis(mew); + + if (legalitychecker.Valid) + { + Console.WriteLine("Legal Egg created!"); + } + else + { + Console.WriteLine("Illegal Egg Created!"); + } +#endif + + return mew; + + } + + + + public static EggCreator decodeJSON(string filepath, bool is_filepath) + { /// /// decodeJSON: Decodes a JSON object into a PokemonCreator object /// @@ -98,23 +203,26 @@ public static EggCreator decodeJSON(string filepath, bool is_filepath) { { json = File.ReadAllText(filepath); } - else { + else + { json = filepath; } - - + + dynamic newObject = JsonConvert.DeserializeObject(json); Console.WriteLine("Successfully deserialized JSON!"); Console.WriteLine("Nature: "); - Console.WriteLine((byte) newObject.nature.Value); + Console.WriteLine((byte)newObject.nature.Value); - Nature nature = natureEnumGrab((byte) newObject.nature.Value); + Nature nature = natureEnumGrab((byte)newObject.nature.Value); Console.WriteLine(nature); + int generation = (int)newObject.generation; + int[] IV = newObject.IV.ToObject(); int[] EV = newObject.EV.ToObject(); @@ -123,37 +231,38 @@ public static EggCreator decodeJSON(string filepath, bool is_filepath) { bool isShiny = newObject.isShiny; - byte ball = (byte) newObject.ball; - ushort dexNumber = (ushort) newObject.dexNumber; - int language = (int) newObject.language; - int ability = (int) newObject.ability; - int heldItem = (int) newObject.heldItem; + byte ball = (byte)newObject.ball; + ushort dexNumber = (ushort)newObject.dexNumber; + int language = (int)newObject.language; + int ability = (int)newObject.ability; + int heldItem = (int)newObject.heldItem; string OT = newObject.OT; - byte OTGender = (byte) newObject.OTGender; + byte OTGender = (byte)newObject.OTGender; string nickname = newObject.nickname; // Print EggCreator args - return new EggCreator( - ball, - dexNumber, - language, - ability, - nature, - OT, - OTGender, - nickname, - IV, - EV, - convertIntArrayViaCast(moves), - convertIntArrayViaCast(movespp), - heldItem, - isShiny - - ); - + return new EggCreator() + { + ball = ball, + dexNumber = dexNumber, + language = language, + Ability = ability, + Nature = nature, + OT = OT, + OTGender = OTGender, + nickname = nickname, + IV = IV, + EV = EV, + moves = convertIntArrayViaCast(moves), + movespp = convertIntArrayViaCast(movespp), + heldItem = heldItem, + isShiny = isShiny, + generation = generation + }; + } public static Nature natureEnumGrab(byte value) @@ -173,7 +282,7 @@ public static ushort[] convertIntArrayViaCast(int[] array) ushort[] result = new ushort[array.Length]; for (int i = 0; i < result.Length; i++) { - result[i] = (ushort) array[i]; + result[i] = (ushort)array[i]; } return result; diff --git a/pkhex/pkhex-egglocke/pkhex-egglocke/HTTPRoutes.cs b/pkhex/pkhex-egglocke/pkhex-egglocke/HTTPRoutes.cs index ff4c27e..57eca59 100644 --- a/pkhex/pkhex-egglocke/pkhex-egglocke/HTTPRoutes.cs +++ b/pkhex/pkhex-egglocke/pkhex-egglocke/HTTPRoutes.cs @@ -50,6 +50,13 @@ public string getGameSavPath(uint gamecode) { return @"support/Blank_Pearl.sav"; case 12: return @"support/Blank_Platinum.sav"; + case 20: + return @"support/Blank_White.sav"; + case 21: + return @"support/Blank_Black.sav"; + case 23: + return @"support/Blank_Black2.sav"; + default: throw new Exception("Invalid game code"); diff --git a/pkhex/pkhex-egglocke/pkhex-egglocke/SaveWriter.cs b/pkhex/pkhex-egglocke/pkhex-egglocke/SaveWriter.cs index 0268ec6..e24fb58 100644 --- a/pkhex/pkhex-egglocke/pkhex-egglocke/SaveWriter.cs +++ b/pkhex/pkhex-egglocke/pkhex-egglocke/SaveWriter.cs @@ -69,17 +69,6 @@ public void massAddEggs(string JSONPath) { } - } - - internal void MakeShiny(PK4 pokemon) { - // Get IDs - ushort trainer_id = pokemon.TID16; - ushort secret_id = pokemon.SID16; - uint pid = ShinyUtil.GetShinyPID(trainer_id, secret_id, pokemon.PID, 0); - - pokemon.PID = pid; - - } internal static bool IsShinyPID(uint pid, uint trainer_id, uint secret_id) { @@ -130,87 +119,90 @@ private static PK4 createDefaultEgg(uint tid, uint sid) { } - public void addEgg( EggCreator pokemon, int boxIndex) { - - - - // hacky start - hardcoded to gen 4 pokemon - PK4 mew = createDefaultEgg(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + private PK5 gen5Conversions(EggCreator pokemon, int originGeneration) { - // Set the trainer ID according to the save file - mew.TrainerTID7 = this.currentSave.TrainerTID7; - mew.TrainerSID7 = this.currentSave.TrainerSID7; + switch (originGeneration) + { + case 4: + PK4 pk4 = pokemon.exportPK4(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + return pk4.ConvertToPK5(); - // Standard Egg attributes - mew.IsEgg = pokemon.IsEgg; - mew.EggLocationDP = pokemon.EggLocationDP; - mew.MetLevel = pokemon.MetLevel; - mew.Ball = pokemon.ball; + default: + throw new Exception("Unsupported origin generation (" + originGeneration + ")"); + } - - // Pokemon Info - mew.Species = pokemon.dexNumber; - mew.Nickname = pokemon.nickname; - mew.Language = pokemon.language; - mew.OriginalTrainerName = pokemon.OT; - mew.OriginalTrainerGender = pokemon.OTGender; - - mew.HeldItem = pokemon.heldItem; - mew.Version = GameVersion.HG; - + } + private PK6 gen6Conversions(EggCreator pokemon, int originGeneration) { - mew.Ability = pokemon.Ability; + switch (originGeneration) + { - Console.WriteLine(pokemon.moves); - // Moveset + //case 3: + // PK3 pk3 = pokemon.exportPK3(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + // PK4 pk4 = pk3.ConvertToPK4(); + // return pk4.ConvertToPK5().ConvertToPK6(); + + case 4: + PK4 gen4_pk4 = pokemon.exportPK4(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + PK5 gen4_pk5 = gen4_pk4.ConvertToPK5(); + return gen4_pk5.ConvertToPK6(); + //case 5: + // PK5 gen5_pk5 = pokemon.exportPK5(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + // return gen5_pk5.ConvertToPK6(); + default: + throw new Exception("Unsupported origin generation (" + originGeneration + ")"); - // Based on number of moves, set the moves - for (int i = 0; i < pokemon.moves.Length; i++) { - mew.SetMove(i, pokemon.moves[i]); } - mew.IVs = pokemon.IV; - - var box = this.currentSave.BoxData; + } - // Logic to confirm that the PID matches the nature and shininess - for (; !( (Nature)(mew.PID % 25) == pokemon.Nature) && (pokemon.isShiny == pokemon.isShiny); ) - { - // Attempt to set the nature - mew.SetPIDNature(pokemon.Nature); - MakeShiny(mew); - } + public void addEgg( EggCreator pokemon, int boxIndex) { + var box = this.currentSave.BoxData; + // check game version + byte saveFileGeneration = this.currentSave.Generation; - Console.WriteLine("Nature after setting"); - Console.WriteLine(mew.Nature); -#if DEBUG - // Check legality of the pokemon - LegalityAnalysis legalitychecker = new LegalityAnalysis(mew); - - if (legalitychecker.Valid) - { - Console.WriteLine("Legal Egg created!"); - } - else + if (pokemon.generation != saveFileGeneration) { - Console.WriteLine("Illegal Egg Created!"); + // run conversion scripts here for non-native pokemon + Console.WriteLine("Converting from generation " + pokemon.generation + " to generation " + saveFileGeneration); + PKM convertedPokemon; + switch(saveFileGeneration) { + case 5: + convertedPokemon = gen5Conversions(pokemon, pokemon.generation); + break; + + case 6: + convertedPokemon = gen6Conversions(pokemon, pokemon.generation); + break; + default: + throw new Exception("Unsupported save file generation (Generation " + saveFileGeneration + ")"); + } + + box[boxIndex] = convertedPokemon; } -#endif + else { + // Native pokemon generation - box[boxIndex] = mew; + switch (saveFileGeneration) { + case 4: + box[boxIndex] = pokemon.exportPK4(this.currentSave.TrainerTID7, this.currentSave.TrainerSID7); + break; + default: + throw new Exception("Unsupported save file generation (Generation " + saveFileGeneration + ")"); - // update box - this.currentSave.BoxData = box; + } + + } - // this.currentSave.AddBoxData( , 1, 1 ); + this.currentSave.BoxData = box; diff --git a/pkhex/pkhex-egglocke/pkhex-egglocke/pkhexEgglocke.csproj b/pkhex/pkhex-egglocke/pkhex-egglocke/pkhexEgglocke.csproj index 109a0bd..0640dac 100644 --- a/pkhex/pkhex-egglocke/pkhex-egglocke/pkhexEgglocke.csproj +++ b/pkhex/pkhex-egglocke/pkhex-egglocke/pkhexEgglocke.csproj @@ -20,6 +20,9 @@ + + Always + Always diff --git a/pkhex/pkhex-egglocke/pkhex-egglocke/support/Blank_Black2.sav b/pkhex/pkhex-egglocke/pkhex-egglocke/support/Blank_Black2.sav new file mode 100644 index 0000000000000000000000000000000000000000..38496c6c98d730b2a6c8c61cd710432bc5de1a8c GIT binary patch literal 524288 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 zKmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck) z1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`; zKmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck) z1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`; zKmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck) z1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`; zKmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck) z1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`; zKmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1VG^bHvtks5SkI(I$ARqsTZZqNcwZ(|8E|sJqUmR2!H?x UfB*=900@8p2!H?x{Eh_v4@WUn3jhEB literal 0 HcmV?d00001 diff --git a/server/pokepoll/views.py b/server/pokepoll/views.py index fcaa10a..e545276 100644 --- a/server/pokepoll/views.py +++ b/server/pokepoll/views.py @@ -27,6 +27,7 @@ "Pokemon Diamond": 10, "Pokemon Pearl": 11, "Pokemon Platinum": 12, + "Pokemon Black 2": 23, } @require_GET @@ -200,6 +201,7 @@ def saveGenView(request): "movespp": [0] * len(egg.pokemon_moves), "heldItem": egg.pokemon_held_item, "isShiny": egg.pokemon_is_shiny, + "generation": 4, })