-
-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added session for map portals (#459)
- Loading branch information
1 parent
d980e3b
commit 6390871
Showing
3 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
using HarmonyLib; | ||
using RimWorld; | ||
using UnityEngine; | ||
using Verse; | ||
|
||
namespace Multiplayer.Client.Persistent; | ||
|
||
[HarmonyPatch(typeof(Widgets), nameof(Widgets.ButtonTextWorker))] | ||
static class MakeMapPortalCancelButtonRed | ||
{ | ||
static void Prefix(string label, ref bool __state) | ||
{ | ||
if (MapPortalProxy.drawing == null) return; | ||
if (label != "CancelButton".Translate()) return; | ||
|
||
GUI.color = new Color(1f, 0.3f, 0.35f); | ||
__state = true; | ||
} | ||
|
||
static void Postfix(bool __state, ref Widgets.DraggableResult __result) | ||
{ | ||
if (!__state) return; | ||
|
||
GUI.color = Color.white; | ||
if (__result.AnyPressed()) | ||
{ | ||
MapPortalProxy.drawing.Session?.Remove(); | ||
__result = Widgets.DraggableResult.Idle; | ||
} | ||
} | ||
} | ||
|
||
[HarmonyPatch(typeof(Widgets), nameof(Widgets.ButtonTextWorker))] | ||
static class MapPortalHandleReset | ||
{ | ||
static void Prefix(string label, ref bool __state) | ||
{ | ||
if (MapPortalProxy.drawing == null) return; | ||
if (label != "ResetButton".Translate()) return; | ||
|
||
__state = true; | ||
} | ||
|
||
static void Postfix(bool __state, ref Widgets.DraggableResult __result) | ||
{ | ||
if (!__state) return; | ||
|
||
if (__result.AnyPressed()) | ||
{ | ||
MapPortalProxy.drawing.Session?.Reset(); | ||
__result = Widgets.DraggableResult.Idle; | ||
} | ||
} | ||
} | ||
|
||
[HarmonyPatch(typeof(Dialog_EnterPortal), nameof(Dialog_EnterPortal.TryAccept))] | ||
static class TryAcceptMapPortal | ||
{ | ||
static bool Prefix(Dialog_EnterPortal __instance) | ||
{ | ||
if (Multiplayer.InInterface && __instance is MapPortalProxy mapPortal) | ||
{ | ||
mapPortal.Session?.TryAccept(); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
|
||
[HarmonyPatch(typeof(Dialog_EnterPortal), nameof(Dialog_EnterPortal.AddToTransferables))] | ||
static class CancelMapPortalAddItems | ||
{ | ||
static bool Prefix(Dialog_EnterPortal __instance) | ||
{ | ||
if (__instance is MapPortalProxy { itemsReady: true } mp) | ||
{ | ||
// Sets the transferables list back to the session list | ||
// as it gets reset in CalculateAndRecacheTransferables | ||
mp.transferables = mp.Session.transferables; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
|
||
static class OpenMapPortalSessionDialog | ||
{ | ||
[MpPrefix(typeof(MapPortal), nameof(MapPortal.GetGizmos), 0)] | ||
static bool Prefix(MapPortal __instance) | ||
{ | ||
if (Multiplayer.Client == null) | ||
return true; | ||
|
||
MapPortalSession.OpenOrCreateSession(__instance); | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using RimWorld; | ||
using UnityEngine; | ||
|
||
namespace Multiplayer.Client.Persistent; | ||
|
||
public class MapPortalProxy(MapPortal portal) : Dialog_EnterPortal(portal), ISwitchToMap | ||
{ | ||
public static MapPortalProxy drawing; | ||
public bool itemsReady = false; | ||
|
||
public MapPortalSession Session => portal.Map.MpComp().sessionManager.GetFirstOfType<MapPortalSession>(); | ||
|
||
public override void DoWindowContents(Rect inRect) | ||
{ | ||
drawing = this; | ||
var session = Session; | ||
SyncSessionWithTransferablesMarker.DrawnSessionWithTransferables = session; | ||
|
||
try | ||
{ | ||
if (session == null) | ||
Close(); | ||
|
||
base.DoWindowContents(inRect); | ||
} | ||
finally | ||
{ | ||
drawing = null; | ||
SyncSessionWithTransferablesMarker.DrawnSessionWithTransferables = null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Multiplayer.API; | ||
using RimWorld; | ||
using Verse; | ||
|
||
namespace Multiplayer.Client.Persistent; | ||
|
||
public class MapPortalSession : ExposableSession, ISessionWithTransferables, ISessionWithCreationRestrictions | ||
{ | ||
public MapPortal portal; | ||
public List<TransferableOneWay> transferables; | ||
|
||
public override Map Map => portal.Map; | ||
|
||
public MapPortalSession(Map _) : base(null) | ||
{ | ||
// Mandatory constructor | ||
} | ||
|
||
public MapPortalSession(MapPortal portal) : base(null) | ||
{ | ||
this.portal = portal; | ||
|
||
AddItems(); | ||
} | ||
|
||
private void AddItems() | ||
{ | ||
var dialog = new MapPortalProxy(portal); | ||
|
||
// Init code taken from Dialog_EnterPortal.PostOpen | ||
dialog.CalculateAndRecacheTransferables(); | ||
|
||
transferables = dialog.transferables; | ||
} | ||
|
||
public override bool IsCurrentlyPausing(Map map) => Map == map; | ||
|
||
public override FloatMenuOption GetBlockingWindowOptions(ColonistBar.Entry entry) | ||
{ | ||
if (entry.map != Map) | ||
return null; | ||
|
||
return new FloatMenuOption("MpMapPortalSession".Translate(portal?.Label), () => | ||
{ | ||
SwitchToMapOrWorld(Map); | ||
OpenWindow(); | ||
}); | ||
} | ||
|
||
public static void OpenOrCreateSession(MapPortal portal) | ||
{ | ||
var session = portal.Map.MpComp().sessionManager.AllSessions | ||
.OfType<MapPortalSession>() | ||
.FirstOrDefault(s => s.portal == portal); | ||
if (session == null) | ||
CreateSession(portal); | ||
else | ||
session.OpenWindow(); | ||
} | ||
|
||
[SyncMethod] | ||
private static void CreateSession(MapPortal portal) | ||
{ | ||
var map = portal.Map; | ||
var manager = map.MpComp().sessionManager; | ||
var session = manager.GetOrAddSession(new MapPortalSession(portal)); | ||
|
||
// Shouldn't happen and is here for safety. | ||
if (session == null) | ||
Log.Error($"Failed creating session of type {nameof(MapPortalSession)}."); | ||
else if (MP.IsExecutingSyncCommandIssuedBySelf) | ||
session.OpenWindow(); | ||
} | ||
|
||
[SyncMethod] | ||
public void TryAccept() | ||
{ | ||
// There's not a single situation where TryAccept would return false. | ||
// However, it will likely be used by prefixes added by mods. | ||
if (PrepareDummyDialog().TryAccept()) | ||
Remove(); | ||
} | ||
|
||
[SyncMethod] | ||
public void Reset() => transferables.ForEach(t => t.CountToTransfer = 0); | ||
|
||
[SyncMethod] | ||
public void Remove() => Map.MpComp().sessionManager.RemoveSession(this); | ||
|
||
public void OpenWindow(bool sound = true) | ||
{ | ||
var dialog = PrepareDummyDialog(); | ||
if (!sound) | ||
dialog.soundAppear = null; | ||
|
||
Find.WindowStack.Add(dialog); | ||
} | ||
|
||
private MapPortalProxy PrepareDummyDialog() | ||
{ | ||
return new MapPortalProxy(portal) | ||
{ | ||
itemsReady = true, | ||
transferables = transferables, | ||
}; | ||
} | ||
|
||
public override void ExposeData() | ||
{ | ||
base.ExposeData(); | ||
|
||
Scribe_Collections.Look(ref transferables, "transferables", LookMode.Deep); | ||
Scribe_References.Look(ref portal, "portal"); | ||
} | ||
|
||
public Transferable GetTransferableByThingId(int thingId) | ||
=> transferables.Find(tr => tr.things.Any(t => t.thingIDNumber == thingId)); | ||
|
||
public void Notify_CountChanged(Transferable tr) | ||
{ | ||
// There should not really be a need to clear caches, as this dialog does not really have any. | ||
} | ||
|
||
public bool CanExistWith(Session other) => other is not MapPortalSession portalSession || portalSession.portal != portal; | ||
} |