OnAnalysisComplete
OnAnalysisComplete is called on the server when a player finishes analyzing a survey crater (the resource survey minigame found with a Survey Charge), right as the crater's AnalysisComplete RPC runs on the server.
void OnAnalysisComplete(SurveyCrater surveyCrater, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
surveyCrater | SurveyCrater | The SurveyCrater entity whose survey finished. Use it to read position, owner, and to destroy or replace the crater after the analysis completes. |
player | BasePlayer | The BasePlayer who completed the survey, taken from the RPC message. May be null if the message had no player, so always null-check it. |
Return value
The hook's return value is ignored. The patched AnalysisComplete method only calls the hook and returns void, so returning null or any value does not change the game's behavior. To alter results, modify the crater or player state directly inside the hook.
How it works
This hook fires inside SurveyCrater.AnalysisComplete, which is invoked when a SurveyCrater receives the RPC that marks its analysis as done. In practice a player places a Survey Charge, detonates it to create the crater, then interacts with the crater to pull its survey results; the server runs this method to finalize the analysis. By the time the hook runs, the crater entity (surveyCrater) already exists and belongs to the player who detonated the charge. The player argument is the RPC sender, so it identifies who completed the analysis, which is useful for per-player rewards or logging.
Because the parameter types are concrete (SurveyCrater and BasePlayer), you can narrow further — for example declaring BaseEntity would also match, but there is no benefit; keep the SurveyCrater type if you need crater-specific members. The hook is not on a hot path (a survey finishes once per charge), so light work such as chat messages or spawning a small entity is fine. Null-check both arguments before using them; a missing player is possible if the RPC carried no connection.
Example plugin: Reward players when they finish a resource survey
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Survey Reward Crate", "RustPluginGenerator", "1.0.0")]
[Description("Gives players a configured item reward when they finish analyzing a survey crater.")]
public class SurveyRewardCrate : RustPlugin
{
private const string PermUse = "surveyrewardcrate.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Reward shortname")]
public string RewardShortname = "scrap";
[JsonProperty("Reward amount")]
public int RewardAmount = 25;
[JsonProperty("Require permission")]
public bool RequirePermission = true;
}
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>
{
["Reward"] = "Survey complete. You received {0} x {1}.",
["NoItem"] = "Survey complete, but the configured reward item could not be found."
}, 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(PermUse, this);
}
private void OnAnalysisComplete(SurveyCrater surveyCrater, BasePlayer player)
{
if (player == null || player.IsNpc || !player.IsConnected) return;
if (surveyCrater == null || surveyCrater.IsDestroyed) return;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse)) return;
var def = ItemManager.FindItemDefinition(config.RewardShortname);
if (def == null)
{
player.ChatMessage(Msg("NoItem", player.UserIDString));
PrintWarning("Reward shortname '" + config.RewardShortname + "' is not a valid item.");
return;
}
var item = ItemManager.CreateByItemID(def.itemid, Mathf.Max(1, config.RewardAmount), 0UL);
if (item == null) return;
player.GiveItem(item);
player.ChatMessage(Msg("Reward", player.UserIDString, item.amount, def.displayName.english));
}
}
}The plugin listens for OnAnalysisComplete and, for each finished survey, gives the player a small item reward and a chat confirmation. A permission (surveyrewardcrate.use) gates who receives the reward. The reward shortname, amount, and message are all configurable through the plugin's config file. The hook null-checks both the crater and the player, resolves the item definition before creating the item, and uses the language file for the chat line so admins can localize it. Because the return value is ignored, the plugin does not try to cancel or modify the survey itself — it only adds a side reward on top of whatever the crater produced.
Common use cases
Grant survey rewards
Give players scrap, components, or a custom item every time they finish analyzing a crater, optionally only on specific permission groups.
Log survey activity
Record player id, name, and crater position to a data file or admin log for anti-cheat review or server statistics.
Relocate or clean up craters
Kill the crater after analysis or spawn a replacement marker at its position so the map does not fill with leftover craters.
Pitfalls
Player may be null
The RPC message may not carry a player connection in edge cases. Always check
player == nullbefore reading UserIDString or sending messages.Return value does nothing
There is no way to cancel the analysis or change its result via the hook return. To change outcomes you must modify the crater or player directly.
Crater can already be destroyed
Check
surveyCrater.IsDestroyedbefore calling Kill or reading transform data if your code manipulates the entity.
Build a plugin with OnAnalysisComplete
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 OnAnalysisComplete
Generate