Rewrite /imageprint to be a drawop. This means the output can now be affected by /transform.

This commit is contained in:
UnknownShadow200 2016-08-31 00:11:02 +10:00
parent 4e271d1ede
commit e29a3d31c6
7 changed files with 98 additions and 85 deletions

View File

@ -121,25 +121,13 @@ namespace MCGalaxy.Commands.Building {
op.Source = bmp; op.Source = bmp;
op.Layer = dArgs.layer; op.Layer = dArgs.layer;
op.Mode = dArgs.popType; op.Mode = dArgs.popType;
op.Filename = dArgs.name;
if (op.Layer) { if (op.Layer) {
if (op.Mode == 1) op.Mode = 2; if (op.Mode == 1) op.Mode = 2;
if (op.Mode == 3) op.Mode = 4; if (op.Mode == 3) op.Mode = 4;
} }
DrawOp.DoDrawOp(op, null, p, m, false);
BufferedBlockSender buffer = new BufferedBlockSender(op.Level);
foreach (var b in op.Perform(m, p, p.level, null)) {
if (b.Block == Block.Zero) continue;
if (!op.Level.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) continue;
int index = op.Level.PosToInt(b.X, b.Y, b.Z);
op.Level.AddToBlockDB(p, index, b.Block, b.ExtBlock, b.Block == 0);
buffer.Add(index, b.Block, b.ExtBlock);
}
buffer.Send(true);
if (dArgs.name == "tempImage_" + p.name)
File.Delete("extra/images/tempImage_" + p.name + ".bmp");
Player.Message(p, "Finished printing image using " + ImagePalette.Names[op.Mode]);
} }
public override void Help(Player p) { public override void Help(Player p) {

View File

@ -53,7 +53,7 @@ namespace MCGalaxy.Drawing.Ops {
} }
long affected = op.BlocksAffected(op.Level, marks); long affected = op.BlocksAffected(op.Level, marks);
if (p != null && op.AffectedByTransform) if (p != null && op.AffectedByTransform)
p.Transform.GetBlocksAffected(ref affected); p.Transform.GetBlocksAffected(ref affected);
if (checkLimit && !op.CanDraw(marks, p, affected)) if (checkLimit && !op.CanDraw(marks, p, affected))
@ -73,13 +73,8 @@ namespace MCGalaxy.Drawing.Ops {
static void AppendDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks, long affected) { static void AppendDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks, long affected) {
if (p == null) { if (p == null) {
BufferedBlockSender buffer = new BufferedBlockSender(op.Level); BufferedBlockSender buffer = new BufferedBlockSender(op.Level);
foreach (var b in op.Perform(marks, p, op.Level, brush)) { op.Perform(marks, p, op.Level, brush,
int index = op.Level.PosToInt(b.X, b.Y, b.Z); b => ConsoleOutputBlock(b, op.Level, buffer));
if (!op.Level.DoPhysicsBlockchange(index, b.Block, false,
default(PhysicsArgs), b.ExtBlock)) continue;
buffer.Add(index, b.Block, b.ExtBlock);
}
buffer.Send(true); buffer.Send(true);
return; return;
} }
@ -99,6 +94,13 @@ namespace MCGalaxy.Drawing.Ops {
ProcessDrawOps(p); ProcessDrawOps(p);
} }
static void ConsoleOutputBlock(DrawOpBlock b, Level lvl, BufferedBlockSender buffer) {
int index = lvl.PosToInt(b.X, b.Y, b.Z);
if (!lvl.DoPhysicsBlockchange(index, b.Block, false,
default(PhysicsArgs), b.ExtBlock)) return;
buffer.Add(index, b.Block, b.ExtBlock);
}
static void ProcessDrawOps(Player p) { static void ProcessDrawOps(Player p) {
while (true) { while (true) {
PendingDrawOp item; PendingDrawOp item;
@ -138,44 +140,56 @@ namespace MCGalaxy.Drawing.Ops {
static void DoDrawOp(PendingDrawOp item, Player p) { static void DoDrawOp(PendingDrawOp item, Player p) {
Level lvl = item.Level; Level lvl = item.Level;
IEnumerable<DrawOpBlock> iterator = null; Action<DrawOpBlock, Player, Level> output = null;
if (item.Op.AffectedByTransform)
iterator = p.Transform.Perform(item.Marks, p, lvl, item.Op, item.Brush);
else
iterator = item.Op.Perform(item.Marks, p, lvl, item.Brush);
if (item.Affected > Server.DrawReloadLimit) { if (item.Affected > Server.DrawReloadLimit) {
foreach (var b in iterator) { output = SetTileOutput;
if (b.Block == Block.Zero) continue;
byte old = lvl.GetTile(b.X, b.Y, b.Z);
bool sameBlock = old == b.Block;
if (sameBlock && b.Block == Block.custom_block)
sameBlock = lvl.GetExtTile(b.X, b.Y, b.Z) == b.ExtBlock;
if (sameBlock || old == Block.Zero || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block, b.ExtBlock))
continue;
lvl.SetTile(b.X, b.Y, b.Z, b.Block, p, b.ExtBlock);
p.IncrementBlockStats(b.Block, true);
}
} else if (item.Level.bufferblocks) { } else if (item.Level.bufferblocks) {
foreach (var b in iterator) { output = BufferedOutput;
if (b.Block == Block.Zero) continue;
if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) continue;
int index = lvl.PosToInt(b.X, b.Y, b.Z);
lvl.AddToBlockDB(p, index, b.Block, b.ExtBlock, b.Block == 0);
BlockQueue.Addblock(p, index, b.Block, b.ExtBlock);
}
} else { } else {
foreach (var b in iterator) { output = SlowOutput;
if (b.Block == Block.Zero) continue;
if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) continue;
int index = lvl.PosToInt(b.X, b.Y, b.Z);
lvl.AddToBlockDB(p, index, b.Block, b.ExtBlock, b.Block == 0);
Player.GlobalBlockchange(lvl, b.X, b.Y, b.Z, b.Block, b.ExtBlock);
}
} }
if (item.Op.AffectedByTransform) {
p.Transform.Perform(item.Marks, p, lvl, item.Op, item.Brush,
b => output(b, p, lvl));
} else {
item.Op.Perform(item.Marks, p, lvl, item.Brush,
b => output(b, p, lvl));
}
}
static void SetTileOutput(DrawOpBlock b, Player p, Level lvl) {
if (b.Block == Block.Zero) return;
byte old = lvl.GetTile(b.X, b.Y, b.Z);
if (old == Block.Zero) return;
bool same = old == b.Block;
if (same && b.Block == Block.custom_block)
same = lvl.GetExtTile(b.X, b.Y, b.Z) == b.ExtBlock;
if (same || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block, b.ExtBlock))
return;
lvl.SetTile(b.X, b.Y, b.Z, b.Block, p, b.ExtBlock);
p.IncrementBlockStats(b.Block, true);
}
static void BufferedOutput(DrawOpBlock b, Player p, Level lvl) {
if (b.Block == Block.Zero) return;
if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) return;
int index = lvl.PosToInt(b.X, b.Y, b.Z);
lvl.AddToBlockDB(p, index, b.Block, b.ExtBlock, b.Block == 0);
BlockQueue.Addblock(p, index, b.Block, b.ExtBlock);
}
static void SlowOutput(DrawOpBlock b, Player p, Level lvl) {
if (b.Block == Block.Zero) return;
if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) return;
int index = lvl.PosToInt(b.X, b.Y, b.Z);
lvl.AddToBlockDB(p, index, b.Block, b.ExtBlock, b.Block == 0);
Player.GlobalBlockchange(lvl, b.X, b.Y, b.Z, b.Block, b.ExtBlock);
} }
static void DoReload(Player p, Level lvl) { static void DoReload(Player p, Level lvl) {
@ -186,6 +200,6 @@ namespace MCGalaxy.Drawing.Ops {
} }
GC.Collect(); GC.Collect();
GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
} }
} }
} }

