refactor(castle-siege): drive the cycle on the client's state numbers and persist guilds by id
Moves AdaMu's working Castle Siege onto the upstream data model that the previous commit introduced, without changing how the siege plays. State model - CastleSiegePhase is replaced by DataModel's CastleSiegeState, whose values are exactly what the game client's CASTLESIEGE_STATE enum expects. The cycle now runs Idle1(0) -> RegisterGuild(1) -> Ready(6) -> Start(7) -> End(8) -> EndCycle(9) -> Idle1(0). - Idle2(2), RegisterMark(3), Idle3(4) and Notify(5) keep their numbers for client compatibility but are never entered: AdaMu registers guilds directly and has no Mark of Lord step. Guild identity - Guilds are now identified by their persistent Guid instead of by name, so a rename (or a delete and re-create under the same name) can no longer hand castle ownership to the wrong guild. Names are carried alongside only for display and for the packets that send a name to the client. - Interfaces.Guild deliberately has no id and the guild server's short ids are in-memory only, so the persistent id is resolved through the guild name once and cached per process. This avoids adding a method to IGuildServer, which upstream keeps changing. Persistence - The castle owner is stored in the CastleSiegeData row and the registrations in CastleSiegeGuildRegistration rows, replacing the previous plugin-configuration JSON blob. Only the current state and when it started still ride on the plugin configuration, because they have no column in the upstream schema. Castle NPCs - The hard-coded gate, catapult, crown and switch coordinates are gone. They are read from GameConfiguration.CastleSiegeConfiguration, seeded by CastleSiegeInitializer. Definitions flagged IsPersistedToDatabase are the breakable defenses and count towards the throne, which additionally brings in the 4 guardian statues the previous implementation did not spawn. - The crown hold time now comes from the seeded configuration instead of the plugin settings. The AdaMu operational settings (cycle durations, registration fee, designated server id, auto-open schedule) moved to a renamed CastleSiegeSettings class, so they no longer collide with upstream's CastleSiegeConfiguration entity. Verified: full server build succeeds with 0 errors. Not yet done: the 0xB2 0x00 CastleSiegeState request handler, and the docker / local run.
This commit is contained in:
@@ -49,7 +49,7 @@ public class CastleSiegeGuardsmanTalkPlugIn : IPlayerTalkToNpcPlugIn
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.Phase != CastleSiegePhase.Registration)
|
||||
if (context.State != CastleSiegeState.RegisterGuild)
|
||||
{
|
||||
await ShowAsync(player, "Castle Siege registration is not open right now.").ConfigureAwait(false);
|
||||
return;
|
||||
@@ -61,17 +61,15 @@ public class CastleSiegeGuardsmanTalkPlugIn : IPlayerTalkToNpcPlugIn
|
||||
return;
|
||||
}
|
||||
|
||||
var guildName = guildStatus.GuildId.ToString();
|
||||
if (player.GameContext is IGameServerContext serverContext)
|
||||
// Registrations are keyed on the guild's persistent id, so a later rename cannot detach them.
|
||||
if (await CastleSiegeEventPlugIn.GetPersistentGuildAsync(player).ConfigureAwait(false) is not { } guild)
|
||||
{
|
||||
var guild = await serverContext.GuildServer.GetGuildAsync(guildStatus.GuildId).ConfigureAwait(false);
|
||||
if (guild?.Name is { Length: > 0 } name)
|
||||
{
|
||||
guildName = name;
|
||||
}
|
||||
await ShowAsync(player, "Your guild could not be resolved. Please try again in a moment.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.RegisteredGuilds.Contains(guildName))
|
||||
var guildName = guild.Name;
|
||||
if (context.IsRegistered(guild.Id))
|
||||
{
|
||||
await ShowAsync(player, $"Your guild '{guildName}' is already registered for the Castle Siege.").ConfigureAwait(false);
|
||||
return;
|
||||
@@ -84,7 +82,7 @@ public class CastleSiegeGuardsmanTalkPlugIn : IPlayerTalkToNpcPlugIn
|
||||
return;
|
||||
}
|
||||
|
||||
context.RegisterGuild(guildName);
|
||||
context.RegisterGuild(guild.Id, guildName);
|
||||
await ShowAsync(player, fee > 0
|
||||
? $"Your guild '{guildName}' is registered for the Castle Siege. ({fee} zen paid)"
|
||||
: $"Your guild '{guildName}' is registered for the Castle Siege.").ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user