Extending number of players

Mass Effect 3 Private Server Emulator is a replacement for the Origin/Blaze backend that handles the online component of Mass Effect 3.

Moderator: PSE Developer

User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Extending number of players

Post by Mgamerz »

I've been looking into this for some time, and since you've done quite a bit of work on the blaze side of things I'm wondering if you know anything about the openness of a lobby (from the matchmaking bot perspective) in terms of the number of players. I beleive I can raise the number of players (UI will be messed up of course) but the only thing that has stopped mei n the past is that origin closes the lobby so you cannot "invite" or click "join game". In your tests have you seen anything like this happen before?

I've also been looking to perhaps doing this directly through the console. This is the function the game uses when starting an MP game.

Code: Select all

[CB: 0x03]SFXGameMPContent.SFXGameInfoMP_Lobby.OnMPGameStarted(Function) (Superclass: Class) (Data Offset: 0x 137F5)
==============Function==============
Childindex : 95
Unknown1 : 97
Unknown2 : 861
Script Size : 661
Flags ( Defined Public  )
Native Index: 0
Script:
20 : If(OnlineSub)
	{
		GameInterface = OnlineSub.GameInterface;
	}
40 : If (!(NotEqual_InterfaceInterface(GameInterface,OnlineGameInterface,None))) Goto(0x2E9);
54 : If(bWasSuccessful){GameInterface.ClearCreateOnlineGameCompleteDelegate(OnCreateGameComplete);}
81 : GameInterface.ClearQuickMatchCompleteDelegate(OnQuickMatchComplete);
A6 : GameInterface.ClearDestroyOnlineGameCompleteDelegate(OnMultiplayerGameDestroyed);
CB : If (!(GameInterface.GetResolvedConnectString('Game',connectString);)) Goto(0x282);
F4 : connectString $= '?origin=MultiplayerMenu'
11A : connectString $= '?privacy=' $ MatchMakingGameSettings.GetPrivacy()
150 : connectString $= '?map=' $ MatchMakingGameSettings.mME3MapName
179 : connectString $= '?enemy=' $ MatchMakingGameSettings.EnemyType
1A6 : connectString $= '?difficulty=' $ MatchMakingGameSettings.Difficulty
1DA : connectString = 'open ' $ connectString;
1EF : Goto(0x2B0)
1F2 : OnMPFatalError('GetResolvedConnectString failed.')
220 : Goto(0x2E6)
223 : OnMPNetworkError('Starting MP match failed.')
24A : CancelSearch()
256 : Goto(0x306)
259 : OnMPFatalError(this @ GetFuncName())
272 : Goto(0x326)
275 : OnMPFatalError(this @ GetFuncName())
28E : WorldInfo.ConsoleCommand(connectString,null)
2B2 : Return ();
2B4 : \\End of Script
I am wondering if you can connect to other players this way.
User avatar
Erik JS
Posts: 110
Joined: Sun Jan 10, 2016 8:03 pm
Location: Brazil

Re: Extending number of players

Post by Erik JS »

Well, from what I saw, the player capacity is set by the lobby creator. When a player wants to create a lobby, ME3 sends a createGame packet to the server. Sample:

Code: Select all

ATTR
BTPL => 0 0 0 (0x0 0x0 0x0)
GCTR => 
GENT => 0 (0x0)
GNAM => TEST
GSET => 287 (0x11F)
GTYP => 
GURL => 
HNET list: 3
_ Entry #0
_ _ EXIP
_ _ _ IP   => 0 (0x0)
_ _ _ PORT => 0 (0x0)
_ _ INIP
_ _ _ IP   => 3232235876 (0xC0A80164)
_ _ _ PORT => 3659 (0xE4B)
IGNO => 0 (0x0)
NRES => 0 (0x0)
NTOP => 0 (0x0)
PCAP list: 0 (player capacity)
_ 4 (0x00000004), 0 (0x00000000)
PGID => 
PGSC
PMAX => 4 (0x4) (maximum number of players)
PRES => 1 (0x1)
QCAP => 0 (0x0)
RGID => 0 (0x0)
SLOT => 0 (0x0)
TCAP => 0 (0x0)
TIDX => 65535 (0xFFFF)
VOIP => 2 (0x2)
VSTR => ME3-295976325-179181965240128
Anyone joining that lobby (including the creator) will receive a returnDedicatedServerToPool packet, where copies of PCAP and PMAX are present (as CAP and MCAP, respectively).

