Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
58 changes: 27 additions & 31 deletions AdvancedPortals/AdvancedPortals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,45 +99,41 @@ private void OnDestroy()
Config.Save();
}

private FileSystemWatcher _configWatcher;

private void SetupWatcher()
{
// The reload is driven by ConfigFileReloader watching the file's timestamp; the events
// below only ask it to look sooner than its own poll would. See that class for why the
// events on their own are not enough on a Linux server, and why a connected client does
// not reload.
//
// Nothing to apply by hand once it does: Config.Reload raises SettingChanged for every
// entry whose value actually changed, and PieceLoader and Portals both act on that
// themselves.
ConfigFileReloader.Begin(Config, ConfigFileFullPath);

FileSystemWatcher watcher = new(BepInEx.Paths.ConfigPath, ConfigFileName);
watcher.Changed += ReadConfigValues;
watcher.Created += ReadConfigValues;
watcher.Renamed += ReadConfigValues;
watcher.IncludeSubdirectories = true;
watcher.Changed += OnConfigFileEvent;
watcher.Created += OnConfigFileEvent;
watcher.Renamed += OnConfigFileEvent;
// FileName included so an editor that saves by writing a temp file and renaming it over
// the config still reports; LastWrite alone only covers writes made in place.
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Size;
watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
watcher.EnableRaisingEvents = true;
// Not IncludeSubdirectories: the file only ever lives directly in BepInEx/config, and
// recursing made Mono register an inotify watch for every subdirectory under it - every
// other mod's config folder included - for a filter that can only ever match at the top.
//
// Held in a field so it can be disposed or replaced later. Mono's watcher backends keep
// every instance rooted until Dispose, so this is not what keeps events flowing.
_configWatcher = watcher;
}

private DateTime _lastReloadTime;
private const long RELOAD_DELAY = 10000000; // One second

