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 @@
+