Fougerite Official

Fougerite Official 1.8.3C

No permission to download
Lots of additions I have to say, so here we go:

MoonSharp Engine (LUA 5.2) was added.
This means you can develope with LUA now, but the plugins only support Fougerite hooks atm. I'm planning to add some sort of Oxide plugin compatibility.​
Patcher was modified.
You should repatch I did some major patching to stabilize the server​
Engine Updates.
Jint,Magma, IronPython is now having an auto command registration feature, which means It will only call the hooks which contains the command that you typed. This register is working 100%, unless the plugin uses custom commands. (Taking the command names out of an INI or a DataStore) Fougerite detects that, and will call all the hooks for that command like It did before. This can be solved by doing:
Code:
Plugin.CommandList.Add(commandname)
at plugin init.

Magma, Jint, MoonSharp received the advanced timer feature which is based on IronPython's.
For Magma and Jint I had to create a variable for that.
Here is the class
To reach this in Magma or Jint:
JavaScript:
function On_PlayerConnected()
{
    var ConnectionData = Plugin.CreateDict();
    ConnectionData["Player"] = Player;
    // Launch a void after 10 seconds
    Plugin.AdvancedTimers.CreateParallelTimer("Connect", 10000, ConnectionData).Start();
}

function ConnectCallback(timer)
{
    timer.Kill();
    var data = timer.Args;
    var player = data["Player"]
    player.Message("I called a timer for you 10 seconds ago!");
}
For Lua:
Code:
function On_PlayerConnected(Player)
    local ConnectionData = Plugin.CreateDict()
    ConnectionData["Player"] = Player
    -- Launch a void after 10 seconds
    Plugin:CreateParallelTimer("Connect", 10000, ConnectionData).Start()
end

function ConnectCallback(timer)
    timer:Kill()
    local data = timer.Args
    local player = data["Player"]
    player:Message("I called a timer for you 10 seconds ago!")
end
Server Class modifications:
I added two lists.
One of them is able to disable calling specific commands for the player. (CommandCancelList)
The 2. one is a list which you can add commands to, and this will also force Fougerite to call all the hooks for the specific command. (ForceCallForCommands)
Class is here
  • Player Property is now available in the InventoryAdd/Remove event
  • Autoban for radiation hackers
  • ClientMove hook for C# users
  • Modified patcher, please re-patch
  • Added an Entity.MaxHealth property
  • Fougerite Ban check/methods are now fixed, and I'm now checking if you are banned OnPlayerApproval event
  • RustPP API got some extras
C#:
        public bool HasPermission(string perm)
        {
            return AdminClass.HasPermission(perm);
        }

        public bool IsAdmin(ulong uid)
        {
            return Administrator.IsAdmin(uid);
        }

        public bool IsAdmin(string name)
        {
            return Administrator.IsAdmin(name);
        }

        public Administrator GetAdmin(ulong userID)
        {
            return Administrator.GetAdmin(userID);
        }

        public Administrator GetAdmin(string name)
        {
            return Administrator.GetAdmin(name);
        }
  • New messages were requested by a user in RustPP, so here It is.
INI:
startermsg=You have spawned a Starter Kit!
startercdmsg=You must wait awhile before using this..
  • Fougerite.dll and RustPP.dll were updated.
  • Fougerite now uses the GlobalBanlist and checks if the player is banned on connection
  • Improved the Ban methods in the Server class
  • RustPP got two new config options (Included in the new config file, Join and Leave message values):
INI:
[Settings]
rust++_enabled=true
chatname=Rust++
help_string1=Chat Commands: /help /location /history /pm /r /players /starter /ping /share /unshare
help_string2=/friends /addfriend /unfriend /about
admin_help_string1=Admin Commands: /addadmin /addflag /addwl /announce /ban /getflags /give /i
admin_help_string2=/god /instako /kick /kill /loadout /mute /reload /saveall /tphere /tpto
admin_help_string3=/unadmin /unban /unfriend /unflag /unmute /location player|all
time=12
airdrop_count=5
starterkit_cooldown=60
shutdown_countdown=60
voice_proximity=true
chat_history_amount=6
keepitems=false
friendly_fire=true
joinmsg=has joined the server
leavemsg=has left the server
default_admin_flags=CanKick|CanTeleport|CanAnnounce|CanGetFlags|CanMute|CanUnmute|Moderator
  • I patched HumanController which bypasses the teleportation hack. Do a repatch. I made a config option in Fougerite.cfg (BanOnInvalidPacket=true) You should update your Fougerite.cfg ... If this option is false, the player will be kicked only.
INI:
[Fougerite]
; uncomment to disable Fougerite, to disable version announce at login,
; or to enable structure and deployed item decay
;enabled=false
;tellversion=false
;deployabledecay=true
;structuredecay=true
;
; Remove players from cache after they disconnect.
RemovePlayersFromCache=false
BanOnInvalidPacket=true

