Skip to content

Implement Guild Alliance System#737

Draft
Copilot wants to merge 6 commits intomasterfrom
copilot/implement-guild-alliance-system
Draft

Implement Guild Alliance System#737
Copilot wants to merge 6 commits intomasterfrom
copilot/implement-guild-alliance-system

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 24, 2026

Implements the foundational guild alliance and hostility system required as a prerequisite for Castle Siege. Multiple guilds can form an alliance under a master guild, with full CRUD lifecycle and transitive hostility support.

Core Server Logic

  • IGuildServer — Added 8 new methods: CreateAllianceAsync, RemoveAllianceGuildAsync, DisbandAllianceAsync, GetAllianceGuildsAsync, IsAllianceMasterAsync, GetAllianceMasterIdAsync, SetHostilityAsync, GetGuildRelationshipAsync. Added AllianceGuildEntry and GuildRelationship types.
  • GuildServer — Full implementation. Alliance master is identified by self-referencing AllianceGuild property. Max alliance size enforced via MaxAllianceSize = 5 constant. Transitive hostility: if any guild in Alliance A is hostile to any guild in Alliance B, all members across both alliances are considered rivals.
  • GuildPosition — Added AssistantMaster value for castle siege NPC management.

Publisher & Context

  • IGuildChangePublisher — Added AllianceCreatedAsync, AllianceGuildRemovedAsync, AllianceDisbandedAsync.
  • GameServerContext.ForEachAlliancePlayerAsync — Removed the TODO stub; now queries GuildServer.GetAllianceGuildsAsync to iterate online players across all guilds in the alliance.

Network Packets (Server→Client)

Three new server-to-client packets added to XML, generated structs, ref structs, and ConnectionExtensions:

Code Name Purpose
0xE5 GuildRelationshipRequest Forward alliance/hostility request to target guild master
0xE6 GuildRelationshipChangeResult Result of relationship change back to requester
0xE9 AllianceList List of guilds in the alliance

Game Logic & Handlers

  • GuildRelationshipChangeAction — Validates guild master status, routes join/leave/hostility requests. Alliance join uses a PendingAllianceRequest property on Player for the two-step request/response flow (mirroring the guild war pattern).
  • Packet handlersGuildRelationshipChangeHandlerPlugIn (C1 E5), GuildRelationshipChangeResponseHandlerPlugIn (C1 E6), AllianceListRequestHandlerPlugIn (C1 E9), AllianceGroupHandlerPlugIn + RemoveAllianceGuildHandlerPlugIn (C1 EB 01).
  • Remote view pluginsShowGuildRelationshipRequestPlugIn, ShowGuildRelationshipChangeResultPlugIn, ShowAllianceListPlugIn.

Dapr

Both GuildChangePublisher and ServerClients/GuildServer updated to implement the new interface methods.

Original prompt

This section details on the original issue you should resolve

<issue_title>Guild Alliance System</issue_title>
<issue_description>## Summary

Implement the Guild Alliance system, which allows multiple guilds to form an alliance under an alliance master guild. This is a prerequisite for Castle Siege, where entire alliances participate as a unit. The system also includes guild hostility (rival relationships).

Prerequisites

None — this is the foundational phase.

Background

OpenMU already has partial support for alliances:

  • Interfaces.Guild has AllianceGuild and Hostility navigation properties.
  • DataModel.Entities.Guild extends Interfaces.Guild with Members.
  • Alliance chat routes through IEventPublisher.AllianceMessageAsync.
  • IGameServerContext.ForEachAlliancePlayerAsync is declared but needs implementation.
  • Client→Server packet docs exist: C1-E6-GuildRelationshipChangeResponse, C1-E9-RequestAllianceList, C1-EB-01-RemoveAllianceGuildRequest.

What's missing is the actual server-side CRUD logic for alliances and the corresponding message handlers.

Requirements

1. IGuildServer Extensions (Interfaces/IGuildServer.cs)

Add these methods to the IGuildServer interface:

ValueTask<bool> CreateAllianceAsync(uint masterGuildId, uint targetGuildId);
ValueTask<bool> RemoveAllianceGuildAsync(uint masterGuildId, uint targetGuildId);
ValueTask<bool> DisbandAllianceAsync(uint masterGuildId);
ValueTask<IImmutableList<AllianceGuildEntry>> GetAllianceGuildsAsync(uint guildId);
ValueTask<bool> IsAllianceMasterAsync(uint guildId);
ValueTask<uint> GetAllianceMasterIdAsync(uint guildId);
ValueTask<bool> SetHostilityAsync(uint guildId, uint targetGuildId, bool create);
ValueTask<GuildRelationship> GetGuildRelationshipAsync(uint guild1, uint guild2);

Add supporting types:

public class AllianceGuildEntry
{
    public string GuildName { get; set; }
    public uint GuildId { get; set; }
}

public enum GuildRelationship : byte
{
    None = 0,
    Union = 1,
    Rival = 2,
}

2. GuildPosition Extension (Interfaces/GuildPosition.cs)

Add AssistantMaster value (needed for castle siege NPC management):

public enum GuildPosition : byte
{
    Undefined,
    NormalMember,
    GuildMaster,
    BattleMaster,
    AssistantMaster, // NEW
}

3. GuildServer Implementation (GuildServer/GuildServer.cs)

Implement the alliance CRUD methods:

  • CreateAllianceAsync: Set AllianceGuild on both guilds. The requesting guild becomes the alliance master (self-referencing AllianceGuild). The target guild's AllianceGuild is set to the master. Enforce configurable max alliance size (default 5). Both guild masters must agree (request/response flow similar to guild join).
  • RemoveAllianceGuildAsync: Only the alliance master can remove member guilds. Clear the removed guild's AllianceGuild.
  • DisbandAllianceAsync: Clear AllianceGuild on all member guilds.
  • GetAllianceGuildsAsync: Find all guilds in the _guildDictionary whose Guild.AllianceGuild matches the given guild's alliance master. Also query the database for offline alliance members.
  • IsAllianceMasterAsync: A guild is the alliance master when guild.AllianceGuild points to itself.
  • GetAllianceMasterIdAsync: Return the runtime uint ID of the alliance master guild.
  • SetHostilityAsync: Set or clear Guild.Hostility on the requesting guild.
  • GetGuildRelationshipAsync: Return Union if both guilds share the same AllianceGuild, Rival if hostility exists (transitively through alliances), None otherwise.

Hostility transitivity rule: If any guild in Alliance A has Hostility pointing to any guild in Alliance B, all members of both alliances are rivals.

4. IGuildChangePublisher Extensions (GuildServer/IGuildChangePublisher.cs)

Add methods to broadcast alliance changes to game servers:

ValueTask AllianceCreatedAsync(uint masterGuildId, uint memberGuildId);
ValueTask AllianceGuildRemovedAsync(uint masterGuildId, uint memberGuildId);
ValueTask AllianceDisbandedAsync(uint masterGuildId);

Implement in GuildChangeToGameServerPublisher.cs.

5. Player Action (GameLogic/PlayerActions/Guild/GuildRelationshipChangeAction.cs) — New file

Validates the request:

  • Player must be a guild master.
  • For alliance creation: target guild must exist, not already in an alliance, max size not exceeded.
  • For alliance removal: player must be the alliance master.
  • For hostility: target guild must exist.

Calls the appropriate IGuildServer method via IGameServerContext.GuildServer.

6. Message Handlers — New files in GameServer/MessageHandler/Guild/

Follow the pattern of existing handlers (e.g., GuildRequestHandlerPlugIn.cs):

  • GuildRelationshipChangeHandlerPlugIn: Handles C1-E5 (or the correct headcode for guild relationship requests). Parses the packet, calls `GuildRelationshipC...

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits March 24, 2026 23:18
Copilot AI changed the title [WIP] Implement guild alliance system for Castle Siege Implement Guild Alliance System Mar 24, 2026
Copilot AI requested a review from sven-n March 24, 2026 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guild Alliance System

2 participants