Initial commit

This commit is contained in:
2026-09-19 14:39:03 +01:00
commit 3449f141fa
21 changed files with 3349 additions and 0 deletions
+306
View File
@@ -0,0 +1,306 @@
# Monopoly Poker Mod Helper
This repository contains helper code, notes, and logs for modding `Monopoly Poker`.
## Overview
`Monopoly Poker` is an Unity IL2CPP game on Steam, so mods should be built for `IL2CPP`. BepInEx IL2CPP is used in this project.
This repo is focused on reverse engineering game behavior, finding useful types through reflection, and automating helper actions.
## Requirements
- Visual Studio
- `.NET 6`
- `BepInEx IL2CPP`
- `dnSpy` (for inspecting game assemblies and objects)
## Repository Structure
### `MonopolyPokerHelper/`
Main mod/helper project code.
Example files:
- `ClaimMissionHandler.cs` - discovers and claims missions through reflection
### Assembly-CSharp
This is a dnSpy dump of the game's main assembly, used for reference and exploration. It is not meant to be built or modified directly.
## What This Project Is For
- Uses reflection to inspect game objects and types
- Automates helper actions inside the game
- Stores notes and logs for reverse engineering work
## Notes
- The dash character `—` may display incorrectly in the BepInEx console.
- `dnSpy` may need a fix for loading certain assemblies.
- You can use `BepInEx.ConfigurationManager` if you want an in-game configuration UI.
## Setup
1. Open the solution in Visual Studio.
2. Ensure the project targets `.NET 6` and references the game assembly as needed.
3. Build the helper project.
4. Deploy the output into the BepInEx plugin folder.
## Useful References
- BepInEx IL2CPP: https://github.com/BepInEx/BepInEx
- Configuration Manager: https://github.com/BepInEx/BepInEx.ConfigurationManager/releases/tag/v18.4.1
- [UnityExplorer](https://github.com/sinai-dev/UnityExplorer) (for browsing game assets and types during runtime)
- **BepInEx Docs**: <https://docs.bepinex.dev/>
- **Harmony Docs**: <https://harmony.pardeike.net/>
Note UnityExplorer is archived, need to use a fork.
## Known Issues
### dnSpy Import Project
When trying to load a disassembled project that was then reassembled with dnSpy into Visual Studio you'll encounter the error:
`A numeric comparison was attempted on "$(_TargetFrameworkVersionWithoutV)" that evaluates to "" instead of a number, in condition "('$(TargetFrameworkIdentifier)' != '.NETCoreApp'`
This is because the project file generated by dnSpy is adding a v to <TargetFrameworkVersion> and as well as not including _TargetFrameworkVersionWithoutV. To fix this:
1. Open the .csproj file in a text editor.
2. Near the top you'll see these two lines:
```xml
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
```
Modify the first line (remove the "v"), and insert the second line, so it looks like this:
```xml
<TargetFrameworkVersion>5.0</TargetFrameworkVersion>
<_TargetFrameworkVersionWithoutV>5.0</_TargetFrameworkVersionWithoutV>
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
```
Load the project as you were, and it should work.
Mileage may vary with different versions of Visual Studio and .NET SDK, but this is the general fix for the issue.
[Source](https://www.clearhat.org/post/how-fix-numeric-comparison-was-attempted-_targetframeworkversionwithoutv-evaluates-instead-number-condition-targetframeworkidentifier-netcoreapp)
### Encoding issues in BepInEx Console
"—" always shows as ΓòÉ on BepInEx Console. Use the regular hyphen "-" instead.
## How to Extend This README
Add new sections when needed:
- setup and build instructions
- file-by-file descriptions
- known issues
- update history
## Git Stash Reminder
to git stash staged changes, you can use the following command:
```
git stash push --staged -m "message"
```
## Modding Guide
### Tech Stack
#### What is BepInEx?
**BepInEx** (Bepis Injector Extendable) is a plugin/mod loader for Unity games. It:
- Injects itself into the game when it launches
- Loads your plugin DLLs automatically from `BepInEx/plugins/`
- Provides logging, configuration, and modding APIs
- Handles IL2CPP games (compiled to native C++ code, harder to mod than Mono)
#### What is Harmony?
**Harmony** is a runtime patching library that lets you modify game methods without changing the original game files:
- **Prefix**: Run your code BEFORE the original method (can block the original)
- **Postfix**: Run your code AFTER the original method
- **Transpiler**: Modify the method's IL code directly (advanced)
You patch methods by their type and method name - no compile-time references needed!
---
## 📋 Common Patterns
### Pattern: Periodic Timer
```csharp
private static float _timer;
private const float INTERVAL = 10f;
private static void UpdatePostfix()
{
_timer += UnityEngine.Time.deltaTime;
if (_timer < INTERVAL) return;
_timer = 0f;
// Do something every 10 seconds
}
```
### Pattern: Singleton Access
```csharp
// Most game managers use the Singleton pattern
var instance = ManagerType.GetProperty("Instance").GetValue(null);
```
### Pattern: Safe Reflection
```csharp
try
{
var method = type.GetMethod("MethodName");
if (method == null)
{
Log.LogWarning("Method not found!");
return;
}
method.Invoke(instance, args);
}
catch (Exception ex)
{
Log.LogError($"Reflection error: {ex.Message}");
}
```
### Pattern: Patch All Overloads
```csharp
var methods = targetType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach (var method in methods)
{
if (method.Name == "TargetMethod")
{
_harmony.Patch(method, prefix: myPrefix);
}
}
```
---
## ⚠️ Common Pitfalls
### 1. **IL2CPP Array Indexing**
IL2CPP arrays need special handling:
```csharp
// DON'T: arr[0]
// DO:
var getMethod = array.GetType().GetMethod("get_Item");
var value = getMethod.Invoke(array, new object[] { 0 });
```
### 2. **Timing Issues**
Game managers may not be loaded immediately:
```csharp
// Wait before trying to access managers
if (!_initialDelayDone)
{
_elapsed += deltaTime;
if (_elapsed < 30f) return; // wait 30 seconds
_initialDelayDone = true;
}
```
### 3. **Type Name Collisions**
Multiple assemblies may have classes with the same name:
```csharp
// Use full namespace
FindType("YoudaGames.MonopolyPoker.Popups.RollingOffersPopup");
```
### 4. **Harmony Patch Failures**
Methods might not exist or load later:
```csharp
try
{
_harmony.Patch(method, prefix);
}
catch (Exception ex)
{
Log.LogWarning($"Patch failed: {ex.Message}");
// Method may load later - try again or check name
}
```
---
## 🎉 Example Mod Ideas
Now that you understand the basics, try creating:
1. **Auto Claimer** - Automatically collect daily rewards (you have this!)
2. **Speed Hack** - Patch animation methods to speed up gameplay
3. **UI Remover** - Block annoying popups (you have this!)
4. **Unlimited Resources** - Modify currency values via reflection
5. **Auto Player** - Hook game actions and make decisions automatically
6. **Visual Tweaks** - Modify Unity UI elements at runtime
---
## 🐛 Debugging Tips
### View Logs
```
<Game Dir>/BepInEx/LogOutput.log
```
### Enable Debug Logging
In your plugin:
```csharp
Log.LogDebug("Debug message"); // Will show if debug level enabled
```
In `BepInEx/config/BepInEx.cfg`:
```ini
[Logging.Console]
LogLevels = Fatal, Error, Warning, Message, Info, Debug
```
## UnityExplorer Console Snippets
### Dumping GameObject Information
Replace the type with the one you need, e.g., `YoudaGames.MonopolyPoker.Popups.BoardwalkJackpotRollPopup`.
```
var instances = UnityEngine.Object.FindObjectsOfType<YoudaGames.MonopolyPoker.Popups.BoardwalkJackpotRollPopup>();
foreach (var popup in instances)
{
Console.WriteLine($"--- Begin for instance {popup} ---");
var type = popup.GetType();
foreach (var prop in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
Console.WriteLine($"{prop.Name}: {prop.GetValue(popup)}");
}
Console.WriteLine("--- End ---");
}
```
TODO: Perhaps seperate this README into a docs folder and link to it from the main README, to keep the main README concise and focused on project overview and setup.