[Modules]
;module = folder
; if a module needs no folder, just use any word, or no word
; you can change folder names to suit your needs
; only modules listed in [Modules] are loaded
; comment out a module to disable it
; Запись должна быть следующего вида: имя_модуля=папка_для_конфигов
; Загружаются только модули, перечисленные в разделе [Modules]
; Закомментируйте строку с плагином чтобы отключить его
RustPP=Rust++
GlitchFix=GlitchFix
MagmaPlugin=Magma
JintPlugin=JsPlugins
IronPythonModule=PyPlugins

[Logging]
; Fougerite logs are in PublicFolder\Logs
; Putting these false will still do the logging, but
; the console won't display them
debug=false
error=true
exception=true
  • Inventory event.. Seems like there is no way to get the looter or the inventory event. Atleast I haven't found one yet. I'm working on it. Same for the airdrop event.
  • Last time I forgot to tell that I created two reflection methods in the Util class, that plugin devs can use.
C#:
        public object GetInstanceField(Type type, object instance, string fieldName)
        {
            BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
                | BindingFlags.Static;
            try
            {
                FieldInfo field = type.GetField(fieldName, bindFlags);
                object v = field.GetValue(instance);
                return v;
            }
            catch (Exception ex)
            {
                Logger.LogError("[Reflection] Failed to get value of " + fieldName + "! " + ex.ToString());
                return null;
            }
        }

        public void SetInstanceField(Type type, object instance, string fieldName, object val)
        {
            BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
                | BindingFlags.Static;
            FieldInfo field = type.GetField(fieldName, bindFlags);
            try
            {
                field.SetValue(instance, val);
            }
            catch (Exception ex)
            {
                Logger.LogError("[Reflection] Failed to set value of " + fieldName + "! " + ex.ToString());
            }
        }
I couldn't fix the Airdrop patching yet.

New Hooks:


SteamDeny. This might make you bad boys :3
Parameter class
Python:
def On_SteamDeny(self, SteamDenyEvent):
        Server.Broadcast(SteamDenyEvent.ClientConnection.UserName + "is failing to connect. " +
                         str(SteamDenyEvent.ErrorNumber))
JavaScript:
function On_SteamDeny(SteamDenyEvent)
{
    Server.Broadcast(SteamDenyEvent.ClientConnection.UserName + "is failing to connect. " +
                         SteamDenyEvent.ErrorNumber);
}
PlayerApproval. Runs before PlayerConnected event.
Parameter class
Python:
def On_PlayerApproval(self, PlayerApprovalEvent):
        Server.Broadcast("About to deny? " + str(PlayerApprovalEvent.AboutToDeny))
JavaScript:
function On_PlayerApproval(PlayerApprovalEvent)
{
    Server.Broadcast("About to deny? " + PlayerApprovalEvent.AboutToDeny);
}
Some other things I did:

Server class
C#:
        public void BanPlayer(Fougerite.Player player)
        {
            IniParser ini = GlobalBanList;
            ini.AddSetting("Ips", player.IP, player.Name);
            ini.AddSetting("Ids", player.SteamID, player.Name);
            ini.AddSetting("NameIps", player.Name, player.IP);
            ini.AddSetting("NameIds", player.Name, player.SteamID);
            ini.Save();
            player.Disconnect();
        }

        public void BanPlayerIP(string ip, string name = "1")
        {
            IniParser ini = GlobalBanList;
            ini.AddSetting("Ips", ip, name);
            ini.AddSetting("NameIps", name, ip);
            ini.Save();
        }

        public void BanPlayerID(string id, string name = "1")
        {
            IniParser ini = GlobalBanList;
            ini.AddSetting("Ids", id, name);
            ini.AddSetting("NameIds", name, id);
            ini.Save();
        }

        public bool IsBannedID(string id)
        {
            IniParser ini = GlobalBanList;
            if (ini.ContainsSetting("Ids", id))
            {
                return true;
            }
            return false;
        }

        public bool IsBannedIP(string ip)
        {
            IniParser ini = GlobalBanList;
            if (ini.ContainsSetting("Ips", ip))
            {
                return true;
            }
            return false;
        }

        public bool UnbanByName(string name)
        {
            var id = ReturnACNByName2(name);
            var ip = ReturnACNByName(name);
            if (id == null)
            {
                return false;
            }
            IniParser ini = GlobalBanList;
            name = id;
            var iprq = ini.GetSetting("NameIps", ip);
            var idrq = ini.GetSetting("NameIds", id);
            ini.DeleteSetting("Ips", iprq);
            ini.DeleteSetting("Ids", idrq);
            ini.DeleteSetting("NameIps", name);
            ini.DeleteSetting("NameIds", name);
            ini.Save();
            return true;
        }

        public bool UnbanByIP(string ip)
        {
            IniParser ini = GlobalBanList;
            if (ini.ContainsSetting("Ips", ip))
            {
                var name = ini.GetSetting("Ips", ip);
                ini.DeleteSetting("Ips", ip);
                ini.DeleteSetting("NameIps", name);
                ini.Save();
                return true;
            }
            return false;
        }

        public bool UnbanByID(string id)
        {
            IniParser ini = GlobalBanList;
            if (ini.ContainsSetting("Ids", id))
            {
                var name = ini.GetSetting("Ids", id);
                ini.DeleteSetting("Ids", id);
                ini.DeleteSetting("NameIds", name);
                ini.Save();
                return true;
            }
            return false;
        }

        public string ReturnACNByName(string name)
        {
            IniParser ini = GlobalBanList;
            string l = name.ToLower();
            var ips = ini.EnumSection("NameIps");
            foreach (string ip in ips)
            {
                string n = ini.GetSetting("NameIps", ip).ToLower();
                if (l.Equals(n))
                {
                    return ip;
                }
            }
            return null;
        }

        public string ReturnACNByName2(string name)
        {
            IniParser ini = GlobalBanList;
            string l = name.ToLower();
            var ids = ini.EnumSection("NameIds");
            foreach (string id in ids)
            {
                string n = ini.GetSetting("NameIds", id).ToLower();
                if (l.Equals(n))
                {
                    return id;
                }
            }
            return null;
        }
  • Screwed the Airdrop event. It's static void, I need to look in It. Repatch. For now I disabled the call of the event.
