static void HighlightPlayer(Player p, TimeSpan delta, string who, int[] ids, Vec3S32[] marks) { HighlightDrawOp op = new HighlightDrawOp(); op.Start = DateTime.UtcNow.Subtract(delta); op.who = who; op.ids = ids; op.Setup(p, p.level, marks); BufferedBlockSender buffer = new BufferedBlockSender(p); op.Perform(marks, null, P => { int index = p.level.PosToInt(P.X, P.Y, P.Z); buffer.Add(index, P.Block); }); buffer.Flush(); if (op.found) { p.Message("Now highlighting past &b{0} &Sfor {1}", delta.Shorten(true), p.FormatNick(who)); p.Message("&WUse /reload to un-highlight"); } else { p.Message("No changes found by {1} &Sin the past &b{0}", delta.Shorten(true), p.FormatNick(who)); } }
static void HighlightPlayer(Player p, TimeSpan delta, string who, int[] ids, Vec3S32[] marks) { HighlightDrawOp op = new HighlightDrawOp(); op.Start = DateTime.UtcNow.Subtract(delta); op.who = who; op.ids = ids; DrawOpPerformer.Setup(op, p, marks); BufferedBlockSender buffer = new BufferedBlockSender(p); op.Perform(marks, null, P => { int index = p.level.PosToInt(P.X, P.Y, P.Z); buffer.Add(index, P.Block.BlockID, P.Block.ExtID); }); buffer.Send(true); if (op.found) { Player.Message(p, "Now highlighting past &b{0} %Sfor {1}", delta.Shorten(true), PlayerInfo.GetColoredName(p, who)); Player.Message(p, "&cUse /reload to un-highlight"); } else { Player.Message(p, "No changes found by {1} %Sin the past &b{0}", delta.Shorten(true), PlayerInfo.GetColoredName(p, who)); } }
static void AppendDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks, long affected) { if (p == null) { BufferedBlockSender buffer = new BufferedBlockSender(op.Level); op.Perform(marks, brush, b => ConsoleOutputBlock(b, op.Level, buffer)); buffer.Send(true); return; } PendingDrawOp item = new PendingDrawOp(); item.Op = op; item.Brush = brush; item.Marks = marks; lock (p.pendingDrawOpsLock) { p.PendingDrawOps.Add(item); // Another thread is already processing draw ops. if (p.PendingDrawOps.Count > 1) { return; } } ProcessDrawOps(p); }
static void FixLight(Player p, Level lvl, ref int totalFixed) { int index = 0, oneY = lvl.Width * lvl.Length; BufferedBlockSender buffer = new BufferedBlockSender(lvl); BlockID above, block; for (ushort y = 0; y < lvl.Height - 1; y++) { for (ushort z = 0; z < lvl.Length; z++) { for (ushort x = 0; x < lvl.Width; x++) { block = lvl.FastGetBlock(index); bool inShadow = false; if (lvl.Props[block].GrassBlock != Block.Invalid) { for (int i = 1; i < (lvl.Height - y); i++) { above = lvl.FastGetBlock(index + oneY * i); if (!lvl.LightPasses(above)) { inShadow = true; break; } } BlockID grass = lvl.Props[block].GrassBlock; if (!inShadow && p.level.TryChangeBlock(p, x, y, z, grass) == ChangeResult.Modified) { buffer.Add(lvl.PosToInt(x, y, z), grass); totalFixed++; } } else if (lvl.Props[block].DirtBlock != Block.Invalid) { for (int i = 1; i < (lvl.Height - y); i++) { above = lvl.FastGetBlock(index + oneY * i); if (!lvl.LightPasses(above)) { inShadow = true; break; } } BlockID dirt = lvl.Props[block].DirtBlock; if (inShadow && p.level.TryChangeBlock(p, x, y, z, dirt) == ChangeResult.Modified) { buffer.Add(lvl.PosToInt(x, y, z), dirt); totalFixed++; } } index++; } } } buffer.Flush(); }
static void Fix(Player p, Level lvl, ref int totalFixed, bool fixGrass, bool fixDirt) { int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length; BufferedBlockSender buffer = new BufferedBlockSender(lvl); ExtBlock above = default(ExtBlock), block = default(ExtBlock); for (ushort y = 0; y < lvl.Height; y++) { for (ushort z = 0; z < lvl.Length; z++) { for (ushort x = 0; x < lvl.Width; x++) { block.BlockID = lvl.blocks[index]; block.ExtID = 0; if (block.BlockID == Block.custom_block) { block.ExtID = lvl.GetExtTile(x, y, z); } if (fixGrass && lvl.Props[block.Index].GrassIndex != Block.Invalid) { above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY]; above.ExtID = 0; if (above.BlockID == Block.custom_block) { above.ExtID = lvl.GetExtTile(x, (ushort)(y + 1), z); } ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex); if (lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, grass) == 2) { buffer.Add(index, grass.BlockID, grass.ExtID); totalFixed++; } } else if (fixDirt && lvl.Props[block.Index].DirtIndex != Block.Invalid) { above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY]; above.ExtID = 0; if (above.BlockID == Block.custom_block) { above.ExtID = lvl.GetExtTile(x, (ushort)(y + 1), z); } ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex); if (!lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, dirt) == 2) { buffer.Add(index, dirt.BlockID, dirt.ExtID); totalFixed++; } } index++; } } } buffer.Send(true); }
protected override bool UndoEntry(Player p, string path, Vec3U16[] marks, ref byte[] temp, DateTime start) { Player.UndoPos Pos = default(Player.UndoPos); int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; string[] lines = File.ReadAllText(path).Split(' '); Vec3U16 min = marks[0], max = marks[1]; bool undoArea = min.X != ushort.MaxValue; BufferedBlockSender buffer = new BufferedBlockSender(null); string last = null; // because we have space to end of each entry, need to subtract one otherwise we'll start at a "". for (int i = (lines.Length - 1) / 7; i >= 0; i--) { try { // line format: mapName x y z date oldblock newblock if (!InTime(lines[(i * 7) - 3], start)) { return(false); } Level lvl = LevelInfo.FindExact(lines[(i * 7) - 7]); if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name))) { continue; } if (!undoArea) { min = new Vec3U16(0, 0, 0); max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1)); } if (last == null || last != lvl.name) { buffer.CheckIfSend(true); last = lvl.name; } buffer.level = lvl; Pos.mapName = lvl.name; Pos.x = Convert.ToUInt16(lines[(i * 7) - 6]); Pos.y = Convert.ToUInt16(lines[(i * 7) - 5]); Pos.z = Convert.ToUInt16(lines[(i * 7) - 4]); if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z || Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z) { continue; } Pos.newtype = Convert.ToByte(lines[(i * 7) - 1]); Pos.type = Convert.ToByte(lines[(i * 7) - 2]); UndoBlock(p, lvl, Pos, timeDelta, buffer); } catch { } } buffer.CheckIfSend(true); return(true); }
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 FixDirtAndGrass(Player p, Level lvl, ref int totalFixed) { int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length; BufferedBlockSender buffer = new BufferedBlockSender(lvl); for (int y = 0; y < lvl.Height; y++) { for (int z = 0; z < lvl.Length; z++) { for (int x = 0; x < lvl.Width; x++) { byte block = lvl.blocks[index]; if (block == Block.dirt) { byte above = y == maxY ? Block.air : lvl.blocks[index + oneY], extAbove = 0; if (above == Block.custom_block) { extAbove = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z); } if (Block.LightPass(above, extAbove, lvl.CustomBlockDefs)) { if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, Block.grass)) { buffer.Add(index, Block.grass, 0); totalFixed++; } } } else if (block == Block.grass) { byte above = y == maxY ? Block.air : lvl.blocks[index + oneY], extAbove = 0; if (above == Block.custom_block) { extAbove = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z); } if (!Block.LightPass(above, extAbove, lvl.CustomBlockDefs)) { if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, Block.dirt)) { buffer.Add(index, Block.dirt, 0); totalFixed++; } } } index++; } } } buffer.Send(true); }
public override void Perform(Vec3U16[] marks, Player p, Level lvl, Brush brush) { UndoCache cache = p.UndoBuffer; UndoCacheNode node = cache.Tail; if (node == null) { return; } int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; while (node != null) { lvl = LevelInfo.FindExact(node.MapName); if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name))) { node = node.Prev; continue; } List <UndoCacheItem> items = node.Items; BufferedBlockSender buffer = new BufferedBlockSender(lvl); for (int i = items.Count - 1; i >= 0; i--) { UndoCacheItem item = items[i]; ushort x, y, z; node.Unpack(item.Index, out x, out y, out z); DateTime time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); if (time > End) { continue; } if (time < Start) { buffer.CheckIfSend(true); return; } byte tile, extTile; item.GetBlock(out tile, out extTile); if (lvl.DoBlockchange(p, x, y, z, tile, extTile)) { buffer.Add(lvl.PosToInt(x, y, z), tile, extTile); buffer.CheckIfSend(false); } } buffer.CheckIfSend(true); node = node.Prev; } }
void EndRound(Player winner) { RoundInProgress = false; Alive.Clear(); UpdateAllStatus1(); if (winner != null) { winner.SendMessage("Congratulations, you won this round of NOG!"); // TODO: Money } BufferedBlockSender bulk = new BufferedBlockSender(Map); bulk.Flush(); }
public static void DoHighlight(Stream s, UndoFormat format, UndoFormatArgs args) { BufferedBlockSender buffer = new BufferedBlockSender(args.Player); Level lvl = args.Player.level; foreach (UndoFormatEntry P in format.GetEntries(s, args)) { byte block = P.Block, newBlock = P.NewBlock; byte highlight = (newBlock == Block.air || Block.Convert(block) == Block.water || block == Block.waterstill || Block.Convert(block) == Block.lava || block == Block.lavastill) ? Block.red : Block.green; buffer.Add(lvl.PosToInt(P.X, P.Y, P.Z), highlight, 0); } buffer.Send(true); }
protected internal static void UndoBlock(Player p, Level lvl, Player.UndoPos Pos, int timeDelta, BufferedBlockSender buffer) { byte lvlTile = lvl.GetTile(Pos.x, Pos.y, Pos.z); if (lvlTile == Pos.newtype || Block.Convert(lvlTile) == Block.water || Block.Convert(lvlTile) == Block.lava || lvlTile == Block.grass) { byte newExtType = Pos.newExtType; Pos.newtype = Pos.type; Pos.newExtType = Pos.extType; Pos.extType = newExtType; Pos.type = lvlTile; Pos.timeDelta = timeDelta; if (lvl.DoBlockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, Pos.newExtType)) { buffer.Add(lvl.PosToInt(Pos.x, Pos.y, Pos.z), Pos.newtype, Pos.newExtType); buffer.CheckIfSend(false); } } }
static void Fix(Player p, Level lvl, ref int totalFixed, bool fixGrass, bool fixDirt) { int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length; BufferedBlockSender buffer = new BufferedBlockSender(lvl); BlockID above, block; for (ushort y = 0; y < lvl.Height; y++) { for (ushort z = 0; z < lvl.Length; z++) { for (ushort x = 0; x < lvl.Width; x++) { block = lvl.FastGetBlock(index); if (fixGrass && lvl.Props[block].GrassBlock != Block.Invalid) { above = y == maxY ? Block.Air : lvl.FastGetBlock(index + oneY); BlockID grass = lvl.Props[block].GrassBlock; if (lvl.LightPasses(above) && p.level.TryChangeBlock(p, x, y, z, grass) == ChangeResult.Modified) { buffer.Add(index, grass); totalFixed++; } } else if (fixDirt && lvl.Props[block].DirtBlock != Block.Invalid) { above = y == maxY ? Block.Air : lvl.FastGetBlock(index + oneY); BlockID dirt = lvl.Props[block].DirtBlock; if (!lvl.LightPasses(above) && p.level.TryChangeBlock(p, x, y, z, dirt) == ChangeResult.Modified) { buffer.Add(index, dirt); totalFixed++; } } index++; } } } buffer.Flush(); }
static void FixLight(Player p, Level lvl, ref int totalFixed) { int index = 0; BufferedBlockSender buffer = new BufferedBlockSender(lvl); for (int y = 0; y < lvl.Height - 1; y++) { for (int z = 0; z < lvl.Length; z++) { for (int x = 0; x < lvl.Width; x++) { byte block = lvl.blocks[index]; bool inShadow = false; if (block == Block.dirt) { for (int i = 1; i < (lvl.Height - y); i++) { byte above = lvl.blocks[index + (lvl.Width * lvl.Length) * i], extAbove = 0; if (above == Block.custom_block) { extAbove = lvl.GetExtTile((ushort)x, (ushort)(y + i), (ushort)z); } if (!Block.LightPass(above, extAbove, lvl.CustomBlockDefs)) { inShadow = true; break; } } if (!inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, Block.grass)) { buffer.Add(index, Block.grass, 0); totalFixed++; } } else if (block == Block.grass) { for (int i = 1; i < (lvl.Height - y); i++) { byte above = lvl.blocks[index + (lvl.Width * lvl.Length) * i], extAbove = 0; if (above == Block.custom_block) { extAbove = lvl.GetExtTile((ushort)x, (ushort)(y + i), (ushort)z); } if (!Block.LightPass(above, extAbove, lvl.CustomBlockDefs)) { inShadow = true; break; } } if (inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, Block.dirt)) { buffer.Add(index, Block.dirt, 0); totalFixed++; } } index++; } } } buffer.Send(true); }
static void FixLight(Player p, Level lvl, ref int totalFixed) { int index = 0; BufferedBlockSender buffer = new BufferedBlockSender(lvl); ExtBlock above = default(ExtBlock), block = default(ExtBlock); for (ushort y = 0; y < lvl.Height - 1; y++) { for (ushort z = 0; z < lvl.Length; z++) { for (ushort x = 0; x < lvl.Width; x++) { block.BlockID = lvl.blocks[index]; block.ExtID = 0; bool inShadow = false; if (block.BlockID == Block.custom_block) { block.ExtID = lvl.GetExtTile(x, y, z); } if (lvl.Props[block.Index].GrassIndex != Block.Invalid) { for (int i = 1; i < (lvl.Height - y); i++) { above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i]; above.ExtID = 0; if (above.BlockID == Block.custom_block) { above.ExtID = lvl.GetExtTile(x, (ushort)(y + i), z); } if (!lvl.LightPasses(above)) { inShadow = true; break; } } ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex); if (!inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, grass) == 2) { buffer.Add(index, grass.BlockID, grass.ExtID); totalFixed++; } } else if (lvl.Props[block.Index].DirtIndex != Block.Invalid) { for (int i = 1; i < (lvl.Height - y); i++) { above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i]; above.ExtID = 0; if (above.BlockID == Block.custom_block) { above.ExtID = lvl.GetExtTile(x, (ushort)(y + i), z); } if (!lvl.LightPasses(above)) { inShadow = true; break; } } ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex); if (inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, dirt) == 2) { buffer.Add(index, dirt.BlockID, dirt.ExtID); totalFixed++; } } index++; } } } buffer.Send(true); }
void PerformUndo(Player p, ref Level saveLvl) { UndoCache cache = who.UndoBuffer; UndoCacheNode node = cache.Tail; if (node == null) { return; } Vec3U16 min = Min, max = Max; bool undoArea = min.X != ushort.MaxValue; Player.UndoPos Pos = default(Player.UndoPos); int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; while (node != null) { Level lvl = LevelInfo.FindExact(node.MapName); if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name))) { node = node.Prev; continue; } Pos.mapName = lvl.name; saveLvl = lvl; List <UndoCacheItem> items = node.Items; BufferedBlockSender buffer = new BufferedBlockSender(lvl); if (!undoArea) { min = new Vec3U16(0, 0, 0); max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1)); } for (int i = items.Count - 1; i >= 0; i--) { UndoCacheItem item = items[i]; node.Unpack(item.Index, out Pos.x, out Pos.y, out Pos.z); if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z || Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z) { continue; } DateTime time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); if (time > End) { continue; } if (time < Start) { buffer.CheckIfSend(true); return; } item.GetNewBlock(out Pos.newtype, out Pos.newExtType); item.GetBlock(out Pos.type, out Pos.extType); UndoFile.UndoBlock(p, lvl, Pos, timeDelta, buffer); } buffer.CheckIfSend(true); node = node.Prev; } }
protected override bool UndoEntry(Player p, string path, Vec3U16[] marks, ref byte[] temp, DateTime start) { List <ChunkHeader> list = new List <ChunkHeader>(); int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; Player.UndoPos Pos = default(Player.UndoPos); Vec3U16 min = marks[0], max = marks[1]; bool undoArea = min.X != ushort.MaxValue; UndoCacheItem item = default(UndoCacheItem); using (Stream fs = File.OpenRead(path)) using (BinaryReader r = new BinaryReader(fs)) { ReadHeaders(list, r); for (int i = list.Count - 1; i >= 0; i--) { ChunkHeader chunk = list[i]; Level lvl; if (!CheckChunk(chunk, start, p, out lvl)) { return(false); } if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name))) { continue; } BufferedBlockSender buffer = new BufferedBlockSender(lvl); if (!undoArea) { min = new Vec3U16(0, 0, 0); max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1)); } Pos.mapName = chunk.LevelName; fs.Seek(chunk.DataPosition, SeekOrigin.Begin); if (temp == null) { temp = new byte[ushort.MaxValue * entrySize]; } fs.Read(temp, 0, chunk.Entries * entrySize); for (int j = chunk.Entries - 1; j >= 0; j--) { int offset = j * entrySize; item.Flags = U16(temp, offset + 0); DateTime time = chunk.BaseTime.AddTicks((item.Flags & 0x3FFF) * TimeSpan.TicksPerSecond); if (time < start) { buffer.CheckIfSend(true); return(false); } int index = I32(temp, offset + 2); Pos.x = (ushort)(index % chunk.Width); Pos.y = (ushort)((index / chunk.Width) / chunk.Length); Pos.z = (ushort)((index / chunk.Width) % chunk.Length); if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z || Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z) { continue; } item.Type = temp[offset + 6]; item.NewType = temp[offset + 7]; item.GetBlock(out Pos.type, out Pos.extType); item.GetNewBlock(out Pos.newtype, out Pos.newExtType); UndoBlock(p, lvl, Pos, timeDelta, buffer); } buffer.CheckIfSend(true); } } return(true); }