AutoRadioManager/AutoRadioManager.cs

542 lines
21 KiB
C#
Raw Permalink Normal View History

2025-03-16 15:13:31 +00:00
using Newtonsoft.Json;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Oxide.Plugins
{
2025-03-17 10:35:42 +00:00
[Info("Auto Radio Manager", "RustySats", "1.0.1")]
2025-03-16 15:13:31 +00:00
[Description("Automatically manages boomboxes in your Rust server with various configuration options")]
public class AutoRadioManager : RustPlugin
{
#region Configuration
private Configuration config;
public class Configuration
{
[JsonProperty("Radio Stream URL")]
public string RadioStreamUrl = "https://radio.goodmorningbitcoin.com/listen/goodmorningbitcoin/radio.mp3";
[JsonProperty("Additional Radio Stations (name,url format)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, string> AdditionalRadioStations = new Dictionary<string, string>
{
{ "Good Morning Bitcoin", "https://radio.goodmorningbitcoin.com/listen/goodmorningbitcoin/radio.mp3" }
};
[JsonProperty("Enable for deployed boomboxes")]
public bool EnableForDeployed = false;
[JsonProperty("Enable for handheld boomboxes")]
public bool EnableForHandheld = true;
[JsonProperty("Enable for static/monument boomboxes")]
public bool EnableForStatic = true;
[JsonProperty("Auto-restart interval (minutes)")]
public int AutoRestartInterval = 60;
[JsonProperty("Enable auto-restart")]
public bool EnableAutoRestart = true;
[JsonProperty("Turn on radios after server restart")]
public bool TurnOnAfterServerRestart = true;
2025-03-17 10:35:42 +00:00
[JsonProperty("Debug mode")]
public bool DebugMode = false;
2025-03-16 15:13:31 +00:00
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null)
{
throw new JsonException();
}
SaveConfig();
}
catch
{
PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
Config.WriteObject(config, true);
Puts($"Configuration saved to {Name}.json");
}
#endregion
#region Fields
private Timer autoRestartTimer;
private string originalServerUrlList;
#endregion
#region Oxide Hooks
private void Init()
{
// Initialize any necessary resources
Puts("Auto Radio Manager initialized");
// Store the original server URL list for restoration on unload
originalServerUrlList = BoomBox.ServerUrlList;
}
private void OnServerInitialized()
{
// Update the server URL list with additional radio stations
UpdateServerUrlList();
// Start the auto-restart timer if enabled
if (config.EnableAutoRestart)
{
StartAutoRestartTimer();
}
// Turn on all radios after server restart if enabled
if (config.TurnOnAfterServerRestart)
{
// Use a slight delay to ensure all entities are fully loaded
timer.Once(5f, () => TurnOnAllRadios());
}
}
private void OnEntitySpawned(DeployableBoomBox boombox)
{
if (!config.EnableForDeployed || boombox == null)
return;
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Deployable boombox spawned: {boombox}");
2025-03-16 15:13:31 +00:00
// Use a slight delay to ensure the entity is fully initialized
timer.Once(0.5f, () => {
if (boombox != null && boombox.BoxController != null)
SetBoomboxRadioIP(boombox.BoxController);
});
}
private void OnEntitySpawned(HeldBoomBox boombox)
{
if (!config.EnableForHandheld || boombox == null)
return;
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Handheld boombox spawned: {boombox}");
2025-03-16 15:13:31 +00:00
// Use a slight delay to ensure the entity is fully initialized
timer.Once(0.5f, () => {
if (boombox != null && boombox.BoxController != null)
SetBoomboxRadioIP(boombox.BoxController);
});
}
private void OnEntitySpawned(BoomBox boombox)
{
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: BoomBox entity spawned: {boombox}, Type: {boombox?.GetType().Name}");
2025-03-16 15:13:31 +00:00
if (!config.EnableForStatic || boombox == null)
return;
// Use a slight delay to ensure the entity is fully initialized
timer.Once(0.5f, () => {
2025-03-17 10:35:42 +00:00
if (boombox != null)
{
bool isStatic = IsStaticBoombox(boombox);
if (config.DebugMode)
Puts($"DEBUG: IsStaticBoombox result: {isStatic} for {boombox}");
if (isStatic)
SetBoomboxRadioIP(boombox);
}
2025-03-16 15:13:31 +00:00
});
}
void Unload()
{
// Clean up the timer when the plugin is unloaded
if (autoRestartTimer != null)
{
autoRestartTimer.Destroy();
autoRestartTimer = null;
}
// Restore the original server URL list
BoomBox.ServerUrlList = originalServerUrlList;
if (BoomBox.ServerValidStations != null && !string.IsNullOrEmpty(originalServerUrlList))
{
BoomBox.ServerValidStations.Clear();
Server.Command($"BoomBox.ServerUrlList \"{originalServerUrlList}\"");
}
Puts("Auto Radio Manager unloaded");
}
#endregion
#region Methods
private void UpdateServerUrlList()
{
if (config.AdditionalRadioStations == null || config.AdditionalRadioStations.Count == 0)
{
Puts("No additional radio stations configured");
return;
}
List<string> stationEntries = new List<string>();
// Process additional radio stations from config
foreach (var station in config.AdditionalRadioStations)
{
string entry = $"{station.Key},{station.Value}";
stationEntries.Add(entry);
}
if (stationEntries.Count > 0)
{
// Clear existing stations if needed
if (BoomBox.ServerValidStations != null)
{
BoomBox.ServerValidStations.Clear();
}
// Build the comma-separated list for the server
string urlList = string.Join(",", stationEntries);
// Apply the list through server command
Server.Command($"BoomBox.ServerUrlList \"{urlList}\"");
Puts($"Added {stationEntries.Count} additional radio stations to server list");
}
}
2025-03-17 10:35:42 +00:00
// Fixed method to identify static boomboxes based on name
2025-03-16 15:13:31 +00:00
private bool IsStaticBoombox(BoomBox boombox)
{
2025-03-17 10:35:42 +00:00
if (boombox == null)
return false;
if (config.DebugMode)
2025-03-16 15:13:31 +00:00
{
2025-03-17 10:35:42 +00:00
Puts($"DEBUG: Checking if {boombox} is static. Type: {boombox.GetType().Name}");
// Debug the hierarchy
if (boombox.GetComponentInParent<DeployableBoomBox>() != null)
Puts($"DEBUG: Has DeployableBoomBox parent");
if (boombox.GetComponentInParent<HeldBoomBox>() != null)
Puts($"DEBUG: Has HeldBoomBox parent");
2025-03-16 15:13:31 +00:00
2025-03-17 10:35:42 +00:00
// Log entity name if available
if (boombox.baseEntity != null)
2025-03-16 15:13:31 +00:00
{
2025-03-17 10:35:42 +00:00
Puts($"DEBUG: Entity name: {boombox.baseEntity.name}");
Puts($"DEBUG: Owner ID: {boombox.baseEntity.OwnerID}");
2025-03-16 15:13:31 +00:00
}
2025-03-17 10:35:42 +00:00
}
// Check if the name contains "static" - this is the most reliable way to identify them
if (boombox.baseEntity != null && boombox.baseEntity.name != null)
{
string entityName = boombox.baseEntity.name.ToLower();
if (entityName.Contains("static"))
{
if (config.DebugMode)
Puts($"DEBUG: Identified as static by name: {entityName}");
return true;
}
}
// The original method wasn't reliable, so we'll skip parent component checks
// As a fallback, use the owner ID check
if (boombox.baseEntity != null && boombox.baseEntity.OwnerID == 0)
{
// For additional safety, make sure it's not already counted as handheld
var handhelds = UnityEngine.Object.FindObjectsOfType<HeldBoomBox>();
2025-03-16 15:13:31 +00:00
foreach (var handheld in handhelds)
{
2025-03-17 10:35:42 +00:00
if (handheld != null && handheld.BoxController == boombox)
return false; // It's already identified as handheld
2025-03-16 15:13:31 +00:00
}
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Identified as static by having no owner");
2025-03-16 15:13:31 +00:00
2025-03-17 10:35:42 +00:00
return true;
2025-03-16 15:13:31 +00:00
}
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Not identified as static");
return false;
2025-03-16 15:13:31 +00:00
}
private void SetBoomboxRadioIP(BoomBox box)
{
if (box == null) return;
try
{
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Setting radio IP for {box}");
2025-03-16 15:13:31 +00:00
// Set the radio IP to the configured stream URL
box.CurrentRadioIp = config.RadioStreamUrl;
// Notify clients of the change
box.baseEntity.ClientRPC<string>(null, "OnRadioIPChanged", box.CurrentRadioIp);
// Turn on the radio
box.SetFlag(BaseEntity.Flags.On, true);
box.baseEntity.SendNetworkUpdate();
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Radio configured successfully for {box}");
2025-03-16 15:13:31 +00:00
}
catch (Exception ex)
{
PrintError($"Error setting boombox radio IP: {ex.Message}");
}
}
private void StartAutoRestartTimer()
{
// Destroy any existing timer
if (autoRestartTimer != null)
{
autoRestartTimer.Destroy();
autoRestartTimer = null;
}
// Validate interval (minimum 1 minute)
int interval = Math.Max(1, config.AutoRestartInterval);
// Create a new timer with the configured interval
autoRestartTimer = timer.Every(interval * 60f, RestartAllRadios);
Puts($"Auto-restart timer started with interval of {interval} minutes");
}
private void TurnOnAllRadios()
{
Puts("Turning on all radios...");
int deployedCount = 0;
int handheldCount = 0;
int staticCount = 0;
try
{
// Find all deployed boomboxes
if (config.EnableForDeployed)
{
var deployables = UnityEngine.Object.FindObjectsOfType<DeployableBoomBox>();
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Found {deployables.Length} deployable boomboxes");
2025-03-16 15:13:31 +00:00
foreach (var deployable in deployables)
{
if (deployable != null && deployable.BoxController != null)
{
2025-03-17 10:35:42 +00:00
// Skip if this is a static boombox incorrectly identified as deployed
if (deployable.BoxController.baseEntity != null &&
deployable.BoxController.baseEntity.name != null &&
deployable.BoxController.baseEntity.name.ToLower().Contains("static"))
{
if (config.DebugMode)
Puts($"DEBUG: Skipping static boombox incorrectly identified as deployed: {deployable.BoxController.baseEntity.name}");
continue;
}
2025-03-16 15:13:31 +00:00
SetBoomboxRadioIP(deployable.BoxController);
deployedCount++;
}
}
}
// Find all handheld boomboxes
if (config.EnableForHandheld)
{
var handhelds = UnityEngine.Object.FindObjectsOfType<HeldBoomBox>();
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Found {handhelds.Length} handheld boomboxes");
2025-03-16 15:13:31 +00:00
foreach (var handheld in handhelds)
{
if (handheld != null && handheld.BoxController != null)
{
SetBoomboxRadioIP(handheld.BoxController);
handheldCount++;
}
}
}
// Find all static boomboxes
if (config.EnableForStatic)
{
var allBoomboxes = UnityEngine.Object.FindObjectsOfType<BoomBox>();
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Found {allBoomboxes.Length} total boomboxes of all types");
// First, find all boomboxes with "static" in their name
2025-03-16 15:13:31 +00:00
foreach (var boombox in allBoomboxes)
{
2025-03-17 10:35:42 +00:00
if (boombox != null && boombox.baseEntity != null &&
boombox.baseEntity.name != null &&
boombox.baseEntity.name.ToLower().Contains("static"))
2025-03-16 15:13:31 +00:00
{
2025-03-17 10:35:42 +00:00
if (config.DebugMode)
Puts($"DEBUG: Found static boombox by name: {boombox.baseEntity.name}");
2025-03-16 15:13:31 +00:00
SetBoomboxRadioIP(boombox);
staticCount++;
}
}
2025-03-17 10:35:42 +00:00
// If no static boomboxes were found by name, try other methods
if (staticCount == 0)
{
foreach (var boombox in allBoomboxes)
{
if (boombox != null && boombox.baseEntity != null &&
boombox.baseEntity.OwnerID == 0)
{
// Make sure it's not already handled as handheld or deployed
bool isHandheld = false;
bool isDeployed = false;
var handhelds = UnityEngine.Object.FindObjectsOfType<HeldBoomBox>();
foreach (var handheld in handhelds)
{
if (handheld != null && handheld.BoxController == boombox)
{
isHandheld = true;
break;
}
}
if (!isHandheld)
{
var deployables = UnityEngine.Object.FindObjectsOfType<DeployableBoomBox>();
foreach (var deployable in deployables)
{
if (deployable != null && deployable.BoxController == boombox)
{
isDeployed = true;
break;
}
}
}
if (!isHandheld && !isDeployed)
{
if (config.DebugMode)
Puts($"DEBUG: Found static boombox by elimination: {boombox}");
SetBoomboxRadioIP(boombox);
staticCount++;
}
}
}
}
2025-03-16 15:13:31 +00:00
}
Puts($"Turned on {deployedCount} deployed, {handheldCount} handheld, and {staticCount} static boomboxes");
}
catch (Exception ex)
{
PrintError($"Error in TurnOnAllRadios: {ex.Message}");
}
}
private void RestartAllRadios()
{
Puts("Auto-restarting all radios...");
int deployedCount = 0;
int handheldCount = 0;
int staticCount = 0;
try
{
// First turn off all radios
// Deployed boomboxes
if (config.EnableForDeployed)
{
var deployables = UnityEngine.Object.FindObjectsOfType<DeployableBoomBox>();
foreach (var deployable in deployables)
{
2025-03-17 10:35:42 +00:00
// Skip if this is a static boombox incorrectly identified as deployed
if (deployable != null && deployable.BoxController != null &&
deployable.BoxController.baseEntity != null &&
deployable.BoxController.baseEntity.name != null &&
deployable.BoxController.baseEntity.name.ToLower().Contains("static"))
{
continue;
}
2025-03-16 15:13:31 +00:00
if (deployable != null && deployable.BoxController != null)
{
deployable.BoxController.SetFlag(BaseEntity.Flags.On, false);
deployable.BoxController.baseEntity.SendNetworkUpdate();
deployedCount++;
}
}
}
// Handheld boomboxes
if (config.EnableForHandheld)
{
var handhelds = UnityEngine.Object.FindObjectsOfType<HeldBoomBox>();
foreach (var handheld in handhelds)
{
if (handheld != null && handheld.BoxController != null)
{
handheld.BoxController.SetFlag(BaseEntity.Flags.On, false);
handheld.BoxController.baseEntity.SendNetworkUpdate();
handheldCount++;
}
}
}
// Static boomboxes
if (config.EnableForStatic)
{
var allBoomboxes = UnityEngine.Object.FindObjectsOfType<BoomBox>();
foreach (var boombox in allBoomboxes)
{
2025-03-17 10:35:42 +00:00
if (boombox != null && boombox.baseEntity != null &&
boombox.baseEntity.name != null &&
boombox.baseEntity.name.ToLower().Contains("static"))
2025-03-16 15:13:31 +00:00
{
boombox.SetFlag(BaseEntity.Flags.On, false);
boombox.baseEntity.SendNetworkUpdate();
staticCount++;
}
}
}
Puts($"Turned off {deployedCount} deployed, {handheldCount} handheld, and {staticCount} static boomboxes");
// Wait a short delay to ensure they're all off
timer.Once(2f, () => {
Puts("Turning radios back on...");
TurnOnAllRadios();
});
}
catch (Exception ex)
{
PrintError($"Error in RestartAllRadios: {ex.Message}");
}
}
#endregion
}
}