private void PacketHandler_0x02_CreateA(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); var email = packet.ReadString8(); // This string will contain a client-ready message if the provided password // isn't valid. byte passwordErr = 0x0; if (Game.World.PlayerExists(name)) { client.LoginMessage("That name is unavailable.", 3); } else if (name.Length < 4 || name.Length > 12) { client.LoginMessage("Names must be between 4 to 12 characters long.", 3); } else if (!ValidPassword(password, out passwordErr)) { client.LoginMessage(GetPasswordError(passwordErr), 3); } else if (Regex.IsMatch(name, "^[A-Za-z]{4,12}$")) { client.NewCharacterName = name; client.NewCharacterPassword = HashPassword(password); client.LoginMessage("\0", 0); } else { client.LoginMessage("Names may only contain letters.", 3); } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); GameLog.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); if (!World.PlayerExists(name)) { client.LoginMessage("That character does not exist", 3); GameLog.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); return; } if (World.TryGetUser(name, out User loginUser)) { if (loginUser.VerifyPassword(password)) { GameLog.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.WorldData.ContainsKey <User>(name)) { GameLog.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); client.LoginMessage("That character is already online. Please try again.", 3); World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); return; } GameLog.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); GameLog.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); GameLog.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); loginUser.Login.LastLogin = DateTime.Now; loginUser.Login.LastLoginFrom = ((IPEndPoint)client.Socket.RemoteEndPoint).Address.ToString(); loginUser.Save(); client.Redirect(redirect); } else { GameLog.WarningFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); loginUser.Login.LastLoginFailure = DateTime.Now; loginUser.Login.LoginFailureCount++; loginUser.Save(); } } else { // Something bad has happened client.LoginMessage("An unknown error occurred. Please contact Hybrasyl support.", 3); } }
// Chart for all error password-related error codes were provided by kojasou@ on // https://github.com/hybrasyl/server/pull/11. private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet) { var name = packet.ReadString8(); var currentPass = packet.ReadString8(); // Clientside validation ensures that the same string is typed twice for the new // password, and the new password is only sent to the server once. We can assume // that they matched if 0x26 request is sent from the client. var newPass = packet.ReadString8(); using (var ctx = new hybrasylEntities(Constants.ConnectionString)) { var player = ctx.players.Where(p => p.name == name).SingleOrDefault(); // Check that `name` exists. If not, return a message indicating that to the user. if (player == null) { client.LoginMessage(GetPasswordError(0x0E), 0x0E); Logger.DebugFormat("Password change attempt on invalid player `{0}`", name); } // If the player does exist, validate the current and new passwords before updating. else { // Check that the current password is correct and the new password is different // than the current password. if (VerifyPassword(currentPass, player)) { // Check if the password is valid. byte err = 0x00; if (ValidPassword(newPass, out err)) { player.password_hash = HashPassword(newPass); ctx.SaveChanges(); // Let the user know the good news. client.LoginMessage("Your password has been changed successfully.", 0x0); Logger.InfoFormat("Password successfully changed for `{0}`", name); } else { client.LoginMessage(GetPasswordError(err), err); Logger.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name); } } // The current password is incorrect. Don't allow any changes to happen. else { client.LoginMessage(GetPasswordError(0x0F), 0x0F); Logger.ErrorFormat("Invalid current password during password change attempt for `{0}`", name); } } } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); Logger.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); using (var ctx = new hybrasylEntities(Constants.ConnectionString)) { var result = ctx.players.Where(player => player.name == name).SingleOrDefault(); if (result == null) { client.LoginMessage("That character does not exist", 3); Logger.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); } else { if (VerifyPassword(password, result)) { Logger.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.ActiveUsersByName.ContainsKey(name)) { Logger.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); } Logger.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); Logger.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); Logger.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); client.Redirect(redirect); } else { Logger.WarnFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); } } } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); Logger.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); User loginUser; if (!World.TryGetUser(name, out loginUser)) { client.LoginMessage("That character does not exist", 3); Logger.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); } else if (loginUser.VerifyPassword(password)) { Logger.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.ActiveUsersByName.ContainsKey(name)) { Logger.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); } Logger.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); Logger.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); Logger.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); client.Redirect(redirect); loginUser.Login.LastLogin = DateTime.Now; loginUser.Login.LastLoginFrom = ((IPEndPoint)client.Socket.RemoteEndPoint).Address.ToString(); loginUser.Save(); } else { Logger.WarnFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); loginUser.Login.LastLoginFailure = DateTime.Now; loginUser.Login.LoginFailureCount++; loginUser.Save(); } }
private void PacketHandler_0x10_ClientJoin(Client client, ClientPacket packet) { var seed = packet.ReadByte(); var keyLength = packet.ReadByte(); var key = packet.Read(keyLength); var name = packet.ReadString8(); var id = packet.ReadUInt32(); var redirect = ExpectedConnections[id]; if (Game.World.WorldData.TryGetAuthInfo(name, out AuthInfo login)) { login.CurrentState = UserState.Login; login.Save(); } if (redirect.Matches(name, key, seed)) { ((IDictionary)ExpectedConnections).Remove(id); client.EncryptionKey = key; client.EncryptionSeed = seed; if (redirect.Source is Lobby || redirect.Source is World) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x00); x60.WriteUInt32(Game.NotificationCrc); client.Enqueue(x60); } } }
private void PacketHandler_0x10_ClientJoin(Client client, ClientPacket packet) { var seed = packet.ReadByte(); var keyLength = packet.ReadByte(); var key = packet.Read(keyLength); var name = packet.ReadString8(); var id = packet.ReadUInt32(); var redirect = ExpectedConnections[id]; if (redirect.Matches(name, key, seed)) { ((IDictionary)ExpectedConnections).Remove(id); client.EncryptionKey = key; client.EncryptionSeed = seed; if (redirect.Source is Lobby) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x00); x60.WriteUInt32(Game.NotificationCrc); client.Enqueue(x60); } } }
// Chart for all error password-related error codes were provided by kojasou@ on // https://github.com/hybrasyl/server/pull/11. private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet) { var name = packet.ReadString8(); var currentPass = packet.ReadString8(); // Clientside validation ensures that the same string is typed twice for the new // password, and the new password is only sent to the server once. We can assume // that they matched if 0x26 request is sent from the client. var newPass = packet.ReadString8(); // TODO: REDIS User player; if (!World.TryGetUser(name, out player)) { client.LoginMessage(GetPasswordError(0x0E), 0x0E); Logger.InfoFormat("cid {0}: Password change attempt on nonexistent player {1}", client.ConnectionId, name); return; } if (player.VerifyPassword(currentPass)) { // Check if the password is valid. byte err = 0x00; if (ValidPassword(newPass, out err)) { player.Password.Hash = HashPassword(newPass); player.Password.LastChanged = DateTime.Now; player.Password.LastChangedFrom = ((IPEndPoint)client.Socket.RemoteEndPoint).Address.ToString(); player.Save(); // Let the user know the good news. client.LoginMessage("Your password has been changed successfully.", 0x0); Logger.InfoFormat("Password successfully changed for `{0}`", name); } else { client.LoginMessage(GetPasswordError(err), err); Logger.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name); } } // The current password is incorrect. Don't allow any changes to happen. else { client.LoginMessage(GetPasswordError(0x0F), 0x0F); Logger.ErrorFormat("Invalid current password during password change attempt for `{0}`", name); } }
private void MerchantMenuHandler_BuyItem(User user, Merchant merchant, ClientPacket packet) { string name = packet.ReadString8(); if (!merchant.Inventory.ContainsKey(name)) { user.ShowMerchantGoBack(merchant, "I do not sell that item.", MerchantMenuItem.BuyItemMenu); return; } var template = merchant.Inventory[name]; if (template.Stackable) { user.ShowBuyMenuQuantity(merchant, name); return; } if (user.Gold < template.value) { user.ShowMerchantGoBack(merchant, "You do not have enough gold.", MerchantMenuItem.BuyItemMenu); return; } if (user.CurrentWeight + template.weight > user.MaximumWeight) { user.ShowMerchantGoBack(merchant, "That item is too heavy for you to carry.", MerchantMenuItem.BuyItemMenu); return; } if (user.Inventory.IsFull) { user.ShowMerchantGoBack(merchant, "You cannot carry any more items.", MerchantMenuItem.BuyItemMenu); return; } user.RemoveGold((uint) template.value); var item = CreateItem(template.id); Insert(item); user.AddItem(item); user.UpdateAttributes(StatUpdateFlags.Experience); user.ShowBuyMenu(merchant); }
// Chart for all error password-related error codes were provided by kojasou@ on // https://github.com/hybrasyl/server/pull/11. private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet) { var name = packet.ReadString8(); var currentPass = packet.ReadString8(); // Clientside validation ensures that the same string is typed twice for the new // password, and the new password is only sent to the server once. We can assume // that they matched if 0x26 request is sent from the client. var newPass = packet.ReadString8(); // TODO: REDIS IDatabase cache = World.DatastoreConnection.GetDatabase(); var myPerson = cache.Get(name); if (myPerson == null) { client.LoginMessage(GetPasswordError(0x0E), 0x0E); Logger.DebugFormat("Password change attempt on invalid player `{0}`", name); } var player = JsonConvert.DeserializeObject(myPerson as String) as User; if (player.VerifyPassword(currentPass)) { // Check if the password is valid. byte err = 0x00; if (ValidPassword(newPass, out err)) { player.Password.Hash = HashPassword(newPass); player.Password.LastChanged = DateTime.Now; player.Password.LastChangedFrom = ((IPEndPoint) client.Socket.RemoteEndPoint).Address.ToString(); player.Save(); // Let the user know the good news. client.LoginMessage("Your password has been changed successfully.", 0x0); Logger.InfoFormat("Password successfully changed for `{0}`", name); } else { client.LoginMessage(GetPasswordError(err), err); Logger.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name); } } // The current password is incorrect. Don't allow any changes to happen. else { client.LoginMessage(GetPasswordError(0x0F), 0x0F); Logger.ErrorFormat("Invalid current password during password change attempt for `{0}`", name); } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); Logger.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); User loginUser; if (!World.TryGetUser(name, out loginUser)) { client.LoginMessage("That character does not exist", 3); Logger.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); } else if (loginUser.VerifyPassword(password)) { Logger.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.ActiveUsersByName.ContainsKey(name)) { Logger.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); } Logger.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); Logger.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); Logger.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); client.Redirect(redirect); loginUser.Login.LastLogin = DateTime.Now; loginUser.Login.LastLoginFrom = ((IPEndPoint) client.Socket.RemoteEndPoint).Address.ToString(); loginUser.Save(); } else { Logger.WarnFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); loginUser.Login.LastLoginFailure = DateTime.Now; loginUser.Login.LoginFailureCount++; loginUser.Save(); } }
private void MerchantMenuHandler_SellItemWithQuantity(User user, Merchant merchant, ClientPacket packet) { packet.ReadByte(); byte slot = packet.ReadByte(); string qStr = packet.ReadString8(); int quantity; if (!int.TryParse(qStr, out quantity) || quantity < 1) { user.ShowSellQuantity(merchant, slot); return; } var item = user.Inventory[slot]; if (item == null || !item.Stackable) return; if (!merchant.Inventory.ContainsKey(item.Name)) { user.ShowMerchantGoBack(merchant, "I do not want that item.", MerchantMenuItem.SellItemMenu); return; } if (item.Count < quantity) { user.ShowMerchantGoBack(merchant, "You don't have that many to sell.", MerchantMenuItem.SellItemMenu); return; } user.ShowSellConfirm(merchant, slot, quantity); }
private void PacketHandler_0x0E_Talk(Object obj, ClientPacket packet) { var user = (User) obj; var isShout = packet.ReadByte(); var message = packet.ReadString8(); if (message.StartsWith("/")) { var args = message.Split(' '); #region world's biggest switch statement switch (args[0].ToLower()) { case "/gold": { uint amount; if (args.Length != 2 || !uint.TryParse(args[1], out amount)) break; user.Gold = amount; user.UpdateAttributes(StatUpdateFlags.Experience); } break; case "/summon": { if (!user.IsPrivileged) return; if (args.Length == 2) { if (!Users.ContainsKey(args[1])) { user.SendMessage("User not logged in.", MessageTypes.SYSTEM); return; } var target = Users[args[1]]; if (target.IsExempt) user.SendMessage("Access denied.", MessageTypes.SYSTEM); else { target.Teleport(user.Map.Id, user.MapX, user.MapY); Logger.InfoFormat("GM activity: {0} summoned {1}", user.Name, target.Name); } } } break; case "/kick": { if (!user.IsPrivileged) return; if (args.Length == 2) { if (!Users.ContainsKey(args[1])) { user.SendMessage("User not logged in.", MessageTypes.SYSTEM); return; } var target = Users[args[1]]; if (target.IsExempt) user.SendMessage("Access denied.", MessageTypes.SYSTEM); else target.Logoff(); Logger.InfoFormat("GM activity: {0} kicked {1}", user.Name, target.Name); } } break; case "/teleport": { ushort number = ushort.MaxValue; byte x = user.X, y = user.Y; if (args.Length == 2) { if (!ushort.TryParse(args[1], out number)) { if (!Users.ContainsKey(args[1])) { user.SendMessage("Invalid map number or user name", 3); return; } else { var target = Users[args[1]]; number = target.Map.Id; x = target.X; y = target.Y; } } } else if (args.Length == 4) { ushort.TryParse(args[1], out number); byte.TryParse(args[2], out x); byte.TryParse(args[3], out y); } if (Maps.ContainsKey(number)) { var map = Maps[number]; if (x < map.X && y < map.Y) user.Teleport(number, x, y); else user.SendMessage("Invalid x/y", 3); } else user.SendMessage("Invalid map number", 3); } break; case "/motion": { byte motion; short speed = 20; if (args.Length > 1 && byte.TryParse(args[1], out motion)) { if (args.Length > 2) short.TryParse(args[2], out speed); user.Motion(motion, speed); } } break; case "/maplist": { // This is an extremely expensive slash command var searchString = ""; if (args.Length == 1) { user.SendMessage("Usage: /maplist <searchterm>\nExample: /maplist Mileth - show maps with Mileth in the title\n", MessageTypes.SLATE); return; } else if (args.Length == 2) searchString = args[1]; else searchString = String.Join(" ", args, 1, args.Length - 1); Regex searchTerm; try { Logger.InfoFormat("Search term was {0}",searchString); searchTerm = new Regex(String.Format("{0}", searchString)); } catch { user.SendMessage("Invalid search. Try again or send no options for help.", MessageTypes.SYSTEM); return; } var queryMaps = from amap in MapCatalog where searchTerm.IsMatch(amap.Key) select amap; var result = queryMaps.Aggregate("", (current, map) => current + String.Format("{0} - {1}\n", map.Value.Id, map.Value.Name)); if (result.Length > 65400) result = String.Format("{0}\n(Results truncated)", result.Substring(0, 65400)); user.SendMessage(String.Format("Search Results\n---------------\n\n{0}", result), MessageTypes.SLATE_WITH_SCROLLBAR); } break; case "/effect": { ushort effect; short speed = 100; if (args.Length > 1 && ushort.TryParse(args[1], out effect)) { if (args.Length > 2) short.TryParse(args[2], out speed); user.Effect(effect, speed); } } break; case "/sound": { byte sound; if (args.Length > 1 && byte.TryParse(args[1], out sound)) { user.SendSound(sound); } } break; case "/music": { byte track; if (args.Length > 1 && byte.TryParse(args[1], out track)) { user.Map.Music = track; foreach (var mapuser in user.Map.Users.Values) { mapuser.SendMusic(track); } } } break; case "/mapmsg": { if (args.Length > 1) { var mapmsg = string.Join(" ", args, 1, args.Length - 1); user.Map.Message = mapmsg; foreach (var mapuser in user.Map.Users.Values) { mapuser.SendMessage(mapmsg, 18); } } } break; case "/worldmsg": { if (args.Length > 1) { var msg = string.Join(" ", args, 1, args.Length - 1); foreach (var connectedUser in ActiveUsers) { connectedUser.Value.SendWorldMessage(user.Name, msg); } } } break; case "/class": { var className = string.Join(" ", args, 1, args.Length - 1); int classValue; if (Hybrasyl.Constants.CLASSES.TryGetValue(className, out classValue)) { user.Class = (Hybrasyl.Enums.Class) Hybrasyl.Constants.CLASSES[className]; user.SendMessage(String.Format("Class set to {0}", className.ToLower()), 0x1); } else { user.SendMessage("I know nothing about that class. Try again.", 0x1); } } break; case "/level": { byte newLevel; var level = string.Join(" ", args, 1, args.Length - 1); if (!Byte.TryParse(level, out newLevel)) user.SendMessage("That's not a valid level, champ.", 0x1); else { user.Level = newLevel; user.UpdateAttributes(StatUpdateFlags.Full); user.SendMessage(String.Format("Level changed to {0}", newLevel), 0x1); } } break; case "/attr": { if (args.Length != 3) { return; } byte newStat; if (!Byte.TryParse(args[2], out newStat)) { user.SendSystemMessage("That's not a valid value for an attribute, chief."); return; } switch (args[1].ToLower()) { case "str": user.BaseStr = newStat; break; case "con": user.BaseCon = newStat; break; case "dex": user.BaseDex = newStat; break; case "wis": user.BaseWis = newStat; break; case "int": user.BaseInt = newStat; break; default: user.SendSystemMessage("Invalid attribute, sport."); break; } user.UpdateAttributes(StatUpdateFlags.Stats); } break; case "/guild": { var guild = string.Join(" ", args, 1, args.Length - 1); user.Guild = guild; user.SendMessage(String.Format("Guild changed to {0}", guild), 0x1); } break; case "/guildrank": { var guildrank = string.Join(" ", args, 1, args.Length - 1); user.GuildRank = guildrank; user.SendMessage(String.Format("Guild rank changed to {0}", guildrank), 0x1); } break; case "/title": { var title = string.Join(" ", args, 1, args.Length - 1); user.Title = title; user.SendMessage(String.Format("Title changed to {0}", title), 0x1); } break; case "/debug": { if (!user.IsPrivileged) return; user.SendMessage("Debugging enabled", 3); ((log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository()).Root.Level = Level.Debug; ((log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository()).RaiseConfigurationChanged( EventArgs.Empty); Logger.InfoFormat("Debugging enabled by admin command"); } break; case "/nodebug": { if (!user.IsPrivileged) return; user.SendMessage("Debugging disabled", 3); ((log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository()).Root.Level = Level.Info; ((log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository()).RaiseConfigurationChanged( EventArgs.Empty); Logger.InfoFormat("Debugging disabled by admin command"); } break; case "/gcm": { if (!user.IsPrivileged) return; var gcmContents = "Contents of Global Connection Manifest\n"; var userContents = "Contents of User Dictionary\n"; var ActiveUserContents = "Contents of ActiveUsers Concurrent Dictionary\n"; foreach (var pair in GlobalConnectionManifest.ConnectedClients) { var serverType = String.Empty; switch (pair.Value.ServerType) { case ServerTypes.Lobby: serverType = "Lobby"; break; case ServerTypes.Login: serverType = "Login"; break; default: serverType = "World"; break; } try { gcmContents = gcmContents + String.Format("{0}:{1} - {2}:{3}\n", pair.Key, ((IPEndPoint) pair.Value.Socket.RemoteEndPoint).Address.ToString(), ((IPEndPoint) pair.Value.Socket.RemoteEndPoint).Port, serverType); } catch { gcmContents = gcmContents + String.Format("{0}:{1} disposed\n", pair.Key, serverType); } } foreach (var tehuser in Users) { userContents = userContents + tehuser.Value.Name + "\n"; } foreach (var tehotheruser in ActiveUsersByName) { ActiveUserContents = ActiveUserContents + String.Format("{0}: {1}\n", tehotheruser.Value, tehotheruser.Key); } // Report to the end user user.SendMessage( String.Format("{0}\n\n{1}\n\n{2}", gcmContents, userContents, ActiveUserContents), MessageTypes.SLATE_WITH_SCROLLBAR); } break; case "/item": { int count; string itemName; Logger.DebugFormat("/item: Last argument is {0}", args.Last()); Regex integer = new Regex(@"^\d+$"); if (integer.IsMatch(args.Last())) { count = Convert.ToInt32(args.Last()); itemName = string.Join(" ", args, 1, args.Length - 2); Logger.InfoFormat("Admin command: Creating item {0} with count {1}", itemName, count); } else { count = 1; itemName = string.Join(" ", args, 1, args.Length - 1); } // HURR O(N) IS MY FRIEND // change this to use itemcatalog pls foreach (var template in Items) { if (template.Value.name.Equals(itemName, StringComparison.CurrentCultureIgnoreCase)) { var item = CreateItem(template.Key); if (count > item.MaximumStack) item.Count = item.MaximumStack; else item.Count = count; Insert(item); user.AddItem(item); } } } break; case "/mute": { if (!user.IsPrivileged) return; var charTarget = string.Join(" ", args, 1, args.Length - 1); var userObj = FindUser(charTarget); if (userObj != null) { userObj.IsMuted = true; userObj.Save(); user.SendMessage(String.Format("{0} is now muted.", userObj.Name), 0x1); } else { user.SendMessage("That Aisling is not in Temuair.", 0x01); } } break; case "/unmute": { if (!user.IsPrivileged) return; var charTarget = string.Join(" ", args, 1, args.Length - 1); var userObj = FindUser(charTarget); if (userObj != null) { userObj.IsMuted = false; userObj.Save(); user.SendMessage(String.Format("{0} is now unmuted.", userObj.Name), 0x1); } else { user.SendMessage("That Aisling is not in Temuair.", 0x01); } } break; case "/reload": { if (!user.IsPrivileged) return; // Do nothing here for now // This should reload warps, worldwarps, "item templates", worldmaps, and world map points. // This should obviously use the new ControlMessage stuff. user.SendMessage("This feature is not currently implemented.", 0x01); } break; case "/shutdown": { if (!user.IsPrivileged) return; var password = args[1]; if (String.Equals(password, Constants.ShutdownPassword)) { MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.ShutdownServer, user.Name)); } } break; case "/scripting": { if (!user.IsPrivileged) return; // Valid scripting commands // /scripting (reload|disable|enable|status) [scriptname] if (args.Count() >= 3) { var script = ScriptProcessor.GetScript(args[2].Trim()); if (script != null) { if (args[1].ToLower() == "reload") { script.Disabled = true; if (script.Load()) { user.SendMessage(String.Format("Script {0}: reloaded", script.Name), 0x01); if (script.InstantiateScriptable()) user.SendMessage( String.Format("Script {0}: instances recreated", script.Name), 0x01); } else { user.SendMessage( String.Format("Script {0}: load error, consult status", script.Name), 0x01); } } else if (args[1].ToLower() == "enable") { script.Disabled = false; user.SendMessage(String.Format("Script {0}: enabled", script.Name), 0x01); } else if (args[1].ToLower() == "disable") { script.Disabled = true; user.SendMessage(String.Format("Script {0}: disabled", script.Name), 0x01); } else if (args[1].ToLower() == "status") { var scriptStatus = String.Format("{0}:", script.Name); String errorSummary = "--- Error Summary ---\n"; if (script.Instance == null) scriptStatus = String.Format("{0} not instantiated,", scriptStatus); else scriptStatus = String.Format("{0} instantiated,", scriptStatus); if (script.Disabled) scriptStatus = String.Format("{0} disabled", scriptStatus); else scriptStatus = String.Format("{0} enabled", scriptStatus); if (script.LastRuntimeError == String.Empty && script.CompilationError == String.Empty) errorSummary = String.Format("{0} no errors", errorSummary); else { if (script.CompilationError != String.Empty) errorSummary = String.Format("{0} compilation error: {1}", errorSummary, script.CompilationError); if (script.LastRuntimeError != String.Empty) errorSummary = String.Format("{0} runtime error: {1}", errorSummary, script.LastRuntimeError); } // Report to the end user user.SendMessage(String.Format("{0}\n\n{1}", scriptStatus, errorSummary), MessageTypes.SLATE_WITH_SCROLLBAR); } } else { user.SendMessage(String.Format("Script {0} not found!", args[2]), 0x01); } } else if (args.Count() == 2) { if (args[1].ToLower() == "status") { // Display status information for all NPCs String statusReport = String.Empty; String errorSummary = "--- Error Summary ---\n"; foreach (KeyValuePair<string, Script> entry in ScriptProcessor.Scripts) { var scriptStatus = String.Format("{0}:", entry.Key); var scriptErrors = String.Format("{0}:", entry.Key); if (entry.Value.Instance == null) scriptStatus = String.Format("{0} not instantiated,", scriptStatus); else scriptStatus = String.Format("{0} instantiated,", scriptStatus); if (entry.Value.Disabled) scriptStatus = String.Format("{0} disabled", scriptStatus); else scriptStatus = String.Format("{0} enabled", scriptStatus); if (entry.Value.LastRuntimeError == String.Empty && entry.Value.CompilationError == String.Empty) scriptErrors = String.Format("{0} no errors", scriptErrors); else { if (entry.Value.CompilationError != String.Empty) scriptErrors = String.Format("{0} compilation error: {1}", scriptErrors, entry.Value.CompilationError); if (entry.Value.LastRuntimeError != String.Empty) scriptErrors = String.Format("{0} runtime error: {1}", scriptErrors, entry.Value.LastRuntimeError); } statusReport = String.Format("{0}\n{1}", statusReport, scriptStatus); errorSummary = String.Format("{0}\n{1}", errorSummary, scriptErrors); } // Report to the end user user.SendMessage(String.Format("{0}\n\n{1}", statusReport, errorSummary), MessageTypes.SLATE_WITH_SCROLLBAR); } } } break; #endregion world's biggest switch statement } } else { if (user.CheckSquelch(0x0e, message)) { Logger.DebugFormat("{1}: squelched (say/shout)", user.Name); return; } if (isShout == 1) { user.Shout(message); } else { user.Say(message); } } }
private void MerchantMenuHandler_BuyItemWithQuantity(User user, Merchant merchant, ClientPacket packet) { string name = packet.ReadString8(); string qStr = packet.ReadString8(); if (!merchant.Inventory.ContainsKey(name)) { user.ShowMerchantGoBack(merchant, "I do not sell that item.", MerchantMenuItem.BuyItemMenu); return; } var template = merchant.Inventory[name]; if (!template.Stackable) return; int quantity; if (!int.TryParse(qStr, out quantity) || quantity < 1) { user.ShowBuyMenuQuantity(merchant, name); return; } uint cost = (uint) (template.value*quantity); if (user.Gold < cost) { user.ShowMerchantGoBack(merchant, "You do not have enough gold.", MerchantMenuItem.BuyItemMenu); return; } if (quantity > template.max_stack) { user.ShowMerchantGoBack(merchant, string.Format("You cannot hold that many {0}.", name), MerchantMenuItem.BuyItemMenu); return; } if (user.Inventory.Contains(name)) { byte slot = user.Inventory.SlotOf(name); if (user.Inventory[slot].Count + quantity > template.max_stack) { user.ShowMerchantGoBack(merchant, string.Format("You cannot hold that many {0}.", name), MerchantMenuItem.BuyItemMenu); return; } user.IncreaseItem(slot, quantity); } else { if (user.Inventory.IsFull) { user.ShowMerchantGoBack(merchant, "You cannot carry any more items.", MerchantMenuItem.BuyItemMenu); return; } var item = CreateItem(template.id, quantity); Insert(item); user.AddItem(item); } user.RemoveGold(cost); user.UpdateAttributes(StatUpdateFlags.Experience); user.ShowBuyMenu(merchant); }
private void PacketHandler_0x7B_RequestMetafile(Object obj, ClientPacket packet) { var user = (User) obj; var all = packet.ReadBoolean(); if (all) { var x6F = new ServerPacket(0x6F); x6F.WriteBoolean(all); x6F.WriteUInt16((ushort) Metafiles.Count); foreach (var metafile in Metafiles.Values) { x6F.WriteString8(metafile.Name); x6F.WriteUInt32(metafile.Checksum); } user.Enqueue(x6F); } else { var name = packet.ReadString8(); if (Metafiles.ContainsKey(name)) { var file = Metafiles[name]; var x6F = new ServerPacket(0x6F); x6F.WriteBoolean(all); x6F.WriteString8(file.Name); x6F.WriteUInt32(file.Checksum); x6F.WriteUInt16((ushort) file.Data.Length); x6F.Write(file.Data); user.Enqueue(x6F); } } }
private void PacketHandler_0x3A_DialogUse(Object obj, ClientPacket packet) { var user = (User) obj; if (user.CheckSquelch(0x38, null)) { Logger.InfoFormat("{0}: squelched (dialog use)", user.Name); return; } var header = packet.ReadDialogHeader(); var objectType = packet.ReadByte(); var objectID = packet.ReadUInt32(); var pursuitID = packet.ReadUInt16(); var pursuitIndex = packet.ReadUInt16(); Logger.DebugFormat("objectType {0}, objectID {1}, pursuitID {2}, pursuitIndex {3}", objectType, objectID, pursuitID, pursuitIndex); Logger.DebugFormat("active dialog via state object: pursuitID {0}, pursuitIndex {1}", user.DialogState.CurrentPursuitId, user.DialogState.CurrentPursuitIndex); if (pursuitID == user.DialogState.CurrentPursuitId && pursuitIndex == user.DialogState.CurrentPursuitIndex) { // If we get a packet back with the same index and ID, the dialog has been closed. Logger.DebugFormat("Dialog closed, resetting dialog state"); user.DialogState.EndDialog(); return; } if ((pursuitIndex > user.DialogState.CurrentPursuitIndex + 1) || (pursuitIndex < user.DialogState.CurrentPursuitIndex - 1)) { Logger.ErrorFormat("Dialog index is outside of acceptable limits (next/prev)"); return; } WorldObject wobj; if (user.World.Objects.TryGetValue(objectID, out wobj)) { VisibleObject clickTarget = wobj as VisibleObject; // Was the previous button clicked? Handle that first if (pursuitIndex == user.DialogState.CurrentPursuitIndex - 1) { Logger.DebugFormat("Handling prev: client passed index {0}, current index is {1}", pursuitIndex, user.DialogState.CurrentPursuitIndex); if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } } // Is the active dialog an input or options dialog? if (user.DialogState.ActiveDialog is OptionsDialog) { var paramsLength = packet.ReadByte(); var option = packet.ReadByte(); var dialog = user.DialogState.ActiveDialog as OptionsDialog; dialog.HandleResponse(user, option, clickTarget); } if (user.DialogState.ActiveDialog is TextDialog) { var paramsLength = packet.ReadByte(); var response = packet.ReadString8(); var dialog = user.DialogState.ActiveDialog as TextDialog; dialog.HandleResponse(user, response, clickTarget); } // Did the handling of a response result in our active dialog sequence changing? If so, exit. if (user.DialogState.CurrentPursuitId != pursuitID) { Logger.DebugFormat("Dialog has changed, exiting"); return; } if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { Logger.DebugFormat("Pursuit index is now {0}", pursuitIndex); user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } else { Logger.DebugFormat("Sending close packet"); var p = new ServerPacket(0x30); p.WriteByte(0x0A); p.WriteByte(0x00); user.Enqueue(p); user.DialogState.EndDialog(); } } }
private void PacketHandler_0x10_ClientJoin(Object obj, ClientPacket packet) { var connectionId = (long) obj; var seed = packet.ReadByte(); var keyLength = packet.ReadByte(); var key = packet.Read(keyLength); var name = packet.ReadString8(); var id = packet.ReadUInt32(); var redirect = ExpectedConnections[id]; if (redirect.Matches(name, key, seed)) { ((IDictionary) ExpectedConnections).Remove(id); if (PlayerExists(name)) { var user = new User(this, connectionId, name); user.SetEncryptionParameters(key, seed, name); user.LoadDataFromEntityFramework(true); user.UpdateLoginTime(); user.UpdateAttributes(StatUpdateFlags.Full); Logger.DebugFormat("Elapsed time since login: {0}", user.SinceLastLogin); if (user.Citizenship.spawn_points.Count != 0 && user.SinceLastLogin > Hybrasyl.Constants.NATION_SPAWN_TIMEOUT) { Insert(user); var spawnpoint = user.Citizenship.spawn_points.First(); user.Teleport((ushort) spawnpoint.map_id, (byte) spawnpoint.map_x, (byte) spawnpoint.map_y); } else if (user.MapId != null && Maps.ContainsKey(user.MapId)) { Insert(user); user.Teleport(user.MapId, (byte) user.MapX, (byte) user.MapY); } else { // Handle any weird cases where a map someone exited on was deleted, etc // This "default" of Mileth should be set somewhere else Insert(user); user.Teleport((ushort) 500, (byte) 50, (byte) 50); } Logger.DebugFormat("Adding {0} to hash", user.Name); AddUser(user); ActiveUsers[connectionId] = user; ActiveUsersByName[user.Name] = connectionId; Logger.InfoFormat("cid {0}: {1} entering world", connectionId, user.Name); } } }