WARNING. The new source was built on the last release of Rust Legacy Server. (May 01)

Those who had Fougerite installed already, get a fresh Assembly dll file, and use the patcher.


First of all I would like to thank @mikec for keeping up with the last improvements and modifications. Two days ago I started patching, and I received the basic knowlegde from @balu92 and I added a bunch of events.
I made some tweaks / improvements / API additions. I will give you a list below. I might have forgotten some things, I'm concentrating not to forget anything.

Just to clarify at the beginning: Source was moved here.

Engine Modifications:
Jint:
Jint received the reload commands similar to py engine.
jint.load PluginName
jint.unload PluginName
jint.reload PluginName
jint.reload
Magma:
Same for magma:
magma.load PluginName
magma.unload PluginName
magma.reload PluginName
magma.reload
RustPP:
  • /tpto x y z - New command for coords ( I didn't test It :O )
  • Guess what we have here. I added some access to the RustPP API. Which you can Reach at Server.GetRustPPAPI() You can access admins/friends from there. It leads here.
  • I added a Player.Moderator property. It checks if the player has the flag called Moderator (Yea plugin devs, be happy.)
Fougerite:
I made some safety mechanisms. If you use Plugin.Log and It reaches 1 mb file size, It will be renamed, so It won't cause writing lags. (I'm sure It could take more, but I wanted It smooth.)

Same for inis, but they are limited to 0.65 mb and they won't get removed. The Server will just log that you should delete the file.

Global Ini file for banlist:
Server.GlobalBanList

New Hooks:

Navmesh
No, I didn't make a plugin hook for this, only for fougerite. If anyone requests It, I may do It. The purpose of this event was to kill the bugged animals. No more messages like that.
ReceiveNetwork
I made this hook only for CSharp users. Same for this thing, anybody wants this in Py or Js plugins I can do It. But I think this hook won't be used at all. The purpose of this event was to bypass players sending wrong Metabolism properties, causing crash/using hacks.
PlayerTeleport
This hook is for everyone. It gets called when somebody teleports (Uses Fougerite Teleport function) Just incase I'm planning to patch Rust It self, so we can detect all teleportation calls. (Maybe hacks too?)

Python:
def On_PlayerTeleport(self, Player, Vector3From, Vector3To):
    Server.Broadcast(Player.Name + " teleported!")
JavaScript:
function On_PlayerTeleport(Player, Vector3From, Vector3To)
{
    Server.Broadcast(Player.Name + " teleported!");
}
CraftingEvent
Old users were waiting for this a lot since Magma. Now It's here.
Parameter class

Python:
def On_Crafting(self, CraftingEvent):
        CraftingEvent.Player.Message("Time: " + str(CraftingEvent.LastWorkBenchTime))
        if not CraftingEvent.IsLegit:
            Server.Broadcast(CraftingEvent.Player.Name + " is crafting something that he doesn't have!")
            Server.Broadcast("What a n00b hacker!")
            #CraftingEvent.Cancel() - Fougerite cancels the hook by default If It's not legit.
            #CraftingEvent.Player.Disconnect() - Fougerite bans the player automatically
