Skip to content

Automatic clan join (ad-hoc request from the UI Team)#772

Open
CapoMK25 wants to merge 3 commits intodevfrom
automatic-clan-join
Open

Automatic clan join (ad-hoc request from the UI Team)#772
CapoMK25 wants to merge 3 commits intodevfrom
automatic-clan-join

Conversation

@CapoMK25
Copy link
Collaborator

@CapoMK25 CapoMK25 commented Feb 5, 2026

Brief description

The UI-Team asked the server team on discord to explain that the automatic clan join when creating an account doesn't work if all clans are full. They asked for a new clan to be added (or multiple to be exact).

So this PR implements an automatic fallback to ensure every new player is onboarded into a clan immediately. Previously, new players would've remained clanless if all existing clans reached the 30-player limit.

Change list

  • Logic Implementation (JoinService)

  • Capacity Fallback: Added a secondary check within the player.created event listener. If no isOpen clans with room (playerCount < 30) are found, the system now triggers an automated clan creation.

  • Smart Naming: Implemented a dynamic naming convention: Expedition [TotalClans + 1]-[HHmm]. This prevents naming collisions and provides a sense of progression.

  • Infrastructure Reuse: Utilized createOneWithoutAdmin to ensure all standard clan side-effects (SoulHome initialization, default Roles, and Stock) are executed correctly.

  • DTO Compliance: Refactored the creation logic to use CreateClanDto, satisfying mandatory fields like phrase and labels without using as any type-casting.

  • Error Handling: Wrapped the creation process in a try-catch block with NestJS Logger integration. This ensures that if the auto-creation fails, it won't crash the player-creation lifecycle, while still leaving a trace for debugging later due to the logger.

  • Spec Update: Updated findClanForNewPlayer.test.ts. The test formerly asserting that a player remains clanless in a full world now asserts that an "AUTO" tagged clan is created and joined.

  • Regression Testing: Verified that all 1,153 tests pass, ensuring no regressions in the standard join or voting flows.

  • Manual Test: Verified on the local environment by setting all clans to playerCount: 30 manually.

  • Result: A new player was created, an Expedition clan was generated, and the player was successfully linked via clan_id.

Copy link
Member

@hoan301298 hoan301298 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your solution is quite good, only some extra-work might not be needed.

*/
@OnEvent('player.created')
async findClanForNewPlayer(playerId: string) {
const randomClan = await this.clanService.model
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function finds a random clan matching criteria.

.then((res) => res[0]);

if (!randomClan) return;
const availableClan = await this.clanService.model.findOne({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But your solution finds the first document by index order --> so technically, if 2 players are created and they will be all added to a clan including <29 players. It's better to add them randomly, so we all have some newbie distributed evenly across different teams.

const joinableClanCount = await this.clanService.model.countDocuments({
isOpen: true,
playerCount: { $lt: 30 }
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so much extra work, so the logic is if (availableClan) existed, let player join into it, else - create a new clan. Therefore, this function doesn't help and check blockif (joinableClanCount > 0) should be removed too

const totalClans = await this.clanService.model.countDocuments();
const now = new Date();
const suffix = `${now.getHours()}${now.getMinutes()}`;
const newClanName = `Expedition ${totalClans + 1}-${suffix}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to ask UI Team for the rule of naming random new clan - for example: "New Clan-1", "New Clan-2". Try to avoid collision.


await this.joinClan(playerId, newClan._id.toString());

} catch (err: any) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like try-catch block is unecessary here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants