diff --git a/ChestPvPProtection/ChestPvPProtection.csproj b/ChestPvPProtection/ChestPvPProtection.csproj new file mode 100644 index 0000000..312cea9 --- /dev/null +++ b/ChestPvPProtection/ChestPvPProtection.csproj @@ -0,0 +1,471 @@ + + + netstandard2.1 + VMods.ChestPvPProtection + VMods.ChestPvPProtection + A mod that prevents looting of enemy player chests/workstations by players with the PvP Protection buff + 1.0.0 + true + latest + False + + + + M:\Games\Steam\steamapps\common\VRising\BepInEx\unhollowed + M:\Games\Steam\steamapps\common\VRising\BepInEx\WetstonePlugins + M:\Games\Steam\steamapps\common\VRising\VRising_Server\BepInEx\WetstonePlugins + + + + + + + + + + + + + + + + + + + + + $(UnhollowedDllPath)\com.stunlock.console.dll + + + $(UnhollowedDllPath)\com.stunlock.metrics.dll + + + $(UnhollowedDllPath)\com.stunlock.network.lidgren.dll + + + $(UnhollowedDllPath)\com.stunlock.network.steam.dll + + + $(UnhollowedDllPath)\Il2CppMono.Security.dll + + + $(UnhollowedDllPath)\Il2CppSystem.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Configuration.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Core.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Data.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Numerics.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Runtime.Serialization.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Xml.dll + + + $(UnhollowedDllPath)\Il2CppSystem.Xml.Linq.dll + + + $(UnhollowedDllPath)\Lidgren.Network.dll + + + $(UnhollowedDllPath)\MagicaCloth.dll + + + $(UnhollowedDllPath)\Malee.ReorderableList.dll + + + $(UnhollowedDllPath)\Newtonsoft.Json.dll + + + $(UnhollowedDllPath)\ProjectM.Behaviours.dll + + + $(UnhollowedDllPath)\ProjectM.Camera.dll + + + $(UnhollowedDllPath)\ProjectM.CastleBuilding.Systems.dll + + + $(UnhollowedDllPath)\ProjectM.Conversion.dll + + + $(UnhollowedDllPath)\ProjectM.Gameplay.Scripting.dll + + + $(UnhollowedDllPath)\ProjectM.Gameplay.Systems.dll + + + $(UnhollowedDllPath)\ProjectM.GeneratedNetCode.dll + + + $(UnhollowedDllPath)\ProjectM.Misc.Systems.dll + + + $(UnhollowedDllPath)\ProjectM.Pathfinding.dll + + + $(UnhollowedDllPath)\ProjectM.Presentation.Systems.dll + + + $(UnhollowedDllPath)\ProjectM.Roofs.dll + + + $(UnhollowedDllPath)\ProjectM.ScriptableSystems.dll + + + $(UnhollowedDllPath)\ProjectM.Shared.dll + + + $(UnhollowedDllPath)\Il2Cppmscorlib.dll + + + $(UnhollowedDllPath)\ProjectM.dll + + + $(UnhollowedDllPath)\com.stunlock.network.dll + + + $(UnhollowedDllPath)\ProjectM.Shared.Systems.dll + + + $(UnhollowedDllPath)\ProjectM.Terrain.dll + + + $(UnhollowedDllPath)\RootMotion.dll + + + $(UnhollowedDllPath)\Sequencer.dll + + + $(UnhollowedDllPath)\Stunlock.Fmod.dll + + + $(UnhollowedDllPath)\Unity.Burst.dll + + + $(UnhollowedDllPath)\Unity.Burst.Unsafe.dll + + + $(UnhollowedDllPath)\Unity.Collections.dll + + + $(UnhollowedDllPath)\Unity.Collections.LowLevel.ILSupport.dll + + + $(UnhollowedDllPath)\Unity.Deformations.dll + + + $(UnhollowedDllPath)\Unity.Entities.dll + + + $(UnhollowedDllPath)\ProjectM.HUD.dll + + + $(UnhollowedDllPath)\Unity.Entities.Hybrid.dll + + + $(UnhollowedDllPath)\Unity.Jobs.dll + + + $(UnhollowedDllPath)\Unity.Mathematics.dll + + + $(UnhollowedDllPath)\Unity.Mathematics.Extensions.dll + + + $(UnhollowedDllPath)\Unity.Mathematics.Extensions.Hybrid.dll + + + $(UnhollowedDllPath)\Unity.Physics.dll + + + $(UnhollowedDllPath)\Unity.Physics.Hybrid.dll + + + $(UnhollowedDllPath)\Unity.Properties.dll + + + $(UnhollowedDllPath)\Unity.Rendering.Hybrid.dll + + + $(UnhollowedDllPath)\Unity.RenderPipelines.Core.Runtime.dll + + + $(UnhollowedDllPath)\Unity.RenderPipelines.HighDefinition.Config.Runtime.dll + + + $(UnhollowedDllPath)\Unity.RenderPipelines.HighDefinition.Runtime.dll + + + $(UnhollowedDllPath)\Unity.Scenes.dll + + + $(UnhollowedDllPath)\Unity.Serialization.dll + + + $(UnhollowedDllPath)\Unity.Services.Analytics.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Configuration.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Device.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Environments.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Environments.Internal.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Internal.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Registration.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Scheduler.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Telemetry.dll + + + $(UnhollowedDllPath)\Unity.Services.Core.Threading.dll + + + $(UnhollowedDllPath)\Unity.TextMeshPro.dll + + + $(UnhollowedDllPath)\Unity.Transforms.dll + + + $(UnhollowedDllPath)\Unity.Transforms.Hybrid.dll + + + $(UnhollowedDllPath)\Unity.VisualEffectGraph.Runtime.dll + + + $(UnhollowedDllPath)\UnityEngine.dll + + + $(UnhollowedDllPath)\UnityEngine.AccessibilityModule.dll + + + $(UnhollowedDllPath)\UnityEngine.AIModule.dll + + + $(UnhollowedDllPath)\UnityEngine.AndroidJNIModule.dll + + + $(UnhollowedDllPath)\UnityEngine.AnimationModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ARModule.dll + + + $(UnhollowedDllPath)\UnityEngine.AssetBundleModule.dll + + + $(UnhollowedDllPath)\UnityEngine.AudioModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ClothModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ClusterInputModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ClusterRendererModule.dll + + + $(UnhollowedDllPath)\UnityEngine.CoreModule.dll + + + $(UnhollowedDllPath)\ProjectM.CodeGeneration.dll + + + $(UnhollowedDllPath)\Stunlock.Core.dll + + + $(UnhollowedDllPath)\UnityEngine.CrashReportingModule.dll + + + $(UnhollowedDllPath)\UnityEngine.DirectorModule.dll + + + $(UnhollowedDllPath)\UnityEngine.DSPGraphModule.dll + + + $(UnhollowedDllPath)\UnityEngine.GameCenterModule.dll + + + $(UnhollowedDllPath)\UnityEngine.GIModule.dll + + + $(UnhollowedDllPath)\UnityEngine.GridModule.dll + + + $(UnhollowedDllPath)\UnityEngine.HotReloadModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ImageConversionModule.dll + + + $(UnhollowedDllPath)\UnityEngine.IMGUIModule.dll + + + $(UnhollowedDllPath)\UnityEngine.InputLegacyModule.dll + + + $(UnhollowedDllPath)\UnityEngine.InputModule.dll + + + $(UnhollowedDllPath)\UnityEngine.JSONSerializeModule.dll + + + $(UnhollowedDllPath)\UnityEngine.LocalizationModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ParticleSystemModule.dll + + + $(UnhollowedDllPath)\UnityEngine.PerformanceReportingModule.dll + + + $(UnhollowedDllPath)\UnityEngine.Physics2DModule.dll + + + $(UnhollowedDllPath)\UnityEngine.PhysicsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ProfilerModule.dll + + + $(UnhollowedDllPath)\UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll + + + $(UnhollowedDllPath)\UnityEngine.ScreenCaptureModule.dll + + + $(UnhollowedDllPath)\UnityEngine.SharedInternalsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.SpriteMaskModule.dll + + + $(UnhollowedDllPath)\UnityEngine.SpriteShapeModule.dll + + + $(UnhollowedDllPath)\UnityEngine.StreamingModule.dll + + + $(UnhollowedDllPath)\UnityEngine.SubstanceModule.dll + + + $(UnhollowedDllPath)\UnityEngine.SubsystemsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TerrainModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TerrainPhysicsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TextCoreModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TextRenderingModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TilemapModule.dll + + + $(UnhollowedDllPath)\UnityEngine.TLSModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UI.dll + + + $(UnhollowedDllPath)\UnityEngine.UIElementsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UIElementsNativeModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UIModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UmbraModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UNETModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityAnalyticsModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityConnectModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityCurlModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityTestProtocolModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityWebRequestAssetBundleModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityWebRequestAudioModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityWebRequestModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityWebRequestTextureModule.dll + + + $(UnhollowedDllPath)\UnityEngine.UnityWebRequestWWWModule.dll + + + $(UnhollowedDllPath)\UnityEngine.VehiclesModule.dll + + + $(UnhollowedDllPath)\UnityEngine.VFXModule.dll + + + $(UnhollowedDllPath)\UnityEngine.VideoModule.dll + + + $(UnhollowedDllPath)\UnityEngine.VirtualTexturingModule.dll + + + $(UnhollowedDllPath)\UnityEngine.VRModule.dll + + + $(UnhollowedDllPath)\UnityEngine.WindModule.dll + + + $(UnhollowedDllPath)\UnityEngine.XRModule.dll + + + $(UnhollowedDllPath)\VivoxUnity.dll + + + + + + + + diff --git a/ChestPvPProtection/Configs/ChestPvPProtectionSystemConfig.cs b/ChestPvPProtection/Configs/ChestPvPProtectionSystemConfig.cs new file mode 100644 index 0000000..ea4d11d --- /dev/null +++ b/ChestPvPProtection/Configs/ChestPvPProtectionSystemConfig.cs @@ -0,0 +1,25 @@ +using BepInEx.Configuration; + +namespace VMods.ChestPvPProtection +{ + public static class ChestPvPProtectionSystemConfig + { + #region Properties + + public static ConfigEntry ChestPvPProtectionEnabled { get; private set; } + + public static ConfigEntry ChestPvPProtectionSendMessage { get; private set; } + + #endregion + + #region Public Methods + + public static void Initialize(ConfigFile config) + { + ChestPvPProtectionEnabled = config.Bind(nameof(ChestPvPProtection), nameof(ChestPvPProtectionEnabled), false, "Enabled/disable the Chest PvP Protection system."); + ChestPvPProtectionSendMessage = config.Bind(nameof(ChestPvPProtection), nameof(ChestPvPProtectionSendMessage), true, "Enabled/disable the sending of a system message to the player with the PvP Protection buff that's attempting to interact with an enemy player's chest."); + } + + #endregion + } +} diff --git a/ChestPvPProtection/Hooks/InventoryHooks.cs b/ChestPvPProtection/Hooks/InventoryHooks.cs new file mode 100644 index 0000000..997424b --- /dev/null +++ b/ChestPvPProtection/Hooks/InventoryHooks.cs @@ -0,0 +1,158 @@ +using HarmonyLib; +using ProjectM; +using ProjectM.Network; +using Unity.Collections; +using Unity.Entities; +using VMods.Shared; +using Wetstone.API; + +namespace VMods.ChestPvPProtection +{ + [HarmonyPatch] + public static class InventoryHooks + { + #region Events + + public delegate void InventoryInteractionEventHandler(Entity eventEntity, VModCharacter vmodCharacter, params Entity[] inventoryEntities); + public static event InventoryInteractionEventHandler InventoryInteractionEvent; + private static void FireInventoryInteractionEvent(Entity eventEntity, VModCharacter vmodCharacter, params Entity[] inventoryEntities) => InventoryInteractionEvent?.Invoke(eventEntity, vmodCharacter, inventoryEntities); + + #endregion + + #region Private Methods + + [HarmonyPatch(typeof(MoveItemBetweenInventoriesSystem), nameof(MoveItemBetweenInventoriesSystem.OnUpdate))] + [HarmonyPrefix] + private static void MoveItemBetweenInventories(MoveItemBetweenInventoriesSystem __instance) + { + if(!VWorld.IsServer || __instance._MoveItemBetweenInventoriesEventQuery == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance._MoveItemBetweenInventoriesEventQuery.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var moveEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, moveEvent.FromInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity, moveEvent.ToInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + [HarmonyPatch(typeof(MoveAllItemsBetweenInventoriesSystem), nameof(MoveAllItemsBetweenInventoriesSystem.OnUpdate))] + [HarmonyPrefix] + private static void MoveAllItemsBetweenInventories(MoveAllItemsBetweenInventoriesSystem __instance) + { + if(!VWorld.IsServer || __instance.__MoveAllItemsJob_entityQuery == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance.__MoveAllItemsJob_entityQuery.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var moveEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, moveEvent.FromInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity, moveEvent.ToInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + [HarmonyPatch(typeof(DropInventoryItemSystem), nameof(DropInventoryItemSystem.OnUpdate))] + [HarmonyPrefix] + private static void DropInventoryItem(DropInventoryItemSystem __instance) + { + if(!VWorld.IsServer || __instance.__DropInventoryItemJob_entityQuery == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance.__DropInventoryItemJob_entityQuery.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var dropEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, dropEvent.Inventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + [HarmonyPatch(typeof(SplitItemSystem), nameof(SplitItemSystem.OnUpdate))] + [HarmonyPrefix] + private static void SplitItem(SplitItemSystem __instance) + { + if(!VWorld.IsServer || __instance._Query == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance._Query.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var splitEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, splitEvent.Inventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + [HarmonyPatch(typeof(SortAllItemsSystem), nameof(SortAllItemsSystem.OnUpdate))] + [HarmonyPrefix] + private static void SortAllItems(SplitItemSystem __instance) + { + if(!VWorld.IsServer || __instance._Query == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance._Query.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var sortEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, sortEvent.Inventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + [HarmonyPatch(typeof(SmartMergeItemsBetweenInventoriesSystem), nameof(SmartMergeItemsBetweenInventoriesSystem.OnUpdate))] + [HarmonyPrefix] + private static void SmartMergeItemsBetweenInventories(SplitItemSystem __instance) + { + if(!VWorld.IsServer || __instance._Query == null) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var networkIdToEntityMap = __instance._NetworkIdSystem._NetworkIdToEntityMap; + + var entities = __instance._Query.ToEntityArray(Allocator.Temp); + foreach(var entity in entities) + { + var fromCharacter = new VModCharacter(entityManager.GetComponentData(entity), entityManager); + var mergeEvent = entityManager.GetComponentData(entity); + FireInventoryInteractionEvent(entity, fromCharacter, mergeEvent.FromInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity, mergeEvent.ToInventory.GetNetworkedEntity(networkIdToEntityMap)._Entity); + } + } + + #endregion + } +} diff --git a/ChestPvPProtection/Plugin.cs b/ChestPvPProtection/Plugin.cs new file mode 100644 index 0000000..6feb577 --- /dev/null +++ b/ChestPvPProtection/Plugin.cs @@ -0,0 +1,56 @@ +using BepInEx; +using BepInEx.IL2CPP; +using HarmonyLib; +using System.Reflection; +using VMods.Shared; +using Wetstone.API; + +namespace VMods.ChestPvPProtection +{ + [BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] + [BepInDependency("xyz.molenzwiebel.wetstone")] + [Reloadable] + public class Plugin : BasePlugin + { + #region Variables + + private Harmony _hooks; + + #endregion + + #region Public Methods + + public sealed override void Load() + { + if(VWorld.IsClient) + { + Log.LogMessage($"{PluginInfo.PLUGIN_NAME} only needs to be installed server side."); + return; + } + Utils.Initialize(Log, PluginInfo.PLUGIN_NAME); + + ChestPvPProtectionSystemConfig.Initialize(Config); + + ChestPvPProtectionSystem.Initialize(); + + _hooks = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly()); + + Log.LogInfo($"Plugin {PluginInfo.PLUGIN_NAME} (v{PluginInfo.PLUGIN_VERSION}) is loaded!"); + } + + public sealed override bool Unload() + { + if(VWorld.IsClient) + { + return true; + } + _hooks?.UnpatchSelf(); + ChestPvPProtectionSystem.Deinitialize(); + Config.Clear(); + Utils.Deinitialize(); + return true; + } + + #endregion + } +} diff --git a/ChestPvPProtection/Systems/ChestPvPProtectionSystem.cs b/ChestPvPProtection/Systems/ChestPvPProtectionSystem.cs new file mode 100644 index 0000000..3622624 --- /dev/null +++ b/ChestPvPProtection/Systems/ChestPvPProtectionSystem.cs @@ -0,0 +1,76 @@ +using ProjectM; +using ProjectM.Network; +using ProjectM.Scripting; +using System.Linq; +using Unity.Entities; +using VMods.Shared; +using Wetstone.API; + +namespace VMods.ChestPvPProtection +{ + public static class ChestPvPProtectionSystem + { + #region Public Methods + + public static void Initialize() + { + InventoryHooks.InventoryInteractionEvent += OnInventoryInteraction; + } + + public static void Deinitialize() + { + InventoryHooks.InventoryInteractionEvent -= OnInventoryInteraction; + } + + #endregion + + #region Private Methods + + private static void OnInventoryInteraction(Entity eventEntity, VModCharacter vmodCharacter, params Entity[] inventoryEntities) + { + if(!ChestPvPProtectionSystemConfig.ChestPvPProtectionEnabled.Value) + { + return; + } + + var server = VWorld.Server; + var entityManager = server.EntityManager; + var teamChecker = server.GetExistingSystem()._ServerGameManager._TeamChecker; + + if(!vmodCharacter.HasBuff(Utils.PvPProtectionBuff) || vmodCharacter.User.IsAdmin) + { + return; + } + + var playerTeam = entityManager.GetComponentData(vmodCharacter.FromCharacter.Character); + var teams = inventoryEntities.Select(FindTeam); + + // Check if the player is not an ally and the inventory isn't neutral (i.e. an npc chest) of any inventory + if(teams.Any(team => !teamChecker.IsAllies(playerTeam, team) && !teamChecker.IsNeutral(team))) + { + entityManager.AddComponent(eventEntity); + if(ChestPvPProtectionSystemConfig.ChestPvPProtectionSendMessage.Value) + { + Utils.SendMessage(vmodCharacter.FromCharacter.User, $"Cannot interact with enemy Chests/Workstations while PvP Protected", ServerChatMessageType.System); + } + } + + // Nested Method(s) + Team FindTeam(Entity entity) + { + if(entityManager.HasComponent(entity)) + { + return entityManager.GetComponentData(entity); + } + else + { + // Workstations don't have a team but are attached, thus retrieve the team of the station's parent. + var attach = entityManager.GetComponentData(entity); + return entityManager.GetComponentData(attach.Parent); + } + } + } + + #endregion + } +} diff --git a/README.md b/README.md index af50030..922b959 100644 --- a/README.md +++ b/README.md @@ -101,3 +101,8 @@ Both the amount of offenses before being punishes as well as the punishment itse * % of reduced Spell Power + +## Chest PvP Protection +A server-side only mod that prevents looting of enemy player chests/workstations by players with the PvP Protection buff. + +Besides looting, it'll also prevent moving, sorting, swapping and merging ("compilsively count") of items within those chests/workstations. diff --git a/Shared/Utils.cs b/Shared/Utils.cs index 7599f9e..75114d5 100644 --- a/Shared/Utils.cs +++ b/Shared/Utils.cs @@ -20,6 +20,8 @@ public static class Utils public static readonly PrefabGUID SevereGarlicDebuff = new(1582196539); + public static readonly PrefabGUID PvPProtectionBuff = new(1111481396); + #endregion #region Variables @@ -291,6 +293,17 @@ public static void LogAllComponentTypes(Entity entity, EntityManager? entityMana Logger.LogMessage($"---"); } + public static void LogAllComponentTypes(EntityQuery entityQuery) + { + var types = entityQuery.GetQueryTypes(); + Logger.LogMessage($"---"); + foreach(var t in types) + { + Logger.LogMessage($"Query Component Type: {t}"); + } + Logger.LogMessage($"---"); + } + #endregion #region Nested diff --git a/Shared/VModCharacter.cs b/Shared/VModCharacter.cs index 866e6f0..d705c71 100644 --- a/Shared/VModCharacter.cs +++ b/Shared/VModCharacter.cs @@ -23,6 +23,14 @@ public readonly struct VModCharacter Character = user.LocalCharacter._Entity, }); + public VModCharacter(FromCharacter fromCharacter, EntityManager? entityManager = null) + { + entityManager ??= Utils.CurrentWorld.EntityManager; + User = entityManager.Value.GetComponentData(fromCharacter.User); + Character = entityManager.Value.GetComponentData(fromCharacter.Character); + FromCharacter = fromCharacter; + } + public VModCharacter(Entity userEntity, Entity charEntity, EntityManager? entityManager = null) { entityManager ??= Utils.CurrentWorld.EntityManager; diff --git a/Thunderstone/ChestPvPProtection/README.md b/Thunderstone/ChestPvPProtection/README.md new file mode 100644 index 0000000..a2e60cd --- /dev/null +++ b/Thunderstone/ChestPvPProtection/README.md @@ -0,0 +1,25 @@ +# Chest PvP Protection +A server-side only mod that prevents looting of enemy player chests/workstations by players with the PvP Protection buff. + +Besides looting, it'll also prevent moving, sorting, swapping and merging ("compilsively count") of items within those chests/workstations. + +## How to manually install +* Install [BepInEx](https://v-rising.thunderstore.io/package/BepInEx/BepInExPack_V_Rising/) +* Install [Wetstone](https://v-rising.thunderstore.io/package/molenzwiebel/Wetstone/) +* (Locally hosted games only) Install [ServerLaunchFix](https://v-rising.thunderstore.io/package/Mythic/ServerLaunchFix/) +* Extract the Vmods._mod-name_.dll +* Move the desired mod(s) to the `[VRising (server) folder]/BepInEx/WetstonePlugins/` +* Launch the server (or game) to auto-generate the config files +* Edit the configs as you desire (found in `[VRising (server) folder]/BepInEx/config/`) +* Reload the mods using the Wetstone commands (by default F6 for client-side mods, and/or `!reload` for server-side mods) + * If this doesn't work, or isn't enabled, restart the server/game + +## Commands +Most of the VMods come with a set of commands that can be used. To see the available commands, by default a player or admin can use `!help`. +Normal players won't see the Admin-only commands listed. +The prefix (`!`) can be changed on a per-mod basis. +To prevent spam/abuse there's also a command cooldown for non-admins, this value can also be tweaked on a per-mod basis. +Commands can also be disabled completely on a per-mod basis. + +## More Details +* [ChangeLog](https://github.com/WhiteFang5/VMods/blob/master/CHANGELOG.md#chest-pvp-protection) diff --git a/Thunderstone/ChestPvPProtection/manifest.json b/Thunderstone/ChestPvPProtection/manifest.json new file mode 100644 index 0000000..c6f1a92 --- /dev/null +++ b/Thunderstone/ChestPvPProtection/manifest.json @@ -0,0 +1,10 @@ +{ + "name": "VMods_Chest_PvP_Protection", + "description": "A mod that that prevents looting of enemy player chests/workstations by players with the PvP Protection buff.", + "version_number": "1.0.0", + "dependencies": [ + "BepInEx-BepInExPack_V_Rising-1.0.0", + "molenzwiebel-Wetstone-1.1.0" + ], + "website_url": "https://github.com/WhiteFang5/VMods#chest-pvp-protection" +} diff --git a/VMods.sln b/VMods.sln index 424c735..985f2bd 100644 --- a/VMods.sln +++ b/VMods.sln @@ -11,11 +11,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RecoverEmptyContainers", "R EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExperimentalMod", "ExperimentalMod\ExperimentalMod.csproj", "{695DC4E6-1831-4826-9A64-B85107AB555A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PvPPunishment", "PvPPunishment\PvPPunishment.csproj", "{FBB60595-8F29-49D5-A9A1-0CEA1B9CFF91}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PvPPunishment", "PvPPunishment\PvPPunishment.csproj", "{FBB60595-8F29-49D5-A9A1-0CEA1B9CFF91}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{81DE42A0-8493-49B4-9F0E-353198C1E2AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{81DE42A0-8493-49B4-9F0E-353198C1E2AD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PvPLeaderboard", "PvPLeaderboard\PvPLeaderboard.csproj", "{8D3A6ED6-46CD-41CD-BE61-5587F05EAB4E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PvPLeaderboard", "PvPLeaderboard\PvPLeaderboard.csproj", "{8D3A6ED6-46CD-41CD-BE61-5587F05EAB4E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChestPvPProtection", "ChestPvPProtection\ChestPvPProtection.csproj", "{081DA46E-5AAB-4825-89E8-8B167988CC20}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +53,10 @@ Global {8D3A6ED6-46CD-41CD-BE61-5587F05EAB4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D3A6ED6-46CD-41CD-BE61-5587F05EAB4E}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D3A6ED6-46CD-41CD-BE61-5587F05EAB4E}.Release|Any CPU.Build.0 = Release|Any CPU + {081DA46E-5AAB-4825-89E8-8B167988CC20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {081DA46E-5AAB-4825-89E8-8B167988CC20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {081DA46E-5AAB-4825-89E8-8B167988CC20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {081DA46E-5AAB-4825-89E8-8B167988CC20}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE