C#:
---title : API Referencelanguage_tabs : - csharp - javascript - lua - pythontoc_footers : - <a href='http://forum.rustoxide.com'>Get help on our forums</a> - <a href='https://github.com/OxideMod/Oxide'>View Oxide source on GitHub</a> - <a href='https://github.com/tripit/slate'>Documentation powered by Slate</a>search : true---
# Introduction
``` _ _ _ | |__ ___| | | ___ | '_ \ / _ \ | |/ _ \
| | | | __/ | | (_) |
|_| |_|\___|_|_|\___/ _
__ _____ _ __| | __| |
\ \ /\ / / _ \| '__| |/ _` | \ V V / (_) | | | | (_| | \_/\_/ \___/|_| |_|\__, _|So you want to develop plugins for Oxide?We'll show you how to get started, along with sample code!
```
Oxide is a complete rewrite of the popular, original Oxide mod for the game Rust. Oxide has a focus on modularity and extensibility.
The core is highly abstracted and loosely coupled, and could be used to mod any game that uses .NET such as 7 Days to Die, The Forest, Space Engineers, and more. Support for games, plugin languages, and other functionality is added via extensions. When loading, Oxide 2 scans the binary folder for DLL extensions. Extension filenames are formatted as `Oxide.Ext.Name.dll`.
The current official extensions are listed below:
* Oxide.Ext.CSharp - _Allows raw CSharp plugins to be loaded_
* Oxide.Ext.JavaScript - _Allows JavaScript plugins to be loaded_
* Oxide.Ext.Lua - _Allows Lua plugins to be loaded_
* Oxide.Ext.Python - _Allows Python plugins to be loaded_
* Oxide.Ext.Rust - _Provides support for the Rust Experimental server_
* Oxide.Ext.Unity - _Provides support for Unity games_
As an example to what kind of extensions may be used in the future, here is a non-exhaustive list of possibilities:
* Oxide.Ext.IRC - _Allows plugins to access an IRC server_
* Oxide.Ext.MySQL - _Allows plugins to access a MySQL database_
* Oxide.Ext.SQLite - _Allows plugins to access a SQLite database_
* Oxide.Ext.WebServer - _Allows the game server to also host a web server_
# API Hooks
## Plugin specific hooks
### Init()
* Called when the plugin is being loaded
* Other plugins may or may not be present, dependant on load order
* Other plugins WILL have been executed though, so globals exposed by them will be present
### LoadDefaultConfig()
* Called when the config for the plugin should be initialized
* Only called if the config file does not already exist
### Unload()
* Called when the plugin is being unloaded
## General hooks
### OnInitLogging()
* Called from Assembly-CSharp/Bootstrap.StartupShared
* No return behavior
* Used internally by Oxide to start Unity logging
### OnTick()
* Called from Assembly-CSharp/ServerMgr.DoTick
* No return behavior
* Called every tick (defined by the tickrate of the server?)
### ModifyTags(string oldtags)
* Called from Assembly-CSharp/ServerMgr.UpdateServerInformation
* Returning a string overrides the tags with new ones
* Used by RustCore and abstracted into BuildServerTags
### BuildServerTags(IList<string> tags)
* Called from RustCore.ModifyTags
* No return behavior
* Add tags to the list, they will be concat'd at the end
### OnServerInitialized()
* Called from Assembly-CSharp/ServerMgr * No return behavior * Is called after the server startup has been completed and is awaiting connections
### OnRunCommand(Facepunch/ConsoleSystem.Arg arg)
* Called from Facepunch/ConsoleSystem.Run, Facepunch/ConsoleSystem.RunUnrestricted and Facepunch/ConsoleSystem.ClientRun * Return true to override Rust's command handling system
* Useful for intercepting commands before they get to their intended target (like chat.say)
* Used by RustCore to implement chat commands
### OnUserApprove(Facepunch/Network.Connection connection)
* Called from Assembly-CSharp/ConnectionAuth.OnNewConnection
* Returning a non-null value overrides default behavior, plugin should call Reject if it does this
* Used by RustCore and abstracted into CanClientLogin
### CanClientLogin(Facepunch/Network.Connection connection)
* Called from RustCore.OnUserApprove
* Returning true will allow the connection, returning nothing will by default allow the connection, returning anything else will reject it with an error message
* Returning a string will use the string as the error message
### OnFindSpawnPoint()
* Called from Assembly-CSharp/ServerMgr
* Return a Assembly-CSharp/BasePlayer.SpawnPoint object to use that spawnpoint
* Useful for controlling player spawnpoints (like making all spawns occur in a set area)
### OnPlayerConnected(Facepunch/Network.Message packet)
* Called from Assembly-CSharp/ServerMgr
* No return behavior
* Is called before the player object is created, but after the player has been approved to join the game
* Can get the connection from packet.connection
### OnPlayerSpawn(Assembly-CSharp/BasePlayer player, Facepunch/Network.Connection connection)
* Called when the player spawns (specifically when they click the "Respawn" button)
* No return behavior
* ONLY called when the player is transitioning from dead to not-dead, so not when they're waking up * This means it's possible for a player to connect and disconnect from a server without OnPlayerSpawn ever triggering for them
### OnRunPlayerMetabolism(Assembly-CSharp/PlayerMetabolism metabolism)
* Called before a metabolism update occurs for the specified player
* Returning true cancels the update
* Metabolism update consists of managing the player's temperature, health etc * You can use this to turn off or change certain aspects of the metabolism, either by editing values before returning, or taking complete control of the method * Access the player object using metabolism : GetComponent("BasePlayer")
### OnPlayerDisconnected(Assembly-CSharp/BasePlayer player)
* Called from Assembly-CSharp/ServerMgr * No return behavior * Is called before the player object is created, but after the player has been approved to join the game
### OnPlayerAttack(Assembly-CSharp/BasePlayer attacker, Assembly-CSharp/HitInfo hitinfo)
* Called from Assembly-CSharp/BasePlayer * Returning true cancels the attack * Useful for modifying an attack before it goes out * hitinfo.HitEntity should be the entity that this attack would hit
### OnItemCraft(Assembly-CSharp/ItemCraftTask item)
* Called from Assembly-CSharp/ItemCrafter * Return a Assembly-CSharp/ItemCraftTask object to modify behavior * Is called right after an item has started crafting
### OnItemDeployed(Assembly-CSharp/Deployer deployer, Assembly-CSharp/BaseEntity deployedentity)
* Assembly-CSharp/Deployer * No return behavior * Is called right after an item has been deployed
### OnItemAddedToContainer(Assembly-CSharp/ItemContainer container, Assembly-CSharp/Item item)
* Called from Assembly-CSharp/ItemContainer * No return behavior * Is called right after an item was added to a container * An entire stack has to be created, not just adding more wood to a wood stack for example
### OnItemRemovedFromContainer(Assembly-CSharp/ItemContainer container, Assembly-CSharp/Item item)
* Called from Assembly-CSharp/ItemContainer * No return behavior * Is called right after an item was removed from a container * The entire stack has to be removed for this to be called, not just a little bit
### OnGather(Assembly-CSharp/ResourceDispenser dispenser, Assembly-CSharp/BaseEntity entity, Assembly-CSharp/Item item)
* Assembly-CSharp/ResourceDispenser * No return behavior * Is called before the player is given items from a resource
### CanOpenDoor(Assembly-CSharp/BasePlayer player, Assembly-CSharp/BaseLock door)
* Called from Assembly-CSharp/BaseLock * Returning true will allow door usage, nothing will by default will allow door usage, returning anything else will reject door usage
### CanOpenDoor(Assembly-CSharp/BasePlayer player, Assembly-CSharp/CodeLock code)
* Called from Assembly-CSharp/CodeLock * Returning true will allow door code usage, nothing will by default will allow door code usage, returning anything else will reject door code usage
### CanOpenDoor(Assembly-CSharp/BasePlayer player, Assembly-CSharp/KeyLock key)
* Called from Assembly-CSharp/KeyLock * Returning true will allow door key usage, nothing will by default will allow door key usage, returning anything else will reject door key usage
### OnEntityAttacked(UnityEngine/Monobehavior entity, Assembly-CSharp/HitInfo hitinfo)
* Called from multiple places, each entity's attack handler basically
* Returning non-null value overrides default server behavior (useful for godmode etc)
* Alternatively, modify the hitinfo object to change the damage
* It should be ok to set the damage to 0, but if you don't return non-null, the player's client will receive a damage indicator (if entity is a BasePlayer)
* hitinfo has all kinds of useful things in it, such as hitinfo.Weapon, hitinfo.damageAmount or hitinfo.damageType
* Currently implemented for: BasePlayer, BaseAnimal
### OnEntityBuilt(Assembly-CSharp/BasePlayer player, UnityEngine/GameObject gameobject)
* Called from Assembly-CSharp/Item.Modules.Planner
* No return behavior
* Called when any structure is built (walls, ceilings, stairs, etc)
### OnEntityDeath(UnityEngine/Monobehavior entity, Assembly-CSharp/HitInfo hitinfo)
* Called from multiple places, each entity's death handler basically * No return behavior * hitinfo might be null, check it before use * Editing hitinfo probably has no effect * Currently implemented for : BasePlayer, BaseAnimal
### OnEntityEnter(Assembly-CSharp/TriggerBase triggerbase, Assembly-CSharp/BaseEntity entity)
* Called from Assembly-CSharp/TriggerBase * No return behavior * Called when an entity enters an area/zone (building privilege zone, water area, radiation zone, hurt zone, etc)
### OnEntityLeave(Assembly-CSharp/TriggerBase triggerbase, Assembly-CSharp/BaseEntity entity)
* Called from Assembly-CSharp/TriggerBase * No return behavior * Called when an entity leaves an area/zone (building privilege zone, water area, radiation zone, hurt zone, etc)
### OnEntitySpawn(UnityEngine/Monobehavior entity)
* Called from Assembly-CSharp/BaseNetworkable * No return behavior * Called when any networked entity is spawned (including trees)
### OnPlayerInit(Assembly-CSharp/BasePlayer player)
* Called from Assembly-CSharp/BasePlayer * No return behavior * Called when the player is initialising (after they've connected, before they wake up)
### OnPlayerChat(Assembly-CSharp/chat.say arg)
* Called from Assembly-CSharp/chat.say
* Returning a non-null value overrides default behavior of chat, not commands
### OnPlayerLoot(Assembly-CSharp/PlayerLoot lootinventory, Assembly-CSharp/BaseEntity targetentity)
* Called from Assembly-CSharp/PlayerLoot
* No return behavior
* Called when the player starts looting an entity
### OnPlayerLoot(Assembly-CSharp/PlayerLoot lootinventory, Assembly-CSharp/BasePlayer targetplayer)
* Called from Assembly-CSharp/PlayerLoot
* No return behavior
* Called when the player starts looting another player
### OnPlayerLoot(Assembly-CSharp/PlayerLoot lootinventory, Assembly-CSharp/Item targetitem)
* Called from Assembly-CSharp/PlayerLoot
* No return behavior
* Called when the player starts looting an item
# Configurations
## Loading / Creating a Configuration Table
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
PLUGIN.Name = "Name Of Plugin"
PLUGIN.Title = "Title Of Plugin"
PLUGIN.Version = V(0, 0, 1)
PLUGIN.Description = "Plugin description"
PLUGIN.Author = "Author"
PLUGIN.HasConfig = true
function PLUGIN:LoadDefaultConfig()
self.Config.Messages = {}
self.Config.Messages.Join = "Welcome to this server"
self.Config.Messages.Leave = "Goodbye"
self.Config.ShowJoinMessage = true
self.Config.ShowLeaveMessage = true
end
```
``` python
We need an example here
```
## Saving a Configuration Table
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
self:SaveConfig()
```
``` python
We need an example here
```
# Data Tables
## Loading / Creating a Data Table
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
We need an example here
```
``` python
We need an example here
```
## Saving a Data Table
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
We need an example here
```
``` python
We need an example here
```
# Timers
## Creating a timer
Sometimes you come across a situation which only a timer can fix. Timers are great for delaying code, allowing it to be run later.
### timer.Once
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
self.broadcastTimer = timer.Once(3, function()
rust.BroadcastChat("SERVER", "Hello world!")
end)
self.TimersList = {}
self.TimersList["Notice1"] = timer.Once(3, function()
rust.BroadcastChat("SERVER", "This is the Notice 1 every 3 seconds")
end)
self.TimersList["Notice2"] = timer.Once(10, function()
rust.BroadcastChat("SERVER", "This is the Notice 2 every 10 seconds")
end)
```
``` python
We need an example here
```
Executes the specified function once after the specified delay.
### timer.Repeat
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
self.broadcastTimer = timer.Repeat(10, 0, function()
rust.BroadcastChat("SERVER", "Hello world!")
end)
```
``` python
We need an example here
```
Executes the specified function every "delay" seconds. If "repeats" is specified, the function will only be called "repeats" times.
### timer.NextFrame
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
We need an example here
```
``` python
We need an example here
```
Executes the specified function at the next frame.
### timer.Chain
``` csharp
We need an example here
```
``` javascript
We need an example here
```
``` lua
We need an example here
```
``` python
We need an example here
```
Executes a chain of delayed functions. Each number in the argument list delays the timer chain by n more seconds, and each function in the argument list gets called after the previous delays in the chain have passed.
## Destroying a timer
``` c#
We need an example here
```
``` javascript
We need an example here
```
``` lua
function PLUGIN:Unload()
if broadcastTimer then
broadcastTimer:Destroy()
end
end
function PLUGIN:Unload()
for k,v in pairs(self.TimersList) do
self.TimersList[k]:Destroy()
end
end
```
``` python
We need an example here
```
It's always a good habit to stop all timers when your plugin is unloaded;
do this by destroying the instance of the timer.Timers can be used anywhere in your plugin, not just in the Unload function.Just make sure to always destroy them, as you wouldn't want a bunch of timers piling up and slowing down someone's server!
# Web Requests
Sends a HTTP web request to the specified URL.Returns true if the web request was sent, false if not.The callback is called with 2 parameters - an integer HTTP response code and a string response.
## Get method
This uses the raw connection to a webpage as you would on your browserReturns true/false``` c#We need an example here`````` javascriptWe need an example here`````` lualocal r = webrequests.EnqueueGet("http://www.google.com/search?q=rustoxide", function(code, response) if(response == nil) then print("Couldn't get an answer from Google") return end print("Google Answered:") print(tostring(response))end)`````` pythonWe need an example here```
## Post method
Returns true/false
# Styling Messages
> Render the text in boldface``` htmlWe are <b>not</b> amused.```> Render the text in italics``` htmlWe are <i>usually</i> not amused.```> It is possible to apply more than one style to a section of text by “nesting” one element inside another.``` htmlWe are <b><i>definitely not</i></b> amused```> Note the ordering of the ending tags, which is in reverse to that of the starting tags.The reason for this is perhaps clearer when you consider that the inner tags need not span the whole text of the outermost element.``` htmlWe are <b>absolutely <i>definitely</i> not</b> amused```> Change the size of text, by pixel value``` htmlWe are <size=50>largely</size> unaffected.```> Change the color of text``` html<color=#00ffffff>Hello world</color>```With Rust, you can stylize messages send from the server via plugins.Styling is limited to bold, italic, size, and color.The color can be specified in the traditional HTML format.`#rrggbbaa`...where the letters correspond to pairs of hexadecimal digits denoting the red, green, blue and alpha (transparency) values for the color.Another option is to use the name of the color.This is easier to understand but naturally, the range of colors is limited and full opacity is always assumed.`<color=cyan>`...The available color names are given in the table below.|Color Name |Hex Value |Swatch ||---------------------------|-----------|----------------------------------||aqua (same as cyan) |#00ffffff | ||black |#000000ff | ||blue |#0000ffff | ||brown |#a52a2aff | ||cyan (same as aqua) |#00ffffff | ||darkblue |#0000a0ff | ||fuchsia (same as magenta) |#ff00ffff | ||green |#008000ff | ||grey |#808080ff | ||lightblue |#add8e6ff | ||lime |#00ff00ff | ||magenta (same as fuchsia) |#ff00ffff | ||maroon |#800000ff | ||navy |#000080ff | ||olive |#808000ff | ||orange |#ffa500ff | ||purple |#800080ff | ||red |#ff0000ff | ||silver |#c0c0c0ff | ||teal |#008080ff | ||white |#ffffffff | ||yellow |#ffff00ff | |_Source : [http : //docs.unity3d.com/Manual/StyledText.html](http://docs.unity3d.com/Manual/StyledText.html)_
# Rust Functions
## BroadcastChat
rust.BroadcastChat(name, message, userid)<br>Broadcast a message ingame<br>userid is used for the avatar, 0 is the server console, see further to know how to get players userID``` luafunction PLUGIN : OnPlayerInit(player) rust.BroadcastChat("SERVER", "Welcome to " ..player.diplayName, "0")end`````` c#void OnPlayerInit(BasePlayer player) {
var message = string.Format("<color=orange>{0}</color> has joined the server", player.displayName);
ConsoleSystem.Broadcast("chat.add", {
player.userID, message, 1f
}
);
}
```
## SendChatMessage
rust.SendChatMessage(player, name, message, userid)<br>Send a message to a player<br>userid is used for the avatar, 0 is the server console, see further to know how to get players userID``` luafunction PLUGIN : OnPlayerSpawn(player) rust.SendChatMessage(player, "SERVER", "You've respawned from a terrible death", "0")end`````` c#void OnPlayerSpawn(BasePlayer player) {
var message = "You've respawned from a terrible death";
player.SendConsoleCommand("chat.add", {
0, message
}
);
}
```
## QuoteSafe
rust.QuoteSafe(message)<br>Add quotes to safely save or send a text``` luarust.QuoteSafe(message)`````` c#message.QuoteSafe();
```
## UserIDFromConnection
rust.UserIDFromConnection(connection)<br>Get the UserID of a player from his connection``` luafunction PLUGIN : CanClientLogin(connection) local playerid = rust.UserIDFromConnection(connection) if(playerid == "76561197961481118") then return "We don't want you on this server Reneb!!!" end -- please don't use this on your server <3
end
```
``` c#
object CanClientLogin(Network.Connection connection)
{
var playerid = connection.userid.ToString();
if(playerid == "76561197961481118")
{
return "We don't want you on this server Reneb!!!";
}
// please don't use this on your server <3
return null;
}
```
## UserIDFromDeployedItem
rust.UserIDFromDeployedItem(deployeditem)<br>
Get the OwnerID of a deployable
``` lua
rust.UserIDFromDeployedItem(deployeditem)
```
``` c#
we need an example here
```
## UserIDFromPlayer
rust.UserIDFromPlayer(player)<br>
Get the UserID of a baseplayer
``` lua
function PLUGIN:Init()
command.AddChatCommand( "steamid", self.Object, "cmdSteamid" )
end
function PLUGIN:cmdSteamid(player,cmd,arg)
rust.SendChatMessage(player,"SERVER","Your SteamID is : " .. rust.UserIDFromPlayer(player), "0")
end
```
``` c#
[ChatCommand("steamid")]
void cmdChatSteamid(BasePlayer player, string command, string[] args)
{
SendReply(player, "Your SteamID is : " + player.userID.ToString());
}
```
## UserIDsFromBuildingPrivlidge
rust.UserIDsFromBuildingPrivlidge(buildingpriv)<br>
Get the UserID of players that have access to a Tool Cupboard<br>
You will see an exemple of this use in the Snippets
## RunServerCommand
rust.RunServerCommand(command, args)<br>
Run a server command
``` lua
rust.RunServerCommand("server.hostname", "New Server Name")
```
## ForcePlayerPosition
rust.ForcePlayerPosition(player, x, y, z)<br>
Teleport a player to a position
``` lua
rust.ForcePlayerPosition(player, x, y, z)
```
``` c#
void ForcePlayerPosition(BasePlayer player, string x, string y, string z)
{
Vector3 destination = new UnityEngine.Vector3();
destination.x = x;
destination.y = y;
destination.z = z;
player.transform.position = destination;
player.ClientRPC(null, player, "ForcePositionTo", new object[] { destination });
player.TransformChanged();
}
```
## PrivateBindingFlag
rust.PrivateBindingFlag()<br>
Usefull to get/set private methods / fields and properties<br>
You will see an exemple of use of this in the Snippets
There are a few functions that have been added to wrap Rust functions, creating aliases of sorts to make your life easier during initial coding as well as during upgrades.
Placeholder text.
# Snippets
## General
### Hello World
``` c#
// Reference: Oxide.Ext.Rust
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Data;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("HelloWorld", "Reneb", 1.0)]
class HelloWorld : RustPlugin
{
void Loaded()
{
Puts("Hello World");
}
}
}
```
``` javascript
We need an example here
```
``` lua
PLUGIN.Name = "Hello World"
PLUGIN.Title = "Hello World"
PLUGIN.Version = V(1, 0, 0)
PLUGIN.Description = "Hello World"
PLUGIN.Author = "Reneb"
PLUGIN.HasConfig = false
function PLUGIN:Init()
print("Hello World")
end
```
``` python
We need an example here
```
### Chat Command
``` c#
// Reference: Oxide.Ext.Rust
using System;
using System.Data;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("HelloYou", "Reneb", 1.0)]
class HelloYou : RustPlugin
{
void Loaded()
{
}
[ChatCommand("helloyou")]
void cmdChatHello(BasePlayer player, string command, string[] args)
{
if (player.net.connection.authLevel < 1)
{
SendReply(player, "You are not allowed to use this command");
return;
}
SendReply(player, "Hello to you too");
}
}
}
```
``` javascript
We need an example here
```
``` lua
PLUGIN.Name = "Hello You"
PLUGIN.Title = "Hello You"
PLUGIN.Version = V(1, 0, 0)
PLUGIN.Description = "Hello You"
PLUGIN.Author = "Reneb"
PLUGIN.HasConfig = false
function PLUGIN:Init()
command.AddChatCommand( "helloyou", self.Object, "cmdHelloyou" )
end
function PLUGIN:cmdHelloyou(player,cmd,args)
if(player:GetComponent("BaseNetworkable").net.connection.authLevel < 1) then
rust.SendChatMessage(player, "You are not allowed to use this command")
return
end
rust.SendChatMessage(player, "Hello to you too")
end
```
``` python
We need an example here
```
## Private fields
### Get a private field
To get a private field you will need:<br>
- Type<br>
- Fieldname<br>
- BindingFlags that point to get NonPublic<br>
``` c#
// Reference: Oxide.Ext.Rust
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Data;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("BuildingPrivileges", "Reneb", 1.0)]
class BuildingPrivileges : RustPlugin
{
private FieldInfo localbuildingPrivileges;
void Loaded()
{
localbuildingPrivileges = typeof(BasePlayer).GetField("buildingPrivlidges", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
}
[ChatCommand("bdp")]
void cmdChatBuildingPrivileges(BasePlayer player, string command, string[] args)
{
if (player.net.connection.authLevel < 1)
{
SendReply(player, "You are not allowed to use this command");
return;
}
var bldprivs = localbuildingPrivileges.GetValue(player) as List<BuildingPrivlidge>;
foreach(BuildingPrivlidge bldpriv in bldprivs)
{
SendReply(player, "Found a Tool Cupboard, getting names of allowed users");
var locAllowed = bldpriv.authorizedPlayers;
foreach( ProtoBuf.PlayerNameID ply in locAllowed )
{
SendReply(player, ply.username);
}
}
}
}
}
```
``` javascript
We need an example here
```
``` lua
PLUGIN.Name = "List of Current Buildings Privileges"
PLUGIN.Title = "List of Current Buildings Privileges"
PLUGIN.Version = V(1, 0, 0)
PLUGIN.Description = "List of Current Buildings Privileges"
PLUGIN.Author = "Reneb"
PLUGIN.HasConfig = false
function PLUGIN:Init()
command.AddChatCommand( "bdp", self.Object, "cmdBuildingPrivileges" )
end
function PLUGIN:cmdTest(player,cmd,args)
-- So first you need to get the field out of BasePlayer type named buildingPrivlidges
-- var = type:GetField("fieldname"),privatefield
-- var is the variable that it will be saved in
-- type is the type of the class
-- fieldname is the private field name you want
-- privatefield is rust.PrivateBindingFlag()
localbuildingPrivileges = global.BasePlayer._type:GetField("buildingPrivlidges", rust.PrivateBindingFlag() )
-- Now we get the value off the player
bldpriv = localbuildingPrivileges:GetValue(player)
-- as buildingPrivlidges is a list you have to read it value by value
for i=0, bldpriv.Count-1 do
rust.SendChatMessage(player,"Found a Tool Cupboard, getting names of allowed users")
locAllowed = bldpriv[i].authorizedPlayers
for u=0, locAllowed.Count-1 do
rust.SendChatMessage(player,locAllowed[u].username)
end
end
end
```
``` python
We need an example here
```
### Set a private field
To set a private field you will need:<br>
- Type<br>
- Fieldname<br>
- BindingFlags that point to get NonPublic<br>
<br>
Notice that from lua you will only be able to set fields that have a value as: string, float or boolean, and of course others that have Vector3, Quaternion, that can be created from Lua.<br>
All others are only accessible via C#
``` c#
// Reference: Oxide.Ext.Rust
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Data;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("AirdropSpecifics", "Reneb", 1.0)]
class AirdropSpecifics : RustPlugin
{
private FieldInfo CPstartPos;
private FieldInfo CPendPos;
private FieldInfo CPdropped;
private FieldInfo CPsecondsToTake;
private FieldInfo CPsecondsTaken;
private MethodInfo CreateEntity;
private Vector3 startPos;
private Vector3 endPos;
private float secondsToTake;
private BaseEntity cargoplane;
void Loaded()
{
startPos = new UnityEngine.Vector3(1000f,200f,1000f);
endPos = new UnityEngine.Vector3(500f,200f,1000f);
secondsToTake = 5f;
CPstartPos = typeof(CargoPlane).GetField("startPos", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
CPendPos = typeof(CargoPlane).GetField("endPos", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
CPdropped = typeof(CargoPlane).GetField("dropped", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
CPsecondsToTake = typeof(CargoPlane).GetField("secondsToTake", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
CPsecondsTaken = typeof(CargoPlane).GetField("secondsTaken", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
}
[ConsoleCommand("airdrop.start")]
void cmdAirdropStart(ConsoleSystem.Arg arg)
{
if (arg.connection != null)
{
if (arg.connection.authLevel < 1)
{
SendReply(arg, "You are not allowed to use this command");
return;
}
}
if(cargoplane != null)
{
cargoplane.KillMessage();
}
cargoplane = GameManager.server.CreateEntity( "events/cargo_plane", new UnityEngine.Vector3() , new UnityEngine.Quaternion() );
if (cargoplane != null)
{
cargoplane.Spawn(true);
CPstartPos.SetValue(cargoplane,startPos);
CPendPos.SetValue(cargoplane,endPos);
CPsecondsToTake.SetValue(cargoplane, secondsToTake);
}
}
}
}
```
``` javascript
We need an example here
```
``` lua
PLUGIN.Title = "Airdrop-Specifics"
PLUGIN.Version = V(1, 0, 0)
PLUGIN.Description = "Set airdrop specifics, from where & to.You can't set the secondsToTake as it's in Int32, no editable via Lua"
PLUGIN.Author = "Reneb"
PLUGIN.HasConfig = false
function PLUGIN:Init()
command.AddConsoleCommand("airdrop.start", self.Object, "ccmdAirDrop")
CreateEntity = global.GameManager._type:GetMethod("CreateEntity")
end
function PLUGIN:OnServerInitialized()
-- Here you will get ALL the fields that you want to set
CPstartPos = global.CargoPlane._type:GetField("startPos", rust.PrivateBindingFlag() )
CPendPos = global.CargoPlane._type:GetField("endPos", rust.PrivateBindingFlag() )
CPdropped = global.CargoPlane._type:GetField("dropped", rust.PrivateBindingFlag() )
-- secondsToTake and secondsTaken are just an exemple and can only be read, not set
CPsecondsToTake = global.CargoPlane._type:GetField("secondsToTake", rust.PrivateBindingFlag() )
CPsecondsTaken = global.CargoPlane._type:GetField("secondsTaken", rust.PrivateBindingFlag() )
-- Here i'm making a static start position and static end position as this is only an exemple, not going to create a full plugin :p
startPos = new( UnityEngine.Vector3._type, nil )
endPos = new( UnityEngine.Vector3._type, nil )
startPos.x = 1000
startPos.y = 200
startPos.z = 1000
endPos.x = 500
endPos.y = 200
endPos.z = 500
end
function PLUGIN:ccmdAirDrop( arg )
if(cargoplane) then
cargoplane:KillMessage()
end
cargoplane = CreateEntity:Invoke( global.GameManager.server, util.TableToArray( { "events/cargo_plane", new( UnityEngine.Vector3._type, nil ) , new( UnityEngine.Quaternion._type, nil ) } ) )
if (cargoplane ~= nil) then
cargoplane:Spawn(true)
-- As you want to EDIT the startPos and endPos, you will have to wait for Rust to create his own, and THEN edit it.
-- So just place the SetValues after.
CPstartPos:SetValue(cargoplane,startPos)
CPendPos:SetValue(cargoplane,endPos)
-- And voila!
end
end
```
``` python
We need an example here
```
# Compiling Source
While you don't need to compile your own Oxide builds, you can! We recommend using one of the [official release builds](http://forum.rustoxide.com/download/) though.
1. Clone the git repository locally.
2. Open the solution in Visual Studio (2013 is recommended, but it should work on earlier versions).
3. Compile the project. If you get errors, it probably means you're missing .NET framework.
<aside class="warning">Keep in mind that only official builds are supported by the Oxide team and community.</aside>