Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetAmmo&CategoryLimit #2515

Merged
merged 22 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Exiled.API/Extensions/MirrorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static class MirrorExtensions
private static readonly ReadOnlyDictionary<string, string> ReadOnlyRpcFullNamesValue = new(RpcFullNamesValue);
private static MethodInfo setDirtyBitsMethodInfoValue;
private static MethodInfo sendSpawnMessageMethodInfoValue;
private static MethodInfo addOperationMethodInfo;

/// <summary>
/// Gets <see cref="MethodInfo"/> corresponding to <see cref="Type"/>.
Expand Down Expand Up @@ -141,6 +142,20 @@ public static ReadOnlyDictionary<string, string> RpcFullNames
/// </summary>
public static MethodInfo SendSpawnMessageMethodInfo => sendSpawnMessageMethodInfoValue ??= typeof(NetworkServer).GetMethod("SendSpawnMessage", BindingFlags.NonPublic | BindingFlags.Static);

/// <summary>
/// Gets a SyncList{T}.AddOperation's <see cref="MethodInfo"/>.
/// </summary>
public static MethodInfo AddOperationMethodInfo => addOperationMethodInfo ??= typeof(SyncList<>).GetMethod("AddOperation", BindingFlags.NonPublic | BindingFlags.Static);

#pragma warning disable CS1591 // Commentaire XML manquant pour le type ou le membre visible publiquement
#pragma warning disable SA1600 // Elements should be documented
public static void AddOperation<T>(this SyncList<T> synclist, SyncList<T>.Operation op, int itemIndex, T oldItem, T newItem, bool checkAccess)
{
AddOperationMethodInfo.Invoke(synclist, new object[] { op, itemIndex, oldItem, newItem, checkAccess, });
}
#pragma warning restore CS1591 // Commentaire XML manquant pour le type ou le membre visible publiquement
#pragma warning restore SA1600 // Elements should be documented

/// <summary>
/// Plays a beep sound that only the target <paramref name="player"/> can hear.
/// </summary>
Expand Down
37 changes: 35 additions & 2 deletions Exiled.API/Features/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ public class Player : GameEntity
/// A list of the player's items.
/// </summary>
internal readonly List<Item> ItemsValue = new(8);
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
#pragma warning disable SA1600 // Elements should be documented
internal List<sbyte> categoryLimits;
internal List<ServerConfigSynchronizer.AmmoLimit> ammoLimits;
#pragma warning restore SA1600 // Elements should be documented
#pragma warning restore SA1307 // Accessible fields should begin with upper-case letter
#pragma warning restore SA1401