private void ReadConfigValues(object sender, FileSystemEventArgs e)
private void OnConfigFileEvent(object sender, FileSystemEventArgs e)
{
DateTime now = DateTime.Now;
long time = now.Ticks - _lastReloadTime.Ticks;
if (!File.Exists(ConfigFileFullPath) || time < RELOAD_DELAY) return;

// A connected client must not reload: Jotunn has already replaced these values with the
// server's, and a reload would clobber them with whatever this machine happens to have on disk.
// The main menu (no ZNet yet) and a singleplayer or host session both still reload.
if (ZNet.instance != null && !ZNet.instance.IsServer()) return;

try
{
APLogger.LogInfo("Attempting to reload configuration...");
Config.Reload();
}
catch
{
APLogger.LogWarning($"There was an issue loading {ConfigFileName}");
return;
}

// Nothing to apply by hand: Config.Reload raises SettingChanged for every entry whose value
// actually changed, and PieceLoader and Portals both act on that themselves.
_lastReloadTime = now;
ConfigFileReloader.CheckSoon();
}
}
}
50 changes: 27 additions & 23 deletions EpicLoot/EpicLoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace EpicLoot;
public sealed class EpicLoot : BaseUnityPlugin {
public const string PluginId = "randyknapp.mods.epicloot";
public const string DisplayName = "Epic Loot";
public const string Version = "0.14.2";
public const string Version = "0.14.9";

private static string ConfigFileName = PluginId + ".cfg";
private static string ConfigFileFullPath = BepInEx.Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName;
Expand Down Expand Up @@ -122,6 +122,9 @@ void Awake() {
MagicItemEffects.Shards.PoisonAdrenalinePulse.Create();
MagicItemEffects.Shards.StormFuryPulse.Create();

// Logs, from the buyer's side, a bounty or treasure map that has not appeared at its map circle.
AdventureSpawnWatchdog.Create();

// Main file config watcher
SetupWatcher();
}
Expand Down Expand Up @@ -636,7 +639,7 @@ private static void LoadCraftableItems() {
}

private static void LoadBountySpawner() {
GameObject bounty_spawner = EpicAssets.AssetBundle.LoadAsset<GameObject>("EL_SpawnController");
GameObject bounty_spawner = EpicAssets.AssetBundle.LoadAsset<GameObject>(AdventureSpawnController.PrefabName);

if (bounty_spawner == null) {
LogErrorForce("Unable to find bounty spawner asset! This mod will not behave as expected!");
Expand Down Expand Up @@ -1162,32 +1165,33 @@ public static void SetWorldLuckFactor(float luckFactor) {
_instance._worldLuckFactor = luckFactor;
}

private FileSystemWatcher _configWatcher;

private void SetupWatcher() {
// The reload is driven by ConfigFileReloader watching the file's timestamp; the events below
// only ask it to look sooner than its own poll would. See that class for why the events on
// their own are not enough on a Linux server, and why a connected client does not reload.
ConfigFileReloader.Begin(Config, ConfigFileFullPath);

FileSystemWatcher watcher = new(BepInEx.Paths.ConfigPath, ConfigFileName);
watcher.Changed += ReadConfigValues;
watcher.Created += ReadConfigValues;
watcher.Renamed += ReadConfigValues;
watcher.IncludeSubdirectories = true;
watcher.Changed += OnConfigFileEvent;
watcher.Created += OnConfigFileEvent;
watcher.Renamed += OnConfigFileEvent;
// FileName included so an editor that saves by writing a temp file and renaming it over the
// config still reports; LastWrite alone only covers writes made in place.
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Size;
watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
watcher.EnableRaisingEvents = true;
// Not IncludeSubdirectories: the file only ever lives directly in BepInEx/config, and
// recursing made Mono register an inotify watch for every subdirectory under it - every
// other mod's config folder included - for a filter that can only ever match at the top.
//
// Held in a field so it can be disposed or replaced later. Mono's watcher backends keep every
// instance rooted until Dispose, so this is not what keeps events flowing.
_configWatcher = watcher;
}

private DateTime _lastReloadTime;
private const long RELOAD_DELAY = 10000000; // One second

private void ReadConfigValues(object sender, FileSystemEventArgs e) {
var now = DateTime.Now;
var time = now.Ticks - _lastReloadTime.Ticks;
if (!File.Exists(ConfigFileFullPath) || time < RELOAD_DELAY) return;

try {
Log("Attempting to reload configuration...");
Config.Reload();
} catch {
Log($"There was an issue loading {ConfigFileName}");
return;
}

_lastReloadTime = now;
private void OnConfigFileEvent(object sender, FileSystemEventArgs e) {
ConfigFileReloader.CheckSoon();
}
}
7 changes: 7 additions & 0 deletions EpicLoot/EpicLoot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@
<EmbeddedResource Remove="config-patches\**" />
<None Remove="config-patches\**" />
<None Remove="localizations\*" />
<!-- A stray copy of the Unity ExternalLibraries folder sits under this project. The default
glob put its DLLs into @(None), and ResolveAssemblyReference checks @(None) before any
HintPath, so every vanilla, BepInEx and Jotunn reference resolved to that snapshot instead
of the installed game. A Valheim update then built green against the old API and failed
at runtime: PlayerProfile.s_bypassCheatChecks became a property, and the compiled field
read threw MissingFieldException from Piece.DropResources, blocking every piece removal. -->
<None Remove="ValheimUnity\**" />
</ItemGroup>

<ItemGroup>
Expand Down
38 changes: 38 additions & 0 deletions EpicLoot/Package/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
**0.14.9**
* Fix for Grappling hook
* Trader window diagnostics, please report your log if you have issues opening the trader window
* Another fix for Joystick controller issues

**0.14.8**
* Controller update for 9/17
* Increases placement allowance for bounties/treasures
* Removes bounty/treasure relocation due to the potential for schisms

**0.14.7**
* Recompiled against current game build (fixes building destruction issues)


**0.14.6**
* Destroying an enchanting table now refunds the full upgrade cost of every unlocked feature. Amounts above an item's stack size (Surtling Cores, berries, mushrooms, fish) were previously lost
* Optimizes bounty and treasure chests spawning, now spawns the target considerably earlier
* Fixes Epicloot trader UI not showing up when other mods break the trader (your other mods are still breaking your game, just not breaking Epicloot)

**0.14.5**
* Additional safety checks for world upgrades
* Fix for edge cases that could cause the trader UI to not show up
* Fix for existing loot pools that already contain invalid items


**0.14.4**
* Adds safety checks for data lookup issues
* Prevents the item auto-sorter from adding new hidden, unused items to the loot pool

**0.14.3**

* Improves config synchronization refresh from disk on dedicated Linux servers, now also for the baseconfig json files (magiceffects, loottables, ...): an edit is applied once the file stops changing, and is picked up even when the server never sees a file event (NFS, SFTP, container mounts)
* A config reloaded on a player-hosted game is now pushed to the connected players, not only from a dedicated server
* A client connected to a server no longer applies edits to its own baseconfig files until it disconnects, at which point its own files are restored
* Config reloads and server config pushes now log at the default log level
* Fixed magicmats spawning broken items (reminder magicmats is a cheat command)
* Delays main menu welcome message and config prompt until after cutscenes have played

**0.14.2**

* Fixes biome explored not being updated on Deep North
Expand Down
2 changes: 1 addition & 1 deletion EpicLoot/Package/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "EpicLoot",
"version_number": "0.14.2",
"version_number": "0.14.9",
"website_url": "https://discord.gg/ZNhYeavv3C",
"description": "Adds loot drops, magic items, and enchanting to Valheim.",
"dependencies": [
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Bulgarian.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Ярост!!",
"mod_epicloot_itemtooltip_rarity": "Рядкост",
"mod_epicloot_itemtooltip_effects": "Ефекти",
"mod_epicloot_adventure_spawnrelocated": "Картата ти беше преначертана – отбелязаният район беше зает.",
"mod_epicloot_bounties_claimedmsg": "Наградата е взета!",
"mod_epicloot_bounties_completemsg": "Баунти справено!",
"mod_epicloot_bounties_locatingmsg": "Намиране на целта за баунти...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Chinese.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "愤怒!!",
"mod_epicloot_itemtooltip_rarity": "稀有度",
"mod_epicloot_itemtooltip_effects": "效果",
"mod_epicloot_adventure_spawnrelocated": "地图已重绘——标记的区域已被占用。",
"mod_epicloot_bounties_claimedmsg": "赏金已领取!",
"mod_epicloot_bounties_completemsg": "赏金已消灭!",
"mod_epicloot_bounties_locatingmsg": "定位赏金目标...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Chinese_Trad.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "憤怒!!",
"mod_epicloot_itemtooltip_rarity": "稀有度",
"mod_epicloot_itemtooltip_effects": "效果",
"mod_epicloot_adventure_spawnrelocated": "地圖已重繪——標記的區域已被占用。",
"mod_epicloot_bounties_claimedmsg": "賞金已領取!",
"mod_epicloot_bounties_completemsg": "賞金已消滅!",
"mod_epicloot_bounties_locatingmsg": "正在定位賞金目標...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Croatian.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Luuudilo!!",
"mod_epicloot_itemtooltip_rarity": "Rijetkost",
"mod_epicloot_itemtooltip_effects": "Učinci",
"mod_epicloot_adventure_spawnrelocated": "Tvoja je karta ponovno iscrtana – označeno područje bilo je zauzeto.",
"mod_epicloot_bounties_claimedmsg": "Plijen pronađen!",
"mod_epicloot_bounties_completemsg": "Plijen poražen!",
"mod_epicloot_bounties_locatingmsg": "Lociranje mete plijena...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Czech.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaage!!",
"mod_epicloot_itemtooltip_rarity": "Vzácnost",
"mod_epicloot_itemtooltip_effects": "Efekty",
"mod_epicloot_adventure_spawnrelocated": "Tvá mapa byla překreslena – označená oblast byla obsazena.",
"mod_epicloot_bounties_claimedmsg": "Odmena nárokována!",
"mod_epicloot_bounties_completemsg": "Odmena poražena!",
"mod_epicloot_bounties_locatingmsg": "Vyhledávání cíle odměny...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Danish.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaage!!",
"mod_epicloot_itemtooltip_rarity": "Sjældenhed",
"mod_epicloot_itemtooltip_effects": "Effekter",
"mod_epicloot_adventure_spawnrelocated": "Dit kort er tegnet om – det markerede område var optaget.",
"mod_epicloot_bounties_claimedmsg": "Bounty Claimed!",
"mod_epicloot_bounties_completemsg": "Bounty Vanquished!",
"mod_epicloot_bounties_locatingmsg": "Lokalisering af Bounty-mål...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Dutch.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Wooede!!",
"mod_epicloot_itemtooltip_rarity": "Zeldzaamheid",
"mod_epicloot_itemtooltip_effects": "Effecten",
"mod_epicloot_adventure_spawnrelocated": "Je kaart is opnieuw getekend: het gemarkeerde gebied was bezet.",
"mod_epicloot_bounties_claimedmsg": "Beloning Geclaimd!",
"mod_epicloot_bounties_completemsg": "Beloning Verslagen!",
"mod_epicloot_bounties_locatingmsg": "Op Zoek naar Doelwit...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/English.json
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,6 @@

"mod_epicloot_adventure_locatefailed": "Could not find a suitable location in the $1.",
"mod_epicloot_adventure_locateunavailable": "Still mapping the world - try again in a moment.",
"mod_epicloot_adventure_spawnrelocated": "Your map has been redrawn - the marked area was occupied.",

"mod_epicloot_bounties_claimedmsg": "Bounty Claimed!",
"mod_epicloot_bounties_completemsg": "Bounty Vanquished!",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Finnish.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaaage!!",
"mod_epicloot_itemtooltip_rarity": "Harvinaisuus",
"mod_epicloot_itemtooltip_effects": "Vaikutukset",
"mod_epicloot_adventure_spawnrelocated": "Karttasi on piirretty uudelleen – merkitty alue oli varattu.",
"mod_epicloot_bounties_claimedmsg": "Palkinto lunastettu!",
"mod_epicloot_bounties_completemsg": "Palkkio voitettu!",
"mod_epicloot_bounties_locatingmsg": "Etsitään palkkion kohdetta...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/French.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaage!!",
"mod_epicloot_itemtooltip_rarity": "Rareté",
"mod_epicloot_itemtooltip_effects": "Effets",
"mod_epicloot_adventure_spawnrelocated": "Votre carte a été redessinée : la zone marquée était occupée.",
"mod_epicloot_bounties_claimedmsg": "Prime réclamée!",
"mod_epicloot_bounties_completemsg": "Prime vaincue!",
"mod_epicloot_bounties_locatingmsg": "Localisation de la cible de prime...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Georgian.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "რაააჯ!!",
"mod_epicloot_itemtooltip_rarity": "რარიტეტი",
"mod_epicloot_itemtooltip_effects": "ეფექტები",
"mod_epicloot_adventure_spawnrelocated": "რუკა ხელახლა დაიხატა — მონიშნული ადგილი უკვე დაკავებული იყო.",
"mod_epicloot_bounties_claimedmsg": "სამომავლო გადაიტანე!",
"mod_epicloot_bounties_completemsg": "სამომავლო გადაიტანე!",
"mod_epicloot_bounties_locatingmsg": "სამომავლოს ადგილის გელოვა...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/German.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaage!!",
"mod_epicloot_itemtooltip_rarity": "Seltenheit",
"mod_epicloot_itemtooltip_effects": "Effekte",
"mod_epicloot_adventure_spawnrelocated": "Deine Karte wurde neu gezeichnet – das markierte Gebiet war besetzt.",
"mod_epicloot_bounties_claimedmsg": "Kopfgeld beansprucht!",
"mod_epicloot_bounties_completemsg": "Kopfgeld vernichtet!",
"mod_epicloot_bounties_locatingmsg": "Suche nach Kopfgeldziel...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Greek.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Θυμός!!",
"mod_epicloot_itemtooltip_rarity": "Σπανιότητα",
"mod_epicloot_itemtooltip_effects": "Εφέ",
"mod_epicloot_adventure_spawnrelocated": "Ο χάρτης σου ξανασχεδιάστηκε – η σημειωμένη περιοχή ήταν κατειλημμένη.",
"mod_epicloot_bounties_claimedmsg": "Κυνήγι Ανταμοιβής!",
"mod_epicloot_bounties_completemsg": "Κυνήγι Καταστράφηκε!",
"mod_epicloot_bounties_locatingmsg": "Εντοπισμός Στόχου Ανταμοιβής...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Hindi.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "रेज!!",
"mod_epicloot_itemtooltip_rarity": "रेयरिटी",
"mod_epicloot_itemtooltip_effects": "प्रभाव",
"mod_epicloot_adventure_spawnrelocated": "मानचित्र दोबारा बनाया गया — चिह्नित क्षेत्र पहले से भरा हुआ था।",
"mod_epicloot_bounties_claimedmsg": "इनाम प्राप्त किया गया!",
"mod_epicloot_bounties_completemsg": "इनाम जीता गया!",
"mod_epicloot_bounties_locatingmsg": "इनाम का निशाना ढूंढ़ रहा है...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Hungarian.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Dühödt vagy!!",
"mod_epicloot_itemtooltip_rarity": "Ritkaság",
"mod_epicloot_itemtooltip_effects": "Hatások",
"mod_epicloot_adventure_spawnrelocated": "A térképedet újrarajzoltuk – a megjelölt terület foglalt volt.",
"mod_epicloot_bounties_claimedmsg": "Jutalom igényelve!",
"mod_epicloot_bounties_completemsg": "Jutalom elnyerve!",
"mod_epicloot_bounties_locatingmsg": "Jutalom célpont lokalizálása...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Icelandic.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaaage!!",
"mod_epicloot_itemtooltip_rarity": "Sjaldgæfni",
"mod_epicloot_itemtooltip_effects": "Áhrif",
"mod_epicloot_adventure_spawnrelocated": "Kortið þitt hefur verið teiknað upp á nýtt – merkta svæðið var upptekið.",
"mod_epicloot_bounties_claimedmsg": "Bounty krækta!",
"mod_epicloot_bounties_completemsg": "Bounty sigraður!",
"mod_epicloot_bounties_locatingmsg": "Að finna Bounty markmið...",
Expand Down
1 change: 0 additions & 1 deletion EpicLoot/localizations/Italian.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@
"mod_epicloot_se_berserker_startmessage": "Raaaage!!",
"mod_epicloot_itemtooltip_rarity": "Rarità",
"mod_epicloot_itemtooltip_effects": "Effetti",
"mod_epicloot_adventure_spawnrelocated": "La tua mappa è stata ridisegnata: l'area segnata era occupata.",
"mod_epicloot_bounties_claimedmsg": "Taglia Richiesta!",
"mod_epicloot_bounties_completemsg": "Taglia Sconfitta!",
"mod_epicloot_bounties_locatingmsg": "Localizzazione del Bersaglio della Taglia...",
Expand Down
Loading
Loading