View File

@ -17,6 +17,7 @@
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Draw = System.Drawing; using Draw = System.Drawing;
using MCGalaxy.Drawing.Brushes; using MCGalaxy.Drawing.Brushes;
@ -32,6 +33,7 @@ namespace MCGalaxy.Drawing.Ops {
internal Draw.Bitmap Source; internal Draw.Bitmap Source;
internal int Mode, Direction; internal int Mode, Direction;
internal bool Layer; internal bool Layer;
internal string Filename;
public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush, Action<DrawOpBlock> output) { public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush, Action<DrawOpBlock> output) {
Vec3U16 p0 = Clamp(marks[0]); Vec3U16 p0 = Clamp(marks[0]);
@ -69,7 +71,12 @@ namespace MCGalaxy.Drawing.Ops {
if (col.A < 20) cur.Block = Block.air; if (col.A < 20) cur.Block = Block.air;
output(Place(X, Y, Z, cur.Block, 0)); output(Place(X, Y, Z, cur.Block, 0));
} }
Source.Dispose();
Source = null; Source = null;
if (Filename == "tempImage_" + p.name)
File.Delete("extra/images/tempImage_" + p.name + ".bmp");
Player.Message(p, "Finished printing image using " + ImagePalette.Names[Mode]);
} }
void CalcMul(bool layer, int dir, void CalcMul(bool layer, int dir,

View File

@ -26,9 +26,9 @@ namespace MCGalaxy.Drawing.Transforms {
public override string Name { get { return "None"; } } public override string Name { get { return "None"; } }
public static NoTransform Instance = new NoTransform(); public static NoTransform Instance = new NoTransform();
public override IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p, public override void Perform(Vec3S32[] marks, Player p, Level lvl,
Level lvl, DrawOp op, Brush brush) { DrawOp op, Brush brush, Action<DrawOpBlock> output) {
return op.Perform(marks, p, lvl, brush); op.Perform(marks, p, lvl, brush, output);
} }
} }
@ -37,6 +37,9 @@ namespace MCGalaxy.Drawing.Transforms {
public override string Name { get { return "Scale"; } } public override string Name { get { return "Scale"; } }
public bool CentreOrigin; public bool CentreOrigin;
public int XMul, XDiv, YMul, YDiv, ZMul, ZDiv; public int XMul, XDiv, YMul, YDiv, ZMul, ZDiv;
int dirX, dirY, dirZ;
int width, height, length;
Vec3S32 P;
public override void GetBlocksAffected(ref long affected) { public override void GetBlocksAffected(ref long affected) {
// NOTE: We do not the actual size of the drawop on each axis, so we take // NOTE: We do not the actual size of the drawop on each axis, so we take
@ -45,10 +48,12 @@ namespace MCGalaxy.Drawing.Transforms {
affected = Math.Max(x, Math.Max(y, z)); affected = Math.Max(x, Math.Max(y, z));
} }
public override IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p, public override void Perform(Vec3S32[] marks, Player p, Level lvl,
Level lvl, DrawOp op, Brush brush) { DrawOp op, Brush brush, Action<DrawOpBlock> output) {
Vec3S32 P = (op.Min + op.Max) / 2; P = (op.Min + op.Max) / 2;
int dirX = 1, dirY = 1, dirZ = 1; dirX = 1; dirY = 1; dirZ = 1;
width = lvl.Width; height = lvl.Height; length = lvl.Length;
if (!CentreOrigin) { if (!CentreOrigin) {
// Guess the direction in which we should be scaling - // Guess the direction in which we should be scaling -
// for simplicity we assume we are scaling in positive direction // for simplicity we assume we are scaling in positive direction
@ -56,21 +61,21 @@ namespace MCGalaxy.Drawing.Transforms {
dirX = op.Min.X == op.Max.X ? 1 : (P.X == op.Max.X ? -1 : 1); dirX = op.Min.X == op.Max.X ? 1 : (P.X == op.Max.X ? -1 : 1);
dirY = op.Min.Y == op.Max.Y ? 1 : (P.Y == op.Max.Y ? -1 : 1); dirY = op.Min.Y == op.Max.Y ? 1 : (P.Y == op.Max.Y ? -1 : 1);
dirZ = op.Min.Z == op.Max.Z ? 1 : (P.Z == op.Max.Z ? -1 : 1); dirZ = op.Min.Z == op.Max.Z ? 1 : (P.Z == op.Max.Z ? -1 : 1);
} }
op.Perform(marks, p, lvl, brush, b => OutputBlock(b, output));
}
void OutputBlock(DrawOpBlock b, Action<DrawOpBlock> output) {
int dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z;
foreach (DrawOpBlock b in op.Perform(marks, p, lvl, brush)) { // Scale out until we hit the next block
int dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z; for (int y = P.Y + dy * YMul / YDiv; y != P.Y + (dy + dirY) * YMul / YDiv; y += dirY)
DrawOpBlock cur = b; for (int z = P.Z + dz * ZMul / ZDiv; z != P.Z + (dz + dirZ) * ZMul / ZDiv; z += dirZ)
for (int x = P.X + dx * XMul / XDiv; x != P.X + (dx + dirX) * XMul / XDiv; x += dirX)
// Scale out until we hit the next block {
for (int y = P.Y + dy * YMul / YDiv; y != P.Y + (dy + dirY) * YMul / YDiv; y += dirY) if (x < 0 || y < 0 || z < 0 || x >= width || y >= height || z >= length) continue;
for (int z = P.Z + dz * ZMul / ZDiv; z != P.Z + (dz + dirZ) * ZMul / ZDiv; z += dirZ) b.X = (ushort)x; b.Y = (ushort)y; b.Z = (ushort)z;
for (int x = P.X + dx * XMul / XDiv; x != P.X + (dx + dirX) * XMul / XDiv; x += dirX) output(b);
{
if (!lvl.IsValidPos(x, y, z)) continue;
cur.X = (ushort)x; cur.Y = (ushort)y; cur.Z = (ushort)z;
yield return cur;
}
} }
} }
} }

