C#:
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("FixBlock", "Night[EXE]", "1.0.1")]
class FixBlock : RustPlugin
{
int waterLevel = 10;
int maxHeight = 25;
bool caveBuild = true;
bool roadRestrict = true;
bool adminIgnore = false;
float treeRadius = 2f;
private void LoadDefaultConfig()
{
GetConfig("Основные настройки", "Запрещать строительство глубже n метров", ref waterLevel);
GetConfig("Основные настройки", "Запрещать строительство выше n метров", ref maxHeight);
GetConfig("Основные настройки", "Разрешить строительство в пещерах", ref caveBuild);
GetConfig("Основные настройки", "Запрещать строительство на дорогах", ref roadRestrict);
GetConfig("Основные настройки", "Игнорировать админов", ref adminIgnore);
GetConfig("Основные настройки", "Минимальный радиус от дерева", ref treeRadius);
SaveConfig();
}
private void GetConfig<T>(string MainMenu, string Key, ref T var)
{
if (Config[MainMenu, Key] != null)
{
var = (T)Convert.ChangeType(Config[MainMenu, Key], typeof(T));
}
Config[MainMenu, Key] = var;
}
private int worldLayer = LayerMask.GetMask("World", "Default", "Terrain");
private void OnEntityBuilt(Planner planner, GameObject gameObject)
{
if (planner == null || gameObject == null) return;
BasePlayer player = planner.GetOwnerPlayer();
if (player.IsAdmin && adminIgnore) return;
if (player == null) return;
int MaxHeight = -1;
RaycastHit hitInfo;
BaseEntity entity = gameObject.GetComponent<BaseEntity>();
if (MaxHeight > 0 && Physics.Raycast(new Ray(entity.transform.position, Vector3.down), out hitInfo, float.PositiveInfinity, Rust.Layers.Terrain))
{
if (hitInfo.distance > MaxHeight)
{
Refund(player, entity);
SendReply(player, "<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строение запрещенно!\nВаши ресурсы были возращенны!");
entity.Kill();
return;
}
}
Vector3 pos = entity.GetNetworkPosition();
if (roadRestrict)
{
RaycastHit hit;
if (Physics.Raycast(pos , Vector3.down, out hit, worldLayer))
{
if (hit.transform.name == "Road Mesh")
{
Refund(player, entity);
SendReply(player, "<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строительство на дорогах запрещено!\nВаши ресурсы были возращенны!");
entity.Kill();
return;
}
}
}
if (pos.y < -waterLevel) if (caveBuild) return; else
{
Refund(player, entity);
SendReply(player,"<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строительство глубже {0} метров запрещено!\nВаши ресурсы были возращенны!", waterLevel);
entity.Kill();
return;
}
if (TerrainMeta.WaterMap.GetHeight(pos) - pos.y > waterLevel)
{
Refund(player, entity);
SendReply(player,"<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строительство глубже {0} метров запрещено!\nВаши ресурсы были возращенны!", waterLevel);
entity.Kill();
return;
}
if (pos.y - TerrainMeta.HeightMap.GetHeight(pos) > maxHeight)
{
Refund(player, entity);
SendReply(player, "<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строительство выше {0} метров запрещено!\nВаши ресурсы были возращенны!", maxHeight);
entity.Kill();
return;
}
if (treeRadius > 0 && entity.ShortPrefabName.Contains("foundation"))
{
List<TreeEntity> treeList = new List<TreeEntity>();
Vis.Entities(pos, treeRadius, treeList, LayerMask.GetMask("Tree"), QueryTriggerInteraction.Ignore);
if (treeList.Count > 0)
{
SendReply(player, "<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строительство рядом с деревьями в радиусе {0}м. запрещено!\nВаши ресурсы были возращенны!", (int)treeRadius);
Refund(player, entity);
entity.Kill();
return;
}
}
CheckEntity(entity, player);
}
private void OnItemDeployed(Deployer deployer, BaseEntity entity)
{
BasePlayer player = deployer.GetOwnerPlayer();
if (player != null)
{
CheckEntity(entity, player);
}
}
private void CheckEntity(BaseEntity entity, BasePlayer player)
{
if (entity != null)
{
RaycastHit[] targets = Physics.RaycastAll(new Ray(entity.transform.position + Vector3.up * 200f, Vector3.down), 250, worldLayer);
foreach (RaycastHit hit in targets)
{
MeshCollider collider = hit.collider.GetComponent<MeshCollider>();
if (collider == null || !collider.sharedMesh.name.StartsWith("rock_") || !IsInside(hit.collider, entity) && (false|| !IsInCave(entity))) continue;
Refund(player, entity);
SendReply(player, "<color=#483D8B>[УВЕДОМЛЕНИЕ]:</color> Строение запрещенно!\nВаши ресурсы были возращенны!");
entity.Kill();
break;
}
}
}
private bool IsInCave(BaseEntity entity)
{
RaycastHit[] targets = Physics.RaycastAll(new Ray(entity.transform.position, Vector3.up), 250, worldLayer);
foreach (RaycastHit hit in targets)
{
if (hit.collider.name.StartsWith("rock_")) return true;
}
return false;
}
private static bool IsInside(Collider collider, BaseEntity entity)
{
Vector3 point = entity.WorldSpaceBounds().ToBounds().max;
Vector3 center = collider.bounds.center;
Vector3 direction = center - point;
Ray ray = new Ray(point, direction);
RaycastHit hitInfo;
return !collider.Raycast(ray, out hitInfo, direction.magnitude + 1);
}
void Refund(BasePlayer player, BaseEntity entity)
{
RefundHelper.Refund(player, entity);
}
public static class RefundHelper
{
private static Dictionary<uint, Dictionary<ItemDefinition, int>> refundItems =
new Dictionary<uint, Dictionary<ItemDefinition, int>>();
public static void Refund(BasePlayer player, BaseEntity entity, float percent = 1)
{
StorageContainer storage = entity as StorageContainer;
if (storage)
{
for (int i = storage.inventory.itemList.Count - 1; i >= 0; i--)
{
var item = storage.inventory.itemList[i];
if (item == null) continue;
item.amount = (int)(item.amount * percent);
float single = 20f;
Vector3 vector32 = Quaternion.Euler(UnityEngine.Random.Range(-single * 0.5f, single * 0.5f), UnityEngine.Random.Range(-single * 0.5f, single * 0.5f), UnityEngine.Random.Range(-single * 0.5f, single * 0.5f)) * Vector3.up;
BaseEntity baseEntity = item.Drop(storage.transform.position + (Vector3.up * 1f), vector32 * UnityEngine.Random.Range(5f, 10f), UnityEngine.Random.rotation);
baseEntity.SetAngularVelocity(UnityEngine.Random.rotation.eulerAngles * 5f);
}
}
BuildingBlock block = entity as BuildingBlock;
if (block != null)
{
try
{
if (block.currentGrade == null) return;
foreach (var item in block.currentGrade.costToBuild)
{
var amount = (int)(item.amount * (Mathf.Approximately(percent, -1) ? 0.5f : percent));
if (amount < 1) amount = 1;
player.GiveItem(ItemManager.Create(item.itemDef, amount, 0));
}
}
catch
{
}
return;
}
Dictionary<ItemDefinition, int> items;
if (refundItems.TryGetValue(entity.prefabID, out items))
{
foreach (var item in items)
if (item.Value > 0)
player.GiveItem(ItemManager.Create(item.Key, (int)(item.Value)));
}
}
private static void InitRefundItems()
{
foreach (var item in ItemManager.itemList)
{
var deployable = item.GetComponent<ItemModDeployable>();
if (deployable != null)
{
if (item.Blueprint == null || deployable.entityPrefab == null) continue;
refundItems.Add(deployable.entityPrefab.resourceID, item.Blueprint.ingredients.ToDictionary(p => p.itemDef, p => ((int)p.amount)));
}
}
}
}
}
}