C#:
// Reference: 0Harmony
/*
▄▄▄▄ ███▄ ▄███▓ ▄████ ▄▄▄██▀▀▀▓█████▄▄▄█████▓
▓█████▄ ▓██▒▀█▀ ██▒ ██▒ ▀█▒ ▒██ ▓█ ▀▓ ██▒ ▓▒
▒██▒ ▄██▓██ ▓██░▒██░▄▄▄░ ░██ ▒███ ▒ ▓██░ ▒░
▒██░█▀ ▒██ ▒██ ░▓█ ██▓▓██▄██▓ ▒▓█ ▄░ ▓██▓ ░
░▓█ ▀█▓▒██▒ ░██▒░▒▓███▀▒ ▓███▒ ░▒████▒ ▒██▒ ░
░▒▓███▀▒░ ▒░ ░ ░ ░▒ ▒ ▒▓▒▒░ ░░ ▒░ ░ ▒ ░░
▒░▒ ░ ░ ░ ░ ░ ░ ▒ ░▒░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░
*/
using Harmony;
using System;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("EdgeProtection", "bmgjet", "1.0.2")]
[Description("Teleports Player At Edge Of Map Instead Of Killing Them")]
class EdgeProtection : RustPlugin
{
private HarmonyInstance _harmony; //Harmony Instance
public static EdgeProtection _plugin; //Self Reference
//Config
private PluginConfig config;
protected override void LoadDefaultConfig() { Config.WriteObject(GetDefaultConfig(), true); }
private PluginConfig GetDefaultConfig()
{
return new PluginConfig
{
EdgeDistance = 100, //How far from edge to trigger
MoveMultiplyer = -0.996f, //How far to move from edge on other side of map
TickRate = 0.5f, //How often to check position
};
}
private class PluginConfig
{
public int EdgeDistance;
public float MoveMultiplyer;
public float TickRate;
}
//Oxide Hooks
private void Init()
{
_plugin = this;
config = Config.ReadObject<PluginConfig>(); //Load Config
_harmony = HarmonyInstance.Create(Name + "PATCH"); //Create Harmony Patch
Type patch = AccessTools.Inner(typeof(EdgeProtection), "TerrainMeta_OutOfMargin");
new PatchProcessor(_harmony, patch, HarmonyMethod.Merge(patch.GetHarmonyMethods())).Patch();
}
private void OnServerInitialized()
{
foreach (BasePlayer player in BasePlayer.activePlayerList) //Check player list and apply
{
if (player != null && !player.IsNpc && !player.IsSleeping())
{
if (!player.HasComponent<EdgeTeleport>()) { player.gameObject.AddComponent<EdgeTeleport>(); }
}
}
}
private void Unload() //Unload what plugin has spawned
{
foreach (BasePlayer player in BasePlayer.allPlayerList) //Remove from all players
{
if (player != null && !player.IsNpc)
{
EdgeTeleport edgeProtection = player.GetComponent<EdgeTeleport>();
if (edgeProtection != null) { edgeProtection.RemoveMe(); }
}
}
_harmony.UnpatchAll(Name + "PATCH"); //Unpatch Harmony
}
void OnPlayerSleepEnd(BasePlayer player)
{
if (!player.IsNpc)
{
//Attach componant to players
if (!player.HasComponent<EdgeTeleport>()) { player.gameObject.AddComponent<EdgeTeleport>(); }
}
}
void OnPlayerSleep(BasePlayer player)
{
if (!player.IsNpc)
{
//Remove componant from players
EdgeTeleport edgeProtection = player.GetComponent<EdgeTeleport>();
if (edgeProtection != null) { edgeProtection.RemoveMe(); }
}
}
//Harmony Hook
[HarmonyPatch(typeof(TerrainMeta), "OutOfMargin", typeof(Vector3))]
public static class
TerrainMeta_OutOfMargin //Extends the limits of the kill zone to the max allowed by default network grid
{
[HarmonyPrefix]
private static bool a(Vector3 worldPos, ref bool __result)
{
//Simplify the bounds checks, You near edge of network grid you die
if (worldPos.x > -4096 && worldPos.x < 4096 && worldPos.z > -4096 && worldPos.z < 4096)
{
__result = false;
return false;
}
__result = true;
return false;
}
}
//Class
public class EdgeTeleport : MonoBehaviour
{
private BasePlayer player;
private float delay = 0;
private void Awake()
{
player = GetComponent<BasePlayer>();
if (player == null) { Destroy(this); } //No player so remove
delay = UnityEngine.Time.time + UnityEngine.Random.Range(1,3); //Setup start delay
}
public void RemoveMe() => Destroy(this); //Remove componant function
public void FixedUpdate()
{
if (delay >= Time.time) //Delay so doesnt fire check every 50hz
{
return; //Cancel since not waited long enough
}
if (player == null || player.IsSleeping()) { Destroy(this); } //Player is disconnected or sleeping
delay = Time.time + _plugin.config.TickRate; //Set up next scan
try
{
//Check if close enough to edge to trigger
if (OutOfMap(player.transform))
{
//Set position to move to as custom position
Vector3 pos = new Vector3(player.transform.position.x * _plugin.config.MoveMultiplyer, player.transform.position.y, player.transform.position.z * _plugin.config.MoveMultiplyer);
float height = TerrainMeta.HeightMap.GetHeight(pos);
if (pos.y <= height) { pos.y = height + 0.1f; }
if (player.HasParent())
{
//Has Parent (walking on a tug)
BaseEntity baseenty = player.GetParentEntity();
if (baseenty != null && !(baseenty is CargoShip)) //Dont teleport cargoships
{
baseenty.transform.position = pos;
baseenty.SendNetworkUpdateImmediate();
}
}
else if (player.isMounted)
{
//Is mounted so move parent
BaseEntity baseenty = player.GetMountedVehicle();
baseenty.transform.position = pos;
baseenty.SendNetworkUpdateImmediate();
}
else
{
//Walking player so teleport them and disable ground fall as moving.
player.RemoveFromTriggers();
player.SetServerFall(true);
player.Teleport(pos);
player.SetServerFall(false);
player.ForceUpdateTriggers();
}
}
}
catch { }
}
private bool OutOfMap(Transform ent)
{
//Check world bounds at distance set in config
//Check at 4 axis
return (!ValidBounds.Test(ent.position + ent.forward * _plugin.config.EdgeDistance) ||
!ValidBounds.Test(ent.transform.position + ent.transform.forward * -_plugin.config.EdgeDistance) ||
!ValidBounds.Test(ent.transform.position + ent.transform.right * -_plugin.config.EdgeDistance) ||
!ValidBounds.Test(ent.transform.position + ent.transform.right * _plugin.config.EdgeDistance));
}
}
}
}