public void HandlePacket(GameClient client, GSPacketIn packet) { if (client.Player == null) { return; } Region region = client.Player.CurrentRegion; if (region == null) { return; } ushort id; if (client.Version >= GameClient.eClientVersion.Version1126) { id = packet.ReadShortLowEndian(); // Dre: disassembled game.dll show a write of uint, is it a wip in the game.dll? } else { id = packet.ReadShort(); } GameNPC npc = region.GetObject(id) as GameNPC; if (npc == null || !client.Player.IsWithinRadius(npc, WorldMgr.OBJ_UPDATE_DISTANCE)) { client.Out.SendObjectDelete(id); return; } if (npc != null) { Tuple <ushort, ushort> key = new Tuple <ushort, ushort>(npc.CurrentRegionID, (ushort)npc.ObjectID); long updatetime; if (!client.GameObjectUpdateArray.TryGetValue(key, out updatetime)) { updatetime = 0; } client.Out.SendNPCCreate(npc); // override update from npc create as this is a client request ! if (updatetime > 0) { client.GameObjectUpdateArray[key] = updatetime; } if (npc.Inventory != null) { client.Out.SendLivingEquipmentUpdate(npc); } //DO NOT SEND A NPC UPDATE, it is done in Create anyway //Sending a Update causes a UDP packet to be sent and //the client will get the UDP packet before the TCP Create packet //Causing the client to issue another NPC CREATION REQUEST! //client.Out.SendNPCUpdate(npc); <-- BIG NO NO } }
public void HandlePacket(GameClient client, GSPacketIn packet) { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } // Send the crypt key to the client client.Out.SendVersionAndCryptKey(); }
public void HandlePacket(GameClient client, GSPacketIn packet) { // for 1.115c+ The First client packet Changes. if (client.Version < GameClient.eClientVersion.Version1115) { int rc4 = packet.ReadByte(); byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); byte major = (byte)packet.ReadByte(); byte minor = (byte)packet.ReadByte(); byte build = (byte)packet.ReadByte(); if (rc4 == 1) { //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(client.PacketProcessor.Encoding.SBox); packet.Read(((PacketEncoding168)client.PacketProcessor.Encoding).SBox, 0, 256); ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState = PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; //DOLConsole.WriteLine(client.Socket.RemoteEndPoint.ToString()+": SBox set!"); //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(((PacketEncoding168)client.PacketProcessor.Encoding).SBox); } else { //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } } else { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { // for 1.115c+ The First client packet Changes. if (client.Version < GameClient.eClientVersion.Version1115) { int rc4 = packet.ReadByte(); byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); byte major = (byte)packet.ReadByte(); byte minor = (byte)packet.ReadByte(); byte build = (byte)packet.ReadByte(); if(rc4==1) { //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(client.PacketProcessor.Encoding.SBox); packet.Read(((PacketEncoding168)client.PacketProcessor.Encoding).SBox,0,256); ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; //DOLConsole.WriteLine(client.Socket.RemoteEndPoint.ToString()+": SBox set!"); //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(((PacketEncoding168)client.PacketProcessor.Encoding).SBox); } else { //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } } else { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { ushort id; if (client.Version >= GameClient.eClientVersion.Version1126) { id = packet.ReadShortLowEndian(); } else { id = packet.ReadShort(); } Region region = client.Player?.CurrentRegion; if (region?.GetObject(id) is GameNPC npc) { Tuple <ushort, ushort> key = new Tuple <ushort, ushort>(npc.CurrentRegionID, (ushort)npc.ObjectID); if (!client.GameObjectUpdateArray.TryGetValue(key, out var updatetime)) { updatetime = 0; } client.Out.SendNPCCreate(npc); // override update from npc create as this is a client request ! if (updatetime > 0) { client.GameObjectUpdateArray[key] = updatetime; } if (npc.Inventory != null) { client.Out.SendLivingEquipmentUpdate(npc); } // DO NOT SEND A NPC UPDATE, it is done in Create anyway // Sending a Update causes a UDP packet to be sent and // the client will get the UDP packet before the TCP Create packet // Causing the client to issue another NPC CREATION REQUEST! // client.Out.SendNPCUpdate(npc); <-- BIG NO NO } }
/// <summary> /// Reads up ONE character iteration on the packet stream /// </summary> /// <param name="packet"></param> /// <param name="client"></param> public CreationCharacterData(GSPacketIn packet, GameClient client) { //unk - probably indicates customize or create (these are moved from 1.99 4 added bytes) if (client.Version >= GameClient.eClientVersion.Version1104) { packet.ReadIntLowEndian(); } CharName = packet.ReadString(24); CustomMode = packet.ReadByte(); EyeSize = packet.ReadByte(); LipSize = packet.ReadByte(); EyeColor = packet.ReadByte(); HairColor = packet.ReadByte(); FaceType = packet.ReadByte(); HairStyle = packet.ReadByte(); packet.Skip(3); MoodType = packet.ReadByte(); packet.Skip(8); Operation = packet.ReadInt(); var unk = packet.ReadByte(); packet.Skip(24); //Location String packet.Skip(24); //Skip class name packet.Skip(24); //Skip race name var level = packet.ReadByte(); //not safe! Class = packet.ReadByte(); Realm = packet.ReadByte(); //The following byte contains //1bit=start location ... in ShroudedIsles you can choose ... //1bit=first race bit //1bit=unknown //1bit=gender (0=male, 1=female) //4bit=race byte startRaceGender = (byte)packet.ReadByte(); Race = (startRaceGender & 0x0F) + ((startRaceGender & 0x40) >> 2); Gender = ((startRaceGender >> 4) & 0x01); SIStartLocation = ((startRaceGender >> 7) != 0); CreationModel = packet.ReadShortLowEndian(); Region = packet.ReadByte(); packet.Skip(1); //TODO second byte of region unused currently packet.Skip(4); //TODO Unknown Int / last used? Strength = packet.ReadByte(); Dexterity = packet.ReadByte(); Constitution = packet.ReadByte(); Quickness = packet.ReadByte(); Intelligence = packet.ReadByte(); Piety = packet.ReadByte(); Empathy = packet.ReadByte(); Charisma = packet.ReadByte(); packet.Skip(40); //TODO equipment var activeRightSlot = packet.ReadByte(); // 0x9C var activeLeftSlot = packet.ReadByte(); // 0x9D var siZone = packet.ReadByte(); // 0x9E // skip 4 bytes added in 1.99 if (client.Version >= GameClient.eClientVersion.Version199 && client.Version < GameClient.eClientVersion.Version1104) { packet.Skip(4); } // New constitution must be read before skipping 4 bytes NewConstitution = packet.ReadByte(); // 0x9F }
public void HandlePacket(GameClient client, GSPacketIn packet) { ushort jumpSpotId; jumpSpotId = client.Version >= GameClient.eClientVersion.Version1127 ? packet.ReadShortLowEndian() : packet.ReadShort(); eRealm targetRealm = client.Player.Realm; if (client.Player.CurrentRegion.Expansion == (int)eClientExpansion.TrialsOfAtlantis && client.Player.CurrentZone.Realm != eRealm.None) { // if we are in TrialsOfAtlantis then base the target jump on the current region realm instead of the players realm // this is only used if zone table has the proper realms defined, otherwise it reverts to old behavior - Tolakram targetRealm = client.Player.CurrentZone.Realm; } var zonePoint = GameServer.Database.SelectObjects <ZonePoint>( "`Id` = @Id AND (`Realm` = @Realm OR `Realm` = @DefaultRealm OR `Realm` IS NULL)", new[] { new QueryParameter("@Id", jumpSpotId), new QueryParameter("@Realm", (byte)targetRealm), new QueryParameter("@DefaultRealm", 0) }) .FirstOrDefault(); if (zonePoint == null || zonePoint.TargetRegion == 0) { ChatUtil.SendDebugMessage(client, $"Invalid Jump (ZonePoint table): [{jumpSpotId}]{((zonePoint == null) ? ". Entry missing!" : ". TargetRegion is 0!")}"); zonePoint = new ZonePoint { Id = jumpSpotId }; } if (client.Account.PrivLevel > 1) { client.Out.SendMessage($"JumpSpotID = {jumpSpotId}", eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage($"ZonePoint Target: Region = {zonePoint.TargetRegion}, ClassType = \'{zonePoint.ClassType}\'", eChatType.CT_System, eChatLoc.CL_SystemWindow); } // Dinberg: Fix - some jump points are handled code side, such as instances. // As such, region MAY be zero in the database, so this causes an issue. if (zonePoint.TargetRegion != 0) { Region reg = WorldMgr.GetRegion(zonePoint.TargetRegion); if (reg != null) { // check for target region disabled if player is in a standard region // otherwise the custom region should handle OnZonePoint for this check if (client.Player.CurrentRegion.IsCustom == false && reg.IsDisabled) { if ((client.Player.Mission is TaskDungeonMission mission && mission.TaskRegion.Skin == reg.Skin) == false) { client.Out.SendMessage("This region has been disabled!", eChatType.CT_System, eChatLoc.CL_SystemWindow); if (client.Account.PrivLevel == 1) { return; } } } } } // Allow the region to either deny exit or handle the zonepoint in a custom way if (client.Player.CurrentRegion.OnZonePoint(client.Player, zonePoint) == false) { return; } // check caps for battleground Battleground bg = GameServer.KeepManager.GetBattleground(zonePoint.TargetRegion); if (client.Player.Level < bg?.MinLevel && client.Player.Level > bg.MaxLevel && client.Player.RealmLevel >= bg.MaxRealmLevel) { return; } IJumpPointHandler customHandler = null; if (string.IsNullOrEmpty(zonePoint.ClassType) == false) { customHandler = (IJumpPointHandler)_customJumpPointHandlers[zonePoint.ClassType]; // check for db change to update cached handler if (customHandler != null && customHandler.GetType().FullName != zonePoint.ClassType) { customHandler = null; } if (customHandler == null) { // Dinberg - Instances need to use a special handler. This is because some instances will result // in duplicated zonepoints, such as if Tir Na Nog were to be instanced for a quest. string type = client.Player.CurrentRegion.IsInstance ? "DOL.GS.ServerRules.InstanceDoorJumpPoint" : zonePoint.ClassType; Type t = ScriptMgr.GetType(type); if (t == null) { Log.Error($"jump point {zonePoint.Id}: class {zonePoint.ClassType} not found!"); } else if (!typeof(IJumpPointHandler).IsAssignableFrom(t)) { Log.Error($"jump point {zonePoint.Id}: class {zonePoint.ClassType} must implement IJumpPointHandler interface!"); } else { try { customHandler = (IJumpPointHandler)Activator.CreateInstance(t); } catch (Exception e) { customHandler = null; Log.Error($"jump point {zonePoint.Id}: error creating a new instance of jump point handler {zonePoint.ClassType}", e); } } } if (customHandler != null) { _customJumpPointHandlers[zonePoint.ClassType] = customHandler; } } new RegionChangeRequestHandler(client.Player, zonePoint, customHandler).Start(1); }
public void HandlePacket(GameClient client, GSPacketIn packet) { var player = client.Player; ushort jumpSpotId; if (client.Version < GameClient.eClientVersion.Version1126) { jumpSpotId = packet.ReadShort(); } else { jumpSpotId = packet.ReadShortLowEndian(); } eRealm targetRealm = player.Realm; if (player.CurrentRegion.Expansion == (int)eClientExpansion.TrialsOfAtlantis && player.CurrentZone.Realm != eRealm.None) { // if we are in TrialsOfAtlantis then base the target jump on the current region realm instead of the players realm // this is only used if zone table has the proper realms defined, otherwise it reverts to old behavior - Tolakram targetRealm = player.CurrentZone.Realm; } var filterRealm = DB.Column(nameof(ZonePoint.Realm)).IsEqualTo((byte)targetRealm).Or(DB.Column(nameof(ZonePoint.Realm)).IsEqualTo(0)).Or(DB.Column(nameof(ZonePoint.Realm)).IsNull()); var zonePoint = DOLDB <ZonePoint> .SelectObject(DB.Column(nameof(ZonePoint.Id)).IsEqualTo(jumpSpotId).And(filterRealm)); if (zonePoint == null || zonePoint.TargetRegion == 0) { ChatUtil.SendDebugMessage(client, $"Invalid Jump (ZonePoint table): [{jumpSpotId}]{((zonePoint == null) ? ". Entry missing!" : ". TargetRegion is 0!")}"); zonePoint = new ZonePoint(); zonePoint.Id = jumpSpotId; string zonePointLocation = $"Region {player.CurrentRegionID} and coordinates ({player.X},{player.Y},{player.Z})"; Log.Error($"ZonePoint {jumpSpotId} at {zonePointLocation} on client {client.Version} missing. Either ZonePoint missing or RegionChangeRequestHandler needs to be updated."); } if (client.Account.PrivLevel > 1) { client.Out.SendMessage($"JumpSpotID = {jumpSpotId}", eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage($"ZonePoint Target: Region = {zonePoint.TargetRegion}, ClassType = \'{zonePoint.ClassType}\'", eChatType.CT_System, eChatLoc.CL_SystemWindow); } //Dinberg: Fix - some jump points are handled code side, such as instances. //As such, region MAY be zero in the database, so this causes an issue. if (zonePoint.TargetRegion != 0) { Region reg = WorldMgr.GetRegion(zonePoint.TargetRegion); if (reg != null) { // check for target region disabled if player is in a standard region // otherwise the custom region should handle OnZonePoint for this check if (player.CurrentRegion.IsCustom == false && reg.IsDisabled) { if ((player.Mission is TaskDungeonMission && (player.Mission as TaskDungeonMission).TaskRegion.Skin == reg.Skin) == false) { client.Out.SendMessage("This region has been disabled!", eChatType.CT_System, eChatLoc.CL_SystemWindow); if (client.Account.PrivLevel == 1) { return; } } } } } // Allow the region to either deny exit or handle the zonepoint in a custom way if (player.CurrentRegion.OnZonePoint(player, zonePoint) == false) { return; } //check caps for battleground Battleground bg = GameServer.KeepManager.GetBattleground(zonePoint.TargetRegion); if (bg != null) { if (player.Level < bg.MinLevel && player.Level > bg.MaxLevel && player.RealmLevel >= bg.MaxRealmLevel) { return; } } IJumpPointHandler customHandler = null; if (string.IsNullOrEmpty(zonePoint.ClassType) == false) { customHandler = (IJumpPointHandler)m_customJumpPointHandlers[zonePoint.ClassType]; // check for db change to update cached handler if (customHandler != null && customHandler.GetType().FullName != zonePoint.ClassType) { customHandler = null; } if (customHandler == null) { //Dinberg - Instances need to use a special handler. This is because some instances will result //in duplicated zonepoints, such as if Tir Na Nog were to be instanced for a quest. string type = player.CurrentRegion.IsInstance ? "DOL.GS.ServerRules.InstanceDoorJumpPoint" : zonePoint.ClassType; Type t = ScriptMgr.GetType(type); if (t == null) { Log.ErrorFormat("jump point {0}: class {1} not found!", zonePoint.Id, zonePoint.ClassType); } else if (!typeof(IJumpPointHandler).IsAssignableFrom(t)) { Log.ErrorFormat("jump point {0}: class {1} must implement IJumpPointHandler interface!", zonePoint.Id, zonePoint.ClassType); } else { try { customHandler = (IJumpPointHandler)Activator.CreateInstance(t); } catch (Exception e) { customHandler = null; Log.Error( string.Format("jump point {0}: error creating a new instance of jump point handler {1}", zonePoint.Id, zonePoint.ClassType), e); } } } if (customHandler != null) { m_customJumpPointHandlers[zonePoint.ClassType] = customHandler; } } new RegionChangeRequestHandler(player, zonePoint, customHandler).Start(1); }
private int CheckCharacterForUpdates(GameClient client, GSPacketIn packet, DOLCharacters character, string charName, byte customizationMode) { int newModel = character.CurrentModel; if (customizationMode == 1 || customizationMode == 2 || customizationMode == 3) { bool flagChangedStats = false; character.EyeSize = (byte)packet.ReadByte(); character.LipSize = (byte)packet.ReadByte(); character.EyeColor = (byte)packet.ReadByte(); character.HairColor = (byte)packet.ReadByte(); character.FaceType = (byte)packet.ReadByte(); character.HairStyle = (byte)packet.ReadByte(); packet.Skip(3); character.MoodType = (byte)packet.ReadByte(); packet.Skip(89); // Skip location string, race string, classe string, level ,class ,realm and startRaceGender newModel = packet.ReadShortLowEndian(); //read new model if (customizationMode != 3 && client.Version >= GameClient.eClientVersion.Version189) { packet.Skip(6); // Region ID + character Internal ID int[] stats = new int[8]; stats[0] = (byte)packet.ReadByte(); // Strength stats[2] = (byte)packet.ReadByte(); // Dexterity stats[1] = (byte)packet.ReadByte(); // Constitution stats[3] = (byte)packet.ReadByte(); // Quickness stats[4] = (byte)packet.ReadByte(); // Intelligence stats[5] = (byte)packet.ReadByte(); // Piety stats[6] = (byte)packet.ReadByte(); // Empathy stats[7] = (byte)packet.ReadByte(); // Charisma packet.Skip(43);// armor models/armor color/weapon models/active weapon slots/siZone if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } // what is this? byte newConstitution = (byte)packet.ReadByte(); if (newConstitution > 0 && newConstitution < 255) // added 255 check, still not sure why this is here - tolakram stats[1] = newConstitution; flagChangedStats |= stats[0] != character.Strength; flagChangedStats |= stats[1] != character.Constitution; flagChangedStats |= stats[2] != character.Dexterity; flagChangedStats |= stats[3] != character.Quickness; flagChangedStats |= stats[4] != character.Intelligence; flagChangedStats |= stats[5] != character.Piety; flagChangedStats |= stats[6] != character.Empathy; flagChangedStats |= stats[7] != character.Charisma; // // !! Stat changes disabled by Tolakram until someone figures out why this can create invalid stats !! // flagChangedStats = false; if (flagChangedStats) { ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class); if (charClass != null) { int points = 0; int[] leveledStats = new int[8]; int[] raceStats = new int[8]; bool valid = true; for (int j = 0; j < 8; j++) { eStat stat = (eStat)ValidateCharacter.eStatIndex[j]; raceStats[j] = ValidateCharacter.STARTING_STATS[character.Race][j]; for (int level = character.Level; level > 5; level--) { if (charClass.PrimaryStat != eStat.UNDEFINED && charClass.PrimaryStat == stat) { leveledStats[j]++; } if (charClass.SecondaryStat != eStat.UNDEFINED && charClass.SecondaryStat == stat) { if ((level - 6) % 2 == 0) leveledStats[j]++; } if (charClass.TertiaryStat != eStat.UNDEFINED && charClass.TertiaryStat == stat) { if ((level - 6) % 3 == 0) leveledStats[j]++; } } int result = stats[j] - leveledStats[j] - raceStats[j]; bool validBeginStat = result >= 0; int pointsUsed = result; string statCategory = ""; if (charClass.PrimaryStat != eStat.UNDEFINED && charClass.PrimaryStat == stat) statCategory = "1)"; if (charClass.SecondaryStat != eStat.UNDEFINED && charClass.SecondaryStat == stat) statCategory = "2)"; if (charClass.TertiaryStat != eStat.UNDEFINED && charClass.TertiaryStat == stat) statCategory = "3)"; pointsUsed += Math.Max(0, result - 10); //two points used pointsUsed += Math.Max(0, result - 15); //three points used log.Info(string.Format("{0,-2} {1,-3}:{2, 3} {3,3} {4,3} {5,3} {6,2} {7} {8}", statCategory, (stat == eStat.STR) ? "STR" : stat.ToString(), stats[j], leveledStats[j], stats[j] - leveledStats[j], raceStats[j], result, pointsUsed, (validBeginStat) ? "" : "Not Valid")); points += pointsUsed; if (!validBeginStat) { valid = false; if (client.Account.PrivLevel == 1) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban Hack char update : Wrong {0} point:{1}", (stat == eStat.STR) ? "STR" : stat.ToString(), result); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); } client.Disconnect(); return 1; } } } if (valid) { character.Strength = (byte)stats[0]; character.Constitution = (byte)stats[1]; character.Dexterity = (byte)stats[2]; character.Quickness = (byte)stats[3]; character.Intelligence = (byte)stats[4]; character.Piety = (byte)stats[5]; character.Empathy = (byte)stats[6]; character.Charisma = (byte)stats[7]; DOLCharacters[] chars = client.Account.Characters; for (int z = 0; z < chars.Length; z++) { if (chars[z].Name != character.Name) continue; //Log.Error(string.Format("found activePlayer:[{0}] {1} {2}", client.ActiveCharIndex, client.Player.Name, character.Name)); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} updated in cache!\n", charName)); if (client.Player != null) { client.Player.DBCharacter.Strength = (byte)stats[0]; client.Player.DBCharacter.Constitution = (byte)stats[1]; client.Player.DBCharacter.Dexterity = (byte)stats[2]; client.Player.DBCharacter.Quickness = (byte)stats[3]; client.Player.DBCharacter.Intelligence = (byte)stats[4]; client.Player.DBCharacter.Piety = (byte)stats[5]; client.Player.DBCharacter.Empathy = (byte)stats[6]; client.Player.DBCharacter.Charisma = (byte)stats[7]; } client.Account.Characters[z].Strength = (byte)stats[0]; client.Account.Characters[z].Constitution = (byte)stats[1]; client.Account.Characters[z].Dexterity = (byte)stats[2]; client.Account.Characters[z].Quickness = (byte)stats[3]; client.Account.Characters[z].Intelligence = (byte)stats[4]; client.Account.Characters[z].Piety = (byte)stats[5]; client.Account.Characters[z].Empathy = (byte)stats[6]; client.Account.Characters[z].Charisma = (byte)stats[7]; } } } else { if (log.IsErrorEnabled) log.Error("No CharacterClass with ID " + character.Class + " found"); } } } else { packet.Skip(58); // skip all other things if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } } if (customizationMode == 2) // change player customization { if (client.Account.PrivLevel == 1 && ((newModel >> 11) & 3) == 0) // Player size must be > 0 (from 1 to 3) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban Hack char update : zero character size in model:{0}", newModel); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); client.Disconnect(); return 1; } if ((ushort)newModel != character.CreationModel) { character.CurrentModel = newModel; } character.CustomisationStep = 2; // disable config button GameServer.Database.SaveObject(character); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} face proprieties configured by account {1}!\n", charName, client.Account.Name)); } else if (customizationMode == 3) //auto config -- seems someone thinks this is not possible? { character.CustomisationStep = 3; // enable config button to player GameServer.Database.SaveObject(character); //if (log.IsInfoEnabled) // log.Info(String.Format("Character {0} face proprieties auto updated!\n", charName)); } else if (customizationMode == 1 && flagChangedStats) //changed stat only for 1.89+ { GameServer.Database.SaveObject(character); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} stat updated!\n", charName)); } } return 1; }
private void CreateCharacter(GameClient client, GSPacketIn packet, string charName, int accountSlot) { Account account = client.Account; DOLCharacters ch = new DOLCharacters(); ch.AccountName = account.Name; ch.Name = charName; if (packet.ReadByte() == 0x01) { ch.EyeSize = (byte)packet.ReadByte(); ch.LipSize = (byte)packet.ReadByte(); ch.EyeColor = (byte)packet.ReadByte(); ch.HairColor = (byte)packet.ReadByte(); ch.FaceType = (byte)packet.ReadByte(); ch.HairStyle = (byte)packet.ReadByte(); packet.Skip(3); ch.MoodType = (byte)packet.ReadByte(); ch.CustomisationStep = 2; // disable config button packet.Skip(13); log.Debug("Disable Config Button"); } else { packet.Skip(23); } packet.Skip(24); //Location String ch.LastName = ""; ch.GuildID = ""; packet.Skip(24); //Skip class name packet.Skip(24); //Skip race name ch.Level = packet.ReadByte(); //not safe! ch.Level = 1; ch.Class = packet.ReadByte(); if (ServerProperties.Properties.START_AS_BASE_CLASS) { ch.Class = RevertClass(ch); } ch.Realm = packet.ReadByte(); if (log.IsDebugEnabled) log.Debug("Creation " + client.Version + " character, class:" + ch.Class + ", realm:" + ch.Realm); // Is class disabled ? int occurences = 0; List<string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true); occurences = (from j in disabled_classes where j == ch.Class.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { log.Debug("Client " + client.Account.Name + " tried to create a disabled classe: " + (eCharacterClass)ch.Class); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } if (client.Version >= GameClient.eClientVersion.Version193) { ValidateCharacter.init_post193_tables(); } else { ValidateCharacter.init_pre193_tables(); } if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class)) { log.Error(client.Account.Name + " tried to create a character with wrong class ID: " + ch.Class + ", realm:" + ch.Realm); if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); client.Disconnect(); } return; } ch.AccountSlot = accountSlot + ch.Realm * 100; //The following byte contains //1bit=start location ... in ShroudedIsles you can choose ... //1bit=first race bit //1bit=unknown //1bit=gender (0=male, 1=female) //4bit=race byte startRaceGender = (byte)packet.ReadByte(); ch.Race = (startRaceGender & 0x0F) + ((startRaceGender & 0x40) >> 2); List<string> disabled_races = new List<string>(Properties.DISABLED_RACES.SplitCSV(true)); occurences = (from j in disabled_races where j == ch.Race.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { log.Debug("Client " + client.Account.Name + " tried to create a disabled race: " + (eRace)ch.Race); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } ch.Gender = ((startRaceGender >> 4) & 0x01); bool siStartLocation = ((startRaceGender >> 7) != 0); ch.CreationModel = packet.ReadShortLowEndian(); ch.CurrentModel = ch.CreationModel; ch.Region = packet.ReadByte(); packet.Skip(1); //TODO second byte of region unused currently packet.Skip(4); //TODO Unknown Int / last used? ch.Strength = (byte)packet.ReadByte(); ch.Dexterity = (byte)packet.ReadByte(); ch.Constitution = (byte)packet.ReadByte(); ch.Quickness = (byte)packet.ReadByte(); ch.Intelligence = (byte)packet.ReadByte(); ch.Piety = (byte)packet.ReadByte(); ch.Empathy = (byte)packet.ReadByte(); ch.Charisma = (byte)packet.ReadByte(); packet.Skip(44); //TODO equipment if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } // log.DebugFormat("STR {0}, CON {1}, DEX {2}, QUI {3}, INT {4}, PIE {5}, EMP {6}, CHA {7}", ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma); // check if client tried to create invalid char if (!ValidateCharacter.IsCharacterValid(ch)) { if (log.IsWarnEnabled) { log.Warn(ch.AccountName + " tried to create invalid character:" + "\nchar name=" + ch.Name + ", gender=" + ch.Gender + ", race=" + ch.Race + ", realm=" + ch.Realm + ", class=" + ch.Class + ", region=" + ch.Region + "\nstr=" + ch.Strength + ", con=" + ch.Constitution + ", dex=" + ch.Dexterity + ", qui=" + ch.Quickness + ", int=" + ch.Intelligence + ", pie=" + ch.Piety + ", emp=" + ch.Empathy + ", chr=" + ch.Charisma); } // This is not live like but unfortunately we are missing code / packet support to stay on character create screen if something is invalid client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } ch.CreationDate = DateTime.Now; ch.Endurance = 100; ch.MaxEndurance = 100; ch.Concentration = 100; ch.MaxSpeed = GamePlayer.PLAYER_BASE_SPEED; #region Starting Locations //if the server property for disable tutorial is set, we load in the classic starting locations if (ch.Region == 27 && ServerProperties.Properties.DISABLE_TUTORIAL) { switch (ch.Realm) { case 1: ch.Region = 1; break; case 2: ch.Region = 100; break; case 3: ch.Region = 200; break; } } ch.Xpos = 505603; ch.Ypos = 494709; ch.Zpos = 2463; ch.Direction = 5947; if (ch.Region == 51 && ch.Realm == 1)//Albion ShroudedIsles start point (I hope) { ch.Xpos = 526252; ch.Ypos = 542415; ch.Zpos = 3165; ch.Direction = 5286; } if (ch.Region != 51 && ch.Realm == 1)//Albion start point (Church outside Camelot/humberton) { ch.Xpos = 505603; ch.Ypos = 494709; ch.Zpos = 2463; ch.Direction = 5947; //ch.Region = 1; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } if (ch.Region == 151 && ch.Realm == 2)//Midgard ShroudedIsles start point { ch.Xpos = 293720; ch.Ypos = 356408; ch.Zpos = 3488; ch.Direction = 6670; } if (ch.Region != 151 && ch.Realm == 2)//Midgard start point (Fort Atla) { ch.Xpos = 749103; ch.Ypos = 815835; ch.Zpos = 4408; ch.Direction = 7915; //ch.Region = 100; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } if (ch.Region == 181 && ch.Realm == 3)//Hibernia ShroudedIsles start point { ch.Xpos = 426483; ch.Ypos = 440626; ch.Zpos = 5952; ch.Direction = 2403; } if (ch.Region != 181 && ch.Realm == 3)//Hibernia start point (Mag Mel) { ch.Xpos = 345900; ch.Ypos = 490867; ch.Zpos = 5200; ch.Direction = 4826; //ch.Region = 200; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } // chars are bound on creation ch.BindRegion = ch.Region; ch.BindHeading = ch.Direction; ch.BindXpos = ch.Xpos; ch.BindYpos = ch.Ypos; ch.BindZpos = ch.Zpos; #endregion Starting Locations #region starting guilds if (account.PrivLevel == 1 && Properties.STARTING_GUILD) { switch (ch.Realm) { case 1: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Clan Cotswold"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Klan Cotswold"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Clan Cotswold"); break; } break; case 2: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Mularn Protectors"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Beschützer von Mularn"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Mularn Protectors"); break; } break; case 3: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog Adventurers"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog-Abenteurer"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog Adventurers"); break; } break; default: break; } if (ch.GuildID != "") ch.GuildRank = 8; } #endregion starting guilds if (Properties.STARTING_BPS > 0) ch.BountyPoints = Properties.STARTING_BPS; if (Properties.STARTING_MONEY > 0) { long value = Properties.STARTING_MONEY; ch.Copper = Money.GetCopper(value); ch.Silver = Money.GetSilver(value); ch.Gold = Money.GetGold(value); ch.Platinum = Money.GetPlatinum(value); } if (Properties.STARTING_REALM_LEVEL > 0) { int realmLevel = Properties.STARTING_REALM_LEVEL; long rpamount = 0; if (realmLevel < GamePlayer.REALMPOINTS_FOR_LEVEL.Length) rpamount = GamePlayer.REALMPOINTS_FOR_LEVEL[realmLevel]; // thanks to Linulo from http://daoc.foren.4players.de/viewtopic.php?t=40839&postdays=0&postorder=asc&start=0 if (rpamount == 0) rpamount = (long)(25.0 / 3.0 * (realmLevel * realmLevel * realmLevel) - 25.0 / 2.0 * (realmLevel * realmLevel) + 25.0 / 6.0 * realmLevel); ch.RealmPoints = rpamount; ch.RealmLevel = realmLevel; ch.RealmSpecialtyPoints = realmLevel; } ch.RespecAmountRealmSkill += 2; SetBasicCraftingForNewCharacter(ch); //Save the character in the database GameServer.Database.AddObject(ch); //Fire the character creation event GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client)); //add equipment StartupEquipment.AddEquipment(ch); //write changes GameServer.Database.SaveObject(ch); // Log creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", charName); client.Account.Characters = null; if (log.IsInfoEnabled) log.Info(String.Format("Character {0} created!", charName)); GameServer.Database.FillObjectRelations(client.Account); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; }
public void HandlePacket(GameClient client, GSPacketIn packet) { ushort id = client.Version >= GameClient.eClientVersion.Version1126 ? packet.ReadShortLowEndian() : packet.ReadShort(); GameClient target = WorldMgr.GetClientFromID(id); if (target == null) { if (Log.IsWarnEnabled) { Log.Warn($"Client {client.SessionID}:{client.TcpEndpointAddress} account {(client.Account == null ? "null" : client.Account.Name)} requested invalid client {id} --- disconnecting"); } client.Disconnect(); return; } // DOLConsole.WriteLine("player creation request "+target.Player.Name); if (target.IsPlaying && target.Player != null && target.Player.ObjectState == GameObject.eObjectState.Active) { client.Out.SendPlayerCreate(target.Player); client.Out.SendLivingEquipmentUpdate(target.Player); } }