private ReferenceHub referenceHub;
Expand Down Expand Up @@ -2497,17 +2503,44 @@ public bool DropAmmo(AmmoType ammoType, ushort amount, bool checkMinimals = fals
/// </summary>
/// <param name="type">The <see cref="AmmoType"/> of the ammo to check.</param>
/// <returns>The maximum amount of ammo this player can carry. Guaranteed to be between <c>0</c> and <see cref="ServerConfigSynchronizer.AmmoLimit"/>.</returns>
public int GetAmmoLimit(AmmoType type) =>
public ushort GetAmmoLimit(AmmoType type) =>
InventorySystem.Configs.InventoryLimits.GetAmmoLimit(type.GetItemType(), referenceHub);

/// <summary>
/// Gets the maximum amount of ammo the player can hold, given the ammo <see cref="AmmoType"/>.
/// This method factors in the armor the player is wearing, as well as server configuration.
/// For the maximum amount of ammo that can be given regardless of worn armor and server configuration, see <see cref="ServerConfigSynchronizer.AmmoLimit"/>.
/// </summary>
/// <param name="ammotype">The <see cref="AmmoType"/> of the ammo to check.</param>
/// <param name="value">The <see cref="ushort"/> number that will define the new limit.</param>
public void SetAmmoLimit(AmmoType ammotype, ushort value)
{
ItemType itemtype = ammotype.GetItemType();
int index = ammoLimits.FindIndex(x => x.AmmoType == itemtype);
ammoLimits ??= ServerConfigSynchronizer.Singleton.AmmoLimitsSync.ToList();
ServerConfigSynchronizer.Singleton.AmmoLimitsSync.AddOperation(SyncList<ServerConfigSynchronizer.AmmoLimit>.Operation.OP_SET, index, ammoLimits[index], new() { Limit = value, AmmoType = itemtype }, false);
}

/// <summary>
/// Gets the maximum amount of an <see cref="ItemCategory"/> the player can hold, based on the armor the player is wearing, as well as server configuration.
/// </summary>
/// <param name="category">The <see cref="ItemCategory"/> to check.</param>
/// <returns>The maximum amount of items in the category that the player can hold.</returns>
public int GetCategoryLimit(ItemCategory category) =>
public sbyte GetCategoryLimit(ItemCategory category) =>
InventorySystem.Configs.InventoryLimits.GetCategoryLimit(category, referenceHub);

/// <summary>
/// Set the maximum amount of an <see cref="ItemCategory"/> the player can hold, based on the armor the player is wearing, as well as server configuration.
/// </summary>
/// <param name="category">The <see cref="ItemCategory"/> to check.</param>
/// <param name="value">The <see cref="int"/> number that will define the new limit.</param>
public void SetCategoryLimit(ItemCategory category, sbyte value)
{
categoryLimits ??= ServerConfigSynchronizer.Singleton.CategoryLimits.ToList();
categoryLimits[(int)category] = value;
ServerConfigSynchronizer.Singleton.CategoryLimits.AddOperation(SyncList<sbyte>.Operation.OP_SET, (int)category, categoryLimits[(int)category], value, false);
}

/// <summary>
/// Adds an item of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions Exiled.Events/Patches/Fixes/GetAmmoLimitFix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Exiled.Events.Patches.Fixes
using HarmonyLib;
using InventorySystem.Configs;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches the <see cref="InventoryLimits.GetAmmoLimit(InventorySystem.Items.Armor.BodyArmor, ItemType)"/> delegate.
/// Changes <see cref="ushort.MaxValue"/> to <see cref="ushort.MinValue"/>.
Expand Down
31 changes: 31 additions & 0 deletions Exiled.Events/Patches/Generic/GetCustomAmmoLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -----------------------------------------------------------------------
// <copyright file="GetCustomAmmoLimit.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Fixes
{
using System;

using HarmonyLib;
using InventorySystem.Configs;

/// <summary>
/// Patches the <see cref="InventoryLimits.GetAmmoLimit(ItemType, ReferenceHub)"/> delegate.
/// Sync <see cref="API.Features.Player.SetAmmoLimit(API.Enums.AmmoType, ushort)"/>.
/// Changes <see cref="ushort.MaxValue"/> to <see cref="ushort.MinValue"/>.
/// </summary>
[HarmonyPatch(typeof(InventoryLimits), nameof(InventoryLimits.GetAmmoLimit), new Type[] { typeof(ItemType), typeof(ReferenceHub), })]
internal class GetCustomAmmoLimit
{
private int Postfix(API.Features.Player player, int value, ItemType ammotype)
{
if (player?.ammoLimits is null)
return value;

return player.ammoLimits.Find(x => x.AmmoType == ammotype).Limit + value - InventoryLimits.GetAmmoLimit(null, ammotype);
}
}
}
31 changes: 31 additions & 0 deletions Exiled.Events/Patches/Generic/GetCustomCategoryLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -----------------------------------------------------------------------
// <copyright file="GetCustomCategoryLimit.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Fixes
{
using System;

using HarmonyLib;
using InventorySystem.Configs;

/// <summary>
/// Patches the <see cref="InventoryLimits.GetCategoryLimit(ItemCategory, ReferenceHub)"/> delegate.
/// Sync <see cref="API.Features.Player.SetAmmoLimit(API.Enums.AmmoType, ushort)"/>.
/// Changes <see cref="ushort.MaxValue"/> to <see cref="ushort.MinValue"/>.
/// </summary>
[HarmonyPatch(typeof(InventoryLimits), nameof(InventoryLimits.GetCategoryLimit), new Type[] { typeof(ItemCategory), typeof(ReferenceHub), })]
internal class GetCustomCategoryLimit
{
private int Postfix(API.Features.Player player, int value, ItemType ammotype)
{
if (player?.categoryLimits is null)
return value;

return player.categoryLimits[(int)ammotype] + value - InventoryLimits.GetAmmoLimit(null, ammotype);
}
}
}
Loading