Skip to content

Commit

Permalink
Merge pull request #662 from RyanYappert/feat/auto-kick-on-login
Browse files Browse the repository at this point in the history
Feat: Auto Kick on login
  • Loading branch information
RyanYappert authored Dec 20, 2024
2 parents b7b2401 + fa92b01 commit 4ae8eed
Show file tree
Hide file tree
Showing 23 changed files with 255 additions and 192 deletions.
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.GameServer/Characters/CharacterManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Character SelectCharacter(uint characterId, DbConnection? connectionIn =

character.EpitaphRoadState.UnlockedContent = _Server.Database.GetEpitaphRoadUnlocks(character.CharacterId, connectionIn);

if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards.Value)
if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards)
{
character.EpitaphRoadState.WeeklyRewardsClaimed = _Server.Database.GetEpitaphClaimedWeeklyRewards(character.CharacterId, connectionIn);
}
Expand Down
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.GameServer/Characters/ClanManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ public PacketQueue CompleteClanQuest(Quest quest, GameClient client)
{
ClanQuestClearCount[characterId][quest.QuestScheduleId] = ClanQuestClearCount[characterId].GetValueOrDefault(quest.QuestScheduleId) + 1;

Server.RpcManager.AnnounceOthers("internal/tracking", RpcInternalCommand.NotifyClanQuestCompletion, new RpcQuestCompletionData()
Server.RpcManager.AnnounceOthers("internal/command", RpcInternalCommand.NotifyClanQuestCompletion, new RpcQuestCompletionData()
{
CharacterId = characterId,
QuestStatus = ClanQuestClearCount[characterId]
Expand Down
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.GameServer/Characters/EpitaphRoadManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1290,7 +1290,7 @@ public List<InstancedGatheringItem> RollGatheringLoot(GameClient client, Charact
{
results.AddRange(RollWeeklyChestReward(dungeonInfo, reward));

if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards.Value)
if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards)
{
character.EpitaphRoadState.WeeklyRewardsClaimed.Add(reward.EpitaphId);
_Server.Database.InsertEpitaphWeeklyReward(character.CharacterId, reward.EpitaphId);
Expand Down
7 changes: 3 additions & 4 deletions Arrowgene.Ddon.GameServer/Characters/ExpManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Drawing;
using System.Linq;

namespace Arrowgene.Ddon.GameServer.Characters
Expand Down Expand Up @@ -906,13 +905,13 @@ public uint GetScaledPointAmount(RewardSource source, ExpType type, uint amount)
switch (type)
{
case ExpType.ExperiencePoints:
modifier = (source == RewardSource.Enemy) ? _GameSettings.EnemyExpModifier.Value : _GameSettings.QuestExpModifier.Value;
modifier = (source == RewardSource.Enemy) ? _GameSettings.EnemyExpModifier : _GameSettings.QuestExpModifier;
break;
case ExpType.JobPoints:
modifier = _GameSettings.JpModifier.Value;
modifier = _GameSettings.JpModifier;
break;
case ExpType.PlayPoints:
modifier = _GameSettings.PpModifier.Value;
modifier = _GameSettings.PpModifier;
break;
default:
modifier = 1.0;
Expand Down
8 changes: 3 additions & 5 deletions Arrowgene.Ddon.GameServer/Characters/RewardManager.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.GameServer.Quests;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Model.Quest;
using Arrowgene.Logging;
using System.Collections.Generic;
using Arrowgene.Ddon.Shared.Model.Quest;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Database.Model;
using System.Data.Common;

namespace Arrowgene.Ddon.GameServer.Characters
Expand All @@ -24,7 +22,7 @@ public bool AddQuestRewards(GameClient client, Quest quest, DbConnection? connec
var rewards = quest.GenerateBoxRewards();

var currentRewards = GetQuestBoxRewards(client, connectionIn);
if (currentRewards.Count >= _Server.Setting.GameLogicSetting.RewardBoxMax.Value)
if (currentRewards.Count >= _Server.Setting.GameLogicSetting.RewardBoxMax)
{
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions Arrowgene.Ddon.GameServer/Characters/WalletManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ public uint GetScaledWalletAmount(WalletType type, uint amount)
switch (type)
{
case WalletType.Gold:
modifier = Server.Setting.GameLogicSetting.GoldModifier.Value;
modifier = Server.Setting.GameLogicSetting.GoldModifier;
break;
case WalletType.RiftPoints:
modifier = Server.Setting.GameLogicSetting.RiftModifier.Value;
modifier = Server.Setting.GameLogicSetting.RiftModifier;
break;
case WalletType.BloodOrbs:
modifier = Server.Setting.GameLogicSetting.BoModifier.Value;
modifier = Server.Setting.GameLogicSetting.BoModifier;
break;
case WalletType.HighOrbs:
modifier = Server.Setting.GameLogicSetting.HoModifier.Value;
modifier = Server.Setting.GameLogicSetting.HoModifier;
break;
default:
modifier = 1.0;
Expand Down
27 changes: 19 additions & 8 deletions Arrowgene.Ddon.GameServer/GameServerSetting.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Runtime.Serialization;
using System.Runtime.Serialization;
using Arrowgene.Ddon.Server;

namespace Arrowgene.Ddon.GameServer
Expand All @@ -11,13 +11,7 @@ public class GameServerSetting

public GameServerSetting()
{
ServerSetting = new ServerSetting();
ServerSetting.Id = 10;
ServerSetting.Name = "Game";
ServerSetting.ServerPort = 52000;
ServerSetting.ServerSocketSettings.Identity = "Game";

GameLogicSetting = new GameLogicSetting();
SetDefaultValues();
}

public GameServerSetting(GameServerSetting setting)
Expand All @@ -41,5 +35,22 @@ void OnDeserialized(StreamingContext context)

GameLogicSetting ??= new GameLogicSetting();
}

[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
SetDefaultValues();
}

void SetDefaultValues()
{
ServerSetting = new ServerSetting();
ServerSetting.Id = 10;
ServerSetting.Name = "Game";
ServerSetting.ServerPort = 52000;
ServerSetting.ServerSocketSettings.Identity = "Game";

GameLogicSetting = new GameLogicSetting();
}
}
}
4 changes: 2 additions & 2 deletions Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public override S2CInstanceEnemyKillRes Handle(GameClient client, C2SInstanceEne
if (enemyKilled.BloodOrbs > 0)
{
// Drop BO
uint gainedBo = (uint) (enemyKilled.BloodOrbs * _gameServer.Setting.GameLogicSetting.BoModifier.Value);
uint gainedBo = (uint) (enemyKilled.BloodOrbs * _gameServer.Setting.GameLogicSetting.BoModifier);
uint bonusBo = (uint) (gainedBo * _gameServer.GpCourseManager.EnemyBloodOrbBonus());
CDataUpdateWalletPoint boUpdateWalletPoint = _gameServer.WalletManager.AddToWallet(memberClient.Character, WalletType.BloodOrbs, gainedBo + bonusBo, bonusBo, connectionIn: connectionIn);
updateCharacterItemNtc.UpdateWalletList.Add(boUpdateWalletPoint);
Expand All @@ -218,7 +218,7 @@ public override S2CInstanceEnemyKillRes Handle(GameClient client, C2SInstanceEne
if (enemyKilled.HighOrbs > 0)
{
// Drop HO
uint gainedHo = (uint)(enemyKilled.HighOrbs * _gameServer.Setting.GameLogicSetting.HoModifier.Value);
uint gainedHo = (uint)(enemyKilled.HighOrbs * _gameServer.Setting.GameLogicSetting.HoModifier);
CDataUpdateWalletPoint hoUpdateWalletPoint = _gameServer.WalletManager.AddToWallet(memberClient.Character, WalletType.HighOrbs, gainedHo, connectionIn: connectionIn);
updateCharacterItemNtc.UpdateWalletList.Add(hoUpdateWalletPoint);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.GameServer.Dump;
using Arrowgene.Ddon.GameServer.Quests;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Entity;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
Expand Down Expand Up @@ -36,8 +35,8 @@ public override S2CQuestGetCycleContentsStateListRes Handle(GameClient client, C
ntc.WorldManageQuestOrderList = pcap.WorldManageQuestOrderList; // Recover paths + change vocation

ntc.QuestDefine = pcap.QuestDefine; // Recover quest log data to be able to accept quests
ntc.QuestDefine.OrderMaxNum = Server.Setting.GameLogicSetting.QuestOrderMax.Value;
ntc.QuestDefine.RewardBoxMaxNum = Server.Setting.GameLogicSetting.RewardBoxMax.Value;
ntc.QuestDefine.OrderMaxNum = Server.Setting.GameLogicSetting.QuestOrderMax;
ntc.QuestDefine.RewardBoxMaxNum = Server.Setting.GameLogicSetting.RewardBoxMax;

// pcap.MainQuestIdList; (this will add back all missing functionality which depends on complete MSQ)
var completedMsq = client.Character.CompletedQuests.Values.Where(x => x.QuestType == QuestType.Main);
Expand Down
56 changes: 1 addition & 55 deletions Arrowgene.Ddon.GameServer/RpcManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
using Arrowgene.Logging;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Claims;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace Arrowgene.Ddon.GameServer
Expand Down Expand Up @@ -60,52 +57,6 @@ public bool Update(DateTime newTimestamp, List<RpcCharacterData> characterData)

private readonly Dictionary<ushort, RpcTrackingMap> CharacterTrackingMap;

public class RpcWrappedObject
{
public RpcInternalCommand Command { get; set; }
public ushort Origin { get; set; }
public object Data { get; set; }
public DateTime Timestamp { get; set; }
public RpcWrappedObject()
{
Timestamp = DateTime.UtcNow;
}
}

public class RpcUnwrappedObject
{
public RpcInternalCommand Command { get; set; }
public ushort Origin { get; set; }
public DateTime Timestamp { get; set; }

[JsonConverter(typeof(DataJsonConverter))]
public string Data { get; set; }
public T GetData<T>()
{
return JsonSerializer.Deserialize<T>(Data);
}

// Hack to deserialize nested objects.
internal class DataJsonConverter : JsonConverter<string>
{
public override string Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
return jsonDoc.RootElement.GetRawText();
}
}

public override void Write(
Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}


public RpcManager(DdonGameServer server)
{
Server = server;
Expand Down Expand Up @@ -296,7 +247,7 @@ public void AnnouncePlayerList(Character exception = null)
rpcCharacterDatas.Add(new(character));
}
Logger.Info($"Announcing player list for channel {Server.Id} with {rpcCharacterDatas.Count} players over RPC.");
AnnounceOthers("internal/tracking", RpcInternalCommand.NotifyPlayerList, rpcCharacterDatas);
AnnounceOthers("internal/command", RpcInternalCommand.NotifyPlayerList, rpcCharacterDatas);
CharacterTrackingMap[(ushort) Server.Id].Update(DateTime.Now, rpcCharacterDatas);
}

Expand Down Expand Up @@ -419,10 +370,5 @@ public void AnnounceClanPacket<T>(uint clanId, T packet, uint characterId = 0)
AnnounceClan(clanId, "internal/packet", RpcInternalCommand.AnnouncePacketClan, data);
}
}

public void AnnounceEpitaphWeeklyReset()
{
AnnounceAll("internal/packet", RpcInternalCommand.EpitaphRoadWeeklyReset, null);
}
}
}
6 changes: 2 additions & 4 deletions Arrowgene.Ddon.GameServer/Tasks/EpitaphSchedulerTask.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Model.Rpc;
using Arrowgene.Ddon.Shared.Model.Scheduler;
using Arrowgene.Logging;
Expand All @@ -18,15 +17,14 @@ public EpitaphSchedulerTask(DayOfWeek day, uint hour, uint minute) : base(TaskTy

public override bool IsEnabled(DdonGameServer server)
{
return server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards.Value;
return server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards;
}

public override void RunTask(DdonGameServer server)
{
Logger.Info("Performing weekly epitaph reset");
server.Database.DeleteWeeklyEpitaphClaimedRewards();

server.RpcManager.AnnounceEpitaphWeeklyReset();
server.RpcManager.AnnounceAll("internal/packet", RpcInternalCommand.EpitaphRoadWeeklyReset, null);
}
}
}
78 changes: 72 additions & 6 deletions Arrowgene.Ddon.LoginServer/Handler/ClientLoginHandler.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using Arrowgene.Ddon.Database.Model;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Model.Rpc;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading;

namespace Arrowgene.Ddon.LoginServer.Handler
{
Expand All @@ -17,6 +22,9 @@ public class ClientLoginHandler : LoginStructurePacketHandler<C2LLoginReq>
private readonly object _tokensInFLightLock;
private readonly HashSet<string> _tokensInFlight;

private readonly HttpClient _httpClient = new HttpClient();
private bool _httpReady = false;

public ClientLoginHandler(DdonLoginServer server) : base(server)
{
_setting = server.Setting;
Expand Down Expand Up @@ -101,14 +109,32 @@ public override void Handle(LoginClient client, StructurePacket<C2LLoginReq> pac
}

List<Connection> connections = Database.SelectConnectionsByAccountId(account.Id);
if (connections.Count > 0)

if (_setting.KickOnMultipleLogin)
{
for (uint tryCount = 0; tryCount < _setting.KickOnMultipleLoginTries; tryCount++)
{
if (connections.Any())
{
connections.ForEach(x => RequestKick(x));
Thread.Sleep(_setting.KickOnMultipleLoginTimer);
connections = Database.SelectConnectionsByAccountId(account.Id);
}
else
{
break;
}
}
}

if (connections.Any())
{
Logger.Error(client, $"Already logged in");
res.Error = (uint) ErrorCode.ERROR_CODE_AUTH_MULTIPLE_LOGIN;
Logger.Error(client, $"Already logged in.");
res.Error = (uint)ErrorCode.ERROR_CODE_AUTH_MULTIPLE_LOGIN;
client.Send(res);
return;
}

// Order Important,
// account need to be only assigned after
// verification that no connection exists, and before
Expand Down Expand Up @@ -172,5 +198,45 @@ private bool LockToken(string token)
return true;
}
}

private void RequestKick(Connection connection)
{
// Timing issues with loading files vs server process startup.
if (!_httpReady)
{
lock(_httpClient)
{
ServerInfo serverInfo = Server.AssetRepository.ServerList.Find(x => x.LoginId == Server.Id);
if (serverInfo is null)
{
Logger.Error($"Login server with ID {Server.Id} was not found in the ServerList asset.");
return;
}

// The login server auths as though it was the game server.
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Internal", $"{serverInfo.Id}:{serverInfo.RpcAuthToken}");
_httpReady = true;
}
}

if (connection.Type == ConnectionType.LoginServer)
{
// Can't talk to the login server, but there's usually not a stuck connection here.
return;
}

var channel = Server.AssetRepository.ServerList.Find(x => x.Id == connection.ServerId);
var route = $"http://{channel.Addr}:{channel.RpcPort}/rpc/internal/command";

var wrappedObject = new RpcWrappedObject()
{
Command = RpcInternalCommand.KickInternal,
Origin = (ushort)Server.Id,
Data = connection.AccountId
};

var json = JsonSerializer.Serialize(wrappedObject);
_ = _httpClient.PostAsync(route, new StringContent(json));
}
}
}
Loading

0 comments on commit 4ae8eed

Please sign in to comment.