DB: now use BlockDB flags

This commit is contained in:
UnknownShadow200 2016-12-22 12:36:28 +11:00
parent 5e39139d04
commit 1405c67139
17 changed files with 131 additions and 57 deletions

View File

@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System;
using MCGalaxy.DB;
using MCGalaxy.Levels.IO;
namespace MCGalaxy.Commands {
@ -62,10 +63,10 @@ namespace MCGalaxy.Commands {
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)], extBlock = 0;
byte block = blocks[x + width * (z + y * length)], ext = 0;
if (block == Block.custom_block)
extBlock = other.GetExtTile((ushort)x, (ushort)y, (ushort)z);
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, block, extBlock, true);
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;
}

View File

@ -1,4 +1,22 @@
/*
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;
namespace MCGalaxy.Commands.Building {
public sealed class CmdCenter : Command {
@ -37,7 +55,7 @@ namespace MCGalaxy.Commands.Building {
}
static void Place(Player p, int x, int y, int z) {
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, Block.goldsolid, 0, true);
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, Block.goldsolid, 0, BlockDBFlags.Drawn);
}
public override void Help(Player p) {

View File

@ -19,6 +19,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using MCGalaxy.DB;
using MCGalaxy.Drawing;
using MCGalaxy.Drawing.Brushes;
using MCGalaxy.Drawing.Ops;
@ -129,6 +130,7 @@ namespace MCGalaxy.Commands.Building {
p.CopyBuffer = cState;
if (cArgs.type == 1) {
DrawOp op = new CuboidDrawOp();
op.Flags = BlockDBFlags.Cut;
Brush brush = new SolidBrush(Block.air, 0);
Vec3S32[] marks = { new Vec3S32(minX, minY, minZ), new Vec3S32(maxX, maxY, maxZ) };
DrawOp.DoDrawOp(op, brush, p, marks, false);

View File

@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System.Collections.Generic;
using MCGalaxy.DB;
namespace MCGalaxy.Commands.Building {
public sealed class CmdDrill : Command {
@ -75,15 +76,15 @@ namespace MCGalaxy.Commands.Building {
return true;
}
void DoBlock(Player p, Level lvl, byte block, byte extBlock,
void DoBlock(Player p, Level lvl, byte block, byte ext,
ushort x, ushort y, ushort z) {
int index = lvl.PosToInt(x, y, z);
if (index == -1) return;
byte cur = lvl.blocks[index], extCur = 0;
if (cur == Block.custom_block) extCur = lvl.GetExtTile(x, y, z);
bool same = block == Block.custom_block ? extBlock == extCur : block == cur;
if (same) p.level.UpdateBlock(p, x, y, z, Block.air, 0, true);
bool same = block == Block.custom_block ? ext == extCur : block == cur;
if (same) p.level.UpdateBlock(p, x, y, z, Block.air, 0, BlockDBFlags.Drawn);
}
public override void Help(Player p) {

View File

@ -123,6 +123,7 @@ namespace MCGalaxy.Commands.Building {
}
op.Level = p.level;
op.Player = p;
op.Source = bmp;
op.Layer = dArgs.layer;
op.Mode = dArgs.popType;

View File

@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System;
using MCGalaxy.DB;
namespace MCGalaxy.Commands.Building {
public sealed class CmdPlace : Command {
@ -27,22 +28,22 @@ namespace MCGalaxy.Commands.Building {
public CmdPlace() { }
public override void Use(Player p, string message) {
byte extBlock = 0;
int block = p.GetActualHeldBlock(out extBlock);
byte ext = 0;
int block = p.GetActualHeldBlock(out ext);
ushort x = p.pos[0], y = (ushort)(p.pos[1] - 32), z = p.pos[2];
try {
string[] parts = message.Split(' ');
switch (parts.Length) {
case 1: block = message == "" ? block :
DrawCmd.GetBlockIfAllowed(p, parts[0], out extBlock); break;
DrawCmd.GetBlockIfAllowed(p, parts[0], out ext); break;
case 3:
x = (ushort)(ushort.Parse(parts[0]) * 32);
y = (ushort)(ushort.Parse(parts[1]) * 32);
z = (ushort)(ushort.Parse(parts[2]) * 32);
break;
case 4:
block = DrawCmd.GetBlockIfAllowed(p, parts[0], out extBlock);
block = DrawCmd.GetBlockIfAllowed(p, parts[0], out ext);
x = (ushort)(ushort.Parse(parts[1]) * 32);
y = (ushort)(ushort.Parse(parts[2]) * 32);
z = (ushort)(ushort.Parse(parts[3]) * 32);
@ -58,8 +59,8 @@ namespace MCGalaxy.Commands.Building {
Vec3U16 P = Vec3U16.ClampPos(x, y, z, p.level);
P.X /= 32; P.Y /= 32; P.Z /= 32;
p.level.UpdateBlock(p, P.X, P.Y, P.Z, (byte)block, extBlock);
string blockName = p.level.BlockName((byte)block, extBlock);
p.level.UpdateBlock(p, P.X, P.Y, P.Z, (byte)block, ext, BlockDBFlags.ManualPlace);
string blockName = p.level.BlockName((byte)block, ext);
Player.Message(p, "{3} block was placed at ({0}, {1}, {2}).", P.X, P.Y, P.Z, blockName);
}

View File

@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System;
using MCGalaxy.DB;
namespace MCGalaxy.Commands.Building {
public sealed class CmdSPlace : Command {
@ -72,18 +73,18 @@ namespace MCGalaxy.Commands.Building {
byte heldExt = 0;
byte heldBlock = p.GetActualHeldBlock(out heldExt);
p.level.UpdateBlock(p, endX, endY, endZ, heldBlock, heldExt, true);
p.level.UpdateBlock(p, endX, endY, endZ, heldBlock, heldExt, BlockDBFlags.Drawn);
if (interval > 0) {
int x = m[0].X, y = m[0].Y, z = m[0].Z;
int delta = 0;
while (x >= 0 && y >= 0 && z >= 0 && x < p.level.Width && y < p.level.Height && z < p.level.Length && delta < distance) {
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, heldBlock, heldExt, true);
p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, heldBlock, heldExt, BlockDBFlags.Drawn);
x += dirX * interval; y += dirY * interval; z += dirZ * interval;
delta = Math.Abs(x - m[0].X) + Math.Abs(y - m[0].Y) + Math.Abs(z - m[0].Z);
}
} else {
p.level.UpdateBlock(p, (ushort)m[0].X, (ushort)m[0].Y, (ushort)m[0].Z, heldBlock, heldExt, true);
p.level.UpdateBlock(p, (ushort)m[0].X, (ushort)m[0].Y, (ushort)m[0].Z, heldBlock, heldExt, BlockDBFlags.Drawn);
}
Player.Message(p, "Placed stone blocks {0} apart.", interval > 0 ? interval : distance);

View File

@ -18,34 +18,37 @@
using System;
using System.Collections.Generic;
using MCGalaxy.Commands;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Ops;
namespace MCGalaxy.Drawing.Brushes {
public sealed class PasteBrush : Brush {
readonly CopyState state;
int index;
public PasteBrush(CopyState state) { this.state = state; }
public override string Name { get { return "Paste"; } }
public override void Configure(DrawOp op, Player p) {
op.Flags = BlockDBFlags.Pasted;
}
public override byte NextBlock(DrawOp op) {
Vec3U16 p = LocalCoords(op);
return state.Blocks[state.GetIndex(p.X, p.Y, p.Z)];
}
public override byte NextExtBlock(DrawOp op) {
Vec3U16 p = LocalCoords(op);
return state.ExtBlocks[state.GetIndex(p.X, p.Y, p.Z)];
}
Vec3U16 LocalCoords(DrawOp op) {
// Figure out local coords for this block
int x = (op.Coords.X - op.Min.X) % state.Width;
if (x < 0) x += state.Width;
int y = (op.Coords.Y - op.Min.Y) % state.Height;
if (y < 0) y += state.Height;
int z = (op.Coords.Z - op.Min.Z) % state.Length;
if (z < 0) z += state.Length;
return new Vec3U16((ushort)x, (ushort)y, (ushort)z);
index = state.GetIndex(x, y, z);
return state.Blocks[index];
}
public override byte NextExtBlock(DrawOp op) {
return state.ExtBlocks[index];
}
}
}

View File

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using MCGalaxy.Commands.Building;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Ops;
namespace MCGalaxy.Drawing.Brushes {
@ -31,6 +32,10 @@ namespace MCGalaxy.Drawing.Brushes {
public override string Name { get { return "Replace"; } }
public override void Configure(DrawOp op, Player p) {
op.Flags = BlockDBFlags.Replaced;
}
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;
@ -57,6 +62,10 @@ namespace MCGalaxy.Drawing.Brushes {
public override string Name { get { return "ReplaceNot"; } }
public override void Configure(DrawOp op, Player p) {
op.Flags = BlockDBFlags.Replaced;
}
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;

View File

@ -29,7 +29,6 @@ namespace MCGalaxy.Drawing {
public Brush Brush;
public Vec3S32[] Marks;
public long Affected;
public Level Level;
}
}
@ -41,13 +40,14 @@ namespace MCGalaxy.Drawing.Ops {
ushort x1, ushort y1, ushort z1, ushort x2, ushort y2, ushort z2) {
Vec3S32[] marks = new [] { new Vec3S32(x1, y1, z1), new Vec3S32(x2, y2, z2) };
return DoDrawOp(op, brush, p, marks);
DrawOp.DoDrawOp(new EllipsoidDrawOp(), new SolidBrush(Block.leaf, 0), p, x1, y1, z1, x2, y2, z2);
}
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;
op.Player = p;
if (op.Level != null && !op.Level.DrawingAllowed) {
Player.Message(p, "Drawing commands are turned off on this map.");
return false;
@ -90,7 +90,6 @@ namespace MCGalaxy.Drawing.Ops {
item.Brush = brush;
item.Marks = marks;
item.Affected = affected;
item.Level = op.Level;
lock (p.pendingDrawOpsLock) {
p.PendingDrawOps.Add(item);
@ -125,7 +124,7 @@ namespace MCGalaxy.Drawing.Ops {
UndoDrawOpEntry entry = new UndoDrawOpEntry();
entry.DrawOpName = item.Op.Name;
entry.LevelName = item.Level.name;
entry.LevelName = item.Op.Level.name;
entry.Start = DateTime.UtcNow;
// Use same time method as DoBlockchange writing to undo buffer
int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
@ -140,17 +139,17 @@ namespace MCGalaxy.Drawing.Ops {
if (p.DrawOps.Count > 200)
p.DrawOps.RemoveFirst();
if (item.Affected > Server.DrawReloadLimit)
DoReload(p, item.Level);
DoReload(p, item.Op.Level);
}
}
static void DoDrawOp(PendingDrawOp item, Player p) {
Level lvl = item.Level;
Action<DrawOpBlock, Player, Level> output = null;
Level lvl = item.Op.Level;
Action<DrawOpBlock, DrawOp> output = null;
if (item.Affected > Server.DrawReloadLimit) {
output = SetTileOutput;
} else if (item.Level.bufferblocks) {
} else if (lvl.bufferblocks) {
output = BufferedOutput;
} else {
output = SlowOutput;
@ -158,15 +157,17 @@ namespace MCGalaxy.Drawing.Ops {
if (item.Op.AffectedByTransform) {
p.Transform.Perform(item.Marks, p, lvl, item.Op, item.Brush,
b => output(b, p, lvl));
b => output(b, item.Op));
} else {
item.Op.Perform(item.Marks, p, lvl, item.Brush,
b => output(b, p, lvl));
b => output(b, item.Op));
}
}
static void SetTileOutput(DrawOpBlock b, Player p, Level lvl) {
static void SetTileOutput(DrawOpBlock b, DrawOp op) {
if (b.Block == Block.Invalid) return;
Level lvl = op.Level;
Player p = op.Player;
byte old = lvl.GetTile(b.X, b.Y, b.Z);
if (old == Block.Invalid) return;
@ -176,29 +177,34 @@ namespace MCGalaxy.Drawing.Ops {
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);
lvl.SetTile(b.X, b.Y, b.Z, b.Block, p, b.ExtBlock, op.Flags);
p.IncrementBlockStats(b.Block, true);
}
static void BufferedOutput(DrawOpBlock b, Player p, Level lvl) {
static void BufferedOutput(DrawOpBlock b, DrawOp op) {
if (b.Block == Block.Invalid) return;
Level lvl = op.Level;
Player p = op.Player;
byte old = lvl.GetTile(b.X, b.Y, b.Z), oldExt = 0;
if (old == Block.custom_block) oldExt = lvl.GetExtTile(b.X, b.Y, b.Z);
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, old, oldExt, b.Block, b.ExtBlock);
lvl.AddToBlockDB(p, index, old, oldExt, b.Block, b.ExtBlock, op.Flags);
BlockQueue.Addblock(p, index, b.Block, b.ExtBlock);
}
static void SlowOutput(DrawOpBlock b, Player p, Level lvl) {
static void SlowOutput(DrawOpBlock b, DrawOp op) {
if (b.Block == Block.Invalid) return;
Level lvl = op.Level;
Player p = op.Player;
byte old = lvl.GetTile(b.X, b.Y, b.Z), oldExt = 0;
if (old == Block.custom_block) oldExt = lvl.GetExtTile(b.X, b.Y, b.Z);
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, old, oldExt, b.Block, b.ExtBlock);
lvl.AddToBlockDB(p, index, old, oldExt, b.Block, b.ExtBlock, op.Flags);
Player.GlobalBlockchange(lvl, b.X, b.Y, b.Z, b.Block, b.ExtBlock);
}

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy {
@ -60,6 +61,12 @@ namespace MCGalaxy.Drawing.Ops {
/// <summary> Level the draw operation is being performed upon. </summary>
public Level Level;
/// <summary> Player that is executing the draw operation. </summary>
public Player Player;
/// <summary> BlockDB change flags for blocks affected by this draw operation. </summary>
public ushort Flags = BlockDBFlags.Drawn;
/// <summary> Human friendly name of the draw operation. </summary>
public abstract string Name { get; }

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy.Drawing.Ops {
@ -25,6 +26,10 @@ namespace MCGalaxy.Drawing.Ops {
public List<int> Positions;
public FillDrawOp() {
Flags = BlockDBFlags.Filled;
}
public override string Name { get { return "Fill"; } }
public override bool AffectedByTransform { get { return false; } }

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy.Drawing.Ops {
@ -24,6 +25,10 @@ namespace MCGalaxy.Drawing.Ops {
public override string Name { get { return "Paste"; } }
public CopyState CopyState;
public SimplePasteDrawOp() {
Flags = BlockDBFlags.Pasted;
}
public override long BlocksAffected(Level lvl, Vec3S32[] marks) {
return CopyState.UsedBlocks;
}
@ -61,6 +66,10 @@ namespace MCGalaxy.Drawing.Ops {
public ExtBlock[] Include, Exclude;
public PasteDrawOp() {
Flags = BlockDBFlags.Pasted;
}
public override string Name { get { return "Paste"; } }
public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush, Action<DrawOpBlock> output) {

View File

@ -52,6 +52,7 @@ namespace MCGalaxy.Drawing.Ops {
public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush, Action<DrawOpBlock> output) {
Vec3S32 p1 = Min, p2 = Max;
baseOp.Level = Level;
baseOp.Player = Player;
while (true) {
baseOp.Perform(marks, p, lvl, brush, output);
@ -96,6 +97,7 @@ namespace MCGalaxy.Drawing.Ops {
wallOp.Min = Min; wallOp.Max = Max;
baseOp.Min = Min; baseOp.Max = Max;
wallOp.Level = Level; baseOp.Level = Level;
wallOp.Player = p; baseOp.Player = p;
while (true) {
wallOp.Perform(marks, p, lvl, brush, output);

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
using MCGalaxy.DB;
using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy.Drawing.Ops {
@ -27,6 +28,7 @@ namespace MCGalaxy.Drawing.Ops {
public ReplaceDrawOp(byte type, byte extType) {
Include = new ExtBlock(type, extType);
Flags = BlockDBFlags.Replaced;
}
public override string Name { get { return "Replace"; } }
@ -57,6 +59,7 @@ namespace MCGalaxy.Drawing.Ops {
public ReplaceNotDrawOp(byte type, byte extType) {
Exclude = new ExtBlock(type, extType);
Flags = BlockDBFlags.Replaced;
}
public override string Name { get { return "ReplaceNot"; } }

View File

@ -128,7 +128,8 @@ namespace MCGalaxy {
chunk[(y & 0x0F) << 8 | (z & 0x0F) << 4 | (x & 0x0F)] = 0;
}
public void SetTile(ushort x, ushort y, ushort z, byte block, Player p, byte extBlock = 0) {
public void SetTile(ushort x, ushort y, ushort z, byte block, Player p,
byte ext = 0, ushort flags = BlockDBFlags.ManualPlace) {
int index = PosToInt(x, y, z);
if (blocks == null || index < 0) return;
@ -142,15 +143,15 @@ namespace MCGalaxy {
RevertExtTileNoCheck(x, y, z);
}
if (block == Block.custom_block)
SetExtTileNoCheck(x, y, z, extBlock);
SetExtTileNoCheck(x, y, z, ext);
if (p == null) return;
AddToBlockDB(p, index, oldBlock, oldExtBlock, block, extBlock);
AddToBlockDB(p, index, oldBlock, oldExtBlock, block, ext, flags);
Player.UndoPos Pos;
Pos.x = x; Pos.y = y; Pos.z = z;
Pos.mapName = this.name;
Pos.type = oldBlock; Pos.extType = oldExtBlock;
Pos.newtype = block; Pos.newExtType = extBlock;
Pos.newtype = block; Pos.newExtType = ext;
Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
p.UndoBuffer.Add(this, Pos);
}
@ -428,8 +429,8 @@ namespace MCGalaxy {
return x >= 0 && y >= 0 && z >= 0 && x < Width && y < Height && z < Length;
}
public void AddToBlockDB(Player p, int index, byte oldBlock,
byte oldExtBlock, byte block, byte extBlock) {
public void AddToBlockDB(Player p, int index, byte oldBlock, byte oldExt,
byte block, byte ext, ushort flags) {
if (!UseBlockDB) return;
BlockDBEntry entry;
entry.PlayerID = p.UserID;
@ -437,15 +438,15 @@ namespace MCGalaxy {
entry.Index = index;
entry.OldRaw = oldBlock; entry.NewRaw = block;
entry.Flags = BlockDBFlags.ManualPlace;
entry.Flags = flags;
if (block == Block.custom_block) {
entry.Flags |= BlockDBFlags.NewCustom;
entry.NewRaw = extBlock;
entry.NewRaw = ext;
}
if (oldBlock == Block.custom_block) {
entry.Flags |= BlockDBFlags.OldCustom;
entry.OldRaw = oldExtBlock;
entry.OldRaw = oldExt;
}
lock (blockCacheLock)
@ -453,13 +454,14 @@ namespace MCGalaxy {
}
public void UpdateBlock(Player p, ushort x, ushort y, ushort z,
byte block, byte extBlock, bool drawn = false) {
byte block, byte extBlock, ushort flags) {
byte old = GetTile(x, y, z), oldExt = 0;
if (old == Block.custom_block) oldExt = GetExtTile(x, y, z);
bool drawn = (flags & BlockDBFlags.ManualPlace) != 0;
if (!DoBlockchange(p, x, y, z, block, extBlock, drawn)) return;
int index = PosToInt(x, y, z);
AddToBlockDB(p, index, old, oldExt, block, extBlock);
AddToBlockDB(p, index, old, oldExt, block, extBlock, flags);
if (bufferblocks)
BlockQueue.Addblock(p, index, block, extBlock);

View File

@ -20,6 +20,7 @@ using System.Text.RegularExpressions;
using System.Threading;
using MCGalaxy.Blocks;
using MCGalaxy.Blocks.Physics;
using MCGalaxy.DB;
using MCGalaxy.Commands;
using MCGalaxy.Games;
using MCGalaxy.SQL;
@ -109,6 +110,8 @@ namespace MCGalaxy {
byte blockRaw = block;
if (block < Block.CpeCount) block = bindings[block];
ushort flags = BlockDBFlags.ManualPlace;
if (painting && !doDelete) flags = BlockDBFlags.Painted;
//Ignores updating blocks that are the same and send block only to the player
byte newBlock = (painting || action == 1) ? block : (byte)0;
@ -123,10 +126,10 @@ namespace MCGalaxy {
int index = level.PosToInt(x, y, z);
if (doDelete) {
if (DeleteBlock(old, x, y, z, block, extBlock))
level.AddToBlockDB(this, index, old, oldExt, 0, 0);
level.AddToBlockDB(this, index, old, oldExt, 0, 0, flags);
} else {
if (PlaceBlock(old, x, y, z, block, extBlock))
level.AddToBlockDB(this, index, old, oldExt, heldBlock, heldExt);
level.AddToBlockDB(this, index, old, oldExt, heldBlock, heldExt, flags);
}
}