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); }
private async static Task Main(string[] args) { try { if (!ParseArguments(args)) { return; } logger = new Logger(options?.LogFilePath, finishCTS.Token) { ShowDebugLogs = options?.ShowDebugLogs ?? false }; if (checkUpdates || !options.DisableUpdates) { if (UpdateChecker.IsStartingUpdate(logger, checkUpdates) || checkUpdates) { return; } } logger.LogTechState("Loading data from file..."); try { LoadFile(options.FileName); } catch (Exception ex) { logger.LogError($"Error during loading file: {ex.Message}"); } logger.LogInfo($"File is loaded: {w}x{h}, {deltas.Count + 1} frames"); logger.LogTechState("Downloading palette..."); PixelPlanetHttpApi api = new PixelPlanetHttpApi { ProxySettings = proxySettings }; UserModel user = await api.GetMeAsync(); logger.LogTechInfo("Palette retrieved"); CanvasModel canvas = user.Canvases[canvasType]; palette = new Palette(canvas.Colors); DirectoryInfo dir = Directory.CreateDirectory($"seq_{startTime:MM.dd_HH-mm}"); string pathTemplate = Path.Combine(dir.FullName, "{0:MM.dd_HH-mm-ss}.png"); try { SaveLoadedData(pathTemplate); } catch (Exception ex) { logger.LogError($"Error during saving results: {ex.Message}"); } } catch (Exception ex) { logger?.LogError($"Unhandled app level exception: {ex.Message}"); logger?.LogDebug(ex.ToString()); } finally { if (logger != null) { logger.LogInfo("Exiting..."); logger.LogInfo($"Logs were saved to {logger.LogFilePath}"); } finishCTS.Cancel(); if (logger != null) { Thread.Sleep(500); } logger?.Dispose(); finishCTS.Dispose(); Console.ForegroundColor = ConsoleColor.White; Environment.Exit(0); } }
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); } } }