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.Layer = dArgs.layer;
op.Mode = dArgs.popType;
op.Filename = dArgs.name;
if (op.Layer) {
if (op.Mode == 1) op.Mode = 2;
if (op.Mode == 3) op.Mode = 4;
}
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]);
DrawOp.DoDrawOp(op, null, p, m, false);
}
public override void Help(Player p) {

View File

@ -53,7 +53,7 @@ namespace MCGalaxy.Drawing.Ops {
}
long affected = op.BlocksAffected(op.Level, marks);
if (p != null && op.AffectedByTransform)
if (p != null && op.AffectedByTransform)
p.Transform.GetBlocksAffected(ref 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) {
if (p == null) {
BufferedBlockSender buffer = new BufferedBlockSender(op.Level);
foreach (var b in op.Perform(marks, p, op.Level, brush)) {
int index = op.Level.PosToInt(b.X, b.Y, b.Z);
if (!op.Level.DoPhysicsBlockchange(index, b.Block, false,
default(PhysicsArgs), b.ExtBlock)) continue;
buffer.Add(index, b.Block, b.ExtBlock);
}
op.Perform(marks, p, op.Level, brush,
b => ConsoleOutputBlock(b, op.Level, buffer));
buffer.Send(true);
return;
}
@ -99,6 +94,13 @@ namespace MCGalaxy.Drawing.Ops {
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) {
while (true) {
PendingDrawOp item;
@ -138,44 +140,56 @@ namespace MCGalaxy.Drawing.Ops {
static void DoDrawOp(PendingDrawOp item, Player p) {
Level lvl = item.Level;
IEnumerable<DrawOpBlock> iterator = 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);
Action<DrawOpBlock, Player, Level> output = null;
if (item.Affected > Server.DrawReloadLimit) {
foreach (var b in iterator) {
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);
}
output = SetTileOutput;
} else if (item.Level.bufferblocks) {
foreach (var b in iterator) {
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);
}
output = BufferedOutput;
} else {
foreach (var b in iterator) {
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);
}
output = SlowOutput;
}
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) {
@ -186,6 +200,6 @@ namespace MCGalaxy.Drawing.Ops {
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
}

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using Draw = System.Drawing;
using MCGalaxy.Drawing.Brushes;
@ -32,6 +33,7 @@ namespace MCGalaxy.Drawing.Ops {
internal Draw.Bitmap Source;
internal int Mode, Direction;
internal bool Layer;
internal string Filename;
public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush, Action<DrawOpBlock> output) {
Vec3U16 p0 = Clamp(marks[0]);
@ -69,7 +71,12 @@ namespace MCGalaxy.Drawing.Ops {
if (col.A < 20) cur.Block = Block.air;
output(Place(X, Y, Z, cur.Block, 0));
}
Source.Dispose();
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,

View File

@ -26,9 +26,9 @@ namespace MCGalaxy.Drawing.Transforms {
public override string Name { get { return "None"; } }
public static NoTransform Instance = new NoTransform();
public override IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p,
Level lvl, DrawOp op, Brush brush) {
return op.Perform(marks, p, lvl, brush);
public override void Perform(Vec3S32[] marks, Player p, Level lvl,
DrawOp op, Brush brush, Action<DrawOpBlock> output) {
op.Perform(marks, p, lvl, brush, output);
}
}
@ -37,6 +37,9 @@ namespace MCGalaxy.Drawing.Transforms {
public override string Name { get { return "Scale"; } }
public bool CentreOrigin;
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) {
// 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));
}
public override IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p,
Level lvl, DrawOp op, Brush brush) {
Vec3S32 P = (op.Min + op.Max) / 2;
int dirX = 1, dirY = 1, dirZ = 1;
public override void Perform(Vec3S32[] marks, Player p, Level lvl,
DrawOp op, Brush brush, Action<DrawOpBlock> output) {
P = (op.Min + op.Max) / 2;
dirX = 1; dirY = 1; dirZ = 1;
width = lvl.Width; height = lvl.Height; length = lvl.Length;
if (!CentreOrigin) {
// Guess the direction in which we should be scaling -
// 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);
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);
}
}
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)) {
int dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z;
DrawOpBlock cur = b;
// 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)
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)
{
if (!lvl.IsValidPos(x, y, z)) continue;
cur.X = (ushort)x; cur.Y = (ushort)y; cur.Z = (ushort)z;
yield return cur;
}
// 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)
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)
{
if (x < 0 || y < 0 || z < 0 || x >= width || y >= height || z >= length) continue;
b.X = (ushort)x; b.Y = (ushort)y; b.Z = (ushort)z;
output(b);
}
}
}

View File

@ -33,7 +33,7 @@ namespace MCGalaxy.Drawing.Transforms {
/// <summary> Performs calcuations (if necessary) for the given drawop. </summary>
public virtual void Configure(DrawOp op, Player p) { }
public abstract IEnumerable<DrawOpBlock> Perform(Vec3S32[] marks, Player p,
Level lvl, DrawOp op, Brush brush);
public abstract void Perform(Vec3S32[] marks, Player p, Level lvl,
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;
treeDrawer.SetMarks(treeCoords);
foreach (var block in treeDrawer.Perform(treeCoords, null, Lvl, null))
Lvl.SetTile(block.X, block.Y, block.Z, block.Block);
treeDrawer.Perform(treeCoords, null, Lvl, null,
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) };
op.SetMarks(marks);
foreach (var block in op.Perform(marks, null, lvl, null)) {
lvl.Blockchange(block.X, block.Y, block.Z, block.Block);
}
op.Perform(marks, null, lvl, null,
b => lvl.Blockchange(b.X, b.Y, b.Z, b.Block));
C.data.Data = 255;
}