The way PSE is coded prevents a client from receiving returnDedicatedServerToPool from a fully filled lobby when searching for matches, but that can be changed (and values easily manipulated).

Regarding EA server, currently I see two ways of manipulating player capacity:
1) we hack a PCC or the EXE so the game sends whatever we want (this certainly will take time to figure out);
2) we use PSE and send a packet modified through MITM (I can code this up).

I think I'll go with #2 here. This won't be the first time I send "unofficial" values/packets to EA server.
User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Re: Extending number of players

Post by Mgamerz »

Ive been looking through a lot of PCC files, and have a pretty comprehensive text file dump of everything (enums, scripts, names, exports, names, properties) if you're interested. Most of what I have found is an in game limit of 4 (in 3 places) but it seems that origin is still marking my lobby as full. I was thinking of running a debugger like you and warrantyvoider used to see if I can find out what's going on but I don't have the technical skills to do that. You wrote an extension to binkw32.dll, and I was wondering if you have any knowledge to share on how you did that. (I haven't done much dll work... Want to learn how to hijack game like bink does though)

The really only relevant thing I have seen is a native GetNumPlayers() method related to online subsystem. I obviously can't see it.

Additionally, I am curious where the game knows how to find the balance changes URL. I dumped strings from a decrypted exe and didn't see anything related to the URL... I assume possibly one of the dlls?


