public void Set(IBot bot, int x1, int y1, int x2, int y2, IBlock replaceWith, IBlock replace = null) { EditRegion region = new EditRegion(); region.FirstCorner = new Point(x1, y1); region.SecondCorner = new Point(x2, y2); SetRegion(bot, region, replaceWith, replace); }
public void SetRegion(IBot bot, EditRegion region, IBlock replaceWith, IBlock replace = null) { if (replace == null) { foreach (Point pos in region) { RecordSetBlock(pos.X, pos.Y, replaceWith); } } else { foreach (Point pos in region) { if (bot.Room.getBlock(replaceWith.Layer, pos.X, pos.Y).Id == replace.Id) RecordSetBlock(pos.X, pos.Y, replaceWith); } } }
public override void onCommand(string cmd, string[] args, ICmdSource cmdSource) { if (cmdSource is Player && ((Player)cmdSource).IsOp) { Player player = (Player)cmdSource; if (player.GetMetadata("editregion") == null) player.SetMetadata("editregion", new EditRegion()); EditRegion region = (EditRegion)player.GetMetadata("editregion"); BeginRecord(player); switch (cmd) { case "fill": if (args.Length >= 1) { int id = -1; int layer = 0; int.TryParse(args[0], out id); if (args.Length >= 2) int.TryParse(args[1], out layer); if (id != -1) { layer = (id >= 500 && id < 1000) ? 1 : layer; EditRegion region2 = new EditRegion(); region2.FirstCorner = new Point(1, 1); region2.SecondCorner = new Point(bot.Room.Width - 2, bot.Room.Height - 2); SetRegion(bot, region2, new NormalBlock(id, layer)); } else bot.ChatSayer.Say(player.Name + ": Invalid ID."); } else bot.ChatSayer.Say(player.Name + ": Usage: !fill <id> [layer]"); break; case "undo": if (player.HasMetadata("worldedithistory") && player.HasMetadata("worldedithistoryindex")) { List<IEditChange> history = (List<IEditChange>)player.GetMetadata("worldedithistory"); int index = (int)player.GetMetadata("worldedithistoryindex"); if (index >= 0 && index <= history.Count - 1 && (index != 0 || !history[index].IsUndone)) { history[index].Undo(blockDrawer); if (index - 1 >= 0) player.SetMetadata("worldedithistoryindex", ((int)player.GetMetadata("worldedithistoryindex")) - 1); } else player.Reply("Nothing left to undo."); } else player.Reply("No history."); break; case "redo": if (player.HasMetadata("worldedithistory") && player.HasMetadata("worldedithistoryindex")) { List<IEditChange> history = (List<IEditChange>)player.GetMetadata("worldedithistory"); int index = (int)player.GetMetadata("worldedithistoryindex"); if (index <= history.Count - 1 && (index != history.Count - 1 || !history[index].IsRedone)) { if (history.Count - 1 >= index + 1) history[index + 1].Redo(blockDrawer); else history[index].Redo(blockDrawer); if (index + 1 <= history.Count - 1) player.SetMetadata("worldedithistoryindex", ((int)player.GetMetadata("worldedithistoryindex")) + 1); } else player.Reply("Nothing left to redo."); } else player.Reply("No history."); break; case "set": if (region.Set) { if (args.Length >= 1) { int id = -1; int.TryParse(args[0], out id); if (id != -1) { int layer = ((id >= 500 && id < 1000) || id == 1337 ? 1 : 0); if (args.Length >= 2) int.TryParse(args[1], out layer); SetRegion(bot, region, new NormalBlock(id, layer)); } else bot.ChatSayer.Say(player.Name + ": Invalid ID."); } else bot.ChatSayer.Say(player.Name + ": Usage: !set <id> [layer]"); } else player.Send("You have to set a region."); break; case "replace": if (region.Set) { int blockToReplace; int blockToReplaceWith; if (args.Length >= 2 && int.TryParse(args[0], out blockToReplace) && int.TryParse(args[1], out blockToReplaceWith)) { SetRegion(bot, region, new NormalBlock(blockToReplaceWith), new NormalBlock(blockToReplace)); } else bot.ChatSayer.Say(player.Name + ": Usage: !replace <from> <to>"); } else player.Send("You have to set a region."); break; case "replacenear": { int range; int blockToReplace; int blockToReplaceWith; if (args.Length >= 3 && int.TryParse(args[0], out range) && int.TryParse(args[1], out blockToReplace) && int.TryParse(args[2], out blockToReplaceWith)) { EditRegion closeRegion = new EditRegion(); closeRegion.FirstCorner = new Point(player.BlockX - range, player.BlockY - range); closeRegion.SecondCorner = new Point(player.BlockX + range, player.BlockY + range); SetRegion(bot, closeRegion, new NormalBlock(blockToReplaceWith), new NormalBlock(blockToReplace)); } else bot.ChatSayer.Say(player.Name + ": Usage: !replacenear <range> <from> <to>"); } break; case "copy": if (region.FirstCornerSet) { BlockMap selection = new BlockMap(bot, region.Width, region.Height); foreach (Point pos in region) { selection.setBlock(pos.X - region.FirstCorner.X, pos.Y - region.FirstCorner.Y, bot.Room.getBlock(1, pos.X, pos.Y)); selection.setBlock(pos.X - region.FirstCorner.X, pos.Y - region.FirstCorner.Y, bot.Room.getBlock(0, pos.X, pos.Y)); } player.SetMetadata("selection", selection); } else player.Send("You have to place a region block."); break; case "paste": if (region.FirstCornerSet) { BlockMap selection = (BlockMap)player.GetMetadata("selection"); if (selection != null) { for (int x = 0; x < selection.Width; x++) { for (int y = 0; y < selection.Height; y++) { int blax = x + region.FirstCorner.X; int blay = y + region.FirstCorner.Y; RecordSetBlock(blax, blay, selection.getBackgroundBlock(x, y)); RecordSetBlock(blax, blay, selection.getForegroundBlock(x, y)); } } } else player.Send("You have to copy first."); } else player.Send("You have to place a region block."); break; case "line": { int tempBlock; if (args.Length >= 1 && int.TryParse(args[0], out tempBlock)) { if (region.Set) DrawLine(region.FirstCorner.X, region.FirstCorner.Y, region.SecondCorner.X, region.SecondCorner.Y, new NormalBlock(tempBlock, (tempBlock >= 500 && tempBlock < 1000) ? 1 : 0)); else player.Reply("You have to set a region."); } else player.Reply("Usage: !line <block>"); } break; case "circle": if (region.FirstCornerSet) { int radius; int block; if (args.Length >= 2 && int.TryParse(args[0], out radius) && int.TryParse(args[1], out block)) { DrawCircle(region.FirstCorner.X, region.FirstCorner.Y, radius, new NormalBlock(block, (block >= 500 && block < 1000) ? 1 : 0)); } else player.Send("Usage: !circle <radius> <block>"); } else player.Send("You have to place a region block."); break; case "square": if (region.FirstCornerSet) { int radius; int block; if (args.Length >= 2 && int.TryParse(args[0], out radius) && int.TryParse(args[1], out block)) { for (int x = region.FirstCorner.X - radius; x <= region.FirstCorner.X + radius; x++) { for (int y = region.FirstCorner.Y - radius; y <= region.FirstCorner.Y + radius; y++) { RecordSetBlock(x, y, new NormalBlock(block, (block >= 500 && block < 1000) ? 1 : 0)); } } } else player.Send("Usage: !square <radius> <block>"); } else player.Send("You have to place a region block."); break; case "fillexpand": { int toReplace = 0; int toReplaceLayer = 0; int toReplaceWith = 0; if (args.Length == 1) { if (!int.TryParse(args[0], out toReplaceWith)) { player.Reply("Usage: !fillexpand <from=0> <to>"); return; } } else if (args.Length >= 2) { if (!int.TryParse(args[1], out toReplaceWith) || !int.TryParse(args[0], out toReplace)) { player.Reply("Usage: !fillexpand <from=0> <to>"); return; } } else { player.Reply("Usage: !fillexpand <from=0> <to>"); break; } if (toReplace >= 500 && toReplace < 1000) toReplaceLayer = 1; IBlock startBlock = bot.Room.BlockMap.getBlock(toReplaceLayer, player.BlockX, player.BlockY); if (startBlock.Id == toReplace) { int total = 0; List<Point> closeBlocks = new List<Point> { new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(0, -1) }; Queue<Point> blocksToCheck = new Queue<Point>(); List<Point> blocksToFill = new List<Point>(); blocksToCheck.Enqueue(new Point(player.BlockX, player.BlockY)); while (blocksToCheck.Count > 0) { Point parent = blocksToCheck.Dequeue(); for (int i = 0; i < closeBlocks.Count; i++) { Point current = new Point(closeBlocks[i].X + parent.X, closeBlocks[i].Y + parent.Y); IBlock currentBlock = bot.Room.BlockMap.getBlock(toReplaceLayer, current.X, current.Y); if (currentBlock.Id == toReplace && !blocksToCheck.Contains(current) && !blocksToFill.Contains(current) && current.X >= 0 && current.Y >= 0 && current.X <= bot.Room.Width && current.Y <= bot.Room.Height) { blocksToFill.Add(current); blocksToCheck.Enqueue(current); total++; } } } bot.ChatSayer.Say("total blocks: " + total + ". Filling.."); int layer = 0; if (toReplaceWith >= 500 && toReplaceWith < 1000) layer = 1; foreach (Point p in blocksToFill) { RecordSetBlock((int)p.X, (int)p.Y, new NormalBlock(toReplaceWith, layer)); } } } break; case "stop": blockDrawer.Stop(); break; case "start": blockDrawer.Start(); break; case "clearrepairblocks": //TODO: add function to blockdrawer break; case "write": if (region.FirstCornerSet) { int drawBlock = 0; if (args.Length >= 2 && int.TryParse(args[0], out drawBlock)) { List<char[]> letters = new List<char[]>(); foreach (string str in args.Skip(1)) letters.Add(str.ToLower().ToCharArray()); int spacing = 0; foreach (char[] array in letters) { for (int letterindex = 0; letterindex < array.Length; letterindex++) { string l = array[letterindex].ToString(); if (l != "_") { WriteLetter(spacing, l, region.FirstCorner.X, region.FirstCorner.Y, new NormalBlock(drawBlock, (drawBlock >= 500 && drawBlock < 1000) ? 1 : 0)); } if (l == @"@") spacing += 4; else if (l == "m" || l == "w" || l == "#" || l == "&") spacing += 2; else if (l == "n" || l == "%" || l == @"/" || l == @"\") spacing += 1; if (l == "|" || l == "." || l == "," || l == "'" || l == "!") { spacing -= 2; } else if (l == ",") { spacing -= 1; } spacing += 4; } spacing += array.Length; } } else player.Reply("Usage: !write <block> <text..>"); } else player.Reply("You have to set the first corner."); break; case "border": { int thickness; int block; if (args.Length >= 2 && int.TryParse(args[0], out thickness) && int.TryParse(args[1], out block)) { IBlock baseBlock = (bot.Room.getBlock(1, player.BlockX, player.BlockY).Id == 0 ? bot.Room.getBlock(0, player.BlockX, player.BlockY) : bot.Room.getBlock(0, player.BlockX, player.BlockY)); int layer = baseBlock.Layer; int x = player.BlockX; int y = player.BlockY; List<Point> closeBlocks = new List<Point> { new Point(1, 0), new Point(0, -1), new Point(-1, 0), new Point(0, 1) }; HashSet<Point> previouslySetBlocks = new HashSet<Point>(); for (int currentThickness = 0; currentThickness < thickness; currentThickness++) { int xx = x; while (bot.Room.getBlock(layer, xx + 1, y).Id == baseBlock.Id && !previouslySetBlocks.Contains(new Point(xx + 1, y)) && xx < 2000) xx++; List<Point> blocksToSet = new List<Point>(); HashSet<Point> blocksChecked = new HashSet<Point>(); Queue<Point> blocksToCheck = new Queue<Point>(); Point startPoint = new Point(xx, y); blocksToCheck.Enqueue(startPoint); blocksToSet.Add(startPoint); while (blocksToCheck.Count > 0) { Point parent = blocksToCheck.Dequeue(); for (int i = 0; i < closeBlocks.Count; i++) { Point current = new Point(closeBlocks[i].X + parent.X, closeBlocks[i].Y + parent.Y); IBlock currentBlock = bot.Room.BlockMap.getBlock(layer, current.X, current.Y); if (currentBlock.Id == baseBlock.Id && !previouslySetBlocks.Contains(current) && !blocksToCheck.Contains(current) && !blocksChecked.Contains(current)) { blocksToCheck.Enqueue(current); } else if ((currentBlock.Id != baseBlock.Id || previouslySetBlocks.Contains(current)) && !blocksToSet.Contains(parent)) { blocksToSet.Add(parent); } blocksChecked.Add(parent); } } foreach (Point p in blocksToSet) { RecordSetBlock(p.X, p.Y, new NormalBlock(block, (block >= 500 && block < 1000) ? 1 : 0)); previouslySetBlocks.Add(p); } } } else player.Reply("Usage: !border <thickness> <block>"); } break; case "worldborder": { int block; if (int.TryParse(args[0], out block)) { for (int x = 0; x < bot.Room.Width; x++) { for (int y = 0; y < bot.Room.Height; y++) { if (bot.Room.BlockMap.isOnBorder(x, y)) RecordSetBlock(x, y, new NormalBlock(block)); } } } else player.Reply("Usage: !worldborder <block>"); } break; default: return; } EndRecord(player); } }