Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement a generic task scheduler #653

Merged
merged 4 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Arrowgene.Ddon.Database/Arrowgene.Ddon.Database.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@
<None Update="Files\Database\Script\migration_epitaph_road.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Files\Database\Script\migration_scheduling.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.Database/DdonDatabaseBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class DdonDatabaseBuilder
private static readonly ILogger Logger = LogProvider.Logger<Logger>(typeof(DdonDatabaseBuilder));
private const string DefaultSchemaFile = "Script/schema_sqlite.sql";

public const uint Version = 26;
public const uint Version = 27;

public static IDatabase Build(DatabaseSetting settings)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE ddon_schedule_next (
"type" INTEGER NOT NULL,
"timestamp" BIGINT NOT NULL,
PRIMARY KEY("type")
);

INSERT INTO ddon_schedule_next(type, timestamp) VALUES (19, 0);
Original file line number Diff line number Diff line change
Expand Up @@ -782,3 +782,11 @@ CREATE TABLE IF NOT EXISTS ddon_epitaph_claimed_weekly_rewards (
CONSTRAINT "pk_ddon_epitaph_claimed_weekly_rewards" PRIMARY KEY ("character_id", "epitaph_id"),
CONSTRAINT "fk_ddon_epitaph_claimed_weekly_rewards_character_id" FOREIGN KEY ("character_id") REFERENCES "ddon_character"("character_id") ON DELETE CASCADE
);


CREATE TABLE IF NOT EXISTS ddon_schedule_next (
"type" INTEGER NOT NULL,
"timestamp" BIGINT NOT NULL,
PRIMARY KEY("type")
);
INSERT INTO ddon_schedule_next(type, timestamp) VALUES (19, 0);
7 changes: 6 additions & 1 deletion Arrowgene.Ddon.Database/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Arrowgene.Ddon.Shared.Model.BattleContent;
using Arrowgene.Ddon.Shared.Model.Clan;
using Arrowgene.Ddon.Shared.Model.Quest;
using Arrowgene.Ddon.Shared.Model.Scheduler;

