using Rocket.API;
using Rocket.Core;
using Rocket.Core.Logging;
using Rocket.Core.Plugins;
using Rocket.Unturned.Chat;
using Rocket.Unturned.Player;
using SDG.Unturned;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Rocket.API.Collections;
using SysAction = System.Action;
using Steamworks;
using System.Reflection;
using System.Collections;
using System.Threading;
using Logger = Rocket.Core.Logging.Logger;
namespace Teyhota.ShowInventory
{
public class ShowInventory : RocketPlugin<ShowInventoryConfig>
{
public string pluginName = "Virtual ShowInventory(虚拟查包)";
public string pluginVersion = "4.0";
public string pluginDev = "Teyhota(原作者), GE(修复更新)";
public string pluginSite = "Plugins.4Unturned.tk";
public string unturnedVersion = "3.25.1.0";
public string rocketVersion = "4.9.3.16";
public static ShowInventory Instance;
public Dictionary<CSteamID, CSteamID> ViewingRelationships { get; private set; }
public Dictionary<CSteamID, CSteamID> ViewedPlayers { get; private set; }
public Dictionary<CSteamID, Items> VirtualItems { get; private set; }
private Dictionary<CSteamID, List<System.Action>> playerEventHandlers = new Dictionary<CSteamID, List<System.Action>>();
protected override void Load()
{
Instance = this;
ViewingRelationships = new Dictionary<CSteamID, CSteamID>();
ViewedPlayers = new Dictionary<CSteamID, CSteamID>();
VirtualItems = new Dictionary<CSteamID, Items>();
Logger.LogWarning(" ");
Logger.LogWarning("Plugin by: " + pluginDev);
Logger.LogWarning("Plugin version: " + pluginVersion);
Logger.LogWarning("Made for Unturned version: " + unturnedVersion);
Logger.LogWarning("Made for RocketMod version: " + rocketVersion);
Logger.LogWarning("Support: " + pluginSite);
Logger.LogWarning(" ");
Logger.LogWarning("------");
R.Commands.Register(new Command_Show());
R.Commands.Register(new Command_Hide());
Provider.onServerConnected += OnPlayerConnected;
Provider.onServerDisconnected += OnPlayerDisconnected;
}
private void OnPlayerConnected(CSteamID steamID)
{
StartCoroutine(DelayedInitializePlayerEvents(steamID));
}
private IEnumerator DelayedInitializePlayerEvents(CSteamID steamID)
{
yield return new WaitForSeconds(0.5f);
var player = PlayerTool.getPlayer(steamID);
if (player != null)
{
SetupPlayerEvents(player);
}
}
private void SetupPlayerEvents(Player player)
{
var steamID = player.channel.owner.playerID.steamID;
if (playerEventHandlers.ContainsKey(steamID))
return;
var handlers = new List<SysAction>();
playerEventHandlers[steamID] = handlers;
// 使用更兼容的丢弃事件处理
player.equipment.onDequipRequested += (PlayerEquipment equipment, ref bool shouldAllow) =>
{
if (ViewedPlayers.ContainsKey(steamID))
{
shouldAllow = false;
UnturnedChat.Say(steamID, "查看期间无法丢弃物品", Color.yellow);
}
};
// 添加移除处理函数
handlers.Add(() => player.equipment.onDequipRequested -= (PlayerEquipment equipment, ref bool shouldAllow) => { });
}
private void OnPlayerDisconnected(CSteamID steamID)
{
if (playerEventHandlers.TryGetValue(steamID, out var handlers))
{
foreach (var handler in handlers) handler();
playerEventHandlers.Remove(steamID);
}
if (ViewingRelationships.ContainsKey(steamID))
{
HideInventory(steamID);
}
var viewer = ViewingRelationships.FirstOrDefault(v => v.Value == steamID).Key;
if (viewer != null)
{
HideInventory(viewer);
}
if (ViewedPlayers.ContainsKey(steamID))
{
ViewedPlayers.Remove(steamID);
}
if (VirtualItems.ContainsKey(steamID))
{
VirtualItems.Remove(steamID);
}
}
protected override void Unload()
{
foreach (var relationship in ViewingRelationships.ToList())
{
HideInventory(relationship.Key);
}
Provider.onServerConnected -= OnPlayerConnected;
Provider.onServerDisconnected -= OnPlayerDisconnected;
foreach (var handlers in playerEventHandlers.Values)
{
foreach (var handler in handlers) handler();
}
playerEventHandlers.Clear();
}
// 创建虚拟物品存储
private Items CreateVirtualItems(UnturnedPlayer target)
{
// 创建虚拟存储(背包大小:8x6)
var items = new Items(PlayerInventory.STORAGE);
items.resize(8, 6);
// 复制玩家物品到虚拟存储
CopyPlayerToStorage(target, items);
return items;
}
// 复制玩家物品到存储
private void CopyPlayerToStorage(UnturnedPlayer player, Items storage)
{
// 复制背包物品(page 1)
CopyItemsToStorage(player.Inventory.items[1], storage);
}
private void CopyItemsToStorage(Items source, Items destination)
{
for (byte i = 0; i < source.getItemCount(); i++)
{
var itemJar = source.getItem(i);
if (itemJar != null && itemJar.item != null)
{
destination.addItem(
itemJar.x,
itemJar.y,
itemJar.rot,
new Item(itemJar.item.id, itemJar.item.amount, itemJar.item.quality, itemJar.item.state)
);
}
}
}
// 应用存储内容到玩家
private void ApplyStorageToPlayer(Items storage, UnturnedPlayer player)
{
// 清空玩家背包
ClearInventoryPage(player.Inventory, 1);
// 应用虚拟存储中的物品
for (byte i = 0; i < storage.getItemCount(); i++)
{
var itemJar = storage.getItem(i);
if (itemJar != null && itemJar.item != null)
{
player.Inventory.forceAddItem(
new Item(
itemJar.item.id,
itemJar.item.amount,
itemJar.item.quality,
itemJar.item.state
),
true
);
}
}
}
// 安全清空玩家物品栏页面
public void ClearInventoryPage(PlayerInventory inventory, byte page)
{
try
{
var itemsPage = inventory.items[page];
if (itemsPage == null) return;
int count = itemsPage.getItemCount();
for (int i = 0; i < count; i++)
{
inventory.removeItem(page, 0);
}
}
catch (Exception ex)
{
Logger.LogError($"Error clearing inventory page: {ex}");
}
}
// 显示其他玩家物品栏(使用虚拟存储)
public bool ShowInventoryToPlayer(UnturnedPlayer viewer, UnturnedPlayer target)
{
try
{
if (viewer?.Player == null || target?.Player == null)
return false;
if (ViewingRelationships.ContainsKey(viewer.CSteamID))
{
UnturnedChat.Say(viewer, "您已经在查看另一个玩家的背包", Color.yellow);
return false;
}
// 创建虚拟存储
var virtualItems = CreateVirtualItems(target);
// 记录查看关系
ViewingRelationships[viewer.CSteamID] = target.CSteamID;
VirtualItems[viewer.CSteamID] = virtualItems;
ViewedPlayers[target.CSteamID] = viewer.CSteamID;
// 使用兼容的打开存储方法
viewer.Player.inventory.openStorage(virtualItems, $"{target.CharacterName}'s Inventory");
// 锁定被查看玩家
LockTargetPlayer(target.CSteamID);
return true;
}
catch (Exception ex)
{
Logger.LogError($"Error showing inventory: {ex}");
return false;
}
}
// 锁定被查看玩家
private void LockTargetPlayer(CSteamID steamID)
{
var player = PlayerTool.getPlayer(steamID);
if (player != null)
{
ClosePlayerInventory(player);
}
}
// 关闭玩家物品栏界面
private void ClosePlayerInventory(Player player)
{
try
{
player.inventory.closeStorage();
}
catch (Exception ex)
{
Logger.LogError($"Error closing inventory: {ex}");
}
}
// 隐藏物品栏(关闭虚拟存储)
public bool HideInventory(CSteamID viewerId)
{
try
{
if (!ViewingRelationships.ContainsKey(viewerId))
return false;
var viewer = UnturnedPlayer.FromCSteamID(viewerId);
if (viewer == null) return false;
// 应用更改
ApplyInventoryChanges(viewerId);
return true;
}
catch (Exception ex)
{
Logger.LogError($"Error hiding inventory: {ex}");
return false;
}
}
// 应用更改到被查看玩家
private void ApplyInventoryChanges(CSteamID viewerSteamID)
{
if (!ViewingRelationships.TryGetValue(viewerSteamID, out var targetSteamID))
return;
if (!VirtualItems.TryGetValue(viewerSteamID, out var virtualItems))
return;
var targetPlayer = UnturnedPlayer.FromCSteamID(targetSteamID);
if (targetPlayer == null) return;
// 应用虚拟存储中的物品到被查看玩家
ApplyStorageToPlayer(virtualItems, targetPlayer);
// 清理资源
ViewingRelationships.Remove(viewerSteamID);
ViewedPlayers.Remove(targetSteamID);
VirtualItems.Remove(viewerSteamID);
UnturnedChat.Say(viewerSteamID, Translate("changes_applied"), Color.green);
}
public override TranslationList DefaultTranslations => new TranslationList
{
{ "press_g", "To show {0}'s inventory, press G." },
{ "type_hide", "To hide {0}'s inventory, type /hide." },
{ "hide_success", "Player's inventory hidden!" },
{ "hide_failure", "There are no inventories to hide!" },
{ "show_success", "Now showing {0}'s inventory" },
{ "show_failure", "Player not found or already viewing" },
{ "invalid_target", "Invalid target player" },
{ "changes_applied", "Changes have been applied to the player's inventory!" },
{ "viewing_locked", "Your inventory is locked while being viewed" }
};
}
public class Command_Show : IRocketCommand
{
public AllowedCaller AllowedCaller => AllowedCaller.Player;
public string Name => "show";
public string Help => "Show a player's inventory";
public string Syntax => "<player>";
public List<string> Aliases => new List<string> { "viewinv", "showinv" };
public List<string> Permissions => new List<string> { "showinventory.show" };
public void Execute(IRocketPlayer caller, string[] command)
{
var viewer = (UnturnedPlayer)caller;
if (command.Length == 0)
{
UnturnedChat.Say(caller, "Usage: /show <player>", Color.red);
return;
}
var targetName = string.Join(" ", command);
var targetPlayer = UnturnedPlayer.FromName(targetName);
if (targetPlayer == null && ulong.TryParse(targetName, out ulong steamId))
{
targetPlayer = UnturnedPlayer.FromCSteamID(new CSteamID(steamId));
}
if (targetPlayer == null || targetPlayer.CSteamID == viewer.CSteamID)
{
UnturnedChat.Say(caller, ShowInventory.Instance.Translate("invalid_target"), Color.red);
return;
}
if (ShowInventory.Instance.ShowInventoryToPlayer(viewer, targetPlayer))
{
UnturnedChat.Say(caller, ShowInventory.Instance.Translate("show_success", targetPlayer.CharacterName));
UnturnedChat.Say(targetPlayer, ShowInventory.Instance.Translate("viewing_locked"), Color.yellow);
}
else
{
UnturnedChat.Say(caller, ShowInventory.Instance.Translate("show_failure"));
}
}
}
public class Command_Hide : IRocketCommand
{
public AllowedCaller AllowedCaller => AllowedCaller.Player;
public string Name => "hide";
public string Help => "Hide the viewed inventory";
public string Syntax => "";
public List<string> Aliases => new List<string> { "hideinv" };
public List<string> Permissions => new List<string> { "showinventory.hide" };
public void Execute(IRocketPlayer caller, string[] command)
{
var player = (UnturnedPlayer)caller;
if (ShowInventory.Instance.HideInventory(player.CSteamID))
{
UnturnedChat.Say(caller, ShowInventory.Instance.Translate("hide_success"));
}
else
{
UnturnedChat.Say(caller, ShowInventory.Instance.Translate("hide_failure"));
}
}
}
public class ShowInventoryConfig : IRocketPluginConfiguration
{
public bool LockDuringView { get; set; } = true;
public bool NotifyTarget { get; set; } = true;
public bool CloseTargetInventory { get; set; } = true;
public void LoadDefaults()
{
LockDuringView = true;
NotifyTarget = true;
CloseTargetInventory = true;
}
}
}
CS1501"openStorage”方法没有采用2个参数的重载
Fix Showlnvent... Teyhota.Showl... 250