diff --git a/Commands/building/CmdBrush.cs b/Commands/building/CmdBrush.cs index e3d2ce3bf..6f3e14685 100644 --- a/Commands/building/CmdBrush.cs +++ b/Commands/building/CmdBrush.cs @@ -18,7 +18,7 @@ using System; using MCGalaxy; using MCGalaxy.Drawing.Brushes; - + namespace MCGalaxy.Commands { public sealed class CmdBrush : Command { @@ -32,18 +32,25 @@ namespace MCGalaxy.Commands { if (message == "") { Help(p); return; } if (p == null) { MessageInGameOnly(p); return; } - foreach (var brush in Brush.Brushes) { - if (brush.Key.Equals(message, StringComparison.OrdinalIgnoreCase)) { - Player.SendMessage(p, "Set your brush to: " + brush.Key); - p.BrushName = brush.Key; - return; - } + string brush = FindBrush(message); + if (brush == null) { + Player.SendMessage(p, "No brush found with name \"" + message + "\"."); + Player.SendMessage(p, "Available brushes: " + AvailableBrushes); + } else { + Player.SendMessage(p, "Set your brush to: " + brush); + p.BrushName = brush; } - Player.SendMessage(p, "No brush found with name \"" + message + "\"."); - Player.SendMessage(p, "Available brushes: " + AvailableBrushes); } - static string AvailableBrushes { + internal static string FindBrush(string message) { + foreach (var brush in Brush.Brushes) { + if (brush.Key.Equals(message, StringComparison.OrdinalIgnoreCase)) + return brush.Key; + } + return null; + } + + internal static string AvailableBrushes { get { return string.Join( ", ", Brush.Brushes.Keys); } } diff --git a/Commands/building/CmdReplaceBrush.cs b/Commands/building/CmdReplaceBrush.cs new file mode 100644 index 000000000..9b3983e12 --- /dev/null +++ b/Commands/building/CmdReplaceBrush.cs @@ -0,0 +1,54 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using MCGalaxy; +using MCGalaxy.Drawing.Brushes; + +namespace MCGalaxy.Commands { + + public sealed class CmdReplaceBrush : Command { + public override string name { get { return "replacebrush"; } } + public override string shortcut { get { return "rb"; } } + public override string type { get { return CommandTypes.Building; } } + public override bool museumUsable { get { return false; } } + public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } } + static char[] trimChars = {' '}; + + public override void Use(Player p, string message) { + // TODO: make sure can use or brush first. + if (message == "") { Help(p); return; } + if (p == null) { MessageInGameOnly(p); return; } + string[] args = message.Split(trimChars, 3); + if (args.Length < 2) { Help(p); return } + + byte extType = 0; + byte type = DrawCmd.GetBlock(p, args[0], out extType); + string brush = CmdBrush.FindBrush(args[1]); + if (brush == null) { + Player.SendMessage(p, "No brush found with name \"" + message + "\"."); + Player.SendMessage(p, "Available brushes: " + CmdBrush.AvailableBrushes); + return; + } + } + + public override void Help(Player p) { + Player.SendMessage(p, "/replace [block] [block2].. [new] - replace block with new inside a selected cuboid"); + Player.SendMessage(p, "If more than one [block] is specified, they will all be replaced."); + } + } +} diff --git a/Drawing/Brushes/Brush.cs b/Drawing/Brushes/Brush.cs index 0f5205a9c..3cf051b1f 100644 --- a/Drawing/Brushes/Brush.cs +++ b/Drawing/Brushes/Brush.cs @@ -39,6 +39,8 @@ namespace MCGalaxy.Drawing.Brushes { { "rainbow", RainbowBrush.Process }, { "bwrainbow", BWRainbowBrush.Process }, { "striped", StripedBrush.Process }, + { "replace", ReplaceBrush.Process }, + { "replacenot", ReplaceNotBrush.Process }, }; } diff --git a/Drawing/Brushes/ReplaceBrush.cs b/Drawing/Brushes/ReplaceBrush.cs new file mode 100644 index 000000000..930d5b94e --- /dev/null +++ b/Drawing/Brushes/ReplaceBrush.cs @@ -0,0 +1,119 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; +using MCGalaxy.Commands; +using MCGalaxy.Drawing.Ops; + +namespace MCGalaxy.Drawing.Brushes { + + public sealed class ReplaceBrush : Brush { + readonly ExtBlock[] include; + readonly ExtBlock target; + + public ReplaceBrush(ExtBlock[] include, ExtBlock target) { + this.include = include; this.target = target; + } + + public override string Name { get { return "Replace"; } } + + public static Brush Process(BrushArgs args) { + string[] parts = args.Message.Split(' '); + if (parts.Length < 2) { + args.Player.SendMessage("You need to provide a target block, and at least one block to replace."); return null; + } + + ExtBlock[] toAffect = GetBlocks(args.Player, 0, parts.Length - 1, parts); + ExtBlock target; + target.Type = DrawCmd.GetBlock(args.Player, parts[parts.Length - 1], out target.ExtType); + if (target.Type == Block.Zero) return null; + return target.Type == Block.Zero ? null : new ReplaceBrush(toAffect, target); + } + + internal static ExtBlock[] GetBlocks(Player p, int start, int max, string[] parts) { + ExtBlock[] blocks = new ExtBlock[max - start]; + for (int j = 0; j < blocks.Length; j++) + blocks[j].Type = Block.Zero; + for (int j = 0; start < max; start++, j++ ) { + byte extType = 0; + byte type = DrawCmd.GetBlock(p, parts[start], out extType); + if (type == Block.Zero) continue; + blocks[j].Type = type; blocks[j].ExtType = extType; + } + return blocks; + } + + public override byte NextBlock(DrawOp op) { + ushort x = op.Coords.X, y = op.Coords.Y, z = op.Coords.Z; + byte tile = op.Level.GetTile(x, y, z), extTile = 0; + if (tile == Block.custom_block) extTile = op.Level.GetExtTile(x, y, z); + + for (int i = 0; i < include.Length; i++) { + ExtBlock block = include[i]; + if (tile == block.Type && (tile != Block.custom_block || extTile == block.ExtType)) + return target.Type; + } + return Block.Zero; + } + + public override byte NextExtBlock(DrawOp op) { + return target.ExtType; + } + } + + public sealed class ReplaceNotBrush : Brush { + readonly ExtBlock[] exclude; + readonly ExtBlock target; + + public ReplaceNotBrush(ExtBlock[] include, ExtBlock target) { + this.exclude = include; this.target = target; + } + + public override string Name { get { return "Replace"; } } + + public static Brush Process(BrushArgs args) { + string[] parts = args.Message.Split(' '); + if (parts.Length < 2) { + args.Player.SendMessage("You need to provide a target block, and at least one block to replace."); return null; + } + + ExtBlock[] toAffect = ReplaceBrush.GetBlocks(args.Player, 0, parts.Length - 1, parts); + ExtBlock target; + target.Type = DrawCmd.GetBlock(args.Player, parts[parts.Length - 1], out target.ExtType); + if (target.Type == Block.Zero) return null; + return target.Type == Block.Zero ? null : new ReplaceNotBrush(toAffect, target); + } + + public override byte NextBlock(DrawOp op) { + ushort x = op.Coords.X, y = op.Coords.Y, z = op.Coords.Z; + byte tile = op.Level.GetTile(x, y, z), extTile = 0; + if (tile == Block.custom_block) extTile = op.Level.GetExtTile(x, y, z); + + for (int i = 0; i < exclude.Length; i++) { + ExtBlock block = exclude[i]; + if (tile == block.Type && (tile != Block.custom_block || extTile == block.ExtType)) + return Block.Zero; + } + return target.Type; + } + + public override byte NextExtBlock(DrawOp op) { + return target.ExtType; + } + } +} diff --git a/Drawing/DrawOps/DrawOp.cs b/Drawing/DrawOps/DrawOp.cs index 8e773a598..0249fe00c 100644 --- a/Drawing/DrawOps/DrawOp.cs +++ b/Drawing/DrawOps/DrawOp.cs @@ -47,6 +47,9 @@ namespace MCGalaxy.Drawing.Ops { /// Coordinates of the current block being processed by the drawing command. public Vector3U16 Coords; + /// Level the draw operation is being performed upon. + public Level Level; + /// Whether the two given coordinates from the user should be adjusted, /// so that the first coordinate contains the minimum values on all three axes. public virtual bool MinMaxCoords { get { return true; } } @@ -124,6 +127,7 @@ namespace MCGalaxy.Drawing.Ops { op.Origin = new Vector3U16(x1, y1, z1); op.Min = Vector3U16.Min(x1, y1, z1, x2, y2, z2); op.Max = Vector3U16.Max(x1, y1, z1, x2, y2, z2); + op.Level = p.level; if (op.MinMaxCoords) { ushort xx1 = x1, yy1 = y1, zz1 = z1, xx2 = x2, yy2 = y2, zz2 = z2; x1 = Math.Min(xx1, xx2); x2 = Math.Max(xx1, xx2); diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 7aaa292fe..974f61e8f 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -396,6 +396,7 @@ +