C#:
/*
*
* Copyright © 2025 headtapper
*
* You may not copy, modify, share, distribute, publish, or sell copies of this software.
*
* You may use this plugin for personal use on your own Rust server if you downloaded it from https://codefling.com.
*
* You may not use components of the software's code base for any other purpose.
*
*/
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Configuration;
using UnityEngine;
using Newtonsoft.Json;
namespace Oxide.Plugins
{
[Info("EntityScaler", "headtapper", "1.0.3")]
[Description("Change scale of entities on the spot using a command.")]
public class EntityScaler : RustPlugin
{
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["UnableToFindEntity"] = "<color=#a1fc03>[Entity Scaler]</color> Unable to locate entity.",
["EntityScaled"] = "<color=#a1fc03>[Entity Scaler]</color> Entity {0} scaled to: <color=#a1fc03>{1}x</color>",
["EntityReset"] = "<color=#a1fc03>[Entity Scaler]</color> Entity scale has been reset.",
["ScaleUsage"] = "<color=#a1fc03>[Entity Scaler]</color> Usage: <color=#a1fc03>/scale <amount></color>",
["CheckScale"] = "<color=#a1fc03>[Entity Scaler]</color> Entity scale for <color=#a1fc03>{0}</color>: x: <color=#a1fc03>{1}</color>, y: <color=#a1fc03>{2}</color>, z: <color=#a1fc03>{3}</color>",
["EntityNoData"] = "<color=#a1fc03>[Entity Scaler]</color> No saved data for entity: <color=#a1fc03>{0}</color>",
["EntityScaleReset"] = "<color=#a1fc03>[Entity Scaler]</color> Entity scale reset for: <color=#a1fc03>{0}</color>",
["ResetConfirm"] = "<color=#a1fc03>[Entity Scaler]</color> Type <color=#a1fc03>/resetscaledata confirm</color> to backup and reset the database.",
["ResetSuccess"] = "<color=#a1fc03>[Entity Scaler]</color> Entity Scaler data file has been backed up and reset.",
}, this);
}
#endregion
#region Initialization
private PluginData EntityScaleData { get; set; }
private const string AdminPermission = "entityscaler.admin";
private const string ScaleEntityCommandPermission = "entityscaler.scale";
private const string CheckEntityScaleCommandPermission = "entityscaler.check";
private void Init()
{
permission.RegisterPermission(AdminPermission, this);
permission.RegisterPermission(ScaleEntityCommandPermission, this);
permission.RegisterPermission(CheckEntityScaleCommandPermission, this);
if (!Interface.Oxide.DataFileSystem.ExistsDatafile("EntityScaler"))
{
DynamicConfigFile dataFile = Interface.Oxide.DataFileSystem.GetDatafile("EntityScaler");
dataFile.Save();
}
EntityScaleData = Interface.Oxide.DataFileSystem.ReadObject<PluginData>("EntityScaler");
}
#endregion
#region Data File Management
private void OnServerSave() => SaveDataFile();
private void Unload()
{
SaveDataFile();
}
private void SaveDataFile()
{
Interface.Oxide.DataFileSystem.WriteObject("EntityScaler", EntityScaleData);
}
private void BackupAndResetDataFile()
{
SaveDataFile();
string currentTimestamp = $"{DateTime.Now:yyyy-MM-dd-HH-mm-ss}";
Interface.Oxide.DataFileSystem.WriteObject($"EntityScaler_end_{currentTimestamp}", EntityScaleData);
DynamicConfigFile dataFile = Interface.Oxide.DataFileSystem.GetDatafile("EntityScaler");
dataFile.Clear();
dataFile.Save();
EntityScaleData = Interface.Oxide.DataFileSystem.ReadObject<PluginData>("EntityScaler");
}
#endregion
#region Hooks
private object OnEntityKill(BaseEntity entity)
{
if (entity == null) return null;
if (EntityScaleData.ScaledEntities.ContainsKey(entity.net.ID.Value))
EntityScaleData.ScaledEntities.Remove(entity.net.ID.Value);
return null;
}
private void OnEntitySpawned(BaseEntity entity)
{
if (entity == null) return;
if (!EntityScaleData.ScaledEntities.ContainsKey(entity.net.ID.Value)) return;
PluginData.ScaledEntity savedData = EntityScaleData.ScaledEntities[entity.net.ID.Value];
Vector3 modifiedScale = new Vector3(savedData.ModifiedScaleX, savedData.ModifiedScaleY, savedData.ModifiedScaleZ);
ScaleEntity(entity, entity.transform.localScale, modifiedScale);
}
#endregion
#region Chat Commands
[ChatCommand("scale")]
private void ScaleEntityCommand(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, ScaleEntityCommandPermission) &&
!permission.UserHasPermission(player.UserIDString, AdminPermission)) return;
if (args.Length < 1)
{
player.ChatMessage(lang.GetMessage("ScaleUsage", this, player.UserIDString));
return;
}
if (!float.TryParse(args[0], out float multiplier))
{
player.ChatMessage(lang.GetMessage("ScaleUsage", this, player.UserIDString));
return;
}
BaseEntity entity = GetEntityLookingAt(player);
if (entity == null || entity is BasePlayer)
{
player.ChatMessage(lang.GetMessage("UnableToFindEntity", this, player.UserIDString));
return;
}
Vector3 previousScale = entity.transform.localScale;
Vector3 scale = new Vector3(previousScale.x * multiplier, previousScale.y * multiplier, previousScale.z * multiplier);
ScaleEntity(entity, previousScale, scale);
player.ChatMessage(string.Format(lang.GetMessage("EntityScaled", this, player.UserIDString), entity.ShortPrefabName, multiplier));
}
[ChatCommand("resetscale")]
private void ResetScaleEntityCommand(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, ScaleEntityCommandPermission) &&
!permission.UserHasPermission(player.UserIDString, AdminPermission)) return;
BaseEntity entity = GetEntityLookingAt(player);
if (entity == null || entity is BasePlayer)
{
player.ChatMessage(lang.GetMessage("UnableToFindEntity", this, player.UserIDString));
return;
}
if (!EntityScaleData.ScaledEntities.ContainsKey(entity.net.ID.Value))
{
player.ChatMessage(string.Format(lang.GetMessage("EntityNoData", this, player.UserIDString), entity.ShortPrefabName));
return;
}
PluginData.ScaledEntity savedData = EntityScaleData.ScaledEntities[entity.net.ID.Value];
Vector3 oringialScale = new Vector3(savedData.OriginalScaleX, savedData.OriginalScaleY, savedData.OriginalScaleZ);
ScaleEntity(entity, entity.transform.localScale, oringialScale);
player.ChatMessage(string.Format(lang.GetMessage("EntityScaleReset", this, player.UserIDString), entity.ShortPrefabName));
}
[ChatCommand("checkscale")]
private void CheckScaleEntityCommand(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, CheckEntityScaleCommandPermission) &&
!permission.UserHasPermission(player.UserIDString, AdminPermission)) return;
BaseEntity entity = GetEntityLookingAt(player);
if (entity == null || entity is BasePlayer)
{
player.ChatMessage(lang.GetMessage("UnableToFindEntity", this));
return;
}
Vector3 scale = entity.transform.localScale;
player.ChatMessage(string.Format(lang.GetMessage("CheckScale", this), entity.ShortPrefabName, scale.x, scale.y, scale.z));
}
[ChatCommand("resetscaledata")]
private void backupAndResetCommand(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, AdminPermission)) return;
SaveDataFile();
if (args.Length == 0 || (args[0] != "confirm"))
{
player.ChatMessage(lang.GetMessage("ResetConfirm", this, player.UserIDString));
return;
}
BackupAndResetDataFile();
player.ChatMessage(lang.GetMessage("ResetSuccess", this, player.UserIDString));
}
#endregion
#region Functions
private BaseEntity GetEntityLookingAt(BasePlayer player)
{
if (player == null) return null;
Ray ray = new Ray(player.eyes.position, player.eyes.HeadForward());
if (Physics.Raycast(ray, out RaycastHit hit, 10f))
{
BaseEntity entity = hit.GetEntity();
return entity;
}
return null;
}
private void ScaleEntity(BaseEntity entity, Vector3 previousScale, Vector3 newScale)
{
if (entity == null) return;
if (!EntityScaleData.ScaledEntities.ContainsKey(entity.net.ID.Value))
EntityScaleData.ScaledEntities[entity.net.ID.Value] = new PluginData.ScaledEntity(entity.net.ID.Value, previousScale, newScale);
else
{
EntityScaleData.ScaledEntities[entity.net.ID.Value].ModifiedScaleX = newScale.x;
EntityScaleData.ScaledEntities[entity.net.ID.Value].ModifiedScaleY = newScale.y;
EntityScaleData.ScaledEntities[entity.net.ID.Value].ModifiedScaleZ = newScale.z;
}
entity.networkEntityScale = true;
entity.transform.localScale = newScale;
entity.SendNetworkUpdate();
}
#endregion
#region Entity Scale Data
private class PluginData
{
[JsonProperty("Saved Scaled Entities")]
public Dictionary<ulong, ScaledEntity> ScaledEntities = new Dictionary<ulong, ScaledEntity>();
public class ScaledEntity
{
[JsonProperty("Entity ID")]
public ulong EntityID { get; set; }
[JsonProperty("Original Scale (X)")]
public float OriginalScaleX { get; set; }
[JsonProperty("Original Scale (Y)")]
public float OriginalScaleY { get; set; }
[JsonProperty("Original Scale (Z)")]
public float OriginalScaleZ { get; set; }
[JsonProperty("Modified Scale (X)")]
public float ModifiedScaleX { get; set; }
[JsonProperty("Modified Scale (Y)")]
public float ModifiedScaleY { get; set; }
[JsonProperty("Modified Scale (Z)")]
public float ModifiedScaleZ { get; set; }
public ScaledEntity(ulong entityID, Vector3 originalScale, Vector3 newScale)
{
EntityID = entityID;
OriginalScaleX = originalScale.x;
OriginalScaleY = originalScale.y;
OriginalScaleZ = originalScale.z;
ModifiedScaleX = newScale.x;
ModifiedScaleY = newScale.y;
ModifiedScaleZ = newScale.z;
}
}
}
#endregion
}
}