using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Logging;
using FishNet.Managing.Server;
using FishNet.Object;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace KickMod;
[BepInPlugin("com.trae.kick", "Host Kick Menu", "1.0.0")]
public class KickPlugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
internal static ConfigEntry<KeyCode> KeyToggle;
private void Awake()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
KeyToggle = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)288, "打开玩家管理面板的按键");
GameObject val = new GameObject("KickModRunner");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<KickRunner>();
Log.LogInfo((object)("[KickMod] 已加载。按 " + ((object)KeyToggle.Value/*cast due to .constrained prefix*/).ToString() + " 打开玩家管理面板(仅房主可用)"));
}
}
internal class KickRunner : MonoBehaviour
{
private bool _show;
private Rect _win = new Rect((float)Screen.width * 0.35f, (float)Screen.height * 0.25f, 420f, 400f);
private Vector2 _scroll1 = Vector2.zero;
private Vector2 _scroll2 = Vector2.zero;
private readonly Dictionary<string, string> _bans = new Dictionary<string, string>();
private readonly HashSet<int> _known = new HashSet<int>();
private readonly Dictionary<int, string> _nameCache = new Dictionary<int, string>();
private float _nextScan;
private string _notice = "";
private float _noticeUntil;
private NetworkManager _netMan;
private PropertyInfo _piInstances;
private string BanFile => Path.Combine(Paths.ConfigPath, "kickmod_bans.txt");
private void Start()
{
_piInstances = typeof(NetworkManager).GetProperty("Instances", BindingFlags.Static | BindingFlags.Public);
LoadBans();
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown(KickPlugin.KeyToggle.Value))
{
_show = !_show;
}
if (Time.time >= _nextScan)
{
_nextScan = Time.time + 1f;
RefreshNetMan();
if (IsHost())
{
ScanNewConnections();
}
}
}
private void RefreshNetMan()
{
try
{
if ((Object)(object)_netMan != (Object)null && _netManagerAlive())
{
return;
}
_netMan = null;
if (_piInstances == null)
{
return;
}
object value = _piInstances.GetValue(null, null);
if (!(value is IEnumerable enumerable))
{
return;
}
foreach (object item in enumerable)
{
NetworkManager val = (NetworkManager)((item is NetworkManager) ? item : null);
if ((Object)(object)val != (Object)null)
{
_netMan = val;
break;
}
}
}
catch (Exception)
{
_netMan = null;
}
}
private bool _netManagerAlive()
{
try
{
return (Object)(object)_netMan != (Object)null && (Object)(object)((Component)_netMan).gameObject != (Object)null;
}
catch
{
return false;
}
}
private bool IsHost()
{
return (Object)(object)_netMan != (Object)null && _netMan.IsServerStarted;
}
private void ScanNewConnections()
{
Dictionary<int, NetworkConnection> dictionary = null;
try
{
dictionary = _netMan.ServerManager.Clients;
}
catch (Exception)
{
return;
}
if (dictionary == null)
{
return;
}
HashSet<int> alive = new HashSet<int>();
foreach (KeyValuePair<int, NetworkConnection> item in dictionary)
{
NetworkConnection value = item.Value;
if (value == (NetworkConnection)null || !value.IsActive)
{
continue;
}
alive.Add(item.Key);
if (!_nameCache.ContainsKey(item.Key))
{
string value2 = ResolveName(value, deepScan: true);
if (!string.IsNullOrEmpty(value2))
{
_nameCache[item.Key] = value2;
}
}
if (!_known.Contains(item.Key))
{
_known.Add(item.Key);
string text = SafeAddress(value);
if (!string.IsNullOrEmpty(text) && _bans.ContainsKey(text))
{
value.Kick((KickReason)0, (LoggingType)3, "");
Notice("已自动踢出黑名单玩家: " + NameOf(value));
KickPlugin.Log.LogInfo((object)("[KickMod] 黑名单玩家被自动踢出: " + text));
}
}
}
_known.RemoveWhere((int id) => !alive.Contains(id));
List<int> list = null;
foreach (int key in _nameCache.Keys)
{
if (!alive.Contains(key))
{
if (list == null)
{
list = new List<int>();
}
list.Add(key);
}
}
if (list != null)
{
for (int num = 0; num < list.Count; num++)
{
_nameCache.Remove(list[num]);
}
}
}
private void DoKick(NetworkConnection conn)
{
if (!(conn == (NetworkConnection)null))
{
conn.Kick((KickReason)0, (LoggingType)3, "");
Notice("已踢出: " + NameOf(conn));
KickPlugin.Log.LogInfo((object)("[KickMod] 踢出玩家: " + NameOf(conn) + " (" + SafeAddress(conn) + ")"));
}
}
private void DoBan(NetworkConnection conn)
{
if (!(conn == (NetworkConnection)null))
{
string text = SafeAddress(conn);
string text2 = NameOf(conn);
if (!string.IsNullOrEmpty(text))
{
_bans[text] = text2;
SaveBans();
}
conn.Kick((KickReason)0, (LoggingType)3, "");
Notice("已拉黑并踢出: " + text2);
KickPlugin.Log.LogInfo((object)("[KickMod] 拉黑玩家: " + text2 + " (" + text + ")"));
}
}
private void DoUnban(string addr)
{
_bans.Remove(addr);
SaveBans();
Notice("已移出黑名单: " + addr);
}
private string NameOf(NetworkConnection conn)
{
if (conn == (NetworkConnection)null)
{
return "?";
}
if (_nameCache.TryGetValue(conn.ClientId, out var value))
{
return value;
}
value = ResolveName(conn, deepScan: false);
if (!string.IsNullOrEmpty(value))
{
_nameCache[conn.ClientId] = value;
return value;
}
return "Client #" + conn.ClientId;
}
private string ResolveName(NetworkConnection conn, bool deepScan)
{
try
{
if (IsSelf(conn))
{
Player localPlayer = Player.LocalPlayer;
if ((Object)(object)localPlayer != (Object)null && !string.IsNullOrEmpty(localPlayer.SteamName))
{
return localPlayer.SteamName;
}
}
Player val = null;
if ((Object)(object)conn.FirstObject != (Object)null)
{
val = ((Component)conn.FirstObject).GetComponent<Player>();
}
if ((Object)(object)val == (Object)null && deepScan)
{
Player[] array = Object.FindObjectsOfType<Player>();
for (int i = 0; i < array.Length; i++)
{
if ((Object)(object)array[i] != (Object)null && ((NetworkBehaviour)array[i]).Owner == conn)
{
val = array[i];
break;
}
}
}
if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.SteamName))
{
return val.SteamName;
}
}
catch (Exception)
{
}
return null;
}
private string SafeAddress(NetworkConnection conn)
{
try
{
return conn.GetAddress();
}
catch (Exception)
{
return "";
}
}
private bool IsSelf(NetworkConnection conn)
{
try
{
return conn.IsLocalClient || conn.IsHost;
}
catch (Exception)
{
return false;
}
}
private void Notice(string msg)
{
_notice = msg;
_noticeUntil = Time.time + 3f;
}
private void LoadBans()
{
try
{
_bans.Clear();
if (File.Exists(BanFile))
{
string[] array = File.ReadAllLines(BanFile);
for (int i = 0; i < array.Length; i++)
{
string text = array[i].Trim();
if (text.Length == 0)
{
continue;
}
int num = text.IndexOf('|');
if (num > 0)
{
string text2 = text.Substring(0, num).Trim();
if (text2.Length > 0)
{
_bans[text2] = text.Substring(num + 1).Trim();
}
}
else
{
_bans[text] = "";
}
}
}
KickPlugin.Log.LogInfo((object)("[KickMod] 黑名单已加载: " + _bans.Count + " 人"));
}
catch (Exception ex)
{
KickPlugin.Log.LogWarning((object)("[KickMod] 黑名单读取失败: " + ex.Message));
}
}
private void SaveBans()
{
try
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, string> ban in _bans)
{
list.Add(ban.Key + "|" + ban.Value);
}
File.WriteAllLines(BanFile, list.ToArray());
}
catch (Exception ex)
{
KickPlugin.Log.LogWarning((object)("[KickMod] 黑名单保存失败: " + ex.Message));
}
}
private void OnGUI()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (_show)
{
if (!IsHost())
{
_win = GUILayout.Window(7301, _win, new WindowFunction(DrawNotHost), "KickMod — 仅房主可用", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(320f) });
}
else
{
_win = GUILayout.Window(7302, _win, new WindowFunction(DrawHost), "KickMod — 房主管理面板", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
}
}
}
private void DrawNotHost(int id)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label("你不是房主, 无法管理玩家。", Array.Empty<GUILayoutOption>());
GUILayout.Label("按 " + ((object)KickPlugin.KeyToggle.Value/*cast due to .constrained prefix*/).ToString() + " 关闭本窗口。", Array.Empty<GUILayoutOption>());
GUIStyle val = new GUIStyle(GUI.skin.label);
val.fontSize = 11;
val.normal.textColor = new Color(1f, 1f, 1f, 0.55f);
GUILayout.Space(4f);
GUILayout.Label("作者, dy小文大王。有问题可以私信我", val, Array.Empty<GUILayoutOption>());
GUI.DragWindow();
}
private void DrawHost(int id)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_024e: Unknown result type (might be due to invalid IL or missing references)
//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Expected O, but got Unknown
//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
Dictionary<int, NetworkConnection> dictionary = null;
try
{
dictionary = _netMan.ServerManager.Clients;
}
catch (Exception)
{
}
GUILayout.Label("在线玩家 (" + (dictionary?.Count ?? 0) + "):", Array.Empty<GUILayoutOption>());
_scroll1 = GUILayout.BeginScrollView(_scroll1, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
if (dictionary != null)
{
List<NetworkConnection> list = new List<NetworkConnection>();
foreach (KeyValuePair<int, NetworkConnection> item in dictionary)
{
if (item.Value != (NetworkConnection)null && item.Value.IsActive)
{
list.Add(item.Value);
}
}
for (int i = 0; i < list.Count; i++)
{
NetworkConnection conn = list[i];
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
string text = (IsSelf(conn) ? " (你/房主)" : "");
GUILayout.Label(NameOf(conn) + text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
if (!IsSelf(conn))
{
if (GUILayout.Button("踢出", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
{
DoKick(conn);
}
if (GUILayout.Button("拉黑", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
{
DoBan(conn);
}
}
GUILayout.EndHorizontal();
}
if (list.Count == 0)
{
GUILayout.Label("(没有其他玩家)", Array.Empty<GUILayoutOption>());
}
}
GUILayout.EndScrollView();
GUILayout.Space(8f);
GUILayout.Label("黑名单 (" + _bans.Count + ", 重连自动踢):", Array.Empty<GUILayoutOption>());
_scroll2 = GUILayout.BeginScrollView(_scroll2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(100f) });
string text2 = null;
foreach (KeyValuePair<string, string> ban in _bans)
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
string text3 = (string.IsNullOrEmpty(ban.Value) ? ban.Key : (ban.Value + " (" + ban.Key + ")"));
GUILayout.Label(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(340f) });
if (GUILayout.Button("移除", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
{
text2 = ban.Key;
}
GUILayout.EndHorizontal();
}
if (_bans.Count == 0)
{
GUILayout.Label("(空)", Array.Empty<GUILayoutOption>());
}
GUILayout.EndScrollView();
if (text2 != null)
{
DoUnban(text2);
}
GUILayout.Space(6f);
if (_notice.Length > 0 && Time.time < _noticeUntil)
{
GUILayout.Label(_notice, Array.Empty<GUILayoutOption>());
}
GUILayout.Label("按 " + ((object)KickPlugin.KeyToggle.Value/*cast due to .constrained prefix*/).ToString() + " 关闭", Array.Empty<GUILayoutOption>());
GUIStyle val = new GUIStyle(GUI.skin.label);
val.fontSize = 11;
val.normal.textColor = new Color(1f, 1f, 1f, 0.55f);
GUILayout.Space(4f);
GUILayout.Label("作者, dy小文大王。有问题可以私信我", val, Array.Empty<GUILayoutOption>());
GUI.DragWindow();
}
}