Skip to main content
The online play system provides a flexible room-based infrastructure for both casual playlists and competitive multiplayer. Rooms can be configured with various settings, playlists, and participation rules.

Room Structure

Rooms are the foundation of online play, containing all the information about a play session:
public partial class Room : INotifyPropertyChanged
{
    public long? RoomID { get; set; }
    public string Name { get; set; }
    public string? Password { get; set; }
    public bool HasPassword { get; set; }
    public APIUser? Host { get; set; }
    public RoomCategory Category { get; set; }
    public MatchType Type { get; set; }
    public RoomStatus Status { get; set; }
}

Room Properties

  • RoomID: Online identifier (null until created)
  • Name: Display name for the room
  • ChannelId: Associated chat channel ID
  • Password: Room password (only set during creation)
  • HasPassword: Indicates if password is required
  • Availability: Who can join (public, friends only, etc.)
  • Pinned: Whether the room appears at the top of listings
  • Host: Room creator/host user
  • MaxParticipants: Maximum allowed players
  • ParticipantCount: Current number of players
  • RecentParticipants: List of recent players
  • StartDate: When the room was created
  • EndDate: When the room will close
  • Duration: How long the room stays open
The Password property is write-only after creation for security. Use HasPassword to check if a password is required.

Room Categories

Rooms are organized into categories:

Room Categories

  • Normal: Standard user-created rooms
  • Spotlight: Featured/promoted rooms
  • Featured Artist: Rooms featuring official content
  • Lazer: osu!lazer-specific rooms

Playlist System

Rooms contain playlists of beatmaps to be played:
public IReadOnlyList<PlaylistItem> Playlist { get; set; }

Playlist Items

Each playlist item represents a beatmap with specific settings:

PlaylistItem Properties

  • Beatmap: The beatmap to be played
  • RequiredMods: Mods that all players must use
  • AllowedMods: Mods that players can optionally enable
  • RulesetID: Which game mode to use
  • Expired: Whether this item is no longer playable

Playlist Statistics

Rooms track statistics about their playlists:
public class RoomPlaylistItemStats
{
    public int CountActive { get; set; }  // Active items
    public int CountTotal { get; set; }   // Total items
    public int[] RulesetIDs { get; set; } // Game modes present
}

Difficulty Range

The room displays its difficulty range:
public class RoomDifficultyRange
{
    public double Min { get; set; }
    public double Max { get; set; }
}
This helps players quickly assess if a room matches their skill level.

Room Settings

Different room types support different settings:

Playlist-Specific Settings

Playlist Room Settings

// Maximum attempts per player on each playlist item
public int? MaxAttempts { get; set; }
Limiting attempts adds a challenge element to playlist rooms.

Multiplayer-Specific Settings

Controls who can add songs to the playlist:
public QueueMode QueueMode { get; set; }
  • Host Only
  • All Players
  • All Players (Round Robin)
Automatically start matches after a delay:
public TimeSpan AutoStartDuration { get; set; }
Set to zero to disable auto-start.
Automatically skip beatmap intros:
public bool AutoSkip { get; set; }

Creating and Managing Rooms

Creating a Room

1

Configure Room

Set up basic room properties:
var room = new Room
{
    Name = "My Room",
    Password = "secret123",
    Type = MatchType.HeadToHead,
    MaxParticipants = 16
};
2

Submit Creation Request

Send the room configuration to the server:
var request = new CreateRoomRequest(room);
3

Receive Room ID

After creation, the server assigns a RoomID:
room.RoomID // Now populated

Joining a Room

Join Room Process

var joinRequest = new JoinRoomRequest(roomId, password);
If the room has a password, it must be provided. Invalid passwords throw an exception.

Leaving a Room

var partRequest = new PartRoomRequest(roomId);

Room Status

Rooms have different statuses throughout their lifecycle:
1

Open

Room is active and accepting players.
2

Playing

A match is currently in progress.
3

Ended

Room has closed or expired.

Room Availability

Controls who can see and join the room:
public RoomAvailability Availability { get; set; }
Availability options include public, friends-only, and invite-only modes.

Scoring and Leaderboards

Rooms maintain leaderboards for competitive play:

Room Leaderboard

Leaderboard Request

var leaderboardRequest = new GetRoomLeaderboardRequest(roomId);
Returns all scores for the room, sorted by performance.

Playlist Item Scores

Each playlist item has its own leaderboard:
// Get scores for a specific playlist item
var scoresRequest = new IndexPlaylistScoresRequest(
    roomId,
    playlistItemId,
    cursor,
    sort
);

Score Retrieval

Retrieve a specific score by ID:
var scoreRequest = new ShowPlaylistScoreRequest(roomId, playlistId, scoreId);
Get the current user’s score on a playlist item:
var userScoreRequest = new ShowPlaylistUserScoreRequest(
    roomId,
    playlistId,
    userId
);
Retrieve scores near the user’s ranking:
public class MultiplayerScoresAround
{
    public MultiplayerScores Higher { get; set; }
    public MultiplayerScores Lower { get; set; }
}

User Score Tracking

The room tracks aggregate scoring for each user:
public PlaylistAggregateScore? UserScore { get; set; }

Aggregate Score

Combines performance across all playlist items to show overall user performance in the room.

Score Submission

When playing in a room, scores are submitted to the server:
1

Request Score Token

Before playing, request a token:
var tokenRequest = new CreateRoomScoreRequest(
    roomId,
    playlistItemId,
    versionHash
);
Returns an APIScoreToken for submission.
2

Play Beatmap

Complete the beatmap with the token active.
3

Submit Score

Submit the final score using the token.

Room Listing

Retrieve available rooms from the server:
var roomsRequest = new GetRoomsRequest(category);

Filtering Rooms

Rooms can be filtered by:
  • Category (Normal, Spotlight, etc.)
  • Game mode
  • Status (Open, Playing)
  • Search terms

Room Updates

Room properties update in real-time:
public void CopyFrom(Room other)
{
    // Updates all properties from another room instance
    RoomID = other.RoomID;
    Name = other.Name;
    Playlist = other.Playlist;
    // ... etc
}
The Room class implements INotifyPropertyChanged. Subscribe to property changes to keep UI synchronized:
room.PropertyChanged += (sender, args) =>
{
    // Handle property change
};

Current Playlist Item

For room listings, a current item is tracked:
public PlaylistItem? CurrentPlaylistItem { get; set; }
This property is primarily used in the lounge screen and may not be accurate inside the room.

Attempt Tracking

The system tracks how many times each user has attempted each playlist item:
public class ItemAttemptsCount
{
    public long PlaylistItemID { get; set; }
    public int Attempts { get; set; }
}
This is used to enforce MaxAttempts limits in playlist rooms.

Room Expiration

Rooms automatically close after their end date:
public bool HasEnded => DateTimeOffset.Now >= EndDate;
This property doesn’t update in real-time. Subscribe to EndDate changes for immediate notifications.

Build docs developers (and LLMs) love