Entity Visibility System
Entity Visibility System
Section titled “Entity Visibility System”Journey 3.0 expands the visibility system from NPC-only to all entity types. Any entity in the game — NPCs, mobs, projectiles, item drops, armor stands — can be made visible or invisible on a per-player basis. This powers quest phasing, private dungeons, party-exclusive encounters, and more.
Visibility Types
Section titled “Visibility Types”Every managed entity has a visibility type that determines its default behavior:
| Type | Description |
|---|---|
OWNER_ONLY | Only the owner player can see the entity |
GLOBAL_WHEN_OWNER_ONLINE | Everyone sees it while the owner is online; hidden when they log off |
CONDITIONAL | Visible when a MoLang condition evaluates to true per-player |
AREA_RESTRICTED | Only visible to players inside a specific zone/region |
ALWAYS_VISIBLE | Everyone always sees it (default for normal entities) |
OWNER_ONLY
Section titled “OWNER_ONLY”The entity is only visible to its owner. Other players cannot see or interact with it.
Use cases: Personal quest NPCs, private spawned Pokemon, player-specific interactables.
{ "entity_uuid": "npc-uuid-here", "visibility_type": "OWNER_ONLY", "owner": "player-uuid"}GLOBAL_WHEN_OWNER_ONLINE
Section titled “GLOBAL_WHEN_OWNER_ONLINE”Everyone can see the entity while the owner is online. When the owner disconnects, the entity hides from all players.
Use cases: Player shops, personal mounts in public areas, summoned companions.
{ "entity_uuid": "shop-npc-uuid", "visibility_type": "GLOBAL_WHEN_OWNER_ONLINE", "owner": "player-uuid"}CONDITIONAL
Section titled “CONDITIONAL”Visibility is determined by a MoLang expression evaluated per-player. This is the most flexible type — it replaces the old NPC visibility condition system.
Use cases: Quest-phased NPCs, progressive story content, badge-gated gym leaders.
{ "entity_uuid": "misty-npc-uuid", "visibility_type": "CONDITIONAL", "condition": "q.player.has_flag('gym_badge_boulder')"}AREA_RESTRICTED
Section titled “AREA_RESTRICTED”The entity is only visible to players within a specific zone or Ceremony region.
Use cases: Dungeon bosses, zone-specific NPCs, area-exclusive encounters.
{ "entity_uuid": "dungeon-boss-uuid", "visibility_type": "AREA_RESTRICTED", "zones": ["dungeon-zone-uuid"]}ALWAYS_VISIBLE
Section titled “ALWAYS_VISIBLE”The entity is visible to everyone at all times. This is the default for all entities not registered with the visibility system.
Visibility Groups
Section titled “Visibility Groups”Groups let multiple players share visibility of entities. When any group member can see an entity, all group members can.
Use cases: Party dungeons, co-op quests, team-based world events.
Groups are defined by tagging entities with a group ID:
{ "entity_uuid": "party-boss-uuid", "visibility_type": "OWNER_ONLY", "owner": "player-uuid", "group": "party:party-uuid"}When the owner is in a party, all party members inherit visibility of entities in that party’s group.
Inheritance
Section titled “Inheritance”Entities spawned by other entities (projectiles, drops, etc.) inherit their parent’s visibility rules automatically. If a mob is OWNER_ONLY, any items it drops or projectiles it fires are also only visible to the owner.
This prevents information leaks where a player could see projectiles from an invisible entity or pick up drops from a fight they shouldn’t see.
MoLang Conditions
Section titled “MoLang Conditions”For CONDITIONAL visibility, the condition is a MoLang expression with access to:
| Query | Description |
|---|---|
q.entity_id | The entity’s UUID |
q.entity_x, q.entity_y, q.entity_z | Entity position |
q.is_owner | 1.0 if the current player is the entity’s owner |
q.player.* | All standard player functions (flags, tasks, levelables, zones, etc.) |
Examples
Section titled “Examples”// Visible after completing a questq.player.has_completed_task('journey:rescue_professor')
// Visible to players with a specific flagq.player.has_flag('spirit_vision')
// Visible at high trainer levelq.player.levelable_level('trainer_rank') >= 25.0
// Visible during a quest phaseq.player.has_flag('quest_phase_2') && !q.player.has_flag('quest_phase_3')
// Visible to the owner alwaysq.is_ownerPlayer Functions
Section titled “Player Functions”Control entity visibility from MoLang scripts:
| Function | Description |
|---|---|
q.player.start_watching_entity('entity-uuid') | Make player see an entity |
q.player.stop_watching_entity('entity-uuid') | Make player stop seeing an entity |
NPC Visibility Subsystem
Section titled “NPC Visibility Subsystem”The original NPC visibility system still works and runs as a subsystem within the entity visibility framework (priority 100). All existing NPC visibility functions continue to work:
| Function | Description |
|---|---|
npc.set_visibility_condition("molang") | Set condition for all players |
npc.set_player_visibility('player-uuid', "molang") | Set condition for one player |
npc.force_show_to_player('player-uuid') | Force visible |
npc.force_hide_from_player('player-uuid') | Force hidden |
npc.is_visible_to_player('player-uuid') | Check visibility |
npc.update_visibility() | Refresh for all players |
These NPC functions are shortcuts that register the NPC with the entity visibility system using CONDITIONAL type internally.
Managed Spawn Commands
Section titled “Managed Spawn Commands”Journey provides managed spawn commands that automatically register entities with the visibility system:
/mspawnnpc <npc_id> <pos> [for <owner>] [visibility <type>]
Section titled “/mspawnnpc <npc_id> <pos> [for <owner>] [visibility <type>]”Spawn an NPC with visibility controls.
/mspawnnpc professor_oak ~ ~ ~ for Notch visibility OWNER_ONLY/mspawnnpc gym_leader ~ ~ ~ visibility CONDITIONAL condition "q.player.has_flag('badge_1')"/msummon <entity_type> <pos> [for <owner>] [visibility <type>]
Section titled “/msummon <entity_type> <pos> [for <owner>] [visibility <type>]”Summon any entity with visibility controls.
/msummon minecraft:armor_stand ~ ~ ~ for Notch visibility OWNER_ONLY/msummon cobblemon:npc ~ ~ ~ visibility AREA_RESTRICTED zones dungeon-zone-uuidBoth commands accept the for <owner> modifier to set entity ownership.
Admin Spectator Mode
Section titled “Admin Spectator Mode”Admins can toggle a “see all” mode that reveals all managed entities regardless of visibility rules, without being able to interact with them. This is useful for debugging and oversight.
/journey visibility seeallWhile active, hidden entities appear with a translucent or wireframe effect so admins can distinguish them from normally visible entities.
Commands
Section titled “Commands”| Command | Description |
|---|---|
/journey visibility test <player> <entity> | Check if a player can see an entity |
/journey visibility seeall | Toggle admin see-all mode |
/journey visibility status <entity> | Show an entity’s visibility config |
/journey visibility info <entity> | Show detailed visibility info |
/journey visibility cleanup | Remove visibility data for despawned entities |
/mspawnnpc <npc_id> <pos> [for <owner>] [visibility <type>] | Spawn NPC with visibility |
/msummon <entity> <pos> [for <owner>] [visibility <type>] | Summon entity with visibility |
Permission: journey.command.visibility (level 2)
Configuration
Section titled “Configuration”Entity visibility configs are stored in config/journey/npc_visibility/ (the directory name is retained for backwards compatibility).
{ "entity_uuid": "unique-entity-uuid", "visibility_type": "CONDITIONAL", "condition": "q.player.has_flag('quest_started')", "owner": "", "group": "", "zones": [], "check_interval": 20}| Field | Type | Default | Description |
|---|---|---|---|
entity_uuid | String | Required | The entity’s UUID |
visibility_type | String | "ALWAYS_VISIBLE" | One of the 5 visibility types |
condition | String | "1.0" | MoLang condition (for CONDITIONAL type) |
owner | String | "" | Owner player UUID (for OWNER_ONLY and GLOBAL_WHEN_OWNER_ONLINE) |
group | String | "" | Visibility group ID |
zones | Array | [] | Zone UUIDs (for AREA_RESTRICTED) |
check_interval | Number | 20 | Ticks between condition re-evaluations |
Performance
Section titled “Performance”The entity visibility system uses a packet-level interception on the network thread with O(1) lookup per entity per packet. This means:
- No tick overhead — visibility checks don’t run on the main server thread
- No entity manipulation — entities aren’t teleported or removed, just filtered from packets
- Scales linearly with network traffic, not entity count
- Condition re-evaluation happens on a configurable interval (default: every 20 ticks / 1 second)
Patterns
Section titled “Patterns”Quest-Phased NPC
Section titled “Quest-Phased NPC”NPC appears only during a specific quest phase:
{ "entity_uuid": "guide-npc-uuid", "visibility_type": "CONDITIONAL", "condition": "q.player.has_flag('quest_phase_2') && !q.player.has_flag('quest_phase_3')"}Progressive Gym Leaders
Section titled “Progressive Gym Leaders”Each gym leader appears after earning the previous badge:
{ "entity_uuid": "misty-uuid", "visibility_type": "CONDITIONAL", "condition": "q.player.has_flag('gym_badge_boulder')"}{ "entity_uuid": "surge-uuid", "visibility_type": "CONDITIONAL", "condition": "q.player.has_flag('gym_badge_cascade')"}Party Dungeon Boss
Section titled “Party Dungeon Boss”A boss only visible to the party that spawned it:
{ "entity_uuid": "dungeon-boss-uuid", "visibility_type": "OWNER_ONLY", "owner": "party-leader-uuid", "group": "party:party-uuid"}Zone-Exclusive Encounters
Section titled “Zone-Exclusive Encounters”Entities that only appear inside a specific zone:
{ "entity_uuid": "safari-warden-uuid", "visibility_type": "AREA_RESTRICTED", "zones": ["safari-zone-uuid"]}Troubleshooting
Section titled “Troubleshooting”Entity not appearing:
- Check visibility type and condition with
/journey visibility status <entity> - For
CONDITIONAL, verify the MoLang condition evaluates correctly - For
OWNER_ONLY, confirm the owner UUID is correct - Use
/journey visibility test <player> <entity>to debug
Entity not disappearing:
- Conditions are re-evaluated every
check_intervalticks — wait a moment - Check for force-show overrides on the NPC subsystem
- Run
/journey visibility cleanupto clear stale data
Performance concerns:
- Increase
check_intervalfor entities that don’t need frequent updates - Use
ALWAYS_VISIBLEorOWNER_ONLYwhen possible (no condition evaluation needed) CONDITIONALwith complex MoLang expressions costs more than simple flag checks
Related
Section titled “Related”- NPCs & Paths — NPC scripting and patrol routes
- Zones — Zone definitions for AREA_RESTRICTED
- Flags — Track player progress for conditions
- MoLang — Write complex visibility conditions
- Commands — Full command reference