mirror of
https://github.com/AHA705/Monopoly-Poker-Helper.git
synced 2026-10-07 22:56:34 +01:00
simplified the README and split parts of it into docs
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
# Monopoly Poker Mod Helper
|
# Monopoly Poker Mod Helper
|
||||||
|
|
||||||
This repository contains helper code, notes, and logs for modding `Monopoly Poker`.
|
This repository contains mods for `Monopoly Poker`.
|
||||||
|
|
||||||
|
Currently a WIP.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -14,30 +16,6 @@ This repo is focused on reverse engineering game behavior, finding useful types
|
|||||||
- `BepInEx IL2CPP`
|
- `BepInEx IL2CPP`
|
||||||
- `dnSpy` (for inspecting game assemblies and objects)
|
- `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
|
## Setup
|
||||||
|
|
||||||
1. Open the solution in Visual Studio.
|
1. Open the solution in Visual Studio.
|
||||||
@@ -54,253 +32,3 @@ This is a dnSpy dump of the game's main assembly, used for reference and explora
|
|||||||
- **Harmony Docs**: <https://harmony.pardeike.net/>
|
- **Harmony Docs**: <https://harmony.pardeike.net/>
|
||||||
|
|
||||||
Note UnityExplorer is archived, need to use a fork.
|
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.
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
# Common 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.
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
# Snippets
|
||||||
|
|
||||||
|
## 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Singleton Access
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Most game managers use the Singleton pattern
|
||||||
|
var instance = ManagerType.GetProperty("Instance").GetValue(null);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user