View File

@ -33,7 +33,7 @@ namespace MCGalaxy.Drawing.Transforms {
/// <summary> Performs calcuations (if necessary) for the given drawop. </summary> /// <summary> Performs calcuations (if necessary) for the given drawop. </summary>
public virtual void Configure(DrawOp op, Player p) { } public virtual void Configure(DrawOp op, Player p) { }
public abstract IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p, public abstract void Perform(Vec3S32[] marks, Player p, Level lvl,
Level lvl, DrawOp op, Brush brush); DrawOp op, Brush brush, Action<DrawOpBlock> output);
} }
} }

View File

@ -147,8 +147,8 @@ namespace MCGalaxy.Generator {
treeCoords[0].X = x; treeCoords[0].Y = (ushort)(y + 1); treeCoords[0].Z = z; treeCoords[0].X = x; treeCoords[0].Y = (ushort)(y + 1); treeCoords[0].Z = z;
treeDrawer.SetMarks(treeCoords); treeDrawer.SetMarks(treeCoords);
foreach (var block in treeDrawer.Perform(treeCoords, null, Lvl, null)) treeDrawer.Perform(treeCoords, null, Lvl, null,
Lvl.SetTile(block.X, block.Y, block.Z, block.Block); b => Lvl.SetTile(b.X, b.Y, b.Z, b.Block));
} }
} }
} }

View File

@ -126,9 +126,8 @@ namespace MCGalaxy.BlockPhysics {
Vec3S32[] marks = new [] { new Vec3S32(x, y, z) }; Vec3S32[] marks = new [] { new Vec3S32(x, y, z) };
op.SetMarks(marks); op.SetMarks(marks);
foreach (var block in op.Perform(marks, null, lvl, null)) { op.Perform(marks, null, lvl, null,
lvl.Blockchange(block.X, block.Y, block.Z, block.Block); b => lvl.Blockchange(b.X, b.Y, b.Z, b.Block));
}
C.data.Data = 255; C.data.Data = 255;
} }