using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MorePlayers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+f08f763ef75225fd68131819444998f59746f4bd")]
[assembly: AssemblyProduct("MorePlayers")]
[assembly: AssemblyTitle("MorePlayers")]
[assembly: AssemblyVersion("0.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace MorePlayers
{
internal sealed class ConfigurationManagerAttributes
{
public string DispName;
public int? Order;
}
[BepInPlugin("com.darkharasho.stonewards.moreplayers", "MorePlayers", "0.2.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.darkharasho.stonewards.moreplayers";
public const string PluginName = "MorePlayers";
public const string PluginVersion = "0.2.0";
internal static ManualLogSource Log;
internal static ConfigEntry<int> MaxPlayers;
internal static ConfigEntry<float> EnemyCountPerExtraPlayer;
internal static ConfigEntry<float> ResourceYieldPerExtraPlayer;
internal static ConfigEntry<float> CombatDifficultyMultiplier;
internal static ConfigEntry<float> ForgeCostMultiplier;
private Harmony _harmony;
private void Awake()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Expected O, but got Unknown
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Expected O, but got Unknown
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Expected O, but got Unknown
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Expected O, but got Unknown
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Expected O, but got Unknown
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
MaxPlayers = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPlayers", 8, new ConfigDescription("Most players allowed in a hosted session, including the host. The game's default is 4. Only the host needs this mod; takes effect the next time you host.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 64), new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Max players"
}
}));
EnemyCountPerExtraPlayer = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "EnemyCountPerExtraPlayer", 0.25f, new ConfigDescription("Extra enemies per wave for each player beyond 4, as a fraction of the wave. 0.25 means 8 players fight twice as many enemies. 0 turns it off. Bosses and other single spawns are never multiplied.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Enemy count per extra player"
}
}));
ResourceYieldPerExtraPlayer = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "ResourceYieldPerExtraPlayer", 0.15f, new ConfigDescription("Extra mining, enemy drop and barrel yield for each player beyond 4. 0.15 means 8 players get 1.6x. 0 turns it off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Resource yield per extra player"
}
}));
CombatDifficultyMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "CombatDifficultyMultiplier", 1f, new ConfigDescription("Multiplies the game's own enemy strength scaling once there are more than 4 players. 1 leaves it as vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Combat difficulty multiplier"
}
}));
ForgeCostMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "ForgeCostMultiplier", 1f, new ConfigDescription("Multiplies the game's own forge cost scaling once there are more than 4 players. 1 leaves it as vanilla. Applied in steps of about one player's worth of cost.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Forge cost multiplier"
}
}));
_harmony = new Harmony("com.darkharasho.stonewards.moreplayers");
_harmony.PatchAll();
Log.LogInfo((object)string.Format("{0} {1} loaded (max players {2})", "MorePlayers", "0.2.0", MaxPlayers.Value));
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
}
namespace MorePlayers.Patches
{
[HarmonyPatch(typeof(DifficultyManager), "OnStartServer")]
internal static class ResetPlayerCountPatch
{
private static void Prefix()
{
Scaling.RealPlayerCount = 0;
}
}
[HarmonyPatch(typeof(DifficultyManager), "SetPlayerCount")]
internal static class DifficultyScalingPatch
{
private static readonly FieldRef<DifficultyManager, float> BaseCombatScaling = AccessTools.FieldRefAccess<DifficultyManager, float>("baseCombatScaling");
private static readonly FieldRef<DifficultyManager, float> CombatScalingPerPlayer = AccessTools.FieldRefAccess<DifficultyManager, float>("combatScalingPerPlayer");
private static readonly FieldRef<DifficultyManager, float> BaseForgeScaling = AccessTools.FieldRefAccess<DifficultyManager, float>("baseForgeScaling");
private static readonly FieldRef<DifficultyManager, float> ForgeScalingPerPlayer = AccessTools.FieldRefAccess<DifficultyManager, float>("forgeScalingPerPlayer");
private static readonly MethodInfo Recalculate = AccessTools.Method(typeof(DifficultyManager), "Recalculate", (Type[])null, (Type[])null);
private static void Prefix(DifficultyManager __instance, ref int playerCount)
{
if (NetworkServer.active)
{
if (playerCount > Scaling.RealPlayerCount)
{
Scaling.RealPlayerCount = playerCount;
}
playerCount = ReportedForgeCount(__instance, playerCount);
}
}
private static void Postfix(DifficultyManager __instance)
{
if (NetworkServer.active && Scaling.ExtraPlayers != 0)
{
float num = (BaseCombatScaling.Invoke(__instance) + CombatScalingPerPlayer.Invoke(__instance) * (float)Scaling.RealPlayerCount) * Plugin.CombatDifficultyMultiplier.Value;
if (!Mathf.Approximately(__instance.NetworksyncPlayerFactor, num))
{
__instance.NetworksyncPlayerFactor = num;
Recalculate.Invoke(__instance, null);
}
}
}
private static int ReportedForgeCount(DifficultyManager manager, int playerCount)
{
float value = Plugin.ForgeCostMultiplier.Value;
if (playerCount <= 4 || value <= 1f)
{
return playerCount;
}
float num = BaseForgeScaling.Invoke(manager);
float num2 = ForgeScalingPerPlayer.Invoke(manager);
if (num2 <= 0f)
{
return playerCount;
}
float num3 = (num + num2 * (float)playerCount) * value;
return Mathf.Max(playerCount, Mathf.RoundToInt((num3 - num) / num2));
}
}
[HarmonyPatch(typeof(EnemyManager), "SpawnCurrentWave")]
internal static class EnemyCountPatch
{
private static EnemyWaveDataSO _lastClone;
private static void Prefix(ref EnemyWaveDataSO _Wave)
{
//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)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkServer.active || (Object)(object)_Wave == (Object)null || _Wave.Enemies == null)
{
return;
}
float num = 1f + Plugin.EnemyCountPerExtraPlayer.Value * (float)Scaling.ExtraPlayers;
if (num <= 1f)
{
return;
}
EnemyWaveDataSO val = Object.Instantiate<EnemyWaveDataSO>(_Wave);
List<SEnemyData> enemies = val.Enemies;
for (int i = 0; i < enemies.Count; i++)
{
SEnemyData val2 = enemies[i];
if (!(val2.countRange.y <= 1f))
{
int num2 = Scaling.RandomRound(val2.countRange.x * num);
int num3 = Mathf.Max(num2, Scaling.RandomRound(val2.countRange.y * num));
val2.countRange = new Vector2((float)num2, (float)num3);
enemies[i] = val2;
}
}
if ((Object)(object)_lastClone != (Object)null)
{
Object.Destroy((Object)(object)_lastClone);
}
_lastClone = val;
_Wave = val;
}
}
[HarmonyPatch(typeof(StoneWardsNetworkManager), "Awake")]
internal static class RaiseMaxConnectionsPatch
{
private static void Postfix(StoneWardsNetworkManager __instance)
{
Apply((NetworkManager)(object)__instance);
}
internal static void Apply(NetworkManager manager)
{
if (!((Object)(object)manager == (Object)null))
{
manager.maxConnections = Plugin.MaxPlayers.Value;
}
}
}
[HarmonyPatch(typeof(SteamLobby), "HostLobby")]
internal static class RefreshBeforeHostPatch
{
private static void Prefix()
{
RaiseMaxConnectionsPatch.Apply(NetworkManager.singleton);
}
}
[HarmonyPatch(typeof(HubPlayersNameHolder), "InitUI")]
internal static class HubPlayerCountLabelPatch
{
private static void Postfix(ref int ___maxPlayerCount)
{
if (___maxPlayerCount > 1)
{
___maxPlayerCount = NetworkManager.singleton.maxConnections;
}
}
}
internal static class ResourceYield
{
internal static int ScopeDepth;
private static bool _spawningExtra;
internal static void SpawnExtras(Action spawn)
{
if (_spawningExtra || !NetworkServer.active)
{
return;
}
float num = 1f + Plugin.ResourceYieldPerExtraPlayer.Value * (float)Scaling.ExtraPlayers;
if (num <= 1f)
{
return;
}
int num2 = Scaling.RandomRound(num - 1f);
_spawningExtra = true;
try
{
for (int i = 0; i < num2; i++)
{
spawn();
}
}
finally
{
_spawningExtra = false;
}
}
}
[HarmonyPatch(typeof(DiggingManager), "ServerTrySpawnResource")]
internal static class MiningScopePatch
{
private static void Prefix()
{
ResourceYield.ScopeDepth++;
}
private static void Finalizer()
{
ResourceYield.ScopeDepth--;
}
}
[HarmonyPatch(typeof(ItemBarrel), "ServerInit")]
internal static class BarrelScopePatch
{
private static void Prefix()
{
ResourceYield.ScopeDepth++;
}
private static void Finalizer()
{
ResourceYield.ScopeDepth--;
}
}
[HarmonyPatch(typeof(ItemManager), "ServerInstantiatePickableItem")]
internal static class PickableYieldPatch
{
private static void Postfix(ItemManager __instance, PickableItem __result, string _ItemID, int _Count, Vector3 _Position, bool forceShow, bool disableVfx)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if (ResourceYield.ScopeDepth == 0 || (Object)(object)__result == (Object)null)
{
return;
}
Quaternion rotation = ((Component)__result).transform.rotation;
ResourceYield.SpawnExtras(delegate
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
PickableItem val = __instance.ServerInstantiatePickableItem(_ItemID, _Count, _Position, forceShow, disableVfx);
if ((Object)(object)val != (Object)null)
{
((Component)val).transform.rotation = rotation;
}
});
}
}
[HarmonyPatch(typeof(ItemManager), "ServerInstantiateEnemyDrop")]
internal static class EnemyDropYieldPatch
{
private static void Postfix(ItemManager __instance, PickableItem __result, Vector3 _Position)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)__result == (Object)null))
{
ResourceYield.SpawnExtras(delegate
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
__instance.ServerInstantiateEnemyDrop(_Position);
});
}
}
}
internal static class Scaling
{
internal const int VanillaMaxPlayers = 4;
internal static int RealPlayerCount;
internal static int ExtraPlayers => Math.Max(0, RealPlayerCount - 4);
internal static int RandomRound(float value)
{
int num = Mathf.FloorToInt(value);
return num + ((Random.value < value - (float)num) ? 1 : 0);
}
}
}