Edit: just re-read the beginning... I haven't fully tested my game yet. It's really hard to get 5 players to do this on the official servers. I've seen a lot of online game submission code but I haven't figured out how the number of players is sent (wasn't even aware).
User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Re: Extending number of players

Post by Mgamerz »

Been looking through more code. Found some interesting stuff. This is from Patch_SFXOnlineFoundation.pcc in the TESTPATCH.

Code: Select all

=======================================================================
[CB: 0x00]SFXOnlineGameSettings.IsPrivateMatch(Function) (Superclass: Class) (Data Offset: 0x CC09A)
==============Function==============
Childindex : 5006
Unknown1 : 5007
Unknown2 : 24
Script Size : 16
Flags ( Defined Event Public  )
Native Index: 0
Script:
20 : Return (NumPublicConnections == 0);
29 : Return (ByteToInt(ReturnValue));
2F : \\End of Script

Debug print:

0 :                     EX_Return[0x04]         0x20     Return (NumPublicConnections == 0);
1 :      NATIVE_EqualEqual_IntInt[0x9A]         0x21     NumPublicConnections == 0
2 :                     EX_Unkn11[0x60]         0x22     NumPublicConnections
3 :                    EX_IntZero[0x25]         0x27     0    
4 :           EX_EndFunctionParms[0x16]         0x28          
5 :                     EX_Return[0x04]         0x29     Return (ByteToInt(ReturnValue));
6 :                  EX_ByteToInt[0x3A]         0x2A     ByteToInt(ReturnValue)
7 :                EX_EndOfScript[0x53]         0x2F     \\End of Script

=======================================================================
[CB: 0x00]SFXOnlineGameSettings.SetPrivate.isPrivate(BoolProperty) (Superclass: Class) (Data Offset: 0x CC0D0)
=======================================================================
[CB: 0x00]SFXOnlineGameSettings.SetPrivate(Function) (Superclass: Class) (Data Offset: 0x CC0FC)
==============Function==============
Childindex : 5008
Unknown1 : 5009
Unknown2 : 54
Script Size : 38
Flags ( Defined Event Public  )
Native Index: 0
Script:
20 : NumPublicConnections = (isPrivate) ? 0 : 4;
34 : NumPrivateConnections = 4 - NumPublicConnections;
43 : Return ();
45 : \\End of Script

=======================================================================
[CB: 0x02]SFXOnlineFoundation.SFXOnlineGameSettings.Copy(Function) (Superclass: Class) (Data Offset: 0x 9E78)
==============Function==============
Childindex : 71
Unknown1 : 73
Unknown2 : 571
Script Size : 347
Flags ( Defined Event Public  )
Native Index: 0
Script:
20 : Copy = new(,,,Class 'SFXOnlineGameSettings');
2F : 
30 : Copy.mPrivacySetting = mPrivacySetting;
48 : Copy.mME3MapName = mME3MapName;
60 : Copy.mMapIsRequired = mMapIsRequired;
7A : Copy.EnemyType = EnemyType;
92 : Copy.Difficulty = Difficulty;
AA : Copy.mCreateNewMatch = mCreateNewMatch;
C4 : Copy.mFromGalaxyMap = mFromGalaxyMap;
DE : Copy.NumPublicConnections = NumPublicConnections;
F6 : Copy.NumPrivateConnections = NumPrivateConnections;
10E : Copy.NumOpenPublicConnections = NumOpenPublicConnections;
126 : Copy.NumOpenPrivateConnections = NumOpenPrivateConnections;
13E : Copy.invitedUserId = invitedUserId;
156 : Copy. = ;
16E : Return (Copy);
174 : Return (ByteToInt(ReturnValue));
17A : \\End of Script

=======================================================================
[CB: 0x00]SFXOnlineFoundation.Default__SFXOnlineGameSettings(Default__SFXOnlineGameSettings) (Superclass: Class) (Data Offset: 0x A67E)
=================================================Properties=================================================
|                                    Name|           Type|      Size|                         Value|
|                           MasterMapList|          Array|      2920|                    2920 items|
|                           AvailableMaps|          Array|       168|                     168 items|
|                            PrivacyTypes|          Array|       406|                     406 items|
|                              EnemyTypes|          Array|      1142|                    1142 items|
|                          ChallengeTypes|          Array|       610|                     610 items|
|                             AnyMapImage|         String|        40|GUI_MPImages.MatchSettings.OptMapRandom|
|                           AnyEnemyImage|         String|        40|GUI_MPImages.MatchSettings.OptEmyRandom|
|                       AnyChallengeImage|         String|        43|GUI_MPImages.MatchSettings.OptChallgRandom|
|                                srAnyMap|     String Ref|         4|                        716860|
|                              srAnyEnemy|     String Ref|         4|                        716861|
|                          srAnyChallenge|     String Ref|         4|                        722468|
|                    NumPublicConnections|        Integer|         4|                             4|
|                              Properties|          Array|       184|                     184 items|
|                        PropertyMappings|          Array|       276|                     276 items|
==================================================================================================
As you can see, the number of public AND private connections is always set to 4 here... perhaps if I made them both 3, I could get 3 from both? I don't see a properties for NumPrivateConnections, but it seems that public defaults to 4. If this is raised to say, 8, the gmae will still do 0:4 unless that other part is modified. I don't know where these values are used, my search has no results. I assume it's used in native.

Looking at your code, it kind of looks like maybe this is PCAP? (you have 0, 4 for that listed). Perhaps I should fire up PSE and modify this PCC and see what comes up. Haven't used PSE since it was very new.
User avatar
Erik JS
Posts: 110
Joined: Sun Jan 10, 2016 8:03 pm
Location: Brazil

Re: Extending number of players

Post by Erik JS »

Live post (from Notepad :P):

- Programming is ready. Packet will be recreated with the new value for capacity before being handled by PSE's main server, or sent to EA.

*** Test with cap = 5 ***

- PSE offline profile: everything goes well, PSE's returnDedicatedServerToPool is still hardcoded to 4, so nothing really changes.

*** Now on MITM, under Origin ***

- Private match: everything goes well, I checked returnDedicatedServerToPool and its cap is 5. So EA server acknowledges any cap sent by the lobby creator.

*** Time to go public (with changed name just in case shit happens on other people side so they don't blame me :D) ***

- Public match: lobby created, cap has been set as in private match, waiting for people.

- Nobody joins, tested all difficulties, unknown/unknown. From looking at the log, it seems some algorithm at EA server prevents my lobby from being returned to anyone (obviously they don't expect someone to open a 5-player lobby), no evidence of anyone trying to connect to me and failing.

*** New test with cap = 2, suppressing PSE LAN and MITM private since they'll definitely produce the same results ***

- Public lobby created: waiting...

- Success! One guy joined.

- 2 minutes and no one else joins... I'll just click "ready"...

- Glacier/Geth/Bronze, 13 minutes. The other guy was a level 14 Novaguard, died 4 times. Far from being an idiot, he helped with objectives.

- Back to lobby, waiting for more people.

- No one else joins. If I get out, the other guy will become the leader, and I fear that... never mind, he just left, I'll leave now.

That's it. Player capacity can be manipulated to have less than 4 players in a lobby, but not more. Next test will be on PSE LAN, where I'll try to force 5 clients to join the same lobby.
Mgamerz wrote:Ive been looking through a lot of PCC files, and have a pretty comprehensive text file dump of everything (enums, scripts, names, exports, names, properties) if you're interested.
I assume it includes scripts from DLC's and the TESTPATCH or whatever it's called, right?
Currently, most of the things I find in scripts is through ScriptDB, where I use my own search function.
http://me3explorer.freeforums.org/scrip ... t1871.html
Mgamerz wrote: You wrote an extension to binkw32.dll, and I was wondering if you have any knowledge to share on how you did that. (I haven't done much dll work... Want to learn how to hijack game like bink does though)
Feel free to ask me anything about that and I'll try to answer the best I can.
Is there some other game where you need a fake dll for it?
Mgamerz wrote: Additionally, I am curious where the game knows how to find the balance changes URL. I dumped strings from a decrypted exe and didn't see anything related to the URL... I assume possibly one of the dlls?
There's no URL for balance changes. It's part of the communication with the main game server. The game asks for "ME3_BINI_PC_COMPRESSED" in a packet, and as response the server sends the compressed content of a remote Coalesced file, whatever the hell is its name in EA server, assuming it's a file at all - could be a bunch of bytes stored in some db, the final result would still be the same on our side.
There's a "ME3_BINI_PC" string in the game's memory. Maybe if you change that to something like "ME3_BINI_XX" it will prevent the game from getting the remote Coalesced, since EA server (and even PSE) won't recognize that request.
Fake edit: actually, you have to change "ME3_BINI_VERSION" - the game sends that to the server, the server replies with "BINI_PC_COMPRESSED", then the game asks for "ME3_BINI_PC_COMPRESSED".
User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Re: Extending number of players

Post by Mgamerz »

The game has some hardcode values in areas where max players is set to 4. I think even if you did 5 players on PSE it still would reject the 5th because it prevents it from being actually added to the list of players. Via coalesced I can lower the number of players actually.

Raising I've never been able to test because the lobby appears closed on origin/matchmaking once it fills up. I have a group of people in private lobbies I can ask to help join my game.

Edit: wait so you raised cap on private game to 5 and it returned 5? Could you show me how to do that <3?

I wonder if it's possible to write some reliable way of disabling balance changes if your method works. I would love a krysae that isn't absolutely terrible. This project is pretty useful, I was not aware you could MITM with actual EA server, only read EA and read/write PSE.
User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Re: Extending number of players

Post by Mgamerz »

Used cheat engine today, quite a program. I was able to find the lobby data and see the number of players changing. Setting this byte didn't seem to actually do anything for me though for origin seeing my lobby as full or not. Couldn't disable balance changes either, overwrote a lot of stuff, no changes happened.
User avatar
Erik JS
Posts: 110
Joined: Sun Jan 10, 2016 8:03 pm
Location: Brazil

Re: Extending number of players

Post by Erik JS »

Mgamerz wrote:Edit: wait so you raised cap on private game to 5 and it returned 5? Could you show me how to do that <3?
I still didn't the 5 client test here, but I compiled a test version of PSE for you:
http://www.mediafire.com/download/y6f8j ... pacity.rar
New menu: Test -> Player Capacity.
It'll change client's (game's) createGame request, replacing its original capacity with whatever is set on PSE. You can then check out on Tools -> Packet Viewer the corresponding returnDedicatedServerToPool sent by EA server.
Mgamerz wrote: I was able to find the lobby data and see the number of players changing.
You mean this?
http://me3explorer.freeforums.org/post11683.html#p11683
Mgamerz wrote: Couldn't disable balance changes either, overwrote a lot of stuff, no changes happened.
Image
By default, 'Writable' is checked, "ME3_BINI_VERSION" is in a read-only space.
Mgamerz wrote: This project is pretty useful, I was not aware you could MITM with actual EA server, only read EA and read/write PSE.
It's possible to do some crazy shit with MITM. Aside from being able to manipulate ME3 requests and EA responses, you can also send "loose" packets to EA (which is how "Import player settings" work).

I can confirm that the remote Coalesced can be disabled, but there's something I still can't confirm which is what happens to the weekend challenges. I suspect they may get erased because, as the game has no information about them since they are never sent to it in the first place, the game may (will?) send to EA "incomplete" information about challenge completions, so when you log back with the balance changes enabled your stats on weekend challenges will be 0.
User avatar
Mgamerz
Site Admin
Posts: 571
Joined: Wed Jan 06, 2016 1:13 am

Re: Extending number of players

Post by Mgamerz »

Some of the challenges data is stored in testpatch. There is no null value assignment so technically one could add new challenges with edits, but its pretty complex and I couldn't figure it out. On normal servers I am unsure if it would work because you'd need to be able to grant yourself an entitlement. On PSE that'd be easy since you can just grant loads of entitlements.

I found the items you specified, made the page writable, overwrote all the stuff eith garbage, but things in MP still acted like they normally do. Crappy krysae, rocket didn't wind up... I pretty much changed all of the stuff you mentioned before going to the main menu. I see two instances of _BINI and they were right by each other. I did use your post as a reference, but they reorganized the forums and I had no idea where to look after I found it the first time (search is not very useful)


Also I dont think sending incomplete version info is an issue. I added chakram launcher/polonium rounds/vibration damper and the server persists their progression even if a mod that enables them is not installed.
You can probably move all of the challenges into patch1 (which is useless as patch2 fully supercedes it) and you would have no issues.

Sorry if I seem like a noob at this... New to memory editing stuff.

When I get a chance I'll test out your 5 players test.
User avatar
Erik JS
Posts: 110
Joined: Sun Jan 10, 2016 8:03 pm
Location: Brazil

Re: Extending number of players

Post by Erik JS »

Were you able to select "Friends Only" as privacy when trying to create a match? If yes, then you have successfully disabled the remote Coalesced.

Balance changes are also enforced through Patch02, if memory isn't failing me I think we both mentioned this at some point back in ME3Ex forums. I did two tests (Origin and PSE), and in both cases the rocket reverted itself to the "charging" state. You need to disable the remote Coalesced *AND* edit Patch02's Coalesced (last thing on BioWeapon.xml).
Post Reply