OnPlayerBoatEditStarted
OnPlayerBoatEditStarted is called when a player starts editing their boat at a BoatBuildingStation, immediately before the game removes the original PlayerBoat entity and replaces it with a buildable boat construction.
void OnPlayerBoatEditStarted(PlayerBoat playerBoat, BoatBuildingStation boatBuildingStation)Parameters
| Parameter | Type | Description |
|---|---|---|
playerBoat | PlayerBoat | The PlayerBoat entity that is being converted into an editable boat construction. Use it to read the owner, position, health or contents before the game destroys it. |
boatBuildingStation | BoatBuildingStation | The BoatBuildingStation that triggered the conversion and will take over the boat build. Read its position, owner or building privilege state here. |
Return value
The return value is ignored. The game proceeds to kill the original PlayerBoat and complete the conversion regardless of what your hook method returns, so declare it void.
How it works
The hook fires inside BoatBuildingStation.ConvertPlayerBoatToConstruction, right before playerBoat.Kill() runs. That means it fires only when a player actually begins a boat edit session at a station, not when the boat is created, spawned or destroyed by other means. By the time you receive the call, the boat still exists in the world with its inventory, owner and health intact, so it is the last safe moment to inspect it.
playerBoat is the live vehicle entity: use OwnerID, transform.position, health or net.ID to identify it. boatBuildingStation is the station driving the conversion, useful for proximity checks or logging which station is in use. Declaring either parameter more generally has no practical benefit here; keep the exact types so the call is always delivered.
This is a notification hook. The conversion cannot be vetoed from here; if you need to block the edit, use CanEditPlayerBoat instead. Typical uses are logging boat edits, copying out ownership or metadata before the entity is killed, applying a cooldown, or notifying the owner and nearby players.
Example plugin: Log boat edit sessions and warn the owner
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Boat Edit Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Counts boat edit sessions per owner and warns the player in chat")]
public class BoatEditAnnouncer : RustPlugin
{
private const string DataFileName = "BoatEditAnnouncer";
private PluginConfig config;
private Dictionary<string, int> editCounts = new Dictionary<string, int>();
private class PluginConfig
{
[JsonProperty("Warn owner in chat")]
public bool WarnOnEdit = true;
[JsonProperty("Log to server console")]
public bool LogToConsole = true;
}
private class StoredData
{
[JsonProperty("Edit counts by owner id")]
public Dictionary<string, int> Counts = new Dictionary<string, int>();
}
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>
{
["EditStarted"] = "Your boat at {0} is now an edit station. Total edits: {1}.",
["ConsoleLine"] = "{0} ({1}) started a boat edit at {2}. Total edits: {3}."
}, this);
}
private string Msg(string key, string userId = null, params object[] args) =>
string.Format(lang.GetMessage(key, this, userId), args);
private void Init()
{
LoadData();
}
private void LoadData()
{
var data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(DataFileName);
editCounts = data?.Counts ?? new Dictionary<string, int>();
}
private void SaveData()
{
Interface.Oxide.DataFileSystem.WriteObject(DataFileName, new StoredData { Counts = editCounts });
}
private void OnPlayerBoatEditStarted(PlayerBoat playerBoat, BoatBuildingStation boatBuildingStation)
{
if (playerBoat == null || boatBuildingStation == null) return;
string ownerId = playerBoat.OwnerID.ToString();
int count;
editCounts.TryGetValue(ownerId, out count);
count++;
editCounts[ownerId] = count;
SaveData();
Vector3 pos = playerBoat.transform.position;
string position = $"({Mathf.RoundToInt(pos.x)}, {Mathf.RoundToInt(pos.z)})";
BasePlayer owner = BasePlayer.FindByID(playerBoat.OwnerID);
if (owner == null || !owner.IsConnected) return;
if (config.WarnOnEdit)
{
owner.ChatMessage(Msg("EditStarted", owner.UserIDString, position, count));
}
if (config.LogToConsole)
{
Puts(string.Format(Msg("ConsoleLine"), owner.displayName, owner.UserIDString, position, count));
}
}
private void Unload()
{
SaveData();
editCounts?.Clear();
}
}
}The plugin hooks OnPlayerBoatEditStarted and resolves the boat owner with BasePlayer.FindByID on the boat's OwnerID. It counts edits per owner in a dictionary that is written to oxide/data on every conversion and reloaded on startup, so admins can see how often a player rebuilds their boat. When the configured WarnOnEdit flag is enabled, the owner gets a chat message with their total edit count and the boat's world position, and the same information is printed as a console line so it lands in the server log. Unload saves the data and clears the dictionary.
Common use cases
Audit boat rebuilds
Persist a per-owner counter of how often a PlayerBoat is converted at a station, then read the data file when investigating build abuse or dupe reports.
Give the owner a heads-up
Send the owner a chat or console message that their boat is now an editable construction, including its position so they can find it again.
Snapshot metadata before the kill
Read the boat's skin, health or net ID here and store it, since the PlayerBoat entity is removed immediately after the hook returns.
Pitfalls
The hook cannot cancel the edit
It fires after the decision to convert has been made and the return value is discarded. Use
CanEditPlayerBoatif you need to deny the action.The boat is destroyed right after
Any reference to
playerBoatis invalid once the conversion finishes. Copy the values you need immediately and do not schedule timers that touch the entity.OwnerID may not resolve to a player
Boat ownership is stored as a raw ulong; the owner can be offline, banned or an entity ID. Always null-check the result of
BasePlayer.FindByIDbefore messaging.
Build a plugin with OnPlayerBoatEditStarted
Describe what should happen and get a compiled plugin that uses this hook.
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 OnPlayerBoatEditStarted
Generate