public static EarthPixelColor[,] PixelColorsByUri(string imageUri, Logger logger) { logger.LogTechState("Downloading image..."); using (WebClient wc = new WebClient()) { logger.LogDebug($"PixelColorsByUri(): URI - {imageUri}"); byte[] data = wc.DownloadData(imageUri); using (Image <Rgba32> image = Image.Load(data)) { logger.LogTechInfo("Image is downloaded"); logger.LogTechState("Converting image..."); int w = image.Width; int h = image.Height; EarthPixelColor[,] res = new EarthPixelColor[w, h]; Parallel.For(0, w, x => { for (int y = 0; y < h; y++) { res[x, y] = ClosestAvailable(image[x, y]); } }); logger.LogTechInfo("Image is converted"); return(res); } } }
private static double OutlineCriteria(Pixel p) { const int radius = 3; double score = ThreadSafeRandom.NextDouble() * 125D; (short x, short y, EarthPixelColor c) = p; for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { int ox = x + i; int oy = y + j; double dist = Math.Sqrt(i * i + j * j); if (ox >= 0 && oy >= 0 && ox < width && oy < height) { EarthPixelColor c2 = imagePixels[ox, oy]; if (c2 == EarthPixelColor.None) { score += ImageProcessing.NoneColorDistance / dist; } else if (c != c2) { score += ImageProcessing.RgbCubeDistance(c, c2) / dist; } } else { score += ImageProcessing.NoneColorDistance / dist; } } } return(score); }
public static EarthPixelColor[,] ToColorRectangle(byte[] bytes, int height, int width) { EarthPixelColor[,] map = new EarthPixelColor[height, width]; if (bytes.Length != 0) { unsafe { fixed(byte *byteArr = &bytes[0]) fixed(EarthPixelColor * colorArr = &map[0, 0]) { Buffer.MemoryCopy(byteArr, colorArr, width * height, bytes.Length); } } } return(map); }
public static Rgba32 ToRgba32(this EarthPixelColor color) { if (color == EarthPixelColor.None) { return(Rgba32.Transparent); } if (color == EarthPixelColor.UnsetOcean) { color = EarthPixelColor.SkyBlue; } if (color == EarthPixelColor.UnsetLand) { color = EarthPixelColor.White; } return(colors[(byte)color - 2]); }
private static Delta ReadDelta(this BinaryReader reader) { DateTime dateTime = DateTime.FromBinary(reader.ReadInt64()); uint count = reader.ReadUInt32(); List <(short, short, EarthPixelColor)> pixels = new List <Pixel>(); for (int j = 0; j < count; j++) { short x = reader.ReadInt16(); short y = reader.ReadInt16(); EarthPixelColor color = (EarthPixelColor)reader.ReadByte(); pixels.Add((x, y, color)); } return(new Delta { DateTime = dateTime, Pixels = pixels }); }
private static void LogPixelChanged(object sender, PixelChangedEventArgs e) { MessageGroup msgGroup; short x = PixelMap.ConvertToAbsolute(e.Chunk.Item1, e.Pixel.Item1); short y = PixelMap.ConvertToAbsolute(e.Chunk.Item2, e.Pixel.Item2); if (!placed.Remove((x, y, e.Color))) { try { EarthPixelColor desiredColor = imagePixels[x - options.LeftX, y - options.TopY]; if (desiredColor == EarthPixelColor.None) { msgGroup = MessageGroup.PixelInfo; } else { if (desiredColor == e.Color) { msgGroup = MessageGroup.Assist; builtInLastMinute++; } else { msgGroup = MessageGroup.Attack; griefedInLastMinute++; gotGriefed?.Set(); } } } catch (IndexOutOfRangeException) { logger.LogDebug("LogPixelChanged(): pixel update beyond rectangle"); msgGroup = MessageGroup.PixelInfo; } catch (Exception ex) { logger.LogDebug($"LogPixelChanged(): unhandled exception - {ex.Message}"); msgGroup = MessageGroup.PixelInfo; } logger.LogPixel($"Received pixel update:", e.DateTime, msgGroup, x, y, e.Color); }
public static double RgbCubeDistance(EarthPixelColor c1, EarthPixelColor c2) { if (c1 == EarthPixelColor.None || c2 == EarthPixelColor.None) { if (c1 == c2) { return(0); } else { return(NoneColorDistance); } } Rgba32 rgb1 = c1.ToRgba32(); Rgba32 rgb2 = c2.ToRgba32(); int dR = rgb1.R - rgb2.R; int dG = rgb1.G - rgb2.G; int dB = rgb2.B - rgb2.B; return(Math.Sqrt(dR * dR + dG * dG + dB * dB)); }
public static bool PlacePixel(int x, int y, EarthPixelColor color, out double coolDown, out double totalCoolDown, out string error) { PixelPlacingData data = new PixelPlacingData { Canvas = byte.MinValue, Color = color, AbsoluteX = x, AbsoluteY = y }; try { using (HttpWebResponse response = SendRequest("api/pixel", data)) { switch (response.StatusCode) { case HttpStatusCode.OK: { using (StreamReader sr = new StreamReader(response.GetResponseStream())) { string responseString = sr.ReadToEnd(); Logger.LogDebug($"PlacePixel(): response - {responseString}"); JObject json = JObject.Parse(responseString); if (bool.TryParse(json["success"].ToString(), out bool success) && success) { coolDown = double.Parse(json["coolDownSeconds"].ToString()); totalCoolDown = double.Parse(json["waitSeconds"].ToString()); error = string.Empty; multiplePlacingFails = false; return(true); } else { if (json["errors"].Count() > 0) { string errors = string.Concat(json["errors"].Select(e => $"{Environment.NewLine}\"{e}\"")); throw new PausingException($"Server responded with errors: {errors}"); } else { coolDown = totalCoolDown = double.Parse(json["waitSeconds"].ToString()); error = "IP is overused"; multiplePlacingFails = false; return(false); } } } } default: throw new Exception($"Error: {response.StatusDescription}"); } } } catch (WebException ex) { using (HttpWebResponse response = ex.Response as HttpWebResponse) { if (response == null) { error = "internet connection is slow or not available"; totalCoolDown = coolDown = 1; return(false); } switch (response.StatusCode) { case HttpStatusCode.Forbidden: throw new PausingException("Action was forbidden by pixelworld; admins could have prevented you from placing pixel or area is protected"); case HttpStatusCode.BadGateway: totalCoolDown = coolDown = multiplePlacingFails ? 30 : 10; multiplePlacingFails = true; error = $"site is overloaded, delay {coolDown}s before next attempt"; return(false); case (HttpStatusCode)422: error = "captcha"; totalCoolDown = coolDown = 0.0; return(false); default: throw new Exception(response.StatusDescription); } } } }
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 static void LogPixel(this Logger logger, string msg, DateTime time, MessageGroup group, int x, int y, EarthPixelColor color) { const int maxMsgLength = 22; const int maxCoordLength = 6; string text = string.Format("{0} {1} at ({2};{3})", msg.PadRight(maxMsgLength), color.ToString().PadRight(colorPadLength), x.ToString().PadLeft(maxCoordLength), y.ToString().PadLeft(maxCoordLength)); logger.Log(text, group, time); }