Skip to content
BasaltSoftware
Bedrock 1.26.60

Site colour

Discord
Esc

    ↑↓ moveEnter openEsc close

    Keyboard shortcuts
    Ctrl K
    Search the whole site, from any page
    /
    Jump to the sidebar search, or search the whole site where there isn't one
    Enter
    Open the top search result
    Esc
    Clear the search, or close this panel
    ?
    Show these shortcuts
    Plugin API

    Scoreboards

    Create objectives, track scores for players and fake players, and show them on screen.

    The scoreboard stores a number per participant, grouped into named objectives. Use it for anything you want to count and, optionally, show on screen: kills, coins, join counts, a round timer.

    Plugins reach it through world.scoreboard. It is the same scoreboard the /scoreboard command changes, it is saved with the world, and every plugin sees the same objectives. That makes it a simple way to share numbers between plugins and commands.

    An objective has an id and a display name. Create each one once; addObjective throws if the id is taken, so look it up first:

    import { world } from "@minecraft/server";
    world.afterEvents.worldLoad.subscribe(() => {
    const kills =
    world.scoreboard.getObjective("kills") ??
    world.scoreboard.addObjective("kills", "§cKills");
    console.log(`Tracking ${kills.id} as "${kills.displayName}"`);
    });

    Do this in worldLoad rather than at the top of the file, so the world is ready when it runs.

    Method Does
    addObjective(id, displayName?) Creates an objective and returns it.
    getObjective(id) Returns the objective, or undefined.
    getObjectives() Returns all objectives.
    removeObjective(idOrObjective) Deletes an objective and its scores.

    Scores belong to participants. A participant can be:

    • a Player or other Entity,
    • a plain string, which makes a “fake player”: a named line with no entity behind it,
    • a ScoreboardIdentity you got from the scoreboard.
    import { world, Player } from "@minecraft/server";
    world.afterEvents.entityDie.subscribe((event) => {
    const killer = event.damageSource.damagingEntity;
    if (!(killer instanceof Player)) return;
    const kills = world.scoreboard.getObjective("kills");
    if (!kills) return;
    const total = kills.addScore(killer, 1);
    if (total % 10 === 0) world.sendMessage(`${killer.name} has ${total} kills!`);
    });
    Method Does
    getScore(participant) The score, or undefined if the participant has none in this objective.
    setScore(participant, score) Sets the score.
    addScore(participant, amount) Adds to the score and returns the new total. A negative amount subtracts.
    hasParticipant(participant) Whether the participant has a score here.
    removeParticipant(participant) Removes the participant’s score.
    getScores() Every score in the objective, as { participant, score }.
    getParticipants() Every participant in the objective.

    getScore returns undefined, not 0, for someone with no score, so default it:

    const coins = objective.getScore(player) ?? 0;

    getScore also returns undefined for a player or entity that is no longer in the world, so an interval that walks a list of players does not throw when one of them has left. setScore, addScore and removeParticipant still throw an InvalidEntityError for them.

    An objective can be shown in one of three places.

    DisplaySlotId Where
    Sidebar The panel on the right of the screen
    List The player list (pause menu)
    BelowName Under each player’s name tag
    import { world, DisplaySlotId, ObjectiveSortOrder } from "@minecraft/server";
    world.afterEvents.worldLoad.subscribe(() => {
    const kills =
    world.scoreboard.getObjective("kills") ??
    world.scoreboard.addObjective("kills", "§cKills");
    world.scoreboard.setObjectiveAtDisplaySlot(DisplaySlotId.Sidebar, {
    objective: kills,
    sortOrder: ObjectiveSortOrder.Descending,
    });
    });

    Objectives on display are sent to everyone online and to players as they join, and the display updates as scores change.

    To take one down:

    world.scoreboard.clearObjectiveAtDisplaySlot(DisplaySlotId.Sidebar);

    getObjectiveAtDisplaySlot(slot) tells you what is currently shown there.

    Fake players let you use the sidebar as a small information panel. Each string is a line, and the score orders the lines.

    import { system, world, DisplaySlotId, ObjectiveSortOrder } from "@minecraft/server";
    world.afterEvents.worldLoad.subscribe(() => {
    world.scoreboard.removeObjective("info");
    const info = world.scoreboard.addObjective("info", "§6My Server");
    world.scoreboard.setObjectiveAtDisplaySlot(DisplaySlotId.Sidebar, {
    objective: info,
    sortOrder: ObjectiveSortOrder.Descending,
    });
    system.runInterval(() => {
    info.setScore("§aOnline", world.getAllPlayers().length);
    info.setScore("§eDay", world.getDay());
    }, 20);
    });

    The sidebar is shared: every player sees the same objective. It cannot show a different panel to each player.

    getScores() gives you everything you need to build a ranking:

    import { world, ScoreboardObjective } from "@minecraft/server";
    function top(objective: ScoreboardObjective, count: number): string[] {
    return objective
    .getScores()
    .sort((a, b) => b.score - a.score)
    .slice(0, count)
    .map((entry, index) => `${index + 1}. ${entry.participant.displayName}: ${entry.score}`);
    }
    const kills = world.scoreboard.getObjective("kills");
    if (kills) world.sendMessage(top(kills, 5).join("\n"));

    Each participant is a ScoreboardIdentity with a displayName and a type (Player, Entity or FakePlayer).

    Because plugins and commands share one scoreboard, operators can inspect and correct what your plugin tracks:

    /scoreboard players list Steve
    /scoreboard players set Steve kills 0
    /scoreboard objectives setdisplay sidebar kills descending

    See Commands.

    • Objectives use the dummy criteria only: scores change when a plugin or a command changes them.
    • There are no teams.
    • ScoreboardIdentity.getEntity() does not return entities.
    • Scores are whole numbers.
    Use a scoreboard when Use a dynamic property when
    The value is a whole number The value is text, a boolean, a decimal or a location
    You want to show it on screen It is private to your plugin
    Commands or other plugins should see it Nothing else should touch it