|
15 | 15 |
|
16 | 16 | NetLibrary* g_netLibrary; |
17 | 17 |
|
| 18 | +#include <HostSystem.h> |
| 19 | + |
18 | 20 | // shared relay functions (from early rev. gta:net:five; do update!) |
19 | 21 | #include <ws2tcpip.h> |
20 | 22 |
|
@@ -699,6 +701,148 @@ static int ReturnTrue() |
699 | 701 | return true; |
700 | 702 | } |
701 | 703 |
|
| 704 | + |
| 705 | +GTA_NET_EXPORT fwEvent<HostState, HostState> OnHostStateTransition; |
| 706 | + |
| 707 | +struct HostStateHolder |
| 708 | +{ |
| 709 | + HostState state; |
| 710 | + |
| 711 | + inline bool operator==(HostState right) |
| 712 | + { |
| 713 | + return (state == right); |
| 714 | + } |
| 715 | + |
| 716 | + inline HostState operator=(HostState right) |
| 717 | + { |
| 718 | + trace("SessionState transitioning from %s to %s\n", HostStateToString(state), HostStateToString(right)); |
| 719 | + |
| 720 | + AddCrashometry("hs_state", HostStateToString(right)); |
| 721 | + |
| 722 | + OnHostStateTransition(right, state); |
| 723 | + state = right; |
| 724 | + |
| 725 | + return right; |
| 726 | + } |
| 727 | +}; |
| 728 | + |
| 729 | +struct |
| 730 | +{ |
| 731 | + HostStateHolder state; |
| 732 | + int attempts; |
| 733 | + |
| 734 | + std::string hostResult; |
| 735 | + |
| 736 | + void handleHostResult(const std::string& str) |
| 737 | + { |
| 738 | + hostResult = str; |
| 739 | + } |
| 740 | + |
| 741 | + void process() |
| 742 | + { |
| 743 | + ICoreGameInit* cgi = Instance<ICoreGameInit>::Get(); |
| 744 | + |
| 745 | + switch (state.state) |
| 746 | + { |
| 747 | + case SESSION_STATE_NONE: |
| 748 | + { |
| 749 | + // update presence |
| 750 | + _rlPresence_GamerPresence_Clear(rlPresence__m_GamerPresences); |
| 751 | + _rlPresence_refreshSigninState(0); |
| 752 | + _rlPresence_refreshNetworkStatus(0); |
| 753 | + |
| 754 | + state = SESSION_STATE_ENTER; |
| 755 | + break; |
| 756 | + } |
| 757 | + case SESSION_STATE_ENTER: |
| 758 | + // wait for transition |
| 759 | + if (_getCurrentTransitionState() == 0) |
| 760 | + { |
| 761 | + state = SESSION_STATE_START_JOINING; |
| 762 | + } |
| 763 | + |
| 764 | + break; |
| 765 | + |
| 766 | + case SESSION_STATE_START_JOINING: |
| 767 | + { |
| 768 | + auto lastThread = rage::scrEngine::GetActiveThread(); |
| 769 | + rage::scrEngine::SetActiveThread(fakeThread.GetThread()); |
| 770 | + |
| 771 | + // transition to mp |
| 772 | + _transitionToState(0x73040199); |
| 773 | + |
| 774 | + rage::scrEngine::SetActiveThread(lastThread); |
| 775 | + |
| 776 | + state = SESSION_STATE_JOINING; |
| 777 | + break; |
| 778 | + } |
| 779 | + case SESSION_STATE_JOINING: |
| 780 | + // wait for transition |
| 781 | + if (_getCurrentTransitionState() == 0x73040199) // MP MODE |
| 782 | + { |
| 783 | + state = SESSION_STATE_JOINED; |
| 784 | + } |
| 785 | + else if (_getCurrentTransitionState() == 0x1D94DE8C || _getCurrentTransitionState() == 0) // SP MODE |
| 786 | + { |
| 787 | + state = SESSION_STATE_START_JOINING; |
| 788 | + } |
| 789 | + |
| 790 | + break; |
| 791 | + |
| 792 | + case SESSION_STATE_JOINED: |
| 793 | + if (g_initedPlayer) |
| 794 | + { |
| 795 | + state = SESSION_STATE_5; |
| 796 | + } |
| 797 | + else if (_getCurrentTransitionState() == 0x1D94DE8C || _getCurrentTransitionState() == 0) // SP MODE |
| 798 | + { |
| 799 | + state = SESSION_STATE_START_JOINING; |
| 800 | + } |
| 801 | + |
| 802 | + break; |
| 803 | + |
| 804 | + case SESSION_STATE_5: |
| 805 | + if (cgi->OneSyncEnabled) |
| 806 | + { |
| 807 | + if (sync::IsWaitingForTimeSync()) |
| 808 | + { |
| 809 | + return; |
| 810 | + } |
| 811 | + } |
| 812 | + |
| 813 | + static char sessionIdPtr[48]; |
| 814 | + memset(sessionIdPtr, 0, sizeof(sessionIdPtr)); |
| 815 | + joinOrHost(1, nullptr, sessionIdPtr); |
| 816 | + |
| 817 | + state = SESSION_STATE_6; |
| 818 | + |
| 819 | + break; |
| 820 | + |
| 821 | + case SESSION_STATE_6: |
| 822 | + struct |
| 823 | + { |
| 824 | + char* sessionMultiplayer; |
| 825 | + char pad[16]; |
| 826 | + uint8_t networkInited; |
| 827 | + }* networkMgr; |
| 828 | + |
| 829 | + networkMgr = *(decltype(networkMgr)*)g_networkMgrPtr; |
| 830 | + |
| 831 | + if (networkMgr->networkInited) |
| 832 | + { |
| 833 | + auto networkState = *(BYTE*)(networkMgr->sessionMultiplayer + networkStateOffset); |
| 834 | + |
| 835 | + if (networkState == 4) |
| 836 | + { |
| 837 | + state = SESSION_STATE_7; |
| 838 | + Instance<ICoreGameInit>::Get()->SetVariable("networkInited"); |
| 839 | + } |
| 840 | + } |
| 841 | + break; |
| 842 | + } |
| 843 | + } |
| 844 | +} hostSystem; |
| 845 | + |
702 | 846 | static HookFunction hookFunction([]() |
703 | 847 | { |
704 | 848 | static ConsoleCommand quitCommand("quit", [](const std::string& message) |
@@ -787,139 +931,28 @@ static HookFunction hookFunction([]() |
787 | 931 | // pretend to have CGameScriptHandlerNetComponent always be host |
788 | 932 | hook::jump(hook::get_pattern("33 DB 48 85 C0 74 17 48 8B 48 10 48 85 C9 74 0E", -10), ReturnTrue); |
789 | 933 |
|
790 | | - static LoggedInt tryHostStage = 0; |
791 | | - |
792 | | - static bool gameLoaded; |
793 | | - |
794 | | - Instance<ICoreGameInit>::Get()->OnGameFinalizeLoad.Connect([]() |
795 | | - { |
796 | | - gameLoaded = true; |
797 | | - }); |
798 | | - |
799 | | - static ICoreGameInit* cgi = Instance<ICoreGameInit>::Get(); |
800 | | - |
801 | 934 | OnKillNetwork.Connect([](const char*) |
802 | 935 | { |
803 | | - gameLoaded = false; |
804 | 936 | g_initedPlayer = false; |
805 | 937 | }); |
806 | 938 |
|
807 | 939 | OnMainGameFrame.Connect([]() |
808 | 940 | { |
809 | | - if (!gameLoaded) |
| 941 | + if (Instance<ICoreGameInit>::Get()->GetGameLoaded()) |
810 | 942 | { |
811 | | - return; |
| 943 | + hostSystem.process(); |
812 | 944 | } |
813 | 945 |
|
814 | | - switch (tryHostStage) |
815 | | - { |
816 | | - case 0: |
817 | | - { |
818 | | - // update presence |
819 | | - _rlPresence_GamerPresence_Clear(rlPresence__m_GamerPresences); |
820 | | - _rlPresence_refreshSigninState(0); |
821 | | - _rlPresence_refreshNetworkStatus(0); |
822 | | - |
823 | | - tryHostStage = 1; |
824 | | - break; |
825 | | - } |
826 | | - case 1: |
827 | | - // wait for transition |
828 | | - if (_getCurrentTransitionState() == 0) |
829 | | - { |
830 | | - tryHostStage = 2; |
831 | | - } |
832 | | - |
833 | | - break; |
834 | | - |
835 | | - case 2: |
836 | | - { |
837 | | - auto lastThread = rage::scrEngine::GetActiveThread(); |
838 | | - rage::scrEngine::SetActiveThread(fakeThread.GetThread()); |
839 | | - |
840 | | - // transition to mp |
841 | | - _transitionToState(0x73040199); |
842 | | - |
843 | | - rage::scrEngine::SetActiveThread(lastThread); |
844 | | - |
845 | | - tryHostStage = 3; |
846 | | - break; |
847 | | - } |
848 | | - case 3: |
849 | | - // wait for transition |
850 | | - if (_getCurrentTransitionState() == 0x73040199) |
851 | | - { |
852 | | - tryHostStage = 4; |
853 | | - } |
854 | | - else if (_getCurrentTransitionState() == 0x1D94DE8C || _getCurrentTransitionState() == 0) |
855 | | - { |
856 | | - tryHostStage = 2; |
857 | | - } |
858 | | - |
859 | | - break; |
860 | | - |
861 | | - case 4: |
862 | | - if (g_initedPlayer) |
863 | | - { |
864 | | - tryHostStage = 5; |
865 | | - } |
866 | | - else if (_getCurrentTransitionState() == 0x1D94DE8C || _getCurrentTransitionState() == 0) |
867 | | - { |
868 | | - tryHostStage = 2; |
869 | | - } |
870 | | - |
871 | | - break; |
872 | | - |
873 | | - case 5: |
874 | | - if (cgi->OneSyncEnabled) |
875 | | - { |
876 | | - if (sync::IsWaitingForTimeSync()) |
877 | | - { |
878 | | - return; |
879 | | - } |
880 | | - } |
881 | | - |
882 | | - static char sessionIdPtr[48]; |
883 | | - memset(sessionIdPtr, 0, sizeof(sessionIdPtr)); |
884 | | - joinOrHost(1, nullptr, sessionIdPtr); |
885 | | - |
886 | | - tryHostStage = 6; |
887 | | - |
888 | | - break; |
889 | | - |
890 | | - case 6: |
891 | | - struct |
892 | | - { |
893 | | - char* sessionMultiplayer; |
894 | | - char pad[16]; |
895 | | - uint8_t networkInited; |
896 | | - }* networkMgr; |
897 | | - |
898 | | - networkMgr = *(decltype(networkMgr)*)g_networkMgrPtr; |
899 | | - |
900 | | - if (networkMgr->networkInited) |
901 | | - { |
902 | | - auto networkState = *(BYTE*)(networkMgr->sessionMultiplayer + networkStateOffset); |
903 | | - |
904 | | - if (networkState == 4) |
905 | | - { |
906 | | - tryHostStage = 7; |
907 | | - Instance<ICoreGameInit>::Get()->SetVariable("networkInited"); |
908 | | - } |
909 | | - } |
910 | | - |
911 | | - break; |
912 | | - } |
913 | 946 | }); |
914 | 947 |
|
915 | 948 | static ConsoleCommand hhh("hhh", []() |
916 | 949 | { |
917 | | - tryHostStage = 0; |
| 950 | + hostSystem.state = SESSION_STATE_NONE; |
918 | 951 | }); |
919 | 952 |
|
920 | 953 | OnKillNetworkDone.Connect([]() |
921 | 954 | { |
922 | | - tryHostStage = 0; |
| 955 | + hostSystem.state = SESSION_STATE_NONE; |
923 | 956 | }); |
924 | 957 |
|
925 | 958 | // rlSession::InformPeersOfJoiner bugfix: reintroduce loop (as in, remove break; statement) |
|
0 commit comments