JavaScript:
function On_Crafting(CraftingEvent)
{
    CraftingEvent.Player.Message("Time: " + CraftingEvent.LastWorkBenchTime);
    if (!CraftingEvent.IsLegit)
    {
        Server.Broadcast(CraftingEvent.Player.Name + " is crafting something that he doesn't have!");
        Server.Broadcast("What a n00b hacker!");
        //CraftingEvent.Cancel(); - Fougerite cancels the hook by default If It's not legit.
        //CraftingEvent.Player.Disconnect(); - Fougerite bans the player automatically
    }
}
ResourceSpawn
Called when resource is spawned.
Has a rust parameter, nothing serious.

Python:
def On_ResourceSpawn(self, ResourceTarget):
    Server.Broadcast("Type: " + str(ResourceTarget))
JavaScript:
function On_ResourceSpawn(ResourceTarget)
{
    Server.Broadcast("Type: " + ResourceTarget);
}
ItemAdded
Yaheee. Called when an item is added to an inventory.
(Untested, haha, but should work.)
Parameter class

Python:
def On_ItemAdded(self, InventoryModEvent):
    player = InventoryModEvent.Player # Can be null if he is offline, watch it.
    netuser = InventoryModEvent.NetUser
    item = InventoryModEvent.Item # returns fougerite item https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/EntityItem.cs
    item2 = InventoryModEvent.InventoryItem # returns rust item
    inv = InventoryModEvent.Inventory # returns rust inventory
    inv2 = InventoryModEvent.FInventory # returns fougerite inventory https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/FInventory.cs
    slot = InventoryModEvent.Slot
JavaScript:
function On_ItemAdded(self, InventoryModEvent)
{
    var player = InventoryModEvent.Player; // Can be null if he is offline, watch it.
    var netuser = InventoryModEvent.NetUser;
    var item = InventoryModEvent.Item; // returns fougerite item https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/EntityItem.cs
    var item2 = InventoryModEvent.InventoryItem; // returns rust item
    var inv = InventoryModEvent.Inventory; // returns rust inventory
    var inv2 = InventoryModEvent.FInventory; // returns fougerite inventory https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/FInventory.cs
    var slot = InventoryModEvent.Slot;
}
ItemRemoved
Same parameter, same properties, different event.

Python:
def On_ItemRemoved(self, InventoryModEvent):
    player = InventoryModEvent.Player # Can be null if he is offline, watch it.
    netuser = InventoryModEvent.NetUser
    item = InventoryModEvent.Item # returns fougerite item https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/EntityItem.cs
    item2 = InventoryModEvent.InventoryItem # returns rust item
    inv = InventoryModEvent.Inventory # returns rust inventory
    inv2 = InventoryModEvent.FInventory # returns fougerite inventory https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/FInventory.cs
    slot = InventoryModEvent.Slot
JavaScript:
function On_ItemRemoved(self, InventoryModEvent)
{
    var player = InventoryModEvent.Player; // Can be null if he is offline, watch it.
    var netuser = InventoryModEvent.NetUser;
    var item = InventoryModEvent.Item; // returns fougerite item https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/EntityItem.cs
    var item2 = InventoryModEvent.InventoryItem; // returns rust item
    var inv = InventoryModEvent.Inventory; // returns rust inventory
    var inv2 = InventoryModEvent.FInventory; // returns fougerite inventory https://github.com/dretax/DX-Fougerite/blob/master/Fougerite/Fougerite/FInventory.cs
    var slot = InventoryModEvent.Slot;
}
Airdrop
Called when airdrop is coming. Has a location parameter.

Python:
def On_Airdrop(self, Vector3):
    Server.Broadcast("Airdrop inbound to: " + str(Vector3))
JavaScript:
function On_Airdrop(Vector3)
{
    Server.Broadcast("Airdrop inbound to: " + Vector3);
}
Hopefully I covered them all, but I'm sure I missed some other stuffs out.
I'm gonna be adding 2-3 new hooks too later.
  • Just realised that the modification I made in disconnect event doesn't let you to use the properties of the player, so this fix will work for It. (Removing player from Server.Players after I called all the disconnect hooks)
  • HurtEvent now detects Radiation suicide hack, and bypasses It
  • Sleeper property got a Destroy() function (UnTested)
  • RustPP's /addadmin command was fixed
  • Fixed IsOnline property, now It works 100%
  • Added IsOnline check to Player.AdjustPoisonLevel
  • Server.Cache and OnConnected event tweaks
  • Util.GetDooratCoords and Util.GetEntityatCoords fixes
  • Most of the Hooks are now taking the player out of the Server.Cache instead of doing a for cycle or a Query to find the player (Only PlayerGathering doesn't use It yet.)
  • GlitchFix got some tweaks