public bool AssertForHack(bool isHack, string hackType, bool seriousHack = true) { if (!isHack || IsAdmin) return false; HackLog.Warn(hackType); Trace.WriteLine(hackType); if (IsGM || IsAdmin) return false; HackLog.Warn(hackType); if (seriousHack && HacklogMuted < MasterThread.CurrentDate) { MessagePacket.SendNoticeGMs( $"Check '{hackType}' triggered! Character: '{Name}', Map: '{MapID}'.", MessagePacket.MessageTypes.Megaphone ); } return isHack; }
public override void OnHackDetected() { if (!Loaded || !HackDetected.HasValue) { return; } var character = Player.Character; var hack = HackDetected.Value; if (hack.HasFlag(RedisBackend.HackKind.Speedhack)) { MessagePacket.SendNoticeGMs( $"Detected speed hacks on character '{character.Name}', map {character.MapID}...", MessagePacket.MessageTypes.RedText); if (character.IsGM == false) { character.PermaBan( "Detected speedhack", extraDelay: (int)((2 * 60) + Rand32.Next() % (5 * 60)) ); } } if (hack.HasFlag(RedisBackend.HackKind.MemoryEdits)) { MessagePacket.SendNoticeGMs( $"Detected memory edits on character '{character.Name}', map {character.MapID}.", MessagePacket.MessageTypes.RedText ); if (character.IsGM == false) { // Add some randomness character.PermaBan( "Detected memory edits", // Between 2 and 12 minutes extraDelay: (int)((2 * 60) + Rand32.Next() % (10 * 60)) ); } } }
public static void HandleAdminCommandMessage(Character chr, Packet packet) { byte to = packet.ReadByte(); byte TypeMessage = packet.ReadByte(); // /alert, /notice, /slide string Message = packet.ReadString(); switch (to) { case 0x00: //To every game server MessagePacket.SendAdminMessage(chr, Message, TypeMessage, 0); break; case 0x01: //To channel MessagePacket.SendAdminMessage(chr, Message, TypeMessage, 1); break; case 0x02: //To map MessagePacket.SendAdminMessage(chr, Message, TypeMessage, 2); break; } }
public static void HandlePacket(Character pCharacter, Packet pPacket) { //MessagePacket.SendNotice("PACKET: " + pPacket.ToString(), pCharacter); byte Type = pPacket.ReadByte(); switch (Type) { case 0: // Create miniroom { if (pCharacter.AssertForHack(!pCharacter.CanAttachAdditionalProcess, "Trying to create a miniroom while he cannot attach additional process.")) { return; } CreateMiniRoomBase(pCharacter, pPacket); break; } case 2: // Invite To miniroom { if (pCharacter.Room == null) { InviteResult(pCharacter, 1); return; // NOT OPENED OR FULL } int playerid = pPacket.ReadInt(); Character victim = pCharacter.Field.GetPlayer(playerid); if (victim == null) { miniroomLog.Info($"{pCharacter.Name} fails to invite charid {playerid}: not found?"); // Not found! InviteResult(pCharacter, 1); } else if (pCharacter.Room.IsFull()) { miniroomLog.Info($"{pCharacter.Name} fails to invite charid {playerid}: room already full?"); InviteResult(pCharacter, 2, victim.Name); // DEM REAL DEAL } else if ((pCharacter.IsGM == false && victim.IsGM) || (pCharacter.IsGM && victim.IsGM == false)) { miniroomLog.Info($"{pCharacter.Name} fails to invite charid {playerid}: non-admin tried to invite admin or vice versa"); InviteResult(pCharacter, 1); } else { miniroomLog.Info($"{pCharacter.Name} invited {victim.Name} (charid {playerid})"); Invite(pCharacter.Room, pCharacter, victim); } break; } case 3: // Decline Invite { int roomid = pPacket.ReadInt(); miniroomLog.Info($"{pCharacter.Name} declined invite."); if (!MiniRoomBase.MiniRooms.ContainsKey(roomid)) { // REPORT //ReportManager.FileNewReport("Tried opening a trade room without a proper ID.", pCharacter.ID, 0); //MessagePacket.SendNotice("Tried opening a trade room without a proper ID. ID was: " + roomid.ToString(), pCharacter); return; } MiniRoomBase mrb = MiniRoomBase.MiniRooms[roomid]; //if (mrb.IsFull()) //{ //} break; } case 4: // Enter Room { EnterMiniRoom(pCharacter, pPacket); break; } case 0x06: // Chat { if (pCharacter.Room == null) { return; } var text = pPacket.ReadString(); var chatLogLine = pCharacter.Name + ": " + text; if (MessagePacket.ShowMuteMessage(pCharacter)) { miniroomChatLog.Info("[MUTED] " + chatLogLine); } else { miniroomChatLog.Info(chatLogLine); Chat(pCharacter.Room, pCharacter, text, -1); } break; } case 0x12: //Add item to Player Shop { if (pCharacter.Room == null) { return; } byte inventory = pPacket.ReadByte(); short inventoryslot = pPacket.ReadShort(); short bundleamount = pPacket.ReadShort(); short AmountPerBundle = pPacket.ReadShort(); int price = pPacket.ReadInt(); PlayerShop.HandleShopUpdateItem(pCharacter, inventory, inventoryslot, bundleamount, AmountPerBundle, price); break; } case 0x13: //Buy item from shop { if (pCharacter.Room == null) { return; } byte slot = pPacket.ReadByte(); short bundleamount = pPacket.ReadShort(); PlayerShop ps = MiniRoomBase.PlayerShops[pCharacter.Room.ID]; if (ps != null) { ps.BuyItem(pCharacter, slot, bundleamount); } break; } case 0xA: //Leave { MiniRoomBase mr = pCharacter.Room; if (mr == null) { return; } miniroomLog.Info($"{pCharacter.Name} declined invite."); if (mr.Type == MiniRoomBase.RoomType.Trade) { for (int i = 0; i < 2; i++) { Character chr = mr.Users[i]; Character leader = mr.Users[0]; if (chr == null) { continue; } mr.RemovePlayer(chr, 1); //mr.Users[i] = null; //send this after all characters are removed } } else if (mr.Type == MiniRoomBase.RoomType.PersonalShop) { mr.RemovePlayerFromShop(pCharacter); } else if (mr.Type == MiniRoomBase.RoomType.Omok) { //MessagePacket.SendNotice("leave omok", pCharacter); Omok omok = MiniRoomBase.Omoks[pCharacter.Room.ID]; if (pCharacter == omok.Users[0]) { omok.CloseOmok(pCharacter); } else { ShowLeaveRoom(pCharacter.Room, pCharacter, 2); omok.RemovePlayer(pCharacter, 1); } } break; } case 0xB: //Add announce box { if (pCharacter.Room == null) { return; } MiniGamePacket.AddAnnounceBox(pCharacter, (byte)pCharacter.Room.Type, pCharacter.Room.ID, pCharacter.Room.Title, pCharacter.Room.Private, 0, false); byte RoomType = (byte)pCharacter.Room.Type; switch (RoomType) { case 1: { pCharacter.Field.Omoks.Add(pCharacter.Room.ID, MiniRoomBase.Omoks[pCharacter.Room.ID]); break; } case 4: { pCharacter.Field.PlayerShops.Add(pCharacter.Room.ID, MiniRoomBase.PlayerShops[pCharacter.Room.ID]); break; } } break; } case 0x17: //Move Item from player shop to inventory { return; if (pCharacter.AssertForHack(!(pCharacter.Room is PlayerShop), "PlayerShop hack: taking back item while not in playershop")) { return; } byte slot = pPacket.ReadByte(); //reads as byte, sends as short... wtf lol PlayerShop ps = pCharacter.Room as PlayerShop; if (pCharacter.AssertForHack(ps.Owner != pCharacter, "PlayerShop hack: taking back item while not owner")) { return; } ps.HandleMoveItemBack(pCharacter, slot); ps.Items.Remove(slot); break; } case 0x19: //Request tie result { bool result = pPacket.ReadBool(); break; } case 0x20: //Ready { MiniGamePacket.Ready(pCharacter, pCharacter.Room); break; } case 0x21: { MiniGamePacket.UnReady(pCharacter, pCharacter.Room); break; } case 0x22: //Expell user { //Todo : expell break; } case 0x23: { Omok omok = MiniRoomBase.Omoks[pCharacter.Room.ID]; if (omok != null) { MiniGamePacket.Start(pCharacter, pCharacter.Room); omok.GameStarted = true; } break; } case 0x25: { Omok omok = MiniRoomBase.Omoks[pCharacter.Room.ID]; omok.UpdateGame(pCharacter); omok.GameStarted = false; break; } case 0x26: //Place omok piece { Omok omok = MiniRoomBase.Omoks[pCharacter.Room.ID]; if (omok != null) { int X = pPacket.ReadInt(); int Y = pPacket.ReadInt(); byte Piece = pPacket.ReadByte(); if (omok.Stones[X, Y] != Piece && omok.Stones[X, Y] != omok.GetOtherPiece(Piece)) { MiniGamePacket.MoveOmokPiece(pCharacter, pCharacter.Room, X, Y, Piece); omok.AddStone(X, Y, Piece, pCharacter); } else { MiniGamePacket.OmokMessage(pCharacter, pCharacter.Room, 0); } //MessagePacket.SendNotice("X : " + X + " Y : " + Y, pCharacter); if (omok.CheckStone(Piece)) { //MessagePacket.SendNotice("Win!", pCharacter); omok.UpdateGame(pCharacter); Piece = 0xFF; omok.GameStarted = false; } } break; } case 0x1C: { for (int i = 0; i < 2; i++) { if (pCharacter.Room.Users[i] != pCharacter) { MiniGamePacket.RequestHandicap(pCharacter.Room.Users[i], pCharacter.Room); } } break; } case 0x1D: //Request handicap result { bool result = pPacket.ReadBool(); Omok omok = MiniRoomBase.Omoks[pCharacter.Room.ID]; if (omok != null) { if (result == true) { for (int i = 0; i < 2; i++) { if (pCharacter.Room.Users[i] != pCharacter) { if (omok.PlacedStone[i] == false) { MiniGamePacket.RequestHandicapResult(pCharacter, pCharacter.Room, result, 2); omok.TotalStones -= 2; //MessagePacket.SendNotice("removed", pCharacter); } else { MiniGamePacket.RequestHandicapResult(pCharacter, pCharacter.Room, result, 1); omok.TotalStones--; //omok.Stones[omok.LastPlacedStone[(byte)(pCharacter.RoomSlotId + 1)].mX, omok.LastPlacedStone[(byte)(pCharacter.RoomSlotId + 1)].mY] = 0xFF; //MessagePacket.SendNotice("Removed stone", pCharacter); } } } } } break; } default: { if (pCharacter.Room != null) { pCharacter.Room.OnPacket(pCharacter, Type, pPacket); } //MessagePacket.SendNotice("This feature is currently disabled due to maintenance.", pCharacter); break; } } }
public bool TryHandlePlayerPacket(Packet packet, ISServerMessages msg) { switch (msg) { case ISServerMessages.PlayerChangeServerResult: { string session = packet.ReadString(); Player player = Server.Instance.GetPlayer(session); if (player != null) { player.Socket.StartLogging(); int charid = packet.ReadInt(); byte[] ip = packet.ReadBytes(4); ushort port = packet.ReadUShort(); if (port == 0) { Packet pw = new Packet(ServerMessages.TRANSFER_CHANNEL_REQ_IGNORED); player.Character.SendPacket(pw); } else { player.Character.CleanupInstances(); RedisBackend.Instance.SetPlayerCCIsBeingProcessed(charid); player.IsCC = true; player.Socket.SendConnectToServer(ip, port); } } else { Program.MainForm.LogAppend("Tried to CC unknown player (unknown hash)"); } break; } case ISServerMessages.PlayerWhisperOrFindOperationResult: { bool whisper = packet.ReadBool(); bool found = packet.ReadBool(); int victim = packet.ReadInt(); Character victimChar = Server.Instance.GetCharacter(victim); if (victimChar == null) { break; } victimChar.Player.Socket.StartLogging(); if (whisper) { if (found) { string sender = packet.ReadString(); byte channel = packet.ReadByte(); string message = packet.ReadString(); bool direction = packet.ReadBool(); byte directionByte = 18; if (direction) { directionByte = 10; } MessagePacket.Whisper(victimChar, sender, channel, message, directionByte); } else { string sender = packet.ReadString(); MessagePacket.Find(victimChar, sender, -1, 0, false); } } else { if (found) { string sender = packet.ReadString(); sbyte channel = packet.ReadSByte(); sbyte wat = packet.ReadSByte(); MessagePacket.Find(victimChar, sender, channel, wat, false); } else { string sender = packet.ReadString(); MessagePacket.Find(victimChar, sender, -1, 0, false); } } break; } case ISServerMessages.PlayerSuperMegaphone: { MessagePacket.SendSuperMegaphoneMessage(packet.ReadString(), packet.ReadBool(), packet.ReadByte()); break; } case ISServerMessages.AdminMessage: { string message = packet.ReadString(); byte type = packet.ReadByte(); Packet pw = new Packet(ServerMessages.BROADCAST_MSG); pw.WriteByte(type); pw.WriteString(message); if (type == 4) { pw.WriteBool(message.Length != 0); } foreach (var kvp in DataProvider.Maps) { kvp.Value.SendPacket(pw); } break; } case ISServerMessages.PlayerChangeServerData: { var charid = packet.ReadInt(); var readBufferPacket = new Packet(packet.ReadLeftoverBytes()); Server.Instance.CCIngPlayerList[charid] = new Tuple <Packet, long>(readBufferPacket, MasterThread.CurrentTime); break; } case ISServerMessages.KickPlayerResult: { int userId = packet.ReadInt(); Player player = Server.Instance.PlayerList.Values.FirstOrDefault(p => p.Character != null && p.Character.UserID == userId); if (player != null) { Program.MainForm.LogAppend("Handling centerserver kick request for user " + userId); player.Socket.Disconnect(); } break; } case ISServerMessages.PlayerSendPacket: { Character pChar = Server.Instance.GetCharacter(packet.ReadInt()); ////Console.WriteLine(pChar.Name); pChar?.SendPacket(packet.ReadLeftoverBytes()); break; } default: return(false); } return(true); }
public void OnPlayerLoad(Packet packet) { var characterId = packet.ReadInt(); ThreadContext.Properties["CharacterID"] = characterId; if (RedisBackend.Instance.HoldoffPlayerConnection(characterId)) { Program.MainForm.LogAppend("Bouncing charid: " + characterId); SendConnectToServer(Server.Instance.PublicIP.GetAddressBytes(), Server.Instance.Port, true); return; } if (RedisBackend.Instance.PlayerIsMigrating(characterId, true) == false) { var msg = "Disconnecting because not migrating. Charid: " + characterId; Server.Instance.ServerTraceDiscordReporter.Enqueue(msg); Program.MainForm.LogAppend(msg); goto cleanup_and_disconnect; } var uId = Server.Instance.CharacterDatabase.UserIDByCharID(characterId); ThreadContext.Properties["UserID"] = uId; if (Server.Instance.CharacterDatabase.IsBanned(uId)) { var msg = "Disconnecting because banned. Charid: " + characterId + ". Userid: " + uId; Server.Instance.ServerTraceDiscordReporter.Enqueue(msg); Program.MainForm.LogAppend(msg); goto cleanup_and_disconnect; } if (Server.Instance.CharacterDatabase.IsIpBanned(IP)) { var msg = "Disconnecting because IP banned. Charid: " + characterId + ". Userid: " + uId + ". IP: " + IP; Server.Instance.ServerTraceDiscordReporter.Enqueue(msg); Program.MainForm.LogAppend(msg); goto cleanup_and_disconnect; } if (Server.Instance.CharacterList.ContainsKey(characterId)) { var msg = "Disconnecting characterId " + characterId + " from IP " + IP + ". Already connected in this channel."; Server.Instance.ServerTraceDiscordReporter.Enqueue(msg); Program.MainForm.LogAppend(msg); goto cleanup_and_disconnect; } var character = new Character(characterId); var loadResult = character.Load(IP); if (loadResult != Character.LoadFailReasons.None) { var msg = "Disconnected characterId " + characterId + " from IP " + IP + ". " + loadResult; Server.Instance.ServerTraceDiscordReporter.Enqueue(msg); Program.MainForm.LogAppend(msg); goto cleanup_and_disconnect; } Player.Character = character; character.Player = Player; StartLogging(); Program.MainForm.LogAppend(character.Name + " connected from IP " + IP + "."); Program.MainForm.ChangeLoad(true); Server.Instance.CharacterList.Add(characterId, character); if (character.IsGM) { Server.Instance.StaffCharacters.Add(character); } Loaded = true; //have to load summons after he joins the map, so i have moved this from the load method -Exile if (Server.Instance.CCIngPlayerList.TryGetValue(character.ID, out var info)) { Server.Instance.CCIngPlayerList.Remove(character.ID); } var ccPacket = info?.Item1; if (ccPacket != null) { character.PrimaryStats.DecodeForCC(ccPacket); } character.PrimaryStats.CheckHPMP(); MapPacket.SendJoinGame(character); if (character.IsGM) { string glevel = character.GMLevel == 1 ? "(GM Intern)" : character.GMLevel == 2 ? "(GM)" : "(Admin)"; MessagePacket.SendNotice("Your GM Level: " + character.GMLevel + " " + glevel + ". Undercover? " + (character.Undercover ? "Yes" : "No"), character); } if (character.IsGM && !character.Undercover) { character.TryActivateHide(); } character.Field.AddPlayer(character); if (ccPacket != null) { character.Summons.DecodeForCC(ccPacket); } MessagePacket.SendText(MessagePacket.MessageTypes.Header, Server.Instance.ScrollingHeader, character, MessagePacket.MessageMode.ToPlayer); Server.Instance.CenterConnection.RegisterCharacter(character.ID, character.Name, character.PrimaryStats.Job, character.PrimaryStats.Level, character.GMLevel); Server.Instance.CenterConnection.RequestBuddyListLoad(character.Name, false, character.PrimaryStats.BuddyListCapacity); //Sends a packet that request the buddylistload from the centerserver character.IsOnline = true; Server.Instance.CenterConnection.PlayerUpdateMap(character); // Just to be sure, check if he was banned if (RedisBackend.Instance.TryGetNonGameHackDetect(Player.Character.UserID, out var hax)) { HackDetected = hax; OnHackDetected(); } else if (HackDetected.HasValue) { OnHackDetected(); } return; cleanup_and_disconnect: Server.Instance.CCIngPlayerList.Remove(characterId); Disconnect(); }
public override void AC_OnPacketInbound(Packet packet) { ClientMessages header = 0; try { header = (ClientMessages)packet.ReadByte(); if (!Loaded || Player?.Character == null) { switch (header) { case ClientMessages.MIGRATE_IN: OnPlayerLoad(packet); break; //updated } } // Block packets as we are migrating else if (Server.Instance.InMigration == false || Server.Instance.IsNewServerInMigration) { var character = Player.Character; if (logPackets.Contains(header)) { PacketLog.ReceivedPacket(packet, (byte)header, Server.Instance.Name, IP); } switch (header) { case ClientMessages.ENTER_PORTAL: MapPacket.OnEnterPortal(packet, character); break; case ClientMessages.CHANGE_CHANNEL: OnChangeChannel(character, packet); break; case ClientMessages.ENTER_CASH_SHOP: OnEnterCashShop(character); break; case ClientMessages.MOVE_PLAYER: MapPacket.HandleMove(character, packet); break; case ClientMessages.SIT_REQUEST: MapPacket.HandleSitChair(character, packet); break; case ClientMessages.ENTER_TOWN_PORTAL: MapPacket.HandleDoorUse(character, packet); break; case ClientMessages.CLOSE_RANGE_ATTACK: AttackPacket.HandleMeleeAttack(character, packet); break; case ClientMessages.RANGED_ATTACK: AttackPacket.HandleRangedAttack(character, packet); break; case ClientMessages.MAGIC_ATTACK: AttackPacket.HandleMagicAttack(character, packet); break; case ClientMessages.TAKE_DAMAGE: CharacterStatsPacket.HandleCharacterDamage(character, packet); break; case ClientMessages.CHAT: MessagePacket.HandleChat(character, packet); break; case ClientMessages.GROUP_MESSAGE: MessagePacket.HandleSpecialChat(character, packet); break; case ClientMessages.WHISPER: MessagePacket.HandleCommand(character, packet); break; case ClientMessages.EMOTE: MapPacket.SendEmotion(character, packet.ReadInt()); break; case ClientMessages.NPC_TALK: MapPacket.HandleNPCChat(character, packet); break; case ClientMessages.NPC_TALK_MORE: NpcPacket.HandleNPCChat(character, packet); break; case ClientMessages.SHOP_ACTION: NpcPacket.HandleNPCShop(character, packet); break; case ClientMessages.STORAGE_ACTION: StoragePacket.HandleStorage(character, packet); break; case ClientMessages.ITEM_MOVE: InventoryPacket.HandleInventoryPacket(character, packet); break; case ClientMessages.ITEM_USE: InventoryPacket.HandleUseItemPacket(character, packet); break; case ClientMessages.SUMMON_BAG_USE: InventoryPacket.HandleUseSummonSack(character, packet); break; case ClientMessages.CASH_ITEM_USE: CashPacket.HandleCashItem(character, packet); break; case ClientMessages.RETURN_SCROLL_USE: InventoryPacket.HandleUseReturnScroll(character, packet); break; case ClientMessages.SCROLL_USE: InventoryPacket.HandleScrollItem(character, packet); break; case ClientMessages.DISTRIBUTE_AP: CharacterStatsPacket.HandleStats(character, packet); break; case ClientMessages.HEAL_OVER_TIME: CharacterStatsPacket.HandleHeal(character, packet); break; case ClientMessages.DISTRIBUTE_SP: SkillPacket.HandleAddSkillLevel(character, packet); break; case ClientMessages.PREPARE_SKILL: SkillPacket.HandlePrepareSkill(character, packet); break; case ClientMessages.GIVE_BUFF: SkillPacket.HandleUseSkill(character, packet); break; case ClientMessages.CANCEL_BUFF: SkillPacket.HandleStopSkill(character, packet); break; case ClientMessages.DROP_MESOS: DropPacket.HandleDropMesos(character, packet.ReadInt()); break; case ClientMessages.GIVE_FAME: FamePacket.HandleFame(character, packet); break; case ClientMessages.CHAR_INFO_REQUEST: MapPacket.SendPlayerInfo(character, packet); break; case ClientMessages.SPAWN_PET: PetsPacket.HandleSpawnPet(character, packet.ReadShort()); break; case ClientMessages.SUMMON_MOVE: MapPacket.HandleSummonMove(character, packet); break; case ClientMessages.SUMMON_ATTACK: AttackPacket.HandleSummonAttack(character, packet); break; case ClientMessages.SUMMON_DAMAGED: MapPacket.HandleSummonDamage(character, packet); break; case ClientMessages.MOB_MOVE: MobPacket.HandleMobControl(character, packet); break; case ClientMessages.NPC_ANIMATE: MapPacket.HandleNPCAnimation(character, packet); break; case ClientMessages.PET_MOVE: PetsPacket.HandleMovePet(character, packet); break; case ClientMessages.PET_INTERACTION: PetsPacket.HandleInteraction(character, packet); break; case ClientMessages.PET_ACTION: PetsPacket.HandlePetAction(character, packet); break; case ClientMessages.FIELD_CONTIMOVE_STATE: MapPacket.OnContiMoveState(character, packet); break; case ClientMessages.DROP_PICK_UP: DropPacket.HandlePickupDrop(character, packet); break; case ClientMessages.MESSENGER: MessengerHandler.HandleMessenger(character, packet); break; case ClientMessages.MINI_ROOM_OPERATION: MiniRoomPacket.HandlePacket(character, packet); break; case ClientMessages.FRIEND_OPERATION: BuddyHandler.HandleBuddy(character, packet); break; case ClientMessages.PARTY_OPERATION: PartyHandler.HandleParty(character, packet); break; case ClientMessages.DENY_PARTY_REQUEST: PartyHandler.HandleDecline(character, packet); break; case ClientMessages.REACTOR_HIT: ReactorPacket.HandleReactorHit(character, packet); break; case ClientMessages.REPORT_USER: MiscPacket.ReportPlayer(character, packet); break; //this is a garbage opcode that i use when doing janky client packet workarounds. This is where packets go to die. case ClientMessages.JUNK: Program.MainForm.LogDebug("received junk packet"); break; // eh.. ignore? // Happens when one of the following buffs are set: // Stun, Poison, Seal, Darkness, Weakness, Curse // Maybe patch out of the client case ClientMessages.CHARACTER_IS_DEBUFFED: break; // TODO: Implement??? case ClientMessages.MOB_APPLY_CONTROL: break; case ClientMessages.CLIENT_HASH: break; case ClientMessages.PONG: // Make sure we update the player online thing RedisBackend.Instance.SetPlayerOnline( character.UserID, Server.Instance.GetOnlineId() ); // Cleanup expired items character.Inventory.CheckExpired(); break; default: if (character.Field.HandlePacket(character, packet, header) == false) { Program.MainForm.LogAppend( "[{0}] Unknown packet received! " + packet, header ); } break; } } } catch (Exception ex) { Program.MainForm.LogAppend($"---- ERROR ----\r\n{ex}"); Program.MainForm.LogAppend($"Packet: {packet}"); FileWriter.WriteLine(@"etclog\ExceptionCatcher.log", "[Game Server " + Server.Instance.ID + "][" + DateTime.Now + "] Exception caught: " + ex, true); //Disconnect(); } #if DEBUG if (packet.Length != packet.Position) { var packetStr = packet.ToString(); packetStr = packetStr.Substring(0, packet.Position * 3 - 1) + "-x-" + packetStr.Substring(packet.Position * 3); log.Debug($"Did not read full message in packet: {header} {packetStr}"); } #endif }
public static void HandleCashItem(Character chr, Packet packet) { short slot = packet.ReadShort(); int itemid = packet.ReadInt(); BaseItem item = chr.Inventory.GetItem(2, slot); if (chr.AssertForHack(item == null, "HandleCashItem with null item") || chr.AssertForHack(item.ItemID != itemid, "HandleCashItem with itemid inconsistency") || chr.AssertForHack(!DataProvider.Items.TryGetValue(itemid, out var data), "HandleCashItem with unknown item") || chr.AssertForHack(!data.Cash, "HandleCashItem with non-cash item")) { return; } var itemType = (Constants.Items.Types.ItemTypes)Constants.getItemType(itemid); bool used = false; switch (itemType) { case Constants.Items.Types.ItemTypes.ItemWeather: used = chr.Field.MakeWeatherEffect(itemid, packet.ReadString(), new TimeSpan(0, 0, 30)); break; case Constants.Items.Types.ItemTypes.ItemJukebox: used = chr.Field.MakeJukeboxEffect(itemid, chr.Name, packet.ReadInt()); break; case Constants.Items.Types.ItemTypes.ItemPetTag: { var name = packet.ReadString(); var petItem = chr.GetSpawnedPet(); if (petItem != null && !chr.IsInvalidTextInput("Pet name tag", name, Constants.MaxPetName, Constants.MinPetName)) { petItem.Name = name; PetsPacket.SendPetNamechange(chr, petItem.Name); used = true; } } break; case Constants.Items.Types.ItemTypes.ItemMegaPhone: { var text = packet.ReadString(); if (!chr.IsInvalidTextInput("Megaphone item", text, Constants.MaxSpeakerTextLength)) { switch (itemid) { case 2081000: // Super Megaphone (channel) MessagePacket.SendMegaphoneMessage(chr.Name + " : " + text); used = true; break; case 2082000: // Super Megaphone Server.Instance.CenterConnection.PlayerSuperMegaphone( chr.Name + " : " + text, packet.ReadBool() ); used = true; break; } } } break; case Constants.Items.Types.ItemTypes.ItemKite: if (chr.Field.Kites.Count > 0) { //Todo : check for character positions..? MapPacket.KiteMessage(chr); } else { string message = packet.ReadString(); Kite pKite = new Kite(chr, chr.ID, itemid, message, chr.Field); used = true; } break; case Constants.Items.Types.ItemTypes.ItemMesoSack: if (data.Mesos > 0) { int amountGot = chr.AddMesos(data.Mesos); MiscPacket.SendGotMesosFromLucksack(chr, amountGot); used = true; } break; case Constants.Items.Types.ItemTypes.ItemTeleportRock: { byte mode = packet.ReadByte(); int map = -1; if (mode == 1) { string name = packet.ReadString(); Character target = Server.Instance.GetCharacter(name); if (target != null && target != chr) { map = target.MapID; used = true; } else { SendRockError(chr, RockErrors.DifficultToLocate); } } else { map = packet.ReadInt(); if (!chr.Inventory.HasRockLocation(map)) { map = -1; } } if (map != -1) { //I don't think it's even possible for you to be in a map that doesn't exist and use a Teleport rock? Map from = chr.Field; Map to = DataProvider.Maps.ContainsKey(map) ? DataProvider.Maps[map] : null; if (to == from) { SendRockError(chr, RockErrors.AlreadyThere); } else if (from.Limitations.HasFlag(FieldLimit.TeleportItemLimit)) { SendRockError(chr, RockErrors.CannotGo); } else if (chr.AssertForHack(chr.PrimaryStats.Level < 7, "Using telerock while not lvl 8 or higher.")) { // Hacks. } else { chr.ChangeMap(map); used = true; } } break; } default: Program.MainForm.LogAppend("Unknown cashitem used: {0} {1} {2}", itemType, itemid, packet.ToString()); break; } if (used) { ItemTransfer.ItemUsed(chr.ID, item.ItemID, 1, ""); chr.Inventory.TakeItem(item.ItemID, 1); } else { InventoryPacket.NoChange(chr); } }
public void OnVarset(Character Sent, string Var, object Value, object Value2 = null, object Value3 = null) { if (this != Sent && Sent.IsGM && !Sent.IsAdmin) //Todo Admin levels { MessagePacket.SendNotice("You don't have the premission to edit other players stats!", Sent); //$"{Sent.Name} tried to edit another players stats without premission" } else { try { MapPacket.AvatarModFlag AvatarMod = 0; CharacterStatsPacket.StatFlags dwFlag = 0; switch (Var.ToLower()) { case "hp": dwFlag |= CharacterStatsPacket.StatFlags.Hp; PrimaryStats.HP = Convert.ToInt16(Value); break; case "mp": dwFlag |= CharacterStatsPacket.StatFlags.Mp; PrimaryStats.MP = Convert.ToInt16(Value); break; case "exp": dwFlag |= CharacterStatsPacket.StatFlags.Exp; PrimaryStats.EXP = Convert.ToInt32(Value); break; case "maxhp": dwFlag |= CharacterStatsPacket.StatFlags.MaxHp; if (Value.ToString() == "0") { Value = "1"; } PrimaryStats.MaxHP = Convert.ToInt16(Value); break; case "maxmp": dwFlag |= CharacterStatsPacket.StatFlags.MaxMp; if (Value.ToString() == "0") { Value = "1"; } PrimaryStats.MaxMP = Convert.ToInt16(Value); break; case "ap": dwFlag |= CharacterStatsPacket.StatFlags.Ap; PrimaryStats.AP = Convert.ToInt16(Value); break; case "sp": dwFlag |= CharacterStatsPacket.StatFlags.Sp; PrimaryStats.SP = Convert.ToInt16(Value); break; case "str": dwFlag |= CharacterStatsPacket.StatFlags.Str; PrimaryStats.Str = Convert.ToInt16(Value); break; case "dex": dwFlag |= CharacterStatsPacket.StatFlags.Dex; PrimaryStats.Dex = Convert.ToInt16(Value); break; case "int": dwFlag |= CharacterStatsPacket.StatFlags.Int; PrimaryStats.Int = Convert.ToInt16(Value); break; case "luk": dwFlag |= CharacterStatsPacket.StatFlags.Luk; PrimaryStats.Luk = Convert.ToInt16(Value); break; case "fame": case "pop": dwFlag |= CharacterStatsPacket.StatFlags.Fame; PrimaryStats.Fame = Convert.ToInt16(Value); break; case "mesos": dwFlag |= CharacterStatsPacket.StatFlags.Mesos; Inventory.Mesos = Convert.ToInt32(Value); break; case "job": { var Job = Convert.ToInt16(Value); if (DataProvider.HasJob(Job) || Job == 0) { dwFlag |= CharacterStatsPacket.StatFlags.Job; PrimaryStats.Job = Job; } else { MessagePacket.SendNotice($"Job {Job} does not exist.", Sent); } break; } case "skill": { var SkillID = Convert.ToInt32(Value); if (DataProvider.Skills.TryGetValue(SkillID, out var Skill)) { if (Value2 == null) { Value2 = Skill.MaxLevel; } Skills.SetSkillPoint(SkillID, Convert.ToByte(Value2), true); } else { MessagePacket.SendNotice($"Skill {SkillID} does not exist.", Sent); } break; } case "level": dwFlag |= CharacterStatsPacket.StatFlags.Level; Level = Convert.ToByte(Value); MapPacket.SendPlayerLevelupAnim(this); break; case "skin": { var SkinID = Convert.ToByte(Value); if (SkinID >= 0 && SkinID < 6) { AvatarMod |= MapPacket.AvatarModFlag.Skin; dwFlag |= CharacterStatsPacket.StatFlags.Skin; Skin = SkinID; } else { MessagePacket.SendNotice($"Skin {SkinID} does not exist.", Sent); } break; } case "face": { var FaceID = Convert.ToInt32(Value); if (DataProvider.Equips.ContainsKey(FaceID)) { AvatarMod |= MapPacket.AvatarModFlag.Face; dwFlag |= CharacterStatsPacket.StatFlags.Eyes; Face = FaceID; } else { MessagePacket.SendNotice($"Face {FaceID} does not exist.", Sent); } break; } case "hair": { var HairID = Convert.ToInt32(Value); if (DataProvider.Equips.ContainsKey(HairID)) { AvatarMod |= MapPacket.AvatarModFlag.Equips; dwFlag |= CharacterStatsPacket.StatFlags.Hair; Hair = HairID; } else { MessagePacket.SendNotice($"Hair {HairID} does not exist.", Sent); } break; } case "gender": { Gender = ParseGenderString(Value.ToString()); Server.Instance.CharacterDatabase.RunQuery( "UPDATE characters SET gender = @gender WHERE id = @id", "@gender", Gender, "@id", ID ); MessagePacket.SendNotice($"Gender set to {(Gender == 0 ? "male" : (Gender == 2 ? "Unisex" : "female"))}. Please relog.", this); break; } case "accgender": { var gender = ParseGenderString(Value.ToString()); Server.Instance.CharacterDatabase.RunQuery( "UPDATE users SET gender = @gender WHERE ID = @id", "@gender", gender, "@id", UserID ); MessagePacket.SendNotice($"Account gender set to {(gender == 0 ? "male" : (gender == 2 ? "Unisex" : "female"))}", this); break; } case "map": case "field": { var FieldID = Convert.ToInt32(Value); if (DataProvider.Maps.ContainsKey(FieldID)) { ChangeMap(FieldID); } else { MessagePacket.SendText(MessagePacket.MessageTypes.RedText, "Map not found.", this, MessagePacket.MessageMode.ToPlayer); } break; } default: MessagePacket.SendNotice($"{Var} is not a valid Variable!", Sent); return; } if (dwFlag != 0) { CharacterStatsPacket.SendUpdateStat(this, true, dwFlag); } if (AvatarMod != 0) { MapPacket.SendAvatarModified(this, AvatarMod); } } catch (Exception ex) { MessagePacket.SendNotice(ex.Message, Sent); } } }
public void OnPetVarset(string Var, string Value, bool Me) { MessagePacket.SendNotice("Did you hear a cat just now? That damn thing haunts me.", this); }
public static void HandleInventoryPacket(Character chr, Packet packet) { try { byte inventory = packet.ReadByte(); short slotFrom = packet.ReadShort(); // Slot from short slotTo = packet.ReadShort(); // Slot to if (slotFrom == 0 || inventory < 0 || inventory > 5) { goto no_op; } Trace.WriteLine($"Trying to swap from {slotFrom} to {slotTo}, inventory {inventory}"); if (slotFrom < 0) { Trace.WriteLine("From: " + (Constants.EquipSlots.Slots)((-slotFrom) % 100)); } if (slotTo < 0) { Trace.WriteLine("To: " + (Constants.EquipSlots.Slots)((-slotTo) % 100)); } var itemFrom = chr.Inventory.GetItem(inventory, slotFrom); // Item being moved var itemTo = chr.Inventory.GetItem(inventory, slotTo); // Item in target position, if any if (itemFrom == null) { goto no_op; // Packet Editing, from slot contains no item. } if (slotTo < 0 && slotFrom < 0) { goto no_op; // Packet Editing, both target and source slots are in equip. } if (slotFrom > 0 && slotTo < 0) { Trace.WriteLine($"HandleEquip"); HandleEquip(chr, itemFrom, itemTo, slotFrom, slotTo); } else if (slotFrom < 0 && slotTo > 0) { Trace.WriteLine($"Unequip"); Unequip(chr, itemFrom, slotTo); } else if (slotTo == 0) { if (chr.IsGM && !chr.IsAdmin) { MessagePacket.SendAdminWarning(chr, "You cannot drop items."); NoChange(chr); } else { var quantity = packet.ReadShort(); DropItem(chr, inventory, slotFrom, quantity); } } else { Trace.WriteLine($"Changing slot"); ChangeSlot(chr, itemFrom, itemTo, slotFrom, slotTo); } chr.PrimaryStats.CheckBoosters(); // TO-DO: Pets + Rings return; } catch (Exception ex) { Program.MainForm.LogAppend("[{0}] Exception item movement handler: {1}", chr.ID, ex.ToString()); } no_op: Trace.WriteLine($"Sending nochange!"); NoChange(chr); }