Skip to content

Commit

Permalink
Merge pull request #438 from starfi5h/pr-pause
Browse files Browse the repository at this point in the history
add CanPause check, enable pausing when no connections
  • Loading branch information
PhantomGamers authored Sep 12, 2021
2 parents 264a5a0 + 4aed6d5 commit b636bdf
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 32 deletions.
81 changes: 49 additions & 32 deletions NebulaPatcher/Patches/Transpilers/GameMain_Transpiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,65 @@
namespace NebulaPatcher.Patches.Transpiler
{
[HarmonyPatch(typeof(GameMain))]
class GameMain_Transpiler
internal class GameMain_Transpiler
{
//Ignore Pausing in the multiplayer:
//Enable Pausing only when there is no session or Multiplayer.Session.CanPause is true:
//Change: if (!this._paused)
//To: if (!this._paused || Multiplayer.IsActive)
//To: if (!(this._paused && (Multiplayer.Session == null || Multiplayer.Session.CanPause)))
//Change: if (this._fullscreenPaused && !this._fullscreenPausedUnlockOneFrame)
//To: if (this._fullscreenPaused && (Multiplayer.Session == null || Multiplayer.Session.CanPause) && !this._fullscreenPausedUnlockOneFrame)

[HarmonyTranspiler]
[HarmonyPatch(nameof(GameMain.FixedUpdate))]
static IEnumerable<CodeInstruction> PickupBeltItems_Transpiler(ILGenerator gen, IEnumerable<CodeInstruction> instructions)
private static IEnumerable<CodeInstruction> FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator iL)
{
var found = false;
var codes = new List<CodeInstruction>(instructions);
for (int i = 6; i < codes.Count; i++)
{
if (codes[i].opcode == OpCodes.Callvirt &&
codes[i - 1].opcode == OpCodes.Ldc_I4_1 &&
codes[i - 2].opcode == OpCodes.Br &&
codes[i - 3].opcode == OpCodes.Ldc_I4_0 &&
codes[i - 4].opcode == OpCodes.Br &&
codes[i - 5].opcode == OpCodes.Ceq)
{
found = true;
//Define new jump for firct condition
Label targetLabel = gen.DefineLabel();
codes[i + 4].labels.Add(targetLabel);

//Add my condition
codes.InsertRange(i + 4, new CodeInstruction[] {
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Multiplayer), "get_" + nameof(Multiplayer.IsActive))),
new CodeInstruction(OpCodes.Brfalse_S, codes[i+3].operand)
});
CodeMatcher codeMatcher = new CodeMatcher(instructions, iL)
.MatchForward(true,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), "ApplyGamePauseState")),
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_paused")),
new CodeMatch(OpCodes.Brtrue)
);

//Change jump of first condition
codes[i + 3] = new CodeInstruction(OpCodes.Brfalse_S, targetLabel);
if (codeMatcher.IsInvalid)
{
NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler failed. Mod version not compatible with game version.");
return instructions;
}
object skipLabel1 = codeMatcher.Instruction.operand;
codeMatcher
.CreateLabelAt(codeMatcher.Pos + 1, out Label nextLabel1)
.InsertAndAdvance(
new CodeInstruction(OpCodes.Brfalse_S, nextLabel1), //_paused== false => enter loop
new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
new CodeInstruction(OpCodes.Brfalse_S, skipLabel1), //_paused== true && Multiplayer.Session == null => can pause, skip loop
new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause)))
)
.MatchForward(true,
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_fullscreenPaused")),
new CodeMatch(OpCodes.Brfalse)
);

break;
}
if (codeMatcher.IsInvalid)
{
NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler 2 failed. Mod version not compatible with game version.");
return instructions;
}

if (!found)
NebulaModel.Logger.Log.Error("GameMain FixedUpdate transpiler failed. Mod version not compatible with game version.");
return codes;
object skipLabel2 = codeMatcher.Instruction.operand;
return codeMatcher
.Advance(1)
.CreateLabel(out Label nextLabel2) //position of checking _fullscreenPausedUnlockOneFrame
.InsertAndAdvance(
new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
new CodeInstruction(OpCodes.Brfalse_S, nextLabel2), //_fullscreenPaused && Multiplayer.Session == null => can pause, jump to next check
new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause))),
new CodeInstruction(OpCodes.Brfalse_S, skipLabel2) //_fullscreenPaused && Multiplayer.Session.CanPause == fasle => can't pause, skip
)
.InstructionEnumeration();
}
}
}
10 changes: 10 additions & 0 deletions NebulaWorld/MultiplayerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ public class MultiplayerSession : IDisposable, IMultiplayerSession


public bool IsGameLoaded { get; set; }
public bool CanPause
{
get => canPause;
set
{
canPause = value;
World?.SetPauseIndicator(value);
}
}
private bool canPause = true;

public MultiplayerSession(NetworkProvider networkProvider)
{
Expand Down
28 changes: 28 additions & 0 deletions NebulaWorld/SimulatedWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ public void OnPlayerJoining()
if (!IsPlayerJoining)
{
IsPlayerJoining = true;
Multiplayer.Session.CanPause = true;
GameMain.isFullscreenPaused = true;
InGamePopup.ShowInfo("Loading", "Player joining the game, please wait", null);
}
Expand All @@ -148,6 +149,7 @@ public void OnAllPlayersSyncCompleted()
IsPlayerJoining = false;
InGamePopup.FadeOut();
GameMain.isFullscreenPaused = false;
Multiplayer.Session.CanPause = false;
}

public void SpawnRemotePlayerModel(IPlayerData playerData)
Expand All @@ -172,6 +174,10 @@ public void DestroyRemotePlayerModel(ushort playerId)
{
player.Destroy();
remotePlayersModels.Remove(playerId);
if (remotePlayersModels.Count == 0)
{
Multiplayer.Session.CanPause = true;
}
}
}
}
Expand Down Expand Up @@ -598,5 +604,27 @@ public void UpdatePingIndicator(string text)
pingIndicator.text = text;
}
}

public void SetPauseIndicator(bool canPause)
{
//Tell the user if the game is paused or not
var targetObject = GameObject.Find("UI Root/Overlay Canvas/In Game/Esc Menu/pause-text");
var pauseText = targetObject?.GetComponent<Text>();
var pauseLocalizer = targetObject?.GetComponent<Localizer>();
if (pauseText && pauseLocalizer)
{
if (!canPause)
{
pauseText.text = "-- Nebula Multiplayer --".Translate();
pauseLocalizer.stringKey = "-- Nebula Multiplayer --".Translate();
}
else
{
pauseText.text = "游戏已暂停".Translate();
pauseLocalizer.stringKey = "游戏已暂停".Translate();
}
}

}
}
}

0 comments on commit b636bdf

Please sign in to comment.