Skip to content

Add command to lock/unlock a PopulationCentre's characters for linking #681

Description

@gaidheal1

Problem

New users are assigned a character via assign_character_to_player (users/utils.py):

character = (
    Character.objects.filter(can_link=True, death_date__isnull=True)
    .exclude(links__is_active=True)
    .first()
)

This pulls from every Character with can_link=True across the whole map, so new users land in villages essentially at random. There's currently no way to control which population centres are open for new players.

As new users join, I want to open up villages one at a time (lock all but the currently "active" one) instead of having everyone spread across the entire map.

Proposal

Add a characters_can_link boolean field directly on PopulationCentre (default True), rather than deriving "is this centre open" from the residents' can_link values or bulk-toggling Character.can_link per resident.

("Locked" was considered as the field/flag name, but a population centre could plausibly be "locked" for other reasons in future — e.g. not yet open to visit/travel to — so characters_can_link is more precise about what this specific flag controls.)

Shape, following the existing pattern in locations/management/commands/manage_centres.py + locations/services/population_centre_admin.py:

  • Migration adding PopulationCentre.characters_can_link = models.BooleanField(default=True).
  • A service function, e.g. set_population_centre_characters_can_link(name: str, characters_can_link: bool) -> PopulationCentre in locations/services/population_centre_admin.py.
  • --lock NAME / --unlock NAME options on the existing manage_centres management command (alongside --list / --delete).
  • assign_character_to_player (users/utils.py) needs to additionally filter on the resident's centre being open, e.g. .filter(can_link=True, death_date__isnull=True, population_centre__characters_can_link=True). Need to decide how characters with no population_centre are handled here (currently population_centre is nullable) — presumably still linkable, since they're not tied to a lockable centre.
  • Optionally, expose characters_can_link on PopulationCentreAdmin (locations/admin.py) as an editable/list-display field, similar to the existing mark_as_npc / mark_as_canlink actions on CharacterAdmin.

Behavior

  • Locking must not touch actively linked characters. Locking a centre only affects new assignment via assign_character_to_player — it must not deactivate or otherwise change any character's existing active PlayerCharacterLink. Existing players in a locked centre keep playing normally.
  • Locking/unlocking does not write to Character.can_link at all under this design — it's a separate flag read at assignment time, which sidesteps the bulk-update-clobbers-other-state problem entirely.

Related

See #682Character.can_link is currently a single stored boolean written by several independent code paths (age at spawn, admin toggle, active-link signal, and now this centre flag would be a fourth). That issue proposes deriving can_link from underlying reasons instead of one flat field; this centre flag would be one of those inputs once that lands.

Notes

  • Character.can_link (default False): character/models/character.py
  • Character.population_centre FK, related_name="residents", nullable: character/models/character.py
  • Assignment logic: users/utils.py::assign_character_to_player
  • Existing per-centre command/service to extend: locations/management/commands/manage_centres.py, locations/services/population_centre_admin.py
  • Existing per-character admin actions: character/admin.py (mark_as_npc, mark_as_canlink)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions