diff --git a/Drawing/DrawOps/AdvConeDrawOps.cs b/Drawing/DrawOps/AdvConeDrawOps.cs index 2ce4023cc..3ca9a2afc 100644 --- a/Drawing/DrawOps/AdvConeDrawOps.cs +++ b/Drawing/DrawOps/AdvConeDrawOps.cs @@ -21,6 +21,7 @@ // // ~Merlin33069 using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -34,7 +35,7 @@ namespace MCGalaxy.Drawing.Ops { return (long)(Math.PI / 3 * (R * R * H)); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; @@ -53,7 +54,7 @@ namespace MCGalaxy.Drawing.Ops { byte ctile = lvl.GetTile(x, y, z); if (ctile != 0) continue; - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -69,7 +70,7 @@ namespace MCGalaxy.Drawing.Ops { return (long)(outer - inner); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; @@ -89,7 +90,7 @@ namespace MCGalaxy.Drawing.Ops { byte ctile = lvl.GetTile(x, y, z); if (ctile != 0) continue; - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -103,7 +104,7 @@ namespace MCGalaxy.Drawing.Ops { return (long)(Math.PI / 3 * (R * R * H)); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; @@ -122,9 +123,10 @@ namespace MCGalaxy.Drawing.Ops { byte ctile = lvl.GetTile(x, y, z); if (ctile != 0) continue; + bool layer = dist >= (curRadius - 1) * (curRadius - 1); byte type = layer ? Block.grass : Block.lavastill; - PlaceBlock(p, lvl, x, y, z, type, 0); + yield return Place(x, y, z, type, 0); } } } diff --git a/Drawing/DrawOps/AdvDrawOps.cs b/Drawing/DrawOps/AdvDrawOps.cs index 1dbfcec1e..dbf3687f2 100644 --- a/Drawing/DrawOps/AdvDrawOps.cs +++ b/Drawing/DrawOps/AdvDrawOps.cs @@ -21,6 +21,7 @@ // // ~Merlin33069 using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -42,7 +43,7 @@ namespace MCGalaxy.Drawing.Ops { return (long)(Math.PI * 4.0 / 3.0 * (R * R * R)); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { int upper = (Radius + 1) * (Radius + 1); Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; @@ -53,7 +54,7 @@ namespace MCGalaxy.Drawing.Ops { { int dist = (C.X - x) * (C.X - x) + (C.Y - y) * (C.Y - y) + (C.Z - z) * (C.Z - z); if (dist < upper) - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -70,7 +71,7 @@ namespace MCGalaxy.Drawing.Ops { return (long)(outer - inner); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { int upper = (Radius + 1) * (Radius + 1), inner = (Radius - 1) * (Radius - 1); Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; @@ -81,7 +82,7 @@ namespace MCGalaxy.Drawing.Ops { { int dist = (C.X - x) * (C.X - x) + (C.Y - y) * (C.Y - y) + (C.Z - z) * (C.Z - z); if (dist < upper && dist >= inner) - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } diff --git a/Drawing/DrawOps/AdvPyramidDrawOps.cs b/Drawing/DrawOps/AdvPyramidDrawOps.cs index f495e1fd7..d04a70a38 100644 --- a/Drawing/DrawOps/AdvPyramidDrawOps.cs +++ b/Drawing/DrawOps/AdvPyramidDrawOps.cs @@ -21,6 +21,7 @@ // // ~Merlin33069 using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -34,7 +35,7 @@ namespace MCGalaxy.Drawing.Ops { return (R * R * H) / 3; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; @@ -52,7 +53,7 @@ namespace MCGalaxy.Drawing.Ops { continue; byte ctile = lvl.GetTile(x, y, z); if (ctile != 0) continue; - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -68,7 +69,7 @@ namespace MCGalaxy.Drawing.Ops { return outer - inner; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; @@ -88,7 +89,7 @@ namespace MCGalaxy.Drawing.Ops { byte ctile = lvl.GetTile(x, y, z); if (ctile != 0) continue; - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } diff --git a/Drawing/DrawOps/CuboidDrawOp.cs b/Drawing/DrawOps/CuboidDrawOp.cs index 4830f62e2..d59b1691f 100644 --- a/Drawing/DrawOps/CuboidDrawOp.cs +++ b/Drawing/DrawOps/CuboidDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -28,13 +29,13 @@ namespace MCGalaxy.Drawing.Ops { return (Max.X - Min.X + 1) * (Max.Y - Min.Y + 1) * (Max.Z - Min.Z + 1); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { - Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) for (ushort z = p1.Z; z <= p2.Z; z++) for (ushort x = p1.X; x <= p2.X; x++) { - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -51,47 +52,50 @@ namespace MCGalaxy.Drawing.Ops { return xQuadsVol + yQuadsVol + zQuadzVol; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { - Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); int lenX = (p2.X - p1.X + 1), lenY = (p2.Y - p1.Y + 1); - QuadY(p1.Y, p1.X, p1.Z, p2.X, p2.Z, p, lvl, brush); - QuadY(p2.Y, p1.X, p1.Z, p2.X, p2.Z, p, lvl, brush); + foreach (var block in QuadY(p1.Y, p1.X, p1.Z, p2.X, p2.Z, brush)) + yield return block; + foreach (var block in QuadY(p2.Y, p1.X, p1.Z, p2.X, p2.Z, brush)) + yield return block; if (lenY > 2) { - QuadX(p1.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, p, lvl, brush); - QuadX(p2.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, p, lvl, brush); + foreach (var block in QuadX(p1.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, brush)) + yield return block; + foreach (var block in QuadX(p2.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, brush)) + yield return block; } if (lenX > 2 && lenY > 2) { - QuadZ(p1.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), - (ushort)(p2.Y - 1), (ushort)(p2.X - 1), p, lvl, brush); - QuadZ(p2.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), - (ushort)(p2.Y - 1), (ushort)(p2.X - 1), p, lvl, brush); + foreach (var block in QuadZ(p1.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), + (ushort)(p2.Y - 1), (ushort)(p2.X - 1), brush)) + yield return block; + foreach (var block in QuadZ(p2.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), + (ushort)(p2.Y - 1), (ushort)(p2.X - 1), brush)) + yield return block; } } - protected void QuadX(ushort x, ushort y1, ushort z1, ushort y2, ushort z2, - Player p, Level lvl, Brush brush) { + protected IEnumerable QuadX(ushort x, ushort y1, ushort z1, ushort y2, ushort z2, Brush brush) { for (ushort y = y1; y <= y2; y++) for (ushort z = z1; z <= z2; z++) { - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } - protected void QuadY(ushort y, ushort x1, ushort z1, ushort x2, ushort z2, - Player p, Level lvl, Brush brush) { + protected IEnumerable QuadY(ushort y, ushort x1, ushort z1, ushort x2, ushort z2, Brush brush) { for (ushort z = z1; z <= z2; z++) for (ushort x = x1; x <= x2; x++) { - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } - protected void QuadZ(ushort z, ushort y1, ushort x1, ushort y2, ushort x2, - Player p, Level lvl, Brush brush) { + protected IEnumerable QuadZ(ushort z, ushort y1, ushort x1, ushort y2, ushort x2, Brush brush) { for (ushort y = y1; y <= y2; y++) for (ushort x = x1; x <= x2; x++) { - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -107,15 +111,19 @@ namespace MCGalaxy.Drawing.Ops { return xQuadsVol + zQuadsVol; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { - Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); int lenX = (p2.X - p1.X + 1); - QuadX(p1.X, p1.Y, p1.Z, p2.Y, p2.Z, p, lvl, brush); - QuadX(p2.X, p1.Y, p1.Z, p2.Y, p2.Z, p, lvl, brush); - if (lenX > 2) { - QuadZ(p1.Z, p1.Y, (ushort)(p1.X + 1), p2.Y, (ushort)(p2.X - 1), p, lvl, brush); - QuadZ(p2.Z, p1.Y, (ushort)(p1.X + 1), p2.Y, (ushort)(p2.X - 1), p, lvl, brush); - } + foreach (var block in QuadX(p1.X, p1.Y, p1.Z, p2.Y, p2.Z, brush)) + yield return block; + foreach (var block in QuadX(p2.X, p1.Y, p1.Z, p2.Y, p2.Z, brush)) + yield return block; + + if (lenX <= 2) yield break; + foreach (var block in QuadZ(p1.Z, p1.Y, (ushort)(p1.X + 1), p2.Y, (ushort)(p2.X - 1), brush)) + yield return block; + foreach (var block in QuadZ(p2.Z, p1.Y, (ushort)(p1.X + 1), p2.Y, (ushort)(p2.X - 1), brush)) + yield return block; } } @@ -130,27 +138,27 @@ namespace MCGalaxy.Drawing.Ops { return horSidesvol + verSidesVol; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { - Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++ ) { - PlaceBlock(p, lvl, p1.X, y, p1.Z, brush); - PlaceBlock(p, lvl, p2.X, y, p1.Z, brush); - PlaceBlock(p, lvl, p1.X, y, p2.Z, brush); - PlaceBlock(p, lvl, p2.X, y, p2.Z, brush); + yield return Place(p1.X, y, p1.Z, brush); + yield return Place(p2.X, y, p1.Z, brush); + yield return Place(p1.X, y, p2.Z, brush); + yield return Place(p2.X, y, p2.Z, brush); } for (ushort z = p1.Z; z <= p2.Z; z++) { - PlaceBlock(p, lvl, p1.X, p1.Y, z, brush); - PlaceBlock(p, lvl, p2.X, p1.Y, z, brush); - PlaceBlock(p, lvl, p1.X, p2.Y, z, brush); - PlaceBlock(p, lvl, p2.X, p2.Y, z, brush); + yield return Place(p1.X, p1.Y, z, brush); + yield return Place(p2.X, p1.Y, z, brush); + yield return Place(p1.X, p2.Y, z, brush); + yield return Place(p2.X, p2.Y, z, brush); } for (ushort x = p1.X; x <= p2.X; x++) { - PlaceBlock(p, lvl, x, p1.Y, p1.Z, brush); - PlaceBlock(p, lvl, x, p1.Y, p2.Z, brush); - PlaceBlock(p, lvl, x, p2.Y, p1.Z, brush); - PlaceBlock(p, lvl, x, p2.Y, p2.Z, brush); + yield return Place(x, p1.Y, p1.Z, brush); + yield return Place(x, p1.Y, p2.Z, brush); + yield return Place(x, p2.Y, p1.Z, brush); + yield return Place(x, p2.Y, p2.Z, brush); } } } diff --git a/Drawing/DrawOps/CuboidDrawOps.cs b/Drawing/DrawOps/CuboidDrawOps.cs index 90d7cb403..46c870ebf 100644 --- a/Drawing/DrawOps/CuboidDrawOps.cs +++ b/Drawing/DrawOps/CuboidDrawOps.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -25,7 +26,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Hollow"; } } public byte Skip; - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) for (ushort z = p1.Z; z <= p2.Z; z++) @@ -44,7 +45,7 @@ namespace MCGalaxy.Drawing.Ops { hollow = false; } if (hollow) - PlaceBlock(p, lvl, x, y, z, Block.air, 0); + yield return Place(x, y, z, Block.air, 0); } } @@ -60,7 +61,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Outline"; } } public byte Type, ExtType, NewType, NewExtType; - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) for (ushort z = p1.Z; z <= p2.Z; z++) @@ -75,7 +76,7 @@ namespace MCGalaxy.Drawing.Ops { outline |= Check(lvl, x, (ushort)(y + 1), z); if (outline && !Check(lvl, x, y, z)) - PlaceBlock(p, lvl, x, y, z, NewType, NewExtType); + yield return Place(x, y, z, NewType, NewExtType); } } @@ -90,7 +91,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Rainbow"; } } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); int dx = Math.Abs(p1.X - p2.X), dy = Math.Abs(p1.Y - p2.Y), dz = Math.Abs(p1.Z - p2.Z); byte stepX = 0, stepY = 0, stepZ = 0; @@ -113,7 +114,7 @@ namespace MCGalaxy.Drawing.Ops { for (ushort x = p1.X; x <= p2.X; x++) { i = (i + stepX) % 13; if (lvl.GetTile(x, y, z) != Block.air) - PlaceBlock(p, lvl, x, y, z, (byte)(Block.red + i), 0); + yield return Place(x, y, z, (byte)(Block.red + i), 0); } i = startX; } diff --git a/Drawing/DrawOps/DrawOp.Performer.cs b/Drawing/DrawOps/DrawOp.Performer.cs index 63f74b080..61b213e72 100644 --- a/Drawing/DrawOps/DrawOp.Performer.cs +++ b/Drawing/DrawOps/DrawOp.Performer.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using MCGalaxy.BlockPhysics; using MCGalaxy.Commands; using MCGalaxy.Drawing.Brushes; using MCGalaxy.Drawing.Ops; @@ -41,9 +42,9 @@ namespace MCGalaxy.Drawing.Ops { return DoDrawOp(op, brush, p, marks); } - public static bool DoDrawOp(DrawOp op, Brush brush, Player p, - Vec3S32[] marks, bool checkLimit = true) { - op.SetMarks(marks); + public static bool DoDrawOp(DrawOp op, Brush brush, Player p, + Vec3S32[] marks, bool checkLimit = true) { + op.SetMarks(marks); op.Level = p == null ? null : p.level; if (op.Level != null && !op.Level.DrawingAllowed) { Player.Message(p, "Drawing commands are turned off on this map."); @@ -66,8 +67,13 @@ namespace MCGalaxy.Drawing.Ops { } static void AppendDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks, long affected) { - if (p == null) { op.Perform(marks, p, op.Level, brush); return; } - + if (p == null) { + foreach (var block in op.Perform(marks, p, op.Level, brush)) + op.Level.Blockchange(block.X, block.Y, block.Z, block.Type, + false, default(PhysicsArgs), block.ExtType); + return; + } + PendingDrawOp item = new PendingDrawOp(); item.Op = op; item.Brush = brush; @@ -107,23 +113,62 @@ namespace MCGalaxy.Drawing.Ops { int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; entry.Start = Server.StartTime.AddTicks(timeDelta * TimeSpan.TicksPerSecond); - bool needReveal = item.Op.DetermineDrawOpMethod(item.Level, item.Affected); - if (item.Brush != null) - item.Brush.Configure(item.Op, p); - item.Op.Perform(item.Marks, p, item.Level, item.Brush); + if (item.Brush != null) item.Brush.Configure(item.Op, p); + DoDrawOp(item, p); timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; entry.End = Server.StartTime.AddTicks(timeDelta * TimeSpan.TicksPerSecond); p.DrawOps.Add(entry); if (p.DrawOps.Count > 200) p.DrawOps.RemoveFirst(); - DoReload(p, item.Level, needReveal); + if (item.Affected > Server.DrawReloadLimit) + DoReload(p, item.Level); } } - static void DoReload(Player p, Level lvl, bool needReveal) { - if (!needReveal) return; + static void DoDrawOp(PendingDrawOp item, Player p) { + Level lvl = item.Level; + Level.BlockPos bP = default(Level.BlockPos); + if (item.Affected > Server.DrawReloadLimit) { + foreach (var b in item.Op.Perform(item.Marks, p, lvl, item.Brush)) { + if (b.Type == Block.Zero) continue; + byte old = lvl.GetTile(b.X, b.Y, b.Z); + if (old == Block.Zero || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Type)) + continue; + + lvl.SetTile(b.X, b.Y, b.Z, b.Type, p, b.ExtType); + p.loginBlocks++; + p.overallBlocks++; + } + } else if (item.Level.bufferblocks) { + foreach (var b in item.Op.Perform(item.Marks, p, lvl, item.Brush)) { + if (b.Type == Block.Zero) continue; + if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Type, b.ExtType)) continue; + bP.name = p.name; + bP.index = lvl.PosToInt(b.X, b.Y, b.Z); + bP.SetData(b.Type, b.ExtType, b.Type == 0); + + if (lvl.UseBlockDB) + lvl.blockCache.Add(bP); + BlockQueue.Addblock(p, bP.index, b.Type, b.ExtType); + } + } else { + foreach (var b in item.Op.Perform(item.Marks, p, item.Level, item.Brush)) { + if (b.Type == Block.Zero) continue; + if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Type, b.ExtType)) continue; + bP.name = p.name; + bP.index = lvl.PosToInt(b.X, b.Y, b.Z); + + bP.SetData(b.Type, b.ExtType, b.Type == 0); + if (lvl.UseBlockDB) + lvl.blockCache.Add(bP); + Player.GlobalBlockchange(lvl, b.X, b.Y, b.Z, b.Type, b.ExtType); + } + } + } + + static void DoReload(Player p, Level lvl) { Player[] players = PlayerInfo.Online.Items; foreach (Player pl in players) { if (pl.level.name.CaselessEq(lvl.name)) diff --git a/Drawing/DrawOps/DrawOp.cs b/Drawing/DrawOps/DrawOp.cs index 5c63bbf58..1c49bcf2b 100644 --- a/Drawing/DrawOps/DrawOp.cs +++ b/Drawing/DrawOps/DrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy { @@ -29,6 +30,11 @@ namespace MCGalaxy { Type = type; ExtType = extType; } } + + public struct DrawOpBlock { + public ushort X, Y, Z; + public byte Type, ExtType; + } } namespace MCGalaxy.Drawing.Ops { @@ -50,7 +56,8 @@ namespace MCGalaxy.Drawing.Ops { public Vec3S32 Origin; /// Coordinates of the current block being processed by the drawing command. - public Vec3U16 Coords; + /// Note: You should treat this as coordinates, it is a DrawOpBlock struct for performance reasons. + public DrawOpBlock Coords; /// Level the draw operation is being performed upon. public Level Level; @@ -62,7 +69,7 @@ namespace MCGalaxy.Drawing.Ops { /// Note that this estimate assumes that all possibly affected blocks will be changed by the drawing command. public abstract long GetBlocksAffected(Level lvl, Vec3S32[] marks); - public abstract void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush); + public abstract IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush); public virtual bool CanDraw(Vec3S32[] marks, Player p, out long affected) { affected = GetBlocksAffected(Level, marks); @@ -74,16 +81,6 @@ namespace MCGalaxy.Drawing.Ops { return true; } - public virtual bool DetermineDrawOpMethod(Level lvl, long affected) { - if (affected > Server.DrawReloadLimit) { - method = M_PSetTile; - return true; - } else { - method = lvl.bufferblocks ? M_PBlockQueue : M_PBlockChange; - return false; - } - } - public virtual void SetMarks(Vec3S32[] marks) { Origin = marks[0]; Min = marks[0]; Max = marks[0]; for (int i = 1; i < marks.Length; i++) { @@ -97,63 +94,21 @@ namespace MCGalaxy.Drawing.Ops { TotalModified = 0; } - protected void PlaceBlock(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { + protected DrawOpBlock Place(ushort x, ushort y, ushort z, Brush brush) { Coords.X = x; Coords.Y = y; Coords.Z = z; - byte type = brush.NextBlock(this); - if (type == Block.Zero) return; - PlaceBlock(p, lvl, x, y, z, type, brush.NextExtBlock(this)); + Coords.Type = brush.NextBlock(this); + + if (Coords.Type != Block.Zero) + Coords.ExtType = brush.NextExtBlock(this); + return Coords; } - protected void PlaceBlock(Player p, Level lvl, ushort x, ushort y, ushort z, byte type, byte extType) { - Level.BlockPos bP = default(Level.BlockPos); - switch (method) { - case M_PBlockQueue: - if (!lvl.DoBlockchange(p, x, y, z, type, extType)) return; - bP.name = p.name; - bP.index = lvl.PosToInt(x, y, z); - bP.SetData(type, extType, type == 0); - - if (lvl.UseBlockDB) - lvl.blockCache.Add(bP); - BlockQueue.Addblock(p, bP.index, type, extType); - TotalModified++; - break; - case M_PBlockChange: - if (!lvl.DoBlockchange(p, x, y, z, type, extType)) return; - bP.name = p.name; - bP.index = lvl.PosToInt(x, y, z); - - bP.SetData(type, extType, type == 0); - if (lvl.UseBlockDB) - lvl.blockCache.Add(bP); - Player.GlobalBlockchange(lvl, x, y, z, type, extType); - TotalModified++; - break; - case M_PSetTile: - byte old = lvl.GetTile(x, y, z); - if (old == Block.Zero || !lvl.CheckAffectPermissions(p, x, y, z, old, type)) - return; - lvl.SetTile(x, y, z, type, p, extType); - p.loginBlocks++; - p.overallBlocks++; - TotalModified++; - break; - case M_BlockChange: - lvl.Blockchange(x, y, z, type, extType); - TotalModified++; - break; - case M_SetTile: - lvl.SetTile(x, y, z, type); - if (type == Block.custom_block) - lvl.SetExtTile(x, y, z, extType); - TotalModified++; - break; - } + protected DrawOpBlock Place(ushort x, ushort y, ushort z, byte type, byte extType) { + Coords.X = x; Coords.Y = y; Coords.Z = z; + Coords.Type = type; Coords.ExtType = extType; + return Coords; } - internal const int M_PBlockQueue = 0, M_PBlockChange = 1, M_PSetTile = 2; - internal const int M_BlockChange = 3, M_SetTile = 4; - protected Vec3U16 Clamp(Vec3S32 pos) { pos.X = Math.Max(0, Math.Min(pos.X, Level.Width - 1)); pos.Y = Math.Max(0, Math.Min(pos.Y, Level.Height - 1)); diff --git a/Drawing/DrawOps/FillDrawOp.cs b/Drawing/DrawOps/FillDrawOp.cs index c420082cc..28fac675c 100644 --- a/Drawing/DrawOps/FillDrawOp.cs +++ b/Drawing/DrawOps/FillDrawOp.cs @@ -41,11 +41,12 @@ namespace MCGalaxy.Drawing.Ops { return true; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { ushort x, y, z; - foreach (int pos in Positions) { + for (int i = 0; i < Positions.Count; i++) { + int pos = Positions[i]; lvl.IntToPos(pos, out x, out y, out z); - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } diff --git a/Drawing/DrawOps/LineDrawOp.cs b/Drawing/DrawOps/LineDrawOp.cs index 777d295f7..97f2f42d7 100644 --- a/Drawing/DrawOps/LineDrawOp.cs +++ b/Drawing/DrawOps/LineDrawOp.cs @@ -40,7 +40,7 @@ namespace MCGalaxy.Drawing.Ops { } } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(marks[0]), p2 = Clamp(marks[1]); List buffer = new List(); DrawLine(p1.X, p1.Y, p1.Z, MaxLength, p2.X, p2.Y, p2.Z, buffer); @@ -53,9 +53,9 @@ namespace MCGalaxy.Drawing.Ops { FillPos pos = buffer[i]; if (WallsMode) { for (ushort yy = p1.Y; yy <= p2.Y; yy++) - PlaceBlock(p, lvl, pos.X, yy, pos.Z, brush); + yield return Place(pos.X, yy, pos.Z, brush); } else { - PlaceBlock(p, lvl, pos.X, pos.Y, pos.Z, brush); + yield return Place(pos.X, pos.Y, pos.Z, brush); } } } diff --git a/Drawing/DrawOps/MazeDrawOp.cs b/Drawing/DrawOps/MazeDrawOp.cs index 9eed38f9e..1f30b5220 100644 --- a/Drawing/DrawOps/MazeDrawOp.cs +++ b/Drawing/DrawOps/MazeDrawOp.cs @@ -39,7 +39,7 @@ namespace MCGalaxy.Drawing.Ops { return lenX * lenZ * 3; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { width = Max.X - Min.X; if (width % 2 != 0) { width++; Min.X--; } width -= 2; @@ -48,7 +48,7 @@ namespace MCGalaxy.Drawing.Ops { length -= 2; if (width <= 0 || length <= 0) { - Player.Message(p, "The corners of the maze need to be further apart."); return; + Player.Message(p, "The corners of the maze need to be further apart."); yield break; } Player.Message(p, "Generating maze... this could take a while"); //substract 2 cause we will just make the inner. the outer wall is made seperately @@ -89,22 +89,30 @@ namespace MCGalaxy.Drawing.Ops { for (ushort zz = 0; zz <= length; zz++) if (wall[xx, zz]) { - PlaceBlock(p, lvl, (ushort)(xx + min.X + 1), y, (ushort)(zz + min.Z + 1), Block.staircasefull, 0); - PlaceBlock(p, lvl, (ushort)(xx + min.X + 1), (ushort)(y + 1), (ushort)(zz + min.Z + 1), Block.leaf, 0); - PlaceBlock(p, lvl, (ushort)(xx + min.X + 1), (ushort)(y + 2), (ushort)(zz + min.Z + 1), Block.leaf, 0); + yield return Place((ushort)(xx + min.X + 1), y, (ushort)(zz + min.Z + 1), Block.staircasefull, 0); + yield return Place((ushort)(xx + min.X + 1), (ushort)(y + 1), (ushort)(zz + min.Z + 1), Block.leaf, 0); + yield return Place((ushort)(xx + min.X + 1), (ushort)(y + 2), (ushort)(zz + min.Z + 1), Block.leaf, 0); } brush = new SolidBrush(Block.staircasefull, 0); - QuadX(min.X, y, min.Z, y, max.Z, p, lvl, brush); - QuadX(max.X, y, min.Z, y, max.Z, p, lvl, brush); - QuadZ(min.Z, y, min.X, y, max.X, p, lvl, brush); - QuadZ(max.Z, y, min.X, y, max.X, p, lvl, brush); + foreach (var block in QuadX(min.X, y, min.Z, y, max.Z, brush)) + yield return block; + foreach (var block in QuadX(max.X, y, min.Z, y, max.Z, brush)) + yield return block; + foreach (var block in QuadZ(min.Z, y, min.X, y, max.X, brush)) + yield return block; + foreach (var block in QuadZ(max.Z, y, min.X, y, max.X, brush)) + yield return block; brush = new SolidBrush(Block.leaf, 0); - QuadX(min.X, (ushort)(y + 1), min.Z, (ushort)(y + 2), max.Z, p, lvl, brush); - QuadX(max.X, (ushort)(y + 1), min.Z, (ushort)(y + 2), max.Z, p, lvl, brush); - QuadZ(min.Z, (ushort)(y + 1), min.X, (ushort)(y + 2), max.X, p, lvl, brush); - QuadZ(max.Z, (ushort)(y + 1), min.X, (ushort)(y + 2), max.X, p, lvl, brush); + foreach (var block in QuadX(min.X, (ushort)(y + 1), min.Z, (ushort)(y + 2), max.Z, brush)) + yield return block; + foreach (var block in QuadX(max.X, (ushort)(y + 1), min.Z, (ushort)(y + 2), max.Z, brush)) + yield return block; + foreach (var block in QuadZ(min.Z, (ushort)(y + 1), min.X, (ushort)(y + 2), max.X, brush)) + yield return block; + foreach (var block in QuadZ(max.Z, (ushort)(y + 1), min.X, (ushort)(y + 2), max.X, brush)) + yield return block; Player.Message(p, "Maze painted. Build the entrance and exit yourself"); randomizer = 0; diff --git a/Drawing/DrawOps/PasteDrawOp.cs b/Drawing/DrawOps/PasteDrawOp.cs index 9113415fd..16c42597c 100644 --- a/Drawing/DrawOps/PasteDrawOp.cs +++ b/Drawing/DrawOps/PasteDrawOp.cs @@ -31,7 +31,7 @@ namespace MCGalaxy.Drawing.Ops { return CopyState.UsedBlocks; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { CopyState state = CopyState; bool pasteAir = state.PasteAir; // Adjust for the fact that paste origin may be outside the map. @@ -48,7 +48,7 @@ namespace MCGalaxy.Drawing.Ops { bool place = lvl.InBound(x, y, z) && (b != type || (b == Block.custom_block && extB != extType)); if ((b != Block.air || pasteAir) && place) - PlaceBlock(p, lvl, x, y, z, b, extB); + yield return Place(x, y, z, b, extB); } } } @@ -64,7 +64,7 @@ namespace MCGalaxy.Drawing.Ops { return CopyState.UsedBlocks; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(marks[0]); CopyState state = CopyState; bool pasteAir = state.PasteAir; @@ -92,14 +92,14 @@ namespace MCGalaxy.Drawing.Ops { } } if (!place) continue; - PlaceBlock(p, lvl, x, y, z, b, extB); + yield return Place(x, y, z, b, extB); } if (include != null) { for (int j = 0; j < include.Length; j++) { ExtBlock block = include[j]; if (b == block.Type && (b != Block.custom_block || extB == block.ExtType)) { - PlaceBlock(p, lvl, x, y, z, b, extB); break; + yield return Place(x, y, z, b, extB); break; } } } diff --git a/Drawing/DrawOps/PyramidDrawOp.cs b/Drawing/DrawOps/PyramidDrawOp.cs index 830f59f55..b10e4ad17 100644 --- a/Drawing/DrawOps/PyramidDrawOp.cs +++ b/Drawing/DrawOps/PyramidDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -29,10 +30,6 @@ namespace MCGalaxy.Drawing.Ops { this.yDir = yDir; } - public override bool DetermineDrawOpMethod(Level lvl, long affected) { - return baseOp.DetermineDrawOpMethod(lvl, affected); - } - public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { Vec3S32 oMin = Min, oMax = Max; baseOp.Min = oMin; baseOp.Max = oMax; @@ -52,14 +49,16 @@ namespace MCGalaxy.Drawing.Ops { return total; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3S32 p1 = Min, p2 = Max; baseOp.Level = Level; while (true) { - baseOp.Perform(marks, p, lvl, brush); + foreach (var block in baseOp.Perform(marks, p, lvl, brush)) + yield return block; if (p1.Y >= lvl.Height || Math.Abs(p2.X - p1.X) <= 1 || Math.Abs(p2.Z - p1.Z) <= 1) - break; + yield break; + p1.X++; p2.X--; p1.Z++; p2.Z--; p1.Y = (ushort)(p1.Y + yDir); p2.Y = p1.Y; @@ -95,22 +94,25 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Pyramid reverse"; } } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); wallOp.Min = Min; wallOp.Max = Max; baseOp.Min = Min; baseOp.Max = Max; wallOp.Level = Level; baseOp.Level = Level; while (true) { - wallOp.Perform(marks, p, lvl, brush); + foreach (var block in wallOp.Perform(marks, p, lvl, brush)) + yield return block; if (p1.Y >= lvl.Height || Math.Abs(p2.X - p1.X) <= 1 || Math.Abs(p2.Z - p1.Z) <= 1) - break; + yield break; + p1.X++; p2.X--; p1.Z++; p2.Z--; wallOp.Min = p1; wallOp.Max = p2; baseOp.Min = p1; baseOp.Max = p2; - baseOp.Perform(marks, p, lvl, airBrush); + foreach (var block in baseOp.Perform(marks, p, lvl, airBrush)) + yield return block; p1.Y = (ushort)(p1.Y + yDir); p2.Y = p1.Y; wallOp.Min = p1; wallOp.Max = p2; baseOp.Min = p1; baseOp.Max = p2; diff --git a/Drawing/DrawOps/RedoDrawOp.cs b/Drawing/DrawOps/RedoDrawOp.cs index af16868d9..7bef07228 100644 --- a/Drawing/DrawOps/RedoDrawOp.cs +++ b/Drawing/DrawOps/RedoDrawOp.cs @@ -35,10 +35,10 @@ namespace MCGalaxy.Drawing.Ops { public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { return -1; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { UndoCache cache = p.UndoBuffer; UndoCacheNode node = cache.Tail; - if (node == null) return; + if (node == null) yield break; int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; while (node != null) { @@ -56,7 +56,7 @@ namespace MCGalaxy.Drawing.Ops { DateTime time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); if (time > End) continue; - if (time < Start) { buffer.CheckIfSend(true); return; } + if (time < Start) { buffer.CheckIfSend(true); yield break; } byte tile, extTile; item.GetBlock(out tile, out extTile); @@ -68,6 +68,7 @@ namespace MCGalaxy.Drawing.Ops { buffer.CheckIfSend(true); node = node.Prev; } + yield break; } } } diff --git a/Drawing/DrawOps/ReplaceDrawOp.cs b/Drawing/DrawOps/ReplaceDrawOp.cs index 55270b3ba..c419e5c39 100644 --- a/Drawing/DrawOps/ReplaceDrawOp.cs +++ b/Drawing/DrawOps/ReplaceDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -34,7 +35,7 @@ namespace MCGalaxy.Drawing.Ops { return (Max.X - Min.X + 1) * (Max.Y - Min.Y + 1) * (Max.Z - Min.Z + 1); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) for (ushort z = p1.Z; z <= p2.Z; z++) @@ -44,7 +45,7 @@ namespace MCGalaxy.Drawing.Ops { if (tile == Block.custom_block) extTile = lvl.GetExtTile(x, y, z); if (tile == Include.Type && (tile != Block.custom_block || extTile == Include.ExtType)) - PlaceBlock(p, lvl, x, y, z, brush); + yield return Place(x, y, z, brush); } } } @@ -63,7 +64,7 @@ namespace MCGalaxy.Drawing.Ops { return (Max.X - Min.X + 1) * (Max.Y - Min.Y + 1) * (Max.Z - Min.Z + 1); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) for (ushort z = p1.Z; z <= p2.Z; z++) @@ -72,9 +73,8 @@ namespace MCGalaxy.Drawing.Ops { byte tile = lvl.GetTile(x, y, z), extTile = 0; if (tile == Block.custom_block) extTile = lvl.GetExtTile(x, y, z); - if (tile != Exclude.Type || (tile == Block.custom_block && extTile != Exclude.ExtType)) { - PlaceBlock(p, lvl, x, y, z, brush); - } + if (tile != Exclude.Type || (tile == Block.custom_block && extTile != Exclude.ExtType)) + yield return Place(x, y, z, brush); } } } diff --git a/Drawing/DrawOps/SpheroidDrawOp.cs b/Drawing/DrawOps/SpheroidDrawOp.cs index 0465a3c0a..bd1e07d8e 100644 --- a/Drawing/DrawOps/SpheroidDrawOp.cs +++ b/Drawing/DrawOps/SpheroidDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -29,7 +30,7 @@ namespace MCGalaxy.Drawing.Ops { return (int)(Math.PI * 4.0/3.0 * rx * ry * rz); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { /* Courtesy of fCraft's awesome Open-Source'ness :D */ double cx = (Min.X + Max.X) / 2.0, cy = (Min.Y + Max.Y) / 2.0, cz = (Min.Z + Max.Z) / 2.0; double rx = (Max.X - Min.X) / 2.0 + 0.25, ry = (Max.Y - Min.Y) / 2.0 + 0.25, rz = (Max.Z - Min.Z) / 2.0 + 0.25; @@ -42,7 +43,7 @@ namespace MCGalaxy.Drawing.Ops { { double dx = xx - cx, dy = yy - cy, dz = zz - cz; if ((dx * dx) * rx2 + (dy * dy) * ry2 + (dz * dz) * rz2 <= 1) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } @@ -56,7 +57,7 @@ namespace MCGalaxy.Drawing.Ops { return (int)(Math.PI * 4.0/3.0 * rx * ry * rz); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { /* Courtesy of fCraft's awesome Open-Source'ness :D */ double cx = (Min.X + Max.X) / 2.0, cy = (Min.Y + Max.Y) / 2.0, cz = (Min.Z + Max.Z) / 2.0; double rx = (Max.X - Min.X) / 2.0 + 0.25, ry = (Max.Y - Min.Y) / 2.0 + 0.25, rz = (Max.Z - Min.Z) / 2.0 + 0.25; @@ -75,7 +76,7 @@ namespace MCGalaxy.Drawing.Ops { dx *= dx; dy *= dy; dz *= dz; bool inRange = dx * rx2 + dy * ry2 + dz * rz2 <= 1; if (inRange && (dx * smallrx2 + dy * smallry2 + dz * smallrz2 > 1)) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } @@ -90,7 +91,7 @@ namespace MCGalaxy.Drawing.Ops { return (int)(Math.PI * rx * rz * height); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { /* Courtesy of fCraft's awesome Open-Source'ness :D */ double cx = (Min.X + Max.X) / 2.0, cz = (Min.Z + Max.Z) / 2.0; double rx = (Max.X - Min.X) / 2.0 + 0.25, rz = (Max.Z - Min.Z) / 2.0 + 0.25; @@ -107,7 +108,7 @@ namespace MCGalaxy.Drawing.Ops { dx *= dx; dz *= dz; bool inRange = dx * rx2 + dz * rz2 <= 1; if (inRange && (dx * smallrx2 + dz * smallrz2 > 1)) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } diff --git a/Drawing/DrawOps/TorusDrawOp.cs b/Drawing/DrawOps/TorusDrawOp.cs index be1211ec2..3848e7b6b 100644 --- a/Drawing/DrawOps/TorusDrawOp.cs +++ b/Drawing/DrawOps/TorusDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -30,7 +31,7 @@ namespace MCGalaxy.Drawing.Ops { return (int)(2 * Math.PI * Math.PI * rTube * rTube * rCentre); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { double cx = (Min.X + Max.X) / 2.0, cy = (Min.Y + Max.Y) / 2.0, cz = (Min.Z + Max.Z) / 2.0; double rx = (Max.X - Min.X) / 2.0 + 0.25, ry = (Max.Y - Min.Y) / 2.0 + 0.25, rz = (Max.Z - Min.Z) / 2.0 + 0.25; double rTube = ry, rCentre = Math.Min(rx, rz) - rTube; @@ -45,7 +46,7 @@ namespace MCGalaxy.Drawing.Ops { double dInner = rCentre - Math.Sqrt( dx + dz ); if (dInner * dInner + dy <= rTube * rTube * 0.5 + 0.25) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } diff --git a/Drawing/DrawOps/TreeDrawOp.cs b/Drawing/DrawOps/TreeDrawOp.cs index 38242b1ac..49220e90e 100644 --- a/Drawing/DrawOps/TreeDrawOp.cs +++ b/Drawing/DrawOps/TreeDrawOp.cs @@ -25,6 +25,7 @@ Ideas, concepts, and code were used from the following two sources: */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -42,13 +43,15 @@ namespace MCGalaxy.Drawing.Ops { public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { return -1; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { if (brush == null) brush = defBrush; Vec3U16 P = Clamp(marks[0]); - if (Type == T_Tree) AddTree(p, lvl, P.X, P.Y, P.Z, brush); - if (Type == T_NotchTree) AddNotchTree(p, lvl, P.X, P.Y, P.Z, brush); - if (Type == T_NotchSwamp) AddNotchSwampTree(p, lvl, P.X, P.Y, P.Z, brush); - if (Type == T_Cactus) AddCactus(p, lvl, P.X, P.Y, P.Z); + + if (Type == T_Tree) return AddTree(p, lvl, P.X, P.Y, P.Z, brush); + if (Type == T_NotchTree) return AddNotchTree(p, lvl, P.X, P.Y, P.Z, brush); + if (Type == T_NotchSwamp) return AddNotchSwampTree(p, lvl, P.X, P.Y, P.Z, brush); + if (Type == T_Cactus) return AddCactus(p, lvl, P.X, P.Y, P.Z); + return null; } public override void SetMarks(Vec3S32[] marks) { @@ -77,11 +80,11 @@ namespace MCGalaxy.Drawing.Ops { Max.X += size; Max.Z += size; } - void AddTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { + IEnumerable AddTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { for (ushort dy = 0; dy < top + height - 1; dy++) { ushort yy = (ushort)(y + dy); if (overwrite || lvl.GetTile(x, yy, z) == Block.air || (yy == y && lvl.GetTile(x, yy, z) == Block.shrub)) - PlaceBlock(p, lvl, x, yy, z, Block.trunk, 0); + yield return Place(x, yy, z, Block.trunk, 0); } for (short dy = (short)-top; dy <= top; ++dy) @@ -93,17 +96,17 @@ namespace MCGalaxy.Drawing.Ops { ushort xx = (ushort)(x + dx), yy = (ushort)(y + dy + height), zz = (ushort)(z + dz); if ((xx != x || zz != z || dy >= top - 1) && (overwrite || lvl.GetTile(xx, yy, zz) == Block.air)) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } - void AddNotchTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { + IEnumerable AddNotchTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { for (int dy = 0; dy <= height; dy++) { ushort yy = (ushort)(y + dy); byte tile = lvl.GetTile(x, yy, z); if (overwrite || tile == Block.air || (yy == y && tile == Block.shrub)) - PlaceBlock(p, lvl, x, yy, z, Block.trunk, 0); + yield return Place(x, yy, z, Block.trunk, 0); } for (int dy = top; dy <= height + 1; dy++) { @@ -120,20 +123,20 @@ namespace MCGalaxy.Drawing.Ops { if (dy > height) continue; if (random.Next(2) == 0) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } else { - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } } - void AddNotchSwampTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { + IEnumerable AddNotchSwampTree(Player p, Level lvl, ushort x, ushort y, ushort z, Brush brush) { for (int dy = 0; dy <= height; dy++) { ushort yy = (ushort)(y + dy); byte tile = lvl.GetTile(x, yy, z); if (overwrite || tile == Block.air || (yy == y && tile == Block.shrub)) - PlaceBlock(p, lvl, x, yy, z, Block.trunk, 0); + yield return Place(x, yy, z, Block.trunk, 0); } for (int dy = top; dy <= height + 1; dy++) { @@ -150,18 +153,18 @@ namespace MCGalaxy.Drawing.Ops { if (dy > height) continue; if (random.Next(2) == 0) - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } else { - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } } - void AddCactus(Player p, Level lvl, ushort x, ushort y, ushort z) { + IEnumerable AddCactus(Player p, Level lvl, ushort x, ushort y, ushort z) { for (ushort dy = 0; dy <= height; dy++) { if (overwrite || lvl.GetTile(z, (ushort)(y + dy), z) == Block.air) - PlaceBlock(p, lvl, x, (ushort)(y + dy), z, Block.green, 0); + yield return Place(x, (ushort)(y + dy), z, Block.green, 0); } int inX = 0, inZ = 0; @@ -173,11 +176,11 @@ namespace MCGalaxy.Drawing.Ops { for (ushort dy = height; dy <= random.Next(height + 2, height + 5); dy++) { if (overwrite || lvl.GetTile((ushort)(x + inX), (ushort)(y + dy), (ushort)(z + inZ)) == Block.air) - PlaceBlock(p, lvl, (ushort)(x + inX), (ushort)(y + dy), (ushort)(z + inZ), Block.green, 0); + yield return Place((ushort)(x + inX), (ushort)(y + dy), (ushort)(z + inZ), Block.green, 0); } for (ushort dy = height; dy <= random.Next(height + 2, height + 5); dy++) { if (overwrite || lvl.GetTile((ushort)(x - inX), (ushort)(y + dy), (ushort)(z - inZ)) == Block.air) - PlaceBlock(p, lvl, (ushort)(x - inX), (ushort)(y + dy), (ushort)(z - inZ), Block.green, 0); + yield return Place((ushort)(x - inX), (ushort)(y + dy), (ushort)(z - inZ), Block.green, 0); } } diff --git a/Drawing/DrawOps/TriangleDrawOp.cs b/Drawing/DrawOps/TriangleDrawOp.cs index 94a47a8ae..5ea1f3ea4 100644 --- a/Drawing/DrawOps/TriangleDrawOp.cs +++ b/Drawing/DrawOps/TriangleDrawOp.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { @@ -33,7 +34,7 @@ namespace MCGalaxy.Drawing.Ops { return (int)Math.Sqrt(s * (s - a) * (s - b) * (s - c)); } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3F32 V1 = marks[0], V2 = marks[1], V3 = marks[2]; Vec3F32 N = Vec3F32.Cross(V2 - V1, V3 - V1); N = Vec3F32.Normalise(N); @@ -64,9 +65,9 @@ namespace MCGalaxy.Drawing.Ops { float v = (dot00 * dot12 - dot01 * dot02) * invDenom; if (u >= 0 && v >= 0 && u + v <= 1) { - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } else if (Axis(P, V1, V2) || Axis(P, V1, V3) || Axis(P, V2, V3)) { - PlaceBlock(p, lvl, xx, yy, zz, brush); + yield return Place(xx, yy, zz, brush); } } } diff --git a/Drawing/DrawOps/UndoDrawOp.cs b/Drawing/DrawOps/UndoDrawOp.cs index 2eea3afb3..f45e78df1 100644 --- a/Drawing/DrawOps/UndoDrawOp.cs +++ b/Drawing/DrawOps/UndoDrawOp.cs @@ -42,11 +42,12 @@ namespace MCGalaxy.Drawing.Ops { public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { return -1; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { PerformUndo(p, ref saveLevel); bool foundUser = false; Vec3S32[] bounds = { Min, Max }; UndoFile.UndoPlayer(p, who.name.ToLower(), bounds, Start, ref foundUser); + yield break; } void PerformUndo(Player p, ref Level saveLvl) { @@ -106,9 +107,10 @@ namespace MCGalaxy.Drawing.Ops { public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { return -1; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3S32[] bounds = { Min, Max }; UndoFile.UndoPlayer(p, whoName.ToLower(), bounds, Start, ref foundUser); + yield break; } } @@ -120,7 +122,7 @@ namespace MCGalaxy.Drawing.Ops { public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { return -1; } - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { if (lvl.UndoBuffer.Count != Server.physUndo) { int count = lvl.currentUndo; for (int i = count; i >= 0; i--) { @@ -141,6 +143,7 @@ namespace MCGalaxy.Drawing.Ops { } catch { } } } + yield break; } bool CheckBlockPhysics(Player p, Level lvl, long seconds, int i) { diff --git a/Drawing/DrawOps/WriteDrawOp.cs b/Drawing/DrawOps/WriteDrawOp.cs index 289114236..cd19dcc4e 100644 --- a/Drawing/DrawOps/WriteDrawOp.cs +++ b/Drawing/DrawOps/WriteDrawOp.cs @@ -43,21 +43,26 @@ namespace MCGalaxy.Drawing.Ops { } int dirX, dirZ; - public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 pos; + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = Clamp(marks[0]), p2 = Clamp(marks[1]); if (Math.Abs(p2.X - p1.X) > Math.Abs(p2.Z - p1.Z)) dirX = p2.X > p1.X? 1 : -1; else dirZ = p2.Z > p1.Z ? 1 : -1; - foreach (char c in Text) - DrawLetter(p, lvl, c, ref p1.X, p1.Y, ref p1.Z, brush); + pos = p1; + + foreach (char c in Text) { + foreach (var block in DrawLetter(p, lvl, c, brush)) + yield return block; + } } - void DrawLetter(Player p, Level lvl, char c, ref ushort x, ushort y, ref ushort z, Brush brush) { + IEnumerable DrawLetter(Player p, Level lvl, char c, Brush brush) { if ((int)c >= 256 || letters[(int)c] == null) { Player.Message(p, "\"" + c + "\" is not currently supported, replacing with space."); - x = (ushort)(x + dirX * 4 * Scale); - z = (ushort)(z + dirZ * 4 * Scale); + pos.X = (ushort)(pos.X + dirX * 4 * Scale); + pos.Z = (ushort)(pos.Z + dirZ * 4 * Scale); } else { byte[] flags = letters[(int)c]; for (int i = 0; i < flags.Length; i++) { @@ -68,16 +73,16 @@ namespace MCGalaxy.Drawing.Ops { for (int ver = 0; ver < Scale; ver++) for (int hor = 0; hor < Scale; hor++) { - int xx = x + dirX * hor, yy = y + j * Scale + ver, zz = z + dirZ * hor; - PlaceBlock(p, lvl, (ushort)xx, (ushort)yy, (ushort)zz, brush); + int x = pos.X + dirX * hor, y = pos.Y + j * Scale + ver, z = pos.Z + dirZ * hor; + yield return Place((ushort)x, (ushort)y, (ushort)z, brush); } } - x = (ushort)(x + dirX * Scale); - z = (ushort)(z + dirZ * Scale); + pos.X = (ushort)(pos.X + dirX * Scale); + pos.Z = (ushort)(pos.Z + dirZ * Scale); } } - x = (ushort)(x + dirX * Spacing); - z = (ushort)(z + dirZ * Spacing); + pos.X = (ushort)(pos.X + dirX * Spacing); + pos.Z = (ushort)(pos.Z + dirZ * Spacing); } static int HighestBit(int value) { diff --git a/Generator/RealisticMapGen.cs b/Generator/RealisticMapGen.cs index f9896824e..3708b15aa 100644 --- a/Generator/RealisticMapGen.cs +++ b/Generator/RealisticMapGen.cs @@ -52,7 +52,6 @@ namespace MCGalaxy { treeDrawer = new TreeDrawOp(); treeDrawer.Level = Lvl; treeDrawer.random = rand; - treeDrawer.method = DrawOp.M_SetTile; treeCoords = new Vec3S32[1]; } @@ -149,7 +148,9 @@ namespace MCGalaxy { treeDrawer.Type = genParams.UseCactus ? TreeDrawOp.T_Cactus : TreeDrawOp.T_Tree; treeCoords[0].X = x; treeCoords[0].Y = (ushort)(y + 1); treeCoords[0].Z = z; treeDrawer.SetMarks(treeCoords); - treeDrawer.Perform(treeCoords, null, Lvl, null); + + foreach (var block in treeDrawer.Perform(treeCoords, null, Lvl, null)) + Lvl.SetTile(block.X, block.Y, block.Z, block.Type); } } } diff --git a/Levels/Level.Physics.cs b/Levels/Level.Physics.cs index 4cd3823ff..0d8dc73c3 100644 --- a/Levels/Level.Physics.cs +++ b/Levels/Level.Physics.cs @@ -153,7 +153,7 @@ namespace MCGalaxy { for (int i = 0; i < ListCheck.Count; i++) { Check C = ListCheck.Items[i]; IntToPos(C.b, out x, out y, out z); - try { + //try { if (PhysicsUpdate != null) PhysicsUpdate(x, y, z, C.data, this); if (OnPhysicsUpdateEvent.events.Count > 0) @@ -167,10 +167,10 @@ namespace MCGalaxy { C.data.Data = 255; } ListCheck.Items[i] = C; - } catch { - listCheckExists.Set(x, y, z, false); - ListCheck.RemoveAt(i); - } + //} catch { + // listCheckExists.Set(x, y, z, false); + // ListCheck.RemoveAt(i); + // } } } RemoveExpiredChecks(); @@ -181,14 +181,14 @@ namespace MCGalaxy { for (int i = 0; i < ListUpdate.Count; i++) { Update C = ListUpdate.Items[i]; - try { + //try { byte type = C.data.Data; C.data.Data = 0; if (DoPhysicsBlockchange(C.b, type, false, C.data, 0, true)) bulkSender.Add(C.b, type, 0); - } catch { - Server.s.Log("Phys update issue"); - } + //} catch { + // Server.s.Log("Phys update issue"); + // } bulkSender.CheckIfSend(false); } if (bulkSender != null) diff --git a/Levels/Physics/OtherPhysics.cs b/Levels/Physics/OtherPhysics.cs index aefd01ef9..84335899d 100644 --- a/Levels/Physics/OtherPhysics.cs +++ b/Levels/Physics/OtherPhysics.cs @@ -122,10 +122,10 @@ namespace MCGalaxy.BlockPhysics { TreeDrawOp op = new TreeDrawOp(); op.random = rand; - op.method = DrawOp.M_BlockChange; Vec3S32[] marks = new [] { new Vec3S32(x, y, z) }; op.SetMarks(marks); - op.Perform(marks, null, lvl, null); + foreach (var block in op.Perform(marks, null, lvl, null)) + lvl.Blockchange(block.X, block.Y, block.Z, 0); C.data.Data = 255; } diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 51f99cd74..b2c75b111 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -476,7 +476,6 @@ - @@ -579,6 +578,7 @@ + diff --git a/Levels/BufferedBlockSender.cs b/util/BufferedBlockSender.cs similarity index 100% rename from Levels/BufferedBlockSender.cs rename to util/BufferedBlockSender.cs