From 3324d9573440cc7499c861dd897374acf96dd5d2 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 12 Oct 2025 19:14:02 -0400 Subject: [PATCH 1/5] updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67d4f3e..0dd41b4 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ Edits of the existing AP adding the AltBlackEgg and AltRadiance options. -/hktest is the apworld folder, only necessary when generating the world +/World is the apworld folder, only necessary when generating the world -/Archipelago.HollowKnight is the mod folder, should be built and put into your Hollow Knight mod folder +/Mod is the mod folder, should be built and put into your Hollow Knight mod folder From d7d69af56c170e552935f9e9ac662877f6594ab0 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 12 Oct 2025 19:15:36 -0400 Subject: [PATCH 2/5] initial attributes and ignore files --- .gitattributes | 63 ++++++++ .gitignore | 402 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 465 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d37298 --- /dev/null +++ b/.gitignore @@ -0,0 +1,402 @@ +DLLs/* + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +LocalOverrides.targets \ No newline at end of file From b2e79243d1f77228a180c5db054f7a7039f07288 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 12 Oct 2025 19:15:58 -0400 Subject: [PATCH 3/5] added Mod files --- Mod/Archipelago.HollowKnight.sln | 35 ++ .../Archipelago.HollowKnight.csproj | 335 ++++++++++++ .../ArchipelagoMod.cs | 273 ++++++++++ .../ArchipelagoRandomizer.cs | 397 ++++++++++++++ .../DeathLinkMessages.cs | 127 +++++ Mod/Archipelago.HollowKnight/DupeUIDef.cs | 46 ++ Mod/Archipelago.HollowKnight/Enums.cs | 24 + Mod/Archipelago.HollowKnight/Extensions.cs | 16 + .../GeneratedConsts.cs | 6 + Mod/Archipelago.HollowKnight/Goals.cs | 307 +++++++++++ Mod/Archipelago.HollowKnight/HintTracker.cs | 251 +++++++++ .../IC/ArchipelagoItem.cs | 89 ++++ .../IC/ArchipelagoSprite.cs | 10 + .../IC/ArchipelagoTags.cs | 151 ++++++ .../IC/ArchipelagoUIDef.cs | 55 ++ .../IC/CostFactory.cs | 112 ++++ .../IC/ItemFactory.cs | 64 +++ .../IC/Items/GoalItem.cs | 20 + .../ArchipelagoRemoteItemCounterModule.cs | 91 ++++ .../IC/Modules/BenchSyncModule.cs | 123 +++++ .../IC/Modules/DeathLinkModule.cs | 266 +++++++++ .../IC/Modules/DupeHandlingModule.cs | 27 + .../IC/Modules/GiftingModule.cs | 159 ++++++ .../IC/Modules/GoalModule.cs | 59 ++ .../IC/Modules/ItemNetworkingModule.cs | 372 +++++++++++++ .../IC/Modules/RepositionShadeModule.cs | 37 ++ .../IC/PlacementUtils.cs | 21 + .../IC/RM/HelperPlatformBuilder.cs | 178 +++++++ Mod/Archipelago.HollowKnight/IC/RM/LICENSE | 504 ++++++++++++++++++ Mod/Archipelago.HollowKnight/IC/RM/NOTICE.md | 19 + .../IC/RM/StartDef.cs | 54 ++ .../IC/RM/StartLocationSceneEditsModule.cs | 105 ++++ .../IC/RemotePlacement.cs | 47 ++ .../IC/Tags/ArchipelagoRemoteItemTag.cs | 51 ++ .../LoginValidationException.cs | 19 + .../MC/ArchipelagoModeMenuConstructor.cs | 213 ++++++++ .../ModDependencies.txt | 3 + .../Resources/Data/starts.json | 267 ++++++++++ .../Resources/DeathLinkIcon.png | Bin 0 -> 6441 bytes .../Resources/GrubHappyv2.png | Bin 0 -> 22605 bytes .../Resources/IconBlue.png | Bin 0 -> 19828 bytes .../Resources/IconBlueBig.png | Bin 0 -> 71762 bytes .../Resources/IconBlueSmall.png | Bin 0 -> 6716 bytes .../Resources/IconColor.png | Bin 0 -> 27855 bytes .../Resources/IconColorBig.png | Bin 0 -> 133504 bytes .../Resources/IconColorSmall.png | Bin 0 -> 6414 bytes .../Resources/Pins/pinAP.png | Bin 0 -> 1371 bytes .../Resources/Pins/pinAPProgression.png | Bin 0 -> 2511 bytes .../Resources/Pins/pinAPUseful.png | Bin 0 -> 2547 bytes Mod/Archipelago.HollowKnight/Settings.cs | 23 + .../SlotDataModel/SlotData.cs | 26 + .../SlotDataModel/SlotOptions.cs | 143 +++++ .../TimeoutExtensions.cs | 83 +++ Mod/LICENSE.txt | 22 + Mod/README.md | 41 ++ 55 files changed, 5271 insertions(+) create mode 100644 Mod/Archipelago.HollowKnight.sln create mode 100644 Mod/Archipelago.HollowKnight/Archipelago.HollowKnight.csproj create mode 100644 Mod/Archipelago.HollowKnight/ArchipelagoMod.cs create mode 100644 Mod/Archipelago.HollowKnight/ArchipelagoRandomizer.cs create mode 100644 Mod/Archipelago.HollowKnight/DeathLinkMessages.cs create mode 100644 Mod/Archipelago.HollowKnight/DupeUIDef.cs create mode 100644 Mod/Archipelago.HollowKnight/Enums.cs create mode 100644 Mod/Archipelago.HollowKnight/Extensions.cs create mode 100644 Mod/Archipelago.HollowKnight/GeneratedConsts.cs create mode 100644 Mod/Archipelago.HollowKnight/Goals.cs create mode 100644 Mod/Archipelago.HollowKnight/HintTracker.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/ArchipelagoItem.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/ArchipelagoSprite.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/ArchipelagoTags.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/ArchipelagoUIDef.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/CostFactory.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/ItemFactory.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Items/GoalItem.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/ArchipelagoRemoteItemCounterModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/BenchSyncModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/DeathLinkModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/DupeHandlingModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/GiftingModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/GoalModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/ItemNetworkingModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Modules/RepositionShadeModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/PlacementUtils.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/RM/HelperPlatformBuilder.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/RM/LICENSE create mode 100644 Mod/Archipelago.HollowKnight/IC/RM/NOTICE.md create mode 100644 Mod/Archipelago.HollowKnight/IC/RM/StartDef.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/RM/StartLocationSceneEditsModule.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/RemotePlacement.cs create mode 100644 Mod/Archipelago.HollowKnight/IC/Tags/ArchipelagoRemoteItemTag.cs create mode 100644 Mod/Archipelago.HollowKnight/LoginValidationException.cs create mode 100644 Mod/Archipelago.HollowKnight/MC/ArchipelagoModeMenuConstructor.cs create mode 100644 Mod/Archipelago.HollowKnight/ModDependencies.txt create mode 100644 Mod/Archipelago.HollowKnight/Resources/Data/starts.json create mode 100644 Mod/Archipelago.HollowKnight/Resources/DeathLinkIcon.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/GrubHappyv2.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconBlue.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconBlueBig.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconBlueSmall.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconColor.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconColorBig.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/IconColorSmall.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/Pins/pinAP.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/Pins/pinAPProgression.png create mode 100644 Mod/Archipelago.HollowKnight/Resources/Pins/pinAPUseful.png create mode 100644 Mod/Archipelago.HollowKnight/Settings.cs create mode 100644 Mod/Archipelago.HollowKnight/SlotDataModel/SlotData.cs create mode 100644 Mod/Archipelago.HollowKnight/SlotDataModel/SlotOptions.cs create mode 100644 Mod/Archipelago.HollowKnight/TimeoutExtensions.cs create mode 100644 Mod/LICENSE.txt create mode 100644 Mod/README.md diff --git a/Mod/Archipelago.HollowKnight.sln b/Mod/Archipelago.HollowKnight.sln new file mode 100644 index 0000000..0036850 --- /dev/null +++ b/Mod/Archipelago.HollowKnight.sln @@ -0,0 +1,35 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32228.430 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Archipelago.HollowKnight", "Archipelago.HollowKnight\Archipelago.HollowKnight.csproj", "{7B597421-1AA1-4880-B095-7A293B7FF39E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EA5CCD5F-7520-420B-B06F-5506BB4E18F6}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + .github\workflows\auto-dependabot.yml = .github\workflows\auto-dependabot.yml + .github\workflows\build-release.yml = .github\workflows\build-release.yml + .github\dependabot.yml = .github\dependabot.yml + README.md = README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7B597421-1AA1-4880-B095-7A293B7FF39E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B597421-1AA1-4880-B095-7A293B7FF39E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B597421-1AA1-4880-B095-7A293B7FF39E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B597421-1AA1-4880-B095-7A293B7FF39E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3054058D-AA08-4F84-AFE6-6665F9B3BBA2} + EndGlobalSection +EndGlobal diff --git a/Mod/Archipelago.HollowKnight/Archipelago.HollowKnight.csproj b/Mod/Archipelago.HollowKnight/Archipelago.HollowKnight.csproj new file mode 100644 index 0000000..c8cc7fe --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Archipelago.HollowKnight.csproj @@ -0,0 +1,335 @@ + + + Archipelago.HollowKnight + Archipelago.HollowKnight + net472 + HollowKnight.Archipelago + HollowKnight.Archipelago + The Archipelago Multiworld client for Hollow Knight + + + 0.11.0 + bin\$(Configuration)\ + preview + The Archipelago Community + https://github.com/ArchipelagoMW-HollowKnight/Archipelago.HollowKnight + git + MIT + Archipelago + ../API + bin/Publish + Hussein Farran, Daniel Grace, BadMagic, KonoTyran, Dragonglove + EmbeddedResource + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + $(HollowKnightRefs)/Assembly-CSharp.dll + + + $(HollowKnightRefs)/Assembly-CSharp-firstpass.dll + + + $(HollowKnightRefs)/Mods/Benchwarp/Benchwarp.dll + + + $(HollowKnightRefs)/GalaxyCSharp.dll + + + $(HollowKnightRefs)/Mods/ItemChanger/ItemChanger.dll + + + $(HollowKnightRefs)/Mods/MenuChanger/MenuChanger.dll + + + $(HollowKnightRefs)/MMHOOK_Assembly-CSharp.dll + + + $(HollowKnightRefs)/MMHOOK_PlayMaker.dll + + + $(HollowKnightRefs)/Mono.Cecil.dll + + + $(HollowKnightRefs)/Mono.Security.dll + + + $(HollowKnightRefs)/MonoMod.RuntimeDetour.dll + + + $(HollowKnightRefs)/MonoMod.Utils.dll + + + $(HollowKnightRefs)/netstandard.dll + + + $(HollowKnightRefs)/PlayMaker.dll + + + $(HollowKnightRefs)/System.ComponentModel.Composition.dll + + + $(HollowKnightRefs)/System.Configuration.dll + + + $(HollowKnightRefs)/System.Diagnostics.StackTrace.dll + + + $(HollowKnightRefs)/System.EnterpriseServices.dll + + + $(HollowKnightRefs)/System.Globalization.Extensions.dll + + + + + + $(HollowKnightRefs)/System.Transactions.dll + + + $(HollowKnightRefs)/System.Xml.XPath.XDocument.dll + + + $(HollowKnightRefs)/Unity.Timeline.dll + + + $(HollowKnightRefs)/UnityEngine.dll + + + $(HollowKnightRefs)/UnityEngine.AccessibilityModule.dll + + + $(HollowKnightRefs)/UnityEngine.AIModule.dll + + + $(HollowKnightRefs)/UnityEngine.AndroidJNIModule.dll + + + $(HollowKnightRefs)/UnityEngine.AnimationModule.dll + + + $(HollowKnightRefs)/UnityEngine.ARModule.dll + + + $(HollowKnightRefs)/UnityEngine.AssetBundleModule.dll + + + $(HollowKnightRefs)/UnityEngine.AudioModule.dll + + + $(HollowKnightRefs)/UnityEngine.ClothModule.dll + + + $(HollowKnightRefs)/UnityEngine.ClusterInputModule.dll + + + $(HollowKnightRefs)/UnityEngine.ClusterRendererModule.dll + + + $(HollowKnightRefs)/UnityEngine.CoreModule.dll + + + $(HollowKnightRefs)/UnityEngine.CrashReportingModule.dll + + + $(HollowKnightRefs)/UnityEngine.DirectorModule.dll + + + $(HollowKnightRefs)/UnityEngine.DSPGraphModule.dll + + + $(HollowKnightRefs)/UnityEngine.GameCenterModule.dll + + + $(HollowKnightRefs)/UnityEngine.GIModule.dll + + + $(HollowKnightRefs)/UnityEngine.GridModule.dll + + + $(HollowKnightRefs)/UnityEngine.HotReloadModule.dll + + + $(HollowKnightRefs)/UnityEngine.ImageConversionModule.dll + + + $(HollowKnightRefs)/UnityEngine.IMGUIModule.dll + + + $(HollowKnightRefs)/UnityEngine.InputLegacyModule.dll + + + $(HollowKnightRefs)/UnityEngine.InputModule.dll + + + $(HollowKnightRefs)/UnityEngine.JSONSerializeModule.dll + + + $(HollowKnightRefs)/UnityEngine.LocalizationModule.dll + + + $(HollowKnightRefs)/UnityEngine.ParticleSystemModule.dll + + + $(HollowKnightRefs)/UnityEngine.PerformanceReportingModule.dll + + + $(HollowKnightRefs)/UnityEngine.Physics2DModule.dll + + + $(HollowKnightRefs)/UnityEngine.PhysicsModule.dll + + + $(HollowKnightRefs)/UnityEngine.ProfilerModule.dll + + + $(HollowKnightRefs)/UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll + + + $(HollowKnightRefs)/UnityEngine.ScreenCaptureModule.dll + + + $(HollowKnightRefs)/UnityEngine.SharedInternalsModule.dll + + + $(HollowKnightRefs)/UnityEngine.SpriteMaskModule.dll + + + $(HollowKnightRefs)/UnityEngine.SpriteShapeModule.dll + + + $(HollowKnightRefs)/UnityEngine.StreamingModule.dll + + + $(HollowKnightRefs)/UnityEngine.SubstanceModule.dll + + + $(HollowKnightRefs)/UnityEngine.SubsystemsModule.dll + + + $(HollowKnightRefs)/UnityEngine.TerrainModule.dll + + + $(HollowKnightRefs)/UnityEngine.TerrainPhysicsModule.dll + + + $(HollowKnightRefs)/UnityEngine.TextCoreModule.dll + + + $(HollowKnightRefs)/UnityEngine.TextRenderingModule.dll + + + $(HollowKnightRefs)/UnityEngine.TilemapModule.dll + + + $(HollowKnightRefs)/UnityEngine.TLSModule.dll + + + $(HollowKnightRefs)/UnityEngine.UI.dll + + + $(HollowKnightRefs)/UnityEngine.UIElementsModule.dll + + + $(HollowKnightRefs)/UnityEngine.UIElementsNativeModule.dll + + + $(HollowKnightRefs)/UnityEngine.UIModule.dll + + + $(HollowKnightRefs)/UnityEngine.UmbraModule.dll + + + $(HollowKnightRefs)/UnityEngine.UNETModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityAnalyticsModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityConnectModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityCurlModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityTestProtocolModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityWebRequestAssetBundleModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityWebRequestAudioModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityWebRequestModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityWebRequestTextureModule.dll + + + $(HollowKnightRefs)/UnityEngine.UnityWebRequestWWWModule.dll + + + $(HollowKnightRefs)/UnityEngine.VehiclesModule.dll + + + $(HollowKnightRefs)/UnityEngine.VFXModule.dll + + + $(HollowKnightRefs)/UnityEngine.VideoModule.dll + + + $(HollowKnightRefs)/UnityEngine.VirtualTexturingModule.dll + + + $(HollowKnightRefs)/UnityEngine.VRModule.dll + + + $(HollowKnightRefs)/UnityEngine.WindModule.dll + + + $(HollowKnightRefs)/UnityEngine.XRModule.dll + + + \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/ArchipelagoMod.cs b/Mod/Archipelago.HollowKnight/ArchipelagoMod.cs new file mode 100644 index 0000000..e62017c --- /dev/null +++ b/Mod/Archipelago.HollowKnight/ArchipelagoMod.cs @@ -0,0 +1,273 @@ +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.HollowKnight.MC; +using Archipelago.HollowKnight.SlotDataModel; +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Enums; +using ItemChanger; +using ItemChanger.Internal; +using Modding; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using UnityEngine; + +namespace Archipelago.HollowKnight +{ + public class ArchipelagoMod : Mod, IGlobalSettings, ILocalSettings, IMenuMod + { + // Events support + public static event Action OnArchipelagoGameStarted; + public static event Action OnArchipelagoGameEnded; + + /// + /// Minimum Archipelago Protocol Version + /// + private readonly Version ArchipelagoProtocolVersion = new(0, 5, 0); + + /// + /// Mod version as reported to the modding API + /// + public override string GetVersion() + { + Version assemblyVersion = GetType().Assembly.GetName().Version; + string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}"; +#if DEBUG + using SHA1 sha = SHA1.Create(); + using FileStream str = File.OpenRead(GetType().Assembly.Location); + StringBuilder sb = new(); + foreach (byte b in sha.ComputeHash(str).Take(4)) + { + sb.AppendFormat("{0:x2}", b); + } + version += "-prerelease+" + sb.ToString(); +#endif + return version; + } + public static ArchipelagoMod Instance; + public ArchipelagoSession session { get; private set; } + public SlotData SlotData { get; private set; } + public bool ArchipelagoEnabled { get; set; } + + public bool ToggleButtonInsideMenu => false; + + internal SpriteManager spriteManager; + + internal APGlobalSettings GS = new(); + internal APLocalSettings LS = new(); + + public ArchipelagoMod() : base("Archipelago") { } + + public override void Initialize(Dictionary> preloadedObjects) + { + base.Initialize(); + Log("Initializing"); + Instance = this; + spriteManager = new SpriteManager(typeof(ArchipelagoMod).Assembly, "Archipelago.HollowKnight.Resources."); + + MenuChanger.ModeMenu.AddMode(new ArchipelagoModeMenuConstructor()); + Log("Initialized"); + } + + public void EndGame() + { + LogDebug("Ending Archipelago game"); + try + { + OnArchipelagoGameEnded?.Invoke(); + } + catch (Exception ex) + { + LogError($"Error invoking OnArchipelagoGameEnded:\n {ex}"); + } + + DisconnectArchipelago(); + ArchipelagoEnabled = false; + LS = new(); + + Events.OnItemChangerUnhook -= EndGame; + } + + /// + /// Call when starting or resuming a game to randomize and restore state. + /// + public void StartOrResumeGame(bool randomize) + { + if (!ArchipelagoEnabled) + { + LogDebug("StartOrResumeGame: This is not an Archipelago Game, so not doing anything."); + return; + } + + LogDebug("StartOrResumeGame: This is an Archipelago Game."); + + LoginSuccessful loginResult = ConnectToArchipelago(); + + if (randomize) + { + LogDebug("StartOrResumeGame: Beginning first time randomization."); + LS.Seed = SlotData.Seed; + LS.RoomSeed = session.RoomState.Seed; + + LogDebug($"StartOrResumeGame: Room: {LS.RoomSeed}; Seed = {LS.RoomSeed}"); + + ArchipelagoRandomizer randomizer = new(SlotData); + randomizer.Randomize(); + } + else + { + LogDebug($"StartOrResumeGame: Local : Room: {LS.RoomSeed}; Seed = {LS.Seed}"); + int seed = SlotData.Seed; + LogDebug($"StartOrResumeGame: AP : Room: {session.RoomState.Seed}; Seed = {seed}"); + if (seed != LS.Seed || session.RoomState.Seed != LS.RoomSeed) + { + throw new LoginValidationException("Slot mismatch. Saved seed does not match the server value. Is this the correct save?"); + } + } + + // check the goal is one we know how to cope with + if (SlotData.Options.Goal > GoalsLookup.MAX) + { + throw new LoginValidationException($"Unrecognized goal condition {SlotData.Options.Goal} (are you running an outdated client?)"); + } + + // Hooks happen after we've definitively connected to an Archipelago slot correctly. + // Doing this before checking for the correct slot/seed/room will cause problems if + // the client connects to the wrong session with a matching slot. + Events.OnItemChangerUnhook += EndGame; + + try + { + OnArchipelagoGameStarted?.Invoke(); + } + catch (Exception ex) + { + LogError($"Error invoking OnArchipelagoGameStarted:\n {ex}"); + } + } + + private void OnSocketClosed(string reason) + { + ItemChangerMod.Modules.Get().ReportDisconnect(); + } + + private LoginSuccessful ConnectToArchipelago() + { + session = ArchipelagoSessionFactory.CreateSession(LS.ConnectionDetails.ServerUrl, LS.ConnectionDetails.ServerPort); + + LoginResult loginResult = session.TryConnectAndLogin("Hollow Knight Test", + LS.ConnectionDetails.SlotName, + ItemsHandlingFlags.AllItems, + ArchipelagoProtocolVersion, + password: LS.ConnectionDetails.ServerPassword, + requestSlotData: false); + + if (loginResult is LoginFailure failure) + { + string errors = string.Join(", ", failure.Errors); + LogError($"Unable to connect to Archipelago because: {string.Join(", ", failure.Errors)}"); + throw new LoginValidationException(errors); + } + else if (loginResult is LoginSuccessful success) + { + SlotData = session.DataStorage.GetSlotData(); + session.Socket.SocketClosed += OnSocketClosed; + + return success; + } + else + { + LogError($"Unexpected LoginResult type when connecting to Archipelago: {loginResult}"); + throw new LoginValidationException("Unexpected login result."); + } + } + + public void DisconnectArchipelago() + { + if (session?.Socket != null) + { + session.Socket.SocketClosed -= OnSocketClosed; + } + + if (session?.Socket != null && session.Socket.Connected) + { + session.Socket.DisconnectAsync(); + } + + session = null; + } + + /// + /// Called when loading local (game-specific save data) + /// + /// + /// This is also called on the main menu screen with empty (defaulted) ConnectionDetails. This will have an empty SlotName, so we treat this as a noop. + /// + /// + public void OnLoadLocal(APLocalSettings ls) + { + if (ls.ConnectionDetails == null + || ls.ConnectionDetails.SlotName == null + || ls.ConnectionDetails.SlotName == "") // Apparently, this is called even before a save is loaded. Catch this. + { + return; + } + + LS = ls; + } + + /// + /// Called when saving local (game-specific) save data. + /// + /// + public APLocalSettings OnSaveLocal() + { + if (!ArchipelagoEnabled) + { + return default; + } + + return LS; + } + + /// + /// Called when loading global save data. + /// + /// + /// For simplicity's sake, we use the same data structure for both global and local save data, though not all fields are relevant in the global context. + /// + /// + public void OnLoadGlobal(APGlobalSettings gs) + { + GS = gs; + } + + /// + /// Called when saving global save data. + /// + /// + public APGlobalSettings OnSaveGlobal() + { + APGlobalSettings r = GS with + { + MenuConnectionDetails = GS.MenuConnectionDetails with { ServerPassword = null } + }; + return r; + } + + public List GetMenuData(IMenuMod.MenuEntry? toggleButtonEntry) + { + return [ + new IMenuMod.MenuEntry( + "Enable Gifting", + ["false", "true"], + "Enable or disable interaction with the Archipelago gifting system. Requires reloading the save to take effect.", + (v) => GS.EnableGifting = v == 1, + () => GS.EnableGifting ? 1 : 0 + ) + ]; + } + } +} diff --git a/Mod/Archipelago.HollowKnight/ArchipelagoRandomizer.cs b/Mod/Archipelago.HollowKnight/ArchipelagoRandomizer.cs new file mode 100644 index 0000000..bafe64b --- /dev/null +++ b/Mod/Archipelago.HollowKnight/ArchipelagoRandomizer.cs @@ -0,0 +1,397 @@ +using Archipelago.HollowKnight.IC; +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.HollowKnight.IC.RM; +using Archipelago.HollowKnight.SlotDataModel; +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using ItemChanger.Extensions; +using ItemChanger.Modules; +using ItemChanger.Placements; +using ItemChanger.Tags; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Archipelago.HollowKnight +{ + /// + /// Tracks state only required during initial randomization + /// + internal class ArchipelagoRandomizer + { + /// + /// Randomized charm notch costs as stored in slot data. + /// + public List NotchCosts { get; private set; } + + /// + /// Tracks created placements and their associated locations during randomization. + /// + public Dictionary placements = new(); + + /// + /// Seeded RNG for clientside randomization. + /// + public readonly Random Random; + + /// + /// Factory for IC item creation + /// + public readonly ItemFactory itemFactory; + + /// + /// Factory for IC cost creation + /// + public readonly CostFactory costFactory; + + private readonly SlotData SlotData; + private ArchipelagoSession Session => ArchipelagoMod.Instance.session; + private ArchipelagoMod Instance => ArchipelagoMod.Instance; + + public ArchipelagoRandomizer(SlotData slotData) + { + SlotData = slotData; + Random = new Random(slotData.Seed); + itemFactory = new ItemFactory(); + costFactory = new CostFactory(slotData.LocationCosts); + NotchCosts = slotData.NotchCosts; + + ArchipelagoMod.Instance.Log("Initializing ArchipelagoRandomizer with slot data: " + JsonConvert.SerializeObject(SlotData)); + } + + public void Randomize() + { + ArchipelagoSession session = Session; + ItemChangerMod.CreateSettingsProfile(); + if (SlotData.Options.StartLocationName is string start) + { + if (IC.RM.StartDef.Lookup.TryGetValue(start, out IC.RM.StartDef def)) + { + ItemChangerMod.ChangeStartGame(def.ToItemChangerStartDef()); + ArchipelagoMod.Instance.Log($"Set start to {start}"); + } + else + { + ArchipelagoMod.Instance.LogError($"Unsupported start location {start}, starting in King's Pass"); + } + } + + // Add IC modules as needed + // FUTURE: If Entrance rando, disable palace midwarp and some logical blockers + // if (Entrance Rando Is Enabled) { + // ItemChangerMod.Modules.Add(); + // ItemChangerMod.Modules.Add(); + // } + + AddItemChangerModules(); + AddHelperPlatforms(); + + ApplyCharmCosts(); + + // Initialize shop locations in case they end up with zero items placed. + AbstractLocation location; + AbstractPlacement pmt; + + string[] shops = [ + LocationNames.Sly, LocationNames.Sly_Key, LocationNames.Iselda, + LocationNames.Salubra, LocationNames.Leg_Eater, LocationNames.Grubfather, + LocationNames.Seer + ]; + foreach (string name in shops) + { + location = Finder.GetLocation(name); + placements[name] = pmt = location.Wrap(); + + pmt.AddTag(); + + if (pmt is ShopPlacement shop) + { + shop.defaultShopItems = DefaultShopItems.IseldaMapPins + | DefaultShopItems.IseldaMapMarkers + | DefaultShopItems.LegEaterRepair; + if (SlotData.Options.AddUnshuffledLocations) + { + // AP will add the default items on our behalf + continue; + } + + if (!SlotData.Options.RandomizeCharms) + { + shop.defaultShopItems |= DefaultShopItems.SlyCharms + | DefaultShopItems.SlyKeyCharms + | DefaultShopItems.IseldaCharms + | DefaultShopItems.SalubraCharms + | DefaultShopItems.LegEaterCharms; + } + if (!SlotData.Options.RandomizeMaps) + { + shop.defaultShopItems |= DefaultShopItems.IseldaMaps + | DefaultShopItems.IseldaQuill; + } + if (!SlotData.Options.RandomizeCharmNotches) + { + shop.defaultShopItems |= DefaultShopItems.SalubraNotches + | DefaultShopItems.SalubraBlessing; + } + if (!SlotData.Options.RandomizeKeys) + { + shop.defaultShopItems |= DefaultShopItems.SlySimpleKey + | DefaultShopItems.SlyLantern + | DefaultShopItems.SlyKeyElegantKey; + } + if (!SlotData.Options.RandomizeMaskShards) + { + shop.defaultShopItems |= DefaultShopItems.SlyMaskShards; + } + if (!SlotData.Options.RandomizeVesselFragments) + { + shop.defaultShopItems |= DefaultShopItems.SlyVesselFragments; + } + if (!SlotData.Options.RandomizeRancidEggs) + { + shop.defaultShopItems |= DefaultShopItems.SlyRancidEgg; + } + } + else if (name == LocationNames.Grubfather) + { + DestroyGrubRewardTag t = pmt.AddTag(); + t.destroyRewards = GrubfatherRewards.None; + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeMaskShards) + { + t.destroyRewards |= GrubfatherRewards.MaskShard; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeCharms) + { + t.destroyRewards |= GrubfatherRewards.Grubsong | GrubfatherRewards.GrubberflysElegy; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeRancidEggs) + { + t.destroyRewards |= GrubfatherRewards.RancidEgg; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeRelics) + { + t.destroyRewards |= GrubfatherRewards.HallownestSeal | GrubfatherRewards.KingsIdol; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizePaleOre) + { + t.destroyRewards |= GrubfatherRewards.PaleOre; + } + } + else if (name == LocationNames.Seer) + { + DestroySeerRewardTag t = pmt.AddTag(); + t.destroyRewards = SeerRewards.None; + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeRelics) + { + t.destroyRewards |= SeerRewards.HallownestSeal | SeerRewards.ArcaneEgg; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizePaleOre) + { + t.destroyRewards |= SeerRewards.PaleOre; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeCharms) + { + t.destroyRewards |= SeerRewards.DreamWielder; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeVesselFragments) + { + t.destroyRewards |= SeerRewards.VesselFragment; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeSkills) + { + t.destroyRewards |= SeerRewards.DreamGate | SeerRewards.AwokenDreamNail; + } + if (SlotData.Options.AddUnshuffledLocations || SlotData.Options.RandomizeMaskShards) + { + t.destroyRewards |= SeerRewards.MaskShard; + } + } + } + + Task> scoutTask = session.Locations + .ScoutLocationsAsync(session.Locations.AllLocations.ToArray()); + scoutTask.Wait(); + + Dictionary scoutResult = scoutTask.Result; + foreach (KeyValuePair scout in scoutResult) + { + long id = scout.Key; + ScoutedItemInfo item = scout.Value; + string itemName = item.ItemName ?? $"?Item {item.ItemId}"; + PlaceItem(item.LocationName, itemName, item); + } + ItemChangerMod.AddPlacements(placements.Values); + + } + + private void AddItemChangerModules() + { + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + + if (SlotData.Options.DeathLink) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.RandomizeElevatorPass) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.RandomizeFocus) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.RandomizeSwim) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.SplitMothwingCloak) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.SplitMantisClaw) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.SplitCrystalHeart) + { + ItemChangerMod.Modules.Add(); + } + + if (SlotData.Options.Slopeballs) + { + ItemChangerMod.Modules.Add(); + } + } + + private void AddHelperPlatforms() + { + HelperPlatformBuilder.AddConveniencePlatforms(SlotData.Options); + HelperPlatformBuilder.AddStartLocationRequiredPlatforms(SlotData.Options); + } + + private void ApplyCharmCosts() + { + bool isNotchCostsRandomizedOrPlando = false; + for (int i = 0; i < NotchCosts.Count; i++) + { + if (PlayerData.instance.GetInt($"charmCost_{i + 1}") != NotchCosts[i]) + { + isNotchCostsRandomizedOrPlando = true; + break; + } + } + if (!isNotchCostsRandomizedOrPlando) + { + return; + } + + ItemChangerMod.Modules.Add(); + ItemChangerMod.Modules.Add(); + PlayerDataEditModule playerDataEditModule = ItemChangerMod.Modules.GetOrAdd(); + Instance.LogDebug(playerDataEditModule); + for (int i = 0; i < NotchCosts.Count; i++) + { + playerDataEditModule.AddPDEdit($"charmCost_{i + 1}", NotchCosts[i]); + } + } + + public void PlaceItem(string location, string name, ScoutedItemInfo itemInfo) + { + Instance.LogDebug($"[PlaceItem] Placing item {name} into {location} with ID {itemInfo.ItemId}"); + + string originalLocation = string.Copy(location); + location = StripShopSuffix(location); + // IC does not like placements at these locations if there's also a location at the lore tablet, it renders the lore tablet inoperable. + // But we can have multiple placements at the same location, so do this workaround. (Rando4 does something similar per its README) + if (SlotData.Options.RandomizeLoreTablets) + { + switch (location) + { + case LocationNames.Focus: + location = LocationNames.Lore_Tablet_Kings_Pass_Focus; + break; + case LocationNames.World_Sense: + location = LocationNames.Lore_Tablet_World_Sense; + break; + // no default + } + } + + AbstractLocation loc = Finder.GetLocation(location); + if (loc == null) + { + Instance.LogDebug($"[PlaceItem] Location was null: Name: {location}."); + return; + } + + bool isMyItem = itemInfo.IsReceiverRelatedToActivePlayer; + string recipientName = null; + if (!isMyItem) + { + recipientName = Session.Players.GetPlayerName(itemInfo.Player); + } + + AbstractPlacement pmt = placements.GetOrDefault(location); + if (pmt == null) + { + pmt = loc.Wrap(); + pmt.AddTag(); + placements[location] = pmt; + } + + AbstractItem item; + if (isMyItem) + { + item = itemFactory.CreateMyItem(name, itemInfo); + } + else + { + item = itemFactory.CreateRemoteItem(pmt, recipientName, name, itemInfo); + } + + pmt.Add(item); + costFactory.ApplyCost(pmt, item, originalLocation); + } + + private string StripShopSuffix(string location) + { + if (string.IsNullOrEmpty(location)) + { + return null; + } + + string[] names = + [ + LocationNames.Sly_Key, LocationNames.Sly, LocationNames.Iselda, LocationNames.Salubra, + LocationNames.Leg_Eater, LocationNames.Egg_Shop, LocationNames.Seer, LocationNames.Grubfather + ]; + + foreach (string name in names) + { + if (location.StartsWith(name)) + { + return location.Substring(0, name.Length); + } + } + + return location; + } + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/DeathLinkMessages.cs b/Mod/Archipelago.HollowKnight/DeathLinkMessages.cs new file mode 100644 index 0000000..6cca25c --- /dev/null +++ b/Mod/Archipelago.HollowKnight/DeathLinkMessages.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight +{ + public static class DeathLinkMessages + { + public static readonly List DefaultMessages = new() + { + "@ died.", + "@ has perished.", + "@ made poor life choices.", + "@ didn't listen to Hornet's advice.", + "@ took damage equal to or more than their current HP.", + "@ made a fatal mistake.", + "@ threw some shade at @.", + "@ decided to set up a Shade Skip.", // A System of Vibrant Colors (edited) + "Hopefully @ didn't have a fragile charm equipped.", // Koatlus + "A true servant gives all for the Kingdom. Let @ relieve you of your life.", // Koatlus + "Through @'s sacrifice, you are now dead.", // Koatlus + "The truce remains. Our vigil holds. @ must respawn.", // Koatlus + "Hopefully @ didn't have a fragile charm equipped.", // Koatlus + }; + + public static readonly List UnknownMessages = new() + { + "@ has died in a manner most unusual.", + "@ found a way to break the game, and the game broke @ back.", + "@ has lost The Game", + }; + + public static readonly Dictionary> MessagesByType = new() + { + { + 1, // Deaths from enemy damage + new List + { + "@ has discovered that there are bugs in Hallownest.", + "@ should have dodged.", + "@ should have jumped.", + "@ significantly mistimed their parry attempt.", + "@ should have considered equipping Dreamshield.", + "@ must have never fought that enemy before.", + "@ did not make it to phase 2.", + "@ dashed in the wrong direction.", // Murphmario + "@ tried to talk it out.", // SnowOfAllTrades + "@ made masterful use of their vulnerability frames.", + } + }, + { + 2, // Deaths from spikes + new List + { + "@ was in the wrong place.", + "@ mistimed their jump.", + "@ didn't see the sharp things.", + "@ didn't see that saw.", + "@ fought the spikes and the spikes won.", + "@ sought roses but found only thorns.", + "@ was pricked to death.", // A System of Vibrant Colors + "@ dashed in the wrong direction.", // Murphmario + "@ found their own Path of Pain.", // Fatman + "@ has strayed from the White King's roads.", // Koatlus + } + }, + { + 3, // Deaths from acid + new List + { + "@ was in the wrong place.", + "@ mistimed their jump.", + "@ forgot their floaties.", + "What @ thought was H2O was H2SO4.", + "@ wishes they could swim.", + "@ used the wrong kind of dive.", + "@ got into a fight with a pool of liquid and lost.", + "@ forgot how to swim", // squidy + } + }, + { + 999, // Deaths in the dream realm + new List + { + "@ dozed off for good.", + "@ was caught sleeping on the job.", + "@ sought dreams but found only nightmares.", + "@ got lost in Limbo.", + "Good night, @.", + "@ is resting in pieces.", + "@ exploded into a thousand pieces of essence.", + "Hey, @, you're finally awake.", + } + }, + }; + + private static readonly Random random = new(); // This is only messaging, so does not need to be seeded. + + public static string GetDeathMessage(int cause, string player) + { + // Build candidate death messages. + List messages; + bool knownCauseOfDeath = MessagesByType.TryGetValue(cause, out messages); + + if (knownCauseOfDeath) + { + messages = new(messages); + messages.AddRange(DefaultMessages); + } + else + { + messages = UnknownMessages; + } + + // Choose one at random + string message = messages[random.Next(0, messages.Count)].Replace("@", player); + + // If it's an unknown death, tag in some debugging info + if (!knownCauseOfDeath) + { + ArchipelagoMod.Instance.LogWarn($"UNKNOWN cause of death {cause}"); + message += $" (Type: {cause})"; + } + + return message; + } + }; +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/DupeUIDef.cs b/Mod/Archipelago.HollowKnight/DupeUIDef.cs new file mode 100644 index 0000000..b46ab3f --- /dev/null +++ b/Mod/Archipelago.HollowKnight/DupeUIDef.cs @@ -0,0 +1,46 @@ +using ItemChanger; +using ItemChanger.UIDefs; +using UnityEngine; + +namespace Archipelago.HollowKnight; + +public class DupeUIDef : MsgUIDef +{ + public static MsgUIDef Of(UIDef inner) + { + if (inner is MsgUIDef msg) + { + return new SplitUIDef + { + preview = new BoxedString(msg.GetPreviewName()), + name = new BoxedString($"Nothing ({msg.GetPostviewName()})"), + shopDesc = msg.shopDesc?.Clone(), + sprite = msg.sprite?.Clone(), + }; + } + return new DupeUIDef(inner); + } + + public UIDef Inner { get; set; } + private DupeUIDef(UIDef inner) + { + Inner = inner; + sprite = new ItemChangerSprite("ShopIcons.LampBug"); + if (inner is null) + { + name = new BoxedString("Nothing (Dupe)"); + shopDesc = new BoxedString(""); + } + else + { + // with good practice these should never be accessed but better not to break stuff + name = new BoxedString($"Nothing ({inner.GetPostviewName()})"); + shopDesc = new BoxedString(inner.GetShopDesc()); + } + } + + public override Sprite GetSprite() => Inner is not null ? Inner.GetSprite() : base.GetSprite(); + public override string GetPreviewName() => Inner is not null ? Inner.GetPreviewName() : base.GetPreviewName(); + public override string GetPostviewName() => Inner is not null ? Inner.GetPostviewName() : base.GetPostviewName(); + public override string GetShopDesc() => Inner is not null ? Inner.GetShopDesc() : base.GetShopDesc(); +} diff --git a/Mod/Archipelago.HollowKnight/Enums.cs b/Mod/Archipelago.HollowKnight/Enums.cs new file mode 100644 index 0000000..9c85cb0 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Enums.cs @@ -0,0 +1,24 @@ +namespace Archipelago.HollowKnight +{ + public enum DeathLinkStatus + { + None = 0, + Pending = 1, + Dying = 2 + } + + public enum DeathLinkShadeHandling + { + Vanilla = 0, + Shadeless = 1, + Shade = 2 + } + + public enum WhitePalaceOption + { + Exclude = 0, + KingFragment = 1, + NoPathOfPain = 2, + Include = 3 + } +} diff --git a/Mod/Archipelago.HollowKnight/Extensions.cs b/Mod/Archipelago.HollowKnight/Extensions.cs new file mode 100644 index 0000000..088c7f1 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Extensions.cs @@ -0,0 +1,16 @@ +using ItemChanger; + +namespace Archipelago.HollowKnight; + +public static class Extensions +{ + public static string GetPreviewWithCost(this AbstractItem item) + { + string text = item.GetPreviewName(); + if (item.GetTag(out CostTag tag)) + { + text += " - " + tag.Cost.GetCostText(); + } + return text; + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/GeneratedConsts.cs b/Mod/Archipelago.HollowKnight/GeneratedConsts.cs new file mode 100644 index 0000000..aea4869 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/GeneratedConsts.cs @@ -0,0 +1,6 @@ +using RandoConstantGenerators; + +namespace Archipelago.HollowKnight; + +[GenerateJsonConsts("$.*~", "Data/starts.json")] +public static partial class StartLocationNames { } diff --git a/Mod/Archipelago.HollowKnight/Goals.cs b/Mod/Archipelago.HollowKnight/Goals.cs new file mode 100644 index 0000000..0397a2d --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Goals.cs @@ -0,0 +1,307 @@ +using Archipelago.HollowKnight.IC; +using Archipelago.HollowKnight.IC.Items; +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.MultiClient.Net.Exceptions; +using ItemChanger; +using ItemChanger.Extensions; +using ItemChanger.Internal; +using ItemChanger.Placements; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Archipelago.HollowKnight +{ + public enum GoalsLookup + { + Any = 0, + HollowKnight = 1, + SealedSiblings = 2, + Radiance = 3, + Godhome = 4, + GodhomeFlower = 5, + GrubHunt = 6, + MAX = GrubHunt + } + + public abstract class Goal + { + public abstract string Name { get; } + public abstract string Description { get; } + public virtual bool CanBeSelectedForAnyGoal => true; + + private static readonly Dictionary Lookup = new() + { + [GoalsLookup.HollowKnight] = new HollowKnightGoal(), + [GoalsLookup.SealedSiblings] = new SealedSiblingsGoal(), + [GoalsLookup.Radiance] = new RadianceGoal(), + [GoalsLookup.Godhome] = new GodhomeGoal(), + [GoalsLookup.GodhomeFlower] = new GodhomeFlowerGoal(), + [GoalsLookup.GrubHunt] = new GrubHuntGoal(), + }; + + static Goal() + { + Lookup[GoalsLookup.Any] = new AnyGoal(Lookup.Values.ToList()); + } + + protected void FountainPlaqueTopEdit(ref string s) => s = "Your goal is"; + protected void FountainPlaqueNameEdit(ref string s) => s = Name; + protected void FountainPlaqueDescEdit(ref string s) => s = Description; + + protected abstract bool VictoryCondition(); + + public static Goal GetGoal(GoalsLookup key) + { + Goal value; + if (Lookup.TryGetValue(key, out value)) + { + return value; + } + ArchipelagoMod.Instance.LogError($"Listed goal is {key}, which is greater than {GoalsLookup.MAX}. Is this an outdated client?"); + throw new ArgumentOutOfRangeException($"Unrecognized goal condition {key} (are you running an outdated client?)"); + } + + public async Task CheckForVictoryAsync() + { + ArchipelagoMod.Instance.LogDebug($"Checking for victory; goal is {this.Name}; scene " + + $"{UnityEngine.SceneManagement.SceneManager.GetActiveScene().name}"); + if (VictoryCondition()) + { + ArchipelagoMod.Instance.LogDebug($"Victory detected, declaring!"); + try + { + await ItemChangerMod.Modules.Get().DeclareVictoryAsync().TimeoutAfter(1000); + } + catch (Exception ex) when (ex is TimeoutException or ArchipelagoSocketClosedException) + { + ArchipelagoMod.Instance.LogError("Failed to send goal to server"); + ArchipelagoMod.Instance.LogError(ex); + } + } + } + + public void Select() + { + Events.AddLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_TOP"), FountainPlaqueTopEdit); + Events.AddLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_MAIN"), FountainPlaqueNameEdit); + Events.AddLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_DESC"), FountainPlaqueDescEdit); + OnSelected(); + } + + public void Deselect() + { + Events.RemoveLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_TOP"), FountainPlaqueTopEdit); + Events.RemoveLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_MAIN"), FountainPlaqueNameEdit); + Events.RemoveLanguageEdit(new LanguageKey("Prompts", "FOUNTAIN_PLAQUE_DESC"), FountainPlaqueDescEdit); + OnDeselected(); + } + + public abstract void OnSelected(); + public abstract void OnDeselected(); + } + + public class AnyGoal : Goal + { + private IReadOnlyList subgoals; + + public override string Name => "Any Goal"; + + public override string Description => "Do whichever goal you like. If you're not sure,
try defeating the Hollow Knight!"; + + public AnyGoal(IReadOnlyList subgoals) + { + this.subgoals = subgoals; + } + + public override void OnSelected() + { + foreach (Goal goal in subgoals.Where(g => g.CanBeSelectedForAnyGoal)) + { + goal.OnSelected(); + } + } + + public override void OnDeselected() + { + foreach (Goal goal in subgoals.Where(g => g.CanBeSelectedForAnyGoal)) + { + goal.OnDeselected(); + } + } + + protected override bool VictoryCondition() + { + // this goal is never completed on its own, it relies on subgoals to check for victory themselves. + throw new NotImplementedException(); + } + } + + /// + /// A goal which is achieved by completing a given ending (or harder) + /// + public abstract class EndingGoal : Goal + { + private static List VictoryScenes = new() + { + SceneNames.Cinematic_Ending_A, // THK + SceneNames.Cinematic_Ending_B, // Sealed Siblings + SceneNames.Cinematic_Ending_C, // Radiance + "Cinematic_Ending_D", // Godhome no flower quest + SceneNames.Cinematic_Ending_E // Godhome w/ flower quest + }; + + public abstract string MinimumGoalScene { get; } + + public override void OnSelected() + { + Events.OnSceneChange += SceneChanged; + } + + public override void OnDeselected() + { + Events.OnSceneChange -= SceneChanged; + } + + private async void SceneChanged(UnityEngine.SceneManagement.Scene obj) + { + await CheckForVictoryAsync(); + } + + protected override bool VictoryCondition() + { + string activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; + if (activeScene.StartsWith("Cinematic_Ending_")) + { + int minGoalSceneIndex = VictoryScenes.IndexOf(MinimumGoalScene); + int sceneIndex = VictoryScenes.IndexOf(activeScene); + return sceneIndex >= minGoalSceneIndex; + } + return false; + } + + } + + /// + /// A goal which is achieved by obtaining the Victory item placed at a given location in the world + /// + public abstract class ItemGoal : Goal + { + // We don't use CheckForVictoryAsync here, rather, the Victory item uses GoalModule.DeclareVictoryAsync + // directly when acquired. + protected override bool VictoryCondition() => false; + + protected virtual string GetGoalItemName() => "Victory"; + protected abstract string GetGoalLocation(); + protected virtual Cost GetGoalCost() => null; + protected virtual UIDef GetGoalUIDef() => new ArchipelagoUIDef() + { + name = new BoxedString(GetGoalItemName()), + shopDesc = new BoxedString("You completed your goal so you should probably get this to flex on your friends."), + sprite = new ArchipelagoSprite { key = "IconColorSmall" } + }; + + public override void OnSelected() + { + string goalLocation = GetGoalLocation(); + AbstractPlacement plt = Ref.Settings.Placements.GetOrDefault(goalLocation); + if (plt == null) + { + plt = Finder.GetLocation(goalLocation).Wrap(); + } + + // don't duplicate the goal + if (plt.Items.Any(i => i is GoalItem)) + { + return; + } + + AbstractItem item = new GoalItem() + { + name = GetGoalItemName(), + UIDef = GetGoalUIDef(), + }; + // modules (and therefore goals) are loaded prior to placements so nothing special needed + // to make this load. + plt.Add(item); + + // handle the cost + if (plt is ISingleCostPlacement icsp) + { + Cost desiredCost = GetGoalCost(); + if (icsp.Cost == null) + { + icsp.Cost = desiredCost; + } + else + { + icsp.Cost += desiredCost; + } + } + else + { + item.AddTag(new CostTag() + { + Cost = GetGoalCost(), + }); + } + } + + public override void OnDeselected() { } + } + + public class HollowKnightGoal : EndingGoal + { + public override string Name => "The Hollow Knight"; + public override string Description => "Defeat The Hollow Knight
or any harder ending."; + public override string MinimumGoalScene => SceneNames.Cinematic_Ending_A; + } + + public class SealedSiblingsGoal : EndingGoal + { + public override string Name => "Sealed Siblings"; + public override string Description => "Complete the Sealed Siblings ending
or any harder ending."; + public override string MinimumGoalScene => SceneNames.Cinematic_Ending_B; + } + + public class RadianceGoal : EndingGoal + { + public override string Name => "Dream No More"; + public override string Description => "Defeat The Radiance in Black Egg Temple
or Absolute Radiance in Pantheon 5."; + public override string MinimumGoalScene => SceneNames.Cinematic_Ending_C; + } + + public class GodhomeGoal : EndingGoal + { + public override string Name => "Embrace the Void"; + public override string Description => "Defeat Absolute Radiance in Pantheon 5."; + public override string MinimumGoalScene => "Cinematic_Ending_D"; + } + + public class GodhomeFlowerGoal : EndingGoal + { + public override string Name => "Delicate Flower"; + public override string Description => "Defeat Absolute Radiance in Pantheon 5
after delivering the flower to the Godseeker."; + public override string MinimumGoalScene => SceneNames.Cinematic_Ending_E; + } + + public class GrubHuntGoal : ItemGoal + { + public override string Name => "Grub Hunt"; + + public override string Description => $"Save {ArchipelagoMod.Instance.SlotData.GrubsRequired.Value} of your Grubs and visit Grubfather
to obtain happiness."; + + public override bool CanBeSelectedForAnyGoal => ArchipelagoMod.Instance.SlotData.GrubsRequired != null; + + protected override string GetGoalItemName() => "Happiness"; + protected override string GetGoalLocation() => LocationNames.Grubfather; + protected override Cost GetGoalCost() => Cost.NewGrubCost(ArchipelagoMod.Instance.SlotData.GrubsRequired.Value); + protected override UIDef GetGoalUIDef() => new ArchipelagoUIDef() + { + name = new BoxedString("Happiness"), + shopDesc = new BoxedString("Meemawmaw! Meemawmaw!"), + sprite = new ArchipelagoSprite { key = "GrubHappyv2" } + }; + } +} diff --git a/Mod/Archipelago.HollowKnight/HintTracker.cs b/Mod/Archipelago.HollowKnight/HintTracker.cs new file mode 100644 index 0000000..175672b --- /dev/null +++ b/Mod/Archipelago.HollowKnight/HintTracker.cs @@ -0,0 +1,251 @@ +using Archipelago.HollowKnight.IC; +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Exceptions; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using ItemChanger.Modules; +using ItemChanger.Placements; +using ItemChanger.Tags; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine.SceneManagement; + +namespace Archipelago.HollowKnight; + +public class HintTracker : Module +{ + + public static event Action OnArchipelagoHintUpdate; + + /// + /// List of MultiClient.Net Hint's + /// + public static List Hints; + /// + /// List of placement hints to send on scene change or when closing out the session + /// + private List PendingPlacementHints; + + private ArchipelagoSession session; + + private void UpdateHints(Hint[] arrayHints) + { + + Hints = arrayHints.ToList(); + foreach (Hint hint in Hints) + { + if (hint.FindingPlayer != ArchipelagoMod.Instance.session.ConnectionInfo.Slot) + { + continue; + } + + if (!ArchipelagoPlacementTag.PlacementsByLocationId.ContainsKey(hint.LocationId)) + { + continue; + } + + ArchipelagoMod.Instance.LogDebug($"Hint data received for item {hint.ItemId} at location {hint.LocationId}"); + + AbstractPlacement placement = ArchipelagoPlacementTag.PlacementsByLocationId[hint.LocationId]; + + if (placement == null) + { + continue; + } + + // set the hinted tag for the single item in the placement that was hinted for. + foreach (ArchipelagoItemTag tag in placement.Items.Select(item => item.GetTag()) + .Where(tag => tag.Location == hint.LocationId)) + { + ArchipelagoMod.Instance.LogDebug("Setting hinted true for item"); + tag.Hinted = true; + } + + // if all items inside a placement have been hinted for then mark the entire placement as hinted. + if (placement.Items.TrueForAll(item => item.GetTag().Hinted)) + { + ArchipelagoMod.Instance.LogDebug("Setting hinted true for placement"); + placement.GetTag().Hinted = true; + } + + if (placement is ShopPlacement shop) + { + List<(string, AbstractItem)> previewText = new(); + foreach (AbstractItem item in shop.Items) + { + if (item.GetTag().Hinted) + { + previewText.Add((item.GetPreviewWithCost(), item)); + } + else + { + previewText.Add((Language.Language.Get("???", "IC"), item)); + } + + } + MultiPreviewRecordTag previewRecordTag = shop.GetOrAddTag(); + previewRecordTag.previewTexts ??= new string[shop.Items.Count]; + + foreach ((string, AbstractItem item) p in previewText) + { + string str = p.Item1; + int index = shop.Items.IndexOf(p.item); + if (index >= 0) + { + previewRecordTag.previewTexts[index] = str; + } + } + } + else + { + List previewText = new(); + foreach (AbstractItem item in placement.Items) + { + if (item.WasEverObtained()) + { + continue; + } + + previewText.Add(item.GetTag().Hinted + ? item.GetPreviewWithCost() + : Language.Language.Get("???", "IC")); + } + + placement.GetOrAddTag().previewText = string.Join(Language.Language.Get("COMMA_SPACE", "IC"), previewText); + } + + } + + try + { + OnArchipelagoHintUpdate?.Invoke(); + } + catch (Exception ex) + { + ArchipelagoMod.Instance.LogError($"Error invoking OnArchipelagoHintUpdate:\n {ex}"); + } + } + + public override void Initialize() + { + PendingPlacementHints = []; + + session = ArchipelagoMod.Instance.session; + + // do most setup in OnEnterGame so save data can completely load, we need to + // populate all the AP placements to sync with server + Events.OnEnterGame += OnEnterGame; + } + + private void OnEnterGame() + { + session.DataStorage.TrackHints(UpdateHints); + + AbstractItem.AfterGiveGlobal += UpdateHintFoundStatus; + Events.OnSceneChange += SendHintsOnSceneChange; + } + + public override async void Unload() + { + Events.OnEnterGame -= OnEnterGame; + AbstractItem.AfterGiveGlobal -= UpdateHintFoundStatus; + Events.OnSceneChange -= SendHintsOnSceneChange; + await SendPlacementHintsAsync(); + } + + public void HintPlacement(AbstractPlacement pmt) + { + // todo - accommodate different hinting times (immediate/never) + PendingPlacementHints.Add(pmt); + } + + private void UpdateHintFoundStatus(ReadOnlyGiveEventArgs args) + { + if (Hints != null && args.Orig.GetTag(out ArchipelagoItemTag tag)) + { + long location = tag.Location; + foreach (Hint hint in Hints) + { + if (hint.LocationId == location) + { + hint.Found = true; + try + { + OnArchipelagoHintUpdate?.Invoke(); + } + catch (Exception ex) + { + ArchipelagoMod.Instance.LogError($"Error invoking OnArchipelagoHintUpdate:\n {ex}"); + } + break; + } + } + } + } + + private async void SendHintsOnSceneChange(Scene scene) + { + await SendPlacementHintsAsync(); + } + + private async Task SendPlacementHintsAsync() + { + if (!PendingPlacementHints.Any()) + { + return; + } + + HashSet hintedTags = new(); + HashSet hintedLocationIDs = new(); + ArchipelagoItemTag tag; + + foreach (AbstractPlacement pmt in PendingPlacementHints) + { + foreach (AbstractItem item in pmt.Items) + { + if (item.GetTag(out tag) && !tag.Hinted) + { + if ((tag.Flags.HasFlag(ItemFlags.Advancement) || tag.Flags.HasFlag(ItemFlags.NeverExclude)) + && !item.WasEverObtained() + && !item.HasTag()) + { + hintedTags.Add(tag); + hintedLocationIDs.Add(tag.Location); + } + else + { + tag.Hinted = true; + } + } + } + } + + PendingPlacementHints.Clear(); + if (!hintedLocationIDs.Any()) + { + return; + } + + ArchipelagoMod.Instance.LogDebug($"Hinting {hintedLocationIDs.Count()} locations."); + try + { + await session.Locations.ScoutLocationsAsync(true, hintedLocationIDs.ToArray()) + .ContinueWith(x => + { + bool result = !x.IsFaulted; + foreach (ArchipelagoItemTag tag in hintedTags) + { + tag.Hinted = result; + } + }).TimeoutAfter(1000); + } + catch (Exception ex) when (ex is ArchipelagoSocketClosedException or TimeoutException) + { + ItemChangerMod.Modules.Get().ReportDisconnect(); + } + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/IC/ArchipelagoItem.cs b/Mod/Archipelago.HollowKnight/IC/ArchipelagoItem.cs new file mode 100644 index 0000000..82f87f9 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/ArchipelagoItem.cs @@ -0,0 +1,89 @@ +using Archipelago.MultiClient.Net.Enums; +using ItemChanger; +using ItemChanger.Tags; + +namespace Archipelago.HollowKnight.IC +{ + public class ArchipelagoDummyItem : AbstractItem + { + public string PreferredContainerType { get; set; } = Container.Unknown; + + public override string GetPreferredContainer() => PreferredContainerType; + + public ArchipelagoDummyItem() + { } + public ArchipelagoDummyItem(AbstractItem source) + { + this.name = source.name; + this.UIDef = source.UIDef.Clone(); + PreferredContainerType = source.GetPreferredContainer(); + } + + public override bool GiveEarly(string containerType) + { + // any container (e.g. a grub or soul totem) that would not normally fling a shiny + // in vanilla should not go out of its way to do so for this + return containerType switch + { + Container.Unknown + or Container.Shiny + or Container.Chest + => false, + _ => true + }; + } + + public override void GiveImmediate(GiveInfo info) + { + // Intentional no-op + } + } + + public class ArchipelagoItem : AbstractItem + { + public ArchipelagoItem(string name, string recipientName = null, ItemFlags itemFlags = 0) + { + string desc; + ISprite pinSprite; + if (itemFlags.HasFlag(ItemFlags.Advancement)) + { + desc = "This otherworldly artifact looks very important. Somebody probably really needs it."; + pinSprite = new ArchipelagoSprite { key = "Pins.pinAPProgression" }; + } + else if (itemFlags.HasFlag(ItemFlags.NeverExclude)) + { + desc = "This otherworldly artifact looks like it might be useful to someone."; + pinSprite = new ArchipelagoSprite { key = "Pins.pinAPUseful" }; + } + else + { + desc = "I'm not entirely sure what this is. It appears to be a strange artifact from another world."; + pinSprite = new ArchipelagoSprite { key = "Pins.pinAP" }; + } + if (itemFlags.HasFlag(ItemFlags.Trap)) + { + desc += " Seems kinda suspicious though. It might be full of bees."; + } + this.name = name; + UIDef = new ArchipelagoUIDef() + { + name = new BoxedString($"{recipientName}'s {name}"), + shopDesc = new BoxedString(desc), + sprite = new ArchipelagoSprite { key = "IconColorSmall" } + }; + InteropTag mapInteropTag = new() + { + Message = "RandoSupplementalMetadata", + Properties = new() { + ["PinSprite"] = pinSprite + } + }; + this.AddTag(mapInteropTag); + } + + public override void GiveImmediate(GiveInfo info) + { + // intentional no-op + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/ArchipelagoSprite.cs b/Mod/Archipelago.HollowKnight/IC/ArchipelagoSprite.cs new file mode 100644 index 0000000..84384c5 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/ArchipelagoSprite.cs @@ -0,0 +1,10 @@ +using ItemChanger; +using ItemChanger.Internal; + +namespace Archipelago.HollowKnight.IC +{ + public class ArchipelagoSprite : EmbeddedSprite + { + public override SpriteManager SpriteManager => ArchipelagoMod.Instance.spriteManager; + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/ArchipelagoTags.cs b/Mod/Archipelago.HollowKnight/IC/ArchipelagoTags.cs new file mode 100644 index 0000000..2a73a06 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/ArchipelagoTags.cs @@ -0,0 +1,151 @@ +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using ItemChanger.Tags; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight.IC +{ + /// + /// Tag attached to items that are involved with Archipelago. + /// + /// + /// ArchipelagoItemTags are attached to AP-randomized items to track what their location ID and player ("slot") are. Additionally, they manage events + /// for when items are picked up, ensuring that HK items for other players get replaced out and that all location checks actually get sent. + /// + public class ArchipelagoItemTag : Tag, IInteropTag + { + /// + /// AP location ID for this item. + /// + public long Location { get; set; } + /// + /// AP player ID ("slot") for this item's recipient. + /// + public int Player { get; set; } + /// + /// Network item flags, exposed for benefit of the mapmod + /// + public ItemFlags Flags { get; set; } + + /// + /// Set if this area is hinted. + /// + public bool Hinted { get; set; } = false; + + public bool IsItemForMe { get; set; } + + private ItemNetworkingModule networkModule; + + public void ReadItemInfo(ScoutedItemInfo itemInfo) + { + Location = itemInfo.LocationId; + Player = itemInfo.Player; + Flags = itemInfo.Flags; + + IsItemForMe = itemInfo.IsReceiverRelatedToActivePlayer; + } + + public override async void Load(object parent) + { + base.Load(parent); + networkModule = ItemChangerMod.Modules.Get(); + AbstractItem item = (AbstractItem)parent; + item.AfterGive += AfterGive; + + if (item.WasEverObtained()) + { + await networkModule.SendLocationsAsync(Location); + } + } + + private async void AfterGive(ReadOnlyGiveEventArgs obj) + { + await networkModule.SendLocationsAsync(Location); + } + + public override void Unload(object parent) + { + ((AbstractItem)parent).AfterGive -= AfterGive; + base.Unload(parent); + } + + string IInteropTag.Message => "RandoSupplementalMetadata"; + + bool IInteropTag.TryGetProperty(string propertyName, out T value) where T : default + { + if (propertyName == "ForceEnablePreview" && Hinted is T t) + { + value = t; + return true; + } + + value = default; + return false; + } + } + + /// + /// Tag attached to placements that are involved with Archipelago. + /// + /// + /// ArchipelagoPlacementTags are attached to placements containing AP-randomized. + /// They track whether the placement has been successfully hinted in AP (e.g. when previewed), and what its associated Location ID is. This latter tracking facilitates + /// a dictionary of location IDs to placements so when items are received from our own slot (e.g. same-slot coop or recovering a lost save) we can update the game + /// world accordingly. + /// + public class ArchipelagoPlacementTag : Tag + { + public static Dictionary PlacementsByLocationId = new(); + + /// + /// True if this location has been hinted AP, or is in the process of being hinted. + /// + public bool Hinted { get; set; } + + private HintTracker hintTracker; + + public override void Load(object parent) + { + base.Load(parent); + AbstractPlacement pmt = (AbstractPlacement)parent; + //Archipelago.Instance.LogDebug($"In ArchipelagoPlacementTag:Load for {parent}, locations ({String.Join(", ", PlacementUtils.GetLocationIDs(pmt))})"); + hintTracker = ItemChangerMod.Modules.Get(); + + foreach (long locationId in PlacementUtils.GetLocationIDs(pmt)) + { + PlacementsByLocationId[locationId] = pmt; + } + + pmt.OnVisitStateChanged += OnVisitStateChanged; + // If we've been previewed but never told AP that, tell it now + if (!Hinted && pmt.Visited.HasFlag(VisitState.Previewed)) + { + hintTracker.HintPlacement(pmt); + } + } + + public override void Unload(object parent) + { + //Archipelago.Instance.LogDebug($"In ArchipelagoPlacementTag:UNLOAD for {parent}, locations ({String.Join(", ", PlacementUtils.GetLocationIDs((AbstractPlacement)parent))})"); + ((AbstractPlacement)parent).OnVisitStateChanged -= OnVisitStateChanged; + + foreach (long locationId in PlacementUtils.GetLocationIDs((AbstractPlacement)parent)) + { + PlacementsByLocationId.Remove(locationId); + } + + base.Unload(parent); + } + + private void OnVisitStateChanged(VisitStateChangedEventArgs obj) + { + if (!Hinted && obj.NewFlags.HasFlag(VisitState.Previewed)) + { + // We are now previewed, but we weren't before. + hintTracker.HintPlacement(obj.Placement); + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/ArchipelagoUIDef.cs b/Mod/Archipelago.HollowKnight/IC/ArchipelagoUIDef.cs new file mode 100644 index 0000000..df3b7de --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/ArchipelagoUIDef.cs @@ -0,0 +1,55 @@ +using ItemChanger; +using ItemChanger.UIDefs; + +namespace Archipelago.HollowKnight.IC +{ + internal class ArchipelagoUIDef : MsgUIDef + { + public static string GetSentItemName(AbstractItem item) + { + return item.name switch + { + ItemNames.Grub => "A grub!", + ItemNames.Grimmkin_Flame => "Grimmkin Flame", + ItemNames.Rancid_Egg => "Rancid Egg", + _ => item.UIDef.GetPostviewName(), + }; + } + + public static ArchipelagoUIDef CreateForReceivedItem(AbstractItem item, string sender) + { + return CreateForReceivedItem(item.GetResolvedUIDef(), sender); + } + + public static ArchipelagoUIDef CreateForReceivedItem(UIDef source, string sender) + { + ArchipelagoUIDef result = new(source); + result.name = new BoxedString($"{source.GetPostviewName()} from {sender}"); + return result; + } + public static ArchipelagoUIDef CreateForSentItem(AbstractItem item, string recipient) + { + ArchipelagoUIDef result = new(item.UIDef); + result.name = new BoxedString($"{recipient}'s {GetSentItemName(item)}"); + return result; + } + + internal ArchipelagoUIDef() : base() + { + } + + internal ArchipelagoUIDef(UIDef source) : base() + { + if (source is MsgUIDef msgDef) + { + shopDesc = msgDef.shopDesc.Clone(); + sprite = msgDef.sprite.Clone(); + } + else + { + shopDesc = new BoxedString(source.GetShopDesc()); + sprite = new EmptySprite(); + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/CostFactory.cs b/Mod/Archipelago.HollowKnight/IC/CostFactory.cs new file mode 100644 index 0000000..354c8aa --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/CostFactory.cs @@ -0,0 +1,112 @@ +using ItemChanger; +using ItemChanger.Placements; +using ItemChanger.Tags; +using System.Collections.Generic; +using System.Linq; + +namespace Archipelago.HollowKnight.IC +{ + internal class CostFactory + { + private Dictionary> locationCosts; + + /// + /// Initializes a cost factory with costs provided from slot data + /// + /// A lookup from placement name -> cost type -> amount + public CostFactory(Dictionary> locationCosts) + { + this.locationCosts = locationCosts; + } + + public void ApplyCost(AbstractPlacement pmt, AbstractItem item, string serverLocationName) + { + if (locationCosts.TryGetValue(serverLocationName, out Dictionary costs)) + { + List icCosts = new(); + foreach (KeyValuePair entry in costs) + { + Cost proposedCost = null; + switch (entry.Key) + { + case "GEO": + proposedCost = Cost.NewGeoCost(entry.Value); + break; + case "ESSENCE": + proposedCost = Cost.NewEssenceCost(entry.Value); + break; + case "GRUBS": + proposedCost = Cost.NewGrubCost(entry.Value); + break; + case "CHARMS": + proposedCost = new PDIntCost( + entry.Value, nameof(PlayerData.charmsOwned), + $"Acquire {entry.Value} {((entry.Value == 1) ? "charm" : "charms")}" + ); + break; + case "RANCIDEGGS": + proposedCost = new ItemChanger.Modules.CumulativeRancidEggCost(entry.Value); + break; + default: + ArchipelagoMod.Instance.LogWarn( + $"Encountered UNKNOWN currency type {entry.Key} at location {serverLocationName}!"); + break; + } + + if (proposedCost != null) + { + // suppress inherent costs - if the server told us to pay X, but the implementation of + // the location will force us to pay Y >= X, we skip adding the cost to prevent doubling up. + IEnumerable inherentCosts = pmt.GetPlacementAndLocationTags() + .OfType() + .Where(t => t.Inherent) + .Select(t => t.Cost); + if (inherentCosts.Any(c => c.Includes(proposedCost))) + { + ArchipelagoMod.Instance.LogDebug($"Supressing cost {entry.Value} {entry.Key} for location {serverLocationName}"); + continue; + } + else + { + icCosts.Add(proposedCost); + } + } + } + + if (icCosts.Count == 0) + { + ArchipelagoMod.Instance.LogWarn( + $"Found zero cost types when handling placement at location {serverLocationName}!"); + return; + } + + Cost finalCosts; + if (icCosts.Count == 1) + { + finalCosts = icCosts[0]; + } + else + { + finalCosts = new MultiCost(icCosts); + } + + if (pmt is ISingleCostPlacement scp) + { + if (scp.Cost == null) + { + scp.Cost = finalCosts; + } + else + { + scp.Cost = new MultiCost(scp.Cost, finalCosts); + } + } + else + { + CostTag costTag = item.AddTag(); + costTag.Cost = finalCosts; + } + } + } + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/IC/ItemFactory.cs b/Mod/Archipelago.HollowKnight/IC/ItemFactory.cs new file mode 100644 index 0000000..aa97698 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/ItemFactory.cs @@ -0,0 +1,64 @@ +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using ItemChanger.Items; +using ItemChanger.Tags; +using System; + +namespace Archipelago.HollowKnight.IC +{ + internal class ItemFactory + { + public AbstractItem CreateMyItem(string itemName, ScoutedItemInfo itemInfo) + { + AbstractItem item = Finder.GetItem(itemName); + if (item == null) + { + ArchipelagoMod.Instance.LogError($"Could not find local item with name {itemName}"); + throw new NullReferenceException($"Could not find local item with name {itemName}"); + } + + AddArchipelagoTag(item, itemInfo); + return item; + } + + public AbstractItem CreateRemoteItem(AbstractPlacement targetPlacement, string slotName, string itemName, ScoutedItemInfo itemInfo) + { + ArchipelagoSession session = ArchipelagoMod.Instance.session; + string game = itemInfo.ItemGame; + + AbstractItem orig = Finder.GetItem(itemName); + AbstractItem item; + if (game == "Hollow Knight" && orig != null) + { + // this is a remote HK item - make it a no-op, but cosmetically correct + item = new ArchipelagoDummyItem(orig); + item.UIDef = ArchipelagoUIDef.CreateForSentItem(orig, slotName); + + // give the placement the correct cosmetic soul totem or geo rock type if appropriate + if (orig is SoulTotemItem totem) + { + targetPlacement.GetOrAddTag().Type = totem.soulTotemSubtype; + } + else if (orig is GeoRockItem rock) + { + targetPlacement.GetOrAddTag().Type = rock.geoRockSubtype; + } + } + else + { + // Items from other games, or an unknown HK item + item = new ArchipelagoItem(itemName, slotName, itemInfo.Flags); + } + + AddArchipelagoTag(item, itemInfo); + return item; + } + + private void AddArchipelagoTag(AbstractItem item, ScoutedItemInfo itemInfo) + { + ArchipelagoItemTag itemTag = item.AddTag(); + itemTag.ReadItemInfo(itemInfo); + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Items/GoalItem.cs b/Mod/Archipelago.HollowKnight/IC/Items/GoalItem.cs new file mode 100644 index 0000000..483ace1 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Items/GoalItem.cs @@ -0,0 +1,20 @@ +using Archipelago.HollowKnight.IC.Modules; +using ItemChanger; + +namespace Archipelago.HollowKnight.IC.Items +{ + public class GoalItem : AbstractItem + { + private GoalModule goalModule; + + protected override void OnLoad() + { + goalModule = ItemChangerMod.Modules.Get(); + } + + public override async void GiveImmediate(GiveInfo info) + { + await goalModule.DeclareVictoryAsync(); + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/ArchipelagoRemoteItemCounterModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/ArchipelagoRemoteItemCounterModule.cs new file mode 100644 index 0000000..f4ea839 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/ArchipelagoRemoteItemCounterModule.cs @@ -0,0 +1,91 @@ +using Archipelago.MultiClient.Net.Models; +using ItemChanger.Modules; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight.IC.Modules; + +public class ArchipelagoRemoteItemCounterModule : Module +{ + /// + /// Full history of remote items received and saved by the client. Keys are player, location, item to finally reach a count. + /// + private readonly Dictionary>> savedItemCounts = new(); + + /// + /// History of items seen when receiving from server. Keys are player, location, item to finally reach a count. + /// + + private readonly Dictionary>> serverSeenItemCounts = new(); + + public override void Initialize() + { + } + + public override void Unload() + { + } + + /// + /// Determines whether the specified item should be received from the server based on the current counts. Should be called before receiving the item. + /// + /// The item to evaluate for receiving from the server. + /// + /// if receiving the item would result in the server count exceeding the local saved count; + /// otherwise, . + /// + public bool ShouldReceiveServerItem(ItemInfo item) + { + int currentSavedCount = EnsureCountExists(item.Player, item.LocationId, item.ItemId, savedItemCounts); + int currentServerCount = EnsureCountExists(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); + + // if obtaining this item will have sent more items from the server than we have locally, we should receive the item. otherwise we should skip it. + return currentServerCount + 1 > currentSavedCount; + } + + /// + /// Increments the server-side count for the specified item. + /// + /// The object representing the item whose count is to be incremented. This includes details + /// such as the player, location, and item identifier. + public void IncrementServerCountForItem(ItemInfo item) + { + EnsureCountExists(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); + IncrementCurrentCountForItem(item.Player, item.LocationId, item.ItemId, serverSeenItemCounts); + } + + /// + /// Increments the saved count for a specific item at a given location for a specified player. + /// + /// The identifier of the player for whom the item's saved count is being incremented. + /// The identifier of the location where the item is stored. + /// The identifier of the item whose saved count is being incremented. + public void IncrementSavedCountForItem(int player, long locationId, long itemId) + { + EnsureCountExists(player, locationId, itemId, savedItemCounts); + IncrementCurrentCountForItem(player, locationId, itemId, savedItemCounts); + } + + private static void IncrementCurrentCountForItem(int player, long locationId, long itemId, Dictionary>> itemCounts, int incrementBy = 1) + { + itemCounts[player][locationId][itemId] += incrementBy; + } + + private static int EnsureCountExists(int player, long locationId, long itemId, Dictionary>> itemCounts) + { + if (!itemCounts.TryGetValue(player, out Dictionary> a)) + { + itemCounts[player] = a = new(); + } + + if (!a.TryGetValue(locationId, out Dictionary b)) + { + a[locationId] = b = new(); + } + + if (!b.TryGetValue(itemId, out int count)) + { + b[itemId] = count = 0; + } + return count; + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/BenchSyncModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/BenchSyncModule.cs new file mode 100644 index 0000000..e3f7229 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/BenchSyncModule.cs @@ -0,0 +1,123 @@ +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Models; +using Benchwarp; +using ItemChanger; +using ItemChanger.Modules; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Archipelago.HollowKnight.IC.Modules +{ + public partial class BenchSyncModule : Module + { + private const string DATASTORAGE_KEY_UNLOCKED_BENCHES = "unlocked_benches"; + private const string BENCH_KEY_SEPARATOR = ":::"; + static readonly Dictionary lockedBenches = new() + { + [SceneNames.Hive_01] = "Hive Bench", + [SceneNames.Ruins1_31] = "Toll Machine Bench", + [SceneNames.Abyss_18] = "Toll Machine Bench", + [SceneNames.Fungus3_50] = "Toll Machine Bench" + }; + + private ArchipelagoSession session; + + private Dictionary benchLookup; + + [DataStorageProperty(nameof(session), Scope.Slot, DATASTORAGE_KEY_UNLOCKED_BENCHES)] + private readonly DataStorageElement _unlockedBenches; + + public override async void Initialize() + { + session = ArchipelagoMod.Instance.session; + benchLookup = Bench.Benches.ToDictionary(x => x.ToBenchKey(), x => x); + + Benchwarp.Events.OnBenchUnlock += OnUnlockLocalBench; + UnlockedBenches.Initialize(JObject.FromObject(new Dictionary())); + + UnlockedBenches.OnValueChanged += OnUnlockRemoteBench; + Dictionary benchData = BuildBenchData(Bench.Benches.Where(x => x.HasVisited()).Select(x => x.ToBenchKey())); + UnlockedBenches += Operation.Update(benchData); + + try + { + Dictionary benches = await UnlockedBenches.GetAsync>(); + UnlockBenches(benches); + } + catch (Exception ex) + { + ArchipelagoMod.Instance.LogError($"Unexpected issue unlocking benches from server data: {ex}"); + } + } + + public override void Unload() + { + Benchwarp.Events.OnBenchUnlock -= OnUnlockLocalBench; + UnlockedBenches.OnValueChanged -= OnUnlockRemoteBench; + } + + private void OnUnlockLocalBench(BenchKey obj) + { + UnlockedBenches += Operation.Update(BuildBenchData([obj])); + } + + private void OnUnlockRemoteBench(JToken oldData, JToken newData, Dictionary args) + { + Dictionary benches = newData.ToObject>(); + UnlockBenches(benches); + } + + private Dictionary BuildBenchData(IEnumerable keys) + { + Dictionary obtainedBenches = new(); + foreach (BenchKey key in keys) + { + obtainedBenches[$"{key.SceneName}{BENCH_KEY_SEPARATOR}{key.RespawnMarkerName}"] = true; + } + return obtainedBenches; + } + + private void UnlockBenches(Dictionary benches) + { + if (benches == null) + { + return; + } + + foreach (KeyValuePair kv in benches) + { + string[] keyParts = kv.Key.Split([BENCH_KEY_SEPARATOR], StringSplitOptions.None); + BenchKey key = new(keyParts[0], keyParts[1]); + if (benchLookup.TryGetValue(key, out Bench bench)) + { + bench.SetVisited(kv.Value); + if (lockedBenches.TryGetValue(bench.sceneName, out string persistentBoolName)) + { + GameManager.instance.sceneData.SaveMyState(new PersistentBoolData() + { + activated = true, + sceneName = bench.sceneName, + semiPersistent = false, + id = persistentBoolName + }); + } + + switch (bench.sceneName) + { + case SceneNames.Room_Tram: + PlayerData.instance.SetBool(nameof(PlayerData.openedTramLower), true); + PlayerData.instance.SetBool(nameof(PlayerData.tramOpenedDeepnest), true); + break; + case SceneNames.Room_Tram_RG: + PlayerData.instance.SetBool(nameof(PlayerData.openedTramRestingGrounds), true); + PlayerData.instance.SetBool(nameof(PlayerData.tramOpenedCrossroads), true); + break; + } + } + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/DeathLinkModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/DeathLinkModule.cs new file mode 100644 index 0000000..a0ecec1 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/DeathLinkModule.cs @@ -0,0 +1,266 @@ +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; +using HutongGames.PlayMaker; +using ItemChanger; +using ItemChanger.Extensions; +using ItemChanger.FsmStateActions; +using Modding; +using System; +using System.Reflection; + +namespace Archipelago.HollowKnight.IC.Modules +{ + public class DeathLinkModule : ItemChanger.Modules.Module + { + public const string PREVENT_SHADE_VARIABLE_NAME = "Deathlink Prevent Shade"; + public const string IS_DEATHLINK_VARIABLE_NAME = "Is Deathlink Death"; + private static readonly MethodInfo HeroController_CanTakeDamage = typeof(HeroController) + .GetMethod("CanTakeDamage", BindingFlags.NonPublic | BindingFlags.Instance); + + private DeathLinkService service = null; + private DeathLinkShadeHandling shadeHandling => ArchipelagoMod.Instance.SlotData.Options.DeathLinkShade; + private bool breakFragileCharms => ArchipelagoMod.Instance.SlotData.Options.DeathLinkBreaksFragileCharms; + private DeathLinkStatus status; + private int lastDamageType; + private DateTime lastDamageTime; + private bool hasEditedFsm = false; + + private ArchipelagoSession session; + + private void Reset() + { + lastDamageType = 0; + lastDamageTime = DateTime.MinValue; + status = DeathLinkStatus.None; + } + + public override void Initialize() + { + session = ArchipelagoMod.Instance.session; + Reset(); + + ArchipelagoMod.Instance.LogDebug($"Enabling DeathLink support, type: {shadeHandling}"); + service = ArchipelagoMod.Instance.session.CreateDeathLinkService(); + service.EnableDeathLink(); + service.OnDeathLinkReceived += OnDeathLinkReceived; + ModHooks.HeroUpdateHook += OnHeroUpdate; + On.HeroController.TakeDamage += OnTakeDamage; + Events.AddFsmEdit(new FsmID("Hero Death Anim"), FsmEdit); + } + + public override void Unload() + { + Reset(); + + if (service != null) + { + service.OnDeathLinkReceived -= OnDeathLinkReceived; + service = null; + } + + ModHooks.HeroUpdateHook -= OnHeroUpdate; + On.HeroController.TakeDamage -= OnTakeDamage; + Events.RemoveFsmEdit(new FsmID("Hero Death Anim"), FsmEdit); + hasEditedFsm = false; + } + + private void FsmEdit(PlayMakerFSM fsm) + { + if (hasEditedFsm) + { + return; + } + hasEditedFsm = true; + + ArchipelagoMod ap = ArchipelagoMod.Instance; + + FsmBool preventShade = fsm.AddFsmBool(PREVENT_SHADE_VARIABLE_NAME, false); + FsmBool isDeathlink = fsm.AddFsmBool(IS_DEATHLINK_VARIABLE_NAME, false); + // Death animation starts here - normally whether you get a shade or not is determined purely by whether + // you're in a dream or not. + FsmState mapZone = fsm.GetState("Map Zone"); + + // If it's not someone else's death, then send out a deathlink. Also compute whether a shade should be spawned since + // multiple other states need to know. + mapZone.AddFirstAction(new Lambda(() => + { + ap.LogDebug($"FsmEdit Pre: Status={status} Shade handling={shadeHandling} Break fragiles={breakFragileCharms}."); + + bool isDeathlinkDeath = status == DeathLinkStatus.Dying; + + if (!isDeathlinkDeath) + { + ap.LogDebug($"FsmEdit Pre: Not a deathlink death, so sending out our own deathlink."); + // If we're not caused by DeathLink... then we send a DeathLink + SendDeathLink(); + return; + } + else + { + ap.LogDebug("Beginning deathlink death handling"); + } + + isDeathlink.Value = isDeathlinkDeath; + preventShade.Value = !( + shadeHandling == DeathLinkShadeHandling.Vanilla + || shadeHandling == DeathLinkShadeHandling.Shade && PlayerData.instance.shadeScene == "None" + ); + + if (!preventShade.Value) + { + ap.LogDebug($"FsmEdit Pre: Shade will be created."); + } + })); + + // route around penalties based on settings + FsmState breakMsg = fsm.GetState("Break Msg"); + FsmState removeOvercharm = fsm.GetState("Remove Overcharm"); + + FsmState createShadeCheck = fsm.AddState("Create Shade?"); + createShadeCheck.AddLastAction(new DelegateBoolTest(() => isDeathlink.Value, null, "FINISHED")); + createShadeCheck.AddLastAction(new DelegateBoolTest(() => preventShade.Value, "SKIP SHADE", null)); + createShadeCheck.AddTransition("SKIP SHADE", "Save"); + createShadeCheck.AddTransition("FINISHED", "Remove Geo"); + + FsmState breakFragilesCheck = fsm.AddState("Break Fragiles?"); + breakFragilesCheck.AddLastAction(new DelegateBoolTest(() => isDeathlink.Value, null, "FINISHED")); + breakFragilesCheck.AddLastAction(new DelegateBoolTest(() => !breakFragileCharms, "SKIP BREAK", null)); + breakFragilesCheck.AddTransition("SKIP BREAK", createShadeCheck); + breakFragilesCheck.AddTransition("FINISHED", "Break Glass HP"); + + mapZone.RemoveTransitionsOn("FINISHED"); + mapZone.AddTransition("FINISHED", breakFragilesCheck); + + breakMsg.RemoveTransitionsOn("FINISHED"); + breakMsg.AddTransition("FINISHED", createShadeCheck); + removeOvercharm.RemoveTransitionsOn("FINISHED"); + removeOvercharm.AddTransition("FINISHED", createShadeCheck); + + // adjust soul limiter to be created only if a shade was created + FsmState deathEnding = fsm.GetState("End"); + fsm.GetState("Limit Soul?").Actions = []; + // Replace the first two action (which normally start the soul limiter and notify about it) + deathEnding.Actions[0] = new Lambda(() => + { + // Mimic the Limit Soul? state and the action being replaced - we only want to soul limit if the + // player spawned a shade + if (!preventShade.Value) + { + fsm.Fsm.BroadcastEvent("SOUL LIMITER UP"); + GameManager.instance.StartSoulLimiter(); + } + }); + + // the following 3 states are the ending states of each branch of the FSM. we'll link them into a custom state that resets + // deathlink for us + FsmState dreamReturn = fsm.GetState("Dream Return"); + FsmState waitForHeroController = fsm.GetState("Wait for HeroController"); + FsmState steelSoulCheck = fsm.GetState("Shade?"); + FsmState[] endingStates = [dreamReturn, waitForHeroController, steelSoulCheck]; + // add deathlink cleanup state + FsmState cleanupDeathlink = fsm.AddState("Cleanup Deathlink"); + cleanupDeathlink.AddFirstAction(new Lambda(() => + { + ap.LogDebug("Resetting deathlink state"); + preventShade.Value = false; + isDeathlink.Value = false; + status = DeathLinkStatus.None; + })); + foreach (FsmState state in endingStates) + { + state.AddTransition("FINISHED", cleanupDeathlink); + } + } + + public void MurderPlayer() + { + string scene = GameManager.instance.sceneName; + ArchipelagoMod.Instance.LogDebug($"Deathlink-initiated kill starting. Current scene: {scene}"); + status = DeathLinkStatus.Dying; + HeroController.instance.TakeDamage(HeroController.instance.gameObject, GlobalEnums.CollisionSide.other, + 9999, 0); + } + + private void OnHeroUpdate() + { + HeroController hc = HeroController.instance; + if (status == DeathLinkStatus.Pending + && hc.acceptingInput + && hc.damageMode == GlobalEnums.DamageMode.FULL_DAMAGE + && PlayerData.instance.GetInt(nameof(PlayerData.health)) > 0 + && (bool)HeroController_CanTakeDamage.Invoke(hc, null)) + { + MurderPlayer(); + } + } + + private void OnTakeDamage(On.HeroController.orig_TakeDamage orig, HeroController self, + UnityEngine.GameObject go, GlobalEnums.CollisionSide damageSide, int damageAmount, int hazardType) + { + lastDamageTime = DateTime.UtcNow; + lastDamageType = hazardType; + orig(self, go, damageSide, damageAmount, hazardType); + } + + public void SendDeathLink() + { + ArchipelagoMod ap = ArchipelagoMod.Instance; + // Don't send death links if we're currently in the process of dying to another deathlink. + if (status == DeathLinkStatus.Dying) + { + ap.LogDebug("SendDeathLink(): Not sending a deathlink because we're in the process of dying to one"); + return; + } + + if (service == null) + { + ap.LogDebug("SendDeathLink(): Not sending a deathlink because not enabled."); + return; + } + + if ((DateTime.UtcNow - lastDamageTime).TotalSeconds > 5) + { + ap.LogWarn("Last damage was a long time ago, resetting damage type to zero."); + // Damage source was more than 5 seconds ago, so ignore damage type + lastDamageType = 0; + } + + string message = DeathLinkMessages.GetDeathMessage(lastDamageType, ArchipelagoMod.Instance.session.Players.ActivePlayer.Alias); + ap.LogDebug( + $"SendDeathLink(): Sending deathlink. \"{message}\""); + service.SendDeathLink(new DeathLink(ArchipelagoMod.Instance.session.Players.ActivePlayer.Alias, message)); + } + + private void OnDeathLinkReceived(DeathLink deathLink) + { + ArchipelagoMod ap = ArchipelagoMod.Instance; + ap.LogDebug($"OnDeathLinkReceived(): Receiving deathlink. Status={status}."); + + if (status == DeathLinkStatus.None) + { + status = DeathLinkStatus.Pending; + + string cause = deathLink.Cause; + if (cause == null || cause == "") + { + cause = $"{deathLink.Source} died."; + } + + MenuChanger.ThreadSupport.BeginInvoke(() => + { + new ItemChanger.UIDefs.MsgUIDef() + { + name = new BoxedString(cause), + sprite = new ArchipelagoSprite { key = "DeathLinkIcon" } + }.SendMessage(MessageType.Corner, null); + }); + + lastDamageType = 0; + } + else + { + ap.LogDebug("Skipping this deathlink as one is currently in progress"); + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/DupeHandlingModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/DupeHandlingModule.cs new file mode 100644 index 0000000..9a24004 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/DupeHandlingModule.cs @@ -0,0 +1,27 @@ +using ItemChanger; +using ItemChanger.Items; +using ItemChanger.Modules; + +namespace Archipelago.HollowKnight.IC.Modules; + +public class DupeHandlingModule : Module +{ + public override void Initialize() + { + AbstractItem.ModifyRedundantItemGlobal += ModifyRedundantItem; + } + + public override void Unload() + { + AbstractItem.ModifyRedundantItemGlobal -= ModifyRedundantItem; + } + + private void ModifyRedundantItem(GiveEventArgs args) + { + args.Item = new SpawnLumafliesItem + { + name = $"Lumafly_Escape-{args.Orig.name}", + UIDef = DupeUIDef.Of(args.Orig.UIDef) + }; + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/GiftingModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/GiftingModule.cs new file mode 100644 index 0000000..5997648 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/GiftingModule.cs @@ -0,0 +1,159 @@ +using Archipelago.Gifting.Net.Service; +using Archipelago.Gifting.Net.Traits; +using Archipelago.Gifting.Net.Versioning.Gifts.Current; +using Archipelago.MultiClient.Net; +using ItemChanger; +using ItemChanger.Modules; +using ItemChanger.Tags; +using MenuChanger; +using System.Collections.Generic; +using System.Linq; + +namespace Archipelago.HollowKnight.IC.Modules; + +public class GiftingModule : Module +{ + private static readonly string[] AcceptedTraits = [GiftFlag.Mana, GiftFlag.Life, "Artifact"]; + + private ArchipelagoSession session => ArchipelagoMod.Instance.session; + private GiftingService giftingService; + + public override void Initialize() + { + if (ArchipelagoMod.Instance.GS.EnableGifting) + { + giftingService = new GiftingService(session); + On.GameManager.FinishedEnteringScene += BeginGifting; + } + } + + public override void Unload() + { + if (giftingService != null) + { + giftingService.CloseGiftBox(); + giftingService.OnNewGift -= ReceiveOrRefundGift; + giftingService = null; + } + } + + private async void BeginGifting(On.GameManager.orig_FinishedEnteringScene orig, GameManager self) + { + orig(self); + On.GameManager.FinishedEnteringScene -= BeginGifting; + giftingService.OnNewGift += ReceiveOrRefundGift; + Dictionary pendingGifts = await giftingService.CheckGiftBoxAsync(); + foreach (Gift gift in pendingGifts.Values) + { + ReceiveOrRefundGift(gift); + } + giftingService.OpenGiftBox(false, AcceptedTraits); + } + + private void ReceiveOrRefundGift(Gift gift) + { + giftingService.RemoveGiftFromGiftBox(gift.ID); + GiftTrait bestTrait = PickBestMatchingTrait(gift); + if (bestTrait != null) + { + string itemName; + if (bestTrait.Trait == GiftFlag.Mana) + { + // soul refill based on quality. Average is 90 (large totems), below is 54, above is 200, scaling linearly + if (bestTrait.Quality >= 2.2) + { + itemName = ItemNames.Soul_Totem_Path_of_Pain; + } + else if (bestTrait.Quality <= 0.6) + { + itemName = ItemNames.Soul_Totem_B; + } + else + { + itemName = ItemNames.Soul_Totem_A; + } + } + else if (bestTrait.Trait == GiftFlag.Life) + { + // blue hearts based on quality. Average is 2 blue masks, scaling linearly from that + // todo - do we want XL/XS lifeblood for more interesting variance? + if (bestTrait.Quality >= 1.5) + { + itemName = ItemNames.Lifeblood_Cocoon_Large; + } + else + { + itemName = ItemNames.Lifeblood_Cocoon_Small; + } + } + else if (bestTrait.Trait == "Artifact") + { + // relic based on quality (average case is Hallownest seal, scales roughly linearly from that) + if (bestTrait.Quality <= 0.4) + { + itemName = ItemNames.Wanderers_Journal; + } + else if (bestTrait.Quality >= 2.7) + { + itemName = ItemNames.Arcane_Egg; + } + else if (bestTrait.Quality >= 1.8) + { + itemName = ItemNames.Kings_Idol; + } + else + { + itemName = ItemNames.Hallownest_Seal; + } + } + else + { + // safety net in case we update acceptedtraits + ArchipelagoMod.Instance.LogWarn($"Got an unexpected trait {bestTrait} for gift {gift}"); + giftingService.RefundGift(gift); + return; + } + + string sender = session.Players.GetPlayerName(gift.SenderSlot); + DispatchItem(itemName, gift.Amount, sender); + } + else + { + giftingService.RefundGift(gift); + } + } + + private GiftTrait PickBestMatchingTrait(Gift gift) + { + GiftTrait best = null; + foreach (GiftTrait trait in gift.Traits) + { + if (AcceptedTraits.Contains(trait.Trait)) + { + if (best == null || trait.Quality > best.Quality) + { + best = trait; + } + } + } + return best; + } + + private void DispatchItem(string itemName, int amount, string sender) + { + ThreadSupport.BeginInvoke(() => + { + for (int i = 0; i < amount; i++) + { + AbstractItem item = Finder.GetItem(itemName); + InteropTag recentItemsTag = item.AddTag(); + recentItemsTag.Message = "RecentItems"; + recentItemsTag.Properties["DisplaySource"] = sender; + + item.Load(); + item.Give(null, ItemNetworkingModule.RemoteGiveInfo); + item.Unload(); + } + }); + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/GoalModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/GoalModule.cs new file mode 100644 index 0000000..d938fb9 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/GoalModule.cs @@ -0,0 +1,59 @@ +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Exceptions; +using Archipelago.MultiClient.Net.Packets; +using ItemChanger; +using ItemChanger.Modules; +using System; +using System.Threading.Tasks; + +namespace Archipelago.HollowKnight.IC.Modules +{ + public class GoalModule : Module + { + private ArchipelagoSession session => ArchipelagoMod.Instance.session; + + private Goal goal; + + public bool queuedGoal = false; + + public override void Initialize() + { + goal = Goal.GetGoal(ArchipelagoMod.Instance.SlotData.Options.Goal); + goal.Select(); + Events.OnEnterGame += OnEnterGame; + } + + public override void Unload() + { + Events.OnEnterGame -= OnEnterGame; + goal.Deselect(); + goal = null; + } + + public async Task DeclareVictoryAsync() + { + try + { + await session.Socket.SendPacketAsync(new StatusUpdatePacket() + { + Status = ArchipelagoClientState.ClientGoal + }).TimeoutAfter(1000); + queuedGoal = false; + } + catch (Exception ex) when (ex is TimeoutException or ArchipelagoSocketClosedException) + { + ItemChangerMod.Modules.Get().ReportDisconnect(); + queuedGoal = true; + } + } + + private async void OnEnterGame() + { + if (queuedGoal) + { + await DeclareVictoryAsync(); + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/ItemNetworkingModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/ItemNetworkingModule.cs new file mode 100644 index 0000000..6001449 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/ItemNetworkingModule.cs @@ -0,0 +1,372 @@ +using Archipelago.HollowKnight.IC.Tags; +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Exceptions; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using ItemChanger.Internal; +using ItemChanger.Modules; +using ItemChanger.Tags; +using ItemChanger.Items; +using MenuChanger; +using Modding; +using Newtonsoft.Json; +using System; +using System.Linq; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Threading.Tasks; + +namespace Archipelago.HollowKnight.IC.Modules +{ + /// + /// Handles the sending and receiving of items from the server + /// + public class ItemNetworkingModule : Module + { + /// + /// A preset GiveInfo structure that avoids creating geo and places messages in the corner. + /// + public static GiveInfo RemoteGiveInfo = new() + { + FlingType = FlingType.DirectDeposit, + Callback = null, + Container = Container.Unknown, + MessageType = MessageType.Corner + }; + + /// + /// A preset GiveInfo structure that avoids creating geo and outputs no messages, e.g. for Start Items. + /// + public static GiveInfo SilentGiveInfo = new() + { + FlingType = FlingType.DirectDeposit, + Callback = null, + Container = Container.Unknown, + MessageType = MessageType.None + }; + + private ArchipelagoSession session => ArchipelagoMod.Instance.session; + + private bool networkErrored; + private bool readyToSendReceiveChecks; + + [JsonProperty] + private List deferredLocationChecks = []; + [JsonProperty] + private bool hasEverRecievedStartingGeo = false; + + public override void Initialize() + { + networkErrored = false; + readyToSendReceiveChecks = false; + ModHooks.HeroUpdateHook += PollForItems; + On.GameManager.FinishedEnteringScene += DoInitialSyncAndStartSendReceive; + } + + public override void Unload() + { + // DoInitialSyncAndStartSendReceive unsubscribes itself + ModHooks.HeroUpdateHook -= PollForItems; + session.Locations.CheckedLocationsUpdated -= OnLocationChecksUpdated; + } + + public async Task SendLocationsAsync(params long[] locationIds) + { + if (!readyToSendReceiveChecks) + { + deferredLocationChecks.AddRange(locationIds); + return; + } + + if (networkErrored) + { + deferredLocationChecks.AddRange(locationIds); + ReportDisconnect(); + return; + } + + try + { + await Task.Run(() => session.Locations.CompleteLocationChecks(locationIds)).TimeoutAfter(1000); + } + catch (Exception ex) when (ex is TimeoutException or ArchipelagoSocketClosedException) + { + ArchipelagoMod.Instance.LogWarn("SendLocationsAsync disconnected"); + deferredLocationChecks.AddRange(locationIds); + ReportDisconnect(); + } + catch (Exception ex) + { + ArchipelagoMod.Instance.LogError("Unexpected error in SendLocationsAsync"); + ArchipelagoMod.Instance.LogError(ex); + deferredLocationChecks.AddRange(locationIds); + ReportDisconnect(); + } + } + + public void MarkLocationAsChecked(long locationId, bool silentGive) + { + // Called when marking a location as checked remotely (i.e. through ReceiveItem, etc.) + // This also grants items at said locations. + bool hadNewlyObtainedItems = false; + bool hadUnobtainedItems = false; + + ArchipelagoMod.Instance.LogDebug($"Marking location {locationId} as checked."); + if (!ArchipelagoPlacementTag.PlacementsByLocationId.TryGetValue(locationId, out AbstractPlacement pmt)) + { + ArchipelagoMod.Instance.LogDebug($"Could not find a placement for location {locationId}"); + return; + } + + foreach (AbstractItem item in pmt.Items) + { + if (!item.GetTag(out ArchipelagoItemTag tag)) + { + hadUnobtainedItems = true; + continue; + } + + if (item.WasEverObtained()) + { + continue; + } + + if (tag.Location != locationId) + { + hadUnobtainedItems = true; + continue; + } + + hadNewlyObtainedItems = true; + pmt.AddVisitFlag(VisitState.ObtainedAnyItem); + + GiveInfo giveInfo = silentGive ? SilentGiveInfo : RemoteGiveInfo; + item.Give(pmt, giveInfo.Clone()); + } + + if (hadNewlyObtainedItems && !hadUnobtainedItems) + { + pmt.AddVisitFlag(VisitState.Opened | VisitState.Dropped | VisitState.Accepted | + VisitState.ObtainedAnyItem); + } + } + + private async void DoInitialSyncAndStartSendReceive(On.GameManager.orig_FinishedEnteringScene orig, GameManager self) + { + orig(self); + if (!readyToSendReceiveChecks) + { + On.GameManager.FinishedEnteringScene -= DoInitialSyncAndStartSendReceive; + if (!hasEverRecievedStartingGeo) + { + HeroController.instance.AddGeo(ArchipelagoMod.Instance.SlotData.Options.StartingGeo); + hasEverRecievedStartingGeo = true; + } + readyToSendReceiveChecks = true; + await Synchronize(); + session.Locations.CheckedLocationsUpdated += OnLocationChecksUpdated; + } + } + + private void OnLocationChecksUpdated(ReadOnlyCollection newCheckedLocations) + { + foreach (long location in newCheckedLocations) + { + ThreadSupport.BeginInvoke(() => MarkLocationAsChecked(location, false)); + } + } + + private void PollForItems() + { + if (!readyToSendReceiveChecks || !session.Items.Any()) + { + return; + } + + ReceiveNextItem(false); + } + + private async Task Synchronize() + { + // receive from the server any items that are pending + while (ReceiveNextItem(true)) { } + // ensure any already-checked locations (co-op, restarting save) are marked cleared + foreach (long location in session.Locations.AllLocationsChecked) + { + MarkLocationAsChecked(location, true); + } + // send out any pending items that didn't get to the network from the previous session + long[] pendingLocations = deferredLocationChecks.ToArray(); + deferredLocationChecks.Clear(); + await SendLocationsAsync(pendingLocations); + } + + private bool ReceiveNextItem(bool silentGive) + { + if (!session.Items.Any()) + { + return false; // No items are waiting. + } + + ItemInfo itemInfo = session.Items.DequeueItem(); // Read the next item + + try + { + ReceiveItem(itemInfo, silentGive); + } + catch (Exception ex) + { + ArchipelagoMod.Instance.LogError($"Unexpected exception during receive for item {JsonConvert.SerializeObject(itemInfo.ToSerializable())}: {ex}"); + } + + return true; + } + + private void ReceiveItem(ItemInfo itemInfo, bool silentGive) + { + string name = itemInfo.ItemName; + ArchipelagoMod.Instance.LogDebug($"Receiving item {itemInfo.ItemId} with name {name}. " + + $"Slot is {itemInfo.Player}. Location is {itemInfo.LocationId} with name {itemInfo.LocationName}"); + + + + ArchipelagoRemoteItemCounterModule remoteTracker = ItemChangerMod.Modules.GetOrAdd(); + bool shouldReceive = remoteTracker.ShouldReceiveServerItem(itemInfo); + remoteTracker.IncrementServerCountForItem(itemInfo); + ArchipelagoMod.Instance.LogDebug($"shouldRecieve has value {shouldReceive}"); + ArchipelagoMod.Instance.LogDebug($"ActivePlayer.Slot is {ArchipelagoMod.Instance.session.Players.ActivePlayer.Slot}"); + + // If we have received a spell, we should unlock a dreamer as well with that setting enabled + if(ArchipelagoMod.Instance.SlotData.Options.AltBlackEgg) { + string[] spellNames = ["Vengeful_Spirit", "Shade_Soul", "Desolate_Dive", "Descending_Dark", "Howling_Wraiths", "Abyss_Shriek"]; + if (spellNames.Any(name.Contains)) { + if (shouldReceive || (itemInfo.Player == ArchipelagoMod.Instance.session.Players.ActivePlayer.Slot && itemInfo.LocationId > 0)) + { + DreamerItem dreamItem = new DreamerItem(); + GiveInfo dreamInfo = silentGive ? SilentGiveInfo : RemoteGiveInfo; + dreamItem.GiveImmediate(dreamInfo.Clone()); + } + } + } + + // If we have received enough mask shards to gain a Mask, we should unlock a White Fragment as well with that setting enabled + if(ArchipelagoMod.Instance.SlotData.Options.AltRadiance) { + string[] shardNames = ["Mask_Shard", "Double_Mask_Shard", "Full_Mask"]; + if (shardNames.Any(name.Contains)) { + if (shouldReceive || (itemInfo.Player == ArchipelagoMod.Instance.session.Players.ActivePlayer.Slot && itemInfo.LocationId > 0)) + { + // Getting our current player instance + PlayerData pd = PlayerData.instance; + + // Counting our current heart pieces + int heartPieces = pd.GetInt(nameof(PlayerData.heartPieces)); + ArchipelagoMod.Instance.LogDebug($"Current heartPieces value: {heartPieces}"); + int heartIndex = Array.IndexOf(shardNames, name); + if ((itemInfo.Player == ArchipelagoMod.Instance.session.Players.ActivePlayer.Slot && itemInfo.LocationId > 0)) + { + heartPieces = (heartPieces + 3) % 4; //local mask shards get applied before this function so we account for that here + } + switch (heartIndex) + { + case 0: + heartPieces += 1; + break; + case 1: + heartPieces += 2; + break; + case 2: + heartPieces += 4; + break; + } + ArchipelagoMod.Instance.LogDebug($"Post addition heartPieces value: {heartPieces}"); + // If we have over 3 heart pieces we get a White Fragment + if ( heartPieces >= 4) { + + WhiteFragmentItem fragmentItem = new WhiteFragmentItem(); + int royalCharmLevel = pd.GetInt(nameof(PlayerData.royalCharmState)); + fragmentItem.royalCharmLevel = 2; + + switch (royalCharmLevel) + { + case 1: + case 2: + fragmentItem.royalCharmLevel = 3; + break; + case 3: + fragmentItem.royalCharmLevel = 4; + break; + } + + GiveInfo fragmentInfo = silentGive ? SilentGiveInfo : RemoteGiveInfo; + fragmentItem.GiveImmediate(fragmentInfo.Clone()); + } + } + } + } + + if (itemInfo.Player == ArchipelagoMod.Instance.session.Players.ActivePlayer.Slot && itemInfo.LocationId > 0) + { + MarkLocationAsChecked(itemInfo.LocationId, silentGive); + return; + } + + if (!shouldReceive) + { + ArchipelagoMod.Instance.LogDebug($"Fast-forwarding past already received item {name} from {itemInfo.Player} at location {itemInfo.LocationDisplayName} ({itemInfo.LocationId})"); + return; + } + + // If we're still here, this is an item from someone else. We'll make up our own dummy placement and grant the item. + AbstractItem item = Finder.GetItem(name); + if (item == null) + { + ArchipelagoMod.Instance.LogWarn($"Could not find an item named '{name}'. " + + $"This means that item {itemInfo.ItemId} was not received."); + return; + } + ArchipelagoRemoteItemTag remoteItemTag = new(itemInfo); + item.AddTag(remoteItemTag); + + string sender; + if (itemInfo.LocationId == -1) + { + sender = "Cheat Console"; + } + else if (itemInfo.LocationId == -2) + { + sender = "Start"; + } + else if (itemInfo.Player == 0) + { + sender = "Archipelago"; + } + else + { + sender = session.Players.GetPlayerName(itemInfo.Player); + } + InteropTag recentItemsTag = item.AddTag(); + recentItemsTag.Message = "RecentItems"; + recentItemsTag.Properties["DisplaySource"] = sender; + + RemotePlacement pmt = RemotePlacement.GetOrAddSingleton(); + item.Load(); + pmt.Add(item); + + GiveInfo giveInfo = silentGive ? SilentGiveInfo : RemoteGiveInfo; + item.Give(pmt, giveInfo.Clone()); + } + + public void ReportDisconnect() + { + networkErrored = true; + MessageController.Enqueue( + null, + "Error: Lost connection to Archipelago server" + ); + MessageController.Enqueue( + null, + "Reload your save to attempt to reconnect." + ); + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Modules/RepositionShadeModule.cs b/Mod/Archipelago.HollowKnight/IC/Modules/RepositionShadeModule.cs new file mode 100644 index 0000000..8626745 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Modules/RepositionShadeModule.cs @@ -0,0 +1,37 @@ +using ItemChanger.Modules; +using Modding; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight.IC.Modules +{ + public class RepositionShadeModule : Module + { + private static readonly Dictionary ShadeSpawnPositionFixes = new() + { + { "Abyss_08", (90.0f, 90.0f) }, // Lifeblood Core room. Even outside of deathlink, shades spawn out of bounds. + { "Room_Colosseum_Spectate", (124.0f, 10.0f) }, // Shade spawns inside inaccessible arena + { "Resting_Grounds_09", (7.4f, 10.0f) }, // Shade spawns underground. + { "Runes1_18", (11.5f, 23.0f) }, // Shade potentially spawns on the wrong side of an inaccessible gate. + }; + + public override void Initialize() + { + ModHooks.AfterPlayerDeadHook += FixUnreachableShadePosition; + } + + public override void Unload() + { + ModHooks.AfterPlayerDeadHook -= FixUnreachableShadePosition; + } + private void FixUnreachableShadePosition() + { + // Fixes up some bad shade placements by vanilla HK. + PlayerData pd = PlayerData.instance; + if (ShadeSpawnPositionFixes.TryGetValue(pd.shadeScene, out (float x, float y) position)) + { + pd.shadePositionX = position.x; + pd.shadePositionY = position.y; + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/PlacementUtils.cs b/Mod/Archipelago.HollowKnight/IC/PlacementUtils.cs new file mode 100644 index 0000000..2b7e8fb --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/PlacementUtils.cs @@ -0,0 +1,21 @@ +using ItemChanger; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight.IC +{ + internal static class PlacementUtils + { + internal static IEnumerable GetLocationIDs(AbstractPlacement pmt) + { + ArchipelagoItemTag tag; + foreach (AbstractItem item in pmt.Items) + { + tag = item.GetTag(); + if (tag != null) + { + yield return tag.Location; + } + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/RM/HelperPlatformBuilder.cs b/Mod/Archipelago.HollowKnight/IC/RM/HelperPlatformBuilder.cs new file mode 100644 index 0000000..7529c00 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RM/HelperPlatformBuilder.cs @@ -0,0 +1,178 @@ +using Archipelago.HollowKnight.SlotDataModel; +using ItemChanger; +using System.Collections.Generic; +using SD = ItemChanger.Util.SceneDataUtil; + +namespace Archipelago.HollowKnight.IC.RM +{ + public static class HelperPlatformBuilder + { + public static IBool hasWalljump = new PDBool(nameof(PlayerData.hasWalljump)); + public static IBool hasWalljumpLeft = new PDBool(nameof(ItemChanger.Modules.SplitClaw.hasWalljumpLeft)); + public static IBool hasWalljumpRight = new PDBool(nameof(ItemChanger.Modules.SplitClaw.hasWalljumpRight)); + public static IBool hasDoubleJump = new PDBool(nameof(PlayerData.hasDoubleJump)); + + public static IBool lacksLeftClaw = new Negation(new Disjunction(hasWalljump, hasWalljumpLeft)); + public static IBool lacksLeftVertical = new Negation(new Disjunction(hasWalljump, hasDoubleJump, hasWalljumpLeft)); + public static IBool lacksRightClaw = new Negation(new Disjunction(hasWalljump, hasWalljumpRight)); + public static IBool lacksRightVertical = new Negation(new Disjunction(hasWalljump, hasDoubleJump, hasWalljumpRight)); + public static IBool lacksAnyClaw = new Negation(new Disjunction(hasWalljump, hasWalljumpLeft, hasWalljumpRight)); + public static IBool lacksAnyVertical = new Negation(new Disjunction(hasWalljump, hasDoubleJump, hasWalljumpLeft, hasWalljumpRight)); + + public static void AddStartLocationRequiredPlatforms(SlotOptions options) + { + string startLocationName = options.StartLocationName ?? StartLocationNames.Kings_Pass; + + switch (startLocationName) + { + // Platforms to allow escaping the Hive start regardless of difficulty or initial items + case StartLocationNames.Hive: + ItemChangerMod.AddDeployer(new SmallPlatform { SceneName = SceneNames.Hive_03, X = 58.5f, Y = 134f, Test = lacksRightClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform { SceneName = SceneNames.Hive_03, X = 58.5f, Y = 138.5f, Test = lacksAnyVertical }); + break; + + // Drop the vine platforms and add small platforms for jumping up. + case StartLocationNames.Far_Greenpath: + ItemChangerMod.AddDeployer(new SmallPlatform { SceneName = SceneNames.Fungus1_13, X = 45f, Y = 16.5f, Test = lacksLeftClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform { SceneName = SceneNames.Fungus1_13, X = 64f, Y = 16.5f, Test = lacksRightClaw }); + SD.Save(SceneNames.Fungus1_13, "Vine Platform (1)"); + SD.Save(SceneNames.Fungus1_13, "Vine Platform (2)"); + break; + + // With the Lower Greenpath start, getting to the rest of Greenpath requires + // cutting the vine to the right of the vessel fragment. + case StartLocationNames.Lower_Greenpath: + if (options.RandomizeNail) + { + SD.Save(SceneNames.Fungus1_13, "Vine Platform"); + } + break; + } + } + + public static void AddConveniencePlatforms(SlotOptions options) + { + // FUTURE: when we support room rando, this should be updated based on transition placements. + HashSet targetNames = new(); + string startLocationName = options.StartLocationName ?? StartLocationNames.Kings_Pass; + + if (!options.ExtraPlatforms) + { + return; + } + + // Platforms to climb out from basin wanderer's journal + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_02, X = 128.3f, Y = 7f, Test = lacksLeftClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_02, X = 128.3f, Y = 11f, Test = lacksLeftClaw }); + + // Platforms to climb up to tram in basin from left with no items + if (!targetNames.Contains($"{SceneNames.Abyss_03}[bot1]")) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_03, X = 34f, Y = 7f, Test = lacksRightVertical }); + } + + // Platform to climb out of Abyss with only wings + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_06_Core, X = 88.6f, Y = 263f, Test = lacksLeftClaw }); + + // Platforms to climb back up from pale ore with no items + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 164.7f, Y = 30f, Test = lacksRightVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 99.5f, Y = 12.5f, Test = lacksRightVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 117.7f, Y = 18.8f, Test = lacksRightClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 114.3f, Y = 23f, Test = lacksAnyVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 117.7f, Y = 7f, Test = lacksAnyClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_17, X = 117.7f, Y = 10.8f, Test = lacksAnyClaw }); + + // Platforms to remove softlock with wings at simple key in basin + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Abyss_20, X = 26.5f, Y = 13f, Test = lacksAnyClaw }); + + // Platform for returning to Gorb landing + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Cliffs_02, X = 32.3f, Y = 27.7f, Test = lacksAnyVertical }); + + // Platform to return from Deepnest mimic grub room + if (!targetNames.Contains($"{SceneNames.Deepnest_01b}[right2]") + && !targetNames.Contains($"{SceneNames.Deepnest_02}[left1]") + && !targetNames.Contains($"{SceneNames.Deepnest_02}[right1]")) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Deepnest_01b, X = 48.3f, Y = 40f, Test = lacksAnyVertical }); + } + + // Platforms to return from the Deepnest_02 geo rocks without vertical + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Deepnest_02, X = 26f, Y = 12f, Test = lacksAnyClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Deepnest_02, X = 26f, Y = 16f, Test = lacksAnyClaw }); + + // Platform to escape the Deepnest mimic room when mimics may not be present + if (options.RandomizeMimics) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Deepnest_36, X = 26f, Y = 11f, Test = lacksLeftVertical }); + } + + // Platforms to climb back up from Mantis Lords with only wings + if (!targetNames.Contains($"{SceneNames.Fungus2_15}[left1]") + && !targetNames.Contains($"{SceneNames.Fungus2_25}[top1]") + && !targetNames.Contains($"{SceneNames.Fungus2_25}[top2]")) + { + for (int i = 0; i < 2; i++) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Fungus2_15, X = 48f + 2 * i, Y = 15f + 10 * i, Test = lacksRightClaw }); + } + } + + // Platforms to prevent softlock on lever on the way to love key. + for (int i = 0; i < 2; i++) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Fungus3_05, X = 65.7f, Y = 11f + 4.5f * i, Test = lacksRightClaw }); + } + + if (startLocationName != StartLocationNames.Hive) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Hive_03, X = 58.5f, Y = 134f, Test = lacksAnyVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Hive_03, X = 58.5f, Y = 138.5f, Test = lacksAnyVertical }); + } + + // Move the load in colo downward to prevent bench soft lock + if (!targetNames.Contains($"{SceneNames.Room_Colosseum_02}[top2]") + && !targetNames.Contains($"{SceneNames.Room_Colosseum_Spectate}[right1]")) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Room_Colosseum_02, X = 43.5f, Y = 45f, Test = lacksAnyClaw }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Room_Colosseum_02, X = 43.5f, Y = 49.5f, Test = lacksAnyClaw }); + } + + // Platform to escape from the geo rock above Lemm + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Ruins1_05c, X = 26.6f, Y = 73.2f, Test = lacksAnyVertical }); + + // Platforms to climb back up to King's Pass with no items + if (!targetNames.Contains($"{SceneNames.Town}[right1]") && startLocationName == StartLocationNames.Kings_Pass) + { + for (int i = 0; i < 6; i++) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Town, X = 20f - 2 * (i % 2), Y = 5f * i + 15f, Test = lacksLeftClaw }); + } + } + + // Platforms to prevent itemless softlock when checking left waterways + if (!targetNames.Contains($"{SceneNames.Waterways_04}[left1]") + && !targetNames.Contains($"{SceneNames.Waterways_04}[left2]") + && !targetNames.Contains($"{SceneNames.Waterways_04b}[left1]") + && !targetNames.Contains($"{SceneNames.Waterways_09}[left1]") + && startLocationName != StartLocationNames.West_Waterways) + { + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Waterways_04, X = 148f, Y = 23.1f, Test = lacksAnyVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() { SceneName = SceneNames.Waterways_04, X = 139f, Y = 32f, Test = lacksAnyVertical }); + ItemChangerMod.AddDeployer(new SmallPlatform() + { + SceneName = SceneNames.Waterways_04, + X = 107f, + Y = 10f, + Test = options.RandomizeSwim ? new PDBool("canSwim") : null + }); + ItemChangerMod.AddDeployer(new SmallPlatform() + { + SceneName = SceneNames.Waterways_04, + X = 107f, + Y = 15f, + Test = options.RandomizeSwim ? new PDBool("canSwim") : null + }); + } + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/RM/LICENSE b/Mod/Archipelago.HollowKnight/IC/RM/LICENSE new file mode 100644 index 0000000..ee9ed41 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RM/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/IC/RM/NOTICE.md b/Mod/Archipelago.HollowKnight/IC/RM/NOTICE.md new file mode 100644 index 0000000..4e9ffc7 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RM/NOTICE.md @@ -0,0 +1,19 @@ +The files in this directory are taken with permission from [https://github.com/homothetyhk/RandomizerMod](RandomizerMod) under the LGPL license (also present in this directory). + +## Changes made + +### HelperPlatformBuilder.cs + +* Moved and renamed from RandomizerMod/IC/PlatformList.cs +* Added start-dependent helper platforms from RandomizerMod/IC/Export.cs's ExportStart method +* Changed namespaces and imports according to new file structure +* Changed arguments of `GetPlatformList` to use Archipelago's settings objects rather than RandomizerMod's + + +### StartLocationSceneEditsModule + +* Moved and renamed from RandomizerMod/IC/RandomizerModule.cs +* Changed namespaces and imports according to new file structure +* Scoped to only handle scene edits to prevent starting softlocks +* Adapted to use Archipelago's settings rather than RandomizerMod's +* Formatted to match this project's formatting style diff --git a/Mod/Archipelago.HollowKnight/IC/RM/StartDef.cs b/Mod/Archipelago.HollowKnight/IC/RM/StartDef.cs new file mode 100644 index 0000000..d4d9c7f --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RM/StartDef.cs @@ -0,0 +1,54 @@ +using GlobalEnums; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; +using System.IO; + +namespace Archipelago.HollowKnight.IC.RM; +public record StartDef +{ + public static Dictionary Lookup + { + get + { + if (field != null) + { + return field; + } + JsonSerializer ser = new() + { + TypeNameHandling = TypeNameHandling.Auto, + Converters = + { + new StringEnumConverter() + } + }; + using StreamReader r = new(typeof(StartDef).Assembly.GetManifestResourceStream("Archipelago.HollowKnight.Resources.Data.starts.json")); + using JsonTextReader reader = new(r); + return field = ser.Deserialize>(reader); + } + } + + public string Name { get; init; } + public string SceneName { get; init; } + public float X { get; init; } + public float Y { get; init; } + public MapZone Zone { get; init; } + /// + /// Granted transition in logic + /// + public string Transition { get; init; } + + public ItemChanger.StartDef ToItemChangerStartDef() + { + return new ItemChanger.StartDef + { + SceneName = SceneName, + X = X, + Y = Y, + MapZone = (int)Zone, + RespawnFacingRight = true, + SpecialEffects = ItemChanger.SpecialStartEffects.Default | ItemChanger.SpecialStartEffects.SlowSoulRefill, + }; + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/RM/StartLocationSceneEditsModule.cs b/Mod/Archipelago.HollowKnight/IC/RM/StartLocationSceneEditsModule.cs new file mode 100644 index 0000000..a93dec2 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RM/StartLocationSceneEditsModule.cs @@ -0,0 +1,105 @@ +using Archipelago.HollowKnight.SlotDataModel; +using ItemChanger; +using ItemChanger.Extensions; +using ItemChanger.Modules; +using UnityEngine; +using UnityEngine.SceneManagement; +using UObject = UnityEngine.Object; + +namespace Archipelago.HollowKnight.IC.RM; +public class StartLocationSceneEditsModule : Module +{ + public override void Initialize() + { + ToggleSceneHooks(true); + } + + public override void Unload() + { + ToggleSceneHooks(false); + } + + private static void ToggleSceneHooks(bool toggle) + { + SlotOptions options = ArchipelagoMod.Instance.SlotData.Options; + string startLocation = options.StartLocationName ?? StartLocationNames.Kings_Pass; + + switch (startLocation) + { + case "Ancestral Mound": + if (options.RandomizeNail) + { + if (toggle) + { + Events.AddSceneChangeEdit(SceneNames.Crossroads_ShamanTemple, DestroyPlanksForAncestralMoundStart); + } + else + { + Events.RemoveSceneChangeEdit(SceneNames.Crossroads_ShamanTemple, DestroyPlanksForAncestralMoundStart); + } + } + break; + + case "Fungal Core": + if (toggle) + { + Events.AddSceneChangeEdit(SceneNames.Fungus2_30, CreateBounceShroomsForFungalCoreStart); + } + else + { + Events.RemoveSceneChangeEdit(SceneNames.Fungus2_30, CreateBounceShroomsForFungalCoreStart); + } + + break; + + case "West Crossroads": + if (toggle) + { + Events.AddSceneChangeEdit(SceneNames.Crossroads_36, MoveShadeMarkerForWestCrossroadsStart); + } + else + { + Events.RemoveSceneChangeEdit(SceneNames.Crossroads_36, MoveShadeMarkerForWestCrossroadsStart); + } + + break; + } + + + } + + // Destroy planks in cursed nail mode because we can't slash them + private static void DestroyPlanksForAncestralMoundStart(Scene to) + { + foreach ((_, GameObject go) in to.Traverse()) + { + if (go.name.StartsWith("Plank")) + { + UObject.Destroy(go); + } + } + } + + private static void CreateBounceShroomsForFungalCoreStart(Scene to) + { + GameObject bounceShroom = to.FindGameObjectByName("Bounce Shroom C"); + + GameObject s0 = UObject.Instantiate(bounceShroom); + s0.transform.SetPosition3D(12.5f, 26f, 0f); + s0.SetActive(true); + + GameObject s1 = UObject.Instantiate(bounceShroom); + s1.transform.SetPosition3D(12.5f, 54f, 0f); + s1.SetActive(true); + + GameObject s2 = UObject.Instantiate(bounceShroom); + s2.transform.SetPosition3D(21.7f, 133f, 0f); + s2.SetActive(true); + } + + private static void MoveShadeMarkerForWestCrossroadsStart(Scene to) + { + GameObject marker = to.FindGameObject("_Props/Hollow_Shade Marker 1"); + marker.transform.position = new(46.2f, 28f); + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/RemotePlacement.cs b/Mod/Archipelago.HollowKnight/IC/RemotePlacement.cs new file mode 100644 index 0000000..21ee347 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/RemotePlacement.cs @@ -0,0 +1,47 @@ +using ItemChanger; +using ItemChanger.Extensions; +using ItemChanger.Internal; +using ItemChanger.Tags; +using Newtonsoft.Json; + +namespace Archipelago.HollowKnight.IC +{ + public class RemotePlacement : AbstractPlacement + { + public const string SINGLETON_NAME = "Remote_Items"; + + [JsonConstructor] + private RemotePlacement(string Name) : base(SINGLETON_NAME) { } + + public static RemotePlacement GetOrAddSingleton() + { + if (!Ref.Settings.Placements.TryGetValue(SINGLETON_NAME, out AbstractPlacement pmt)) + { + pmt = new RemotePlacement(SINGLETON_NAME); + CompletionWeightTag remoteCompletionWeightTag = pmt.AddTag(); + remoteCompletionWeightTag.Weight = 0; + InteropTag pinTag = new() + { + Message = "RandoSupplementalMetadata", + Properties = new() + { + ["DoNotMakePin"] = true, + } + }; + pmt.AddTag(pinTag); + ItemChangerMod.AddPlacements(pmt.Yield()); + } + return (RemotePlacement)pmt; + } + + protected override void OnLoad() + { + + } + + protected override void OnUnload() + { + + } + } +} diff --git a/Mod/Archipelago.HollowKnight/IC/Tags/ArchipelagoRemoteItemTag.cs b/Mod/Archipelago.HollowKnight/IC/Tags/ArchipelagoRemoteItemTag.cs new file mode 100644 index 0000000..cb7024d --- /dev/null +++ b/Mod/Archipelago.HollowKnight/IC/Tags/ArchipelagoRemoteItemTag.cs @@ -0,0 +1,51 @@ +using Archipelago.HollowKnight.IC.Modules; +using Archipelago.MultiClient.Net.Models; +using ItemChanger; +using Newtonsoft.Json; +using System; + +namespace Archipelago.HollowKnight.IC.Tags; + + +/// +/// Tag attached to items sent from other players +/// +public class ArchipelagoRemoteItemTag : Tag +{ + /// + /// The slot ID of the sending player + /// + public int Sender { get; set; } + + /// + /// The location ID in the sender's world + /// + public long LocationId { get; set; } + + /// + /// The item ID + /// + public long ItemId { get; set; } + + [JsonConstructor] + private ArchipelagoRemoteItemTag() { } + + public ArchipelagoRemoteItemTag(ItemInfo itemInfo) + { + if (itemInfo is ScoutedItemInfo) + { + throw new ArgumentException("Remote item tags should only be used on items received from other players and should not be initialized from scouts", nameof(itemInfo)); + } + ArchipelagoMod.Instance.LogDebug($"Created remote tag for {itemInfo.ItemName} from {itemInfo.Player} at {itemInfo.LocationDisplayName}"); + Sender = itemInfo.Player; + LocationId = itemInfo.LocationId; + ItemId = itemInfo.ItemId; + } + + public override void Load(object parent) + { + base.Load(parent); + ArchipelagoRemoteItemCounterModule module = ItemChangerMod.Modules.GetOrAdd(); + module.IncrementSavedCountForItem(Sender, LocationId, ItemId); + } +} diff --git a/Mod/Archipelago.HollowKnight/LoginValidationException.cs b/Mod/Archipelago.HollowKnight/LoginValidationException.cs new file mode 100644 index 0000000..26ea8e9 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/LoginValidationException.cs @@ -0,0 +1,19 @@ +using System; + +namespace Archipelago.HollowKnight +{ + internal class LoginValidationException : Exception + { + public LoginValidationException() + { + } + + public LoginValidationException(string message) : base(message) + { + } + + public LoginValidationException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/Mod/Archipelago.HollowKnight/MC/ArchipelagoModeMenuConstructor.cs b/Mod/Archipelago.HollowKnight/MC/ArchipelagoModeMenuConstructor.cs new file mode 100644 index 0000000..7441314 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/MC/ArchipelagoModeMenuConstructor.cs @@ -0,0 +1,213 @@ +using MenuChanger; +using MenuChanger.Extensions; +using MenuChanger.MenuElements; +using MenuChanger.MenuPanels; +using Modding; +using System; +using UnityEngine; + +namespace Archipelago.HollowKnight.MC +{ + internal class ArchipelagoModeMenuConstructor : ModeMenuConstructor + { + private MenuPage modeConfigPage; + + private readonly static Type _settingsType = typeof(ConnectionDetails); + private readonly static Font _perpetua = CanvasUtil.GetFont("Perpetua"); + + public override void OnEnterMainMenu(MenuPage modeMenu) + { + modeConfigPage = new MenuPage("Archipelago Settings", modeMenu); + ConnectionDetails settings = ArchipelagoMod.Instance.GS.MenuConnectionDetails; + + EntryField urlField = CreateUrlField(modeConfigPage, settings); + NumericEntryField portField = CreatePortField(modeConfigPage, settings); + EntryField nameField = CreateSlotNameField(modeConfigPage, settings); + EntryField passwordField = CreatePasswordField(modeConfigPage, settings); + + MenuLabel errorLabel = new(modeConfigPage, ""); + BigButton startButton = new(modeConfigPage, "Start", "May stall after clicking"); + + startButton.AddSetResumeKeyEvent("Archipelago"); + startButton.OnClick += () => StartOrResumeGame(true, errorLabel); + + modeConfigPage.AfterHide += () => errorLabel.Text.text = ""; + + IMenuElement[] elements = + [ + urlField, + portField, + nameField, + passwordField, + startButton, + errorLabel + ]; + VerticalItemPanel vip = new(modeConfigPage, SpaceParameters.TOP_CENTER_UNDER_TITLE, 100, false, elements); + modeConfigPage.AddToNavigationControl(vip); + + AttachResumePage(); + } + + private void AttachResumePage() + { + MenuPage resumePage = new("Archipelago Resume"); + + MenuLabel slotName = new(resumePage, ""); + + EntryField urlField = CreateUrlField(resumePage, null); + NumericEntryField portField = CreatePortField(resumePage, null); + EntryField passwordField = CreatePasswordField(resumePage, null); + + SmallButton resumeButton = new(resumePage, "Resume"); + MenuLabel errorLabel = new(resumePage, ""); + + void RebindSettings() + { + ConnectionDetails settings = ArchipelagoMod.Instance.LS.ConnectionDetails; + if (settings != null) + { + slotName.Text.text = $"Slot Name: {settings.SlotName}"; + urlField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerUrl))); + portField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerPort))); + passwordField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerPassword))); + } + else + { + slotName.Text.text = "Incompatible save file"; + errorLabel.Text.text = "To resume, recreate your save or downgrade to an older client version."; + } + } + + resumeButton.OnClick += () => StartOrResumeGame(false, errorLabel); + + resumePage.BeforeShow += RebindSettings; + resumePage.AfterHide += () => errorLabel.Text.text = ""; + + IMenuElement[] elements = + [ + slotName, + urlField, + portField, + passwordField, + resumeButton, + errorLabel + ]; + + VerticalItemPanel vip = new(resumePage, SpaceParameters.TOP_CENTER_UNDER_TITLE, 100, true, elements); + resumePage.AddToNavigationControl(vip); + + ResumeMenu.AddResumePage("Archipelago", resumePage); + } + + private static EntryField CreateUrlField(MenuPage apPage, ConnectionDetails settings) + { + EntryField urlField = new(apPage, "Server URL: "); + urlField.InputField.characterLimit = 500; + RectTransform urlRect = urlField.InputField.gameObject.transform.Find("Text").GetComponent(); + urlRect.sizeDelta = new Vector2(1500f, 63.2f); + urlField.InputField.textComponent.font = _perpetua; + if (settings != null) + { + urlField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerUrl))); + } + return urlField; + } + + private static NumericEntryField CreatePortField(MenuPage apPage, ConnectionDetails settings) + { + NumericEntryField portField = new(apPage, "Server Port: "); + portField.SetClamp(0, 65535); + portField.InputField.textComponent.font = _perpetua; + if (settings != null) + { + portField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerPort))); + } + return portField; + } + + private static EntryField CreateSlotNameField(MenuPage apPage, ConnectionDetails settings) + { + EntryField nameField = new(apPage, "Slot Name: "); + nameField.InputField.characterLimit = 500; + nameField.InputField.textComponent.font = _perpetua; + RectTransform nameRect = nameField.InputField.gameObject.transform.Find("Text").GetComponent(); + nameRect.sizeDelta = new Vector2(1500f, 63.2f); + if (settings != null) + { + nameField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.SlotName))); + } + return nameField; + } + + private static EntryField CreatePasswordField(MenuPage apPage, ConnectionDetails settings) + { + EntryField passwordField = new(apPage, "Password: "); + passwordField.InputField.characterLimit = 500; + passwordField.InputField.textComponent.font = _perpetua; + RectTransform passwordRect = passwordField.InputField.gameObject.transform.Find("Text").GetComponent(); + passwordRect.sizeDelta = new Vector2(1500f, 63.2f); + if (settings != null) + { + passwordField.Bind(settings, _settingsType.GetProperty(nameof(ConnectionDetails.ServerPassword))); + } + return passwordField; + } + + private static void StartOrResumeGame(bool newGame, MenuLabel errorLabel) + { + ArchipelagoMod.Instance.ArchipelagoEnabled = true; + + // Cloning some settings onto others depending on what is taking precedence. + // If it's a save slot we're resuming (newGame == false) then we want the slot settings to overwrite the global ones. + if (newGame) + { + ArchipelagoMod.Instance.LS = new APLocalSettings() + { + ConnectionDetails = ArchipelagoMod.Instance.GS.MenuConnectionDetails with { }, + }; + } + else if (ArchipelagoMod.Instance.LS.ConnectionDetails != null) + { + ArchipelagoMod.Instance.GS.MenuConnectionDetails = ArchipelagoMod.Instance.LS.ConnectionDetails with { }; + } + + try + { + ArchipelagoMod.Instance.StartOrResumeGame(newGame); + MenuChangerMod.HideAllMenuPages(); + if (newGame) + { + UIManager.instance.StartNewGame(); + } + else + { + UIManager.instance.ContinueGame(); + GameManager.instance.ContinueGame(); + } + } + catch (LoginValidationException ex) + { + ArchipelagoMod.Instance.DisconnectArchipelago(); + errorLabel.Text.text = ex.Message; + } + catch (Exception ex) + { + errorLabel.Text.text = "An unknown error occurred when attempting to connect."; + ArchipelagoMod.Instance.LogError(ex); + ArchipelagoMod.Instance.DisconnectArchipelago(); + } + } + + public override void OnExitMainMenu() + { + modeConfigPage = null; + } + + public override bool TryGetModeButton(MenuPage modeMenu, out BigButton button) + { + button = new BigButton(modeMenu, ArchipelagoMod.Instance.spriteManager.GetSprite("IconColorBig"), "Archipelago"); + button.AddHideAndShowEvent(modeMenu, modeConfigPage); + return true; + } + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/ModDependencies.txt b/Mod/Archipelago.HollowKnight/ModDependencies.txt new file mode 100644 index 0000000..7af1297 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/ModDependencies.txt @@ -0,0 +1,3 @@ +ItemChanger +MenuChanger +Benchwarp \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/Resources/Data/starts.json b/Mod/Archipelago.HollowKnight/Resources/Data/starts.json new file mode 100644 index 0000000..f301f49 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Resources/Data/starts.json @@ -0,0 +1,267 @@ +{ + "King's Pass": { + "name": "King's Pass", + "sceneName": "Tutorial_01", + "x": 35.5, + "y": 11.4, + "zone": "KINGS_PASS", + "transition": "Tutorial_01[right1]", + "logic": "ANY" + }, + "Stag Nest": { + "name": "Stag Nest", + "sceneName": "Cliffs_03", + "x": 85.8, + "y": 46.4, + "zone": "CLIFFS", + "transition": "Cliffs_03[right1]", + "logic": "ANY" + }, + "West Crossroads": { + "name": "West Crossroads", + "sceneName": "Crossroads_36", + "x": 40.2, + "y": 22.0, + "zone": "CROSSROADS", + "transition": "Crossroads_36[right1]", + "logic": "ANY" + }, + "East Crossroads": { + "name": "East Crossroads", + "sceneName": "Crossroads_03", + "x": 14.0, + "y": 68.0, + "zone": "CROSSROADS", + "transition": "Crossroads_03[top1]", + "logic": "ANY" + }, + "Ancestral Mound": { + "name": "Ancestral Mound", + "sceneName": "Crossroads_ShamanTemple", + "x": 37.7, + "y": 46.5, + "zone": "SHAMAN_TEMPLE", + "transition": "Crossroads_ShamanTemple[left1]", + "logic": "ANY" + }, + "West Fog Canyon": { + "name": "West Fog Canyon", + "sceneName": "Fungus3_30", + "x": 35.1, + "y": 16.4, + "zone": "FOG_CANYON", + "transition": "Fungus3_30[bot1]", + "logic": "ANY" + }, + "East Fog Canyon": { + "name": "East Fog Canyon", + "sceneName": "Fungus3_25", + "x": 77.5, + "y": 23.7, + "zone": "FOG_CANYON", + "transition": "Fungus3_25[right1]", + "logic": "ANY" + }, + "Queen's Station": { + "name": "Queen's Station", + "sceneName": "Fungus2_01", + "x": 24.0, + "y": 37.4, + "zone": "QUEENS_STATION", + "transition": "Fungus2_01[left1]", + "logic": "ANY" + }, + "Fungal Wastes": { + "name": "Fungal Wastes", + "sceneName": "Fungus2_28", + "x": 59.6, + "y": 3.4, + "zone": "WASTES", + "transition": "Fungus2_28[left1]", + "logic": "ANY" + }, + "Greenpath": { + "name": "Greenpath", + "sceneName": "Fungus1_32", + "x": 3.8, + "y": 27.4, + "zone": "GREEN_PATH", + "transition": "Fungus1_32[left1]", + "logic": "ANY" + }, + "Lower Greenpath": { + "name": "Lower Greenpath", + "sceneName": "Fungus1_13", + "x": 126.2, + "y": 37.4, + "zone": "GREEN_PATH", + "transition": "Fungus1_13[right1]", + "logic": "ANY" + }, + "West Blue Lake": { + "name": "West Blue Lake", + "sceneName": "Crossroads_50", + "x": 21.2, + "y": 44.4, + "zone": "CROSSROADS", + "transition": "Crossroads_50[left1]", + "logic": "ANY" + }, + "East Blue Lake": { + "name": "East Blue Lake", + "sceneName": "Crossroads_50", + "x": 225.2, + "y": 25.4, + "zone": "CROSSROADS", + "transition": "Crossroads_50[right1]", + "logic": "(ITEMRANDO | MAPAREARANDO) + (ENEMYPOGOS | ELEVATOR) | FULLAREARANDO | ROOMRANDO" + // first branch: ensure upper Resting Grounds or King's Station is accessible + }, + "City Storerooms": { + "name": "City Storerooms", + "sceneName": "Ruins1_17", + "x": 61.6, + "y": 3.4, + "zone": "CITY", + "transition": "Ruins1_17[right1]", + "logic": "ANY" + }, + "King's Station": { + "name": "King's Station", + "sceneName": "Ruins2_10b", + "x": 20.9, + "y": 136.3, + "zone": "CITY", + "transition": "Ruins2_10b[right1]", + "logic": "ANY" + }, + "Outside Colosseum": { + "name": "Outside Colosseum", + "sceneName": "Deepnest_East_09", + "x": 159.9, + "y": 12.4, + "zone": "COLOSSEUM", + "transition": "Deepnest_East_09[right1]", + "logic": "ANY" + }, + "Crystallized Mound": { + "name": "Crystallized Mound", + "sceneName": "Mines_35", + "x": 3.2, + "y": 48.4, + "zone": "MINES", + "transition": "Mines_35[left1]", + "logic": "ANY" + }, + "Mantis Village": { + "name": "Mantis Village", + "sceneName": "Fungus2_14", + "x": 117.8, + "y": 15.4, + "zone": "WASTES", + "transition": "Fungus2_14[right1]", + "logic": "(ITEMRANDO | MAPAREARANDO | FULLAREARANDO) + ENEMYPOGOS | ROOMRANDO | VERTICAL" + // first branch: ensure Queen's Station (or on full area, Fungus2_12[left1]) is reachable + }, + "Kingdom's Edge": { + "name": "Kingdom's Edge", + "sceneName": "Deepnest_East_15", + "x": 26.5, + "y": 4.4, + "zone": "OUTSKIRTS", + "transition": "Deepnest_East_15[left1]", + "logic": "(ITEMRANDO + ENEMYPOGOS + SWIM) | MAPAREARANDO | FULLAREARANDO | ROOMRANDO" + // first branch: ensure King's Station Stag is reachable + }, + "Hallownest's Crown": { + "name": "Hallownest's Crown", + "sceneName": "Mines_34", + "x": 128.3, + "y": 46.4, + "zone": "MINES", + "transition": "Mines_34[bot1]", + "logic": "(ITEMRANDO | MAPAREARANDO) + DARKROOMS | FULLAREARANDO | ROOMRANDO" + }, + "West Waterways": { + "name": "West Waterways", + "sceneName": "Waterways_09", + "x": 34.7, + "y": 30.4, + "zone": "WATERWAYS", + "transition": "Waterways_09[left1]", + "logic": "(ITEMRANDO + ENEMYPOGOS + SHADESKIPS + 2MASKS) | MAPAREARANDO | FULLAREARANDO | ROOMRANDO" + }, + "Queen's Gardens": { + "name": "Queen's Gardens", + "sceneName": "Fungus3_13", + "x": 25.3, + "y": 63.4, + "zone": "ROYAL_GARDENS", + "transition": "Fungus3_13[left1]", + "logic": "(ITEMRANDO | MAPAREARANDO | FULLAREARANDO) + ENEMYPOGOS + DANGEROUSSKIPS | ROOMRANDO" + // skip logic is minimum to ensure Hallownest_Seal-Queen's_Gardens is reachable + }, + "Distant Village": { + "name": "Distant Village", + "sceneName": "Room_spider_small", + "x": 23.1, + "y": 13.4, + "zone": "DEEPNEST", + "transition": "Room_spider_small[left1]", + "logic": "FULLAREARANDO | ROOMRANDO" + }, + "Far Greenpath": { + "name": "Far Greenpath", + "sceneName": "Fungus1_13", + "x": 34.9, + "y": 23.4, + "zone": "GREEN_PATH", + "transition": "Fungus1_13[left1]", + "logic": "MAPAREARANDO | FULLAREARANDO | ROOMRANDO" + }, + "Hive": { + "name": "Hive", + "sceneName": "Hive_03", + "x": 47.2, + "y": 142.7, + "zone": "HIVE", + "transition": "Hive_03[right1]", + "logic": "ROOMRANDO" + }, + "Royal Waterways": { + "name": "Royal Waterways", + "sceneName": "Waterways_03", + "x": 93.6, + "y": 4.4, + "zone": "WATERWAYS", + "transition": "Waterways_03[left1]", + "logic": "ROOMRANDO" + }, + "City of Tears": { + "name": "City of Tears", + "sceneName": "Ruins1_27", + "x": 29.6, + "y": 6.4, + "zone": "CITY", + "transition": "Ruins1_27[left1]", + "logic": "ROOMRANDO" + }, + "Abyss": { + "name": "Abyss", + "sceneName": "Abyss_06_Core", + "x": 42.0, + "y": 5.4, + "zone": "ABYSS", + "transition": "Abyss_06_Core[right2]", + "logic": "ROOMRANDO" + }, + "Fungal Core": { + "name": "Fungal Core", + "sceneName": "Fungus2_30", + "x": 64.8, + "y": 21.4, + "zone": "WASTES", + "transition": "Fungus2_30[top1]", + "logic": "ROOMRANDO" + } +} \ No newline at end of file diff --git a/Mod/Archipelago.HollowKnight/Resources/DeathLinkIcon.png b/Mod/Archipelago.HollowKnight/Resources/DeathLinkIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e7e59eadc851d96fb698238303098ba5ffeed3 GIT binary patch literal 6441 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 Dym>O= literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/GrubHappyv2.png b/Mod/Archipelago.HollowKnight/Resources/GrubHappyv2.png new file mode 100644 index 0000000000000000000000000000000000000000..848786cb8a61085b3572f92320e45e521661028d GIT binary patch literal 22605 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�W@=35AIpK);YB>v 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

iz_+lp61S=VQwZ1YAzS-CrELtt-(TtYHJ} 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 ASO5S3 literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/IconBlueBig.png b/Mod/Archipelago.HollowKnight/Resources/IconBlueBig.png new file mode 100644 index 0000000000000000000000000000000000000000..d707c8b8548b323723e2216584e2fd26b5a245a2 GIT binary patch literal 71762 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 literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/IconBlueSmall.png b/Mod/Archipelago.HollowKnight/Resources/IconBlueSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..a58e07a4e39d143eb6f0a66bb31457d98d72695d GIT binary patch literal 6716 zcmV-C8pGv@P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D8PQ2ZK~#8N?VSyn zTvd6;@0m?Ph%rm84B6QL0RxC80t=d81eB2M>Hl|UXPMo(_s-qVxE@(tGWX6f?~(cvPlC*vv6{i0upMnta^^4(ld zOH4bax99rj>ZK0UIsuAo{-OHql*@79+#??w$Na+L3yui`ldFf$09Y==VhjiDrr# z1th?OqA!WQI32`(s+r!N>)Xe8<^#HXujo(_1E3l2q>1ir6KU3))rI_$@A-FAic~UP zv-{Wd@w=jrivE&&34%5L0(IS$V*byIx6*~o*k{`CZqa3;clzIw#R5^UCjUhmd`Oqn zAyqS7ojg|`e=LIGzrnp0;uX>Vi56>}-|F8<34*pSPC^WyqYu{Zr6QEIR)fAfOtjyE zg~zWSxqr>`{@oNHMdE$*&-BMxqJ#af?%;i*b2KQi1*8Jb&vbR>%moV<9i{QvqpwGc zTx&BEhk^Jr&2|hs&ck`8OLXop)q@#+qA19O>H@I#9i+Ani?)dQZ1J2$8pQkYqW6eU z;#>v>qO(Q6>3?$=PBUGi9ou=gXb=B}`(O)+t>0<5KGV_G4=7%y0(kY#End0{XZPuv zEzn(@=X6N(Hn}FDTDRet+g}8zBvb%nT~7o-$b}K zcW@&G_>t&F(M{I((YOic&9D;lf2faRMSm~C0_Gav?n|Pth**x+7V_Pj_312}-=}NO zyIFhRwHltA^pzk9f+bv%PngohtitQ0LE2} zZvo)0g$UuYk{Z9{W+TxMrgwDp&#~4!KdBO($7JSO@v zWZUes!w zu{|uhPxL*#822MFHscAN$cf%6N=j2kN@<|ltM&N>&)fBQA-^X86bX8NJ$oMUFcG!I`kw(wFABH!y7K!|x}{v#rM z)Hhcf)nkmu0rM%*ABmE%%hSFKJZrBn4E97u&8U4Wb1?X1(IOF(gJ|4(fcut-a<4IF z<5=)eT178DFnk2<>()cRGQhs7DT-F4QkJn!n9*CeQeaCIm7HzMRhF; zF@gB{FVT6Up4qw~za&(QW;^?jQHyTXWwVq!n0&oD_n(VjE79KBr^#nnv$fP&=^W-y zi+|H}!0!lvoOI57%y3b&ET7iyr+=wVGC6OJ(pzi=8k~E~B`ZwzX%F;JQcZlIp znmSVOT_TpjRs#bMF?(llS*{=Ry*9Vaw%y5^1mVA~vKWv5}=Kr^NSqrSTLFP+ZF2bx{*aS`! zkrM4Hkai!*=9VMzCSaWDeg|6buXRZfqU(U!e<5NtS3t}n`{Z+?T1=JvpBoDKCHMs@ zpnk&Ga)yZAOe>YPIFJHtm#NK|eaBHg)3F6JgIpEs<)E{PtT{z56xd!d9-{^R?Wtl! zKaZuW0(uq-E)JzX5jEN#&@5oPn2_`5Gdz#pVsU|}4GWWITSx7fxL`?mR7*ox zOdi_$g!M5cU@2N8Ui*`Sna=db5R;k&yh&ikfuA}62Bi#dRH)5-5|9dk`|^&iWf(qC z9@7feb|kvbbUKY2X$9*!MG7h)4IFbVK4;2=#la)m!36$WYcp8g2ogyv*j^rvWQXY_ z6|_3Rzh1npy{kV=0mVxeC(MZTd`n@_-|kI7HrI#Np5}=GuuigPp99meX{R%(pbW

;j0K+c?P*c-7dl1;8-V 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 literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/IconColorBig.png b/Mod/Archipelago.HollowKnight/Resources/IconColorBig.png new file mode 100644 index 0000000000000000000000000000000000000000..f00b6b6b557f591c21d9163d165078e1472d00bb GIT binary patch literal 133504 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

1R({CD4@JI#}bo8Tst=W(4utNW}y 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 E5BNi0VgLXD literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/IconColorSmall.png b/Mod/Archipelago.HollowKnight/Resources/IconColorSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..ef73ee5675fcb9d8c2af39dbe998ec25e45a22cf GIT binary patch literal 6414 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 literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Resources/Pins/pinAPUseful.png b/Mod/Archipelago.HollowKnight/Resources/Pins/pinAPUseful.png new file mode 100644 index 0000000000000000000000000000000000000000..66a3df34cbe221df909af98bc453c6ad27d0ef9a GIT binary patch literal 2547 zcmd^<`&$wQ7ss(xn#)pa%Qe94cOHCbuA_;=x1vOMe zR7AvUqJn@oE~0>_2r4RwXf&OrAmF8X*IUcCm;R3TJl}IZ&w0-I={(Q(CYXV4TsjY+jXLN|&E|jk{^AP&FtA^KjMxGId;z$A z?dAngF9gDeL3^N3K0ICs`dtVD2_Z>B2&g|fMF;^4p%C$tC;f1!Fcm6G1i=9zdccUD6a){9=o^Hf2EphNaE1hgk|bq}g3!Yd zv4VU@Jv1; zmj_AjdxGkNq6F}40X#>Pk=KjFa531P;_}{s^a3feU@)UdnqD}XT_VjX8ObY^=a$Ix zD@JjZ6NN;15qTU>Qq*Nm)gY(pQR>Dlbxr#7`YdHbuDUTt`7C#;`RNQbf4T{yreUXA zN@nPI6%#kZz-yT0YF7D+PLi^;ZoHJDsHj(v8pcV_hHQ&7w6@xv)U_bBT&-YU2+PO$^CTbu9CCoyLvoeOV&>{>* zocpxDAX}1)mEej73rhzG6@#V4!}wBJ8BsOoNtb)G_tCu9d}Zqn@*3;2QNks|J29R`j%3h$#}`%f&@y z0~Mr!65?QCTpU~X)Fb^Q^8;UnN-p*tLz^x6O51r(hBitxmZdXkdTIkDZoC5ctmA*>sX^377AH0Dv8$&uKOo|11gs*plGy=X*2wk`V_@*mcWcu(>$a zzODoE?L=O~L)770>Ly*A-{$XZ;{Vx&39|81I0Co$9yx+iB^?asUc1j?Gb6@SGMtj@My@$o`{e{ccZeO^&k@Q2_Dt9$)@f}Qku=>9P0BEXaO0N0@WfnkP}QKGJ2Y!n+SGB- z_sNqU_KBfeB7bjXJE5diWFK-vK#q~)qI%R3oQU1A_Nt&ZarZqgZEs}Pt8l_d1mnlo z?lpfKM?^XD5$L;*z7%>b37p4<6!eo z=cB{)espu{qpvmn&Kw_Ktql?EexB~)dQdBYMr_|I8Y1Yb0;9v?**%VK2kt9Xxdp_1 zygta@^D$%lkIXax<2}yOAM0FY&L8IPuXVKNoMrI&FJ@n#$c!9B>FYt&?k?kJjvU^` z2lOCM(1N<&)`F2D7C&zGFVaswnwc3x%vvleVZ|!XI@K!FAM5ib)>yIUc58~;c;CU+ zfY0l3)*x~qI4#x++EGxpDwWTTUzMRm(L_t^LRYr@uQfQA)BZO+VM&U zLb+u9=R@rL8e}7+n>TScVE%UM?ly_fxM${6$Lft(v;XYxX0ejT9khDGvYR=&*! zwsG+dyq%`GbKQ0|X&qR##AMgdAMSAYn=yOW+28i%Z z5xAZkTc*z`4@d>)*6a#?rGUdWfqx_c_c-+Ak+0Q=K@UbNd(yYVoSQ8DFm8u6H`b09 zqvae+iaRQA$z?t~;!acH{<6%F2Mg+=aBI%yO_<$Ukp$3A+qSUIULYo~WWRR4OrlY5co(~YFQo|D-97h_6yo(gq9{(&=BsPR%4D_Z zch(=g?Fv82YYm_Np|RdC>$sg3Nc#B7q6hSwrQ+t5uuUPU=57{$I^t=4$Cp2tWwPZ2 z;Mr4OCjGH5>F?--^1vY^vNcoe8srb;zp3V=I?cPc!|nxr&1>^G;{QGImzTn}7N>J| znJ&#RxXV@ZT>`Y%+1}WD0sFRJ38n@Fg!wpFZr$nV{N?w4zejj^%|&ii+#m2Ro(Vp4 z(gI690}RUCHFBZsRE0u$w^HZw!Rh3Qu$+3^uLSLdi$%G{3eqrhn$WhYaw)0Q94s4@dnE|C8Ff literal 0 HcmV?d00001 diff --git a/Mod/Archipelago.HollowKnight/Settings.cs b/Mod/Archipelago.HollowKnight/Settings.cs new file mode 100644 index 0000000..412fb47 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/Settings.cs @@ -0,0 +1,23 @@ +namespace Archipelago.HollowKnight +{ + public record ConnectionDetails + { + public string ServerUrl { get; set; } = "archipelago.gg"; + public int ServerPort { get; set; } = 38281; + public string SlotName { get; set; } + public string ServerPassword { get; set; } + } + + public record APGlobalSettings + { + public ConnectionDetails MenuConnectionDetails { get; set; } = new(); + public bool EnableGifting { get; set; } = true; + } + + public record APLocalSettings + { + public ConnectionDetails ConnectionDetails { get; set; } + public string RoomSeed { get; set; } + public long Seed { get; set; } + } +} diff --git a/Mod/Archipelago.HollowKnight/SlotDataModel/SlotData.cs b/Mod/Archipelago.HollowKnight/SlotDataModel/SlotData.cs new file mode 100644 index 0000000..bdef2db --- /dev/null +++ b/Mod/Archipelago.HollowKnight/SlotDataModel/SlotData.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Archipelago.HollowKnight.SlotDataModel +{ + public class SlotData + { + [JsonProperty("seed")] + public int Seed { get; set; } + + [JsonProperty("options")] + public SlotOptions Options { get; set; } + + [JsonProperty("location_costs")] + public Dictionary> LocationCosts { get; set; } + + [JsonProperty("notch_costs")] + public List NotchCosts { get; set; } + + [JsonProperty("grub_count")] + public int? GrubsRequired { get; set; } + + [JsonProperty("is_race")] + public bool DisableLocalSpoilerLogs { get; set; } + } +} diff --git a/Mod/Archipelago.HollowKnight/SlotDataModel/SlotOptions.cs b/Mod/Archipelago.HollowKnight/SlotDataModel/SlotOptions.cs new file mode 100644 index 0000000..611f4fd --- /dev/null +++ b/Mod/Archipelago.HollowKnight/SlotDataModel/SlotOptions.cs @@ -0,0 +1,143 @@ +namespace Archipelago.HollowKnight.SlotDataModel +{ + public class SlotOptions + { + public bool RandomizeDreamers { get; set; } + + public bool RandomizeSkills { get; set; } + + public bool RandomizeFocus { get; set; } + + public bool RandomizeSwim { get; set; } + + public bool RandomizeCharms { get; set; } + + public bool RandomizeKeys { get; set; } + + public bool RandomizeMaskShards { get; set; } + + public bool RandomizeVesselFragments { get; set; } + + public bool RandomizeCharmNotches { get; set; } + + public bool RandomizePaleOre { get; set; } + + public bool RandomizeGeoChests { get; set; } + + public bool RandomizeJunkPitChests { get; set; } + + public bool RandomizeRancidEggs { get; set; } + + public bool RandomizeRelics { get; set; } + + public bool RandomizeWhisperingRoots { get; set; } + + public bool RandomizeBossEssence { get; set; } + + public bool RandomizeGrubs { get; set; } + + public bool RandomizeMimics { get; set; } + + public bool RandomizeMaps { get; set; } + + public bool RandomizeStags { get; set; } + + public bool RandomizeLifebloodCocoons { get; set; } + + public bool RandomizeGrimmkinFlames { get; set; } + + public bool RandomizeJournalEntries { get; set; } + + public bool RandomizeNail { get; set; } + + public bool RandomizeGeoRocks { get; set; } + + public bool RandomizeBossGeo { get; set; } + + public bool RandomizeSoulTotems { get; set; } + + public bool RandomizeLoreTablets { get; set; } + + public bool AltBlackEgg { get; set; } + + public bool AltRadiance { get; set; } + + public bool PreciseMovement { get; set; } + + public bool ProficientCombat { get; set; } + + public bool BackgroundObjectPogos { get; set; } + + public bool EnemyPogos { get; set; } + + public bool ObscureSkips { get; set; } + + public bool ShadeSkips { get; set; } + + public bool InfectionSkips { get; set; } + + public bool FireballSkips { get; set; } + + public bool SpikeTunnels { get; set; } + + public bool AcidSkips { get; set; } + + public bool DamageBoosts { get; set; } + + public bool DangerousSkips { get; set; } + + public bool DarkRooms { get; set; } + + public bool ComplexSkips { get; set; } + + public bool DifficultSkips { get; set; } + + public bool Slopeballs { get; set; } + + public bool ShriekPogos { get; set; } + + public bool RemoveSpellUpgrades { get; set; } + + public bool RandomizeElevatorPass { get; set; } + + public string StartLocationName { get; set; } + + public int MinimumGrubPrice { get; set; } + + public int MaximumGrubPrice { get; set; } + + public int MinimumEssencePrice { get; set; } + + public int MaximumEssencePrice { get; set; } + + public int MinimumEggPrice { get; set; } + + public int MaximumEggPrice { get; set; } + + public int RandomCharmCosts { get; set; } + + public int EggShopSlots { get; set; } + + public GoalsLookup Goal { get; set; } + + public bool DeathLink { get; set; } + + public DeathLinkShadeHandling DeathLinkShade { get; set; } + + public bool DeathLinkBreaksFragileCharms { get; set; } + + public WhitePalaceOption WhitePalace { get; set; } + + public bool ExtraPlatforms { get; set; } + + public int StartingGeo { get; set; } + + public bool SplitMantisClaw { get; set; } + + public bool SplitMothwingCloak { get; set; } + + public bool SplitCrystalHeart { get; set; } + + public bool AddUnshuffledLocations { get; set; } + } +} diff --git a/Mod/Archipelago.HollowKnight/TimeoutExtensions.cs b/Mod/Archipelago.HollowKnight/TimeoutExtensions.cs new file mode 100644 index 0000000..1086fd0 --- /dev/null +++ b/Mod/Archipelago.HollowKnight/TimeoutExtensions.cs @@ -0,0 +1,83 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Archipelago.HollowKnight +{ + // implementation from https://devblogs.microsoft.com/pfxteam/crafting-a-task-timeoutafter-method/ + internal static class TimeoutExtensions + { + private struct VoidTypeStruct { } + + private static void MarshalTaskResults(Task source, TaskCompletionSource proxy) + { + switch (source.Status) + { + case TaskStatus.Faulted: + proxy.TrySetException(source.Exception); + break; + case TaskStatus.Canceled: + proxy.TrySetCanceled(); + break; + case TaskStatus.RanToCompletion: + Task castedSource = source as Task; + proxy.TrySetResult( + castedSource == null ? default : // source is a Task + castedSource.Result); // source is a Task + break; + } + } + + public static Task TimeoutAfter(this Task task, int millisecondsTimeout) + { + // Short-circuit #1: infinite timeout or task already completed + if (task.IsCompleted || (millisecondsTimeout == Timeout.Infinite)) + { + // Either the task has already completed or timeout will never occur. + // No proxy necessary. + return task; + } + + // tcs.Task will be returned as a proxy to the caller + TaskCompletionSource tcs = new(); + + // Short-circuit #2: zero timeout + if (millisecondsTimeout == 0) + { + // We've already timed out. + tcs.SetException(new TimeoutException()); + return tcs.Task; + } + + // Set up a timer to complete after the specified timeout period + Timer timer = new Timer(state => + { + // Recover your state information + var myTcs = (TaskCompletionSource)state; + + // Fault our proxy with a TimeoutException + myTcs.TrySetException(new TimeoutException()); + }, tcs, millisecondsTimeout, Timeout.Infinite); + + // Wire up the logic for what happens when source task completes + task.ContinueWith((antecedent, state) => + { + // Recover our state data + var tuple = + (Tuple>)state; + + // Cancel the Timer + tuple.Item1.Dispose(); + + // Marshal results to proxy + MarshalTaskResults(antecedent, tuple.Item2); + }, + Tuple.Create(timer, tcs), + CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return tcs.Task; + } + } +} diff --git a/Mod/LICENSE.txt b/Mod/LICENSE.txt new file mode 100644 index 0000000..17db641 --- /dev/null +++ b/Mod/LICENSE.txt @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2022 Hussein Farran +Copyright (c) 2022 Daniel Grace + +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, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. diff --git a/Mod/README.md b/Mod/README.md new file mode 100644 index 0000000..1bff9e9 --- /dev/null +++ b/Mod/README.md @@ -0,0 +1,41 @@ +# Archipelago.HollowKnight + +A mod which enables Hollow Knight to act as an Archipelago client, enabling multiworld and randomization driven by the [Archipelago multigame multiworld system](https://archipelago.gg). + +## Installing Archipelago.HollowKnight +### Installing with Lumafly +1. [Download Lumafly](https://themulhima.github.io/Lumafly?download). +2. Place Lumafly in a folder other than your Downloads folder and run it + * If it does not detect your HK install directory, lead Lumafly to the correct directory. + * Also, don’t pirate the game. >:( +3. Install and enable Archipelago. + * There are several mods that are needed to for Archipelago to run. They are installed automatically. + * Archipelago Map Mod is an in-game tracker for Archipelago. It is optional and can also be installed from Lumafly. +4. Start the game and ensure **Archipelago** appears in the top left corner of the main menu. + +## Joining an Archipelago Session +1. Start the game after installing all necessary mods. +2. Create a **new save game.** +3. Select the **Archipelago** game mode from the mode selection screen. +4. Enter in the correct settings for your Archipelago server. +5. Hit **Start** to begin the game. The game will stall for a few seconds while it does all item placements. +6. The game will immediately drop you into the randomized game. So if you are waiting for a countdown then wait for it to lapse before hitting Start, or hit Start then pause the game once you're in it. + +# Contributing +Contributions are welcome, all code is licensed under the MIT License. Please track your work within the repository if you are taking on a feature. This is done via GitHub Issues. If you are interesting in taking on an issue please comment on the issue to have it assigned to you. If you are looking to contribute something that isn't in the issues list then please submit an issue to describe what work you intend to take on. + +Contribution guidelines: +* All issues should be labeled appropriately. +* All in-progress issues should have someone assigned to them. +* Pull Requests must have at least (and preferably exactly) one linked issue which they close out. +* Please use feature branches, especially if working in this repository (not a fork). +* Please match the style of the surrounding code. In particular: + * Don't use `var`. + * Use shorthand constructor syntax in declarations, and only in declarations (for example, `ArchipelagoRandomizer randomizer = new(slotData);`). + * Always enclose the body of control flow statements (`if`, `foreach`, etc.) in braces, even for single-line bodies. + +## Development Setup +Follow the instructions in the csproj file to create a LocalOverrides.targets file with your Hollow Knight installation path. If you use the Hollow Knight Modding Visual Studio extension (recommended), there is an item template to create this file for you automatically. + +Post-build events will automatically package the mod for export **as well as install it in your HK installation.** When developing on the mod **do not install Archipelago through an installer.** Some installers, e.g. Lumafly, can pin the development version to prevent it from being replaced by the production version from the installer. + From ef0f523f7a8d7cf1822a7c1a1dfbc10d07eeffcd Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 12 Oct 2025 19:17:37 -0400 Subject: [PATCH 4/5] adjusted mod readme to reflect new providence --- Mod/README.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/Mod/README.md b/Mod/README.md index 1bff9e9..016d849 100644 --- a/Mod/README.md +++ b/Mod/README.md @@ -2,16 +2,7 @@ A mod which enables Hollow Knight to act as an Archipelago client, enabling multiworld and randomization driven by the [Archipelago multigame multiworld system](https://archipelago.gg). -## Installing Archipelago.HollowKnight -### Installing with Lumafly -1. [Download Lumafly](https://themulhima.github.io/Lumafly?download). -2. Place Lumafly in a folder other than your Downloads folder and run it - * If it does not detect your HK install directory, lead Lumafly to the correct directory. - * Also, don’t pirate the game. >:( -3. Install and enable Archipelago. - * There are several mods that are needed to for Archipelago to run. They are installed automatically. - * Archipelago Map Mod is an in-game tracker for Archipelago. It is optional and can also be installed from Lumafly. -4. Start the game and ensure **Archipelago** appears in the top left corner of the main menu. +This mod is a lightly modified fork, the original license is viewable at LICENSE.txt. ## Joining an Archipelago Session 1. Start the game after installing all necessary mods. @@ -21,19 +12,6 @@ A mod which enables Hollow Knight to act as an Archipelago client, enabling mult 5. Hit **Start** to begin the game. The game will stall for a few seconds while it does all item placements. 6. The game will immediately drop you into the randomized game. So if you are waiting for a countdown then wait for it to lapse before hitting Start, or hit Start then pause the game once you're in it. -# Contributing -Contributions are welcome, all code is licensed under the MIT License. Please track your work within the repository if you are taking on a feature. This is done via GitHub Issues. If you are interesting in taking on an issue please comment on the issue to have it assigned to you. If you are looking to contribute something that isn't in the issues list then please submit an issue to describe what work you intend to take on. - -Contribution guidelines: -* All issues should be labeled appropriately. -* All in-progress issues should have someone assigned to them. -* Pull Requests must have at least (and preferably exactly) one linked issue which they close out. -* Please use feature branches, especially if working in this repository (not a fork). -* Please match the style of the surrounding code. In particular: - * Don't use `var`. - * Use shorthand constructor syntax in declarations, and only in declarations (for example, `ArchipelagoRandomizer randomizer = new(slotData);`). - * Always enclose the body of control flow statements (`if`, `foreach`, etc.) in braces, even for single-line bodies. - ## Development Setup Follow the instructions in the csproj file to create a LocalOverrides.targets file with your Hollow Knight installation path. If you use the Hollow Knight Modding Visual Studio extension (recommended), there is an item template to create this file for you automatically. From 138079a99ee09b18ba7b098d1cccf685bc486410 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 12 Oct 2025 19:18:50 -0400 Subject: [PATCH 5/5] lil sassy update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dd41b4..780bfca 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,4 @@ Edits of the existing AP adding the AltBlackEgg and AltRadiance options. /World is the apworld folder, only necessary when generating the world -/Mod is the mod folder, should be built and put into your Hollow Knight mod folder +/Mod is the mod folder, should be built and put into your Hollow Knight mod folder (yay instruckchiouns)