diff --git a/PoGo.NecroBot.CLI/ConsoleEventListener.cs b/PoGo.NecroBot.CLI/ConsoleEventListener.cs index f6da48b38..8e791b29b 100644 --- a/PoGo.NecroBot.CLI/ConsoleEventListener.cs +++ b/PoGo.NecroBot.CLI/ConsoleEventListener.cs @@ -1,6 +1,7 @@ #region using directives using System; +using PoGo.NecroBot.Logic.Common; using PoGo.NecroBot.Logic.Event; using PoGo.NecroBot.Logic.Logging; using PoGo.NecroBot.Logic.State; @@ -15,7 +16,7 @@ public class ConsoleEventListener { public void HandleEvent(ProfileEvent evt, Context ctx) { - Logger.Write($"Playing as {evt.Profile.PlayerData.Username ?? ""}"); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventFortUsed, evt.Profile.PlayerData.Username ?? "")); } public void HandleEvent(ErrorEvent evt, Context ctx) @@ -35,37 +36,35 @@ public void HandleEvent(WarnEvent evt, Context ctx) public void HandleEvent(UseLuckyEggEvent evt, Context ctx) { - Logger.Write($"Used Lucky Egg, remaining: {evt.Count}", LogLevel.Egg); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventUsedLuckyEgg, evt.Count), LogLevel.Egg); } public void HandleEvent(PokemonEvolveEvent evt, Context ctx) { Logger.Write(evt.Result == EvolvePokemonResponse.Types.Result.Success - ? $"{evt.Id} successfully for {evt.Exp}xp" - : $"Failed {evt.Id}. EvolvePokemonOutProto.Result was {evt.Result}, stopping evolving {evt.Id}", + ? ctx.Translations.GetTranslation(TranslationString.EventPokemonEvolvedSuccess, evt.Id, evt.Exp) + : ctx.Translations.GetTranslation(TranslationString.EventPokemonEvolvedFailed, evt.Id, evt.Result, evt.Id), LogLevel.Evolve); } public void HandleEvent(TransferPokemonEvent evt, Context ctx) { - Logger.Write( - $"{evt.Id}\t- CP: {evt.Cp} IV: {evt.Perfection.ToString("0.00")}% [Best CP: {evt.BestCp} IV: {evt.BestPerfection.ToString("0.00")}%] (Candies: {evt.FamilyCandies}) ", - LogLevel.Transfer); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventPokemonTransferred, evt.Id, evt.Cp, evt.Perfection.ToString("0.00"), evt.BestCp, evt.BestPerfection.ToString("0.00"), evt.FamilyCandies), LogLevel.Transfer); } public void HandleEvent(ItemRecycledEvent evt, Context ctx) { - Logger.Write($"{evt.Count}x {evt.Id}", LogLevel.Recycling); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventItemRecycled, evt.Count, evt.Id), LogLevel.Recycling); } public void HandleEvent(FortUsedEvent evt, Context ctx) { - Logger.Write($"XP: {evt.Exp}, Gems: {evt.Gems}, Items: {evt.Items}", LogLevel.Pokestop); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventFortUsed, evt.Exp, evt.Gems, evt.Items), LogLevel.Pokestop); } public void HandleEvent(FortTargetEvent evt, Context ctx) { - Logger.Write($"{evt.Name} in ({Math.Round(evt.Distance)}m)", LogLevel.Info, ConsoleColor.DarkRed); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventFortTargeted, evt.Name, Math.Round(evt.Distance)), LogLevel.Info, ConsoleColor.DarkRed); } public void HandleEvent(PokemonCaptureEvent evt, Context ctx) @@ -75,13 +74,13 @@ public void HandleEvent(PokemonCaptureEvent evt, Context ctx) switch (a) { case ItemId.ItemPokeBall: - return "Poke"; + return ctx.Translations.GetTranslation(TranslationString.Pokeball); case ItemId.ItemGreatBall: - return "Great"; + return ctx.Translations.GetTranslation(TranslationString.GreatPokeball); case ItemId.ItemUltraBall: - return "Ultra"; + return ctx.Translations.GetTranslation(TranslationString.UltraPokeball); case ItemId.ItemMasterBall: - return "Master"; + return ctx.Translations.GetTranslation(TranslationString.MasterPokeball); default: return "Unknown"; } @@ -90,35 +89,35 @@ public void HandleEvent(PokemonCaptureEvent evt, Context ctx) var catchType = evt.CatchType; var catchStatus = evt.Attempt > 1 - ? $"{evt.Status} Attempt #{evt.Attempt}" - : $"{evt.Status}"; + ? ctx.Translations.GetTranslation(TranslationString.CatchStatusAttempt, evt.Status, evt.Attempt) + : ctx.Translations.GetTranslation(TranslationString.CatchStatus, evt.Status); var familyCandies = evt.FamilyCandies > 0 - ? $"Candies: {evt.FamilyCandies}" + ? ctx.Translations.GetTranslation(TranslationString.Candies) : ""; - Logger.Write( - $"({catchStatus}) | ({catchType}) {evt.Id} Lvl: {evt.Level} CP: ({evt.Cp}/{evt.MaxCp}) IV: {evt.Perfection.ToString("0.00")}% | Chance: {evt.Probability}% | {Math.Round(evt.Distance)}m dist | with a {returnRealBallName(evt.Pokeball)}Ball ({evt.BallAmount} left). | {familyCandies}", - LogLevel.Caught); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventPokemonCapture, catchStatus, catchType, evt.Id, + evt.Level, evt.Cp, evt.MaxCp, evt.Perfection.ToString("0.00"), evt.Probability, evt.Distance, + returnRealBallName(evt.Pokeball), evt.BallAmount, familyCandies), LogLevel.Caught); } public void HandleEvent(NoPokeballEvent evt, Context ctx) { - Logger.Write($"No Pokeballs - We missed a {evt.Id} with CP {evt.Cp}", LogLevel.Caught); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventNoPokeballs, evt.Id, evt.Cp), LogLevel.Caught); } public void HandleEvent(UseBerryEvent evt, Context ctx) { - Logger.Write($"Used, remaining: {evt.Count}", LogLevel.Berry); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.EventNoPokeballs, evt.Count), LogLevel.Berry); } public void HandleEvent(DisplayHighestsPokemonEvent evt, Context ctx) { Logger.Write($"====== DisplayHighests{evt.SortedBy} ======", LogLevel.Info, ConsoleColor.Yellow); foreach (var pokemon in evt.PokemonList) - Logger.Write( - $"# CP {pokemon.Item1.Cp.ToString().PadLeft(4, ' ')}/{pokemon.Item2.ToString().PadLeft(4, ' ')} | ({pokemon.Item3.ToString("0.00")}% perfect)\t| Lvl {pokemon.Item4.ToString("00")}\t NAME: '{pokemon.Item1.PokemonId}'", - LogLevel.Info, ConsoleColor.Yellow); + Logger.Write( + $"# CP {pokemon.Item1.Cp.ToString().PadLeft(4, ' ')}/{pokemon.Item2.ToString().PadLeft(4, ' ')} | ({pokemon.Item3.ToString("0.00")}% perfect)\t| Lvl {pokemon.Item4.ToString("00")}\t NAME: '{pokemon.Item1.PokemonId}'", + LogLevel.Info, ConsoleColor.Yellow); } public void Listen(IEvent evt, Context ctx) diff --git a/PoGo.NecroBot.CLI/Settings.cs b/PoGo.NecroBot.CLI/Settings.cs index f12bf78a2..badfc8bd3 100644 --- a/PoGo.NecroBot.CLI/Settings.cs +++ b/PoGo.NecroBot.CLI/Settings.cs @@ -35,7 +35,7 @@ public AuthSettings() { Console.Clear(); return; - } + } do { Console.WriteLine("Username:"); @@ -52,7 +52,7 @@ public AuthSettings() public string GoogleRefreshToken; public string PtcUsername; public string PtcPassword; - + [JsonIgnore] private string FilePath; @@ -92,7 +92,7 @@ public void Save(string path) public void Save() { - if(!string.IsNullOrEmpty(FilePath)) + if (!string.IsNullOrEmpty(FilePath)) { Save(FilePath); } @@ -130,7 +130,7 @@ public static GlobalSettings Load(string path) settings = new GlobalSettings(); } - if(settings.WebSocketPort == 0) + if (settings.WebSocketPort == 0) { settings.WebSocketPort = 14251; } @@ -155,6 +155,7 @@ public void Save(string fullPath) } public bool AutoUpdate = false; + public string TranslationLanguageCode = "en"; public double DefaultAltitude = 10; public double DefaultLatitude = 52.379189; public double DefaultLongitude = 4.899431; @@ -177,7 +178,7 @@ public void Save(string fullPath) public int AmountOfPokemonToDisplayOnStart = 10; public bool RenameAboveIv = false; public int WebSocketPort = 14251; - + [JsonIgnore] internal AuthSettings Auth = new AuthSettings(); @@ -298,6 +299,7 @@ public LogicSettings(GlobalSettings settings) public float EvolveAboveIvValue => _settings.EvolveAboveIvValue; public bool RenameAboveIv => _settings.RenameAboveIv; public int AmountOfPokemonToDisplayOnStart => _settings.AmountOfPokemonToDisplayOnStart; + public string TranslationLanguageCode => _settings.TranslationLanguageCode; public ICollection> ItemRecycleFilter => _settings.ItemRecycleFilter; public ICollection PokemonsToEvolve => _settings.PokemonsToEvolve; public ICollection PokemonsNotToTransfer => _settings.PokemonsNotToTransfer; diff --git a/PoGo.NecroBot.Logic/Common/Translations.cs b/PoGo.NecroBot.Logic/Common/Translations.cs new file mode 100644 index 000000000..8fd2bea0c --- /dev/null +++ b/PoGo.NecroBot.Logic/Common/Translations.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace PoGo.NecroBot.Logic.Common +{ + public class Translations + { + public static Translations Default => new Translations(); + public static string ProfilePath; + public static string ConfigPath; + + public static Translations Load(string translationsLanguageCode) + { + ProfilePath = Directory.GetCurrentDirectory(); + ConfigPath = ProfilePath + "\\config\\translations"; + + var fullPath = ConfigPath + "\\translation." + translationsLanguageCode + ".json"; + + Translations translations = null; + if (File.Exists(fullPath)) + { + var input = File.ReadAllText(fullPath); + + JsonSerializerSettings jsonSettings = new JsonSerializerSettings(); + jsonSettings.Converters.Add(new StringEnumConverter { CamelCaseText = true }); + jsonSettings.ObjectCreationHandling = ObjectCreationHandling.Replace; + jsonSettings.DefaultValueHandling = DefaultValueHandling.Populate; + + translations = JsonConvert.DeserializeObject(input, jsonSettings); + translations.Save(fullPath); + } + else + { + translations = new Translations(); + translations.Save(ConfigPath + "\\translation.en.json"); + } + return translations; + } + + public void Save(string fullPath) + { + var output = JsonConvert.SerializeObject(this, Formatting.Indented, new StringEnumConverter { CamelCaseText = true }); + + string folder = Path.GetDirectoryName(fullPath); + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + + File.WriteAllText(fullPath, output); + } + + public string GetTranslation(TranslationString translationString, params object[] data) + { + string translation = TranslationStrings.FirstOrDefault(t => t.Key.Equals(translationString)).Value; + if (translation != default(string)) + return string.Format(translation, data); + return $"Translation for {translationString} is missing"; + } + + public string GetTranslation(TranslationString translationString) + { + string translation = TranslationStrings.FirstOrDefault(t => t.Key.Equals(translationString)).Value; + if (translation != default(string)) + return translation; + return $"Translation for {translationString} is missing"; + } + + //Default Translations (ENGLISH) + public List> TranslationStrings = new List> + { + new KeyValuePair(Common.TranslationString.Pokeball, "PokeBall"), + new KeyValuePair(Common.TranslationString.GreatPokeball, "GreatBall"), + new KeyValuePair(Common.TranslationString.UltraPokeball, "UltraBall"), + new KeyValuePair(Common.TranslationString.MasterPokeball, "MasterBall"), + new KeyValuePair(Common.TranslationString.WrongAuthType, "Unknown AuthType in config.json"), + new KeyValuePair(Common.TranslationString.FarmPokestopsOutsideRadius, "You're outside of your defined radius! Walking to start ({0}m away) in 5 seconds. Is your Coords.ini file correct?"), + new KeyValuePair(Common.TranslationString.FarmPokestopsNoUsableFound, "No usable PokeStops found in your area. Is your maximum distance too small?"), + new KeyValuePair(Common.TranslationString.EventFortUsed, "XP: {0}, Gems: {1}, Items: {2}"), + new KeyValuePair(Common.TranslationString.EventFortTargeted, "{0} in ({1}m)"), + new KeyValuePair(Common.TranslationString.EventProfileLogin, "Playing as {0}"), + new KeyValuePair(Common.TranslationString.EventUsedLuckyEgg, "Used Lucky Egg, remaining: {0}"), + new KeyValuePair(Common.TranslationString.EventPokemonEvolvedSuccess, "{0} successfully for {1}xp"), + new KeyValuePair(Common.TranslationString.EventPokemonEvolvedFailed, "Failed {0}. Result was {1}, stopping evolving {2}"), + new KeyValuePair(Common.TranslationString.EventPokemonTransferred, "{0}\t- CP: {1} IV: {2}% [Best CP: {3} IV: {4}%] (Candies: {5})"), + new KeyValuePair(Common.TranslationString.EventItemRecycled, "{0}x {1}"), + new KeyValuePair(Common.TranslationString.EventPokemonCapture, "({0}) | ({1}) {2} Lvl: {3} CP: ({4}/{5}) IV: {6}% | Chance: {7}% | {8}m dist | with a {9} ({10} left). | {11}"), + new KeyValuePair(Common.TranslationString.EventNoPokeballs, "No Pokeballs - We missed a {0} with CP {1}"), + new KeyValuePair(Common.TranslationString.CatchStatusAttempt, "{0} Attempt #{1}"), + new KeyValuePair(Common.TranslationString.CatchStatus, "{0}"), + new KeyValuePair(Common.TranslationString.Candies, "Candies: {0}") + }; + } + + public enum TranslationString + { + Pokeball, + GreatPokeball, + UltraPokeball, + MasterPokeball, + LogLevelDebug, + LogLevelPokestop, + WrongAuthType, + FarmPokestopsOutsideRadius, + FarmPokestopsNoUsableFound, + EventFortUsed, + EventFortTargeted, + EventProfileLogin, + EventUsedLuckyEgg, + EventPokemonEvolvedSuccess, + EventPokemonEvolvedFailed, + EventPokemonTransferred, + EventItemRecycled, + EventPokemonCapture, + EventNoPokeballs, + CatchStatusAttempt, + CatchStatus, + Candies, + } +} diff --git a/PoGo.NecroBot.Logic/ILogicSettings.cs b/PoGo.NecroBot.Logic/ILogicSettings.cs index 20f425771..1d6685754 100644 --- a/PoGo.NecroBot.Logic/ILogicSettings.cs +++ b/PoGo.NecroBot.Logic/ILogicSettings.cs @@ -29,6 +29,7 @@ public interface ILogicSettings float EvolveAboveIvValue { get; } bool RenameAboveIv { get; } int AmountOfPokemonToDisplayOnStart { get; } + string TranslationLanguageCode { get; } ICollection> ItemRecycleFilter { get; } diff --git a/PoGo.NecroBot.Logic/PoGo.NecroBot.Logic.csproj b/PoGo.NecroBot.Logic/PoGo.NecroBot.Logic.csproj index de8f23c43..cc8664ac8 100644 --- a/PoGo.NecroBot.Logic/PoGo.NecroBot.Logic.csproj +++ b/PoGo.NecroBot.Logic/PoGo.NecroBot.Logic.csproj @@ -34,6 +34,10 @@ ..\packages\Google.Protobuf.3.0.0-beta4\lib\net45\Google.Protobuf.dll True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + ..\packages\POGOProtos.1.3.0\lib\net45\POGOProtos.dll True @@ -51,6 +55,7 @@ + diff --git a/PoGo.NecroBot.Logic/State/Context.cs b/PoGo.NecroBot.Logic/State/Context.cs index e839856ee..d31019271 100644 --- a/PoGo.NecroBot.Logic/State/Context.cs +++ b/PoGo.NecroBot.Logic/State/Context.cs @@ -1,5 +1,6 @@ #region using directives +using PoGo.NecroBot.Logic.Common; using PokemonGo.RocketAPI; using POGOProtos.Networking.Responses; @@ -13,7 +14,7 @@ public Context(ISettings settings, ILogicSettings logicSettings) { Settings = settings; LogicSettings = logicSettings; - + Translations = Translations.Load(logicSettings.TranslationLanguageCode); Reset(settings, LogicSettings); } @@ -30,6 +31,8 @@ public Context(ISettings settings, ILogicSettings logicSettings) public LogicClient LogicClient { get; private set; } + public Translations Translations { get; private set; } + public void Reset(ISettings settings, ILogicSettings logicSettings) { Client = new Client(Settings); diff --git a/PoGo.NecroBot.Logic/Tasks/FarmPokestopsTask.cs b/PoGo.NecroBot.Logic/Tasks/FarmPokestopsTask.cs index c7d0b43e1..0980644aa 100644 --- a/PoGo.NecroBot.Logic/Tasks/FarmPokestopsTask.cs +++ b/PoGo.NecroBot.Logic/Tasks/FarmPokestopsTask.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using PoGo.NecroBot.Logic.Common; using PoGo.NecroBot.Logic.Event; using PoGo.NecroBot.Logic.Logging; using PoGo.NecroBot.Logic.State; @@ -29,9 +30,7 @@ public static async Task Execute(Context ctx, StateMachine machine) if (ctx.LogicSettings.MaxTravelDistanceInMeters != 0 && distanceFromStart > ctx.LogicSettings.MaxTravelDistanceInMeters) { - Logger.Write( - $"You're outside of your defined radius! Walking to start ({distanceFromStart}m away) in 5 seconds. Is your Coords.ini file correct?", - LogLevel.Warning); + Logger.Write(ctx.Translations.GetTranslation(TranslationString.FarmPokestopsOutsideRadius, distanceFromStart), LogLevel.Warning); await Task.Delay(5000); @@ -45,7 +44,7 @@ await ctx.Navigation.HumanLikeWalking( if (pokestopList.Count <= 0) { - machine.Fire(new WarnEvent { Message = "No usable PokeStops found in your area. Is your maximum distance too small?" }); + machine.Fire(new WarnEvent { Message = ctx.Translations.GetTranslation(TranslationString.FarmPokestopsNoUsableFound) }); } machine.Fire(new PokeStopListEvent { Forts = pokestopList }); @@ -65,7 +64,7 @@ await ctx.Navigation.HumanLikeWalking( ctx.Client.CurrentLongitude, pokeStop.Latitude, pokeStop.Longitude); var fortInfo = await ctx.Client.Fort.GetFort(pokeStop.Id, pokeStop.Latitude, pokeStop.Longitude); - machine.Fire(new FortTargetEvent {Name = fortInfo.Name, Distance = distance}); + machine.Fire(new FortTargetEvent { Name = fortInfo.Name, Distance = distance }); await ctx.Navigation.HumanLikeWalking(new GeoCoordinate(pokeStop.Latitude, pokeStop.Longitude), ctx.LogicSettings.WalkingSpeedInKilometerPerHour, @@ -97,7 +96,7 @@ await ctx.Navigation.HumanLikeWalking(new GeoCoordinate(pokeStop.Latitude, pokeS } await Task.Delay(1000); - if (++stopsHit%5 == 0) //TODO: OR item/pokemon bag is full + if (++stopsHit % 5 == 0) //TODO: OR item/pokemon bag is full { stopsHit = 0; if (fortSearch.ItemsAwarded.Count > 0) diff --git a/PoGo.NecroBot.Logic/packages.config b/PoGo.NecroBot.Logic/packages.config index 24c6b9545..5d95bffc0 100644 --- a/PoGo.NecroBot.Logic/packages.config +++ b/PoGo.NecroBot.Logic/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file