diff --git a/MCGalaxy/Commands/other/CmdFly.cs b/MCGalaxy/Commands/other/CmdFly.cs index 746aa1742..df10d1290 100644 --- a/MCGalaxy/Commands/other/CmdFly.cs +++ b/MCGalaxy/Commands/other/CmdFly.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Threading; using MCGalaxy.Maths; +using MCGalaxy.Tasks; namespace MCGalaxy.Commands.Misc { public sealed class CmdFly : Command { @@ -36,61 +37,71 @@ namespace MCGalaxy.Commands.Misc { p.isFlying = !p.isFlying; if (!p.isFlying) return; - Player.Message(p, "You are now flying. &cJump!"); - - Thread flyThread = new Thread(() => FlyThread(p)); - flyThread.Name = "MCG_Fly"; - flyThread.Start(); - } - - void FlyThread(Player p) { - Position oldpos = default(Position); - List last = new List(), next = new List(); - while (p.isFlying && !p.disconnected) - DoFly(p, ref oldpos, last, next); - - foreach (Vec3U16 cP in last) - p.SendBlockchange(cP.X, cP.Y, cP.Z, ExtBlock.Air); - Player.Message(p, "Stopped flying"); - } - - void DoFly(Player p, ref Position old, List last, List next) { - Thread.Sleep(20); - if (p.Pos == old) return; - try { - int x = p.Pos.BlockX, z = p.Pos.BlockZ; - int y = (p.Pos.Y - 60) / 32; - ExtBlock glass = (ExtBlock)Block.glass; + Player.Message(p, "You are now flying. &cJump!"); + + FlyState state = new FlyState(); + state.player = p; + SchedulerTask task = new SchedulerTask(FlyCallback, state, TimeSpan.Zero, true); + p.CriticalTasks.Add(task); + } + + class FlyState { + public Player player; + public Position oldPos = default(Position); + public List last = new List(); + public List next = new List(); + } + + static void FlyCallback(SchedulerTask task) { + FlyState state = (FlyState)task.State; + Player p = state.player; + if (state.player.isFlying) { DoFly(state); return; } + + foreach (Vec3U16 cP in state.last) { + p.SendBlockchange(cP.X, cP.Y, cP.Z, ExtBlock.Air); + } + + Player.Message(p, "Stopped flying"); + task.Repeating = false; + } - for (int yy = y - 1; yy <= y; yy++) - for (int zz = z - 2; zz <= z + 2; zz++) - for (int xx = x - 2; xx <= x + 2; xx++) - { - ushort offX = (ushort)xx, offY = (ushort)yy, offZ = (ushort)zz; - if (p.level.GetTile(offX, offY, offZ) != Block.air) continue; - - Vec3U16 pos; - pos.X = offX; pos.Y = offY; pos.Z = offZ; - next.Add(pos); - } + static void DoFly(FlyState state) { + Player p = state.player; + if (p.Pos == state.oldPos) return; + + int x = p.Pos.BlockX, z = p.Pos.BlockZ; + int y = (p.Pos.Y - 60) / 32; + ExtBlock glass = (ExtBlock)Block.glass; + + for (int yy = y - 1; yy <= y; yy++) + for (int zz = z - 2; zz <= z + 2; zz++) + for (int xx = x - 2; xx <= x + 2; xx++) + { + ushort offX = (ushort)xx, offY = (ushort)yy, offZ = (ushort)zz; + if (p.level.GetTile(offX, offY, offZ) != Block.air) continue; - foreach (Vec3U16 P in next) { - if (last.Contains(P)) continue; - last.Add(P); - p.SendBlockchange(P.X, P.Y, P.Z, glass); - } + Vec3U16 pos; + pos.X = offX; pos.Y = offY; pos.Z = offZ; + state.next.Add(pos); + } + + foreach (Vec3U16 P in state.next) { + if (state.last.Contains(P)) continue; + state.last.Add(P); + p.SendBlockchange(P.X, P.Y, P.Z, glass); + } + + for (int i = 0; i < state.last.Count; i++) { + Vec3U16 P = state.last[i]; + if (state.next.Contains(P)) continue; - for (int i = 0; i < last.Count; i++) { - Vec3U16 P = last[i]; - if (next.Contains(P)) continue; - - p.SendBlockchange(P.X, P.Y, P.Z, ExtBlock.Air); - last.RemoveAt(i); i--; - } - next.Clear(); - } catch (Exception ex) { Server.ErrorLog(ex); } - old = p.Pos; + p.SendBlockchange(P.X, P.Y, P.Z, ExtBlock.Air); + state.last.RemoveAt(i); i--; + } + + state.next.Clear(); + state.oldPos = p.Pos; } public override void Help(Player p) { diff --git a/MCGalaxy/Player/Player.Fields.cs b/MCGalaxy/Player/Player.Fields.cs index 7c796be16..58016b64c 100644 --- a/MCGalaxy/Player/Player.Fields.cs +++ b/MCGalaxy/Player/Player.Fields.cs @@ -23,6 +23,7 @@ using MCGalaxy.Undo; using MCGalaxy.Maths; using MCGalaxy.Events; using MCGalaxy.Network; +using MCGalaxy.Tasks; namespace MCGalaxy { @@ -146,6 +147,7 @@ namespace MCGalaxy { public bool staticCommands = false; public DateTime ZoneSpam; + public VolatileArray CriticalTasks = new VolatileArray(false); public bool aiming; public bool isFlying = false; diff --git a/MCGalaxy/Player/Player.cs b/MCGalaxy/Player/Player.cs index 8fdb8563d..d0a6fd5e7 100644 --- a/MCGalaxy/Player/Player.cs +++ b/MCGalaxy/Player/Player.cs @@ -276,6 +276,7 @@ namespace MCGalaxy { leftServer = true; if (chatMsg != null) chatMsg = Colors.EscapeColors(chatMsg); discMsg = Colors.EscapeColors(discMsg); + CriticalTasks.Clear(); //Umm...fixed? if (name == "") { diff --git a/MCGalaxy/Server/Tasks/ServerTasks.cs b/MCGalaxy/Server/Tasks/ServerTasks.cs index 2db9d8cbc..a17677e5b 100644 --- a/MCGalaxy/Server/Tasks/ServerTasks.cs +++ b/MCGalaxy/Server/Tasks/ServerTasks.cs @@ -28,43 +28,54 @@ namespace MCGalaxy.Tasks { internal static void LocationChecks(SchedulerTask task) { Player[] players = PlayerInfo.Online.Items; - players = PlayerInfo.Online.Items; + players = PlayerInfo.Online.Items; int delay = players.Length == 0 ? 100 : 20; task.Delay = TimeSpan.FromMilliseconds(delay); for (int i = 0; i < players.Length; i++) { try { - Player p = players[i]; - - if (p.following != "") { - Player who = PlayerInfo.FindExact(p.following); - if (who == null || who.level != p.level) { - p.following = ""; - if (!p.canBuild) - p.canBuild = true; - if (who != null && who.possess == p.name) - who.possess = ""; - continue; - } - - p.SendPos(Entities.SelfID, who.Pos, who.Rot); - } else if (p.possess != "") { - Player who = PlayerInfo.FindExact(p.possess); - if (who == null || who.level != p.level) - p.possess = ""; - } - - Vec3U16 P = (Vec3U16)p.Pos.BlockCoords; - if (p.level.Death) - p.CheckSurvival(P.X, P.Y, P.Z); - p.CheckBlock(); - p.oldIndex = p.level.PosToInt(P.X, P.Y, P.Z); + TickPlayer(players[i]); } catch (Exception e) { Server.ErrorLog(e); } } } + static void TickPlayer(Player p) { + if (p.following != "") { + Player who = PlayerInfo.FindExact(p.following); + if (who == null || who.level != p.level) { + p.following = ""; + if (!p.canBuild) + p.canBuild = true; + if (who != null && who.possess == p.name) + who.possess = ""; + return; + } + + p.SendPos(Entities.SelfID, who.Pos, who.Rot); + } else if (p.possess != "") { + Player who = PlayerInfo.FindExact(p.possess); + if (who == null || who.level != p.level) + p.possess = ""; + } + + Vec3U16 P = (Vec3U16)p.Pos.BlockCoords; + if (p.level.Death) + p.CheckSurvival(P.X, P.Y, P.Z); + p.CheckBlock(); + p.oldIndex = p.level.PosToInt(P.X, P.Y, P.Z); + + SchedulerTask[] tasks = p.CriticalTasks.Items; + for (int i = 0; i < tasks.Length; i++) { + SchedulerTask task = tasks[i]; + task.Callback(task); + + if (task.Repeating) continue; + p.CriticalTasks.Remove(task); + } + } + internal static void UpdateEntityPositions(SchedulerTask task) { Entities.GlobalUpdate(); PlayerBot.GlobalUpdatePosition();