private HubConnections CrateHubConnection <T>(IWebSocketSender webSocketSender) { var wrapper = new WebsocketWrapper( webSocketSender.SendToUser, webSocketSender.SendToRoom, webSocketSender.SendToAll, webSocketSender.SendToAllExcept ); return(new HubConnections(wrapper, typeof(T), _hubConnectionManager)); }
private static void MainWorkingBody() { using (WebsocketWrapper wrapper = new WebsocketWrapper(logger, false)) { wrapper.OnConnectionLost += (o, e) => mapUpdatedResetEvent.Reset(); cache.Wrapper = wrapper; logger.LogDebug("MainWorkingBody(): downloading chunks"); cache.DownloadChunks(); wrapper.OnPixelChanged += LogPixelChanged; placed.Clear(); bool wasChanged; do { logger.LogDebug("MainWorkingBody(): main body cycle started"); wasChanged = false; repeatingFails = false; foreach (Pixel pixel in pixelsToBuild) { mapUpdatedResetEvent.WaitOne(); (short x, short y, EarthPixelColor color) = pixel; EarthPixelColor actualColor = cache.GetPixelColor(x, y); if (!IsCorrectPixelColor(actualColor, color)) { logger.LogDebug($"MainWorkingBody(): {pixel} - wrong color ({actualColor})"); wasChanged = true; bool success; placed.Add(pixel); do { wrapper.WaitWebsocketConnected(); success = HttpWrapper.PlacePixel(x, y, color, out double cd, out double totalCd, out string error); if (success) { logger.LogPixel($"{(cd == 4 ? "P" : "Rep")}laced pixel:", DateTime.Now, MessageGroup.Pixel, x, y, color); Thread.Sleep(TimeSpan.FromSeconds(totalCd < 53 ? 1 : cd)); } else { logger.LogDebug($"MainWorkingBody(): pixel placing handled error {error}"); if (error == "captcha") { ProcessCaptcha(); } else { logger.Log($"Failed to place pixel: {error}", MessageGroup.PixelFail); } logger.LogDebug($"MainWorkingBody(): sleep {cd:F2} seconds"); Thread.Sleep(TimeSpan.FromSeconds(cd)); } } while (!success); } } if (options.DefenseMode) { if (!wasChanged) { logger.Log("Image is intact, waiting...", MessageGroup.Info); lock (waitingGriefLock) { logger.LogDebug("MainWorkingBody(): acquiring grief waiting lock"); gotGriefed.Reset(); gotGriefed.WaitOne(); } logger.LogDebug("MainWorkingBody(): got griefed"); Thread.Sleep(new Random().Next(500, 3000)); } } } while (options.DefenseMode || wasChanged); logger.Log("Building is finished", MessageGroup.Info); return; } }
public async Task Run() { if (options.Canvas == CanvasType.Moon) { throw new Exception("Moon canvas is not designed for bots"); } if (options.SessionName != null) { logger.LogTechState("Loading session..."); SessionManager sessionManager = new SessionManager(proxySettings); session = sessionManager.GetSession(options.SessionName); logger.LogTechInfo("Session loaded"); } logger.LogTechState("Connecting to API..."); PixelPlanetHttpApi api = new PixelPlanetHttpApi { ProxySettings = proxySettings, Session = session }; UserModel user = await api.GetMeAsync(finishToken); logger.LogTechInfo("Successfully connected"); if (options.SessionName != null) { if (user.Name != null) { logger.LogTechInfo($"Session is alive; user \"{user.Name}\""); } else { throw new SessionExpiredException(); } } canvas = user.Canvases[options.Canvas]; LoggerExtensions.MaxCoordXYLength = 1 + (int)Math.Log10(canvas.Size / 2); ValidateCanvas(); palette = new Palette(canvas.Colors, canvas.Is3D); colorNameResolver = new ColorNameResolver(options.Canvas); await LoadImage(); logger.LogTechState("Calculating pixel placing order..."); CalculateOrder(); logger.LogTechInfo("Pixel placing order is calculated"); InitCache(); mapUpdatedResetEvent = new ManualResetEvent(false); cache.OnMapUpdated += (o, e) => { logger.LogDebug("cache.OnMapUpdated event fired"); mapUpdatedResetEvent.Set(); }; if (options.DefenseMode) { gotGriefed = new AutoResetEvent(false); cache.OnMapUpdated += (o, e) => gotGriefed.Set(); waitingGriefLockObject = new object(); } Thread statsThread = new Thread(StatsCollectionThreadBody); statsThread.Start(); do { try { using (WebsocketWrapper wrapper = new WebsocketWrapper(logger, false, proxySettings, session, options.Canvas)) { wrapper.OnConnectionLost += (o, e) => mapUpdatedResetEvent.Reset(); cache.Wrapper = wrapper; cache.DownloadChunks(); wrapper.OnMapChanged += LogMapChanged; ClearPlaced(); bool wasChanged; do { repeatingFails = false; wasChanged = await PerformBuildingCycle(wrapper); if (!wasChanged && options.DefenseMode) { logger.Log("Image is intact, waiting...", MessageGroup.Info); lock (waitingGriefLockObject) { logger.LogDebug("Run(): acquiring grief waiting lock"); gotGriefed.Reset(); gotGriefed.WaitOne(); } logger.LogDebug("Run(): got griefed"); await Task.Delay(ThreadSafeRandom.Next(500, 3000), finishToken); } } while (options.DefenseMode || wasChanged); logger.Log("Building is finished", MessageGroup.Info); } return; } catch (Exception ex) { logger.LogError($"Unhandled exception: {ex.GetBaseException().Message}"); logger.LogDebug(ex.ToString()); int delay = repeatingFails ? 30 : 10; repeatingFails = true; logger.LogTechState($"Reconnecting in {delay} seconds..."); Thread.Sleep(TimeSpan.FromSeconds(delay)); continue; } } while (true); }
protected abstract Task <bool> PerformBuildingCycle(WebsocketWrapper wrapper);
private static async Task Main(string[] args) { try { if (!ParseArguments(args)) { return; } logger = new Logger(options?.LogFilePath, finishCTS.Token) { ShowDebugLogs = options?.ShowDebugLogs ?? false }; logger.LogDebug("Command line: " + Environment.CommandLine); logger.LogTechState("Connecting to API..."); PixelPlanetHttpApi api = new PixelPlanetHttpApi { ProxySettings = proxySettings }; user = await api.GetMeAsync(); logger.LogTechInfo("Successfully connected"); CanvasModel canvas = user.Canvases[options.Canvas]; if (canvas.Is3D) { throw new Exception("3D canvas is not supported"); } LoggerExtensions.MaxCoordXYLength = 1 + (int)Math.Log10(canvas.Size / 2); PixelMap.MapSize = canvas.Size; try { if (options.LeftX < -(canvas.Size / 2) || options.RightX >= canvas.Size / 2) { throw new Exception("X"); } if (options.TopY < -(canvas.Size / 2) || options.BottomY >= canvas.Size / 2) { throw new Exception("Y"); } } catch (Exception ex) { throw new Exception($"Entire rectangle should be inside the map (failed by {ex.Message})"); } colorNameResolver = new ColorNameResolver(options.Canvas); if (checkUpdates || !options.DisableUpdates) { if (UpdateChecker.IsStartingUpdate(logger, checkUpdates) || checkUpdates) { return; } } cache = new ChunkCache2D(options.LeftX, options.TopY, options.RightX, options.BottomY, logger, options.Canvas); bool initialMapSavingStarted = false; saveThread = new Thread(SaveChangesThreadBody); saveThread.Start(); if (string.IsNullOrWhiteSpace(options.FileName)) { options.FileName = string.Format("pixels_({0};{1})-({2};{3})_{4:yyyy.MM.dd_HH-mm}.bin", options.LeftX, options.TopY, options.RightX, options.BottomY, DateTime.Now); } Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(options.FileName))); do { try { using (WebsocketWrapper wrapper = new WebsocketWrapper(logger, true, proxySettings, null, options.Canvas)) { cache.Wrapper = wrapper; if (!initialMapSavingStarted) { logger.LogDebug("Main(): initiating map saving"); initialMapSavingStarted = true; lockingStreamTask = Task.Run(SaveInitialMapState); } wrapper.OnMapChanged += Wrapper_OnMapChanged; stopListening = wrapper.StopListening; Console.CancelKeyPress += (o, e) => { logger.LogDebug("Console.CancelKeyPress received"); e.Cancel = true; wrapper.StopListening(); }; logger.LogInfo("Press Ctrl+C to stop"); wrapper.StartListening(); break; } } catch (Exception ex) { logger.LogError($"Unhandled exception: {ex.Message}"); Thread.Sleep(1000); } } while (true); } catch (Exception ex) { logger?.LogError($"Unhandled app level exception: {ex.Message}"); logger?.LogDebug(ex.ToString()); } finally { if (logger != null) { logger.LogInfo("Exiting when everything is saved..."); logger.LogInfo($"Logs were saved to {logger.LogFilePath}"); } finishCTS.Cancel(); if (logger != null) { Thread.Sleep(500); } finishCTS.Dispose(); logger?.Dispose(); Console.ForegroundColor = ConsoleColor.White; if (saveThread != null && !saveThread.Join(TimeSpan.FromMinutes(1))) { Console.WriteLine("Save thread doesn't finish, aborting"); Environment.Exit(0); } } }
private static void Main(string[] args) { try { if (!ParseArguments(args, out bool isVerbError)) { bool exit = true; if (isVerbError) { Console.WriteLine("No command were found"); Console.WriteLine("Check if your scripts are updated with 'run' command before other parameters"); Console.WriteLine(); Console.WriteLine("If you want to start app with 'run' command added, press Enter"); Console.WriteLine("Please note that this option is added for compatibility with older scripts and will be removed soon"); Console.WriteLine("Press any other key to exit"); while (Console.KeyAvailable) { Console.ReadKey(true); } if (Console.ReadKey(true).Key == ConsoleKey.Enter) { Console.Clear(); if (ParseArguments(args.Prepend("run"), out _)) { exit = false; } } } if (exit) { return; } } logger = new Logger(options?.LogFilePath, finishCTS.Token) { ShowDebugLogs = options?.ShowDebugLogs ?? false }; logger.LogDebug("Command line: " + Environment.CommandLine); HttpWrapper.Logger = logger; if (checkUpdates || !options.DisableUpdates) { if (UpdateChecker.IsStartingUpdate(logger, checkUpdates) || checkUpdates) { return; } } cache = new ChunkCache(options.LeftX, options.TopY, options.RightX, options.BottomY, logger); bool initialMapSavingStarted = false; saveThread = new Thread(SaveChangesThreadBody); saveThread.Start(); if (string.IsNullOrWhiteSpace(options.FileName)) { options.FileName = string.Format("pixels_({0};{1})-({2};{3})_{4:yyyy.MM.dd_HH-mm}.bin", options.LeftX, options.TopY, options.RightX, options.BottomY, DateTime.Now); } Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(options.FileName))); do { try { HttpWrapper.ConnectToApi(); using (WebsocketWrapper wrapper = new WebsocketWrapper(logger, true)) { cache.Wrapper = wrapper; if (!initialMapSavingStarted) { logger.LogDebug("Main(): initiating map saving"); initialMapSavingStarted = true; lockingStreamTask = Task.Run(SaveInitialMapState); } wrapper.OnPixelChanged += Wrapper_OnPixelChanged; stopListening = wrapper.StopListening; Console.CancelKeyPress += (o, e) => { logger.LogDebug("Console.CancelKeyPress received"); e.Cancel = true; wrapper.StopListening(); }; logger.LogInfo("Press Ctrl+C to stop"); wrapper.StartListening(); break; } } catch (Exception ex) { logger.LogError($"Unhandled exception: {ex.Message}"); Thread.Sleep(1000); } } while (true); } catch (Exception ex) { logger?.LogError($"Unhandled app level exception: {ex.Message}"); } finally { if (logger != null) { logger.LogInfo("Exiting when everything is saved..."); logger.LogInfo($"Logs were saved to {logger.LogFilePath}"); } finishCTS.Cancel(); if (logger != null) { Thread.Sleep(500); } finishCTS.Dispose(); logger?.Dispose(); if (saveThread != null && !saveThread.Join(TimeSpan.FromMinutes(1))) { Console.WriteLine("Save thread doesn't finish, aborting"); } Console.ForegroundColor = ConsoleColor.White; Environment.Exit(0); } }