From 3477473a793f5509fd18863813f3b442a93dbe1e Mon Sep 17 00:00:00 2001 From: LeChosenOne Date: Fri, 27 Jun 2014 14:44:09 -0400 Subject: [PATCH] [Unstable] Dual heartbeat and /spy --- AutoRank/AutoRank.cs | 2 +- AutoRank/Settings.cs | 14 +- HeartBeat/HeartbeatSaver.cs | 4 +- ToDo.txt | 6 - fCraft/Commands/BuildingCommands.cs | 4 +- fCraft/Commands/ChatCommands.cs | 21 --- fCraft/Commands/FunCommands.cs | 5 - fCraft/Commands/InfoCommands.cs | 6 +- fCraft/Commands/ModerationCommands.cs | 60 ++++++++- fCraft/Commands/WorldCommands.cs | 22 ++-- fCraft/Games/CTF.cs | 18 +-- fCraft/Games/FFA.cs | 4 +- fCraft/Games/TeamDeathMatch.cs | 6 +- fCraft/Network/CPE.cs | 12 +- fCraft/Network/Heartbeat.cs | 17 +-- fCraft/Network/Player.Networking.cs | 148 ++++++++++++++-------- fCraft/Physics/ParticleSystem.cs | 12 +- fCraft/Player/Bot.cs | 4 +- fCraft/Player/Player.cs | 22 +++- fCraft/System/Server.cs | 176 +++++++++++++++----------- fCraft/Utils/Paths.cs | 36 +++--- fCraft/World/Map.cs | 9 +- zLegendCraft Changelog.txt | 7 +- 23 files changed, 359 insertions(+), 256 deletions(-) diff --git a/AutoRank/AutoRank.cs b/AutoRank/AutoRank.cs index b8715cd8..59369ac5 100644 --- a/AutoRank/AutoRank.cs +++ b/AutoRank/AutoRank.cs @@ -45,7 +45,7 @@ public AutoRank() private void AutoRank_Load(object sender, EventArgs e) { - if (!File.Exists("ref/config.xml")) + if (!File.Exists("config.xml")) { MessageBox.Show("Warning, config.xml not found. Closing Autorank program."); this.Close(); diff --git a/AutoRank/Settings.cs b/AutoRank/Settings.cs index 904c3b6c..3dc7f344 100644 --- a/AutoRank/Settings.cs +++ b/AutoRank/Settings.cs @@ -41,15 +41,15 @@ public static class Settings //Save TreeList data to xml public static void Save() { - if (File.Exists("ref/Autorank.xml")) + if (File.Exists("Autorank.xml")) { - File.Delete("ref/Autorank.xml"); + File.Delete("Autorank.xml"); } XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; - XmlWriter writer = XmlWriter.Create("ref/Autorank.xml", settings); + XmlWriter writer = XmlWriter.Create("Autorank.xml", settings); writer.WriteStartDocument(); writer.WriteComment("This file was generated by the LegendCraft Autorank program."); @@ -110,12 +110,12 @@ public static void Load() bool layered = false; //since Load() is more complicated than Save(), i'll use XDocument instead of XMLReader - if (!File.Exists("ref/Autorank.xml")) + if (!File.Exists("Autorank.xml")) { MessageBox.Show("Autorank.xml not found, using defaults. Ignore this message if this is your first time running autorank."); return; } - XDocument doc = XDocument.Load("ref/Autorank.xml"); + XDocument doc = XDocument.Load("Autorank.xml"); XElement docConfig = doc.Root; //load each rank change @@ -146,12 +146,12 @@ public static void Load() /// public static void LoadRankList() { - if (!File.Exists("ref/config.xml")) + if (!File.Exists("config.xml")) { MessageBox.Show("Error, config.xml is either missing or damaged. Please make sure configGUI.exe was run prior to autorank. Program will now close."); Application.Exit(); } - XDocument doc = XDocument.Load("ref/config.xml"); + XDocument doc = XDocument.Load("config.xml"); XElement docConfig = doc.Root; XElement rankList = docConfig.Element("Ranks"); XElement[] rankDefinitionList = rankList.Elements("Rank").ToArray(); diff --git a/HeartBeat/HeartbeatSaver.cs b/HeartBeat/HeartbeatSaver.cs index fadf5fef..23d388c6 100644 --- a/HeartBeat/HeartbeatSaver.cs +++ b/HeartBeat/HeartbeatSaver.cs @@ -23,8 +23,8 @@ static class HeartbeatSaver static readonly RequestCachePolicy CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.BypassCache); - const string UrlFileName = "ref/externalurl.txt", - DefaultDataFileName = "ref/heartbeatdata.txt", + const string UrlFileName = "externalurl.txt", + DefaultDataFileName = "heartbeatdata.txt", UserAgent = "fCraft HeartbeatSaver"; static string heartbeatDataFileName; diff --git a/ToDo.txt b/ToDo.txt index 8811f30e..e69de29b 100644 --- a/ToDo.txt +++ b/ToDo.txt @@ -1,6 +0,0 @@ -LegendCraft v2.4.0 Roadmap -[]Finish adding in all CPE optionals -[]Work on bots -[]Capture the Flag -[x]Seduce Women, Obtain Currency -[]More to come \ No newline at end of file diff --git a/fCraft/Commands/BuildingCommands.cs b/fCraft/Commands/BuildingCommands.cs index bf935d66..0e3c5503 100644 --- a/fCraft/Commands/BuildingCommands.cs +++ b/fCraft/Commands/BuildingCommands.cs @@ -291,7 +291,7 @@ static void HighlightHandler(Player player, Command cmd) if (worldTarget == "all") { player.Message("_Removing all highlights {0}_", ConfigKey.ServerName.GetString()); - foreach (Player p in Server.Players.Where(p => p.ClassiCube)) + foreach (Player p in Server.Players.Where(p => p.CPE)) { //physically remove all highlights where players are connected to specific worlds if (p.World.Highlights.Count > 0) @@ -325,7 +325,7 @@ static void HighlightHandler(Player player, Command cmd) } player.Message("_Removing all highlights on {0}_", targetWorld.Name); - foreach (Player p in targetWorld.Players.Where(p => p.ClassiCube)) + foreach (Player p in targetWorld.Players.Where(p => p.CPE)) { foreach (var i in targetWorld.Highlights.Values) { diff --git a/fCraft/Commands/ChatCommands.cs b/fCraft/Commands/ChatCommands.cs index 5c285985..c3844a52 100644 --- a/fCraft/Commands/ChatCommands.cs +++ b/fCraft/Commands/ChatCommands.cs @@ -45,7 +45,6 @@ public static void Init() //CommandManager.RegisterCommand(CdJelly); CommandManager.RegisterCommand(CdMad); CommandManager.RegisterCommand(CdBanHammer); - CommandManager.RegisterCommand(CdCredits); CommandManager.RegisterCommand(CdSTFU); CommandManager.RegisterCommand(CdFortuneCookie); CommandManager.RegisterCommand(CdCalculator); @@ -717,26 +716,6 @@ static void STFUHandler(Player player, Command cmd) } } - - - static readonly CommandDescriptor CdCredits = new CommandDescriptor - { - Name = "Credits", - Aliases = new string[] { "credit" }, - Category = CommandCategory.Chat, - Permissions = new[] { Permission.Chat }, - IsConsoleSafe = true, - Usage = "/credits", - Help = "&8Displays the credits of LegendCraft", - NotRepeatable = true, - Handler = CreditsHandler, - }; - - - public static void CreditsHandler(Player player, Command cmd) - { - player.Message(" LegendCraft was developed by LeChosenOne, DingusBungus and Eeyle. LegendCraft was based off of 800Craft developed by Jonty800, GlennMR, and Lao Tszy. 800Craft was based off of fCraft developed by fragmer. Thanks to everyone who contributed to these softwares. And thank you for using LegendCraft!"); - } static readonly CommandDescriptor CdBanHammer = new CommandDescriptor { Name = "BanHammer", diff --git a/fCraft/Commands/FunCommands.cs b/fCraft/Commands/FunCommands.cs index c11e2733..039038c4 100644 --- a/fCraft/Commands/FunCommands.cs +++ b/fCraft/Commands/FunCommands.cs @@ -153,11 +153,6 @@ public static void PlayerMoved(object sender, fCraft.Events.PlayerMovingEventArg static void BotHandler(Player player, Command cmd) { - if (!player.ClassiCube || !Heartbeat.ClassiCube()) - { - player.Message("Bots can only be used on ClassiCube servers and clients!"); - return; - } string option = cmd.Next(); //take in the option arg if (string.IsNullOrEmpty(option)) //empty? return, otherwise continue { diff --git a/fCraft/Commands/InfoCommands.cs b/fCraft/Commands/InfoCommands.cs index a23a3915..64210294 100644 --- a/fCraft/Commands/InfoCommands.cs +++ b/fCraft/Commands/InfoCommands.cs @@ -282,14 +282,10 @@ internal static void AboutHandler(Player player, Command cmd) break; } case "server": - { - ServerInfoHandler(player, new Command("/sinfo")); - break; - } case "software": case "version": { - ChatCommands.CreditsHandler(player, new Command("/credits")); + ServerInfoHandler(player, new Command("/sinfo")); break; } case "rank": diff --git a/fCraft/Commands/ModerationCommands.cs b/fCraft/Commands/ModerationCommands.cs index 9b634f62..31911097 100644 --- a/fCraft/Commands/ModerationCommands.cs +++ b/fCraft/Commands/ModerationCommands.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.IO; using fCraft.Events; using JetBrains.Annotations; -using System.IO; namespace fCraft { /// @@ -86,6 +86,7 @@ static class ModerationCommands { CommandManager.RegisterCommand(CdForceHold); CommandManager.RegisterCommand(CdGetBlock); //CommandManager.RegisterCommand(CdTPA); + CommandManager.RegisterCommand(CdSpy); } #region LegendCraft @@ -108,6 +109,46 @@ static class ModerationCommands { OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ + + static readonly CommandDescriptor CdSpy = new CommandDescriptor + { + Name = "Spy", + Aliases = new[] { "NSA" }, + IsConsoleSafe = true, + Category = CommandCategory.Moderation, + Permissions = new[] { Permission.Spectate }, + Help = "&SReturns all commands and PMs for a player. Use /spy [player] to toggle spying.", + Usage = "&S/Spy [player]", + Handler = SpyHandler + }; + + private static void SpyHandler(Player player, Command cmd) + { + string p = cmd.Next(); + if (String.IsNullOrEmpty(p)) + { + player.Message("Usage is /spy [player]! Use /spy [player] to toggle spying."); + return; + } + + Player pPlayer = Server.FindPlayerOrPrintMatches(player, p, true, true); + if (pPlayer == null) + { + // no one found + return; + } + + if (pPlayer.Spies.Contains(player)) + { + player.Message("You are no longer spying on {0}!", p); + pPlayer.Spies.Remove(player); + } + else + { + player.Message("Now spying on {0}! Use /spy {0} to stop spying on them.", p); + pPlayer.Spies.Add(player); + } + } static readonly CommandDescriptor CdGetBlock = new CommandDescriptor { Name = "GetBlock", @@ -134,7 +175,7 @@ private static void GetBlockHandler(Player player, Command cmd) return; } - if (!targetPlayer.ClassiCube) + if (!targetPlayer.CPE) { player.Message("You can only use /GetBlock on ClassiCube players!"); } @@ -155,7 +196,7 @@ private static void GetBlockHandler(Player player, Command cmd) private static void FHHandler(Player player, Command cmd) { - if (!Heartbeat.ClassiCube() || !player.ClassiCube) + if (!Heartbeat.ClassiCube() || !player.CPE) { player.Message("This is a ClassiCube only command!"); return; @@ -173,7 +214,7 @@ private static void FHHandler(Player player, Command cmd) return; } - if (!p.ClassiCube) + if (!p.CPE) { player.Message("You can only use /ForceHold on ClassiCube players!"); } @@ -215,7 +256,7 @@ private static void FHHandler(Player player, Command cmd) private static void AnnounceHandler(Player player, Command cmd) { - if (!Heartbeat.ClassiCube() || !player.ClassiCube) + if (!Heartbeat.ClassiCube() || !player.CPE) { player.Message("This is a ClassiCube only command!"); return; @@ -262,7 +303,7 @@ private static void AnnounceHandler(Player player, Command cmd) Packet packet = PacketWriter.MakeSpecialMessage(100, message); foreach (Player p in targetPlayers) { - if (p.ClassiCube) + if (p.CPE) { p.Send(packet); } @@ -389,6 +430,11 @@ private static void AutoRankHandler(Player player, Command cmd) private static void SetClickHandler(Player player, Command cmd) { + if (!Heartbeat.ClassiCube()) + { + player.Message("This command can only be used on ClassiCube server!"); + return; + } string targetName = cmd.Next(); if (String.IsNullOrEmpty(targetName)) { @@ -401,7 +447,7 @@ private static void SetClickHandler(Player player, Command cmd) player.MessageNoPlayer(targetName); return; } - if (!target.ClassiCube) + if (!target.CPE) { player.Message("You can only use /SetClickDistance on ClassiCube players!"); } diff --git a/fCraft/Commands/WorldCommands.cs b/fCraft/Commands/WorldCommands.cs index 4763e202..fa3bdb8d 100644 --- a/fCraft/Commands/WorldCommands.cs +++ b/fCraft/Commands/WorldCommands.cs @@ -372,7 +372,7 @@ static void MEditHandler(Player player, Command cmd) //Packet appearence = PacketWriter.MakeEnvSetMapAppearance("", world.sideBlock, world.edgeBlock, world.sideLevel); update once supported Packet weather = PacketWriter.MakeEnvWeatherAppearance((byte)world.WeatherCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(sky); p.Send(cloud); @@ -551,7 +551,7 @@ static void MEditHandler(Player player, Command cmd) world.CloudColorCC = "#ffffff"; Packet cloudPacketNormal = PacketWriter.MakeEnvSetColor((byte)1, (world.CloudColorCC)); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(cloudPacketNormal); } @@ -571,7 +571,7 @@ static void MEditHandler(Player player, Command cmd) world.CloudColorCC = setting; player.Message("The map texture has been edited."); Packet cloudPacket = PacketWriter.MakeEnvSetColor((byte)1, world.CloudColorCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(cloudPacket); } @@ -589,7 +589,7 @@ static void MEditHandler(Player player, Command cmd) world.FogColorCC = "#ffffff"; Packet fogPacketNormal = PacketWriter.MakeEnvSetColor((byte)2, world.FogColorCC.Replace("#", "")); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(fogPacketNormal); } @@ -609,7 +609,7 @@ static void MEditHandler(Player player, Command cmd) world.FogColorCC = setting; player.Message("The map texture has been edited."); Packet fogPacket = PacketWriter.MakeEnvSetColor((byte)2, world.FogColorCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(fogPacket); } @@ -627,7 +627,7 @@ static void MEditHandler(Player player, Command cmd) world.SkyColorCC = "#99CCFF"; Packet skyPacketNormal = PacketWriter.MakeEnvSetColor((byte)0, world.SkyColorCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(skyPacketNormal); } @@ -648,7 +648,7 @@ static void MEditHandler(Player player, Command cmd) world.SkyColorCC = setting; player.Message("The map texture has been edited."); Packet skyPacket = PacketWriter.MakeEnvSetColor((byte)0, world.SkyColorCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(skyPacket); } @@ -670,7 +670,7 @@ static void MEditHandler(Player player, Command cmd) world.WeatherCC = 0; Packet weatherPacketNormal = PacketWriter.MakeEnvWeatherAppearance((byte)world.WeatherCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(weatherPacketNormal); } @@ -682,7 +682,7 @@ static void MEditHandler(Player player, Command cmd) world.WeatherCC = 1; Packet weatherPacketRain = PacketWriter.MakeEnvWeatherAppearance((byte)world.WeatherCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(weatherPacketRain); } @@ -695,7 +695,7 @@ static void MEditHandler(Player player, Command cmd) world.WeatherCC = 2; Packet weatherPacketSnow = PacketWriter.MakeEnvWeatherAppearance((byte)world.WeatherCC); - foreach (Player p in world.Players.Where(p => p.ClassiCube)) + foreach (Player p in world.Players.Where(p => p.CPE)) { p.Send(weatherPacketSnow); } @@ -2685,7 +2685,7 @@ static void BlockInfoSchedulerCallback(SchedulerTask task) static void EnvHandler(Player player, Command cmd) { - if (Heartbeat.ClassiCube() || player.ClassiCube) + if (Heartbeat.ClassiCube() || player.CPE) { player.Message("/Env is a Minecraft.net only command.");//add reference /mapedit here once it works. return; diff --git a/fCraft/Games/CTF.cs b/fCraft/Games/CTF.cs index 483fa8d3..ff14f372 100644 --- a/fCraft/Games/CTF.cs +++ b/fCraft/Games/CTF.cs @@ -140,7 +140,7 @@ public static void Interval(SchedulerTask task) { foreach (Player p in world_.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f"));//super hacky way to remove announcements, simply send a color code and call it a day } @@ -266,7 +266,7 @@ public static void Interval(SchedulerTask task) } foreach (Player p in world_.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { //loop through each block ID for (int i = 1; i < 65; i++) @@ -316,7 +316,7 @@ public static void Interval(SchedulerTask task) //send an announcement (Will be sent as a normal message to non classicube players) p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&cLet the Games Begin!")); - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { //set player health p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]")); @@ -571,7 +571,7 @@ select blue p.entityChanged = true; //reset all special messages - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSetBlockPermissions((byte)0, true, true)); p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); @@ -703,7 +703,7 @@ public static void PowerUp(Player p) healthBar = "&f[&8--------&f]"; } - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar)); } @@ -720,7 +720,7 @@ public static void PowerUp(Player p) world_.Players.Message("&f{0} has been healed for 100 hp.", p.Name); p.Info.Health = 100; - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&8--------&f]")); } @@ -863,7 +863,7 @@ public static void PowerUp(Player p) } foreach (Player pl in world_.Players) { - if (pl.ClassiCube && Heartbeat.ClassiCube()) + if (pl.CPE && Heartbeat.ClassiCube()) { pl.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore)); } @@ -912,7 +912,7 @@ public static void PlayerMoving(object poo, fCraft.Events.PlayerMovingEventArgs p.World.Map.QueueUpdate(blockUpdate); //set game score - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore)); p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag")); @@ -948,7 +948,7 @@ public static void PlayerMoving(object poo, fCraft.Events.PlayerMovingEventArgs p.World.Map.QueueUpdate(blockUpdate); //set game scorecboard - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore)); p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag")); diff --git a/fCraft/Games/FFA.cs b/fCraft/Games/FFA.cs index ac6402e9..74aa3009 100644 --- a/fCraft/Games/FFA.cs +++ b/fCraft/Games/FFA.cs @@ -134,7 +134,7 @@ public static void Interval(SchedulerTask task) { foreach (Player p in world_.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f"));//super hacky way to remove announcement, simply send a color code and call it a day } @@ -306,7 +306,7 @@ public static List GetScoreList() p.JoinWorld(p.World, WorldChangeReason.Rejoin); //reset all special messages - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); diff --git a/fCraft/Games/TeamDeathMatch.cs b/fCraft/Games/TeamDeathMatch.cs index af9bdd81..6dc7c421 100644 --- a/fCraft/Games/TeamDeathMatch.cs +++ b/fCraft/Games/TeamDeathMatch.cs @@ -133,7 +133,7 @@ public static void Interval(SchedulerTask task) { foreach (Player p in world_.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f"));//super hacky way to remove announcement, simply send a color code and call it a day } @@ -175,7 +175,7 @@ public static void Interval(SchedulerTask task) //send an announcement p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&cLet the Games Begin!")); - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { //set player's health p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]")); @@ -380,7 +380,7 @@ public static void DisplayScoreBoard() p.entityChanged = true; //reset all special messages - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); diff --git a/fCraft/Network/CPE.cs b/fCraft/Network/CPE.cs index 1c7eca0e..715e84a8 100644 --- a/fCraft/Network/CPE.cs +++ b/fCraft/Network/CPE.cs @@ -311,10 +311,10 @@ static void ToNetOrder(int number, [NotNull] byte[] arr, int offset) public sealed partial class Map { public const Block MaxCustomBlockType = Block.StoneBrick; - readonly static Block[] FallbackBlocks = new Block[256]; + public readonly static Block[] FallbackBlocks = new Block[256]; - - static void DefineFallbackBlocks() + //fallback for all blocks, blocks 49 (obsidian) and under (non cpe blocks) fallback to themselves + public static void DefineFallbackBlocks() { for (int i = 0; i <= (int)Block.Obsidian; i++) { @@ -344,12 +344,6 @@ public static Block GetFallbackBlock(Block block) return FallbackBlocks[(int)block]; } - public static byte GetFallbackBlock(byte bite) - { - int block = (int)bite; - return (byte)FallbackBlocks[block]; - } - public const Block MaxLegalBlockType = Block.Obsidian; public unsafe byte[] GetFallbackMap() { diff --git a/fCraft/Network/Heartbeat.cs b/fCraft/Network/Heartbeat.cs index 772c2dde..4326ed3f 100644 --- a/fCraft/Network/Heartbeat.cs +++ b/fCraft/Network/Heartbeat.cs @@ -50,8 +50,8 @@ public static bool ClassiCube() /// Known only to this server, heartbeat servers, and webpanel. public static string Salt { get; internal set; } - /// Second salt - /// used if server is running a dual heartbeat + /// Second salt. + /// Used if server is running a dual heartbeat public static string Salt2 { get; internal set; } // Dns lookup, to make sure that IPv4 is preferred for heartbeats @@ -170,7 +170,7 @@ static void SendClassiCubeBeat() { return; } - minecraftNetRequest = CreateRequest(data.CreateUri()); + minecraftNetRequest = CreateRequest(data.CreateUri(Salt2)); var state = new HeartbeatRequestState(minecraftNetRequest, data, true); minecraftNetRequest.BeginGetResponse(ResponseCallback, state); } @@ -182,7 +182,7 @@ static void SendMinecraftNetBeat() { return; } - minecraftNetRequest = CreateRequest(data.CreateUri()); + minecraftNetRequest = CreateRequest(data.CreateUri(Salt)); var state = new HeartbeatRequestState(minecraftNetRequest, data, true); minecraftNetRequest.BeginGetResponse(ResponseCallback, state); } @@ -429,12 +429,13 @@ internal HeartbeatData([NotNull] Uri heartbeatUri) public int ProtocolVersion { get; set; } public Dictionary CustomData { get; private set; } - public Uri CreateUri() + public Uri CreateUri(string salt_) { UriBuilder ub = new UriBuilder(HeartbeatUri); StringBuilder sb = new StringBuilder(); - if (ConfigKey.HeartbeatUrl.GetString() == "ClassiCube.net") + //if we are sending to CC + if (salt_ == Salt2) { sb.AppendFormat("public={0}&max={1}&users={2}&port={3}&software={7}&version={4}&salt={5}&name={6}", IsPublic, @@ -442,7 +443,7 @@ public Uri CreateUri() PlayerCount, Port, ProtocolVersion, - Uri.EscapeDataString(Salt2), + Uri.EscapeDataString(salt_), Uri.EscapeDataString(ServerName), "LegendCraft v" + Updater.LatestStable); foreach (var pair in CustomData) @@ -461,7 +462,7 @@ public Uri CreateUri() PlayerCount, Port, ProtocolVersion, - Uri.EscapeDataString(Salt), + Uri.EscapeDataString(salt_), Uri.EscapeDataString(ServerName)); foreach (var pair in CustomData) { diff --git a/fCraft/Network/Player.Networking.cs b/fCraft/Network/Player.Networking.cs index 0dfbcb0f..c809a5e8 100644 --- a/fCraft/Network/Player.Networking.cs +++ b/fCraft/Network/Player.Networking.cs @@ -8,15 +8,16 @@ using System.Net.Sockets; using System.Text; using System.Threading; +using System.Text.RegularExpressions; +using System.Collections.Concurrent; +using System.Xml.Linq; +using System.Xml; +using System.Security.Cryptography; using fCraft.AutoRank; using fCraft.Drawing; using fCraft.Events; using fCraft.MapConversion; using JetBrains.Annotations; -using System.Text.RegularExpressions; -using System.Collections.Concurrent; -using System.Xml.Linq; -using System.Xml; namespace fCraft { @@ -324,6 +325,12 @@ bool ProcessMessagePacket() reader.ReadByte(); string message = ReadString(); + if (String.IsNullOrEmpty(message)) + { + Message("&WError with handling processed message!"); + return false; + } + if (!IsSuper && message.StartsWith("/womid ")) { IsUsingWoM = true; @@ -370,7 +377,7 @@ void ProcessMovementPacket() { BytesReceived += 10; byte me = reader.ReadByte(); - if (ClassiCube) + if (CPE) { try { @@ -638,13 +645,17 @@ bool LoginSequence() return false; } + //raw name from player ID packet from the client string givenName = ReadString(); string packetPlayerName = givenName; //make a copy of the full name, in case Mojang support is needed bool UsedMojang = false; - string verificationCode = ReadString(); - byte magicNum = reader.ReadByte(); //for ClassiCube protocol check (previously unused) - ClassiCube = (magicNum == 0x42); + //verificication key found in player ID packet + string verificationKey = ReadString(); + ClassiCube = Server.VerifyName(givenName, verificationKey, Heartbeat.Salt2); + + byte magicNum = reader.ReadByte(); //for CPE check (previously unused) + CPE = (magicNum == 0x42); Skinname = givenName; BytesReceived += 131; @@ -736,8 +747,8 @@ bool LoginSequence() Info = PlayerDB.FindOrCreateInfoForPlayer(givenName, IP); ResetAllBinds(); - - if (Server.VerifyName(packetPlayerName, verificationCode, Heartbeat.Salt)) + //if the user is not from classicube, go ahead and verify for minecraft + if (!ClassiCube && Server.VerifyName(packetPlayerName, verificationKey, Heartbeat.Salt)) { IsVerified = true; // update capitalization of player's name @@ -752,6 +763,7 @@ bool LoginSequence() } else { + NameVerificationMode nameVerificationMode = ConfigKey.VerifyNames.GetEnum(); string standardMessage = String.Format("Player.LoginSequence: Could not verify player name for {0} ({1}).", @@ -939,7 +951,7 @@ bool LoginSequence() string motd; if (ConfigKey.WoMEnableEnvExtensions.Enabled()) { - if (ClassiCube) + if (CPE) { if (!startingWorld.Hax) { @@ -969,6 +981,21 @@ bool LoginSequence() SendNow(PacketWriter.MakeHandshake(this, serverName, motd)); bool firstTime = (Info.TimesVisited == 1); + + //update fallback blocks for non CPE users + if (!CPE) + { + Map newMap = startingWorld.Map; + for (int i = 0; i < newMap.Blocks.Length; i++) + { + if (newMap.Blocks[i] > 49) + { + newMap.Blocks[i] = (byte)Map.GetFallbackBlock((Block)Enum.GetValues(typeof(Block)).GetValue(newMap.Blocks[i])); + } + } + startingWorld.Map = newMap; + } + if (!JoinWorldNow(startingWorld, true, WorldChangeReason.FirstWorld)) { Logger.Log(LogType.Warning, @@ -1241,6 +1268,21 @@ void ServeCfg() public void JoinWorld([NotNull] World newWorld, WorldChangeReason reason) { if (newWorld == null) throw new ArgumentNullException("newWorld"); + + //update fallback blocks for non CPE users + if (!CPE) + { + Map newMap = newWorld.Map; + for (int i = 0; i < newMap.Blocks.Length; i++) + { + if (newMap.Blocks[i] > 49) + { + newMap.Blocks[i] = (byte)Map.GetFallbackBlock((Block)Enum.GetValues(typeof(Block)).GetValue(newMap.Blocks[i])); + } + } + newWorld.Map = newMap; + } + lock (joinWorldLock) { useWorldSpawn = true; @@ -1258,6 +1300,21 @@ public void JoinWorld([NotNull] World newWorld, WorldChangeReason reason, Positi { throw new ArgumentOutOfRangeException("reason"); } + + //update fallback blocks for non CPE users + if (!CPE) + { + Map newMap = newWorld.Map; + for (int i = 0; i < newMap.Blocks.Length; i++) + { + if (newMap.Blocks[i] > 49) + { + newMap.Blocks[i] = (byte)Map.GetFallbackBlock((Block)Enum.GetValues(typeof(Block)).GetValue(newMap.Blocks[i])); + } + } + newWorld.Map = newMap; + } + lock (joinWorldLock) { useWorldSpawn = false; @@ -1281,6 +1338,20 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World "Use Player.JoinWorld instead."); } + //update fallback blocks for non CPE users + if (!CPE) + { + Map newMap = newWorld.Map; + for (int i = 0; i < newMap.Blocks.Length; i++) + { + if (newMap.Blocks[i] > 49) + { + newMap.Blocks[i] = (byte)Map.GetFallbackBlock((Block)Enum.GetValues(typeof(Block)).GetValue(newMap.Blocks[i])); + } + } + newWorld.Map = newMap; + } + string textLine1 = ConfigKey.ServerName.GetString(); string textLine2; @@ -1295,7 +1366,7 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World textLine2 = "cfg=" + Server.ExternalIP + ":" + Server.Port + "/" + newWorld.Name; } } - else if (ClassiCube && ConfigKey.WoMEnableEnvExtensions.Enabled() && Heartbeat.ClassiCube()) + else if (CPE && ConfigKey.WoMEnableEnvExtensions.Enabled() && Heartbeat.ClassiCube()) { if (!newWorld.Hax) { @@ -1391,21 +1462,6 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World "Player.JoinWorldNow: Sending compressed map ({0} bytes) to {1}.", blockData.Length, Name); - Map map_ = map; - //if not on CC, take all CC blocks (blocks with IDs over 49), and find the fallback version of that block - if (!ClassiCube) - { - for (int i = 0; i < map_.Blocks.Length; i++) - { - if (map_.Blocks[i] > 49) - { - Logger.LogToConsole(map_.Blocks[i].ToString()); - map_.Blocks[i] = Map.GetFallbackBlock(map_.Blocks[i]); - Logger.LogToConsole(map_.Blocks[i].ToString()); - } - } - } - // Transfer the map copy while (mapBytesSent < blockData.Length) { @@ -1435,11 +1491,11 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World client.NoDelay = ConfigKey.LowLatencyMode.Enabled(); // Done sending over level copy - writer.WriteMapEnd(map_); + writer.WriteMapEnd(map); BytesSent += 7; // Sets player's spawn point to map spawn - writer.WriteAddEntity(255, this, map_.Spawn); + writer.WriteAddEntity(255, this, map.Spawn); BytesSent += 74; // Teleport player to the target location @@ -1507,13 +1563,16 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World Info.placingRedFlag = false; //reset all special messages - Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); - Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); - Send(PacketWriter.MakeSpecialMessage((byte)2, "&f")); + if (CPE) + { + Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); + Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); + Send(PacketWriter.MakeSpecialMessage((byte)2, "&f")); + } - if (Heartbeat.ClassiCube() && ClassiCube) + if (Heartbeat.ClassiCube() && CPE) { //update mapedit values //Packet envSetMapAppearance = PacketWriter.MakeEnvSetMapAppearance(World.textureURL, World.sideBlock, World.edgeBlock, World.sideLevel); @@ -1538,7 +1597,7 @@ internal bool JoinWorldNow([NotNull] World newWorld, bool doUseWorldSpawn, World if (bot.World == World) { Send(PacketWriter.MakeAddEntity(bot.ID, bot.Name, bot.Position)); - if (bot.Model != "humanoid") + if (bot.Model != "humanoid" && CPE) { Send(PacketWriter.MakeChangeModel((byte)bot.ID, bot.Model)); } @@ -1733,8 +1792,6 @@ void ResetVisibleEntities() foreach (var pos in entities.Values) { SendNow(PacketWriter.MakeRemoveEntity(pos.Id)); - if (ClassiCube && Heartbeat.ClassiCube()) - SendNow(PacketWriter.MakeExtRemovePlayerName(pos.Id)); } freePlayerIDs.Clear(); for (int i = 1; i <= sbyte.MaxValue; i++) @@ -1846,7 +1903,7 @@ void UpdateVisibleEntities() entity.MarkedForRetention = true; //update player models - if (ClassiCube) + if (CPE) { Send(PacketWriter.MakeChangeModel((byte)entity.Id, otherPlayer.Model)); } @@ -1932,10 +1989,9 @@ void AddEntity([NotNull] Player player, Position newPos) var pos = new VisibleEntity(newPos, freePlayerIDs.Pop(), player.Info.Rank); entities.Add(player, pos); SendNow(PacketWriter.MakeAddEntity(entities[player].Id, player.Info.Rank.Color + player.Skinname, newPos)); - if (ClassiCube && Heartbeat.ClassiCube()) + if (CPE && Heartbeat.ClassiCube()) { SendNow(PacketWriter.MakeExtAddEntity((byte)entities[player].Id, player.ListName, player.Skinname)); - SendNow(PacketWriter.MakeExtAddPlayerName((short)pos.Id, player.Skinname, player.ListName, player.Info.Rank.ClassyName, (byte)player.Info.Rank.Index)); } } } @@ -1947,8 +2003,6 @@ void HideEntity([NotNull] VisibleEntity entity) entity.Hidden = true; entity.LastKnownPosition = VisibleEntity.HiddenPosition; SendNow(PacketWriter.MakeTeleport(entity.Id, VisibleEntity.HiddenPosition)); - if (ClassiCube && Heartbeat.ClassiCube()) - SendNow(PacketWriter.MakeExtRemovePlayerName(entity.Id)); } @@ -1966,19 +2020,15 @@ void ReAddEntity([NotNull] VisibleEntity entity, [NotNull] Player player, Positi if (entity == null) throw new ArgumentNullException("entity"); if (player == null) throw new ArgumentNullException("player"); SendNow(PacketWriter.MakeRemoveEntity(entity.Id)); - if (ClassiCube && Heartbeat.ClassiCube()) + if (CPE && Heartbeat.ClassiCube()) SendNow(PacketWriter.MakeExtRemovePlayerName((short)entity.Id)); - if (player.iName == null) - SendNow(PacketWriter.MakeAddEntity(entities[player].Id, player.Info.Rank.Color + player.Skinname, newPos)); - else - SendNow(PacketWriter.MakeAddEntity(entities[player].Id, player.iName, newPos)); - if (ClassiCube && Heartbeat.ClassiCube()) + if (CPE && Heartbeat.ClassiCube()) { if (player.iName == null) SendNow(PacketWriter.MakeExtAddEntity((byte)entities[player].Id, player.Skinname, player.Name)); else SendNow(PacketWriter.MakeExtAddEntity((byte)entities[player].Id, player.Skinname, player.iName)); - SendNow(PacketWriter.MakeExtAddPlayerName((short)entity.Id, player.ListName, player.ClassyName, player.Info.Rank.ClassyName, (byte)player.Info.Rank.Index)); + } entity.LastKnownPosition = newPos; } @@ -1988,8 +2038,6 @@ void RemoveEntity([NotNull] Player player) { if (player == null) throw new ArgumentNullException("player"); SendNow(PacketWriter.MakeRemoveEntity(entities[player].Id)); - if (ClassiCube && Heartbeat.ClassiCube()) - SendNow(PacketWriter.MakeExtRemovePlayerName((short)entities[player].Id)); freePlayerIDs.Push(entities[player].Id); entities.Remove(player); } diff --git a/fCraft/Physics/ParticleSystem.cs b/fCraft/Physics/ParticleSystem.cs index 5d20b42b..404b16de 100644 --- a/fCraft/Physics/ParticleSystem.cs +++ b/fCraft/Physics/ParticleSystem.cs @@ -468,7 +468,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i healthBar = "&f[&8--------&f]"; } - if (hitted.ClassiCube && Heartbeat.ClassiCube()) + if (hitted.CPE && Heartbeat.ClassiCube()) { hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar)); } @@ -517,7 +517,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i //revive dead players with 100% health hitted.Info.Health = 100; - if (hitted.ClassiCube && Heartbeat.ClassiCube()) + if (hitted.CPE && Heartbeat.ClassiCube()) { hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]")); } @@ -576,7 +576,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i healthBar = "&f[&8--------&f]"; } hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar)); - if (hitted.ClassiCube && Heartbeat.ClassiCube()) + if (hitted.CPE && Heartbeat.ClassiCube()) { hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar)); } @@ -615,7 +615,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i //update scoreboard for all players foreach (Player p in hitted.World.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + fCraft.TeamDeathMatch.redScore + ",&1 Blue&f: " + fCraft.TeamDeathMatch.blueScore)); } @@ -651,7 +651,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i } foreach (Player p in hitted.World.Players) { - if (p.ClassiCube && Heartbeat.ClassiCube()) + if (p.CPE && Heartbeat.ClassiCube()) { p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&eCurrent Leader&f: " + leader.Name + ", Kills: " + leader.Info.gameKillsFFA)); } @@ -661,7 +661,7 @@ public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref i //revive dead players with 100% health hitted.Info.Health = 100; - if (hitted.ClassiCube && Heartbeat.ClassiCube()) + if (hitted.CPE && Heartbeat.ClassiCube()) { hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]")); } diff --git a/fCraft/Player/Bot.cs b/fCraft/Player/Bot.cs index 44119daf..0db808fe 100644 --- a/fCraft/Player/Bot.cs +++ b/fCraft/Player/Bot.cs @@ -181,7 +181,7 @@ public void changeBotModel(String botModel) return; //something went wrong, model does not exist } - World.Players.Where(p => p.ClassiCube).Send(PacketWriter.MakeChangeModel((byte)ID, botModel)); + World.Players.Where(p => p.CPE).Send(PacketWriter.MakeChangeModel((byte)ID, botModel)); Model = botModel; } @@ -196,7 +196,7 @@ public void Clone(String targetSkin) //something went wrong, player doesn't exist } - World.Players.Where(p => p.ClassiCube).Send(PacketWriter.MakeExtAddEntity((byte)ID, targetSkin, targetSkin)); + World.Players.Where(p => p.CPE).Send(PacketWriter.MakeExtAddEntity((byte)ID, targetSkin, targetSkin)); Skin = targetSkin; } diff --git a/fCraft/Player/Player.cs b/fCraft/Player/Player.cs index cd630296..7631e0f2 100644 --- a/fCraft/Player/Player.cs +++ b/fCraft/Player/Player.cs @@ -80,6 +80,9 @@ public bool IsOnline /// Determines whether or not a player is using a CC compatable client. public bool ClassiCube = false; + + /// Determines whether or not a player is using a CPE compatable client. + public bool CPE = false; /// Has a custom click distance set by the server public bool hasCustomClickDistance { get; set; } @@ -119,6 +122,11 @@ public Map WorldMap [CanBeNull] public Command LastCommand { get; private set; } + /// + /// Array of players spying on this player + /// + public List Spies { get; private set; } + /// Plain version of the name (no formatting). [NotNull] @@ -422,6 +430,8 @@ internal Player([NotNull] string name, World world) public void ParseMessage([NotNull] string rawMessage, bool fromConsole, bool sendMessage) { if (rawMessage == null) throw new ArgumentNullException("rawMessage"); + if (rawMessage == null) throw new ArgumentNullException("fromConsole"); + if (rawMessage == null) throw new ArgumentNullException("sendMessage"); if (rawMessage.Equals("/nvm", StringComparison.OrdinalIgnoreCase)) { if (partialMessage != null) @@ -517,6 +527,11 @@ public void ParseMessage([NotNull] string rawMessage, bool fromConsole, bool sen { LastCommand = cmd; } + + foreach (Player spy in Spies) + { + spy.Message("SPY - {0}: " + rawMessage); + } } } break; @@ -608,6 +623,10 @@ public void ParseMessage([NotNull] string rawMessage, bool fromConsole, bool sen { Chat.SendPM(this, target, messageText); SendToSpectators("to {0}&F: {1}", target.ClassyName, messageText); + foreach (Player spy in Spies) + { + spy.Message("SPY - {0} to {1}: " + messageText, this, target); + } } if (!CanSee(target)) @@ -1347,6 +1366,7 @@ public bool PlaceBlock(Vector3I coord, ClickAction action, Block type) { RevertBlockNow(coord); } + #region CaptureTheFlag if (Info.placingBlueFlag) { @@ -1788,7 +1808,7 @@ public CanPlaceResult CanPlace([NotNull] Map map, Vector3I coords, Block newBloc } //check classicube blocks and convert if necessary - if (!ClassiCube && newBlock > Block.Obsidian) + if (!CPE && newBlock > Block.Obsidian) { newBlock = Map.GetFallbackBlock(newBlock); result = CanPlaceResult.Allowed; diff --git a/fCraft/System/Server.cs b/fCraft/System/Server.cs index f34980e0..e1bd3303 100644 --- a/fCraft/System/Server.cs +++ b/fCraft/System/Server.cs @@ -128,124 +128,136 @@ public static partial class Server { /// string arguments passed to the frontend (if any). /// If library is already initialized. /// Working path, log path, or map path could not be set. - public static void InitLibrary( [NotNull] IEnumerable rawArgs ) { - if( rawArgs == null ) throw new ArgumentNullException( "rawArgs" ); - if( libraryInitialized ) { - throw new InvalidOperationException( "LegendCraft library is already initialized" ); - } - - //adjust files if in wrong location - if (!Directory.Exists("ref")) - { - Directory.CreateDirectory("ref"); - } - DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory()); - foreach (FileInfo file in dir.GetFiles()) + public static void InitLibrary([NotNull] IEnumerable rawArgs) + { + if (rawArgs == null) throw new ArgumentNullException("rawArgs"); + if (libraryInitialized) { - if (file.Name.Contains(".txt") || file.Name.Contains(".xml")) - { - try - { - file.MoveTo("ref/" + file.Name); - } - catch (System.IO.IOException) - { - continue; - } - } + throw new InvalidOperationException("LegendCraft library is already initialized"); } - ServicePointManager.Expect100Continue = false; // try to parse arguments - foreach( string arg in rawArgs ) { - if( arg.StartsWith( "--" ) ) { + foreach (string arg in rawArgs) + { + if (arg.StartsWith("--")) + { string argKeyName, argValue; - if( arg.Contains( '=' ) ) { - argKeyName = arg.Substring( 2, arg.IndexOf( '=' ) - 2 ).ToLower().Trim(); - argValue = arg.Substring( arg.IndexOf( '=' ) + 1 ).Trim(); - if( argValue.StartsWith( "\"" ) && argValue.EndsWith( "\"" ) ) { - argValue = argValue.Substring( 1, argValue.Length - 2 ); + if (arg.Contains('=')) + { + argKeyName = arg.Substring(2, arg.IndexOf('=') - 2).ToLower().Trim(); + argValue = arg.Substring(arg.IndexOf('=') + 1).Trim(); + if (argValue.StartsWith("\"") && argValue.EndsWith("\"")) + { + argValue = argValue.Substring(1, argValue.Length - 2); } - } else { - argKeyName = arg.Substring( 2 ); + } + else + { + argKeyName = arg.Substring(2); argValue = null; } ArgKey key; - if( EnumUtil.TryParse( argKeyName, out key, true ) ) { - Args.Add( key, argValue ); - } else { - Console.Error.WriteLine( "Unknown argument: {0}", arg ); + if (EnumUtil.TryParse(argKeyName, out key, true)) + { + Args.Add(key, argValue); + } + else + { + Console.Error.WriteLine("Unknown argument: {0}", arg); } - } else { - Console.Error.WriteLine( "Unknown argument: {0}", arg ); + } + else + { + Console.Error.WriteLine("Unknown argument: {0}", arg); } } // before we do anything, set path to the default location - Directory.SetCurrentDirectory( Paths.WorkingPath ); + Directory.SetCurrentDirectory(Paths.WorkingPath); // set custom working path (if specified) - string path = GetArg( ArgKey.Path ); - if( path != null && Paths.TestDirectory( "WorkingPath", path, true ) ) { - Paths.WorkingPath = Path.GetFullPath( path ); - Directory.SetCurrentDirectory( Paths.WorkingPath ); - } else if( Paths.TestDirectory( "WorkingPath", Paths.WorkingPathDefault, true ) ) { - Paths.WorkingPath = Path.GetFullPath( Paths.WorkingPathDefault ); - Directory.SetCurrentDirectory( Paths.WorkingPath ); - } else { - throw new IOException( "Could not set the working path." ); + string path = GetArg(ArgKey.Path); + if (path != null && Paths.TestDirectory("WorkingPath", path, true)) + { + Paths.WorkingPath = Path.GetFullPath(path); + Directory.SetCurrentDirectory(Paths.WorkingPath); + } + else if (Paths.TestDirectory("WorkingPath", Paths.WorkingPathDefault, true)) + { + Paths.WorkingPath = Path.GetFullPath(Paths.WorkingPathDefault); + Directory.SetCurrentDirectory(Paths.WorkingPath); + } + else + { + throw new IOException("Could not set the working path."); } // set log path - string logPath = GetArg( ArgKey.LogPath ); - if( logPath != null && Paths.TestDirectory( "LogPath", logPath, true ) ) { - Paths.LogPath = Path.GetFullPath( logPath ); - } else if( Paths.TestDirectory( "LogPath", Paths.LogPathDefault, true ) ) { - Paths.LogPath = Path.GetFullPath( Paths.LogPathDefault ); - } else { - throw new IOException( "Could not set the log path." ); + string logPath = GetArg(ArgKey.LogPath); + if (logPath != null && Paths.TestDirectory("LogPath", logPath, true)) + { + Paths.LogPath = Path.GetFullPath(logPath); + } + else if (Paths.TestDirectory("LogPath", Paths.LogPathDefault, true)) + { + Paths.LogPath = Path.GetFullPath(Paths.LogPathDefault); + } + else + { + throw new IOException("Could not set the log path."); } - if( HasArg( ArgKey.NoLog ) ) { + if (HasArg(ArgKey.NoLog)) + { Logger.Enabled = false; - } else { + } + else + { Logger.MarkLogStart(); } // set map path - string mapPath = GetArg( ArgKey.MapPath ); - if( mapPath != null && Paths.TestDirectory( "MapPath", mapPath, true ) ) { - Paths.MapPath = Path.GetFullPath( mapPath ); + string mapPath = GetArg(ArgKey.MapPath); + if (mapPath != null && Paths.TestDirectory("MapPath", mapPath, true)) + { + Paths.MapPath = Path.GetFullPath(mapPath); Paths.IgnoreMapPathConfigKey = true; - } else if( Paths.TestDirectory( "MapPath", Paths.MapPathDefault, true ) ) { - Paths.MapPath = Path.GetFullPath( Paths.MapPathDefault ); - } else { - throw new IOException( "Could not set the map path." ); + } + else if (Paths.TestDirectory("MapPath", Paths.MapPathDefault, true)) + { + Paths.MapPath = Path.GetFullPath(Paths.MapPathDefault); + } + else + { + throw new IOException("Could not set the map path."); } // set config path Paths.ConfigFileName = Paths.ConfigFileNameDefault; - string configFile = GetArg( ArgKey.Config ); - if( configFile != null ) { - if( Paths.TestFile( "config.xml", configFile, false, FileAccess.Read ) ) { - Paths.ConfigFileName = new FileInfo( configFile ).FullName; + string configFile = GetArg(ArgKey.Config); + if (configFile != null) + { + if (Paths.TestFile("config.xml", configFile, false, FileAccess.Read)) + { + Paths.ConfigFileName = new FileInfo(configFile).FullName; } } - if( MonoCompat.IsMono ) { - Logger.Log( LogType.Debug, "Running on Mono {0}", MonoCompat.MonoVersion ); + if (MonoCompat.IsMono) + { + Logger.Log(LogType.Debug, "Running on Mono {0}", MonoCompat.MonoVersion); } #if DEBUG_EVENTS Logger.PrepareEventTracing(); #endif - Logger.Log( LogType.Debug, "Working directory: {0}", Directory.GetCurrentDirectory() ); - Logger.Log( LogType.Debug, "Log path: {0}", Path.GetFullPath( Paths.LogPath ) ); - Logger.Log( LogType.Debug, "Map path: {0}", Path.GetFullPath( Paths.MapPath ) ); - Logger.Log( LogType.Debug, "Config path: {0}", Path.GetFullPath( Paths.ConfigFileName ) ); + Logger.Log(LogType.Debug, "Working directory: {0}", Directory.GetCurrentDirectory()); + Logger.Log(LogType.Debug, "Log path: {0}", Path.GetFullPath(Paths.LogPath)); + Logger.Log(LogType.Debug, "Map path: {0}", Path.GetFullPath(Paths.MapPath)); + Logger.Log(LogType.Debug, "Config path: {0}", Path.GetFullPath(Paths.ConfigFileName)); libraryInitialized = true; } @@ -321,6 +333,9 @@ public static partial class Server { PlayerDB.Load(); IPBanList.Load(); + //define fallbacks + Map.DefineFallbackBlocks(); + // prepare the list of commands CommandManager.Init(); PluginManager.GetInstance(); //2nd means plugins crash and not 800Craft @@ -931,19 +946,26 @@ static void CheckTempRanks(SchedulerTask task) gcRequested = true; } + /// + /// Checks if the verification key from the player ID packet (client -> server) matches the server's salt + /// public static bool VerifyName( [NotNull] string name, [NotNull] string hash, [NotNull] string salt ) { if( name == null ) throw new ArgumentNullException( "name" ); if( hash == null ) throw new ArgumentNullException( "hash" ); if( salt == null ) throw new ArgumentNullException( "salt" ); + Logger.LogToConsole("n: " + name + " ver: " + hash + " s: " + salt); while( hash.Length < 32 ) { hash = "0" + hash; } MD5 hasher = MD5.Create(); StringBuilder sb = new StringBuilder( 32 ); - foreach( byte b in hasher.ComputeHash( Encoding.ASCII.GetBytes( salt + name ) ) ) { + foreach( byte b in hasher.ComputeHash( Encoding.ASCII.GetBytes( salt + name ) ) ) + { sb.AppendFormat( "{0:x2}", b ); } + + Logger.LogToConsole("h: " + sb.ToString() + " ver: " + hash + " CC: " + (salt == Heartbeat.Salt2)); return sb.ToString().Equals( hash, StringComparison.OrdinalIgnoreCase ); } diff --git a/fCraft/Utils/Paths.cs b/fCraft/Utils/Paths.cs index c05a3fb5..7bbefeb8 100644 --- a/fCraft/Utils/Paths.cs +++ b/fCraft/Utils/Paths.cs @@ -66,7 +66,7 @@ public static class Paths { public const string MapPathDefault = "maps", LogPathDefault = "logs", - ConfigFileNameDefault = "ref/config.xml"; + ConfigFileNameDefault = "config.xml"; public static readonly string WorkingPathDefault; @@ -88,35 +88,35 @@ public static class Paths { public static string ConfigFileName { get; set; } - public const string PlayerDBFileName = "ref/PlayerDB.txt"; + public const string PlayerDBFileName = "PlayerDB.txt"; - public const string IPBanListFileName = "ref/ipbans.txt"; + public const string IPBanListFileName = "ipbans.txt"; - public const string GreetingFileName = "ref/greeting.txt"; + public const string GreetingFileName = "greeting.txt"; - public const string AnnouncementsFileName = "ref/announcements.txt"; + public const string AnnouncementsFileName = "announcements.txt"; - public const string RulesFileName = "ref/rules.txt"; + public const string RulesFileName = "rules.txt"; - public const string RulesDirectory = "ref/rules"; + public const string RulesDirectory = "rules"; - public const string ShoutsFileName = "ref/shouts.txt";//wot is this? + public const string ShoutsFileName = "shouts.txt";//wot is this? - public const string HeartbeatDataFileName = "ref/heartbeatdata.txt"; + public const string HeartbeatDataFileName = "heartbeatdata.txt"; - public const string UpdaterFileName = "ref/UpdateInstaller.exe"; + public const string UpdaterFileName = "UpdateInstaller.exe"; - public const string WorldListFileName = "ref/worlds.xml"; + public const string WorldListFileName = "worlds.xml"; - public const string AutoRankFileName = "ref/autorank.xml"; + public const string AutoRankFileName = "autorank.xml"; public const string BlockDBDirectory = "blockdb"; - public const string ReqDirectory = "ref/requirements"; - public const string ReqFileName = "ref/requirements.txt"; - public const string BasscannonFileName = "ref/basscannon.txt"; - public const string PortalDBFileName = "ref/PortalDB.txt"; - public const string SwearWordsFileName = "ref/swearwords.txt"; + public const string ReqDirectory = "requirements"; + public const string ReqFileName = "requirements.txt"; + public const string BasscannonFileName = "basscannon.txt"; + public const string PortalDBFileName = "PortalDB.txt"; + public const string SwearWordsFileName = "swearwords.txt"; public static string BlockDBPath { @@ -134,7 +134,7 @@ public static string ReqPath public static string ReqTextPath { - get { return Path.Combine(ReqDirectory, "ref/requirements.txt"); } + get { return Path.Combine(ReqDirectory, "requirements.txt"); } } /// Path where map backups are stored diff --git a/fCraft/World/Map.cs b/fCraft/World/Map.cs index ce305b16..458fb72b 100644 --- a/fCraft/World/Map.cs +++ b/fCraft/World/Map.cs @@ -316,9 +316,14 @@ public sealed partial class Map { int blockIndex = Index( update.X, update.Y, update.Z ); Blocks[blockIndex] = (byte)update.BlockType; - if( !World.IsFlushing ) { + if( !World.IsFlushing ) + { + //non classicube players get fallbacks instead of the real blocks Packet packet = PacketWriter.MakeSetBlock( update.X, update.Y, update.Z, update.BlockType ); - World.Players.SendLowPriority( update.Origin, packet ); + Packet packet2 = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, Map.GetFallbackBlock(update.BlockType)); + + World.Players.Where(p => p.CPE).SendLowPriority(update.Origin, packet); + World.Players.Where(p => !p.CPE).SendLowPriority(update.Origin, packet2); } packetsSent++; } diff --git a/zLegendCraft Changelog.txt b/zLegendCraft Changelog.txt index e6242b6d..217092d8 100644 --- a/zLegendCraft Changelog.txt +++ b/zLegendCraft Changelog.txt @@ -1,17 +1,20 @@ LegendCraft Changelog v2.4.0 (In progress) -Add: LegendCraft WebPanel (unfinished) +Add: Dual Heartbeat Support Add: CTF Gamemode Add: Bot AI +Add: /Spy Add: MessageBlocks Add: /DoorList and /DoorCheck Change: ServerGUI expands much more fluidly, controls no longer overlap -Change: LegendCraft now accepted fCraft Autorank XML scripts +Change: LegendCraft now accepts fCraft Autorank XML scripts Change: Players can have multiple doors Change: Fixes to autorank.xml throwing errors when files are missing Change: Fixed bug where ServerGUI themes resulted in invisible text Change: General stability fixes Change: Updates to Helperbot +Change: Bug fixes with the TAB player list Remove: LeBot (HelperBot taking over) +Remove: /Credits LegendCraft Changelog v2.3.0 Add: LegendCraft Webfront is now 500% better (thanks Liam Stanley)