namespace Arrowgene.Ddon.Database
{
Expand Down Expand Up @@ -590,6 +591,10 @@ bool InsertBBMContentTreasure(

bool InsertEpitaphWeeklyReward(uint characterId, uint epitaphId, DbConnection? connectionIn = null);
HashSet<uint> GetEpitaphClaimedWeeklyRewards(uint characterId, DbConnection? connectionIn = null);
void DeleteWeeklyRewards(DbConnection? connectionIn = null);
void DeleteWeeklyEpitaphClaimedRewards(DbConnection? connectionIn = null);

// Scheduler
Dictionary<TaskType, SchedulerTaskEntry> SelectAllTaskEntries();
bool UpdateScheduleInfo(TaskType type, long timestamp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public HashSet<uint> GetEpitaphClaimedWeeklyRewards(uint characterId, DbConnecti
return results;
}

public void DeleteWeeklyRewards(DbConnection? connectionIn = null)
public void DeleteWeeklyEpitaphClaimedRewards(DbConnection? connectionIn = null)
{
ExecuteQuerySafe(connectionIn, (connection) =>
{
Expand Down
49 changes: 49 additions & 0 deletions Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbScheduleNext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Arrowgene.Ddon.Shared.Model.Scheduler;
using System.Collections.Generic;
using System.Data.Common;

namespace Arrowgene.Ddon.Database.Sql.Core
{
public abstract partial class DdonSqlDb<TCon, TCom, TReader> : SqlDb<TCon, TCom, TReader>
where TCon : DbConnection
where TCom : DbCommand
where TReader : DbDataReader
{
protected static readonly string[] ScheduleNextFields = new string[]
{
"type", "timestamp"
};

private static readonly string SqlUpdateScheduleNext = $"UPDATE \"ddon_schedule_next\" SET \"timestamp\"=@timestamp WHERE \"type\"=@type;";
private static readonly string SqlSelectScheduleNext = $"SELECT {BuildQueryField(ScheduleNextFields)} FROM \"ddon_schedule_next\";";


public Dictionary<TaskType, SchedulerTaskEntry> SelectAllTaskEntries()
{
Dictionary<TaskType, SchedulerTaskEntry> results = new Dictionary<TaskType, SchedulerTaskEntry>();
ExecuteReader(SqlSelectScheduleNext, command => { }, reader =>
{
while (reader.Read())
{
TaskType type = (TaskType) GetUInt32(reader, "type");
results[type] = new SchedulerTaskEntry()
{
Type = type,
Timestamp = GetInt64(reader, "timestamp")
};
}
});
return results;
}

public bool UpdateScheduleInfo(TaskType type, long timestamp)
{
return ExecuteNonQuery(SqlUpdateScheduleNext, command =>
{
AddParameter(command, "@type", (uint) type);
AddParameter(command, "@timestamp", timestamp);
}) == 1;
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Data.Common;

namespace Arrowgene.Ddon.Database.Sql.Core.Migration
{
public class TaskSchedulerMigration : IMigrationStrategy
{
public uint From => 26;
public uint To => 27;

private readonly DatabaseSetting DatabaseSetting;

public TaskSchedulerMigration(DatabaseSetting databaseSetting)
{
DatabaseSetting = databaseSetting;
}

public bool Migrate(IDatabase db, DbConnection conn)
{
string adaptedSchema = DdonDatabaseBuilder.GetAdaptedSchema(DatabaseSetting, "Script/migration_scheduling.sql");
db.Execute(conn, adaptedSchema);
return true;
}
}
}

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)
if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards.Value)
{
character.EpitaphRoadState.WeeklyRewardsClaimed = _Server.Database.GetEpitaphClaimedWeeklyRewards(character.CharacterId, connectionIn);
}
Expand Down
19 changes: 18 additions & 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)
if (_Server.Setting.GameLogicSetting.EnableEpitaphWeeklyRewards.Value)
{
character.EpitaphRoadState.WeeklyRewardsClaimed.Add(reward.EpitaphId);
_Server.Database.InsertEpitaphWeeklyReward(character.CharacterId, reward.EpitaphId);
Expand Down Expand Up @@ -1321,5 +1321,22 @@ public List<InstancedGatheringItem> RollGatheringLoot(GameClient client, Charact

return results;
}

/// <summary>
/// Called by the task manager. The main task will signal all channels
/// to flush the cached information queried by the player when first
/// logging in and send a notification to all players that the action
/// occurred.
/// </summary>
public void PerformWeeklyReset()
{
_Server.ChatManager.BroadcastMessage(LobbyChatMsgType.ManagementAlertN, "Epitaph Road Weekly Rewards Reset");

// Clear out cached data related to epitaph weekly rewards
foreach (var client in _Server.ClientLookup.GetAll())
{
client.Character.EpitaphRoadState.WeeklyRewardsClaimed.Clear();
}
}
}
}
20 changes: 13 additions & 7 deletions Arrowgene.Ddon.GameServer/Chat/ChatManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

Expand All @@ -14,11 +15,11 @@ public class ChatManager
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(ChatManager));

private readonly List<IChatHandler> _handler;
private readonly DdonGameServer _server;
private readonly DdonGameServer _Server;

public ChatManager(DdonGameServer server)
{
_server = server;
_Server = server;
_handler = new List<IChatHandler>();
}

Expand All @@ -42,7 +43,7 @@ public void SendMessage(string message, string firstName, string lastName, Lobby
response.PhrasesIndex = 0;
foreach (uint characterId in characterIds)
{
GameClient client = _server.ClientLookup.GetClientByCharacterId(characterId);
GameClient client = _Server.ClientLookup.GetClientByCharacterId(characterId);
if (client == null)
{
continue;
Expand Down Expand Up @@ -73,6 +74,11 @@ public void SendMessage(string message, string firstName, string lastName, Lobby
response.Recipients.AddRange(recipients);
Send(response);
}

public void BroadcastMessage(LobbyChatMsgType type, string message)
{
SendMessage(message, string.Empty, string.Empty, type, _Server.ClientLookup.GetAll());
}

public void SendTellMessage(GameClient sender, GameClient receiver, C2SChatSendTellMsgReq request)
{
Expand All @@ -89,7 +95,7 @@ public void SendTellMessage(GameClient sender, GameClient receiver, C2SChatSendT

public void SendTellMessageForeign(GameClient client, C2SChatSendTellMsgReq request)
{
_server.RpcManager.AnnounceTellChat(client, request);
_Server.RpcManager.AnnounceTellChat(client, request);

ChatResponse senderChatResponse = new ChatResponse
{
Expand Down Expand Up @@ -155,7 +161,7 @@ private void Deliver(GameClient client, ChatResponse response)
{
case LobbyChatMsgType.Say:
case LobbyChatMsgType.Shout:
response.Recipients.AddRange(_server.ClientLookup.GetAll());
response.Recipients.AddRange(_Server.ClientLookup.GetAll());
break;
case LobbyChatMsgType.Party:
PartyGroup party = client.Party;
Expand All @@ -171,13 +177,13 @@ private void Deliver(GameClient client, ChatResponse response)
break;
}

response.Recipients.AddRange(_server.ClientLookup.GetAll().Where(
response.Recipients.AddRange(_Server.ClientLookup.GetAll().Where(
x => x.Character != null
&& client.Character != null
&& x.Character.ClanId == client.Character.ClanId)
);

_server.RpcManager.AnnounceClanChat(client, response);
_Server.RpcManager.AnnounceClanChat(client, response);
break;
default:
response.Recipients.Add(client);
Expand Down
8 changes: 8 additions & 0 deletions Arrowgene.Ddon.GameServer/DdonGameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public DdonGameServer(GameServerSetting setting, IDatabase database, AssetReposi
ClanManager = new ClanManager(this);
RpcManager = new RpcManager(this);
EpitaphRoadManager = new EpitaphRoadManager(this);
ScheduleManager = new ScheduleManager(this);

// Orb Management is slightly complex and requires updating fields across multiple systems
OrbUnlockManager = new OrbUnlockManager(database, WalletManager, JobManager, CharacterManager);
Expand Down Expand Up @@ -115,6 +116,7 @@ public DdonGameServer(GameServerSetting setting, IDatabase database, AssetReposi
public ClanManager ClanManager { get; }
public RpcManager RpcManager { get; }
public EpitaphRoadManager EpitaphRoadManager { get; }
private ScheduleManager ScheduleManager { get; }

public ChatLogHandler ChatLogHandler { get; }

Expand All @@ -129,6 +131,12 @@ public override void Start()
{
QuestManager.LoadQuests(this);
GpCourseManager.EvaluateCourses();

if (ServerUtils.IsHeadServer(this))
{
ScheduleManager.StartServerTasks();
}

LoadChatHandler();
LoadPacketHandler();
base.Start();
Expand Down
12 changes: 12 additions & 0 deletions Arrowgene.Ddon.GameServer/RpcManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
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;
Expand Down Expand Up @@ -142,6 +144,11 @@ public List<CDataGameServerListInfo> ServerListInfo()
return ChannelInfo.Keys.Select(x => ServerListInfo(x)).ToList();
}

public ServerInfo HeadServer()
{
return ChannelInfo.Values.ToList().OrderBy(x => x.Id).ToList()[0];
}

public CDataGameServerListInfo ServerListInfo(ushort channelId)
{
var info = ChannelInfo[channelId].ToCDataGameServerListInfo();
Expand Down Expand Up @@ -412,5 +419,10 @@ 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);
}
}
}
Loading
Loading