Skip to content
RustPluginGenerator

OnMapMarkerAdd

OnMapMarkerAdd is called when a player places a marker on the in-game map, before the server stores it. Returning a non-null value cancels the placement.

Signature
object OnMapMarkerAdd(BasePlayer player, ProtoBuf.MapNote mapNote)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer whose client sent the marker request. Use it for permission checks, team lookups or per-player limits.
mapNoteProtoBuf.MapNoteThe ProtoBuf.MapNote being placed, carrying the world position (x, z) and the icon type (note, vending machine, etc.). Read it to inspect or validate the marker before it is stored.

Return value

Returning null (or nothing) lets the original code continue: the marker is stored unless CanUseMapMarkers is false. Returning any non-null object aborts Server_AddMarker immediately, so the note is never added to State.pointsOfInterest.

How it works

Fires inside BasePlayer.Server_AddMarker, which runs when the server handles the RPC a client sends after the player drops a map note. The method first reads the serialized ProtoBuf.MapNote from the message, calls the hook, and only then checks CanUseMapMarkers and appends the note to State.pointsOfInterest. Because the hook runs before that check, it is the only point where a plugin can inspect the note and refuse it.

mapNote exposes the world position (x, z) and the type field that selects which icon is drawn (MapNote.POI, vending machine, etc.). There is no separate permission requirement on the game side, so this hook is the place to enforce your own rules: a marker limit per player, a block on markers while raiding, a priced marker system, or wiping the position before storage.

The player argument is the sender, not necessarily the map owner in any other sense; it is the player whose account is placing the note. Declaring ProtoBuf.MapNote exactly is required — there is no base type to widen to. Modifying the note object in the hook does not prevent storage, so mutate it only if you intend to change what is kept, and return non-null to stop the placement entirely.

Example plugin: Limit map markers per player with a configurable cap

MapMarkerLimit.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Map Marker Limit", "RustPluginGenerator", "1.0.0")]
    [Description("Caps the number of map markers a player can place.")]
    public class MapMarkerLimit : RustPlugin
    {
        private const string PermBypass = "mapmarkerlimit.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Maximum markers per player")]
            public int MaxMarkersPerPlayer = 10;
        }

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["MarkerLimitReached"] = "You already have {0} map markers placed. Remove one before adding another."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
            => string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            permission.RegisterPermission(PermBypass, this);
        }

        private object OnMapMarkerAdd(BasePlayer player, ProtoBuf.MapNote mapNote)
        {
            if (player == null || mapNote == null) return null;
            if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;

            int limit = Math.Max(1, config.MaxMarkersPerPlayer);
            int current = player.State?.pointsOfInterest?.Count ?? 0;

            if (current >= limit)
            {
                player.ChatMessage(Msg("MarkerLimitReached", player.UserIDString, current));
                return true;
            }

            return null;
        }
    }
}

The plugin keeps a per-player count of placed markers, capped by MaxMarkersPerPlayer in the config and bypassable through the mapmarkerlimit.bypass permission. OnMapMarkerAdd counts the player's current entries in player.State.pointsOfInterest and returns true when the limit is reached, which aborts the placement before the server stores the note. Chat feedback comes from the language file so admins can reword it. Existing markers placed before the plugin was installed are not removed; the count simply starts from whatever the player already has, which keeps behavior consistent across reloads. The permission is registered in Init and checked against the player's UserIDString.

Common use cases

  • Per-player marker caps

    Stop players from littering the map by rejecting placements once they hold more than N notes.

  • Paid map markers

    Charge an economy balance in the hook and reject the note when the player cannot afford it.

  • Zone restrictions

    Read mapNote.x and mapNote.z to refuse markers placed inside a raid zone, event area or admin-only region.

Pitfalls

  • Returning a value from elsewhere

    Any non-null return aborts the method, so always return null after your checks unless you want to block the note; returning false still cancels the placement.

  • Existing markers are not counted retroactively

    State.pointsOfInterest already contains markers placed before the plugin loaded, so counting it enforces a hard total. If you only want to count new markers, track them in data instead.

  • The note is already deserialized

    mapNote is a live object read from the client. Editing it changes what is stored but does not stop storage; return non-null for that.

Build a plugin with OnMapMarkerAdd

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Per-player marker caps using the OnMapMarkerAdd hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnMapMarkerAdd

Generate