diff --git a/README.md b/README.md
index b6c6abd..59773c6 100644
--- a/README.md
+++ b/README.md
@@ -1,84 +1,103 @@
-![enter image description here](https://i.imgur.com/OAfRGXK.jpg)
+![Valheim VeinMine](https://i.imgur.com/OAfRGXK.jpg)
+
Tired of mining for ages?
With Veinmine you're able to mine the whole ore/rock vein at once!
You can do this by holding down the assigned key (Left Alt by default) while mining!
+`Version checks with itself. If installed on the server, it will kick clients who do not have it installed.`
+
+`This mod uses ServerSync, if installed on the server and all clients, it will sync all configs to client`
+
+`This mod uses a file watcher. If the configuration file is not changed with BepInEx Configuration manager, but changed in the file directly on the server, upon file save, it will sync the changes to all clients.`
+
## **Version 1.0.0 - Progressive mode added!**
### **Please delete your previous config when updating as it might break something.**
-You can now enable progressive mode in the config, making it so veinmining is scaled by your Pickaxes level. This is intended to be a less OP way of veinmining, where the tradeoff is taking higher durability damage (and less xp) than if you mined manually.
+You can now enable progressive mode in the config, making it so veinmining is scaled by your Pickaxes level. This is
+intended to be a less OP way of veinmining, where the tradeoff is taking higher durability damage (and less xp) than if
+you mined manually.
+
+The radius of the veinmined area is also scaled by your Pickaxes level.
+
+It works by checking for rocks in a radius set by the Progressive Level Multiplier value in the config. This value is
+multiplied by your Pickaxes level to obtain a radius.
+
+By default, it's set to 0.1 so assuming your Pickaxes level is 20, the radius will be 0.1 * 20 = 2.
+
+What does 2 mean, you ask?
-The radius of the veinmined area is also scaled by your Pickaxes level.
-
-It works by checking for rocks in a radius set by the Progressive Level Multiplier value in the config. This value is multiplied by your Pickaxes level to obtain a radius.
-
-By default, it's set to 0.1 so assuming your Pickaxes level is 20, the radius will be 0.1 * 20 = 2.
-
-What does 2 mean, you ask?
-
It's simple! A standard 2x2 floor piece has a length of 2, exactly like its name suggests.
-# Changelog
-## 1.2.6
- - Compatibility with Mistlands and fix for Silver ore exception.
-### 1.2.5
- - Tentative fix for multiplayer veinmining by replacing the use of Player.m_localPlayer with Player.GetClosestPlayer.
-### 1.2.4
- - Fixed an exception that was thrown when mining Leviathans.
- - Added veinmining support for Leviathans and Glowing Metal (Flametal Ore).
-### 1.2.3
- - Fixed a bug that allowed players to veinmine (and gain exp) without a pickaxe.
-### 1.2.2
- - Possible fix for ore drop quantities (Not sure why they weren't correct, as I don't change drop rates)
-### 1.2.1
- - Compatibility for Hearth and Home;
- - Tentative fix for ores spawning at 0,0 (unable to test without other players)
-### 1.2.0
- - Replaced 'Even' spread damage option with 'Level' as even was useless when the mined vein had a large number of sections.
- - Refactored code.
-### 1.1.9
- - Fixed incompatibility with Rocky Ore mod.
-### 1.1.8
- - Fixed a bug that was causing no ores to be dropped (hopefully)
-### 1.1.7
- - Fixed a bug that caused ores to drop every single pickaxe swing when mining manually.
-### 1.1.6
- - Fixed a bug that was causing no drops to be received when veinmining.
-### 1.1.5
-#### Please delete your previous config when updating to this version.
- - Damage text when veinmining should now display on top of each rock section
- - Veinmining when Progressive mode is disabled is now instant
- - Spread damage now has two options: Even and Distance
- - Even is the same as previous versions
- - Distance makes it so the damage dealt to a rock section is based on distance. The farther away a section is, the less damage is dealt.
-
-### 1.1.4
- - Fixed a bug where if you had spread damage enabled, mining damage would also be reduced when mining manually.
-### 1.1.3
- - Added config option for spreading damage in progressive mode (divides your mining damage equally between all rock sections affected, as opposed to doing full damage to all sections)
- - This is disabled by default.
-### 1.1.2
- - Fixed incompatibility with mods that alter the pickaxe's durability drain values. The value modified by such mods (m_useDurabilityDrain) is now multiplied by the result of the previous formula (which is shown in the config). Take this into account when editing this mod's durability modifier.
-### 1.1.1
- - Added config options for durability and xp multipliers for Progressive mode.
-### 1.1.0
- - Durability taken is now scaled to the player's Pickaxes level when Progressive mode is enabled. This is meant to (somewhat) balance veinmining so it fits in with vanilla.
- - The formula is (120 - Level) / 20, so if you have level 50: (120 - 50) / 20 = 3.5 durability taken **per rock section veinmined**
-### 1.0.1
- - Removed log messages to avoid spam.
-### 1.0.0
- - Added Progressive mode.
-#### 0.0.1.4
- - Fixed a bug that allowed monsters to veinmine and/or give XP to the player.
-#### 0.0.1.3
- - Indestructible items no longer lose durability. (such as items from Epic Loot)
- - Added config option to disable mining visual effects, which *might* help reduce fps lag. (disabled by default)
-#### 0.0.1.2
- - Added config option for veinmining to take pickaxe durability for each section mined (default = true).
- - XP is now only awarded if the section mined wasn't already destroyed.
- - Fixed a NullReferenceException thrown when there were more than 128 rock sections.
-#### 0.0.1.1
- - Mining xp is now awarded for every rock section mined.
-#### 0.0.1.0
- - Initial release
+---
+
+
+Installation Instructions
+
+***You must have BepInEx installed correctly! I can not stress this enough.***
+
+### Manual Installation
+
+`Note: (Manual installation is likely how you have to do this on a server, make sure BepInEx is installed on the server correctly)`
+
+1. **Download the latest release of BepInEx.**
+2. **Extract the contents of the zip file to your game's root folder.**
+3. **Download the latest release of VeinMine from Thunderstore.io. (or Nexus Mods)**
+4. **Extract the contents of the zip file to the `BepInEx/plugins` folder.**
+5. **Launch the game.**
+
+### Installation through Vortex
+
+https://www.youtube.com/watch?v=Kt_6lwGd2Ns
+
+### Installation through r2modman or Thunderstore Mod Manager
+
+1. **Install [r2modman](https://valheim.thunderstore.io/package/ebkr/r2modman/)
+ or [Thunderstore Mod Manager](https://www.overwolf.com/app/Thunderstore-Thunderstore_Mod_Manager).**
+
+ > For r2modman, you can also install it through the Thunderstore site.
+ ![](https://i.imgur.com/s4X4rEs.png "r2modman Download")
+
+ > For Thunderstore Mod Manager, you can also install it through the Overwolf app store
+ ![](https://i.imgur.com/HQLZFp4.png "Thunderstore Mod Manager Download")
+2. **Open the Mod Manager and search for "" under the Online
+ tab. `Note: You can also search for "Azumatt" to find all my mods.`**
+
+ `The image below shows VikingShip as an example, but it was easier to reuse the image.`
+
+ ![](https://i.imgur.com/5CR5XKu.png)
+
+3. **Click the Download button to install the mod.**
+4. **Launch the game.**
+
+
+
+
+
+
+`Feel free to reach out to me on discord if you need manual download assistance.`
+
+# Current Author (Maintainer) Information
+
+### Azumatt
+
+`DISCORD:` Azumatt#2625
+
+`STEAM:` https://steamcommunity.com/id/azumatt/
+
+`GITHUB:` https://github.com/AzumattDev
+
+For Questions or Comments, find me in the Odin Plus Team Discord or in mine:
+
+[![https://i.imgur.com/XXP6HCU.png](https://i.imgur.com/XXP6HCU.png)](https://discord.gg/Pb6bVMnFb2)
+
+
+
+
+# Original Author Information
+
+### WiseHorror
+
+`DISCORD:` WiseHorror (wisehorror)
+
+`GitHub:` https://github.com/WiseHorror
\ No newline at end of file
diff --git a/VeinMine/.gitignore b/VeinMine/.gitignore
index 2f36f26..d7d1412 100644
--- a/VeinMine/.gitignore
+++ b/VeinMine/.gitignore
@@ -1 +1,8 @@
-libs/
\ No newline at end of file
+bin/
+obj/
+/packages/
+riderModule.iml
+/_ReSharper.Caches/
+VeinMine.sln.DotSettings.user
+.idea
+.vs
\ No newline at end of file
diff --git a/VeinMine/Functions.cs b/VeinMine/Functions.cs
index 3c3f095..51bbbca 100644
--- a/VeinMine/Functions.cs
+++ b/VeinMine/Functions.cs
@@ -1,6 +1,6 @@
using UnityEngine;
-namespace WiseHorror.Veinmine
+namespace Veinmine
{
class Functions
{
@@ -34,7 +34,7 @@ public static HitData SpreadDamage(HitData hit)
{
if (hit != null)
{
- if (VeinMine.spreadDamageType.Value == VeinMine.spreadTypes.level)
+ if (VeinMinePlugin.spreadDamageType.Value == VeinMinePlugin.SpreadTypes.Level)
{
float modifier = (float)GetSkillLevel(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes) * 0.01f;
hit.m_damage.m_pickaxe *= modifier;
diff --git a/VeinMine/ILRepack.targets b/VeinMine/ILRepack.targets
new file mode 100644
index 0000000..de9853d
--- /dev/null
+++ b/VeinMine/ILRepack.targets
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VeinMine/LICENSE.md b/VeinMine/LICENSE.md
new file mode 100644
index 0000000..262826b
--- /dev/null
+++ b/VeinMine/LICENSE.md
@@ -0,0 +1,5 @@
+Copyright 2023 WiseHorror/Azumatt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/VeinMine/Nexus/Veinmine_v1.2.8.zip b/VeinMine/Nexus/Veinmine_v1.2.8.zip
new file mode 100644
index 0000000..0b3b9d0
Binary files /dev/null and b/VeinMine/Nexus/Veinmine_v1.2.8.zip differ
diff --git a/VeinMine/Patches.cs b/VeinMine/Patches.cs
index 328c9f0..21dfeaa 100644
--- a/VeinMine/Patches.cs
+++ b/VeinMine/Patches.cs
@@ -1,78 +1,39 @@
-using HarmonyLib;
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Linq;
+using HarmonyLib;
using UnityEngine;
-namespace WiseHorror.Veinmine
+namespace Veinmine
{
[HarmonyPatch(typeof(MineRock), nameof(MineRock.Damage))]
static class MineRockDamagePatch
{
static bool Prefix(MineRock __instance, HitData hit)
{
- if (Input.GetKey(VeinMine.veinMineKey.Value))
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 5f);
+
+ if (VeinMinePlugin.veinMineKey.Value.IsKeyHeld())
{
- if (VeinMine.progressiveMode.Value)
+ Vector3 firstHitPoint = hit.m_point;
+ foreach (var area in __instance.m_hitAreas)
{
- float radius = VeinMine.progressiveMult.Value * (float)Functions.GetSkillLevel(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes);
- Vector3 firstHitPoint = hit.m_point;
+ if (area == null) continue;
- foreach (var area in __instance.m_hitAreas)
+ if (VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.On)
{
- if (Functions.GetDistanceFromPlayer(Player.GetClosestPlayer(hit.m_point, 5f).GetTransform().position, area.bounds.center) <= radius && area != null)
- {
- hit.m_point = area.transform.position;
- hit.m_hitCollider = area;
- if (hit.m_hitCollider == null)
- {
- ZLog.Log("Minerock hit has no collider");
- return false;
- }
+ float radius = VeinMinePlugin.progressiveMult.Value * (float)Functions.GetSkillLevel(closestPlayer.GetSkills(), Skills.SkillType.Pickaxes);
- int areaIndex = __instance.GetAreaIndex(hit.m_hitCollider);
- if (areaIndex == -1)
- {
- //ZLog.Log("Invalid hit area on " + base.gameObject.name);
- return false;
- }
-
- ZLog.Log("Hit mine rock area " + areaIndex);
- __instance.m_nview.InvokeRPC("Hit", new object[]
- {
- hit,
- areaIndex
- });
- hit.m_point = firstHitPoint;
+ if (Functions.GetDistanceFromPlayer(closestPlayer.GetTransform().position, area.bounds.center) <= radius)
+ {
+ ProcessHitArea(__instance, hit, area, firstHitPoint);
}
}
- }
- else
- {
- foreach (var area in __instance.m_hitAreas)
+ else
{
- string hpAreaName = "Health" + __instance.GetAreaIndex(area).ToString();
+ string hpAreaName = $"Health{__instance.GetAreaIndex(area)}";
hit.m_damage.m_pickaxe = __instance.m_nview.GetZDO().GetFloat(hpAreaName, __instance.m_health);
- hit.m_point = __instance.GetHitArea(__instance.GetAreaIndex(area)).bounds.center;
- hit.m_hitCollider = area;
- if (hit.m_hitCollider == null)
- {
- ZLog.Log("Minerock hit has no collider");
- return false;
- }
-
- int areaIndex = __instance.GetAreaIndex(hit.m_hitCollider);
- if (areaIndex == -1)
- {
- //ZLog.Log("Invalid hit area on " + base.gameObject.name);
- return false;
- }
-
- ZLog.Log("Hit mine rock area " + areaIndex);
- __instance.m_nview.InvokeRPC("Hit", new object[]
- {
- hit,
- areaIndex
- });
+ hit.m_point = area.bounds.center;
+ ProcessHitArea(__instance, hit, area, firstHitPoint);
}
}
@@ -81,8 +42,26 @@ static bool Prefix(MineRock __instance, HitData hit)
return true;
}
+
+ private static void ProcessHitArea(MineRock __instance, HitData hit, Collider area, Vector3 firstHitPoint)
+ {
+ hit.m_hitCollider = area;
+ if (hit.m_hitCollider == null)
+ {
+ VeinMinePlugin.logger.LogInfo("Minerock hit has no collider");
+ return;
+ }
+
+ int areaIndex = __instance.GetAreaIndex(hit.m_hitCollider);
+ if (areaIndex == -1) return;
+
+ VeinMinePlugin.logger.LogInfo($"Hit mine rock area {areaIndex}");
+ __instance.m_nview.InvokeRPC("Hit", hit, areaIndex);
+ hit.m_point = firstHitPoint;
+ }
}
+
[HarmonyPatch(typeof(MineRock5), nameof(MineRock5.Damage))]
static class MineRock5DamagePatch
{
@@ -91,66 +70,50 @@ static void Prefix(MineRock5 __instance, HitData hit, out Dictionary();
- if (Input.GetKey(VeinMine.veinMineKey.Value) && VeinMine.progressiveMode.Value)
- {
- var radiusColliders = Physics.OverlapSphere(hit.m_point, VeinMine.progressiveMult.Value * (float)Functions.GetSkillLevel(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes));
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 5f);
+ float radius = VeinMinePlugin.progressiveMult.Value * (float)Functions.GetSkillLevel(closestPlayer.GetSkills(), Skills.SkillType.Pickaxes);
- if (radiusColliders != null)
- {
- foreach (var area in radiusColliders)
- {
- if (__instance.GetAreaIndex(area) >= 0)
- {
- __state.Add(__instance.GetAreaIndex(area), __instance.GetHitArea(__instance.GetAreaIndex(area)).m_bound.m_pos +
- __instance.GetHitArea(__instance.GetAreaIndex(area)).m_collider.transform.position);
- }
- }
- }
- }
-
- if (Input.GetKey(VeinMine.veinMineKey.Value) && !VeinMine.progressiveMode.Value)
+ if (VeinMinePlugin.veinMineKey.Value.IsKeyHeld())
{
- List radiusColliders = new List();
- foreach (var area in __instance.m_hitAreas)
- {
- radiusColliders.Add(area.m_collider);
- }
+ IEnumerable radiusColliders;
+
+ if (VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.On)
+ radiusColliders = Physics.OverlapSphere(hit.m_point, radius);
+ else
+ radiusColliders = __instance.m_hitAreas.Select(area => area.m_collider);
- if (radiusColliders != null)
+ foreach (var area in radiusColliders)
{
- foreach (var area in radiusColliders)
+ int areaIndex = __instance.GetAreaIndex(area);
+ if (areaIndex >= 0)
{
- if (__instance.GetAreaIndex(area) >= 0)
- {
- __state.Add(__instance.GetAreaIndex(area), __instance.GetHitArea(__instance.GetAreaIndex(area)).m_bound.m_pos +
- __instance.GetHitArea(__instance.GetAreaIndex(area)).m_collider.transform.position);
- }
+ __state.Add(areaIndex,
+ __instance.GetHitArea(areaIndex).m_bound.m_pos +
+ __instance.GetHitArea(areaIndex).m_collider.transform.position);
}
}
}
}
- public static void Postfix(MineRock5 __instance, ZNetView ___m_nview, List ___m_hitAreas, HitData hit, Dictionary __state)
+ public static void Postfix(MineRock5 __instance, ZNetView ___m_nview, HitData hit, Dictionary __state)
{
- if (Player.GetClosestPlayer(hit.m_point, 5f) != null && hit.m_attacker == Player.GetClosestPlayer(hit.m_point, 5f).GetZDOID())
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 5f);
+ if (closestPlayer != null && hit.m_attacker == closestPlayer.GetZDOID() && VeinMinePlugin.veinMineKey.Value.IsKeyHeld())
{
- if (Input.GetKey(VeinMine.veinMineKey.Value) && Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().GetDamage().m_pickaxe > 0)
+ var currentWeapon = closestPlayer.GetCurrentWeapon();
+ if (currentWeapon.GetDamage().m_pickaxe > 0)
{
foreach (var index in __state)
{
- if (Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_durability > 0 || !Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_shared.m_useDurability)
+ if (currentWeapon.m_durability > 0 || !currentWeapon.m_shared.m_useDurability)
{
try
{
- ___m_nview.InvokeRPC("Damage", new object[]
- {
- hit,
- index.Key
- });
+ ___m_nview.InvokeRPC("Damage", hit, index.Key);
}
catch
{
- VeinMine.logger.LogInfo("Skipping section: " + index.Key + ".");
+ VeinMinePlugin.logger.LogInfo($"Skipping section: {index.Key}.");
}
}
}
@@ -159,35 +122,44 @@ public static void Postfix(MineRock5 __instance, ZNetView ___m_nview, List 0f) hit.m_damage.m_pickaxe = __instance.m_health;
- bool isVeinmined = false;
+ if (VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.Off && currentWeapon.GetDamage().m_pickaxe > 0f) hit.m_damage.m_pickaxe = __instance.m_health;
+
MineRock5.HitArea hitArea = __instance.GetHitArea(hitAreaIndex);
+ if (hitArea == null)
+ {
+ VeinMinePlugin.logger.LogInfo($"Missing hit area {hitAreaIndex}");
+ __state = 0f;
+ __result = false;
+ return false;
+ }
+
__state = hitArea.m_health;
Vector3 hitPoint = hitArea.m_collider.bounds.center;
- if (VeinMine.enableSpreadDamage.Value) hit = Functions.SpreadDamage(hit);
- if (Input.GetKey(VeinMine.veinMineKey.Value)) isVeinmined = true;
+ if (VeinMinePlugin.enableSpreadDamage.Value == VeinMinePlugin.Toggle.On) hit = Functions.SpreadDamage(hit);
+
+ bool isVeinmined = VeinMinePlugin.veinMineKey.Value.IsKeyHeld();
+ VeinMinePlugin.logger.LogInfo($"Hit mine rock {hitAreaIndex}");
- ZLog.Log("hit mine rock " + hitAreaIndex);
if (hitArea == null)
{
- ZLog.Log("Missing hit area " + hitAreaIndex);
+ VeinMinePlugin.logger.LogInfo($"Missing hit area {hitAreaIndex}");
__result = false;
return false;
}
@@ -195,7 +167,7 @@ static bool Prefix(MineRock5 __instance, HitData hit, int hitAreaIndex, ref Effe
__instance.LoadHealth();
if (hitArea.m_health <= 0f)
{
- ZLog.Log("Already destroyed");
+ VeinMinePlugin.logger.LogInfo("Already destroyed");
__result = false;
return false;
}
@@ -219,7 +191,7 @@ static bool Prefix(MineRock5 __instance, HitData hit, int hitAreaIndex, ref Effe
hitArea.m_health -= totalDamage;
__instance.SaveHealth();
- if (!VeinMine.removeEffects.Value) __instance.m_hitEffect.Create(hitPoint, Quaternion.identity, null, 1f, -1);
+ if (VeinMinePlugin.removeEffects.Value == VeinMinePlugin.Toggle.Off) __instance.m_hitEffect.Create(hitPoint, Quaternion.identity, null, 1f, -1);
Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 10f);
if (closestPlayer)
{
@@ -233,7 +205,7 @@ static bool Prefix(MineRock5 __instance, HitData hit, int hitAreaIndex, ref Effe
hitAreaIndex,
hitArea.m_health
});
- if (!VeinMine.removeEffects.Value) __instance.m_destroyedEffect.Create(hitPoint, Quaternion.identity, null, 1f, -1);
+ if (VeinMinePlugin.removeEffects.Value == VeinMinePlugin.Toggle.Off) __instance.m_destroyedEffect.Create(hitPoint, Quaternion.identity, null, 1f, -1);
foreach (GameObject gameObject in __instance.m_dropItems.GetDropList())
{
if (isVeinmined)
@@ -265,32 +237,32 @@ static bool Prefix(MineRock5 __instance, HitData hit, int hitAreaIndex, ref Effe
static void Postfix(MineRock5 __instance, HitData hit, float __state, bool __result)
{
- if (
- hit != null
- && Player.GetClosestPlayer(hit.m_point, 5f) != null
- && Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon() != null
- )
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 5f);
+ ItemDrop.ItemData? currentWeapon = closestPlayer?.GetCurrentWeapon();
+
+ if (hit != null && closestPlayer != null && currentWeapon != null && VeinMinePlugin.veinMineKey.Value.IsKeyHeld() && currentWeapon.GetDamage().m_pickaxe > 0)
{
- if (Input.GetKey(VeinMine.veinMineKey.Value) && Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().GetDamage().m_pickaxe > 0)
+ if (__state > 0f && hit.m_attacker == closestPlayer.GetZDOID())
{
- if (__state > 0f && hit.m_attacker == Player.GetClosestPlayer(hit.m_point, 5f).GetZDOID() && !VeinMine.progressiveMode.Value)
- {
- Player.GetClosestPlayer(hit.m_point, 5f).RaiseSkill(Skills.SkillType.Pickaxes, Functions.GetSkillIncreaseStep(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes));
+ var skills = closestPlayer.GetSkills();
+ float skillIncreaseStep = Functions.GetSkillIncreaseStep(skills, Skills.SkillType.Pickaxes);
- if (VeinMine.veinMineDurability.Value && Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_shared.m_useDurability)
- {
- Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_durability -= Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_shared.m_useDurabilityDrain;
- }
+ if (VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.Off)
+ {
+ closestPlayer.RaiseSkill(Skills.SkillType.Pickaxes, skillIncreaseStep);
+ }
+ else // VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.On
+ {
+ closestPlayer.RaiseSkill(Skills.SkillType.Pickaxes, skillIncreaseStep * VeinMinePlugin.xpMult.Value);
}
- else if (__state > 0f && hit.m_attacker == Player.GetClosestPlayer(hit.m_point, 5f).GetZDOID() && VeinMine.progressiveMode.Value)
+
+ if (VeinMinePlugin.veinMineDurability.Value == VeinMinePlugin.Toggle.On && currentWeapon.m_shared.m_useDurability)
{
- Player.GetClosestPlayer(hit.m_point, 5f).RaiseSkill(Skills.SkillType.Pickaxes, Functions.GetSkillIncreaseStep(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes) * VeinMine.xpMult.Value);
+ float durabilityLoss = VeinMinePlugin.progressiveMode.Value == VeinMinePlugin.Toggle.On
+ ? currentWeapon.m_shared.m_useDurabilityDrain * ((120 - Functions.GetSkillLevel(skills, Skills.SkillType.Pickaxes)) / (20 * VeinMinePlugin.durabilityMult.Value))
+ : currentWeapon.m_shared.m_useDurabilityDrain;
- if (VeinMine.veinMineDurability.Value && Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_shared.m_useDurability)
- {
- float durabilityLoss = Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_shared.m_useDurabilityDrain * ((120 - Functions.GetSkillLevel(Player.GetClosestPlayer(hit.m_point, 5f).GetSkills(), Skills.SkillType.Pickaxes)) / (20 * VeinMine.durabilityMult.Value));
- Player.GetClosestPlayer(hit.m_point, 5f).GetCurrentWeapon().m_durability -= durabilityLoss;
- }
+ currentWeapon.m_durability -= durabilityLoss;
}
}
}
diff --git a/VeinMine/Properties/AssemblyInfo.cs b/VeinMine/Properties/AssemblyInfo.cs
index db253c5..0ca69a2 100644
--- a/VeinMine/Properties/AssemblyInfo.cs
+++ b/VeinMine/Properties/AssemblyInfo.cs
@@ -1,16 +1,17 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using Veinmine;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("Veinmine")]
+[assembly: AssemblyTitle(VeinMinePlugin.ModName)]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Veinmine")]
-[assembly: AssemblyCopyright("Copyright © WiseHorror 2021")]
+[assembly: AssemblyCompany($"{VeinMinePlugin.Author} & Azumatt")]
+[assembly: AssemblyProduct(VeinMinePlugin.ModName)]
+[assembly: AssemblyCopyright("Copyright © WiseHorror/Azumatt 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +33,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.7.0")]
-[assembly: AssemblyFileVersion("1.2.7.0")]
+[assembly: AssemblyVersion(VeinMinePlugin.ModVersion)]
+[assembly: AssemblyFileVersion(VeinMinePlugin.ModVersion)]
\ No newline at end of file
diff --git a/VeinMine/Thunderstore/CHANGELOG.md b/VeinMine/Thunderstore/CHANGELOG.md
new file mode 100644
index 0000000..64ab3ae
--- /dev/null
+++ b/VeinMine/Thunderstore/CHANGELOG.md
@@ -0,0 +1,133 @@
+## 1.2.8
+
+- Azumatt begins maintaining the mod. (Thanks WiseHorror for the opportunity!)
+- `Changes to the configuration file have been made. Please delete your previous config when updating to this version. Sorry for the inconvenience.`
+- Refactor a lot of code to make it more readable.
+- Addition of ServerSync internally to allow for syncing of config between players and the server.
+ - This addition adds a new config option to enable/disable syncing of config between players and the server.
+- Change the project to have more automation in the build process so that it is easier to maintain and push updates out
+ faster.
+- Addition of MIT license to the code repository per WiseHorror's request.
+- Update the README.md to have more information and add installation instructions.
+
+## 1.2.7
+
+- Fixed mod being broken.
+- Infinite durability can now be enabled for progressive mode.
+
+### 1.2.6
+
+- Compatibility with Mistlands and fix for Silver ore exception.
+
+### 1.2.5
+
+- Tentative fix for multiplayer veinmining by replacing the use of Player.m_localPlayer with Player.GetClosestPlayer.
+
+### 1.2.4
+
+- Fixed an exception that was thrown when mining Leviathans.
+- Added veinmining support for Leviathans and Glowing Metal (Flametal Ore).
+
+### 1.2.3
+
+- Fixed a bug that allowed players to veinmine (and gain exp) without a pickaxe.
+
+### 1.2.2
+
+- Possible fix for ore drop quantities (Not sure why they weren't correct, as I don't change drop rates)
+
+### 1.2.1
+
+- Compatibility for Hearth and Home;
+- Tentative fix for ores spawning at 0,0 (unable to test without other players)
+
+### 1.2.0
+
+- Replaced 'Even' spread damage option with 'Level' as even was useless when the mined vein had a large number of
+ sections.
+- Refactored code.
+
+### 1.1.9
+
+- Fixed incompatibility with Rocky Ore mod.
+
+### 1.1.8
+
+- Fixed a bug that was causing no ores to be dropped (hopefully)
+
+### 1.1.7
+
+- Fixed a bug that caused ores to drop every single pickaxe swing when mining manually.
+
+### 1.1.6
+
+- Fixed a bug that was causing no drops to be received when veinmining.
+
+### 1.1.5
+
+#### Please delete your previous config when updating to this version.
+
+- Damage text when veinmining should now display on top of each rock section
+- Veinmining when Progressive mode is disabled is now instant
+- Spread damage now has two options: Even and Distance
+ - Even is the same as previous versions
+ - Distance makes it so the damage dealt to a rock section is based on distance. The farther away a section is, the
+ less damage is dealt.
+
+### 1.1.4
+
+- Fixed a bug where if you had spread damage enabled, mining damage would also be reduced when mining manually.
+
+### 1.1.3
+
+- Added config option for spreading damage in progressive mode (divides your mining damage equally between all rock
+ sections affected, as opposed to doing full damage to all sections)
+- This is disabled by default.
+
+### 1.1.2
+
+- Fixed incompatibility with mods that alter the pickaxe's durability drain values. The value modified by such mods (
+ m_useDurabilityDrain) is now multiplied by the result of the previous formula (which is shown in the config). Take
+ this into account when editing this mod's durability modifier.
+
+### 1.1.1
+
+- Added config options for durability and xp multipliers for Progressive mode.
+
+### 1.1.0
+
+- Durability taken is now scaled to the player's Pickaxes level when Progressive mode is enabled. This is meant to (
+ somewhat) balance veinmining so it fits in with vanilla.
+- The formula is (120 - Level) / 20, so if you have level 50: (120 - 50) / 20 = 3.5 durability taken **per rock section
+ veinmined**
+
+### 1.0.1
+
+- Removed log messages to avoid spam.
+
+### 1.0.0
+
+- Added Progressive mode.
+
+#### 0.0.1.4
+
+- Fixed a bug that allowed monsters to veinmine and/or give XP to the player.
+
+#### 0.0.1.3
+
+- Indestructible items no longer lose durability. (such as items from Epic Loot)
+- Added config option to disable mining visual effects, which *might* help reduce fps lag. (disabled by default)
+
+#### 0.0.1.2
+
+- Added config option for veinmining to take pickaxe durability for each section mined (default = true).
+- XP is now only awarded if the section mined wasn't already destroyed.
+- Fixed a NullReferenceException thrown when there were more than 128 rock sections.
+
+#### 0.0.1.1
+
+- Mining xp is now awarded for every rock section mined.
+
+#### 0.0.1.0
+
+- Initial release
\ No newline at end of file
diff --git a/VeinMine/Thunderstore/README.md b/VeinMine/Thunderstore/README.md
new file mode 100644
index 0000000..59773c6
--- /dev/null
+++ b/VeinMine/Thunderstore/README.md
@@ -0,0 +1,103 @@
+![Valheim VeinMine](https://i.imgur.com/OAfRGXK.jpg)
+
+Tired of mining for ages?
+With Veinmine you're able to mine the whole ore/rock vein at once!
+You can do this by holding down the assigned key (Left Alt by default) while mining!
+
+`Version checks with itself. If installed on the server, it will kick clients who do not have it installed.`
+
+`This mod uses ServerSync, if installed on the server and all clients, it will sync all configs to client`
+
+`This mod uses a file watcher. If the configuration file is not changed with BepInEx Configuration manager, but changed in the file directly on the server, upon file save, it will sync the changes to all clients.`
+
+## **Version 1.0.0 - Progressive mode added!**
+
+### **Please delete your previous config when updating as it might break something.**
+
+You can now enable progressive mode in the config, making it so veinmining is scaled by your Pickaxes level. This is
+intended to be a less OP way of veinmining, where the tradeoff is taking higher durability damage (and less xp) than if
+you mined manually.
+
+The radius of the veinmined area is also scaled by your Pickaxes level.
+
+It works by checking for rocks in a radius set by the Progressive Level Multiplier value in the config. This value is
+multiplied by your Pickaxes level to obtain a radius.
+
+By default, it's set to 0.1 so assuming your Pickaxes level is 20, the radius will be 0.1 * 20 = 2.
+
+What does 2 mean, you ask?
+
+It's simple! A standard 2x2 floor piece has a length of 2, exactly like its name suggests.
+
+---
+
+
+Installation Instructions
+
+***You must have BepInEx installed correctly! I can not stress this enough.***
+
+### Manual Installation
+
+`Note: (Manual installation is likely how you have to do this on a server, make sure BepInEx is installed on the server correctly)`
+
+1. **Download the latest release of BepInEx.**
+2. **Extract the contents of the zip file to your game's root folder.**
+3. **Download the latest release of VeinMine from Thunderstore.io. (or Nexus Mods)**
+4. **Extract the contents of the zip file to the `BepInEx/plugins` folder.**
+5. **Launch the game.**
+
+### Installation through Vortex
+
+https://www.youtube.com/watch?v=Kt_6lwGd2Ns
+
+### Installation through r2modman or Thunderstore Mod Manager
+
+1. **Install [r2modman](https://valheim.thunderstore.io/package/ebkr/r2modman/)
+ or [Thunderstore Mod Manager](https://www.overwolf.com/app/Thunderstore-Thunderstore_Mod_Manager).**
+
+ > For r2modman, you can also install it through the Thunderstore site.
+ ![](https://i.imgur.com/s4X4rEs.png "r2modman Download")
+
+ > For Thunderstore Mod Manager, you can also install it through the Overwolf app store
+ ![](https://i.imgur.com/HQLZFp4.png "Thunderstore Mod Manager Download")
+2. **Open the Mod Manager and search for "" under the Online
+ tab. `Note: You can also search for "Azumatt" to find all my mods.`**
+
+ `The image below shows VikingShip as an example, but it was easier to reuse the image.`
+
+ ![](https://i.imgur.com/5CR5XKu.png)
+
+3. **Click the Download button to install the mod.**
+4. **Launch the game.**
+
+
+
+
+
+
+`Feel free to reach out to me on discord if you need manual download assistance.`
+
+# Current Author (Maintainer) Information
+
+### Azumatt
+
+`DISCORD:` Azumatt#2625
+
+`STEAM:` https://steamcommunity.com/id/azumatt/
+
+`GITHUB:` https://github.com/AzumattDev
+
+For Questions or Comments, find me in the Odin Plus Team Discord or in mine:
+
+[![https://i.imgur.com/XXP6HCU.png](https://i.imgur.com/XXP6HCU.png)](https://discord.gg/Pb6bVMnFb2)
+
+
+
+
+# Original Author Information
+
+### WiseHorror
+
+`DISCORD:` WiseHorror (wisehorror)
+
+`GitHub:` https://github.com/WiseHorror
\ No newline at end of file
diff --git a/VeinMine/Thunderstore/Veinmine_v1.2.8.zip b/VeinMine/Thunderstore/Veinmine_v1.2.8.zip
new file mode 100644
index 0000000..8a58a78
Binary files /dev/null and b/VeinMine/Thunderstore/Veinmine_v1.2.8.zip differ
diff --git a/VeinMine/Thunderstore/icon.png b/VeinMine/Thunderstore/icon.png
new file mode 100644
index 0000000..d7b01c4
Binary files /dev/null and b/VeinMine/Thunderstore/icon.png differ
diff --git a/VeinMine/Thunderstore/manifest.json b/VeinMine/Thunderstore/manifest.json
new file mode 100644
index 0000000..ac15fb4
--- /dev/null
+++ b/VeinMine/Thunderstore/manifest.json
@@ -0,0 +1,9 @@
+{
+ "name": "Veinmine",
+ "version_number": "1.2.8",
+ "website_url": "https://www.nexusmods.com/valheim/mods/556",
+ "description": "Allows you to mine a whole rock/ore vein by holding down a key. Progressive mode is a less OP version meant to fit in better in Vanilla",
+ "dependencies": [
+ "denikson-BepInExPack_Valheim-5.4.2105"
+ ]
+}
diff --git a/VeinMine/UpdateManifest.ps1 b/VeinMine/UpdateManifest.ps1
new file mode 100644
index 0000000..09c3b53
--- /dev/null
+++ b/VeinMine/UpdateManifest.ps1
@@ -0,0 +1,9 @@
+param ($manifestFile, $versionString)
+
+try {
+ $manifest = Get-Content $manifestFile
+ $manifest = $manifest -replace '"version_number":\s*"([^"]*)"', "`"version_number`": `"$versionString`""
+ Set-Content -Path $manifestFile -Value $manifest
+} catch {
+ Write-Error $_.Exception.Message
+}
diff --git a/VeinMine/VeinMine.cs b/VeinMine/VeinMine.cs
deleted file mode 100644
index 78e8c43..0000000
--- a/VeinMine/VeinMine.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using BepInEx;
-using BepInEx.Configuration;
-using BepInEx.Logging;
-using HarmonyLib;
-using UnityEngine;
-
-namespace WiseHorror.Veinmine
-{
- [BepInPlugin(MOD_ID, MOD_NAME, VERSION)]
- [BepInProcess("valheim.exe")]
- [BepInProcess("valheim_server.exe")]
- [HarmonyPatch]
- public class VeinMine : BaseUnityPlugin
- {
- private const string MOD_ID = "com.wisehorror.Veinmine";
- private const string MOD_NAME = "Veinmine";
- private const string VERSION = "1.2.7";
-
- public static ManualLogSource logger = BepInEx.Logging.Logger.CreateLogSource("Veinmine");
-
- public enum spreadTypes
- {
- level,
- distance
- }
-
- void Awake()
- {
- veinMineKey = Config.Bind("General",
- "Veinmine",
- KeyCode.LeftAlt,
- "Key (or button) to hold for veinmining. Refer to https://docs.unity3d.com/Manual/class-InputManager.html");
-
- veinMineDurability = Config.Bind("General",
- "Durability",
- true,
- "Veinmining takes durability as if you mined every section manually.");
-
- removeEffects = Config.Bind("Visual",
- "Remove Effects",
- false,
- "Remove mining visual effects to try to *possibly* reduce fps lag ");
-
- progressiveMode = Config.Bind("Progressive",
- "Enable Progressive",
- false,
- "Progressive mode scales the number of sections mined according to the player's Pickaxes level.");
-
- progressiveMult = Config.Bind("Progressive",
- "Radius Multiplier",
- 0.1f,
- "Radius around your hit area to veinmine. This value is multiplied by the player's Pickaxes level.\n" +
- "Keep in mind 1 is the same length as the 1x1 wood floor.\n" +
- "So if you have Lvl 30 and set this value to 0.1, you will veinmine rocks in a radius of 3 (0.1 * 30 = 3).");
-
- durabilityMult = Config.Bind("Progressive",
- "Durability Multiplier",
- 1f,
- "Determines durability lost when veinmining.\n" +
- "The formula is (120 - Pickaxes level) / (20 * multiplier) where \"multiplier\" is this value.");
-
- xpMult = Config.Bind("Progressive",
- "XP Multiplier",
- 0.2f,
- "Multiplier for XP gained per rock section veinmined.");
-
- enableSpreadDamage = Config.Bind("Progressive",
- "Enable Spread Damage",
- false,
- "Spreads your hit damage throughout all rock sections mined, as opposed to hitting every section for the total amount of damage.");
-
- spreadDamageType = Config.Bind("Progressive",
- "Spread Damage Type",
- spreadTypes.distance,
- "Level: Scales damage done to each section based on your Pickaxes level.\n" +
- "Distance: Calculates damage done to each section based on your distance from it, the farther away, the less damage you do.");
-
- Harmony harmony = new Harmony(MOD_ID);
- harmony.PatchAll();
- }
-
- public static ConfigEntry veinMineKey;
- public static ConfigEntry veinMineDurability;
- public static ConfigEntry removeEffects;
- public static ConfigEntry progressiveMode;
- public static ConfigEntry enableSpreadDamage;
- public static ConfigEntry spreadDamageType;
- public static ConfigEntry progressiveMult;
- public static ConfigEntry durabilityMult;
- public static ConfigEntry xpMult;
-
-
- }
-}
\ No newline at end of file
diff --git a/VeinMine/VeinMine.csproj b/VeinMine/VeinMine.csproj
index 8777342..1008606 100644
--- a/VeinMine/VeinMine.csproj
+++ b/VeinMine/VeinMine.csproj
@@ -1,88 +1,244 @@
-
-
- Debug
- AnyCPU
- {B89BA476-237B-4A9B-837D-C6D07174918D}
- Library
- Properties
- Veinmine
- Veinmine
- v4.6.2
- 512
- true
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- true
-
-
-
- libs\0Harmony.dll
-
-
- libs\assembly_guiutils_public.dll
-
-
- libs\assembly_utils_public.dll
-
-
- libs\assembly_valheim_public.dll
-
-
- libs\BepInEx.dll
-
-
-
-
-
-
-
-
-
-
- libs\UnityEngine.dll
-
-
- libs\UnityEngine.CoreModule.dll
-
-
- D:\Games\Steam\steamapps\common\Valheim\unstripped_corlib\UnityEngine.ImageConversionModule.dll
-
-
- D:\Games\Steam\steamapps\common\Valheim\unstripped_corlib\UnityEngine.InputLegacyModule.dll
-
-
- D:\Games\Steam\steamapps\common\Valheim\unstripped_corlib\UnityEngine.PhysicsModule.dll
-
-
- D:\Games\Steam\steamapps\common\Valheim\unstripped_corlib\UnityEngine.UI.dll
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Debug
+ AnyCPU
+ {B89BA476-237B-4A9B-837D-C6D07174918D}
+ Library
+ Properties
+ Veinmine
+ Veinmine
+ v4.6.2
+ 512
+ true
+
+ 10
+ enable
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+ $(HOME)/.steam/steam/steamapps/common/Valheim
+ $(HOME)/Library/Application Support/Steam/steamapps/common/Valheim/Contents/MacOS
+ $(GamePath)/unstripped_corelib
+
+
+
+
+ $([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 892970', 'InstallLocation', null, RegistryView.Registry64, RegistryView.Registry32))
+ <_SteamLibraryPath>$([MSBuild]::GetRegistryValueFromView('HKEY_CURRENT_USER\SOFTWARE\Valve\Steam', 'SteamPath', null, RegistryView.Registry32))
+ $(_SteamLibraryPath)\steamapps\common\Valheim
+ $(ValheimGamePath)
+ C:\Program Files\Steam\steamapps\common\Valheim
+ C:\Program Files (x86)\Steam\steamapps\common\Valheim
+ D:\SteamLibrary\steamapps\common\Valheim
+ D:\Games\Steam\steamapps\common\Valheim
+ $(GamePath)\BepInEx
+ $(GamePath)\unstripped_corlib
+ $(GamePath)\valheim_Data\Managed\publicized_assemblies
+ ILRepacker
+
+
+
+
+
+ $(BepInExPath)\core\0Harmony.dll
+
+
+ $(PublicizedAssembliesPath)\assembly_guiutils_publicized.dll
+
+
+ $(PublicizedAssembliesPath)\assembly_utils_publicized.dll
+
+
+ $(PublicizedAssembliesPath)\assembly_valheim_publicized.dll
+
+
+ $(BepInExPath)\core\BepInEx.dll
+
+
+ libs\ServerSync.dll
+
+
+
+
+
+
+
+
+
+
+ $(CorlibPath)\UnityEngine.dll
+
+
+ $(CorlibPath)\UnityEngine.CoreModule.dll
+
+
+ $(CorlibPath)\UnityEngine.ImageConversionModule.dll
+
+
+ $(CorlibPath)\UnityEngine.InputLegacyModule.dll
+
+
+ $(CorlibPath)\UnityEngine.PhysicsModule.dll
+
+
+ $(CorlibPath)\UnityEngine.UI.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(AssemblyVersions.Identity)
+ $(AssemblyVersion.Split('.')[0])
+ $(AssemblyVersion.Split('.')[1])
+ $(AssemblyVersion.Split('.')[2])
+ $(AssemblyName)_v$(Major).$(Minor).$(Patch)
+ $(Major).$(Minor).$(Patch)
+ $(Major).$(Minor).$(Patch)
+ $(ProjectDir)\Thunderstore\$(PackageName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.
+
+
+
\ No newline at end of file
diff --git a/VeinMine/VeinMinePlugin.cs b/VeinMine/VeinMinePlugin.cs
new file mode 100644
index 0000000..c410226
--- /dev/null
+++ b/VeinMine/VeinMinePlugin.cs
@@ -0,0 +1,208 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using BepInEx;
+using BepInEx.Configuration;
+using BepInEx.Logging;
+using HarmonyLib;
+using JetBrains.Annotations;
+using ServerSync;
+using UnityEngine;
+
+namespace Veinmine
+{
+ [BepInPlugin(ModGUID, ModName, ModVersion)]
+ public class VeinMinePlugin : BaseUnityPlugin
+ {
+ internal const string ModName = "Veinmine";
+ internal const string ModVersion = "1.2.8";
+ internal const string Author = "wisehorror";
+ private const string ModGUID = $"com.{Author}.{ModName}";
+ private static string ConfigFileName = $"{ModGUID}.cfg";
+ private static string ConfigFileFullPath = Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName;
+ internal static string ConnectionError = "";
+ private readonly Harmony _harmony = new(ModGUID);
+ public static ManualLogSource logger = BepInEx.Logging.Logger.CreateLogSource(ModName);
+
+ private static readonly ConfigSync ConfigSync = new(ModGUID) { DisplayName = ModName, CurrentVersion = ModVersion, MinimumRequiredVersion = ModVersion };
+
+ public enum SpreadTypes
+ {
+ Level,
+ Distance
+ }
+
+ public enum Toggle
+ {
+ On = 1,
+ Off = 0
+ }
+
+ void Awake()
+ {
+ _serverConfigLocked = config("1 - General",
+ "Lock Configuration",
+ Toggle.On,
+ "If on, the configuration is locked and can be changed by server admins only.");
+ _ = ConfigSync.AddLockingConfigEntry(_serverConfigLocked);
+
+
+ veinMineKey = config("2 - General",
+ "Veinmine",
+ new KeyboardShortcut(KeyCode.LeftAlt),
+ "Key (or button) to hold for veinmining. Refer to https://docs.unity3d.com/Manual/class-InputManager.html", false);
+
+ veinMineDurability = config("2 - General",
+ "Durability",
+ Toggle.On,
+ "Veinmining takes durability as if you mined every section manually.");
+
+ removeEffects = config("3 - Visual",
+ "Remove Effects",
+ Toggle.Off,
+ "Remove mining visual effects to try to *possibly* reduce fps lag", false);
+
+ progressiveMode = config("4 - Progressive",
+ "Enable Progressive",
+ Toggle.Off,
+ "Progressive mode scales the number of sections mined according to the player's Pickaxes level.");
+
+ progressiveMult = config("4 - Progressive",
+ "Radius Multiplier",
+ 0.1f,
+ "Radius around your hit area to veinmine. This value is multiplied by the player's Pickaxes level.\n" +
+ "Keep in mind 1 is the same length as the 1x1 wood floor.\n" +
+ "So if you have Lvl 30 and set this value to 0.1, you will veinmine rocks in a radius of 3 (0.1 * 30 = 3).");
+
+ durabilityMult = config("4 - Progressive",
+ "Durability Multiplier",
+ 1f,
+ "Determines durability lost when veinmining.\n" +
+ "The formula is (120 - Pickaxes level) / (20 * multiplier) where \"multiplier\" is this value.");
+
+ xpMult = config("4 - Progressive",
+ "XP Multiplier",
+ 0.2f,
+ "Multiplier for XP gained per rock section veinmined.");
+
+ enableSpreadDamage = config("4 - Progressive",
+ "Enable Spread Damage",
+ Toggle.Off,
+ "Spreads your hit damage throughout all rock sections mined, as opposed to hitting every section for the total amount of damage.");
+
+ spreadDamageType = config("4 - Progressive",
+ "Spread Damage Type",
+ SpreadTypes.Distance,
+ "Level: Scales damage done to each section based on your Pickaxes level.\n" +
+ "Distance: Calculates damage done to each section based on your distance from it, the farther away, the less damage you do.");
+
+ Assembly assembly = Assembly.GetExecutingAssembly();
+ _harmony.PatchAll(assembly);
+ SetupWatcher();
+ }
+
+ private void OnDestroy()
+ {
+ Config.Save();
+ }
+
+ private void SetupWatcher()
+ {
+ FileSystemWatcher watcher = new(Paths.ConfigPath, ConfigFileName);
+ watcher.Changed += ReadConfigValues;
+ watcher.Created += ReadConfigValues;
+ watcher.Renamed += ReadConfigValues;
+ watcher.IncludeSubdirectories = true;
+ watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
+ watcher.EnableRaisingEvents = true;
+ }
+
+ private void ReadConfigValues(object sender, FileSystemEventArgs e)
+ {
+ if (!File.Exists(ConfigFileFullPath)) return;
+ try
+ {
+ logger.LogDebug("ReadConfigValues called");
+ Config.Reload();
+ }
+ catch
+ {
+ logger.LogError($"There was an issue loading your {ConfigFileName}");
+ logger.LogError("Please check your config entries for spelling and format!");
+ }
+ }
+
+ #region ConfigOptions
+
+ private static ConfigEntry _serverConfigLocked = null!;
+ public static ConfigEntry veinMineKey = null!;
+ public static ConfigEntry veinMineDurability = null!;
+ public static ConfigEntry removeEffects = null!;
+ public static ConfigEntry progressiveMode = null!;
+ public static ConfigEntry enableSpreadDamage = null!;
+ public static ConfigEntry spreadDamageType = null!;
+ public static ConfigEntry progressiveMult = null!;
+ public static ConfigEntry durabilityMult = null!;
+ public static ConfigEntry xpMult = null!;
+
+ private ConfigEntry config(string group, string name, T value, ConfigDescription description,
+ bool synchronizedSetting = true)
+ {
+ ConfigDescription extendedDescription =
+ new(
+ description.Description +
+ (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"),
+ description.AcceptableValues, description.Tags);
+ ConfigEntry configEntry = Config.Bind(group, name, value, extendedDescription);
+ //var configEntry = Config.Bind(group, name, value, description);
+
+ SyncedConfigEntry syncedConfigEntry = ConfigSync.AddConfigEntry(configEntry);
+ syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
+
+ return configEntry;
+ }
+
+ private ConfigEntry config(string group, string name, T value, string description,
+ bool synchronizedSetting = true)
+ {
+ return config(group, name, value, new ConfigDescription(description), synchronizedSetting);
+ }
+
+ private class ConfigurationManagerAttributes
+ {
+ [UsedImplicitly] public int? Order = null!;
+ [UsedImplicitly] public bool? Browsable = null!;
+ [UsedImplicitly] public string Category = null!;
+ [UsedImplicitly] public Action CustomDrawer = null!;
+ }
+
+ class AcceptableShortcuts : AcceptableValueBase
+ {
+ public AcceptableShortcuts() : base(typeof(KeyboardShortcut))
+ {
+ }
+
+ public override object Clamp(object value) => value;
+ public override bool IsValid(object value) => true;
+
+ public override string ToDescriptionString() =>
+ $"# Acceptable values: {string.Join(", ", UnityInput.Current.SupportedKeyCodes)}";
+ }
+
+ #endregion
+ }
+
+ public static class KeyboardExtensions
+ {
+ public static bool IsKeyDown(this KeyboardShortcut shortcut)
+ {
+ return shortcut.MainKey != KeyCode.None && Input.GetKeyDown(shortcut.MainKey) && shortcut.Modifiers.All(Input.GetKey);
+ }
+
+ public static bool IsKeyHeld(this KeyboardShortcut shortcut)
+ {
+ return shortcut.MainKey != KeyCode.None && Input.GetKey(shortcut.MainKey) && shortcut.Modifiers.All(Input.GetKey);
+ }
+ }
+}
\ No newline at end of file
diff --git a/VeinMine/VersionHandshake.cs b/VeinMine/VersionHandshake.cs
new file mode 100644
index 0000000..21794f2
--- /dev/null
+++ b/VeinMine/VersionHandshake.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+using HarmonyLib;
+
+namespace Veinmine
+{
+ [HarmonyPatch(typeof(ZNet), nameof(ZNet.OnNewConnection))]
+ public static class RegisterAndCheckVersion
+ {
+ private static void Prefix(ZNetPeer peer, ref ZNet __instance)
+ {
+ // Register version check call
+ VeinMinePlugin.logger.LogDebug("Registering version RPC handler");
+ peer.m_rpc.Register($"{VeinMinePlugin.ModName}_VersionCheck", new Action(RpcHandlers.RPC_Recycle_N_Reclaim_Version));
+
+ // Make calls to check versions
+ VeinMinePlugin.logger.LogInfo("Invoking version check");
+ ZPackage zpackage = new();
+ zpackage.Write(VeinMinePlugin.ModVersion);
+ zpackage.Write(RpcHandlers.ComputeHashForMod().Replace("-", ""));
+ peer.m_rpc.Invoke($"{VeinMinePlugin.ModName}_VersionCheck", zpackage);
+ }
+ }
+
+ [HarmonyPatch(typeof(ZNet), nameof(ZNet.RPC_PeerInfo))]
+ public static class VerifyClient
+ {
+ private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance)
+ {
+ if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) return true;
+ // Disconnect peer if they didn't send mod version at all
+ VeinMinePlugin.logger.LogWarning($"Peer ({rpc.m_socket.GetHostName()}) never sent version or couldn't due to previous disconnect, disconnecting");
+ rpc.Invoke("Error", 3);
+ return false; // Prevent calling underlying method
+ }
+
+ private static void Postfix(ZNet __instance)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), $"{VeinMinePlugin.ModName}RequestAdminSync", new ZPackage());
+ }
+ }
+
+ [HarmonyPatch(typeof(FejdStartup), nameof(FejdStartup.ShowConnectError))]
+ public class ShowConnectionError
+ {
+ private static void Postfix(FejdStartup __instance)
+ {
+ if (__instance.m_connectionFailedPanel.activeSelf)
+ {
+ __instance.m_connectionFailedError.resizeTextMaxSize = 25;
+ __instance.m_connectionFailedError.resizeTextMinSize = 15;
+ __instance.m_connectionFailedError.text += $"\n{VeinMinePlugin.ConnectionError}";
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(ZNet), nameof(ZNet.Disconnect))]
+ public static class RemoveDisconnectedPeerFromVerified
+ {
+ private static void Prefix(ZNetPeer peer, ref ZNet __instance)
+ {
+ if (!__instance.IsServer()) return;
+ // Remove peer from validated list
+ VeinMinePlugin.logger.LogInfo($"Peer ({peer.m_rpc.m_socket.GetHostName()}) disconnected, removing from validated list");
+ _ = RpcHandlers.ValidatedPeers.Remove(peer.m_rpc);
+ }
+ }
+
+ public static class RpcHandlers
+ {
+ public static readonly List ValidatedPeers = new();
+
+ public static void RPC_Recycle_N_Reclaim_Version(ZRpc rpc, ZPackage pkg)
+ {
+ string? version = pkg.ReadString();
+ string? hash = pkg.ReadString();
+
+ var hashForAssembly = ComputeHashForMod().Replace("-", "");
+
+ VeinMinePlugin.logger.LogInfo($"Hash/Version check, local: {VeinMinePlugin.ModVersion} {hashForAssembly} remote: {version} {hash}");
+ if (hash != hashForAssembly || version != VeinMinePlugin.ModVersion)
+ {
+ VeinMinePlugin.ConnectionError = $"{VeinMinePlugin.ModName} Installed: {VeinMinePlugin.ModVersion} {hashForAssembly}\n Needed: {version} {hash}";
+ if (!ZNet.instance.IsServer()) return;
+ // Different versions - force disconnect client from server
+ VeinMinePlugin.logger.LogWarning($"Peer ({rpc.m_socket.GetHostName()}) has incompatible version, disconnecting...");
+ rpc.Invoke("Error", 3);
+ }
+ else
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ // Enable mod on client if versions match
+ VeinMinePlugin.logger.LogInfo("Received same version from server!");
+ }
+ else
+ {
+ // Add client to validated list
+ VeinMinePlugin.logger.LogInfo($"Adding peer ({rpc.m_socket.GetHostName()}) to validated list");
+ ValidatedPeers.Add(rpc);
+ }
+ }
+ }
+
+ public static string ComputeHashForMod()
+ {
+ using SHA256 sha256Hash = SHA256.Create();
+ // ComputeHash - returns byte array
+ byte[] bytes = sha256Hash.ComputeHash(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location));
+ // Convert byte array to a string
+ StringBuilder builder = new();
+ foreach (byte b in bytes)
+ {
+ builder.Append(b.ToString("X2"));
+ }
+
+ return builder.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/VeinMine/environment.props b/VeinMine/environment.props
new file mode 100644
index 0000000..f56a550
--- /dev/null
+++ b/VeinMine/environment.props
@@ -0,0 +1,13 @@
+
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\Valheim
+ $(ValheimGamePath)\BepInEx
+ $(ValheimGamePath)\unstripped_corlib
+ $(ValheimGamePath)\valheim_Data\Managed\publicized_assemblies
+ $(ValheimGamePath)\BepInEx\plugins
+
+
+ ILRepacker
+
+
\ No newline at end of file
diff --git a/VeinMine/libs/ServerSync.dll b/VeinMine/libs/ServerSync.dll
new file mode 100644
index 0000000..6bb8e90
Binary files /dev/null and b/VeinMine/libs/ServerSync.dll differ
diff --git a/VeinMine/packages.config b/VeinMine/packages.config
index 2258412..9fbbbcd 100644
--- a/VeinMine/packages.config
+++ b/VeinMine/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file