void OutputBlock(DrawOpBlock b, DrawOpOutput output) { int dx = (b.X - P.X) * signX, dy = (b.Y - P.Y) * signY, dz = (b.Z - P.Z) * signZ; int begX = P.X + dx * XMul / XDiv, endX = P.X + (dx + dirX) * XMul / XDiv; int begY = P.Y + dy * YMul / YDiv, endY = P.Y + (dy + dirY) * YMul / YDiv; int begZ = P.Z + dz * ZMul / ZDiv, endZ = P.Z + (dz + dirZ) * ZMul / ZDiv; // Scale out until we hit the next block for (int y = begY; y != endY; y += dirY) { for (int z = begZ; z != endZ; z += dirZ) { for (int x = begX; x != endX; 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); } } } }
void OutputBlock(DrawOpBlock b, DrawOpOutput output) { double dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z; double rotX = 0, rotY = 0, rotZ = 0; // Rotate X rotY = cosX * dy - sinX * dz; rotZ = sinX * dy + cosX * dz; dy = rotY; dz = rotZ; // Rotate Y rotX = cosY * dx + sinY * dz; rotZ = -sinY * dx + cosY * dz; dx = rotX; dz = rotZ; // Rotate Z rotX = cosZ * dx - sinZ * dy; rotY = sinZ * dx + cosZ * dy; dx = rotX; dy = rotY; b.X = (ushort)(dx + P.X + ((dx % 1) >= 0.5 ? 1 : 0)); b.Y = (ushort)(dy + P.Y + ((dy % 1) >= 0.5 ? 1 : 0)); b.Z = (ushort)(dz + P.Z + ((dz % 1) >= 0.5 ? 1 : 0)); output(b); }
static void OutputBlock(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 (op.TotalModified > Server.DrawReloadLimit) { if (old == Block.Invalid) { 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, op.Flags); p.IncrementBlockStats(b.Block, true); } else if (op.TotalModified == Server.DrawReloadLimit) { Player.Message(p, "Affected over {0} blocks, prepared to reload map..", Server.DrawReloadLimit); lock (lvl.queueLock) lvl.blockqueue.Clear(); } else { if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) { return; } lvl.BlockDB.Add(p, b.X, b.Y, b.Z, op.Flags, old, oldExt, b.Block, b.ExtBlock); int index = lvl.PosToInt(b.X, b.Y, b.Z); BlockQueue.Addblock(p, index, b.Block, b.ExtBlock); } op.TotalModified++; }
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); }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { CopyState state = CopyState; bool pasteAir = state.PasteAir; 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++) { DrawOpBlock block = Place(x, y, z, brush); if (pasteAir || block.Block.BlockID != Block.Air) { output(block); } } } } }
void OutputBlock(DrawOpBlock b, Action <DrawOpBlock> output) { int dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z; // 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); } } } }
public void Output(DrawOpBlock b) { if (b.Block == Block.Invalid) { return; } Level lvl = op.Level; Player p = op.Player; if (b.X >= lvl.Width || b.Y >= lvl.Height || b.Z >= lvl.Length) { return; } int index = b.X + lvl.Width * (b.Z + b.Y * lvl.Length); BlockID old = lvl.blocks[index]; #if TEN_BIT_BLOCKS BlockID extended = Block.ExtendedBase[old]; if (extended > 0) { old = (BlockID)(extended | lvl.FastGetExtTile(b.X, b.Y, b.Z)); } #else if (old == Block.custom_block) { old = (BlockID)(Block.Extended | lvl.FastGetExtTile(b.X, b.Y, b.Z)); } #endif if (old == Block.Invalid) { return; } // Check to make sure the block is actually different and that can be used if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) { return; } // Check if player can affect block at coords in world AccessController denied = lvl.CanAffect(p, b.X, b.Y, b.Z); if (denied != null) { if (p.lastAccessStatus < DateTime.UtcNow) { denied.CheckDetailed(p); p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2); } return; } // Set the block (inlined) lvl.Changed = true; if (b.Block >= Block.Extended) { #if TEN_BIT_BLOCKS lvl.blocks[index] = Block.ExtendedClass[b.Block >> Block.ExtendedShift]; #else lvl.blocks[index] = Block.custom_block; #endif lvl.FastSetExtTile(b.X, b.Y, b.Z, (BlockRaw)b.Block); } else { lvl.blocks[index] = (BlockRaw)b.Block; if (old >= Block.Extended) { lvl.FastRevertExtTile(b.X, b.Y, b.Z); } } lvl.BlockDB.Cache.Add(p, b.X, b.Y, b.Z, op.Flags, old, b.Block); p.SessionModified++; p.TotalModified++; p.TotalDrawn++; // increment block stats inline // Potentially buffer the block change if (op.TotalModified == reloadThreshold) { if (!p.Ignores.DrawOutput) { p.Message("Changed over {0} blocks, preparing to reload map..", reloadThreshold); } lvl.blockqueue.ClearAll(); } else if (op.TotalModified < reloadThreshold) { if (!Block.VisuallyEquals(old, b.Block)) { lvl.blockqueue.Add(p, index, b.Block); } if (lvl.physics > 0) { if (old == Block.Sponge && b.Block != Block.Sponge) { OtherPhysics.DoSpongeRemoved(lvl, index, false); } if (old == Block.LavaSponge && b.Block != Block.LavaSponge) { OtherPhysics.DoSpongeRemoved(lvl, index, true); } if (lvl.ActivatesPhysics(b.Block)) { lvl.AddCheck(index); } } } op.TotalModified++; // Attempt to prevent BlockDB in-memory cache from growing too large (> 1,000,000 entries) int count = lvl.BlockDB.Cache.Count; if (count == 0 || (count % 1000000) != 0) { return; } // if drawop has a read lock on BlockDB (e.g. undo/redo), we must release it here bool hasReadLock = false; if (op.BlockDBReadLock != null) { op.BlockDBReadLock.Dispose(); hasReadLock = true; } using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) { if (wLock != null) { lvl.BlockDB.FlushCache(); } } if (!hasReadLock) { return; } op.BlockDBReadLock = lvl.BlockDB.Locker.AccquireRead(); }
public void Output(DrawOpBlock b) { if (b.Block.BlockID == Block.Invalid) { return; } Level lvl = op.Level; Player p = op.Player; if (b.X >= lvl.Width || b.Y >= lvl.Height || b.Z >= lvl.Length) { return; } int index = b.X + lvl.Width * (b.Z + b.Y * lvl.Length); ExtBlock old; old.BlockID = lvl.blocks[index]; old.ExtID = 0; if (old.BlockID == Block.custom_block) { old.ExtID = lvl.GetExtTileNoCheck(b.X, b.Y, b.Z); } if (old.BlockID == Block.Invalid) { return; } // Check to make sure the block is actually different and that we can change it if (old == b.Block || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block)) { return; } // Set the block (inlined) lvl.blocks[index] = b.Block.BlockID; lvl.Changed = true; if (old.BlockID == Block.custom_block && b.Block.BlockID != Block.custom_block) { lvl.RevertExtTileNoCheck(b.X, b.Y, b.Z); } if (b.Block.BlockID == Block.custom_block) { lvl.SetExtTileNoCheck(b.X, b.Y, b.Z, b.Block.ExtID); } if (p != null) { lvl.BlockDB.Cache.Add(p, b.X, b.Y, b.Z, op.Flags, old, b.Block); p.SessionModified++; p.TotalModified++; p.TotalDrawn++; // increment block stats inline } // Potentially buffer the block change if (op.TotalModified == reloadThreshold) { if (p == null || !p.Ignores.DrawOutput) { Player.Message(p, "Changed over {0} blocks, preparing to reload map..", reloadThreshold); } lock (lvl.queueLock) lvl.blockqueue.Clear(); } else if (op.TotalModified < reloadThreshold) { if (!old.VisuallyEquals(b.Block)) { BlockQueue.Addblock(p, index, b.Block); } if (lvl.physics > 0) { if (old.BlockID == Block.Sponge && b.Block.BlockID != Block.Sponge) { OtherPhysics.DoSpongeRemoved(lvl, index, false); } if (old.BlockID == Block.LavaSponge && b.Block.BlockID != Block.LavaSponge) { OtherPhysics.DoSpongeRemoved(lvl, index, true); } if (lvl.ActivatesPhysics(b.Block)) { lvl.AddCheck(index); } } } op.TotalModified++; // Attempt to prevent the BlockDB from growing too large (> 1,000,000 entries) int count = lvl.BlockDB.Cache.Count; if (count == 0 || (count % 1000000) != 0) { return; } // if drawop has a read lock on BlockDB (e.g. undo/redo), we must release it here bool hasReadLock = false; if (op.BlockDBReadLock != null) { op.BlockDBReadLock.Dispose(); hasReadLock = true; } using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) { if (wLock != null) { lvl.BlockDB.WriteEntries(); } } if (!hasReadLock) { return; } op.BlockDBReadLock = lvl.BlockDB.Locker.AccquireRead(); }