diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..155e425 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "0.28.2", + "commands": [ + "dotnet-csharpier" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..723db96 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "[csharp]": { + "editor.tabSize": 4, + "editor.insertSpaces": true, + "editor.defaultFormatter": "csharpier.csharpier-vscode", + "editor.formatOnSave": true, + "editor.formatOnPaste": true + } +} diff --git a/README.md b/README.md index 9e3f2a8..8678143 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,69 @@ # SCHALE.GameServer -## Running -By default the server is configured to run with SQL Server Express in `appsettings.json`. If you wanna use other edition of SQL Server Express change the `ConnectionStrings` in there. +> [!TIP] +> For original README please refer to -Alternatively this software can run in docker too (`docker compose up --build`). +## Prerequisites -## Connecting -- Run the game with this [frida script](https://gist.githubusercontent.com/raphaeIl/c4ca030411186c9417da22d8d7864c4d/raw/00b69c5bacdf79c24972411bd80d785eed3841ce/ba.js) +- Some computer knowledge +- [.NET SDK 8.0](https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0) +- [SQL Express](https://www.microsoft.com/zh-tw/sql-server/sql-server-downloads) +- [SQL Server Management Studio (SSMS)](https://learn.microsoft.com/zh-tw/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16) +- [LD Player 9](https://www.ldplayer.tw/) +- [Python](https://www.python.org/) +- [Frida](https://frida.re/) +- [frida-server-16.2.5-android-x86_64](https://github.com/frida/frida/releases) -## Discuss -[Discord Server](https://discord.gg/fbsRYc7bBA) +## Steps -## How to use (E.g Windows and LDPlayer 9) -1. Download this repo. -```sh -git clone https://github.com/rafi1212122/SCHALE.GameServer.git +1. Start SQL server +2. Start private game server +3. Start LD Player +4. Start Frida server +5. Start ブルアカ +6. Inject Frida script +7. Enjoy :smile: + +### SQL server + +Use SSMS to connect with default settings except that you have to check "Trust server certificate". + +### Game server + +```bash +# in this repo +cd SCHALE.GameServer +dotnet run ``` -2. Download .NET SDK, SQL Server Express, and install them. -- .NET SDK
- -- SQL Server Express
- -3. Download Visual Studio and Install C# and Database Extensions.
-[https://visualstudio.microsoft.com/zh-hans/vs/](https://visualstudio.microsoft.com/vs/) -4. Use Visual Studio to open `SCHALE.GameServer\SCHALE.GameServer.sln` and make it. -5. Download `Excel.zip` and unzip and add the excels to the following path: `SCHALE.GameServer\bin\Debug\net8.0\Resources\excel`. -6. Modify the IP address in `SCHALE.GameServer-master\SCHALE.GameServer\bin\Debug\net8.0\Config.json`. -7. Open `SCHALE.GameServer-master\SCHALE.GameServer\bin\Debug\net8.0\SCHALE.GameServer.exe`. -8. Download python and install frida
You may need to add python site packages to PATH if "frida" command is missing.
- -```sh -pip install frida-tools -pip install frida + +### Frida server + +1. Extract `frida-server-16.2.5-android-x86_64.xz` +to `LDPlayer/frida-server-16.2.5-android-x86_64`. +2. Turn on LD Player +3. Turn on root and adb in the settings of LD Player. +4. + +```bash +# in LDPlayer +cd LDPlayer9 +./adb.exe push ../frida-server-16.2.5-android-x86_64 /data/local/tmp/frida-server +./adb.exe shell +su +cd /data/local/tmp +chmod 755 frida-server +./frida-server ``` -9. Download frida-server(if you use emulator, download x86), find "frida-server-[Latest Version]-android-x86_64.xz" and download & unzip it, before push you may rename the bin file to "frida-server".
- -10. Download adb.
- -11. Use adb connect emulator and start frida-server(enable root first) -```sh -adb root -adb push frida-server /data/local/tmp/ -adb shell "chmod 755 /data/local/tmp/frida-server" -adb shell "/data/local/tmp/frida-server &" -``` -12. Start BluearchiveJP and use frida script - 1. download this [frida script](https://gist.githubusercontent.com/raphaeIl/c4ca030411186c9417da22d8d7864c4d/raw/00b69c5bacdf79c24972411bd80d785eed3841ce/ba.js) and modify `SERVER_ADDRESS` - 2. Start BluearchiveJP first and then start frida - 3. `frida -U "ブルアカ" -l ba.js --realm=emulated` -13. Skip Tutorial
-If you have never finished any tutorials try this
-`INSERT INTO [dbo].[AccountTutorials] ([AccountServerId], [TutorialIds]) VALUES (1, N'[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]');`
-or you have finished the front part of the tutorial use this
-`UPDATE [dbo].[AccountTutorials] SET [TutorialIds] = N'[1, 2, 3, 4, 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]' WHERE [AccountServerId] = [Your Server ID];` -## Command -Go to club and input `/help` to view command usage +### Inject Frida script -## Troubleshooting +> [!NOTE] +> Edit line 5 of [ba.js](./ba.js) to your own server IP. -##### YostarRequestFail:INIT_FAILED(Initialization failed) -- change `SERVER_ADDRESS` in `ba.js` to your IPV4 and not `0.0.0.0` +> [!WARNING] +> Do this fast when you open ブルアカ and see the Yostar logo. -##### アカウント情報の連携中にエラーガ発生乚ま乚た -- restart server or without `Resources\excel` - -##### can enter game but black screen -- close server and delete database, then open server.
-if it isn't work, you may need to pass the official tutorial first. - -##### failed to load club -- change `Address` in `config.json` to your IPV4 - -##### command not work -- the excel you are using may have problem, change your excel. +```bash +# in this repo +frida -U "ブルアカ" -l ba.js --realm=emulated +``` \ No newline at end of file diff --git a/Resources/data/.gitignore b/Resources/data/.gitignore new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/Resources/data/.gitignore @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/Resources/download/.gitignore b/Resources/download/.gitignore new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/Resources/download/.gitignore @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/Resources/url.txt b/Resources/url.txt new file mode 100644 index 0000000..4dd4f0d --- /dev/null +++ b/Resources/url.txt @@ -0,0 +1 @@ +https://prod-clientpatch.bluearchiveyostar.com/r67_utfwo6vcvx7rhl017phc \ No newline at end of file diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs index c0a2da2..e169066 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Account.cs @@ -1,8 +1,8 @@ using SCHALE.Common.Database; +using SCHALE.Common.Database.ModelExtensions; +using SCHALE.Common.FlatData; using SCHALE.Common.NetworkProtocol; using SCHALE.GameServer.Services; -using SCHALE.Common.FlatData; -using SCHALE.Common.Database.ModelExtensions; namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { @@ -12,7 +12,13 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers private readonly SCHALEContext context; private readonly ExcelTableService excelTableService; - public Account(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) + public Account( + IProtocolHandlerFactory protocolHandlerFactory, + ISessionKeyService _sessionKeyService, + SCHALEContext _context, + ExcelTableService _excelTableService + ) + : base(protocolHandlerFactory) { sessionKeyService = _sessionKeyService; context = _context; @@ -24,7 +30,9 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { string[] uidToken = req.EnterTicket.Split(':'); - var account = context.GuestAccounts.SingleOrDefault(x => x.Uid == long.Parse(uidToken[0]) && x.Token == uidToken[1]); + var account = context.GuestAccounts.SingleOrDefault(x => + x.Uid == long.Parse(uidToken[0]) && x.Token == uidToken[1] + ); if (account is null) { @@ -38,7 +46,9 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers return new AccountCheckYostarResponse() { ResultState = 1, - SessionKey = sessionKeyService.Create(account.Uid) ?? new SessionKey() { MxToken = req.EnterTicket } + SessionKey = + sessionKeyService.Create(account.Uid) + ?? new SessionKey() { MxToken = req.EnterTicket } }; } @@ -47,10 +57,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { if (req.SessionKey is null || req.SessionKey.AccountServerId == 0) { - return new ErrorPacket() - { - ErrorCode = WebAPIErrorCode.AccountAuthNotCreated - }; + return new ErrorPacket() { ErrorCode = WebAPIErrorCode.AccountAuthNotCreated }; } else { @@ -69,16 +76,28 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { OpenConditionContent.Cafe, OpenConditionLockReason.StageClear }, { OpenConditionContent.Unit_Growth_Skill, OpenConditionLockReason.None }, { OpenConditionContent.Unit_Growth_LevelUp, OpenConditionLockReason.None }, - { OpenConditionContent.Unit_Growth_Transcendence, OpenConditionLockReason.None }, + { + OpenConditionContent.Unit_Growth_Transcendence, + OpenConditionLockReason.None + }, { OpenConditionContent.WeekDungeon, OpenConditionLockReason.StageClear }, { OpenConditionContent.Arena, OpenConditionLockReason.StageClear }, { OpenConditionContent.Academy, OpenConditionLockReason.StageClear }, { OpenConditionContent.Equip, OpenConditionLockReason.None }, { OpenConditionContent.Item, OpenConditionLockReason.None }, { OpenConditionContent.Mission, OpenConditionLockReason.None }, - { OpenConditionContent.WeekDungeon_Chase, OpenConditionLockReason.StageClear }, - { OpenConditionContent.__Deprecated_WeekDungeon_FindGift, OpenConditionLockReason.None }, - { OpenConditionContent.__Deprecated_WeekDungeon_Blood, OpenConditionLockReason.None }, + { + OpenConditionContent.WeekDungeon_Chase, + OpenConditionLockReason.StageClear + }, + { + OpenConditionContent.__Deprecated_WeekDungeon_FindGift, + OpenConditionLockReason.None + }, + { + OpenConditionContent.__Deprecated_WeekDungeon_Blood, + OpenConditionLockReason.None + }, { OpenConditionContent.Story_Sub, OpenConditionLockReason.None }, { OpenConditionContent.Story_Replay, OpenConditionLockReason.None }, { OpenConditionContent.None, OpenConditionLockReason.None }, @@ -98,24 +117,46 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { OpenConditionContent.Story, OpenConditionLockReason.None }, { OpenConditionContent.Tactic_Speed, OpenConditionLockReason.StageClear }, { OpenConditionContent.Cafe_Invite, OpenConditionLockReason.StageClear }, - { OpenConditionContent.Cafe_Invite_2, OpenConditionLockReason.CafeRank | OpenConditionLockReason.StageClear }, - { OpenConditionContent.EventMiniGame_1, OpenConditionLockReason.StageClear }, + { + OpenConditionContent.Cafe_Invite_2, + OpenConditionLockReason.CafeRank | OpenConditionLockReason.StageClear + }, + { + OpenConditionContent.EventMiniGame_1, + OpenConditionLockReason.StageClear + }, { OpenConditionContent.SchoolDungeon, OpenConditionLockReason.StageClear }, - { OpenConditionContent.TimeAttackDungeon, OpenConditionLockReason.StageClear }, + { + OpenConditionContent.TimeAttackDungeon, + OpenConditionLockReason.StageClear + }, { OpenConditionContent.ShiftingCraft, OpenConditionLockReason.StageClear }, { OpenConditionContent.Tactic_Skip, OpenConditionLockReason.StageClear }, { OpenConditionContent.Mulligan, OpenConditionLockReason.StageClear }, { OpenConditionContent.EventPermanent, OpenConditionLockReason.StageClear }, - { OpenConditionContent.Main_L_1_2, OpenConditionLockReason.ScenarioModeClear }, - { OpenConditionContent.Main_L_1_3, OpenConditionLockReason.ScenarioModeClear }, - { OpenConditionContent.Main_L_1_4, OpenConditionLockReason.ScenarioModeClear }, + { + OpenConditionContent.Main_L_1_2, + OpenConditionLockReason.ScenarioModeClear + }, + { + OpenConditionContent.Main_L_1_3, + OpenConditionLockReason.ScenarioModeClear + }, + { + OpenConditionContent.Main_L_1_4, + OpenConditionLockReason.ScenarioModeClear + }, { OpenConditionContent.EliminateRaid, OpenConditionLockReason.StageClear }, { OpenConditionContent.Cafe_2, OpenConditionLockReason.StageClear }, { OpenConditionContent.MultiFloorRaid, OpenConditionLockReason.StageClear } }, - MissionProgressDBs = [.. context.MissionProgresses.Where(x => x.AccountServerId == account.ServerId)] + MissionProgressDBs = + [ + .. context.MissionProgresses.Where(x => + x.AccountServerId == account.ServerId + ) + ] }; - } } @@ -124,10 +165,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { if (req.SessionKey is null) { - return new ErrorPacket() - { - ErrorCode = WebAPIErrorCode.InvalidSession - }; + return new ErrorPacket() { ErrorCode = WebAPIErrorCode.InvalidSession }; } string[] uidToken = req.SessionKey.MxToken.Split(':'); @@ -137,38 +175,55 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers context.SaveChanges(); // Default items - context.Items.Add(new() - { - AccountServerId = account.ServerId, - UniqueId = 2, - StackCount = 5 - }); + context.Items.Add( + new() + { + AccountServerId = account.ServerId, + UniqueId = 2, + StackCount = 5 + } + ); // Default chars - var defaultCharacters = excelTableService.GetTable().UnPack().DataList; - var newCharacters = defaultCharacters.Select(x => - { - var characterExcel = excelTableService.GetTable().UnPack().DataList.Find(y => y.Id == x.CharacterId); - - return new CharacterDB() + var defaultCharacters = excelTableService + .GetTable() + .UnPack() + .DataList; + var newCharacters = defaultCharacters + .Select(x => { - UniqueId = x.CharacterId, - StarGrade = x.StarGrade, - Level = x.Level, - Exp = x.Exp, - FavorRank = x.FavorRank, - FavorExp = x.FavorExp, - PublicSkillLevel = 1, - ExSkillLevel = x.ExSkillLevel, - PassiveSkillLevel = x.PassiveSkillLevel, - ExtraPassiveSkillLevel = x.ExtraPassiveSkillLevel, - LeaderSkillLevel = x.LeaderSkillLevel, - IsNew = true, - IsLocked = true, - EquipmentServerIds = characterExcel is not null ? characterExcel.EquipmentSlot.Select(x => (long)0).ToList() : [0, 0, 0], - PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } } - }; - }).ToList(); + var characterExcel = excelTableService + .GetTable() + .UnPack() + .DataList.Find(y => y.Id == x.CharacterId); + + return new CharacterDB() + { + UniqueId = x.CharacterId, + StarGrade = x.StarGrade, + Level = x.Level, + Exp = x.Exp, + FavorRank = x.FavorRank, + FavorExp = x.FavorExp, + PublicSkillLevel = 1, + ExSkillLevel = x.ExSkillLevel, + PassiveSkillLevel = x.PassiveSkillLevel, + ExtraPassiveSkillLevel = x.ExtraPassiveSkillLevel, + LeaderSkillLevel = x.LeaderSkillLevel, + IsNew = true, + IsLocked = true, + EquipmentServerIds = characterExcel is not null + ? characterExcel.EquipmentSlot.Select(x => (long)0).ToList() + : [0, 0, 0], + PotentialStats = + { + { 1, 0 }, + { 2, 0 }, + { 3, 0 } + } + }; + }) + .ToList(); account.AddCharacters(context, [.. newCharacters]); context.SaveChanges(); @@ -176,19 +231,26 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers var favCharacter = defaultCharacters.Find(x => x.FavoriteCharacter); if (favCharacter is not null) { - account.RepresentCharacterServerId = (int)newCharacters.First(x => x.UniqueId == favCharacter.CharacterId).ServerId; + account.RepresentCharacterServerId = (int) + newCharacters.First(x => x.UniqueId == favCharacter.CharacterId).ServerId; } if (newCharacters.Count > 0) { - context.Echelons.Add(new() - { - AccountServerId = account.ServerId, - EchelonNumber = 1, - EchelonType = EchelonType.Adventure, - LeaderServerId = newCharacters[0].ServerId, - MainSlotServerIds = newCharacters.Take(3).Select(x => x.ServerId).Append(0).ToList(), - SupportSlotServerIds = [0, 0] - }); + context.Echelons.Add( + new() + { + AccountServerId = account.ServerId, + EchelonNumber = 1, + EchelonType = EchelonType.Adventure, + LeaderServerId = newCharacters[0].ServerId, + MainSlotServerIds = newCharacters + .Take(3) + .Select(x => x.ServerId) + .Append(0) + .ToList(), + SupportSlotServerIds = [0, 0] + } + ); } context.SaveChanges(); @@ -206,17 +268,14 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers account.Nickname = req.Nickname; context.SaveChanges(); - return new AccountNicknameResponse() - { - AccountDB = account - }; - + return new AccountNicknameResponse() { AccountDB = account }; } [ProtocolHandler(Protocol.Account_LoginSync)] public ResponsePacket LoginSyncHandler(AccountLoginSyncRequest req) { var account = sessionKeyService.GetAccount(req.SessionKey); + ArgumentNullException.ThrowIfNull(account); return new AccountLoginSyncResponse() { @@ -224,7 +283,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { AccountCurrencyDB = new AccountCurrencyDB { - AccountLevel = 1, + AccountLevel = 90, AcademyLocationRankSum = 1, CurrencyDict = new Dictionary { @@ -260,23 +319,71 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { CurrencyTypes.AcademyTicket, DateTime.Parse("2024-04-26T19:29:12") }, { CurrencyTypes.ArenaTicket, DateTime.Parse("2024-04-26T19:29:12") }, { CurrencyTypes.RaidTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WeekDungeonChaserATicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WeekDungeonChaserBTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WeekDungeonChaserCTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.SchoolDungeonATicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.SchoolDungeonBTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.SchoolDungeonCTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.TimeAttackDungeonTicket, DateTime.Parse("2024-04-26T19:29:12") }, + { + CurrencyTypes.WeekDungeonChaserATicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WeekDungeonChaserBTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WeekDungeonChaserCTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonATicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonBTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonCTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.TimeAttackDungeonTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, { CurrencyTypes.MasterCoin, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WorldRaidTicketA, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WorldRaidTicketB, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.WorldRaidTicketC, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.ChaserTotalTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.SchoolDungeonTotalTicket, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.EliminateTicketA, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.EliminateTicketB, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.EliminateTicketC, DateTime.Parse("2024-04-26T19:29:12") }, - { CurrencyTypes.EliminateTicketD, DateTime.Parse("2024-04-26T19:29:12") } + { + CurrencyTypes.WorldRaidTicketA, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WorldRaidTicketB, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WorldRaidTicketC, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.ChaserTotalTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonTotalTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.EliminateTicketA, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.EliminateTicketB, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.EliminateTicketC, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.EliminateTicketD, + DateTime.Parse("2024-04-26T19:29:12") + } } } }, @@ -287,10 +394,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers WeaponDBs = [.. account.Weapons], CostumeDBs = [], }, - ItemListResponse = new ItemListResponse() - { - ItemDBs = [.. account.Items], - }, + ItemListResponse = new ItemListResponse() { ItemDBs = [.. account.Items], }, EchelonListResponse = new EchelonListResponse() { @@ -298,7 +402,8 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers }, EventContentPermanentListResponse = new EventContentPermanentListResponse() { - PermanentDBs = [ + PermanentDBs = + [ new() { EventContentId = 900801 }, new() { EventContentId = 900802 }, new() { EventContentId = 900803 }, @@ -327,10 +432,7 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers ClanLoginResponse = new ClanLoginResponse() { - AccountClanMemberDB = new() - { - AccountId = account.ServerId - } + AccountClanMemberDB = new() { AccountId = account.ServerId } }, EliminateRaidLoginResponse = new EliminateRaidLoginResponse() @@ -350,11 +452,15 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers [ProtocolHandler(Protocol.Account_GetTutorial)] public ResponsePacket GetTutorialHandler(AccountGetTutorialRequest req) { - var tutorialIds = context.AccountTutorials.SingleOrDefault(x => x.AccountServerId == sessionKeyService.GetAccount(req.SessionKey).ServerId)?.TutorialIds; + var tutorialIds = context + .AccountTutorials.SingleOrDefault(x => + x.AccountServerId == sessionKeyService.GetAccount(req.SessionKey).ServerId + ) + ?.TutorialIds; return new AccountGetTutorialResponse() { - TutorialIds = tutorialIds ?? [] + TutorialIds = tutorialIds ?? Enumerable.Range(1, 27).Select(i => (long)i).ToList() }; } @@ -362,7 +468,9 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers public ResponsePacket SetTutorialHandler(AccountSetTutorialRequest req) { var account = sessionKeyService.GetAccount(req.SessionKey); - var tutorial = context.AccountTutorials.SingleOrDefault(x => x.AccountServerId == account.ServerId); + var tutorial = context.AccountTutorials.SingleOrDefault(x => + x.AccountServerId == account.ServerId + ); if (tutorial == null) { tutorial = new() @@ -401,45 +509,48 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers [ProtocolHandler(Protocol.Toast_List)] public ResponsePacket ToastListHandler(ToastListRequest req) { - return new ToastListResponse(); } [ProtocolHandler(Protocol.ContentLog_UIOpenStatistics)] - public ResponsePacket ContentLog_UIOpenStatisticsHandler(ContentLogUIOpenStatisticsRequest req) + public ResponsePacket ContentLog_UIOpenStatisticsHandler( + ContentLogUIOpenStatisticsRequest req + ) { - return new ContentLogUIOpenStatisticsResponse(); } [ProtocolHandler(Protocol.Event_RewardIncrease)] public ResponsePacket Event_RewardIncreaseHandler(EventRewardIncreaseRequest req) { - return new EventRewardIncreaseResponse(); } [ProtocolHandler(Protocol.OpenCondition_EventList)] public ResponsePacket OpenCondition_EventListHandler(OpenConditionEventListRequest req) { - return new OpenConditionEventListResponse() { // all open for now ig - StaticOpenConditions = Enum.GetValues(typeof(OpenConditionContent)).Cast().ToDictionary(key => key, key => OpenConditionLockReason.None) + StaticOpenConditions = Enum.GetValues(typeof(OpenConditionContent)) + .Cast() + .ToDictionary(key => key, key => OpenConditionLockReason.None) }; } [ProtocolHandler(Protocol.Notification_EventContentReddotCheck)] - public ResponsePacket Notification_EventContentReddotCheckHandler(NotificationEventContentReddotRequest req) + public ResponsePacket Notification_EventContentReddotCheckHandler( + NotificationEventContentReddotRequest req + ) { return new NotificationEventContentReddotResponse(); } [ProtocolHandler(Protocol.Billing_PurchaseListByYostar)] - public ResponsePacket Billing_PurchaseListByYostarHandler(BillingPurchaseListByYostarRequest req) + public ResponsePacket Billing_PurchaseListByYostarHandler( + BillingPurchaseListByYostarRequest req + ) { - return new BillingPurchaseListByYostarResponse(); } @@ -461,5 +572,4 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers return new MiniGameMissionListResponse(); } } - } diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Arena.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Arena.cs new file mode 100644 index 0000000..979f801 --- /dev/null +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Arena.cs @@ -0,0 +1,327 @@ +using SCHALE.Common.Database; +using SCHALE.Common.FlatData; +using SCHALE.Common.NetworkProtocol; +using SCHALE.GameServer.Services; + +namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers +{ + public class Arena( + IProtocolHandlerFactory protocolHandlerFactory, + ISessionKeyService _sessionKeyService, + SCHALEContext _context + ) : ProtocolHandlerBase(protocolHandlerFactory) + { + private readonly ISessionKeyService sessionKeyService = _sessionKeyService; + private readonly SCHALEContext context = _context; + + private EquipmentDB? GetEquipmentDB(long accountServerId, long equipmentServerId) + { + if (equipmentServerId == 0) + return null; + return context.Equipment.First(c => + c.AccountServerId == accountServerId && c.ServerId == equipmentServerId + ); + } + + private ArenaCharacterDB? Convert(long accountServerId, long characterServerId) + { + if (characterServerId == 0) + return null; + var characterDB = context.Characters.First(c => + c.AccountServerId == accountServerId && c.ServerId == characterServerId + ); + return Convert(characterDB); + } + + private ArenaCharacterDB Convert(CharacterDB db) + { + var res = new ArenaCharacterDB + { + UniqueId = db.UniqueId, + StarGrade = db.StarGrade, + Level = db.Level, + PublicSkillLevel = db.PublicSkillLevel, + ExSkillLevel = db.ExSkillLevel, + PassiveSkillLevel = db.PassiveSkillLevel, + ExtraPassiveSkillLevel = db.ExtraPassiveSkillLevel, + LeaderSkillLevel = db.LeaderSkillLevel, + EquipmentDBs = db + .EquipmentServerIds.Select(i => GetEquipmentDB(db.AccountServerId, i)) + .Where(i => i != null) + .ToList()!, + FavorRankInfo = new Dictionary + { + // TODO: add all + { db.UniqueId, db.FavorRank } + }, + PotentialStats = db.PotentialStats + }; + var weaponDB = context.Weapons.FirstOrDefault(w => + w.AccountServerId == db.AccountServerId && w.BoundCharacterServerId == db.ServerId + ); + if (weaponDB != null) + res.WeaponDB = weaponDB; + var gearDB = context.Gears.FirstOrDefault(w => + w.AccountServerId == db.AccountServerId && w.BoundCharacterServerId == db.ServerId + ); + if (gearDB != null) + res.GearDB = gearDB; + return res; + } + + private ArenaTeamSettingDB Convert(EchelonDB db) + { + var LeaderCharacterId = context + .Characters.First(c => + c.AccountServerId == db.AccountServerId && c.ServerId == db.LeaderServerId + ) + .UniqueId; + + return new ArenaTeamSettingDB() + { + EchelonType = db.EchelonType, + LeaderCharacterId = LeaderCharacterId, + MainCharacters = db + .MainSlotServerIds.Select(i => Convert(db.AccountServerId, i)) + .Where(i => i != null) + .ToList()!, + SupportCharacters = db + .SupportSlotServerIds.Select(i => Convert(db.AccountServerId, i)) + .Where(i => i != null) + .ToList()!, + MapId = 1001, + }; + } + + private static readonly ArenaTeamSettingDB dummyTeam = + new() + { + EchelonType = EchelonType.ArenaDefence, + LeaderCharacterId = 10065, + MainCharacters = + [ + new ArenaCharacterDB() + { + UniqueId = 10065, + StarGrade = 3, + Level = 90, + PublicSkillLevel = 1, + ExSkillLevel = 1, + PassiveSkillLevel = 1, + ExtraPassiveSkillLevel = 1, + LeaderSkillLevel = 1 + } + ], + MapId = 1001, + }; + + private ArenaTeamSettingDB? GetDefense(long accountId) + { + var defense = context.Echelons.FirstOrDefault(e => + e.AccountServerId == accountId + && e.EchelonType == EchelonType.ArenaDefence + && e.EchelonNumber == 1 + && e.ExtensionType == EchelonExtensionType.Base + ); + if (defense == null) + return null; + return Convert(defense); + } + + private static List DummyOpponent(ArenaTeamSettingDB? team) + { + return + [ + new ArenaUserDB() + { + RepresentCharacterUniqueId = 20024, + NickName = "your", + Rank = 2, + Level = 90, + TeamSettingDB = team ?? dummyTeam + }, + new ArenaUserDB() + { + RepresentCharacterUniqueId = 10059, + NickName = "defense", + Rank = 3, + Level = 90, + TeamSettingDB = team ?? dummyTeam + }, + new ArenaUserDB() + { + RepresentCharacterUniqueId = 10065, + NickName = "team", + Rank = 4, + Level = 90, + TeamSettingDB = team ?? dummyTeam + } + ]; + } + + [ProtocolHandler(Protocol.Arena_EnterLobby)] + public ResponsePacket EnterLobbyHandler(ArenaEnterLobbyRequest req) + { + return new ArenaEnterLobbyResponse() + { + ArenaPlayerInfoDB = new() + { + CurrentSeasonId = 6, + PlayerGroupId = 1, + CurrentRank = 1, + SeasonRecord = 1, + AllTimeRecord = 1 + }, + OpponentUserDBs = DummyOpponent(GetDefense(req.AccountId)), + MapId = 1001 + }; + } + + [ProtocolHandler(Protocol.Arena_OpponentList)] + public ResponsePacket OpponentListHandler(ArenaOpponentListRequest req) + { + return new ArenaOpponentListResponse() + { + PlayerRank = 1, + OpponentUserDBs = DummyOpponent(GetDefense(req.AccountId)) + }; + } + + [ProtocolHandler(Protocol.Arena_SyncEchelonSettingTime)] + public ResponsePacket SyncEchelonSettingTimeHandler(ArenaSyncEchelonSettingTimeRequest req) + { + return new ArenaSyncEchelonSettingTimeResponse() { EchelonSettingTime = DateTime.Now }; + } + + [ProtocolHandler(Protocol.Arena_EnterBattlePart1)] + public ResponsePacket EnterBattlePart1Handler(ArenaEnterBattlePart1Request req) + { + var attack = context.Echelons.First(e => + e.AccountServerId == req.AccountId + && e.EchelonType == EchelonType.ArenaAttack + && e.EchelonNumber == 1 + && e.ExtensionType == EchelonExtensionType.Base + ); + + ArenaUserDB arenaUserDB = + new() + { + RepresentCharacterUniqueId = 10059, + NickName = "You", + Rank = 1, + Level = 90, + TeamSettingDB = Convert(attack) + }; + return new ArenaEnterBattlePart1Response() + { + ArenaBattleDB = new() + { + Season = 6, + Group = 1, + BattleStartTime = DateTime.Now, + Seed = 1, + AttackingUserDB = arenaUserDB, + DefendingUserDB = DummyOpponent(GetDefense(req.AccountId))[0] + } + }; + } + + [ProtocolHandler(Protocol.Arena_EnterBattlePart2)] + public ResponsePacket EnterBattlePart2Handler(ArenaEnterBattlePart2Request req) + { + return new ArenaEnterBattlePart2Response() + { + ArenaBattleDB = req.ArenaBattleDB, + ArenaPlayerInfoDB = new ArenaPlayerInfoDB() + { + CurrentSeasonId = 6, + PlayerGroupId = 1, + CurrentRank = 1, + SeasonRecord = 1, + AllTimeRecord = 1 + }, + AccountCurrencyDB = new AccountCurrencyDB + { + AccountLevel = 90, + AcademyLocationRankSum = 1, + CurrencyDict = new Dictionary + { + { CurrencyTypes.Gem, long.MaxValue }, // gacha currency 600 + { CurrencyTypes.GemPaid, 0 }, + { CurrencyTypes.GemBonus, long.MaxValue }, // default blue gem? + { CurrencyTypes.Gold, 962_350_000 }, // credit 10,000 + { CurrencyTypes.ActionPoint, long.MaxValue }, // energy 24 + { CurrencyTypes.AcademyTicket, 3 }, + { CurrencyTypes.ArenaTicket, 5 }, + { CurrencyTypes.RaidTicket, 3 }, + { CurrencyTypes.WeekDungeonChaserATicket, 0 }, + { CurrencyTypes.WeekDungeonChaserBTicket, 0 }, + { CurrencyTypes.WeekDungeonChaserCTicket, 0 }, + { CurrencyTypes.SchoolDungeonATicket, 0 }, + { CurrencyTypes.SchoolDungeonBTicket, 0 }, + { CurrencyTypes.SchoolDungeonCTicket, 0 }, + { CurrencyTypes.TimeAttackDungeonTicket, 3 }, + { CurrencyTypes.MasterCoin, 0 }, + { CurrencyTypes.WorldRaidTicketA, 40 }, + { CurrencyTypes.WorldRaidTicketB, 40 }, + { CurrencyTypes.WorldRaidTicketC, 40 }, + { CurrencyTypes.ChaserTotalTicket, 6 }, + { CurrencyTypes.SchoolDungeonTotalTicket, 6 }, + { CurrencyTypes.EliminateTicketA, 1 }, + { CurrencyTypes.EliminateTicketB, 1 }, + { CurrencyTypes.EliminateTicketC, 1 }, + { CurrencyTypes.EliminateTicketD, 1 } + }, + UpdateTimeDict = new Dictionary + { + { CurrencyTypes.ActionPoint, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.AcademyTicket, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.ArenaTicket, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.RaidTicket, DateTime.Parse("2024-04-26T19:29:12") }, + { + CurrencyTypes.WeekDungeonChaserATicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WeekDungeonChaserBTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.WeekDungeonChaserCTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonATicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonBTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.SchoolDungeonCTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { + CurrencyTypes.TimeAttackDungeonTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { CurrencyTypes.MasterCoin, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.WorldRaidTicketA, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.WorldRaidTicketB, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.WorldRaidTicketC, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.ChaserTotalTicket, DateTime.Parse("2024-04-26T19:29:12") }, + { + CurrencyTypes.SchoolDungeonTotalTicket, + DateTime.Parse("2024-04-26T19:29:12") + }, + { CurrencyTypes.EliminateTicketA, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.EliminateTicketB, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.EliminateTicketC, DateTime.Parse("2024-04-26T19:29:12") }, + { CurrencyTypes.EliminateTicketD, DateTime.Parse("2024-04-26T19:29:12") } + } + } + }; + } + } +} diff --git a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs index ecfcaee..8a286e1 100644 --- a/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs +++ b/SCHALE.GameServer/Controllers/Api/ProtocolHandlers/Echelon.cs @@ -1,4 +1,5 @@ -using SCHALE.Common.Database; +using Microsoft.EntityFrameworkCore; +using SCHALE.Common.Database; using SCHALE.Common.Database.ModelExtensions; using SCHALE.Common.FlatData; using SCHALE.Common.NetworkProtocol; @@ -6,37 +7,36 @@ using SCHALE.GameServer.Services; namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers { - public class Echelon : ProtocolHandlerBase + public class Echelon( + IProtocolHandlerFactory protocolHandlerFactory, + ISessionKeyService _sessionKeyService, + SCHALEContext _context, + ExcelTableService _excelTableService, + ILogger _logger + ) : ProtocolHandlerBase(protocolHandlerFactory) { - private readonly ISessionKeyService sessionKeyService; - private readonly SCHALEContext context; - private readonly ExcelTableService excelTableService; - - public Echelon(IProtocolHandlerFactory protocolHandlerFactory, ISessionKeyService _sessionKeyService, SCHALEContext _context, ExcelTableService _excelTableService) : base(protocolHandlerFactory) - { - sessionKeyService = _sessionKeyService; - context = _context; - excelTableService = _excelTableService; - } + private readonly ISessionKeyService sessionKeyService = _sessionKeyService; + private readonly SCHALEContext context = _context; + private readonly ExcelTableService excelTableService = _excelTableService; + private readonly ILogger logger = _logger; [ProtocolHandler(Protocol.Echelon_List)] public ResponsePacket ListHandler(EchelonListRequest req) { var account = sessionKeyService.GetAccount(req.SessionKey); - return new EchelonListResponse() - { - EchelonDBs = account.Echelons.ToList() - }; + return new EchelonListResponse() { EchelonDBs = [.. account.Echelons] }; } [ProtocolHandler(Protocol.Echelon_Save)] public ResponsePacket SaveHandler(EchelonSaveRequest req) { - return new EchelonSaveResponse() - { - EchelonDB = req.EchelonDB, - }; + var db = req.EchelonDB; + + context.Echelons.Add(db); + context.SaveChanges(); + + return new EchelonSaveResponse() { EchelonDB = req.EchelonDB, }; } } } diff --git a/SCHALE.GameServer/Controllers/Data/DataController.cs b/SCHALE.GameServer/Controllers/Data/DataController.cs new file mode 100644 index 0000000..ef0cc09 --- /dev/null +++ b/SCHALE.GameServer/Controllers/Data/DataController.cs @@ -0,0 +1,81 @@ +using Microsoft.AspNetCore.Mvc; +using SCHALE.Common.Crypto; +using SCHALE.Common.NetworkProtocol; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace SCHALE.GameServer.Controllers.Data +{ + [ApiController] + [Route("/data")] + public class DataController : ControllerBase + { + + private readonly string absFolder; + private readonly ILogger logger; + public DataController(ILogger _logger) + { + logger = _logger; + + var folder = Path.GetDirectoryName(AppContext.BaseDirectory); + string dataFolder; + while (true) + { + dataFolder = Path.Join(folder, "Resources/data"); + if (Directory.Exists(dataFolder)) break; + folder = Path.GetDirectoryName(folder); + if (folder == null) + throw new FileNotFoundException($"Excel folder is not found."); + } + absFolder = dataFolder; + } + + + string? AbsPath(string relPath) + { + string filePath = Path.Combine(absFolder, relPath); + if (!System.IO.File.Exists(filePath)) return null; + logger.LogDebug($"Use our own {relPath}."); + return filePath; + } + + [HttpGet("TableBundles/{fileName}")] + public IActionResult GetTableBundles(string fileName) + { + string relPath = $"TableBundles/{fileName}"; + string? filePath = AbsPath(relPath); + if (filePath == null) return CatchAll(relPath); + + if (fileName.EndsWith(".json")) + { + var jsonContent = System.IO.File.ReadAllText(filePath); + return Content(jsonContent, "application/json"); + } + if (fileName.EndsWith(".zip")) + { + var fileStream = System.IO.File.OpenRead(filePath); + return File(fileStream, "application/zip", fileName); + } + if (fileName.EndsWith(".bytes")) + { + var fileStream = System.IO.File.OpenRead(filePath); + return File(fileStream, "application/octet-stream", fileName); + } + return CatchAll(relPath); + } + + [HttpGet("{*catchAll}")] + public IActionResult CatchAll(string catchAll) + { + logger.LogDebug("Data path: {path}", catchAll); + string re = $"https://prod-clientpatch.bluearchiveyostar.com/r68_10iazxytt13razwn7x9n_3/{catchAll}"; + return Redirect(re); + // return RedirectPermanent(re); + } + } +} diff --git a/SCHALE.GameServer/GameServer.cs b/SCHALE.GameServer/GameServer.cs index 777eb7f..2992010 100644 --- a/SCHALE.GameServer/GameServer.cs +++ b/SCHALE.GameServer/GameServer.cs @@ -1,35 +1,48 @@ -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Serilog.Events; -using Serilog; +using System.Collections; +using System.Net.NetworkInformation; using System.Reflection; +using System.Text; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.EntityFrameworkCore; +using SCHALE.Common.Crypto; using SCHALE.Common.Database; +using SCHALE.GameServer.Commands; using SCHALE.GameServer.Controllers.Api.ProtocolHandlers; using SCHALE.GameServer.Services; -using Microsoft.EntityFrameworkCore; using SCHALE.GameServer.Services.Irc; -using SCHALE.GameServer.Commands; using SCHALE.GameServer.Utils; -using System.Net.NetworkInformation; +using Serilog; +using Serilog.Events; namespace SCHALE.GameServer { public class GameServer { - public static void Main(string[] args) + public static async Task Main(string[] args) { var config = new ConfigurationBuilder() .SetBasePath(Path.GetDirectoryName(AppContext.BaseDirectory)!) .AddJsonFile("appsettings.json") - .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true) + .AddJsonFile( + $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", + true + ) .AddJsonFile("appsettings.Local.json", true) .Build(); { - var logFilePath = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory)!, "logs", "log.txt"); + var logFilePath = Path.Combine( + Path.GetDirectoryName(AppContext.BaseDirectory)!, + "logs", + "log.txt" + ); if (File.Exists(logFilePath)) { - var prevLogFilePath = Path.Combine(Path.GetDirectoryName(logFilePath)!, "log-prev.txt"); + var prevLogFilePath = Path.Combine( + Path.GetDirectoryName(logFilePath)!, + "log-prev.txt" + ); if (File.Exists(prevLogFilePath)) File.Delete(prevLogFilePath); @@ -37,15 +50,22 @@ namespace SCHALE.GameServer } Log.Logger = new LoggerConfiguration() - .WriteTo.Console() - .WriteTo.File(logFilePath, restrictedToMinimumLevel: LogEventLevel.Verbose, shared: true) - .ReadFrom.Configuration(config) - .CreateBootstrapLogger(); + .WriteTo.Console() + .WriteTo.File( + logFilePath, + restrictedToMinimumLevel: LogEventLevel.Verbose, + shared: true + ) + .ReadFrom.Configuration(config) + .CreateBootstrapLogger(); } Log.Information("Starting..."); try { + Log.Information("Downloading Excels..."); + await ExcelTableService.Init(); + // Load Commands CommandFactory.LoadCommands(); @@ -54,17 +74,36 @@ namespace SCHALE.GameServer if (Config.Instance.Address == "127.0.0.1") { - Config.Instance.Address = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback && i.OperationalStatus == OperationalStatus.Up).First().GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).First().Address.ToString(); + Config.Instance.Address = NetworkInterface + .GetAllNetworkInterfaces() + .Where(i => + i.NetworkInterfaceType != NetworkInterfaceType.Loopback + && i.OperationalStatus == OperationalStatus.Up + ) + .First() + .GetIPProperties() + .UnicastAddresses.Where(a => + a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork + ) + .First() + .Address.ToString(); Config.Save(); } var builder = WebApplication.CreateBuilder(args); - builder.Services.Configure(op => op.AllowSynchronousIO = true); + builder.Services.Configure(op => + op.AllowSynchronousIO = true + ); builder.Host.UseSerilog(); // Add services to the container. - builder.Services.AddSQLServerProvider(config.GetConnectionString("SQLServer") ?? throw new ArgumentNullException("ConnectionStrings/SQLServer in appsettings is missing")); + builder.Services.AddSQLServerProvider( + config.GetConnectionString("SQLServer") + ?? throw new ArgumentNullException( + "ConnectionStrings/SQLServer in appsettings is missing" + ) + ); builder.Services.AddControllers(); builder.Services.AddProtocolHandlerFactory(); builder.Services.AddMemorySessionKeyService(); @@ -72,8 +111,11 @@ namespace SCHALE.GameServer builder.Services.AddIrcService(); // Add all Handler Groups - var handlerGroups = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(ProtocolHandlerBase))); - + var handlerGroups = Assembly + .GetExecutingAssembly() + .GetTypes() + .Where(t => t.IsSubclassOf(typeof(ProtocolHandlerBase))); + foreach (var handlerGroup in handlerGroups) builder.Services.AddProtocolHandlerGroupByType(handlerGroup); diff --git a/SCHALE.GameServer/SCHALE.GameServer.csproj b/SCHALE.GameServer/SCHALE.GameServer.csproj index 8fd2e70..d9be2df 100644 --- a/SCHALE.GameServer/SCHALE.GameServer.csproj +++ b/SCHALE.GameServer/SCHALE.GameServer.csproj @@ -7,6 +7,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/SCHALE.GameServer/Services/ExcelTableService.cs b/SCHALE.GameServer/Services/ExcelTableService.cs index af728f8..3d63def 100644 --- a/SCHALE.GameServer/Services/ExcelTableService.cs +++ b/SCHALE.GameServer/Services/ExcelTableService.cs @@ -1,18 +1,79 @@ -using Google.FlatBuffers; -using SCHALE.Common.Crypto; +using System.IO; +using System.Net.Http; using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Google.FlatBuffers; +using Ionic.Zip; +using SCHALE.Common.Crypto; +using Serilog; namespace SCHALE.GameServer.Services { // TODO: High priority, cache UnPack-ed table! - public class ExcelTableService + public class ExcelTableService(ILogger _logger) { - private readonly ILogger logger; + private readonly ILogger logger = _logger; private readonly Dictionary caches = []; - public ExcelTableService(ILogger _logger) + private static string? ResourcesFolder; + private static string? ExcelFolder; + + private static string GetUrl() { - logger = _logger; + string urlPath; + if (ResourcesFolder == null) + { + var folder = Path.GetDirectoryName(AppContext.BaseDirectory); + while (true) + { + urlPath = Path.Join(folder, "Resources/url.txt"); + if (File.Exists(urlPath)) + break; + folder = Path.GetDirectoryName(folder); + if (folder == null) + throw new FileNotFoundException($"Resources folder is not found."); + } + ResourcesFolder = Path.GetDirectoryName(urlPath); + } + else + { + urlPath = Path.Join(ResourcesFolder, "url.txt"); + } + string url = File.ReadAllText(urlPath); + return url + "/"; + } + + private static async Task GetZip() + { + + string url = GetUrl(); + string filePath = "TableBundles/Excel.zip"; + string zipPath = Path.Combine(ResourcesFolder!, "download", filePath); + + ExcelFolder = zipPath[..^4]; + if (File.Exists(zipPath)) + return; + Directory.CreateDirectory(Path.GetDirectoryName(zipPath)!); + + using HttpClient client = new(); + HttpResponseMessage response = await client.GetAsync(url + filePath); + response.EnsureSuccessStatusCode(); + byte[] content = await response.Content.ReadAsByteArrayAsync(); + File.WriteAllBytes(zipPath, content); + using ZipFile zip = ZipFile.Read(zipPath); + //zip.Password = "/wy5f3hIGGXLOIUDS9DZ"; + zip.Password = Convert.ToBase64String(TableService.CreatePassword(Path.GetFileName(filePath))); + + foreach (ZipEntry e in zip) + { + e.Extract(ExcelFolder, ExtractExistingFileAction.OverwriteSilently); + } + } + + public static async Task Init() + { + await GetZip(); } /// @@ -21,14 +82,16 @@ namespace SCHALE.GameServer.Services /// /// /// - public T GetTable() where T : IFlatbufferObject + public T GetTable() + where T : IFlatbufferObject { var type = typeof(T); if (caches.TryGetValue(type, out var cache)) return (T)cache; - var bytesFilePath = Path.Join(Path.GetDirectoryName(AppContext.BaseDirectory), "Resources/excel/", $"{type.Name.ToLower()}.bytes"); + ArgumentNullException.ThrowIfNull(ExcelFolder); + var bytesFilePath = Path.Join(ExcelFolder, $"{type.Name.ToLower()}.bytes"); if (!File.Exists(bytesFilePath)) { throw new FileNotFoundException($"bytes files for {type.Name} not found"); @@ -36,7 +99,12 @@ namespace SCHALE.GameServer.Services var bytes = File.ReadAllBytes(bytesFilePath); TableEncryptionService.XOR(type.Name, bytes); - var inst = type.GetMethod($"GetRootAs{type.Name}", BindingFlags.Static | BindingFlags.Public, [typeof(ByteBuffer)])!.Invoke(null, [new ByteBuffer(bytes)]); + var inst = type.GetMethod( + $"GetRootAs{type.Name}", + BindingFlags.Static | BindingFlags.Public, + [typeof(ByteBuffer)] + )! + .Invoke(null, [new ByteBuffer(bytes)]); caches.Add(type, inst!); logger.LogDebug("{Excel} loaded and cached", type.Name); diff --git a/SCHALE.GameServer/Utils/InventoryUtils.cs b/SCHALE.GameServer/Utils/InventoryUtils.cs index bdd7311..3d4ef86 100644 --- a/SCHALE.GameServer/Utils/InventoryUtils.cs +++ b/SCHALE.GameServer/Utils/InventoryUtils.cs @@ -79,8 +79,8 @@ namespace SCHALE.Common.Utils UniqueId = x.UniqueId, BoundCharacterServerId = x.ServerId, IsLocked = false, - StarGrade = 5, - Level = 200 + StarGrade = 3, + Level = 50 }; }); @@ -132,17 +132,17 @@ namespace SCHALE.Common.Utils { UniqueId = characterId, StarGrade = 5, - Level = 200, + Level = 90, Exp = 0, PublicSkillLevel = 10, ExSkillLevel = 5, PassiveSkillLevel = 10, ExtraPassiveSkillLevel = 10, LeaderSkillLevel = 1, - FavorRank = 500, + FavorRank = 20, IsNew = true, IsLocked = true, - PotentialStats = { { 1, 25 }, { 2, 25 }, { 3, 25 } }, + PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } }, EquipmentServerIds = [0, 0, 0] }; } diff --git a/ba.js b/ba.js new file mode 100644 index 0000000..1904bcf --- /dev/null +++ b/ba.js @@ -0,0 +1,4535 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { + Il2Cpp.trace().classes(Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class("UnityEngine.Debug")).filterMethods(x => x.name.includes("Log")).and().attach('detailed') + + Interceptor.attach(Il2Cpp.Domain.assembly("Airisdk").image.class("Airisdk.AiriSdkData").method("get_Instance").virtualAddress, { + onEnter(args) { + Il2Cpp.perform(() => { + console.log("Setting SDK values"); + const sdkConfig = Il2Cpp.Domain.assembly("Airisdk").image.class("Airisdk.AiriSdkData").method("get_Instance").invoke().field("m_config").value; + if (sdkConfig) { + sdkConfig.method("set_TestURL").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}`)); + sdkConfig.method("set_ReleaseURL").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}`)); + sdkConfig.method("set_SDK_URL").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}`)); + + } + }) + }, + }); + + Il2Cpp.Domain.assembly("BlueArchive").image.class("ServerInfoData").method("GetConnectionGroup").implementation = function (...args) { + const Conn = this.method("GetConnectionGroup").invoke(...args); + Conn.method("set_GatewayUrl").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}/api/`)); + Conn.method("set_ApiUrl").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}/api/`)); + Conn.method("set_ProhibitedWordBlackListUri").invoke(Il2Cpp.String.from("")); + Conn.method("set_ProhibitedWordBlackListUri").invoke(Il2Cpp.String.from("")); + const acur = Conn.method("get_AddressablesCatalogUrlRoot").invoke(); + console.log("AddressablesCatalogUrlRoot: " + acur); + Conn.method("set_AddressablesCatalogUrlRoot").invoke(Il2Cpp.String.from(`http://${SERVER_ADDRESS}/data`)); + + return Conn; + } + + Il2Cpp.Domain.assembly("BlueArchive").image.class("MX.GameLogic.Service.ProhibitedWordService").method("IsAllowed").implementation = function (...args) { + return true + } + }) + + break + } +} +},{"frida-il2cpp-bridge":30}],2:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +; +function cache(target, name, descriptor) { + var getter = descriptor.get; + if (!getter) + throw new TypeError("Getter property descriptor expected"); + descriptor.get = function () { + var value = getter.call(this); + Object.defineProperty(this, name, { + configurable: descriptor.configurable, + enumerable: descriptor.enumerable, + writable: false, + value: value + }); + return value; + }; +} +exports.cache = cache; + +},{}],3:[function(require,module,exports){ +"use strict"; +exports.__esModule = true; +exports.distance = exports.closest = void 0; +var peq = new Uint32Array(0x10000); +var myers_32 = function (a, b) { + var n = a.length; + var m = b.length; + var lst = 1 << (n - 1); + var pv = -1; + var mv = 0; + var sc = n; + var i = n; + while (i--) { + peq[a.charCodeAt(i)] |= 1 << i; + } + for (i = 0; i < m; i++) { + var eq = peq[b.charCodeAt(i)]; + var xv = eq | mv; + eq |= ((eq & pv) + pv) ^ pv; + mv |= ~(eq | pv); + pv &= eq; + if (mv & lst) { + sc++; + } + if (pv & lst) { + sc--; + } + mv = (mv << 1) | 1; + pv = (pv << 1) | ~(xv | mv); + mv &= xv; + } + i = n; + while (i--) { + peq[a.charCodeAt(i)] = 0; + } + return sc; +}; +var myers_x = function (b, a) { + var n = a.length; + var m = b.length; + var mhc = []; + var phc = []; + var hsize = Math.ceil(n / 32); + var vsize = Math.ceil(m / 32); + for (var i = 0; i < hsize; i++) { + phc[i] = -1; + mhc[i] = 0; + } + var j = 0; + for (; j < vsize - 1; j++) { + var mv_1 = 0; + var pv_1 = -1; + var start_1 = j * 32; + var vlen_1 = Math.min(32, m) + start_1; + for (var k = start_1; k < vlen_1; k++) { + peq[b.charCodeAt(k)] |= 1 << k; + } + for (var i = 0; i < n; i++) { + var eq = peq[a.charCodeAt(i)]; + var pb = (phc[(i / 32) | 0] >>> i) & 1; + var mb = (mhc[(i / 32) | 0] >>> i) & 1; + var xv = eq | mv_1; + var xh = ((((eq | mb) & pv_1) + pv_1) ^ pv_1) | eq | mb; + var ph = mv_1 | ~(xh | pv_1); + var mh = pv_1 & xh; + if ((ph >>> 31) ^ pb) { + phc[(i / 32) | 0] ^= 1 << i; + } + if ((mh >>> 31) ^ mb) { + mhc[(i / 32) | 0] ^= 1 << i; + } + ph = (ph << 1) | pb; + mh = (mh << 1) | mb; + pv_1 = mh | ~(xv | ph); + mv_1 = ph & xv; + } + for (var k = start_1; k < vlen_1; k++) { + peq[b.charCodeAt(k)] = 0; + } + } + var mv = 0; + var pv = -1; + var start = j * 32; + var vlen = Math.min(32, m - start) + start; + for (var k = start; k < vlen; k++) { + peq[b.charCodeAt(k)] |= 1 << k; + } + var score = m; + for (var i = 0; i < n; i++) { + var eq = peq[a.charCodeAt(i)]; + var pb = (phc[(i / 32) | 0] >>> i) & 1; + var mb = (mhc[(i / 32) | 0] >>> i) & 1; + var xv = eq | mv; + var xh = ((((eq | mb) & pv) + pv) ^ pv) | eq | mb; + var ph = mv | ~(xh | pv); + var mh = pv & xh; + score += (ph >>> (m - 1)) & 1; + score -= (mh >>> (m - 1)) & 1; + if ((ph >>> 31) ^ pb) { + phc[(i / 32) | 0] ^= 1 << i; + } + if ((mh >>> 31) ^ mb) { + mhc[(i / 32) | 0] ^= 1 << i; + } + ph = (ph << 1) | pb; + mh = (mh << 1) | mb; + pv = mh | ~(xv | ph); + mv = ph & xv; + } + for (var k = start; k < vlen; k++) { + peq[b.charCodeAt(k)] = 0; + } + return score; +}; +var distance = function (a, b) { + if (a.length < b.length) { + var tmp = b; + b = a; + a = tmp; + } + if (b.length === 0) { + return a.length; + } + if (a.length <= 32) { + return myers_32(a, b); + } + return myers_x(a, b); +}; +exports.distance = distance; +var closest = function (str, arr) { + var min_distance = Infinity; + var min_index = 0; + for (var i = 0; i < arr.length; i++) { + var dist = distance(str, arr[i]); + if (dist < min_distance) { + min_distance = dist; + min_index = i; + } + } + return arr[min_index]; +}; +exports.closest = closest; + +},{}],4:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const versioning_1 = __importDefault(require("versioning")); +const console_1 = require("../utils/console"); +class Il2CppApi { + constructor() { } + static get _alloc() { + return this.r("il2cpp_alloc", "pointer", ["size_t"]); + } + static get _arrayGetElements() { + return this.r("il2cpp_array_get_elements", "pointer", ["pointer"]); + } + static get _arrayGetLength() { + return this.r("il2cpp_array_length", "uint32", ["pointer"]); + } + static get _arrayNew() { + return this.r("il2cpp_array_new", "pointer", ["pointer", "uint32"]); + } + static get _assemblyGetImage() { + return this.r("il2cpp_assembly_get_image", "pointer", ["pointer"]); + } + static get _classForEach() { + return this.r("il2cpp_class_for_each", "void", ["pointer", "pointer"]); + } + static get _classFromName() { + return this.r("il2cpp_class_from_name", "pointer", ["pointer", "pointer", "pointer"]); + } + static get _classFromSystemType() { + return this.r("il2cpp_class_from_system_type", "pointer", ["pointer"]); + } + static get _classFromType() { + return this.r("il2cpp_class_from_type", "pointer", ["pointer"]); + } + static get _classGetActualInstanceSize() { + return this.r("il2cpp_class_get_actual_instance_size", "int32", ["pointer"]); + } + static get _classGetArrayClass() { + return this.r("il2cpp_array_class_get", "pointer", ["pointer", "uint32"]); + } + static get _classGetArrayElementSize() { + return this.r("il2cpp_class_array_element_size", "int", ["pointer"]); + } + static get _classGetAssemblyName() { + return this.r("il2cpp_class_get_assemblyname", "pointer", ["pointer"]); + } + static get _classGetBaseType() { + return this.r("il2cpp_class_enum_basetype", "pointer", ["pointer"]); + } + static get _classGetDeclaringType() { + return this.r("il2cpp_class_get_declaring_type", "pointer", ["pointer"]); + } + static get _classGetElementClass() { + return this.r("il2cpp_class_get_element_class", "pointer", ["pointer"]); + } + static get _classGetFieldFromName() { + return this.r("il2cpp_class_get_field_from_name", "pointer", ["pointer", "pointer"]); + } + static get _classGetFields() { + return this.r("il2cpp_class_get_fields", "pointer", ["pointer", "pointer"]); + } + static get _classGetFlags() { + return this.r("il2cpp_class_get_flags", "int", ["pointer"]); + } + static get _classGetImage() { + return this.r("il2cpp_class_get_image", "pointer", ["pointer"]); + } + static get _classGetInstanceSize() { + return this.r("il2cpp_class_instance_size", "int32", ["pointer"]); + } + static get _classGetInterfaces() { + return this.r("il2cpp_class_get_interfaces", "pointer", ["pointer", "pointer"]); + } + static get _classGetMethodFromName() { + return this.r("il2cpp_class_get_method_from_name", "pointer", ["pointer", "pointer", "int"]); + } + static get _classGetMethods() { + return this.r("il2cpp_class_get_methods", "pointer", ["pointer", "pointer"]); + } + static get _classGetName() { + return this.r("il2cpp_class_get_name", "pointer", ["pointer"]); + } + static get _classGetNamespace() { + return this.r("il2cpp_class_get_namespace", "pointer", ["pointer"]); + } + static get _classGetNestedClasses() { + return this.r("il2cpp_class_get_nested_types", "pointer", ["pointer", "pointer"]); + } + static get _classGetParent() { + return this.r("il2cpp_class_get_parent", "pointer", ["pointer"]); + } + static get _classGetRank() { + return this.r("il2cpp_class_get_rank", "int", ["pointer"]); + } + static get _classGetStaticFieldData() { + return this.r("il2cpp_class_get_static_field_data", "pointer", ["pointer"]); + } + static get _classGetValueSize() { + return this.r("il2cpp_class_value_size", "int32", ["pointer", "pointer"]); + } + static get _classGetType() { + return this.r("il2cpp_class_get_type", "pointer", ["pointer"]); + } + static get _classHasReferences() { + return this.r("il2cpp_class_has_references", "bool", ["pointer"]); + } + static get _classInit() { + return this.r("il2cpp_runtime_class_init", "void", ["pointer"]); + } + static get _classIsAbstract() { + return this.r("il2cpp_class_is_abstract", "bool", ["pointer"]); + } + static get _classIsAssignableFrom() { + return this.r("il2cpp_class_is_assignable_from", "bool", ["pointer", "pointer"]); + } + static get _classIsBlittable() { + return this.r("il2cpp_class_is_blittable", "bool", ["pointer"]); + } + static get _classIsEnum() { + return this.r("il2cpp_class_is_enum", "bool", ["pointer"]); + } + static get _classIsGeneric() { + return this.r("il2cpp_class_is_generic", "bool", ["pointer"]); + } + static get _classIsInflated() { + return this.r("il2cpp_class_is_inflated", "bool", ["pointer"]); + } + static get _classIsInterface() { + return this.r("il2cpp_class_is_interface", "bool", ["pointer"]); + } + static get _classIsSubclassOf() { + return this.r("il2cpp_class_is_subclass_of", "bool", ["pointer", "pointer", "bool"]); + } + static get _classIsValueType() { + return this.r("il2cpp_class_is_valuetype", "bool", ["pointer"]); + } + static get _domainAssemblyOpen() { + return this.r("il2cpp_domain_assembly_open", "pointer", ["pointer", "pointer"]); + } + static get _domainGet() { + return this.r("il2cpp_domain_get", "pointer", []); + } + static get _domainGetAssemblies() { + return this.r("il2cpp_domain_get_assemblies", "pointer", ["pointer", "pointer"]); + } + static get _fieldGetModifier() { + return this.r("il2cpp_field_get_modifier", "pointer", ["pointer"]); + } + static get _fieldGetClass() { + return this.r("il2cpp_field_get_parent", "pointer", ["pointer"]); + } + static get _fieldGetFlags() { + return this.r("il2cpp_field_get_flags", "int", ["pointer"]); + } + static get _fieldGetName() { + return this.r("il2cpp_field_get_name", "pointer", ["pointer"]); + } + static get _fieldGetOffset() { + return this.r("il2cpp_field_get_offset", "int32", ["pointer"]); + } + static get _fieldGetStaticValue() { + return this.r("il2cpp_field_static_get_value", "void", ["pointer", "pointer"]); + } + static get _fieldGetType() { + return this.r("il2cpp_field_get_type", "pointer", ["pointer"]); + } + static get _fieldIsLiteral() { + return this.r("il2cpp_field_is_literal", "bool", ["pointer"]); + } + static get _fieldIsStatic() { + return this.r("il2cpp_field_is_static", "bool", ["pointer"]); + } + static get _fieldIsThreadStatic() { + return this.r("il2cpp_field_is_thread_static", "bool", ["pointer"]); + } + static get _fieldSetStaticValue() { + return this.r("il2cpp_field_static_set_value", "void", ["pointer", "pointer"]); + } + static get _free() { + return this.r("il2cpp_free", "void", ["pointer"]); + } + static get _gcCollect() { + return this.r("il2cpp_gc_collect", "void", ["int"]); + } + static get _gcCollectALittle() { + return this.r("il2cpp_gc_collect_a_little", "void", []); + } + static get _gcDisable() { + return this.r("il2cpp_gc_disable", "void", []); + } + static get _gcEnable() { + return this.r("il2cpp_gc_enable", "void", []); + } + static get _gcGetHeapSize() { + return this.r("il2cpp_gc_get_heap_size", "int64", []); + } + static get _gcGetMaxTimeSlice() { + return this.r("il2cpp_gc_get_max_time_slice_ns", "int64", []); + } + static get _gcGetUsedSize() { + return this.r("il2cpp_gc_get_used_size", "int64", []); + } + static get _gcHandleGetTarget() { + return this.r("il2cpp_gchandle_get_target", "pointer", ["uint32"]); + } + static get _gcHandleFree() { + return this.r("il2cpp_gchandle_free", "void", ["uint32"]); + } + static get _gcHandleNew() { + return this.r("il2cpp_gchandle_new", "uint32", ["pointer", "bool"]); + } + static get _gcHandleNewWeakRef() { + return this.r("il2cpp_gchandle_new_weakref", "uint32", ["pointer", "bool"]); + } + static get _gcIsDisabled() { + return this.r("il2cpp_gc_is_disabled", "bool", []); + } + static get _gcIsIncremental() { + return this.r("il2cpp_gc_is_incremental", "bool", []); + } + static get _gcSetMaxTimeSlice() { + return this.r("il2cpp_gc_set_max_time_slice_ns", "void", ["int64"]); + } + static get _gcStartIncrementalCollection() { + return this.r("il2cpp_gc_start_incremental_collection", "void", []); + } + static get _gcStartWorld() { + return this.r("il2cpp_start_gc_world", "void", []); + } + static get _gcStopWorld() { + return this.r("il2cpp_stop_gc_world", "void", []); + } + static get _getCorlib() { + return this.r("il2cpp_get_corlib", "pointer", []); + } + static get _imageGetAssembly() { + return this.r("il2cpp_image_get_assembly", "pointer", ["pointer"]); + } + static get _imageGetClass() { + return this.r("il2cpp_image_get_class", "pointer", ["pointer", "uint"]); + } + static get _imageGetClassCount() { + return this.r("il2cpp_image_get_class_count", "uint32", ["pointer"]); + } + static get _imageGetName() { + return this.r("il2cpp_image_get_name", "pointer", ["pointer"]); + } + static get _init() { + return this.r("il2cpp_init", "void", []); + } + static get _livenessAllocateStruct() { + return this.r("il2cpp_unity_liveness_allocate_struct", "pointer", ["pointer", "int", "pointer", "pointer", "pointer"]); + } + static get _livenessCalculationBegin() { + return this.r("il2cpp_unity_liveness_calculation_begin", "pointer", ["pointer", "int", "pointer", "pointer", "pointer", "pointer"]); + } + static get _livenessCalculationEnd() { + return this.r("il2cpp_unity_liveness_calculation_end", "void", ["pointer"]); + } + static get _livenessCalculationFromStatics() { + return this.r("il2cpp_unity_liveness_calculation_from_statics", "void", ["pointer"]); + } + static get _livenessFinalize() { + return this.r("il2cpp_unity_liveness_finalize", "void", ["pointer"]); + } + static get _livenessFreeStruct() { + return this.r("il2cpp_unity_liveness_free_struct", "void", ["pointer"]); + } + static get _memorySnapshotCapture() { + return this.r("il2cpp_capture_memory_snapshot", "pointer", []); + } + static get _memorySnapshotFree() { + return this.r("il2cpp_free_captured_memory_snapshot", "void", ["pointer"]); + } + static get _memorySnapshotGetClasses() { + return this.r("il2cpp_memory_snapshot_get_classes", "pointer", ["pointer", "pointer"]); + } + static get _memorySnapshotGetGCHandles() { + return this.r("il2cpp_memory_snapshot_get_gc_handles", ["uint32", "pointer"], ["pointer"]); + } + static get _memorySnapshotGetRuntimeInformation() { + return this.r("il2cpp_memory_snapshot_get_information", ["uint32", "uint32", "uint32", "uint32", "uint32", "uint32"], ["pointer"]); + } + static get _methodGetModifier() { + return this.r("il2cpp_method_get_modifier", "pointer", ["pointer"]); + } + static get _methodGetClass() { + return this.r("il2cpp_method_get_class", "pointer", ["pointer"]); + } + static get _methodGetFlags() { + return this.r("il2cpp_method_get_flags", "uint32", ["pointer", "pointer"]); + } + static get _methodGetFromReflection() { + return this.r("il2cpp_method_get_from_reflection", "pointer", ["pointer"]); + } + static get _methodGetName() { + return this.r("il2cpp_method_get_name", "pointer", ["pointer"]); + } + static get _methodGetObject() { + return this.r("il2cpp_method_get_object", "pointer", ["pointer", "pointer"]); + } + static get _methodGetParameterCount() { + return this.r("il2cpp_method_get_param_count", "uint8", ["pointer"]); + } + static get _methodGetParameterName() { + return this.r("il2cpp_method_get_param_name", "pointer", ["pointer", "uint32"]); + } + static get _methodGetParameters() { + return this.r("il2cpp_method_get_parameters", "pointer", ["pointer", "pointer"]); + } + static get _methodGetParameterType() { + return this.r("il2cpp_method_get_param", "pointer", ["pointer", "uint32"]); + } + static get _methodGetPointer() { + return this.r("il2cpp_method_get_pointer", "pointer", ["pointer"]); + } + static get _methodGetReturnType() { + return this.r("il2cpp_method_get_return_type", "pointer", ["pointer"]); + } + static get _methodIsExternal() { + return this.r("il2cpp_method_is_external", "bool", ["pointer"]); + } + static get _methodIsGeneric() { + return this.r("il2cpp_method_is_generic", "bool", ["pointer"]); + } + static get _methodIsInflated() { + return this.r("il2cpp_method_is_inflated", "bool", ["pointer"]); + } + static get _methodIsInstance() { + return this.r("il2cpp_method_is_instance", "bool", ["pointer"]); + } + static get _methodIsSynchronized() { + return this.r("il2cpp_method_is_synchronized", "bool", ["pointer"]); + } + static get _monitorEnter() { + return this.r("il2cpp_monitor_enter", "void", ["pointer"]); + } + static get _monitorExit() { + return this.r("il2cpp_monitor_exit", "void", ["pointer"]); + } + static get _monitorPulse() { + return this.r("il2cpp_monitor_pulse", "void", ["pointer"]); + } + static get _monitorPulseAll() { + return this.r("il2cpp_monitor_pulse_all", "void", ["pointer"]); + } + static get _monitorTryEnter() { + return this.r("il2cpp_monitor_try_enter", "bool", ["pointer", "uint32"]); + } + static get _monitorTryWait() { + return this.r("il2cpp_monitor_try_wait", "bool", ["pointer", "uint32"]); + } + static get _monitorWait() { + return this.r("il2cpp_monitor_wait", "void", ["pointer"]); + } + static get _objectGetClass() { + return this.r("il2cpp_object_get_class", "pointer", ["pointer"]); + } + static get _objectGetVirtualMethod() { + return this.r("il2cpp_object_get_virtual_method", "pointer", ["pointer", "pointer"]); + } + static get _objectInit() { + return this.r("il2cpp_runtime_object_init_exception", "void", ["pointer", "pointer"]); + } + static get _objectNew() { + return this.r("il2cpp_object_new", "pointer", ["pointer"]); + } + static get _objectGetSize() { + return this.r("il2cpp_object_get_size", "uint32", ["pointer"]); + } + static get _objectUnbox() { + return this.r("il2cpp_object_unbox", "pointer", ["pointer"]); + } + static get _resolveInternalCall() { + return this.r("il2cpp_resolve_icall", "pointer", ["pointer"]); + } + static get _stringChars() { + return this.r("il2cpp_string_chars", "pointer", ["pointer"]); + } + static get _stringLength() { + return this.r("il2cpp_string_length", "int32", ["pointer"]); + } + static get _stringNew() { + return this.r("il2cpp_string_new", "pointer", ["pointer"]); + } + static get _stringSetLength() { + return this.r("il2cpp_string_set_length", "void", ["pointer", "int32"]); + } + static get _valueBox() { + return this.r("il2cpp_value_box", "pointer", ["pointer", "pointer"]); + } + static get _threadAttach() { + return this.r("il2cpp_thread_attach", "pointer", ["pointer"]); + } + static get _threadCurrent() { + return this.r("il2cpp_thread_current", "pointer", []); + } + static get _threadGetAllAttachedThreads() { + return this.r("il2cpp_thread_get_all_attached_threads", "pointer", ["pointer"]); + } + static get _threadIsVm() { + return this.r("il2cpp_is_vm_thread", "bool", ["pointer"]); + } + static get _threadDetach() { + return this.r("il2cpp_thread_detach", "void", ["pointer"]); + } + static get _typeGetName() { + return this.r("il2cpp_type_get_name", "pointer", ["pointer"]); + } + static get _typeGetObject() { + return this.r("il2cpp_type_get_object", "pointer", ["pointer"]); + } + static get _typeGetTypeEnum() { + return this.r("il2cpp_type_get_type", "int", ["pointer"]); + } + static get _typeIsByReference() { + return this.r("il2cpp_type_is_byref", "bool", ["pointer"]); + } + static get _typeIsPrimitive() { + return this.r("il2cpp_type_is_primitive", "bool", ["pointer"]); + } + /** @internal */ + static get cModule() { + if (versioning_1.default.lt(Il2Cpp.unityVersion, "5.3.0") || versioning_1.default.gte(Il2Cpp.unityVersion, "2022.2.0")) { + (0, console_1.warn)(`current Unity version ${Il2Cpp.unityVersion} is not supported, expect breakage`); + } + const offsetsFinderCModule = new CModule(`\ +#include + +#define OFFSET_OF(name, type) \ + int16_t name (char * p,\ + type e)\ + {\ + for (int16_t i = 0; i < 512; i++) if (* ((type *) p + i) == e) return i;\ + return -1;\ + } + +OFFSET_OF (offset_of_int32, int32_t) +OFFSET_OF (offset_of_pointer, void *) + `); + const offsetOfInt32 = new NativeFunction(offsetsFinderCModule.offset_of_int32, "int16", ["pointer", "int32"]); + const offsetOfPointer = new NativeFunction(offsetsFinderCModule.offset_of_pointer, "int16", ["pointer", "pointer"]); + const SystemString = Il2Cpp.Image.corlib.class("System.String"); + const SystemDateTime = Il2Cpp.Image.corlib.class("System.DateTime"); + const SystemReflectionModule = Il2Cpp.Image.corlib.class("System.Reflection.Module"); + SystemDateTime.initialize(); + SystemReflectionModule.initialize(); + const DaysToMonth365 = (SystemDateTime.tryField("daysmonth") ?? + SystemDateTime.tryField("DaysToMonth365") ?? + SystemDateTime.field("s_daysToMonth365")).value; + const FilterTypeName = SystemReflectionModule.field("FilterTypeName").value; + const FilterTypeNameMethodPointer = FilterTypeName.field("method_ptr").value; + const FilterTypeNameMethod = FilterTypeName.field("method").value; + const source = `\ +#include +#include + + +typedef struct _Il2CppObject Il2CppObject; +typedef enum _Il2CppTypeEnum Il2CppTypeEnum; +typedef struct _Il2CppReflectionMethod Il2CppReflectionMethod; +typedef struct _Il2CppManagedMemorySnapshot Il2CppManagedMemorySnapshot; +typedef struct _Il2CppMetadataType Il2CppMetadataType; + + +struct _Il2CppObject +{ + void * class; + void * monitor; +}; + +enum _Il2CppTypeEnum +{ + IL2CPP_TYPE_END = 0x00, + IL2CPP_TYPE_VOID = 0x01, + IL2CPP_TYPE_BOOLEAN = 0x02, + IL2CPP_TYPE_CHAR = 0x03, + IL2CPP_TYPE_I1 = 0x04, + IL2CPP_TYPE_U1 = 0x05, + IL2CPP_TYPE_I2 = 0x06, + IL2CPP_TYPE_U2 = 0x07, + IL2CPP_TYPE_I4 = 0x08, + IL2CPP_TYPE_U4 = 0x09, + IL2CPP_TYPE_I8 = 0x0a, + IL2CPP_TYPE_U8 = 0x0b, + IL2CPP_TYPE_R4 = 0x0c, + IL2CPP_TYPE_R8 = 0x0d, + IL2CPP_TYPE_STRING = 0x0e, + IL2CPP_TYPE_PTR = 0x0f, + IL2CPP_TYPE_BYREF = 0x10, + IL2CPP_TYPE_VALUETYPE = 0x11, + IL2CPP_TYPE_CLASS = 0x12, + IL2CPP_TYPE_VAR = 0x13, + IL2CPP_TYPE_ARRAY = 0x14, + IL2CPP_TYPE_GENERICINST = 0x15, + IL2CPP_TYPE_TYPEDBYREF = 0x16, + IL2CPP_TYPE_I = 0x18, + IL2CPP_TYPE_U = 0x19, + IL2CPP_TYPE_FNPTR = 0x1b, + IL2CPP_TYPE_OBJECT = 0x1c, + IL2CPP_TYPE_SZARRAY = 0x1d, + IL2CPP_TYPE_MVAR = 0x1e, + IL2CPP_TYPE_CMOD_REQD = 0x1f, + IL2CPP_TYPE_CMOD_OPT = 0x20, + IL2CPP_TYPE_INTERNAL = 0x21, + IL2CPP_TYPE_MODIFIER = 0x40, + IL2CPP_TYPE_SENTINEL = 0x41, + IL2CPP_TYPE_PINNED = 0x45, + IL2CPP_TYPE_ENUM = 0x55 +}; + +struct _Il2CppReflectionMethod +{ + Il2CppObject object; + void * method; + void * name; + void * reftype; +}; + +struct _Il2CppManagedMemorySnapshot +{ + struct Il2CppManagedHeap + { + uint32_t section_count; + void * sections; + } heap; + struct Il2CppStacks + { + uint32_t stack_count; + void * stacks; + } stacks; + struct Il2CppMetadataSnapshot + { + uint32_t type_count; + Il2CppMetadataType * types; + } metadata_snapshot; + struct Il2CppGCHandles + { + uint32_t tracked_object_count; + Il2CppObject ** pointers_to_objects; + } gc_handles; + struct Il2CppRuntimeInformation + { + uint32_t pointer_size; + uint32_t object_header_size; + uint32_t array_header_size; + uint32_t array_bounds_offset_in_header; + uint32_t array_size_offset_in_header; + uint32_t allocation_granularity; + } runtime_information; + void * additional_user_information; +}; + +struct _Il2CppMetadataType +{ + uint32_t flags; + void * fields; + uint32_t field_count; + uint32_t statics_size; + uint8_t * statics; + uint32_t base_or_element_type_index; + char * name; + const char * assembly_name; + uint64_t type_info_address; + uint32_t size; +}; + + +#define THREAD_STATIC_FIELD_OFFSET -1; + +#define FIELD_ATTRIBUTE_FIELD_ACCESS_MASK 0x0007 +#define FIELD_ATTRIBUTE_COMPILER_CONTROLLED 0x0000 +#define FIELD_ATTRIBUTE_PRIVATE 0x0001 +#define FIELD_ATTRIBUTE_FAM_AND_ASSEM 0x0002 +#define FIELD_ATTRIBUTE_ASSEMBLY 0x0003 +#define FIELD_ATTRIBUTE_FAMILY 0x0004 +#define FIELD_ATTRIBUTE_FAM_OR_ASSEM 0x0005 +#define FIELD_ATTRIBUTE_PUBLIC 0x0006 + +#define FIELD_ATTRIBUTE_STATIC 0x0010 +#define FIELD_ATTRIBUTE_LITERAL 0x0040 + +#define METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK 0x0007 +#define METHOD_ATTRIBUTE_COMPILER_CONTROLLED 0x0000 +#define METHOD_ATTRIBUTE_PRIVATE 0x0001 +#define METHOD_ATTRIBUTE_FAM_AND_ASSEM 0x0002 +#define METHOD_ATTRIBUTE_ASSEMBLY 0x0003 +#define METHOD_ATTRIBUTE_FAMILY 0x0004 +#define METHOD_ATTRIBUTE_FAM_OR_ASSEM 0x0005 +#define METHOD_ATTRIBUTE_PUBLIC 0x0006 + +#define METHOD_ATTRIBUTE_STATIC 0x0010 +#define METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL 0x1000 +#define METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED 0x0020 + + +static const char * (*il2cpp_class_get_name) (void *) = (void *) ${this._classGetName}; +static int (*il2cpp_field_get_flags) (void *) = (void *) ${this._fieldGetFlags}; +static size_t (*il2cpp_field_get_offset) (void *) = (void *) ${this._fieldGetOffset}; +static uint32_t (*il2cpp_method_get_flags) (void *, uint32_t *) = (void *) ${this._methodGetFlags}; +static char * (*il2cpp_type_get_name) (void *) = (void *) ${this._typeGetName}; +static Il2CppTypeEnum (*il2cpp_type_get_type_enum) (void *) = (void *) ${this._typeGetTypeEnum}; +static void (*il2cpp_free) (void * pointer) = (void *) ${this._free}; + + +void +il2cpp_string_set_length (int32_t * string, + int32_t length) +{ + *(string + ${offsetOfInt32(Il2Cpp.String.from("vfsfitvnm"), 9)}) = length; +} + +void * +il2cpp_array_get_elements (int32_t * array) +{ + return array + ${offsetOfInt32(DaysToMonth365, 31) - 1}; +} + +uint8_t +il2cpp_type_is_byref (void * type) +{ + char * name; + char last_char; + + name = il2cpp_type_get_name (type); + last_char = name[strlen (name) - 1]; + + il2cpp_free (name); + return last_char == '&'; +} + +uint8_t +il2cpp_type_is_primitive (void * type) +{ + Il2CppTypeEnum type_enum; + + type_enum = il2cpp_type_get_type_enum (type); + + return ((type_enum >= IL2CPP_TYPE_BOOLEAN && + type_enum <= IL2CPP_TYPE_R8) || + type_enum == IL2CPP_TYPE_I || + type_enum == IL2CPP_TYPE_U + ); +} + +int32_t +il2cpp_class_get_actual_instance_size (int32_t * class) +{ + return *(class + ${offsetOfInt32(SystemString, SystemString.instanceSize - 2)}); +} + +uint8_t +il2cpp_class_get_rank (void * class) +{ + uint8_t rank; + const char * name; + + rank = 0; + name = il2cpp_class_get_name (class); + + for (uint16_t i = strlen (name) - 1; i > 0; i--) + { + char c = name[i]; + + if (c == ']') rank++; + else if (c == '[' || rank == 0) break; + else if (c == ',') rank++; + else break; + } + + return rank; +} + +const char * +il2cpp_field_get_modifier (void * field) +{ + int flags; + + flags = il2cpp_field_get_flags (field); + + switch (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) { + case FIELD_ATTRIBUTE_PRIVATE: + return "private"; + case FIELD_ATTRIBUTE_FAM_AND_ASSEM: + return "private protected"; + case FIELD_ATTRIBUTE_ASSEMBLY: + return "internal"; + case FIELD_ATTRIBUTE_FAMILY: + return "protected"; + case FIELD_ATTRIBUTE_FAM_OR_ASSEM: + return "protected internal"; + case FIELD_ATTRIBUTE_PUBLIC: + return "public"; + } + + return ""; +} + +uint8_t +il2cpp_field_is_literal (void * field) +{ + return (il2cpp_field_get_flags (field) & FIELD_ATTRIBUTE_LITERAL) != 0; +} + +uint8_t +il2cpp_field_is_static (void * field) +{ + return (il2cpp_field_get_flags (field) & FIELD_ATTRIBUTE_STATIC) != 0; +} + +uint8_t +il2cpp_field_is_thread_static (void * field) +{ + return il2cpp_field_get_offset (field) == THREAD_STATIC_FIELD_OFFSET; +} + +const char * +il2cpp_method_get_modifier (void * method) +{ + uint32_t flags; + + flags = il2cpp_method_get_flags (method, NULL); + + switch (flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) { + case METHOD_ATTRIBUTE_PRIVATE: + return "private"; + case METHOD_ATTRIBUTE_FAM_AND_ASSEM: + return "private protected"; + case METHOD_ATTRIBUTE_ASSEMBLY: + return "internal"; + case METHOD_ATTRIBUTE_FAMILY: + return "protected"; + case METHOD_ATTRIBUTE_FAM_OR_ASSEM: + return "protected internal"; + case METHOD_ATTRIBUTE_PUBLIC: + return "public"; + } + + return ""; +} + +void * +il2cpp_method_get_from_reflection (const Il2CppReflectionMethod * method) +{ + return method->method; +} + +void * +il2cpp_method_get_pointer (void ** method) +{ + return * (method + ${offsetOfPointer(FilterTypeNameMethod, FilterTypeNameMethodPointer)}); +} + +uint8_t +il2cpp_method_is_external (void * method) +{ + uint32_t implementation_flags; + + il2cpp_method_get_flags (method, &implementation_flags); + + return (implementation_flags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) != 0; +} + +uint8_t +il2cpp_method_is_synchronized (void * method) +{ + uint32_t implementation_flags; + + il2cpp_method_get_flags (method, &implementation_flags); + + return (implementation_flags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) != 0; +} + +uintptr_t +il2cpp_memory_snapshot_get_classes (const Il2CppManagedMemorySnapshot * snapshot, + Il2CppMetadataType ** iter) +{ + const int zero; + const void * null; + + if (iter != NULL && snapshot->metadata_snapshot.type_count > zero) + { + if (*iter == null) + { + *iter = snapshot->metadata_snapshot.types; + return (uintptr_t) (*iter)->type_info_address; + } + else + { + Il2CppMetadataType * metadata_type = *iter + 1; + + if (metadata_type < snapshot->metadata_snapshot.types + snapshot->metadata_snapshot.type_count) + { + *iter = metadata_type; + return (uintptr_t) (*iter)->type_info_address; + } + } + } + return 0; +} + +struct Il2CppGCHandles +il2cpp_memory_snapshot_get_gc_handles (const Il2CppManagedMemorySnapshot * snapshot) +{ + return snapshot->gc_handles; +} + +struct Il2CppRuntimeInformation +il2cpp_memory_snapshot_get_information (const Il2CppManagedMemorySnapshot * snapshot) +{ + return snapshot->runtime_information; +} + `; + offsetsFinderCModule.dispose(); + return new CModule(source); + } + /** @internal */ + static r(exportName, retType, argTypes) { + const exportPointer = Il2Cpp.module.findExportByName(exportName) ?? this.cModule[exportName]; + if (exportPointer == null) { + (0, console_1.raise)(`cannot resolve export ${exportName}`); + } + return new NativeFunction(exportPointer, retType, argTypes); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_alloc", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_arrayGetElements", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_arrayGetLength", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_arrayNew", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_assemblyGetImage", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classForEach", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classFromName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classFromSystemType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classFromType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetActualInstanceSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetArrayClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetArrayElementSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetAssemblyName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetBaseType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetDeclaringType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetElementClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetFieldFromName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetFields", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetFlags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetImage", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetInstanceSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetInterfaces", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetMethodFromName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetMethods", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetNamespace", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetNestedClasses", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetParent", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetRank", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetStaticFieldData", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetValueSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classGetType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classHasReferences", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classInit", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsAbstract", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsAssignableFrom", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsBlittable", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsEnum", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsGeneric", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsInflated", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsInterface", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsSubclassOf", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_classIsValueType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_domainAssemblyOpen", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_domainGet", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_domainGetAssemblies", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetModifier", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetFlags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetOffset", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetStaticValue", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldGetType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldIsLiteral", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldIsStatic", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldIsThreadStatic", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_fieldSetStaticValue", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_free", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcCollect", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcCollectALittle", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcDisable", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcEnable", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcGetHeapSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcGetMaxTimeSlice", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcGetUsedSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcHandleGetTarget", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcHandleFree", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcHandleNew", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcHandleNewWeakRef", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcIsDisabled", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcIsIncremental", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcSetMaxTimeSlice", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcStartIncrementalCollection", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcStartWorld", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_gcStopWorld", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_getCorlib", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_imageGetAssembly", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_imageGetClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_imageGetClassCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_imageGetName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_init", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessAllocateStruct", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessCalculationBegin", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessCalculationEnd", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessCalculationFromStatics", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessFinalize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_livenessFreeStruct", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_memorySnapshotCapture", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_memorySnapshotFree", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_memorySnapshotGetClasses", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_memorySnapshotGetGCHandles", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_memorySnapshotGetRuntimeInformation", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetModifier", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetFlags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetFromReflection", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetObject", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetParameterCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetParameterName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetParameters", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetParameterType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetPointer", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodGetReturnType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodIsExternal", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodIsGeneric", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodIsInflated", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodIsInstance", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_methodIsSynchronized", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorEnter", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorExit", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorPulse", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorPulseAll", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorTryEnter", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorTryWait", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_monitorWait", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectGetClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectGetVirtualMethod", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectInit", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectNew", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectGetSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_objectUnbox", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_resolveInternalCall", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_stringChars", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_stringLength", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_stringNew", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_stringSetLength", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_valueBox", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_threadAttach", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_threadCurrent", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_threadGetAllAttachedThreads", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_threadIsVm", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_threadDetach", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_typeGetName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_typeGetObject", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_typeGetTypeEnum", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_typeIsByReference", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "_typeIsPrimitive", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppApi, "cModule", null); +Il2Cpp.Api = Il2CppApi; + +},{"../utils/console":31,"decorator-cache-getter":2,"versioning":37}],5:[function(require,module,exports){ +(function (setImmediate){(function (){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const versioning_1 = __importDefault(require("versioning")); +const console_1 = require("../utils/console"); +const native_wait_1 = require("../utils/native-wait"); +/** */ +class Il2CppBase { + constructor() { } + /** @internal Gets the Il2Cpp module name. */ + static get moduleName() { + switch (Process.platform) { + case "linux": + try { + const _ = Java.androidVersion; + return "libil2cpp.so"; + } + catch (e) { + return "GameAssembly.so"; + } + case "windows": + return "GameAssembly.dll"; + case "darwin": + try { + return "UnityFramework"; + } + catch (e) { + return "GameAssembly.dylib"; + } + } + (0, console_1.raise)(`${Process.platform} is not supported yet`); + } + /** */ + static get applicationDataPath() { + const get_persistentDataPath = this.internalCall("UnityEngine.Application::get_persistentDataPath", "pointer", []); + return new Il2Cpp.String(get_persistentDataPath()).content; + } + /** */ + static get applicationIdentifier() { + const get_identifier = this.internalCall("UnityEngine.Application::get_identifier", "pointer", []) ?? + this.internalCall("UnityEngine.Application::get_bundleIdentifier", "pointer", []); + return get_identifier ? new Il2Cpp.String(get_identifier()).content : null; + } + /** Gets the version of the application */ + static get applicationVersion() { + const get_version = this.internalCall("UnityEngine.Application::get_version", "pointer", []); + return get_version ? new Il2Cpp.String(get_version()).content : null; + } + /** Gets the attached threads. */ + static get attachedThreads() { + if (Il2Cpp.currentThread == null) { + (0, console_1.raise)("only Il2Cpp threads can invoke Il2Cpp.attachedThreads"); + } + const array = []; + const sizePointer = Memory.alloc(Process.pointerSize); + const startPointer = Il2Cpp.Api._threadGetAllAttachedThreads(sizePointer); + const size = sizePointer.readInt(); + for (let i = 0; i < size; i++) { + array.push(new Il2Cpp.Thread(startPointer.add(i * Process.pointerSize).readPointer())); + } + return array; + } + /** Gets the current attached thread, if any. */ + static get currentThread() { + const handle = Il2Cpp.Api._threadCurrent(); + return handle.isNull() ? null : new Il2Cpp.Thread(handle); + } + /** Gets the Il2Cpp module as a Frida module. */ + static get module() { + return Process.getModuleByName(this.moduleName); + } + /** Gets the Unity version of the current application. */ + static get unityVersion() { + const get_unityVersion = this.internalCall("UnityEngine.Application::get_unityVersion", "pointer", []); + if (get_unityVersion == null) { + (0, console_1.raise)("couldn't determine the Unity version, please specify it manually"); + } + return new Il2Cpp.String(get_unityVersion()).content; + } + /** @internal */ + static get unityVersionIsBelow201830() { + return versioning_1.default.lt(this.unityVersion, "2018.3.0"); + } + /** Allocates the given amount of bytes. */ + static alloc(size = Process.pointerSize) { + return Il2Cpp.Api._alloc(size); + } + /** Dumps the application. */ + static dump(fileName, path) { + fileName = fileName ?? `${Il2Cpp.applicationIdentifier ?? "unknown"}_${Il2Cpp.applicationVersion ?? "unknown"}.cs`; + const destination = `${path ?? Il2Cpp.applicationDataPath}/${fileName}`; + const file = new File(destination, "w"); + for (const assembly of Il2Cpp.Domain.assemblies) { + (0, console_1.inform)(`dumping ${assembly.name}...`); + for (const klass of assembly.image.classes) { + file.write(`${klass}\n\n`); + } + } + file.flush(); + file.close(); + (0, console_1.ok)(`dump saved to ${destination}`); + } + /** Frees memory. */ + static free(pointer) { + return Il2Cpp.Api._free(pointer); + } + /** @internal Waits for Unity and Il2Cpp native libraries to be loaded and initialized. */ + static async initialize() { + if (Process.platform == "darwin") { + let il2cppModuleName = Process.findModuleByAddress(Module.findExportByName(null, "il2cpp_init") ?? NULL)?.name; + if (il2cppModuleName == undefined) { + il2cppModuleName = await (0, native_wait_1.forModule)("UnityFramework", "GameAssembly.dylib"); + } + Reflect.defineProperty(Il2Cpp, "moduleName", { value: il2cppModuleName }); + } + else { + await (0, native_wait_1.forModule)(this.moduleName); + } + if (Il2Cpp.Api._getCorlib().isNull()) { + await new Promise(resolve => { + const interceptor = Interceptor.attach(Il2Cpp.Api._init, { + onLeave() { + interceptor.detach(); + setImmediate(resolve); + } + }); + }); + } + } + /** */ + static installExceptionListener(targetThread = "current") { + const threadId = Process.getCurrentThreadId(); + return Interceptor.attach(Il2Cpp.module.getExportByName("__cxa_throw"), function (args) { + if (targetThread == "current" && this.threadId != threadId) { + return; + } + (0, console_1.inform)(new Il2Cpp.Object(args[0].readPointer())); + }); + } + /** */ + static internalCall(name, retType, argTypes) { + const handle = Il2Cpp.Api._resolveInternalCall(Memory.allocUtf8String(name)); + return handle.isNull() ? null : new NativeFunction(handle, retType, argTypes); + } + /** Schedules a callback on the Il2Cpp initializer thread. */ + static scheduleOnInitializerThread(block) { + return new Promise(resolve => { + const listener = Interceptor.attach(Il2Cpp.Api._threadCurrent, () => { + const currentThreadId = Il2Cpp.currentThread?.id; + if (currentThreadId != undefined && currentThreadId == Il2Cpp.attachedThreads[0].id) { + listener.detach(); + const result = block(); + setImmediate(() => resolve(result)); + } + }); + }); + } + /** Attaches the caller thread to Il2Cpp domain and executes the given block. */ + static async perform(block) { + await this.initialize(); + let thread = this.currentThread; + const isForeignThread = thread == null; + if (thread == null) { + thread = Il2Cpp.Domain.attach(); + } + try { + const result = block(); + return result instanceof Promise ? await result : result; + } + catch (e) { + globalThis.console.log(e); + throw e; + } + finally { + if (isForeignThread) { + thread.detach(); + } + } + } + /** Creates a new `Il2Cpp.Tracer` instance. */ + static trace() { + return new Il2Cpp.Tracer(); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "applicationDataPath", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "applicationIdentifier", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "applicationVersion", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "module", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "unityVersion", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppBase, "unityVersionIsBelow201830", null); +Reflect.set(globalThis, "Il2Cpp", Il2CppBase); + +}).call(this)}).call(this,require("timers").setImmediate) + +},{"../utils/console":31,"../utils/native-wait":33,"decorator-cache-getter":2,"timers":36,"versioning":37}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** Filtering utilities. */ +class Il2CppFiltering { + constructor() { } + /** Creates a filter which includes `element`s whose type can be assigned to `klass` variables. */ + static Is(klass) { + return (element) => { + if (element instanceof Il2Cpp.Class) { + return klass.isAssignableFrom(element); + } + else { + return klass.isAssignableFrom(element.class); + } + }; + } + /** Creates a filter which includes `element`s whose type corresponds to `klass` type. */ + static IsExactly(klass) { + return (element) => { + if (element instanceof Il2Cpp.Class) { + return element.equals(klass); + } + else { + return element.class.equals(klass); + } + }; + } +} +Il2Cpp.Filtering = Il2CppFiltering; + +},{}],7:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("./base"); +require("./api"); +require("./filtering"); +require("./runtime"); +require("./tracer"); +require("./structs/array"); +require("./structs/assembly"); +require("./structs/class"); +require("./structs/domain"); +require("./structs/field"); +require("./structs/gc"); +require("./structs/gc-handle"); +require("./structs/image"); +require("./structs/memory-snapshot"); +require("./structs/method"); +require("./structs/object"); +require("./structs/parameter"); +require("./structs/pointer"); +require("./structs/reference"); +require("./structs/string"); +require("./structs/thread"); +require("./structs/type"); +require("./structs/type-enum"); +require("./structs/value-type"); + +},{"./api":4,"./base":5,"./filtering":6,"./runtime":8,"./structs/array":9,"./structs/assembly":10,"./structs/class":11,"./structs/domain":12,"./structs/field":13,"./structs/gc":15,"./structs/gc-handle":14,"./structs/image":16,"./structs/memory-snapshot":17,"./structs/method":18,"./structs/object":19,"./structs/parameter":20,"./structs/pointer":21,"./structs/reference":22,"./structs/string":23,"./structs/thread":24,"./structs/type":26,"./structs/type-enum":25,"./structs/value-type":27,"./tracer":28}],8:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +/** */ +class Il2CppRuntime { + constructor() { } + /** Gets the allocation granularity. */ + static get allocationGranularity() { + return this.information[5]; + } + /** Gets the size of the Il2CppArray struct. */ + static get arrayHeaderSize() { + return this.information[2]; + } + /** @internal */ + static get information() { + const snapshot = Il2Cpp.MemorySnapshot.capture(); + try { + return Il2Cpp.Api._memorySnapshotGetRuntimeInformation(snapshot); + } + finally { + Il2Cpp.Api._memorySnapshotFree(snapshot); + } + } + /** Gets the pointer size. */ + static get pointerSize() { + return this.information[0]; + } + /** Gets the size of the Il2CppObject struct. */ + static get objectHeaderSize() { + return this.information[1]; + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppRuntime, "information", null); +Il2Cpp.Runtime = Il2CppRuntime; + +},{"decorator-cache-getter":2}],9:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const console_1 = require("../../utils/console"); +const native_struct_1 = require("../../utils/native-struct"); +/** Represents a `Il2CppArraySize`. */ +class Il2CppArray extends native_struct_1.NativeStruct { + /** @internal */ + static from(klass, lengthOrElements) { + const length = typeof lengthOrElements == "number" ? lengthOrElements : lengthOrElements.length; + const array = new Il2Cpp.Array(Il2Cpp.Api._arrayNew(klass, length)); + if (Array.isArray(lengthOrElements)) { + array.elements.write(lengthOrElements); + } + return array; + } + /** @internal Gets a pointer to the first element of the current array. */ + get elements() { + return new Il2Cpp.Pointer(Il2Cpp.Api._arrayGetElements(this), this.elementType); + } + /** Gets the size of the object encompassed by the current array. */ + get elementSize() { + return this.elementType.class.arrayElementSize; + } + /** Gets the type of the object encompassed by the current array. */ + get elementType() { + return this.object.class.type.class.baseType; + } + /** Gets the total number of elements in all the dimensions of the current array. */ + get length() { + return Il2Cpp.Api._arrayGetLength(this); + } + /** Gets the encompassing object of the current array. */ + get object() { + return new Il2Cpp.Object(this); + } + /** Gets the element at the specified index of the current array. */ + get(index) { + if (index < 0 || index >= this.length) { + (0, console_1.raise)(`cannot get element at index ${index}: array length is ${this.length}`); + } + return this.elements.get(index); + } + /** Sets the element at the specified index of the current array. */ + set(index, value) { + if (index < 0 || index >= this.length) { + (0, console_1.raise)(`cannot get element at index ${index}: array length is ${this.length}`); + } + this.elements.set(index, value); + } + /** */ + toString() { + return this.isNull() ? "null" : `[${this.elements.read(this.length, 0)}]`; + } + /** Iterable. */ + *[Symbol.iterator]() { + for (let i = 0; i < this.length; i++) { + yield this.elements.get(i); + } + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppArray.prototype, "elements", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppArray.prototype, "elementSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppArray.prototype, "elementType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppArray.prototype, "length", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppArray.prototype, "object", null); +Il2Cpp.Array = Il2CppArray; + +},{"../../utils/console":31,"../../utils/native-struct":32,"decorator-cache-getter":2}],10:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../../utils/utils"); +/** Represents a `Il2CppAssembly`. */ +let Il2CppAssembly = class Il2CppAssembly extends native_struct_1.NonNullNativeStruct { + /** Gets the image of this assembly. */ + get image() { + return new Il2Cpp.Image(Il2Cpp.Api._assemblyGetImage(this)); + } + /** Gets the name of this assembly. */ + get name() { + return this.image.name.replace(".dll", ""); + } + /** Gets the encompassing object of the current assembly. */ + get object() { + return Il2Cpp.Image.corlib.class("System.Reflection.Assembly").method("Load").invoke(Il2Cpp.String.from(this.name)); + } +}; +__decorate([ + decorator_cache_getter_1.cache +], Il2CppAssembly.prototype, "image", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppAssembly.prototype, "name", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppAssembly.prototype, "object", null); +Il2CppAssembly = __decorate([ + utils_1.cacheInstances +], Il2CppAssembly); +Il2Cpp.Assembly = Il2CppAssembly; + +},{"../../utils/native-struct":32,"../../utils/utils":34,"decorator-cache-getter":2}],11:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const console_1 = require("../../utils/console"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../../utils/utils"); +/** Represents a `Il2CppClass`. */ +let Il2CppClass = class Il2CppClass extends native_struct_1.NonNullNativeStruct { + /** Gets the actual size of the instance of the current class. */ + get actualInstanceSize() { + return Il2Cpp.Api._classGetActualInstanceSize(this); + } + /** Gets the array class which encompass the current class. */ + get arrayClass() { + return new Il2Cpp.Class(Il2Cpp.Api._classGetArrayClass(this, 1)); + } + /** Gets the size of the object encompassed by the current array class. */ + get arrayElementSize() { + return Il2Cpp.Api._classGetArrayElementSize(this); + } + /** Gets the name of the assembly in which the current class is defined. */ + get assemblyName() { + return Il2Cpp.Api._classGetAssemblyName(this).readUtf8String(); + } + /** Gets the class that declares the current nested class. */ + get declaringClass() { + const handle = Il2Cpp.Api._classGetDeclaringType(this); + return handle.isNull() ? null : new Il2Cpp.Class(handle); + } + /** Gets the encompassed type of this array, reference, pointer or enum type. */ + get baseType() { + const handle = Il2Cpp.Api._classGetBaseType(this); + return handle.isNull() ? null : new Il2Cpp.Type(handle); + } + /** Gets the class of the object encompassed or referred to by the current array, pointer or reference class. */ + get elementClass() { + const handle = Il2Cpp.Api._classGetElementClass(this); + return handle.isNull() ? null : new Il2Cpp.Class(handle); + } + /** Gets the fields of the current class. */ + get fields() { + return Array.from((0, utils_1.nativeIterator)(this, Il2Cpp.Api._classGetFields, Il2Cpp.Field)); + } + /** Gets the flags of the current class. */ + get flags() { + return Il2Cpp.Api._classGetFlags(this); + } + /** Gets the amount of generic parameters of this generic class. */ + get genericParameterCount() { + if (!this.isGeneric) { + return 0; + } + return this.type.object.method("GetGenericArguments").invoke().length; + } + /** Determines whether the GC has tracking references to the current class instances. */ + get hasReferences() { + return !!Il2Cpp.Api._classHasReferences(this); + } + /** Determines whether ther current class has a valid static constructor. */ + get hasStaticConstructor() { + const staticConstructor = this.tryMethod(".cctor"); + return staticConstructor != null && !staticConstructor.virtualAddress.isNull(); + } + /** Gets the image in which the current class is defined. */ + get image() { + return new Il2Cpp.Image(Il2Cpp.Api._classGetImage(this)); + } + /** Gets the size of the instance of the current class. */ + get instanceSize() { + return Il2Cpp.Api._classGetInstanceSize(this); + } + /** Determines whether the current class is abstract. */ + get isAbstract() { + return !!Il2Cpp.Api._classIsAbstract(this); + } + /** Determines whether the current class is blittable. */ + get isBlittable() { + return !!Il2Cpp.Api._classIsBlittable(this); + } + /** Determines whether the current class is an enumeration. */ + get isEnum() { + return !!Il2Cpp.Api._classIsEnum(this); + } + /** Determines whether the current class is a generic one. */ + get isGeneric() { + return !!Il2Cpp.Api._classIsGeneric(this); + } + /** Determines whether the current class is inflated. */ + get isInflated() { + return !!Il2Cpp.Api._classIsInflated(this); + } + /** Determines whether the current class is an interface. */ + get isInterface() { + return !!Il2Cpp.Api._classIsInterface(this); + } + /** Determines whether the current class is a value type. */ + get isValueType() { + return !!Il2Cpp.Api._classIsValueType(this); + } + /** Gets the interfaces implemented or inherited by the current class. */ + get interfaces() { + return Array.from((0, utils_1.nativeIterator)(this, Il2Cpp.Api._classGetInterfaces, Il2Cpp.Class)); + } + /** Gets the methods implemented by the current class. */ + get methods() { + return Array.from((0, utils_1.nativeIterator)(this, Il2Cpp.Api._classGetMethods, Il2Cpp.Method)); + } + /** Gets the name of the current class. */ + get name() { + return Il2Cpp.Api._classGetName(this).readUtf8String(); + } + /** Gets the namespace of the current class. */ + get namespace() { + return Il2Cpp.Api._classGetNamespace(this).readUtf8String(); + } + /** Gets the classes nested inside the current class. */ + get nestedClasses() { + return Array.from((0, utils_1.nativeIterator)(this, Il2Cpp.Api._classGetNestedClasses, Il2Cpp.Class)); + } + /** Gets the class from which the current class directly inherits. */ + get parent() { + const handle = Il2Cpp.Api._classGetParent(this); + return handle.isNull() ? null : new Il2Cpp.Class(handle); + } + /** Gets the rank (number of dimensions) of the current array class. */ + get rank() { + return Il2Cpp.Api._classGetRank(this); + } + /** Gets a pointer to the static fields of the current class. */ + get staticFieldsData() { + return Il2Cpp.Api._classGetStaticFieldData(this); + } + /** Gets the size of the instance - as a value type - of the current class. */ + get valueSize() { + return Il2Cpp.Api._classGetValueSize(this, NULL); + } + /** Gets the type of the current class. */ + get type() { + return new Il2Cpp.Type(Il2Cpp.Api._classGetType(this)); + } + /** Allocates a new object of the current class. */ + alloc() { + return new Il2Cpp.Object(Il2Cpp.Api._objectNew(this)); + } + /** Gets the field identified by the given name. */ + field(name) { + return this.tryField(name); + } + /** Builds a generic instance of the current generic class. */ + inflate(...classes) { + if (!this.isGeneric) { + (0, console_1.raise)(`cannot inflate class ${this.type.name}: it has no generic parameters`); + } + if (this.genericParameterCount != classes.length) { + (0, console_1.raise)(`cannot inflate class ${this.type.name}: it needs ${this.genericParameterCount} generic parameter(s), not ${classes.length}`); + } + const types = classes.map(klass => klass.type.object); + const typeArray = Il2Cpp.Array.from(Il2Cpp.Image.corlib.class("System.Type"), types); + const inflatedType = this.type.object.method("MakeGenericType", 1).invoke(typeArray); + return new Il2Cpp.Class(Il2Cpp.Api._classFromSystemType(inflatedType)); + } + /** Calls the static constructor of the current class. */ + initialize() { + Il2Cpp.Api._classInit(this); + } + /** Determines whether an instance of `other` class can be assigned to a variable of the current type. */ + isAssignableFrom(other) { + return !!Il2Cpp.Api._classIsAssignableFrom(this, other); + } + /** Determines whether the current class derives from `other` class. */ + isSubclassOf(other, checkInterfaces) { + return !!Il2Cpp.Api._classIsSubclassOf(this, other, +checkInterfaces); + } + /** Gets the method identified by the given name and parameter count. */ + method(name, parameterCount = -1) { + return this.tryMethod(name, parameterCount); + } + /** Gets the nested class with the given name. */ + nested(name) { + return this.tryNested(name); + } + /** Allocates a new object of the current class and calls its default constructor. */ + new() { + const object = this.alloc(); + const exceptionArray = Memory.alloc(Process.pointerSize); + Il2Cpp.Api._objectInit(object, exceptionArray); + const exception = exceptionArray.readPointer(); + if (!exception.isNull()) { + (0, console_1.raise)(new Il2Cpp.Object(exception).toString()); + } + return object; + } + /** Gets the field with the given name. */ + tryField(name) { + const handle = Il2Cpp.Api._classGetFieldFromName(this, Memory.allocUtf8String(name)); + return handle.isNull() ? null : new Il2Cpp.Field(handle); + } + /** Gets the method with the given name and parameter count. */ + tryMethod(name, parameterCount = -1) { + const handle = Il2Cpp.Api._classGetMethodFromName(this, Memory.allocUtf8String(name), parameterCount); + return handle.isNull() ? null : new Il2Cpp.Method(handle); + } + /** Gets the nested class with the given name. */ + tryNested(name) { + return this.nestedClasses.find(e => e.name == name); + } + /** */ + toString() { + const inherited = [this.parent].concat(this.interfaces); + return `\ +// ${this.assemblyName} +${this.isEnum ? `enum` : this.isValueType ? `struct` : this.isInterface ? `interface` : `class`} \ +${this.type.name}\ +${inherited ? ` : ${inherited.map(e => e?.type.name).join(`, `)}` : ``} +{ + ${this.fields.join(`\n `)} + ${this.methods.join(`\n `)} +}`; + } + /** Executes a callback for every defined class. */ + static enumerate(block) { + const callback = new NativeCallback(function (klass, _) { + block(new Il2Cpp.Class(klass)); + }, "void", ["pointer", "pointer"]); + return Il2Cpp.Api._classForEach(callback, NULL); + } +}; +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "actualInstanceSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "arrayClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "arrayElementSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "assemblyName", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "declaringClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "baseType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "elementClass", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "fields", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "flags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "genericParameterCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "hasReferences", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "hasStaticConstructor", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "image", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "instanceSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isAbstract", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isBlittable", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isEnum", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isGeneric", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isInflated", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isInterface", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "isValueType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "interfaces", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "methods", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "name", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "namespace", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "nestedClasses", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "parent", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "rank", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "staticFieldsData", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "valueSize", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppClass.prototype, "type", null); +__decorate([ + (0, utils_1.levenshtein)("fields") +], Il2CppClass.prototype, "field", null); +__decorate([ + (0, utils_1.levenshtein)("methods") +], Il2CppClass.prototype, "method", null); +__decorate([ + (0, utils_1.levenshtein)("nestedClasses") +], Il2CppClass.prototype, "nested", null); +Il2CppClass = __decorate([ + utils_1.cacheInstances +], Il2CppClass); +Il2Cpp.Class = Il2CppClass; + +},{"../../utils/console":31,"../../utils/native-struct":32,"../../utils/utils":34,"decorator-cache-getter":2}],12:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const utils_1 = require("../../utils/utils"); +/** Represents a `Il2CppDomain`. */ +class Il2CppDomain { + constructor() { } + /** Gets the assemblies that have been loaded into the execution context of the application domain. */ + static get assemblies() { + const sizePointer = Memory.alloc(Process.pointerSize); + const startPointer = Il2Cpp.Api._domainGetAssemblies(this, sizePointer); + const count = sizePointer.readInt(); + const array = new Array(count); + for (let i = 0; i < count; i++) { + array[i] = new Il2Cpp.Assembly(startPointer.add(i * Process.pointerSize).readPointer()); + } + if (count == 0) { + for (const assemblyObject of this.object.method("GetAssemblies").overload().invoke()) { + const assemblyName = assemblyObject.method("GetSimpleName").invoke().content; + if (assemblyName != null) { + array.push(this.assembly(assemblyName)); + } + } + } + return array; + } + /** Gets the application domain handle. */ + static get handle() { + return Il2Cpp.Api._domainGet(); + } + /** Gets the encompassing object of the application domain. */ + static get object() { + return Il2Cpp.Image.corlib.class("System.AppDomain").method("get_CurrentDomain").invoke(); + } + /** Opens and loads the assembly with the given name. */ + static assembly(name) { + return this.tryAssembly(name); + } + /** Attached a new thread to the application domain. */ + static attach() { + return new Il2Cpp.Thread(Il2Cpp.Api._threadAttach(this)); + } + /** Opens and loads the assembly with the given name. */ + static tryAssembly(name) { + const handle = Il2Cpp.Api._domainAssemblyOpen(this, Memory.allocUtf8String(name)); + return handle.isNull() ? null : new Il2Cpp.Assembly(handle); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppDomain, "assemblies", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppDomain, "handle", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppDomain, "object", null); +__decorate([ + (0, utils_1.levenshtein)("assemblies") +], Il2CppDomain, "assembly", null); +Il2Cpp.Domain = Il2CppDomain; + +},{"../../utils/utils":34,"decorator-cache-getter":2}],13:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const console_1 = require("../../utils/console"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../utils"); +/** Represents a `FieldInfo`. */ +class Il2CppField extends native_struct_1.NonNullNativeStruct { + /** Gets the class in which this field is defined. */ + get class() { + return new Il2Cpp.Class(Il2Cpp.Api._fieldGetClass(this)); + } + /** Gets the flags of the current field. */ + get flags() { + return Il2Cpp.Api._fieldGetFlags(this); + } + /** Determines whether this field value is known at compile time. */ + get isLiteral() { + return !!Il2Cpp.Api._fieldIsLiteral(this); + } + /** Determines whether this field is static. */ + get isStatic() { + return !!Il2Cpp.Api._fieldIsStatic(this); + } + /** Determines whether this field is thread static. */ + get isThreadStatic() { + return !!Il2Cpp.Api._fieldIsThreadStatic(this); + } + /** Gets the access modifier of this field. */ + get modifier() { + return Il2Cpp.Api._fieldGetModifier(this).readUtf8String(); + } + /** Gets the name of this field. */ + get name() { + return Il2Cpp.Api._fieldGetName(this).readUtf8String(); + } + /** Gets the offset of this field, calculated as the difference with its owner virtual address. */ + get offset() { + return Il2Cpp.Api._fieldGetOffset(this); + } + /** Gets the type of this field. */ + get type() { + return new Il2Cpp.Type(Il2Cpp.Api._fieldGetType(this)); + } + /** Gets the value of this field. */ + get value() { + const handle = Memory.alloc(Process.pointerSize); + Il2Cpp.Api._fieldGetStaticValue(this.handle, handle); + return (0, utils_1.read)(handle, this.type); + } + /** Sets the value of this field. Thread static or literal values cannot be altered yet. */ + set value(value) { + if (this.isThreadStatic || this.isLiteral) { + (0, console_1.raise)(`cannot modify the value of field ${this.name}: is thread static or literal`); + } + const handle = Memory.alloc(Process.pointerSize); + (0, utils_1.write)(handle, value, this.type); + Il2Cpp.Api._fieldSetStaticValue(this.handle, handle); + } + /** */ + toString() { + return `\ +${this.isThreadStatic ? `[ThreadStatic] ` : ``}\ +${this.isStatic ? `static ` : ``}\ +${this.type.name} \ +${this.name}\ +${this.isLiteral ? ` = ${this.type.class.isEnum ? (0, utils_1.read)(this.value.handle, this.type.class.baseType) : this.value}` : ``};\ +${this.isThreadStatic || this.isLiteral ? `` : ` // 0x${this.offset.toString(16)}`}`; + } + /** @internal */ + withHolder(instance) { + let valueHandle = instance.handle.add(this.offset); + if (instance instanceof Il2Cpp.ValueType) { + valueHandle = valueHandle.sub(Il2Cpp.Runtime.objectHeaderSize); + } + return new Proxy(this, { + get(target, property) { + if (property == "value") { + return (0, utils_1.read)(valueHandle, target.type); + } + return Reflect.get(target, property); + }, + set(target, property, value) { + if (property == "value") { + (0, utils_1.write)(valueHandle, value, target.type); + return true; + } + return Reflect.set(target, property, value); + } + }); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "class", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "flags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "isLiteral", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "isStatic", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "isThreadStatic", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "name", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "offset", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppField.prototype, "type", null); +Reflect.set(Il2Cpp, "Field", Il2CppField); + +},{"../../utils/console":31,"../../utils/native-struct":32,"../utils":29,"decorator-cache-getter":2}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** Represents a GCHandle. */ +class Il2CppGCHandle { + handle; + /** @internal */ + constructor(handle) { + this.handle = handle; + } + /** Gets the object associated to this handle. */ + get target() { + const handle = Il2Cpp.Api._gcHandleGetTarget(this.handle); + return handle.isNull() ? null : new Il2Cpp.Object(handle); + } + /** Frees this handle. */ + free() { + return Il2Cpp.Api._gcHandleFree(this.handle); + } +} +Il2Cpp.GC.Handle = Il2CppGCHandle; + +},{}],15:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const versioning_1 = __importDefault(require("versioning")); +/** Garbage collector utility functions. */ +class Il2CppGC { + constructor() { } + /** Gets the heap size in bytes. */ + static get heapSize() { + return Il2Cpp.Api._gcGetHeapSize(); + } + /** Determines whether the garbage collector is disabled. */ + static get isEnabled() { + return !Il2Cpp.Api._gcIsDisabled(); + } + /** Determines whether the garbage collector is incremental. */ + static get isIncremental() { + return !!Il2Cpp.Api._gcIsIncremental(); + } + /** Gets the number of nanoseconds the garbage collector can spend in a collection step. */ + static get maxTimeSlice() { + return Il2Cpp.Api._gcGetMaxTimeSlice(); + } + /** Gets the used heap size in bytes. */ + static get usedHeapSize() { + return Il2Cpp.Api._gcGetUsedSize(); + } + /** Enables or disables the garbage collector. */ + static set isEnabled(value) { + value ? Il2Cpp.Api._gcEnable() : Il2Cpp.Api._gcDisable(); + } + /** Sets the number of nanoseconds the garbage collector can spend in a collection step. */ + static set maxTimeSlice(nanoseconds) { + Il2Cpp.Api._gcSetMaxTimeSlice(nanoseconds); + } + /** Returns the heap allocated objects of the specified class. This variant reads GC descriptors. */ + static choose(klass) { + const matches = []; + const callback = (objects, size, _) => { + for (let i = 0; i < size; i++) { + matches.push(new Il2Cpp.Object(objects.add(i * Process.pointerSize).readPointer())); + } + }; + const chooseCallback = new NativeCallback(callback, "void", ["pointer", "int", "pointer"]); + if (versioning_1.default.gte(Il2Cpp.unityVersion, "2021.2.0")) { + const realloc = (handle, size) => { + if (!handle.isNull() && size.compare(0) == 0) { + Il2Cpp.free(handle); + return NULL; + } + else { + return Il2Cpp.alloc(size); + } + }; + const reallocCallback = new NativeCallback(realloc, "pointer", ["pointer", "size_t", "pointer"]); + const state = Il2Cpp.Api._livenessAllocateStruct(klass.handle, 0, chooseCallback, NULL, reallocCallback); + Il2Cpp.Api._livenessCalculationFromStatics(state); + Il2Cpp.Api._livenessFinalize(state); + Il2Cpp.Api._livenessFreeStruct(state); + } + else { + const onWorld = new NativeCallback(() => { }, "void", []); + const state = Il2Cpp.Api._livenessCalculationBegin(klass.handle, 0, chooseCallback, NULL, onWorld, onWorld); + Il2Cpp.Api._livenessCalculationFromStatics(state); + Il2Cpp.Api._livenessCalculationEnd(state); + } + return matches; + } + /** Forces a garbage collection of the specified generation. */ + static collect(generation) { + Il2Cpp.Api._gcCollect(generation < 0 ? 0 : generation > 2 ? 2 : generation); + } + /** Forces a garbage collection. */ + static collectALittle() { + Il2Cpp.Api._gcCollectALittle(); + } + /** Resumes all the previously stopped threads. */ + static startWorld() { + return Il2Cpp.Api._gcStartWorld(); + } + /** Performs an incremental garbage collection. */ + static startIncrementalCollection() { + return Il2Cpp.Api._gcStartIncrementalCollection(); + } + /** Stops all threads which may access the garbage collected heap, other than the caller. */ + static stopWorld() { + return Il2Cpp.Api._gcStopWorld(); + } +} +Reflect.set(Il2Cpp, "GC", Il2CppGC); + +},{"versioning":37}],16:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../../utils/utils"); +/** Represents a `Il2CppImage`. */ +let Il2CppImage = class Il2CppImage extends native_struct_1.NonNullNativeStruct { + /** Gets the COR library. */ + static get corlib() { + return new Il2Cpp.Image(Il2Cpp.Api._getCorlib()); + } + /** Gets the assembly in which the current image is defined. */ + get assembly() { + return new Il2Cpp.Assembly(Il2Cpp.Api._imageGetAssembly(this)); + } + /** Gets the amount of classes defined in this image. */ + get classCount() { + return Il2Cpp.Api._imageGetClassCount(this); + } + /** Gets the classes defined in this image. */ + get classes() { + if (Il2Cpp.unityVersionIsBelow201830) { + const types = this.assembly.object.method("GetTypes").invoke(false); + // On Unity 5.3.8f1, getting System.Reflection.Emit.OpCodes type name + // without iterating all the classes first somehow blows things up at + // app startup, hence the `Array.from`. + return Array.from(types).map(e => new Il2Cpp.Class(Il2Cpp.Api._classFromSystemType(e))); + } + else { + return Array.from(Array(this.classCount), (_, i) => new Il2Cpp.Class(Il2Cpp.Api._imageGetClass(this, i))); + } + } + /** Gets the name of this image. */ + get name() { + return Il2Cpp.Api._imageGetName(this).readUtf8String(); + } + /** Gets the class with the specified name defined in this image. */ + class(name) { + return this.tryClass(name); + } + /** Gets the class with the specified name defined in this image. */ + tryClass(name) { + const dotIndex = name.lastIndexOf("."); + const classNamespace = Memory.allocUtf8String(dotIndex == -1 ? "" : name.slice(0, dotIndex)); + const className = Memory.allocUtf8String(name.slice(dotIndex + 1)); + const handle = Il2Cpp.Api._classFromName(this, classNamespace, className); + return handle.isNull() ? null : new Il2Cpp.Class(handle); + } +}; +__decorate([ + decorator_cache_getter_1.cache +], Il2CppImage.prototype, "assembly", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppImage.prototype, "classCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppImage.prototype, "classes", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppImage.prototype, "name", null); +__decorate([ + (0, utils_1.levenshtein)("classes", e => (e.namespace ? `${e.namespace}.${e.name}` : e.name)) +], Il2CppImage.prototype, "class", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppImage, "corlib", null); +Il2CppImage = __decorate([ + utils_1.cacheInstances +], Il2CppImage); +Il2Cpp.Image = Il2CppImage; + +},{"../../utils/native-struct":32,"../../utils/utils":34,"decorator-cache-getter":2}],17:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../../utils/utils"); +/** Represents a `Il2CppManagedMemorySnapshot`. */ +class Il2CppMemorySnapshot extends native_struct_1.NonNullNativeStruct { + /** Captures a memory snapshot. */ + static capture() { + return new Il2Cpp.MemorySnapshot(); + } + /** Creates a memory snapshot with the given handle. */ + constructor(handle = Il2Cpp.Api._memorySnapshotCapture()) { + super(handle); + } + /** Gets any initialized class. */ + get classes() { + return Array.from((0, utils_1.nativeIterator)(this, Il2Cpp.Api._memorySnapshotGetClasses, Il2Cpp.Class)); + } + /** Gets the objects tracked by this memory snapshot. */ + get objects() { + const array = []; + const [count, start] = Il2Cpp.Api._memorySnapshotGetGCHandles(this); + for (let i = 0; i < count; i++) { + array.push(new Il2Cpp.Object(start.add(i * Process.pointerSize).readPointer())); + } + return array; + } + /** Frees this memory snapshot. */ + free() { + Il2Cpp.Api._memorySnapshotFree(this); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMemorySnapshot.prototype, "classes", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMemorySnapshot.prototype, "objects", null); +Il2Cpp.MemorySnapshot = Il2CppMemorySnapshot; + +},{"../../utils/native-struct":32,"../../utils/utils":34,"decorator-cache-getter":2}],18:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const console_1 = require("../../utils/console"); +const native_struct_1 = require("../../utils/native-struct"); +const utils_1 = require("../../utils/utils"); +const utils_2 = require("../utils"); +/** Represents a `MethodInfo`. */ +class Il2CppMethod extends native_struct_1.NonNullNativeStruct { + /** Gets the class in which this method is defined. */ + get class() { + return new Il2Cpp.Class(Il2Cpp.Api._methodGetClass(this)); + } + /** Gets the flags of the current method. */ + get flags() { + return Il2Cpp.Api._methodGetFlags(this, NULL); + } + /** Gets the implementation flags of the current method. */ + get implementationFlags() { + const implementationFlagsPointer = Memory.alloc(Process.pointerSize); + Il2Cpp.Api._methodGetFlags(this, implementationFlagsPointer); + return implementationFlagsPointer.readU32(); + } + /** */ + get fridaSignature() { + const types = []; + for (const parameter of this.parameters) { + types.push(parameter.type.fridaAlias); + } + if (!this.isStatic || Il2Cpp.unityVersionIsBelow201830) { + types.unshift("pointer"); + } + if (this.isInflated) { + types.push("pointer"); + } + return types; + } + /** Gets the amount of generic parameters of this generic method. */ + get genericParameterCount() { + if (!this.isGeneric) { + return 0; + } + return this.object.method("GetGenericArguments").invoke().length; + } + /** Determines whether this method is external. */ + get isExternal() { + return !!Il2Cpp.Api._methodIsExternal(this); + } + /** Determines whether this method is generic. */ + get isGeneric() { + return !!Il2Cpp.Api._methodIsGeneric(this); + } + /** Determines whether this method is inflated (generic with a concrete type parameter). */ + get isInflated() { + return !!Il2Cpp.Api._methodIsInflated(this); + } + /** Determines whether this method is static. */ + get isStatic() { + return !Il2Cpp.Api._methodIsInstance(this); + } + /** Determines whether this method is synchronized. */ + get isSynchronized() { + return !!Il2Cpp.Api._methodIsSynchronized(this); + } + /** Gets the access modifier of this method. */ + get modifier() { + return Il2Cpp.Api._methodGetModifier(this).readUtf8String(); + } + /** Gets the name of this method. */ + get name() { + return Il2Cpp.Api._methodGetName(this).readUtf8String(); + } + /** @internal */ + get nativeFunction() { + return new NativeFunction(this.virtualAddress, this.returnType.fridaAlias, this.fridaSignature); + } + /** Gets the encompassing object of the current method. */ + get object() { + return new Il2Cpp.Object(Il2Cpp.Api._methodGetObject(this, NULL)); + } + /** Gets the amount of parameters of this method. */ + get parameterCount() { + return Il2Cpp.Api._methodGetParameterCount(this); + } + /** Gets the parameters of this method. */ + get parameters() { + return Array.from(Array(this.parameterCount), (_, i) => { + const parameterName = Il2Cpp.Api._methodGetParameterName(this, i).readUtf8String(); + const parameterType = Il2Cpp.Api._methodGetParameterType(this, i); + return new Il2Cpp.Parameter(parameterName, i, new Il2Cpp.Type(parameterType)); + }); + } + /** Gets the relative virtual address (RVA) of this method. */ + get relativeVirtualAddress() { + return this.virtualAddress.sub(Il2Cpp.module.base); + } + /** Gets the return type of this method. */ + get returnType() { + return new Il2Cpp.Type(Il2Cpp.Api._methodGetReturnType(this)); + } + /** Gets the virtual address (VA) to this method. */ + get virtualAddress() { + return Il2Cpp.Api._methodGetPointer(this); + } + /** Replaces the body of this method. */ + set implementation(block) { + const startIndex = +!this.isStatic | +Il2Cpp.unityVersionIsBelow201830; + const callback = (...args) => { + const parameters = this.parameters.map((e, i) => (0, utils_2.fromFridaValue)(args[i + startIndex], e.type)); + return (0, utils_2.toFridaValue)(block.call(this.isStatic ? this.class : new Il2Cpp.Object(args[0]), ...parameters)); + }; + try { + Interceptor.replace(this.virtualAddress, new NativeCallback(callback, this.returnType.fridaAlias, this.fridaSignature)); + } + catch (e) { + switch (e.message) { + case "access violation accessing 0x0": + (0, console_1.raise)(`cannot implement method ${this.name}: it has a NULL virtual address`); + case `unable to intercept function at ${this.virtualAddress}; please file a bug`: + (0, console_1.warn)(`cannot implement method ${this.name}: it may be a thunk`); + break; + case "already replaced this function": + (0, console_1.warn)(`cannot implement method ${this.name}: already replaced by a thunk`); + break; + default: + throw e; + } + } + } + /** Creates a generic instance of the current generic method. */ + inflate(...classes) { + if (!this.isGeneric) { + (0, console_1.raise)(`cannot inflate method ${this.name}: it has no generic parameters`); + } + if (this.genericParameterCount != classes.length) { + (0, console_1.raise)(`cannot inflate method ${this.name}: it needs ${this.genericParameterCount} generic parameter(s), not ${classes.length}`); + } + const types = classes.map(klass => klass.type.object); + const typeArray = Il2Cpp.Array.from(Il2Cpp.Image.corlib.class("System.Type"), types); + const inflatedMethodObject = this.object.method("MakeGenericMethod", 1).invoke(typeArray); + return new Il2Cpp.Method(Il2Cpp.Api._methodGetFromReflection(inflatedMethodObject)); + } + /** Invokes this method. */ + invoke(...parameters) { + if (!this.isStatic) { + (0, console_1.raise)(`cannot invoke a non-static method ${this.name}: must be invoked throught a Il2Cpp.Object, not a Il2Cpp.Class`); + } + return this.invokeRaw(NULL, ...parameters); + } + /** @internal */ + invokeRaw(instance, ...parameters) { + const allocatedParameters = parameters.map(utils_2.toFridaValue); + if (!this.isStatic || Il2Cpp.unityVersionIsBelow201830) { + allocatedParameters.unshift(instance); + } + if (this.isInflated) { + allocatedParameters.push(this.handle); + } + try { + const returnValue = this.nativeFunction(...allocatedParameters); + return (0, utils_2.fromFridaValue)(returnValue, this.returnType); + } + catch (e) { + if (e == null) { + (0, console_1.raise)("an unexpected native function exception occurred, this is due to parameter types mismatch"); + } + switch (e.message) { + case "bad argument count": + (0, console_1.raise)(`cannot invoke method ${this.name}: it needs ${this.parameterCount} parameter(s), not ${parameters.length}`); + case "expected a pointer": + case "expected number": + case "expected array with fields": + (0, console_1.raise)(`cannot invoke method ${this.name}: parameter types mismatch`); + } + throw e; + } + } + /** Gets the overloaded method with the given parameter types. */ + overload(...parameterTypes) { + const result = this.tryOverload(...parameterTypes); + if (result != undefined) + return result; + (0, console_1.raise)(`cannot find overloaded method ${this.name}(${parameterTypes})`); + } + /** Gets the parameter with the given name. */ + parameter(name) { + return this.tryParameter(name); + } + /** Restore the original method implementation. */ + revert() { + Interceptor.revert(this.virtualAddress); + Interceptor.flush(); + } + /** Gets the overloaded method with the given parameter types. */ + tryOverload(...parameterTypes) { + return this.class.methods.find(e => e.name == this.name && + e.parameterCount == parameterTypes.length && + e.parameters.every((e, i) => e.type.name == parameterTypes[i])); + } + /** Gets the parameter with the given name. */ + tryParameter(name) { + return this.parameters.find(e => e.name == name); + } + /** */ + toString() { + return `\ +${this.isStatic ? `static ` : ``}\ +${this.returnType.name} \ +${this.name}\ +(${this.parameters.join(`, `)});\ +${this.virtualAddress.isNull() ? `` : ` // 0x${this.relativeVirtualAddress.toString(16).padStart(8, `0`)}`}`; + } + /** @internal */ + withHolder(instance) { + return new Proxy(this, { + get(target, property) { + switch (property) { + case "invoke": + return target.invokeRaw.bind(target, instance.handle); + case "inflate": + case "overload": + case "tryOverload": + return function (...args) { + return target[property](...args)?.withHolder(instance); + }; + } + return Reflect.get(target, property); + } + }); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "class", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "flags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "implementationFlags", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "fridaSignature", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "genericParameterCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "isExternal", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "isGeneric", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "isInflated", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "isStatic", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "isSynchronized", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "name", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "nativeFunction", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "object", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "parameterCount", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "parameters", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "relativeVirtualAddress", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "returnType", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppMethod.prototype, "virtualAddress", null); +__decorate([ + (0, utils_1.levenshtein)("parameters") +], Il2CppMethod.prototype, "parameter", null); +Reflect.set(Il2Cpp, "Method", Il2CppMethod); + +},{"../../utils/console":31,"../../utils/native-struct":32,"../../utils/utils":34,"../utils":29,"decorator-cache-getter":2}],19:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const native_struct_1 = require("../../utils/native-struct"); +/** Represents a `Il2CppObject`. */ +class Il2CppObject extends native_struct_1.NativeStruct { + /** Gets the class of this object. */ + get class() { + return new Il2Cpp.Class(Il2Cpp.Api._objectGetClass(this)); + } + /** Gets the size of the current object. */ + get size() { + return Il2Cpp.Api._objectGetSize(this); + } + /** Acquires an exclusive lock on the current object. */ + enter() { + return Il2Cpp.Api._monitorEnter(this); + } + /** Release an exclusive lock on the current object. */ + exit() { + return Il2Cpp.Api._monitorExit(this); + } + /** Gets the field with the given name. */ + field(name) { + return this.class.field(name).withHolder(this); + } + /** Gets the method with the given name. */ + method(name, parameterCount = -1) { + return this.class.method(name, parameterCount).withHolder(this); + } + /** Notifies a thread in the waiting queue of a change in the locked object's state. */ + pulse() { + return Il2Cpp.Api._monitorPulse(this); + } + /** Notifies all waiting threads of a change in the object's state. */ + pulseAll() { + return Il2Cpp.Api._monitorPulseAll(this); + } + /** Creates a reference to this object. */ + ref(pin) { + return new Il2Cpp.GC.Handle(Il2Cpp.Api._gcHandleNew(this, +pin)); + } + /** Gets the correct virtual method from the given virtual method. */ + virtualMethod(method) { + return new Il2Cpp.Method(Il2Cpp.Api._objectGetVirtualMethod(this, method)).withHolder(this); + } + /** Attempts to acquire an exclusive lock on the current object. */ + tryEnter(timeout) { + return !!Il2Cpp.Api._monitorTryEnter(this, timeout); + } + /** Gets the field with the given name. */ + tryField(name) { + return this.class.tryField(name)?.withHolder(this); + } + /** Gets the field with the given name. */ + tryMethod(name, parameterCount = -1) { + return this.class.tryMethod(name, parameterCount)?.withHolder(this); + } + /** Releases the lock on an object and attempts to block the current thread until it reacquires the lock. */ + tryWait(timeout) { + return !!Il2Cpp.Api._monitorTryWait(this, timeout); + } + /** */ + toString() { + return this.isNull() ? "null" : this.method("ToString").invoke().content ?? "null"; + } + /** Unboxes the value type out of this object. */ + unbox() { + return new Il2Cpp.ValueType(Il2Cpp.Api._objectUnbox(this), this.class.type); + } + /** Releases the lock on an object and blocks the current thread until it reacquires the lock. */ + wait() { + return Il2Cpp.Api._monitorWait(this); + } + /** Creates a weak reference to this object. */ + weakRef(trackResurrection) { + return new Il2Cpp.GC.Handle(Il2Cpp.Api._gcHandleNewWeakRef(this, +trackResurrection)); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppObject.prototype, "class", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppObject.prototype, "size", null); +Il2Cpp.Object = Il2CppObject; + +},{"../../utils/native-struct":32,"decorator-cache-getter":2}],20:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** Represents a `ParameterInfo`. */ +class Il2CppParameter { + /** Name of this parameter. */ + name; + /** Position of this parameter. */ + position; + /** Type of this parameter. */ + type; + constructor(name, position, type) { + this.name = name; + this.position = position; + this.type = type; + } + /** */ + toString() { + return `${this.type.name} ${this.name}`; + } +} +Il2Cpp.Parameter = Il2CppParameter; + +},{}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../utils"); +const native_struct_1 = require("../../utils/native-struct"); +/** */ +class Il2CppPointer extends native_struct_1.NativeStruct { + type; + constructor(handle, type) { + super(handle); + this.type = type; + } + /** Gets the element at the given index. */ + get(index) { + return (0, utils_1.read)(this.handle.add(index * this.type.class.arrayElementSize), this.type); + } + /** Reads the given amount of elements starting at the given offset. */ + read(length, offset = 0) { + const values = new Array(length); + for (let i = 0; i < length; i++) { + values[i] = this.get(i + offset); + } + return values; + } + /** Sets the given element at the given index */ + set(index, value) { + (0, utils_1.write)(this.handle.add(index * this.type.class.arrayElementSize), value, this.type); + } + /** */ + toString() { + return this.handle.toString(); + } + /** Writes the given elements starting at the given index. */ + write(values, offset = 0) { + for (let i = 0; i < values.length; i++) { + this.set(i + offset, values[i]); + } + } +} +Il2Cpp.Pointer = Il2CppPointer; + +},{"../../utils/native-struct":32,"../utils":29}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../utils"); +const native_struct_1 = require("../../utils/native-struct"); +const console_1 = require("../../utils/console"); +/** Represent a parameter passed by reference. */ +class Il2CppReference extends native_struct_1.NativeStruct { + type; + constructor(handle, type) { + super(handle); + this.type = type; + } + /** Gets the element referenced by the current reference. */ + get value() { + return (0, utils_1.read)(this.handle, this.type); + } + /** Sets the element referenced by the current reference. */ + set value(value) { + (0, utils_1.write)(this.handle, value, this.type); + } + /** */ + toString() { + return this.isNull() ? "null" : `->${this.value}`; + } + /** Creates a reference to the specified value. */ + static to(value, type) { + const handle = Memory.alloc(Process.pointerSize); + switch (typeof value) { + case "boolean": + return new Il2Cpp.Reference(handle.writeS8(+value), Il2Cpp.Image.corlib.class("System.Boolean").type); + case "number": + switch (type?.typeEnum) { + case 5 /* U1 */: + return new Il2Cpp.Reference(handle.writeU8(value), type); + case 4 /* I1 */: + return new Il2Cpp.Reference(handle.writeS8(value), type); + case 3 /* Char */: + case 7 /* U2 */: + return new Il2Cpp.Reference(handle.writeU16(value), type); + case 6 /* I2 */: + return new Il2Cpp.Reference(handle.writeS16(value), type); + case 9 /* U4 */: + return new Il2Cpp.Reference(handle.writeU32(value), type); + case 8 /* I4 */: + return new Il2Cpp.Reference(handle.writeS32(value), type); + case 11 /* U8 */: + return new Il2Cpp.Reference(handle.writeU64(value), type); + case 10 /* I8 */: + return new Il2Cpp.Reference(handle.writeS64(value), type); + case 12 /* R4 */: + return new Il2Cpp.Reference(handle.writeFloat(value), type); + case 13 /* R8 */: + return new Il2Cpp.Reference(handle.writeDouble(value), type); + } + case "object": + if (value instanceof Il2Cpp.ValueType || value instanceof Il2Cpp.Pointer) { + return new Il2Cpp.Reference(handle.writePointer(value), value.type); + } + else if (value instanceof Il2Cpp.Object) { + return new Il2Cpp.Reference(handle.writePointer(value), value.class.type); + } + else if (value instanceof Il2Cpp.String || value instanceof Il2Cpp.Array) { + return new Il2Cpp.Reference(handle.writePointer(value), value.object.class.type); + } + else if (value instanceof NativePointer) { + switch (type?.typeEnum) { + case 25 /* UnsignedNativeInteger */: + case 24 /* NativeInteger */: + return new Il2Cpp.Reference(handle.writePointer(value), type); + } + } + else if (value instanceof Int64) { + return new Il2Cpp.Reference(handle.writeS64(value), Il2Cpp.Image.corlib.class("System.Int64").type); + } + else if (value instanceof UInt64) { + return new Il2Cpp.Reference(handle.writeU64(value), Il2Cpp.Image.corlib.class("System.UInt64").type); + } + default: + (0, console_1.raise)(`don't know how to create a reference to ${value} using type ${type?.name}`); + } + } +} +Il2Cpp.Reference = Il2CppReference; + +},{"../../utils/console":31,"../../utils/native-struct":32,"../utils":29}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const native_struct_1 = require("../../utils/native-struct"); +/** Represents a `Il2CppString`. */ +class Il2CppString extends native_struct_1.NativeStruct { + /** Gets the content of this string. */ + get content() { + return Il2Cpp.Api._stringChars(this).readUtf16String(this.length); + } + /** Sets the content of this string. */ + set content(value) { + Il2Cpp.Api._stringChars(this).writeUtf16String(value ?? ""); + Il2Cpp.Api._stringSetLength(this, value?.length ?? 0); + } + /** Gets the length of this string. */ + get length() { + return Il2Cpp.Api._stringLength(this); + } + /** Gets the encompassing object of the current string. */ + get object() { + return new Il2Cpp.Object(this); + } + /** */ + toString() { + return this.isNull() ? "null" : `"${this.content}"`; + } + /** Creates a new string with the specified content. */ + static from(content) { + return new Il2Cpp.String(Il2Cpp.Api._stringNew(Memory.allocUtf8String(content || ""))); + } +} +Il2Cpp.String = Il2CppString; + +},{"../../utils/native-struct":32}],24:[function(require,module,exports){ +(function (setImmediate){(function (){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const console_1 = require("../../utils/console"); +const native_struct_1 = require("../../utils/native-struct"); +/** Represents a `Il2CppThread`. */ +class Il2CppThread extends native_struct_1.NativeStruct { + /** @internal */ + static get idOffset() { + const handle = ptr(Il2Cpp.currentThread.internal.field("thread_id").value.toString()); + const currentThreadId = Process.getCurrentThreadId(); + for (let i = 0; i < 1024; i++) { + const candidate = handle.add(i).readS32(); + if (candidate == currentThreadId) { + return i; + } + } + (0, console_1.raise)(`couldn't determine the offset for a native thread id value`); + } + /** Gets the native id of the current thread. */ + get id() { + return ptr(this.internal.field("thread_id").value.toString()).add(Il2Cpp.Thread.idOffset).readS32(); + } + /** @internal Gets the encompassing internal object (System.Threding.InternalThreead) of the current thread. */ + get internal() { + const internalThread = this.object.tryField("internal_thread")?.value; + return internalThread ? internalThread : this.object; + } + /** Determines whether the current thread is the garbage collector finalizer one. */ + get isFinalizer() { + return !Il2Cpp.Api._threadIsVm(this); + } + /** Gets the encompassing object of the current thread. */ + get object() { + return new Il2Cpp.Object(this); + } + /** @internal */ + get staticData() { + return this.internal.field("static_data").value; + } + /** @internal */ + get synchronizationContext() { + const get_ExecutionContext = this.object.tryMethod("GetMutableExecutionContext") || this.object.method("get_ExecutionContext"); + let synchronizationContext = get_ExecutionContext.invoke().tryMethod("get_SynchronizationContext")?.invoke(); + if (synchronizationContext == null) { + const SystemThreadingSynchronizationContext = Il2Cpp.Image.corlib.class("System.Threading.SynchronizationContext"); + for (let i = 0; i < 16; i++) { + try { + const candidate = new Il2Cpp.Object(this.staticData + .add(Process.pointerSize * i) + .readPointer() + .readPointer()); + if (candidate.class.isSubclassOf(SystemThreadingSynchronizationContext, false)) { + synchronizationContext = candidate; + break; + } + } + catch (e) { } + } + } + if (synchronizationContext == null) { + (0, console_1.raise)("couldn't retrieve the SynchronizationContext for this thread."); + } + return synchronizationContext; + } + /** Detaches the thread from the application domain. */ + detach() { + return Il2Cpp.Api._threadDetach(this); + } + /** Schedules a callback on the current thread. */ + schedule(block, delayMs = 0) { + const threadId = this.id; + const GetDisplayName = Il2Cpp.Image.corlib.class("Mono.Runtime").method("GetDisplayName"); + const SendOrPostCallback = Il2Cpp.Image.corlib.class("System.Threading.SendOrPostCallback").alloc(); + SendOrPostCallback.method(".ctor").invoke(NULL, GetDisplayName.handle); + const Post = this.synchronizationContext.method("Post"); + return new Promise(resolve => { + const listener = Interceptor.attach(GetDisplayName.virtualAddress, function () { + if (this.threadId == threadId) { + listener.detach(); + const result = block(); + setImmediate(() => resolve(result)); + } + }); + setTimeout(() => Post.invoke(SendOrPostCallback, NULL), delayMs); + }); + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppThread.prototype, "internal", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppThread.prototype, "object", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppThread.prototype, "staticData", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppThread.prototype, "synchronizationContext", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppThread, "idOffset", null); +Il2Cpp.Thread = Il2CppThread; + +}).call(this)}).call(this,require("timers").setImmediate) + +},{"../../utils/console":31,"../../utils/native-struct":32,"decorator-cache-getter":2,"timers":36}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); + +},{}],26:[function(require,module,exports){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const native_struct_1 = require("../../utils/native-struct"); +/** Represents a `Il2CppType`. */ +class Il2CppType extends native_struct_1.NonNullNativeStruct { + /** Gets the class of this type. */ + get class() { + return new Il2Cpp.Class(Il2Cpp.Api._classFromType(this)); + } + /** */ + get fridaAlias() { + if (this.isByReference) { + return "pointer"; + } + switch (this.typeEnum) { + case 1 /* Void */: + return "void"; + case 2 /* Boolean */: + return "bool"; + case 3 /* Char */: + return "uchar"; + case 4 /* I1 */: + return "int8"; + case 5 /* U1 */: + return "uint8"; + case 6 /* I2 */: + return "int16"; + case 7 /* U2 */: + return "uint16"; + case 8 /* I4 */: + return "int32"; + case 9 /* U4 */: + return "uint32"; + case 10 /* I8 */: + return "int64"; + case 11 /* U8 */: + return "uint64"; + case 12 /* R4 */: + return "float"; + case 13 /* R8 */: + return "double"; + case 17 /* ValueType */: + return getValueTypeFields(this); + case 24 /* NativeInteger */: + case 25 /* UnsignedNativeInteger */: + case 15 /* Pointer */: + case 14 /* String */: + case 29 /* SingleDimensionalZeroLowerBoundArray */: + case 20 /* Array */: + return "pointer"; + case 18 /* Class */: + case 28 /* Object */: + case 21 /* GenericInstance */: + return this.class.isValueType ? getValueTypeFields(this) : "pointer"; + default: + return "pointer"; + } + } + /** Determines whether this type is passed by reference. */ + get isByReference() { + return !!Il2Cpp.Api._typeIsByReference(this); + } + /** Determines whether this type is primitive. */ + get isPrimitive() { + return !!Il2Cpp.Api._typeIsPrimitive(this); + } + /** Gets the name of this type. */ + get name() { + const handle = Il2Cpp.Api._typeGetName(this); + try { + return handle.readUtf8String(); + } + finally { + Il2Cpp.free(handle); + } + } + /** Gets the encompassing object of the current type. */ + get object() { + return new Il2Cpp.Object(Il2Cpp.Api._typeGetObject(this)); + } + /** Gets the type enum of the current type. */ + get typeEnum() { + return Il2Cpp.Api._typeGetTypeEnum(this); + } + /** */ + toString() { + return this.name; + } +} +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "class", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "fridaAlias", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "isByReference", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "isPrimitive", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "name", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "object", null); +__decorate([ + decorator_cache_getter_1.cache +], Il2CppType.prototype, "typeEnum", null); +function getValueTypeFields(type) { + const instanceFields = type.class.fields.filter(f => !f.isStatic); + return instanceFields.length == 0 ? ["char"] : instanceFields.map(f => f.type.fridaAlias); +} +Reflect.set(Il2Cpp, "Type", Il2CppType); + +},{"../../utils/native-struct":32,"decorator-cache-getter":2}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const native_struct_1 = require("../../utils/native-struct"); +/** Value type class utility. */ +class Il2CppValueType extends native_struct_1.NativeStruct { + type; + constructor(handle, type) { + super(handle); + this.type = type; + } + /** Boxes the current value type in a object. */ + box() { + return new Il2Cpp.Object(Il2Cpp.Api._valueBox(this.type.class, this)); + } + /** Gets the field with the given name. */ + field(name) { + return this.type.class.field(name).withHolder(this); + } + /** */ + toString() { + return this.isNull() ? "null" : this.box().toString(); + } +} +Il2Cpp.ValueType = Il2CppValueType; + +},{"../../utils/native-struct":32}],28:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const console_1 = require("../utils/console"); +const utils_1 = require("./utils"); +/** Tracing utilities. */ +class Il2CppTracer { + /** @internal */ + targets = []; + /** @internal */ + #assemblies; + /** @internal */ + #classes; + /** @internal */ + #methods; + /** @internal */ + #assemblyFilter; + /** @internal */ + #classFilter; + /** @internal */ + #methodFilter; + /** @internal */ + #parameterFilter; + domain() { + return this; + } + assemblies(...assemblies) { + this.#assemblies = assemblies; + return this; + } + classes(...classes) { + this.#classes = classes; + return this; + } + methods(...methods) { + this.#methods = methods; + return this; + } + filterAssemblies(filter) { + this.#assemblyFilter = filter; + return this; + } + filterClasses(filter) { + this.#classFilter = filter; + return this; + } + filterMethods(filter) { + this.#methodFilter = filter; + return this; + } + filterParameters(filter) { + this.#parameterFilter = filter; + return this; + } + and() { + const filterMethod = (method) => { + if (this.#parameterFilter == undefined) { + this.targets.push(method); + return; + } + for (const parameter of method.parameters) { + if (this.#parameterFilter(parameter)) { + this.targets.push(method); + break; + } + } + }; + const filterMethods = (values) => { + for (const method of values) { + filterMethod(method); + } + }; + const filterClass = (klass) => { + if (this.#methodFilter == undefined) { + filterMethods(klass.methods); + return; + } + for (const method of klass.methods) { + if (this.#methodFilter(method)) { + filterMethod(method); + } + } + }; + const filterClasses = (values) => { + for (const klass of values) { + filterClass(klass); + } + }; + const filterAssembly = (assembly) => { + if (this.#classFilter == undefined) { + filterClasses(assembly.image.classes); + return; + } + for (const klass of assembly.image.classes) { + if (this.#classFilter(klass)) { + filterClass(klass); + } + } + }; + const filterAssemblies = (assemblies) => { + for (const assembly of assemblies) { + filterAssembly(assembly); + } + }; + const filterDomain = (domain) => { + if (this.#assemblyFilter == undefined) { + filterAssemblies(domain.assemblies); + return; + } + for (const assembly of domain.assemblies) { + if (this.#assemblyFilter(assembly)) { + filterAssembly(assembly); + } + } + }; + this.#methods + ? filterMethods(this.#methods) + : this.#classes + ? filterClasses(this.#classes) + : this.#assemblies + ? filterAssemblies(this.#assemblies) + : filterDomain(Il2Cpp.Domain); + this.#assemblies = undefined; + this.#classes = undefined; + this.#methods = undefined; + this.#assemblyFilter = undefined; + this.#classFilter = undefined; + this.#methodFilter = undefined; + this.#parameterFilter = undefined; + return this; + } + attach(mode = "full") { + let count = 0; + for (const target of this.targets) { + if (target.virtualAddress.isNull()) { + continue; + } + const offset = `\x1b[2m0x${target.relativeVirtualAddress.toString(16).padStart(8, `0`)}\x1b[0m`; + const fullName = `${target.class.type.name}.\x1b[1m${target.name}\x1b[0m`; + if (mode == "detailed") { + const startIndex = +!target.isStatic | +Il2Cpp.unityVersionIsBelow201830; + const callback = (...args) => { + const thisParameter = target.isStatic ? undefined : new Il2Cpp.Parameter("this", -1, target.class.type); + const parameters = thisParameter ? [thisParameter].concat(target.parameters) : target.parameters; + (0, console_1.inform)(`\ +${offset} ${`│ `.repeat(count++)}┌─\x1b[35m${fullName}\x1b[0m(\ +${parameters.map(e => `\x1b[32m${e.name}\x1b[0m = \x1b[31m${(0, utils_1.fromFridaValue)(args[e.position + startIndex], e.type)}\x1b[0m`).join(`, `)});`); + const returnValue = target.nativeFunction(...args); + (0, console_1.inform)(`\ +${offset} ${`│ `.repeat(--count)}└─\x1b[33m${fullName}\x1b[0m\ +${returnValue == undefined ? `` : ` = \x1b[36m${(0, utils_1.fromFridaValue)(returnValue, target.returnType)}`}\x1b[0m;`); + return returnValue; + }; + try { + target.revert(); + const nativeCallback = new NativeCallback(callback, target.returnType.fridaAlias, target.fridaSignature); + Interceptor.replace(target.virtualAddress, nativeCallback); + } + catch (e) { } + } + else { + try { + Interceptor.attach(target.virtualAddress, { + onEnter: () => (0, console_1.inform)(`${offset} ${`│ `.repeat(count++)}┌─\x1b[35m${fullName}\x1b[0m`), + onLeave: () => (0, console_1.inform)(`${offset} ${`│ `.repeat(--count)}└─\x1b[33m${fullName}\x1b[0m${count == 0 ? `\n` : ``}`) + }); + } + catch (e) { } + } + } + } +} +Il2Cpp.Tracer = Il2CppTracer; + +},{"../utils/console":31,"./utils":29}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toFridaValue = exports.fromFridaValue = exports.write = exports.read = void 0; +const console_1 = require("../utils/console"); +const native_struct_1 = require("../utils/native-struct"); +/** @internal */ +function read(pointer, type) { + switch (type.typeEnum) { + case 2 /* Boolean */: + return !!pointer.readS8(); + case 4 /* I1 */: + return pointer.readS8(); + case 5 /* U1 */: + return pointer.readU8(); + case 6 /* I2 */: + return pointer.readS16(); + case 7 /* U2 */: + return pointer.readU16(); + case 8 /* I4 */: + return pointer.readS32(); + case 9 /* U4 */: + return pointer.readU32(); + case 3 /* Char */: + return pointer.readU16(); + case 10 /* I8 */: + return pointer.readS64(); + case 11 /* U8 */: + return pointer.readU64(); + case 12 /* R4 */: + return pointer.readFloat(); + case 13 /* R8 */: + return pointer.readDouble(); + case 24 /* NativeInteger */: + case 25 /* UnsignedNativeInteger */: + return pointer.readPointer(); + case 15 /* Pointer */: + return new Il2Cpp.Pointer(pointer.readPointer(), type.class.baseType); + case 17 /* ValueType */: + return new Il2Cpp.ValueType(pointer, type); + case 28 /* Object */: + case 18 /* Class */: + return new Il2Cpp.Object(pointer.readPointer()); + case 21 /* GenericInstance */: + return type.class.isValueType ? new Il2Cpp.ValueType(pointer, type) : new Il2Cpp.Object(pointer.readPointer()); + case 14 /* String */: + return new Il2Cpp.String(pointer.readPointer()); + case 29 /* SingleDimensionalZeroLowerBoundArray */: + case 20 /* Array */: + return new Il2Cpp.Array(pointer.readPointer()); + } + (0, console_1.raise)(`read: "${type.name}" (${type.typeEnum}) has not been handled yet. Please file an issue!`); +} +exports.read = read; +/** @internal */ +function write(pointer, value, type) { + switch (type.typeEnum) { + case 2 /* Boolean */: + return pointer.writeS8(+value); + case 4 /* I1 */: + return pointer.writeS8(value); + case 5 /* U1 */: + return pointer.writeU8(value); + case 6 /* I2 */: + return pointer.writeS16(value); + case 7 /* U2 */: + return pointer.writeU16(value); + case 8 /* I4 */: + return pointer.writeS32(value); + case 9 /* U4 */: + return pointer.writeU32(value); + case 3 /* Char */: + return pointer.writeU16(value); + case 10 /* I8 */: + return pointer.writeS64(value); + case 11 /* U8 */: + return pointer.writeU64(value); + case 12 /* R4 */: + return pointer.writeFloat(value); + case 13 /* R8 */: + return pointer.writeDouble(value); + case 24 /* NativeInteger */: + case 25 /* UnsignedNativeInteger */: + case 15 /* Pointer */: + case 17 /* ValueType */: + case 14 /* String */: + case 28 /* Object */: + case 18 /* Class */: + case 29 /* SingleDimensionalZeroLowerBoundArray */: + case 20 /* Array */: + case 21 /* GenericInstance */: + if (value instanceof Il2Cpp.ValueType) { + Memory.copy(pointer, value.handle, type.class.valueSize); + return pointer; + } + return pointer.writePointer(value); + } + (0, console_1.raise)(`write: "${type.name}" (${type.typeEnum}) has not been handled yet. Please file an issue!`); +} +exports.write = write; +/** @internal */ +function fromFridaValue(value, type) { + if (Array.isArray(value)) { + return arrayToValueType(type, value); + } + else if (value instanceof NativePointer) { + if (type.isByReference) { + return new Il2Cpp.Reference(value, type); + } + switch (type.typeEnum) { + case 15 /* Pointer */: + return new Il2Cpp.Pointer(value, type.class.baseType); + case 14 /* String */: + return new Il2Cpp.String(value); + case 18 /* Class */: + case 21 /* GenericInstance */: + case 28 /* Object */: + return new Il2Cpp.Object(value); + case 29 /* SingleDimensionalZeroLowerBoundArray */: + case 20 /* Array */: + return new Il2Cpp.Array(value); + default: + return value; + } + } + else if (type.typeEnum == 2 /* Boolean */) { + return !!value; + } + else { + return value; + } +} +exports.fromFridaValue = fromFridaValue; +/** @internal */ +function toFridaValue(value) { + if (typeof value == "boolean") { + return +value; + } + else if (value instanceof Il2Cpp.ValueType) { + return valueTypeToArray(value); + } + else { + return value; + } +} +exports.toFridaValue = toFridaValue; +function valueTypeToArray(value) { + const instanceFields = value.type.class.fields.filter(f => !f.isStatic); + return instanceFields.length == 0 + ? [value.handle.readU8()] + : instanceFields + .map(field => field.withHolder(value).value) + .map(value => value instanceof Il2Cpp.ValueType + ? valueTypeToArray(value) + : value instanceof native_struct_1.NativeStruct + ? value.handle + : typeof value == "boolean" + ? +value + : value); +} +function arrayToValueType(type, nativeValues) { + function iter(type, startOffset = 0) { + const arr = []; + for (const field of type.class.fields) { + if (!field.isStatic) { + const offset = startOffset + field.offset - Il2Cpp.Runtime.objectHeaderSize; + if (field.type.typeEnum == 17 /* ValueType */ || + (field.type.typeEnum == 21 /* GenericInstance */ && field.type.class.isValueType)) { + arr.push(...iter(field.type, offset)); + } + else { + arr.push([field.type.typeEnum, offset]); + } + } + } + if (arr.length == 0) { + arr.push([5 /* U1 */, 0]); + } + return arr; + } + const valueType = Memory.alloc(type.class.valueSize); + nativeValues = nativeValues.flat(Infinity); + const typesAndOffsets = iter(type); + for (let i = 0; i < nativeValues.length; i++) { + const value = nativeValues[i]; + const [typeEnum, offset] = typesAndOffsets[i]; + const pointer = valueType.add(offset); + switch (typeEnum) { + case 2 /* Boolean */: + pointer.writeS8(value); + break; + case 4 /* I1 */: + pointer.writeS8(value); + break; + case 5 /* U1 */: + pointer.writeU8(value); + break; + case 6 /* I2 */: + pointer.writeS16(value); + break; + case 7 /* U2 */: + pointer.writeU16(value); + break; + case 8 /* I4 */: + pointer.writeS32(value); + break; + case 9 /* U4 */: + pointer.writeU32(value); + break; + case 3 /* Char */: + pointer.writeU16(value); + break; + case 10 /* I8 */: + pointer.writeS64(value); + break; + case 11 /* U8 */: + pointer.writeU64(value); + break; + case 12 /* R4 */: + pointer.writeFloat(value); + break; + case 13 /* R8 */: + pointer.writeDouble(value); + break; + case 24 /* NativeInteger */: + case 25 /* UnsignedNativeInteger */: + case 15 /* Pointer */: + case 29 /* SingleDimensionalZeroLowerBoundArray */: + case 20 /* Array */: + case 14 /* String */: + case 28 /* Object */: + case 18 /* Class */: + case 21 /* GenericInstance */: + pointer.writePointer(value); + break; + default: + (0, console_1.warn)(`arrayToValueType: defaulting ${typeEnum} to pointer`); + pointer.writePointer(value); + break; + } + } + return new Il2Cpp.ValueType(valueType, type); +} + +},{"../utils/console":31,"../utils/native-struct":32}],30:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("./il2cpp"); + +},{"./il2cpp":7}],31:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.inform = exports.ok = exports.warn = exports.raise = void 0; +/** @internal */ +function raise(message) { + throw `\x1B[0m\x1B[38;5;9mil2cpp\x1B[0m: ${message}`; +} +exports.raise = raise; +/** @internal */ +function warn(message) { + globalThis.console.log(`\x1B[38;5;11mil2cpp\x1B[0m: ${message}`); +} +exports.warn = warn; +/** @internal */ +function ok(message) { + globalThis.console.log(`\x1B[38;5;10mil2cpp\x1B[0m: ${message}`); +} +exports.ok = ok; +/** @internal */ +function inform(message) { + globalThis.console.log(`\x1B[38;5;12mil2cpp\x1B[0m: ${message}`); +} +exports.inform = inform; + +},{}],32:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NonNullNativeStruct = exports.NativeStruct = void 0; +/** Scaffold class. */ +class NativeStruct { + handle; + constructor(handleOrWrapper) { + if (handleOrWrapper instanceof NativePointer) { + this.handle = handleOrWrapper; + } + else { + this.handle = handleOrWrapper.handle; + } + } + equals(other) { + return this.handle.equals(other.handle); + } + isNull() { + return this.handle.isNull(); + } +} +exports.NativeStruct = NativeStruct; +/** Scaffold class whom pointer cannot be null. */ +class NonNullNativeStruct extends NativeStruct { + constructor(handle) { + super(handle); + if (handle.isNull()) { + throw new Error(`Handle for "${this.constructor.name}" cannot be NULL.`); + } + } +} +exports.NonNullNativeStruct = NonNullNativeStruct; + +},{}],33:[function(require,module,exports){ +(function (setImmediate){(function (){ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.forModule = void 0; +const decorator_cache_getter_1 = require("decorator-cache-getter"); +const versioning_1 = __importDefault(require("versioning")); +class Target { + stringEncoding; + address; + constructor(responsible, name, stringEncoding) { + this.stringEncoding = stringEncoding; + this.address = Module.findExportByName(responsible, name) ?? NULL; + } + static get targets() { + function info() { + switch (Process.platform) { + case "linux": + try { + if (versioning_1.default.gte(Java.androidVersion, "12")) { + return [null, ["__loader_dlopen", "utf8"]]; + } + else { + return ["libdl.so", ["dlopen", "utf8"], ["android_dlopen_ext", "utf8"]]; + } + } + catch (e) { + return [null, ["dlopen", "utf8"]]; + } + case "darwin": + return ["libdyld.dylib", ["dlopen", "utf8"]]; + case "windows": + const ll = "LoadLibrary"; + return ["kernel32.dll", [`${ll}W`, "utf16"], [`${ll}ExW`, "utf16"], [`${ll}A`, "ansi"], [`${ll}ExA`, "ansi"]]; + } + } + const [responsible, ...targets] = info(); + return targets.map(([name, encoding]) => new Target(responsible, name, encoding)).filter(target => !target.address.isNull()); + } + readString(pointer) { + switch (this.stringEncoding) { + case "utf8": + return pointer.readUtf8String(); + case "utf16": + return pointer.readUtf16String(); + case "ansi": + return pointer.readAnsiString(); + } + } +} +__decorate([ + decorator_cache_getter_1.cache +], Target, "targets", null); +/** @internal */ +function forModule(...moduleNames) { + return new Promise(resolve => { + for (const moduleName of moduleNames) { + const module = Process.findModuleByName(moduleName); + if (module != null) { + resolve(moduleName); + return; + } + } + const interceptors = Target.targets.map(target => Interceptor.attach(target.address, { + onEnter(args) { + this.modulePath = target.readString(args[0]) ?? ""; + }, + onLeave(returnValue) { + if (returnValue.isNull()) + return; + for (const moduleName of moduleNames) { + if (!this.modulePath.endsWith(moduleName)) + continue; + setImmediate(() => interceptors.forEach(i => i.detach())); + resolve(moduleName); + } + } + })); + }); +} +exports.forModule = forModule; + +}).call(this)}).call(this,require("timers").setImmediate) + +},{"decorator-cache-getter":2,"timers":36,"versioning":37}],34:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.levenshtein = exports.cacheInstances = exports.nativeIterator = void 0; +const fastest_levenshtein_1 = require("fastest-levenshtein"); +const console_1 = require("./console"); +/** @internal */ +function* nativeIterator(holder, nativeFunction, Class) { + const iterator = Memory.alloc(Process.pointerSize); + let handle; + while (!(handle = nativeFunction(holder, iterator)).isNull()) { + yield new Class(handle); + } +} +exports.nativeIterator = nativeIterator; +/** @internal */ +function cacheInstances(Class) { + const instanceCache = new Map(); + return new Proxy(Class, { + construct(Target, argArray) { + const handle = argArray[0].toUInt32(); + if (!instanceCache.has(handle)) { + instanceCache.set(handle, new Target(argArray[0])); + } + return instanceCache.get(handle); + } + }); +} +exports.cacheInstances = cacheInstances; +/** @internal */ +function levenshtein(candidatesKey, nameGetter = e => e.name) { + return function (_, propertyKey, descriptor) { + const original = descriptor.value; + descriptor.value = function (key, ...args) { + const result = original.call(this, key, ...args); + if (result != null) + return result; + const closestMatch = (0, fastest_levenshtein_1.closest)(key, this[candidatesKey].map(nameGetter)); + (0, console_1.raise)(`couldn't find ${propertyKey} ${key} in ${this.name}${closestMatch ? `, did you mean ${closestMatch}?` : ``}`); + }; + }; +} +exports.levenshtein = levenshtein; + +},{"./console":31,"fastest-levenshtein":3}],35:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],36:[function(require,module,exports){ +(function (setImmediate,clearImmediate){(function (){ +var nextTick = require('process/browser.js').nextTick; +var apply = Function.prototype.apply; +var slice = Array.prototype.slice; +var immediateIds = {}; +var nextImmediateId = 0; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { timeout.close(); }; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } +}; + +// That's not how node.js implements it but the exposed api is the same. +exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); + } else { + fn.call(null); + } + // Prevent ids from leaking + exports.clearImmediate(id); + } + }); + + return id; +}; + +exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; +}; +}).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate) + +},{"process/browser.js":35,"timers":36}],37:[function(require,module,exports){ +/** + * Semantic Version Number + * @author 闲耘 + * + * @usage + * var version = new Versioning("1.2.3") + * version > 1 + * version.eq(1) + */ + + +// Semantic Versioning Delimiter. +var delimiter = "."; + +var Version = function(version){ + this._version = String(version); +}; + +function compare(v1, v2, complete){ + v1 = String(v1); + v2 = String(v2); + if(v1 === v2){return 0;} + var v1s = v1.split(delimiter); + var v2s = v2.split(delimiter); + var len = Math[complete ? "max" : "min"](v1s.length, v2s.length); + for(var i=0; i v2s[i]){return 1;} + if(v1s[i] < v2s[i]){return -1;} + } + return 0; +} + +Version.compare = function(v1, v2){ + return compare(v1, v2, true); +}; + +/** + * @param {String} v1. + * @param {String} v2. + * @return {Boolean} true if v1 equals v2. + * + * Version.eq("6.1", "6"); // true. + * Version.eq("6.1.2", "6.1"); // true. + */ +Version.eq = function(v1, v2, strict){ + return compare(v1, v2, strict) === 0; +}; + +/** + * @param {String} v1. + * @param {String} v2. + * @return {Boolean} return true + */ +Version.gt = function(v1, v2){ + return compare(v1, v2, true) > 0; +}; + +Version.gte = function(v1, v2){ + return compare(v1, v2, true) >= 0; +}; + +Version.lt = function(v1, v2){ + return compare(v1, v2, true) < 0; +}; + +Version.lte = function(v1, v2){ + return compare(v1, v2, true) <= 0; +}; + +Version.prototype = { + // new Version("6.1").eq(6); // true. + // new Version("6.1.2").eq("6.1"); // true. + eq: function(version){ + return Version.eq(this._version, version); + }, + + gt: function(version){ + return Version.gt(this._version, version); + }, + + gte: function(version){ + return Version.gte(this._version, version); + }, + + lt: function(version){ + return Version.lt(this._version, version); + }, + + lte: function(version){ + return Version.lte(this._version, version); + }, + + valueOf: function(){ + return parseFloat( + this._version.split(delimiter).slice(0, 2).join(delimiter), + 10); + }, + + /** + * XXX: ""+ver 调用的转型方法是 valueOf,而不是 toString,这个有点悲剧。 + * 只能使用 String(ver) 或 ver.toString() 方法。 + * @param {Number} precision, 返回的版本号精度。默认返回完整版本号。 + * @return {String} + */ + toString: function(precision){ + return "undefined" === typeof precision ? this._version : + this._version.split(delimiter).slice(0, precision).join(delimiter); + } +}; + + +module.exports = Version; + +},{}]},{},[1])