Make /restoreselection a drawop and allow it to work with different sized restores. Fixes #219.

This commit is contained in:
UnknownShadow200 2017-05-07 18:26:49 +10:00
parent 699510f7a7
commit 322b6e9a85
5 changed files with 75 additions and 32 deletions

View File

@ -16,6 +16,8 @@
permissions and limitations under the Licenses.
*/
using System;
using MCGalaxy.Drawing;
using MCGalaxy.Drawing.Ops;
using MCGalaxy.DB;
using MCGalaxy.Levels.IO;
@ -29,6 +31,7 @@ namespace MCGalaxy.Commands.Moderation {
public override void Use(Player p, string message) {
if (message == "") { Help(p); return; }
if (!Formatter.ValidName(p, name, "level")) return;
if (LevelInfo.ExistsBackup(p.level.name, message)) {
p.SendMessage("Select two corners for restore.");
@ -39,40 +42,20 @@ namespace MCGalaxy.Commands.Moderation {
}
bool DoRestore(Player p, Vec3S32[] marks, object state, byte type, byte extType) {
string path = LevelInfo.BackupPath(p.level.name, (string)state);
try {
using (Level other = IMapImporter.Formats[0].Read(path, "templevel", false)) {
return CopyBlocks(p, other, marks);
}
} catch (Exception ex) {
Server.ErrorLog(ex);
Server.s.Log("Restore selection failed");
return false;
}
}
static bool CopyBlocks(Player p, Level other, Vec3S32[] m) {
byte[] blocks = other.blocks;
if (blocks.Length != p.level.blocks.Length) {
Player.Message(p, "Cannot restore selection of different size maps.");
return false;
}
string path = LevelInfo.BackupPath(p.level.name, (string)state);
Level source = IMapImporter.Formats[0].Read(path, "templevel", false);
int width = other.Width, length = other.Length;
for (int y = Math.Min(m[0].Y, m[1].Y); y <= Math.Max(m[0].Y, m[1].Y); y++)
for (int z = Math.Min(m[0].Z, m[1].Z); z <= Math.Max(m[0].Z, m[1].Z); z++)
for (int x = Math.Min(m[0].X, m[1].X); x <= Math.Max(m[0].X, m[1].X); x++)
{
byte block = blocks[x + width * (z + y * length)], ext = 0;
if (block == Block.custom_block)
ext = other.GetExtTile((ushort)x, (ushort)y, (ushort)z);
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, block, ext, BlockDBFlags.Restored);
}
return true;
RestoreSelectionDrawOp op = new RestoreSelectionDrawOp();
op.Source = source;
if (DrawOpPerformer.Do(op, null, p, marks)) return false;
// Not high enough draw limit
source.Dispose();
return false;
}
public override void Help(Player p) {
Player.Message(p, "%T/restoreselection [number]");
Player.Message(p, "%T/restoreselection [backup name]");
Player.Message(p, "%HRestores a previous backup of the current selection");
}
}

View File

@ -112,7 +112,6 @@ namespace MCGalaxy.Undo {
}
struct UndoCacheItem {
public int Index;
public byte Type, NewType;
public ushort Flags; // upper 2 bits for 'ext' or 'physics' type, lower 14 bits for time delta.

View File

@ -39,7 +39,7 @@ namespace MCGalaxy.Drawing.Ops {
}
}
public class CuboidHollowsDrawOp : DrawOp {
public class CuboidHollowsDrawOp : DrawOp {
public override string Name { get { return "Cuboid Hollow"; } }
public override long BlocksAffected(Level lvl, Vec3S32[] marks) {

View File

@ -0,0 +1,60 @@
/*
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.DB;
using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy.Drawing.Ops {
public class RestoreSelectionDrawOp : DrawOp {
public override string Name { get { return "RestoreSelection"; } }
public override bool AffectedByTransform { get { return false; } }
public override long BlocksAffected(Level lvl, Vec3S32[] marks) {
return (Max.X - Min.X + 1) * (Max.Y - Min.Y + 1) * (Max.Z - Min.Z + 1);
}
public RestoreSelectionDrawOp() {
Flags = BlockDBFlags.Restored;
}
public Level Source;
public override void Perform(Vec3S32[] marks, Brush brush, Action<DrawOpBlock> output) {
Max.X = Math.Min(Max.X, Source.Width - 1);
Max.Y = Math.Min(Max.Y, Source.Height - 1);
Max.Z = Math.Min(Max.Z, Source.Length - 1);
Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max);
int width = Source.Width, length = Source.Length;
byte[] blocks = Source.blocks;
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++)
{
byte block = blocks[x + width * (z + y * length)], ext = 0;
if (block == Block.custom_block)
ext = Source.GetExtTileNoCheck(x, y, z);
output(Place(x, y, z, block, ext));
}
Source.Dispose();
}
}
}

View File

@ -439,6 +439,7 @@
<Compile Include="Drawing\DrawOps\PasteDrawOp.cs" />
<Compile Include="Drawing\DrawOps\RedoDrawOp.cs" />
<Compile Include="Drawing\DrawOps\ReplaceDrawOp.cs" />
<Compile Include="Drawing\DrawOps\RestoreSelectionDrawOp.cs" />
<Compile Include="Drawing\DrawOps\SpheroidDrawOp.cs" />
<Compile Include="Drawing\DrawOps\PyramidDrawOp.cs" />
<Compile Include="Drawing\DrawOps\TorusDrawOp.cs" />