Skip to content

Commit

Permalink
Merge branch 'master' of github.com:SokyranTheDragon/Multiplayer into…
Browse files Browse the repository at this point in the history
… replace-dyn-delegate

# Conflicts:
#	Source/Client/Syncing/Worker/SyncWorkers.cs
  • Loading branch information
SokyranTheDragon committed Apr 6, 2024
2 parents 9892e8b + 5b7a8ea commit 63b50f1
Show file tree
Hide file tree
Showing 79 changed files with 1,513 additions and 1,429 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-workshop.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Build workshop

on:
workflow_dispatch:
push:
tags:
- 'v*'
Expand Down
4 changes: 2 additions & 2 deletions About/About.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<packageId>rwmt.Multiplayer</packageId>
<name>Multiplayer</name>
<supportedVersions>
<li>1.4</li>
<li>1.5</li>
</supportedVersions>
<author>RimWorld Multiplayer Team</author>
<url>https://github.com/rwmt/Multiplayer</url>
<description>&lt;color=red&gt;&lt;b&gt;Important: &lt;/b&gt; This mod should be placed right below Core and expansions in the mod list to work properly!
Requires Rimworld >= v1.4.3901&lt;/color&gt;\n
Requires Rimworld >= v1.5.4034&lt;/color&gt;\n
Multiplayer mod for RimWorld.

FAQ - https://hackmd.io/@rimworldmultiplayer/docs/
Expand Down
2 changes: 1 addition & 1 deletion Source/Client/AsyncTime/AsyncTimePatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static void Postfix()
}
}

[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string))]
[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string), typeof(int), typeof(bool))]
static class ReceiveLetterPause
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> insts)
Expand Down
37 changes: 36 additions & 1 deletion Source/Client/AsyncTime/TimeControlUI.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using HarmonyLib;
Expand Down Expand Up @@ -283,6 +283,10 @@ public static class ColonistBarTimeControl
public static float btnWidth = TimeControls.TimeButSize.x;
public static float btnHeight = TimeControls.TimeButSize.y;

private static Dictionary<Vector2, float> flashDict = new Dictionary<Vector2, float>();
private static float flashInterval = 6f;
private static Color flashColor = Color.red;

static void Prefix(ref bool __state)
{
if (Event.current.type is EventType.MouseDown or EventType.MouseUp)
Expand Down Expand Up @@ -316,6 +320,7 @@ static void DrawButtons()
Rect groupBar = bar.drawer.GroupFrameRect(entry.group);
float drawXPos = groupBar.x;
Color bgColor = (entryTickable.ActualRateMultiplier(TimeSpeed.Normal) == 0f) ? pauseBgColor : normalBgColor;
Vector2 flashPos = new Vector2(drawXPos + btnWidth / 2, groupBar.yMax + btnHeight / 2);

if (Multiplayer.GameComp.asyncTime)
{
Expand All @@ -337,6 +342,24 @@ static void DrawButtons()
Rect button = new Rect(drawXPos, groupBar.yMax, btnWidth, btnHeight);
MpTimeControls.TimeIndicateBlockingPause(button, bgColor);
drawXPos += TimeControls.TimeButSize.x;

float pauseTime = flashDict.GetValueOrDefault(flashPos);
if (flashDict.ContainsKey(flashPos))
{
// Draw flash for ongoing blocking pause
DrawPauseFlash(flashPos);
}
else
{
// There is a new blocking pause
flashDict.Add(flashPos, Time.time);
}
}

if (entryTickable.ActualRateMultiplier(TimeSpeed.Normal) != 0f && flashDict.ContainsKey(flashPos))
{
// No longer any blocking pauses, stop flashing here
flashDict.Remove(flashPos);
}

List<FloatMenuOption> options = GetBlockingWindowOptions(entry, entryTickable);
Expand Down Expand Up @@ -375,6 +398,18 @@ static void SwitchToMapOrWorld(Map map)
Current.Game.CurrentMap = map;
}
}

static void DrawPauseFlash(Vector2 pos)
{
float pauseTime = flashDict.GetValueOrDefault(pos);
float pauseDuration = Time.time - pauseTime;

// Only flash at flashInterval from the time the blocking pause began
if (pauseDuration > 0f && pauseDuration % flashInterval < 1f)
{
GenUI.DrawFlash(pos.x, pos.y, UI.screenWidth * 0.6f, Pulser.PulseBrightness(1f, 1f, pauseDuration) * 0.4f, flashColor);
}
}
}

[HarmonyPatch(typeof(MainButtonWorker), nameof(MainButtonWorker.DoButton))]
Expand Down
8 changes: 4 additions & 4 deletions Source/Client/Comp/World/FactionWorldData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ public void ExposeData()
public void ReassignIds()
{
foreach (DrugPolicy p in drugPolicyDatabase.policies)
p.uniqueId = Find.UniqueIDsManager.GetNextThingID();
p.id = Find.UniqueIDsManager.GetNextThingID();

foreach (Outfit o in outfitDatabase.outfits)
o.uniqueId = Find.UniqueIDsManager.GetNextThingID();
foreach (ApparelPolicy o in outfitDatabase.outfits)
o.id = Find.UniqueIDsManager.GetNextThingID();

foreach (FoodRestriction o in foodRestrictionDatabase.foodRestrictions)
foreach (FoodPolicy o in foodRestrictionDatabase.foodRestrictions)
o.id = Find.UniqueIDsManager.GetNextThingID();
}

Expand Down
20 changes: 12 additions & 8 deletions Source/Client/Debug/DebugActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;

using HarmonyLib;
using LudeonTK;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
Expand Down Expand Up @@ -134,17 +135,20 @@ public static void SaveGame()
public static void DumpSyncTypes()
{
var dict = new Dictionary<string, Type[]>() {
{"ThingComp", RwImplSerialization.thingCompTypes},
{"AbilityComp", RwImplSerialization.abilityCompTypes},
{"Designator", RwImplSerialization.designatorTypes},
{"WorldObjectComp", RwImplSerialization.worldObjectCompTypes},
{"HediffComp", RwImplSerialization.hediffCompTypes},
{"IStoreSettingsParent", RwImplSerialization.storageParents},
{"IStoreSettingsParent", RwImplSerialization.storageSettingsParent},
{"IPlantToGrowSettable", RwImplSerialization.plantToGrowSettables},
{"ISlotGroup", RwImplSerialization.slotGroupTypes},
{"ISlotGroupParent", RwImplSerialization.slotGroupParents},

{"GameComponent", RwImplSerialization.gameCompTypes},
{"WorldComponent", RwImplSerialization.worldCompTypes},
{"MapComponent", RwImplSerialization.mapCompTypes},
{"ThingComp", CompSerialization.thingCompTypes},
{"AbilityComp", CompSerialization.abilityCompTypes},
{"WorldObjectComp", CompSerialization.worldObjectCompTypes},
{"HediffComp", CompSerialization.hediffCompTypes},

{"GameComponent", CompSerialization.gameCompTypes},
{"WorldComponent", CompSerialization.worldCompTypes},
{"MapComponent", CompSerialization.mapCompTypes},
};

foreach(var kv in dict) {
Expand Down
2 changes: 1 addition & 1 deletion Source/Client/Debug/DebugPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static void Prefixfactionman()
!trace.Contains("Client.FactionContext") &&
!trace.Contains("Thing.ExposeData")
)
Log.Message($"factionman call {trace}", true);
Log.Message($"factionman call {trace}");
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Source/Client/Debug/DebugSync.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using HarmonyLib;
using LudeonTK;
using Multiplayer.Common;

using RimWorld;
Expand Down
21 changes: 18 additions & 3 deletions Source/Client/EarlyInit.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using Multiplayer.Client.Patches;
Expand Down Expand Up @@ -55,10 +56,12 @@ internal static void EarlyPatches(Harmony harmony)

internal static void InitSync()
{
using (DeepProfilerWrapper.Section("Multiplayer SyncSerialization.Init"))
SyncSerialization.Init();
MpReflection.allAssembliesHook = RwAllAssemblies;

using (DeepProfilerWrapper.Section("Multiplayer SyncGame"))
using (DeepProfilerWrapper.Section("Multiplayer RwSerialization.Init"))
RwSerialization.Init();

using (DeepProfilerWrapper.Section("Multiplayer SyncGame.Init"))
SyncGame.Init();

using (DeepProfilerWrapper.Section("Multiplayer Sync register attributes"))
Expand All @@ -68,6 +71,18 @@ internal static void InitSync()
Sync.ValidateAll();
}

private static IEnumerable<Assembly> RwAllAssemblies()
{
yield return Assembly.GetAssembly(typeof(Game));

foreach (ModContentPack mod in LoadedModManager.RunningMods)
foreach (Assembly assembly in mod.assemblies.loadedAssemblies)
yield return assembly;

if (Assembly.GetEntryAssembly() != null)
yield return Assembly.GetEntryAssembly();
}

internal static void LatePatches()
{
if (MpVersion.IsDebug)
Expand Down
2 changes: 0 additions & 2 deletions Source/Client/EarlyPatches/SettingsPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ static class PrefGettersInMultiplayer
{
static IEnumerable<MethodBase> TargetMethods()
{
yield return AccessTools.PropertyGetter(typeof(Prefs), nameof(Prefs.PauseOnError));
yield return AccessTools.PropertyGetter(typeof(Prefs), nameof(Prefs.AutomaticPauseMode));
yield return AccessTools.PropertyGetter(typeof(Prefs), nameof(Prefs.PauseOnLoad));
yield return AccessTools.PropertyGetter(typeof(Prefs), nameof(Prefs.AdaptiveTrainingEnabled));
Expand All @@ -29,7 +28,6 @@ static class PrefSettersInMultiplayer
{
static IEnumerable<MethodBase> TargetMethods()
{
yield return AccessTools.PropertySetter(typeof(Prefs), nameof(Prefs.PauseOnError));
yield return AccessTools.PropertySetter(typeof(Prefs), nameof(Prefs.AutomaticPauseMode));
yield return AccessTools.PropertySetter(typeof(Prefs), nameof(Prefs.PauseOnLoad));
yield return AccessTools.PropertySetter(typeof(Prefs), nameof(Prefs.AdaptiveTrainingEnabled));
Expand Down
4 changes: 2 additions & 2 deletions Source/Client/Factions/Blueprints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Multiplayer.Client
// Don't draw other factions' blueprints
// Don't link graphics of different factions' blueprints

[HarmonyPatch(typeof(GenConstruct), nameof(GenConstruct.CanPlaceBlueprintAt))]
[HarmonyPatch(typeof(GenConstruct), nameof(GenConstruct.CanPlaceBlueprintAt_NewTemp))]
static class CanPlaceBlueprintAtPatch
{
static MethodInfo CanPlaceBlueprintOver = AccessTools.Method(typeof(GenConstruct), nameof(GenConstruct.CanPlaceBlueprintOver));
Expand Down Expand Up @@ -49,7 +49,7 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> e, M
}


[HarmonyPatch(typeof(GenConstruct), nameof(GenConstruct.CanPlaceBlueprintAt))]
[HarmonyPatch(typeof(GenConstruct), nameof(GenConstruct.CanPlaceBlueprintAt_NewTemp))]
static class CanPlaceBlueprintAtPatch2
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> e, MethodBase original)
Expand Down
5 changes: 2 additions & 3 deletions Source/Client/Factions/FactionContextSetters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,9 @@ static void Prefix(Bill_Production __instance, ref Map __state)
{
if (Multiplayer.Client == null) return;

var zoneManager = __instance.storeZone?.zoneManager ?? __instance.includeFromZone?.zoneManager;
if (__instance.Map != null && zoneManager != null)
if (__instance.Map != null && __instance.billStack?.billGiver is Thing { Faction: { } faction })
{
__instance.Map.PushFaction(zoneManager.map.MpComp().GetFactionId(zoneManager));
__instance.Map.PushFaction(faction);
__state = __instance.Map;
}
}
Expand Down
5 changes: 3 additions & 2 deletions Source/Client/Factions/FactionCreationPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ static void Finalizer(ProgramState __state)
}
}

[HarmonyPatch(typeof(Page_ConfigureStartingPawns), nameof(Page_ConfigureStartingPawns.RandomizeCurPawn))]
static class ConfigureStartingPawns_RandomizeCurPawn_Patch
[HarmonyPatch(typeof(StartingPawnUtility), nameof(StartingPawnUtility.RandomizePawn))]
static class StartingPawnUtility_RandomizePawn_Patch
{
static void Prefix(ref ProgramState __state)
{
// todo is this compatible with 1.5's "Create new wanderers?"
__state = Current.ProgramState;
Current.programStateInt = ProgramState.Entry;
}
Expand Down
4 changes: 2 additions & 2 deletions Source/Client/Factions/MultifactionPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ static void Postfix(IAttackTarget target, ref bool __result)
}
}

[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string))]
[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string), typeof(int), typeof(bool))]
static class LetterStackReceiveOnlyMyFaction
{
// todo the letter might get culled from the archive if it isn't in the stack and Sync depends on the archive
Expand All @@ -333,7 +333,7 @@ static void Postfix(LetterStack __instance, Letter let)
}
}

[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string))]
[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter), typeof(Letter), typeof(string), typeof(int), typeof(bool))]
static class LetterStackReceiveSoundOnlyMyFaction
{
private static MethodInfo PlayOneShotOnCamera =
Expand Down
4 changes: 2 additions & 2 deletions Source/Client/Multiplayer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>11</LangVersion>
<LangVersion>12</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputPath>bin</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
Expand All @@ -29,7 +29,7 @@
<ItemGroup>
<PackageReference Include="Krafs.Publicizer" Version="2.0.1" />
<PackageReference Include="Lib.Harmony" Version="2.2.2" ExcludeAssets="runtime" />
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.4.3901" />
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.5.4055-beta" />
<PackageReference Include="RestSharp" Version="106.12.0" />
<PackageReference Include="RimWorld.MultiplayerAPI" Version="0.5.0" />
</ItemGroup>
Expand Down
24 changes: 13 additions & 11 deletions Source/Client/MultiplayerData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,22 @@ internal static void CollectDefInfos()

int TypeHash(Type type) => GenText.StableStringHash(type.FullName);

dict["ThingComp"] = GetDefInfo(RwImplSerialization.thingCompTypes, TypeHash);
dict["AbilityComp"] = GetDefInfo(RwImplSerialization.abilityCompTypes, TypeHash);
dict["Designator"] = GetDefInfo(RwImplSerialization.designatorTypes, TypeHash);
dict["WorldObjectComp"] = GetDefInfo(RwImplSerialization.worldObjectCompTypes, TypeHash);
dict["HediffComp"] = GetDefInfo(RwImplSerialization.hediffCompTypes, TypeHash);
dict["IStoreSettingsParent"] = GetDefInfo(RwImplSerialization.storageParents, TypeHash);
dict["ThingComp"] = GetDefInfo(CompSerialization.thingCompTypes, TypeHash);
dict["AbilityComp"] = GetDefInfo(CompSerialization.abilityCompTypes, TypeHash);
dict["WorldObjectComp"] = GetDefInfo(CompSerialization.worldObjectCompTypes, TypeHash);
dict["HediffComp"] = GetDefInfo(CompSerialization.hediffCompTypes, TypeHash);
dict["IStoreSettingsParent"] = GetDefInfo(RwImplSerialization.storageSettingsParent, TypeHash);
dict["IPlantToGrowSettable"] = GetDefInfo(RwImplSerialization.plantToGrowSettables, TypeHash);
dict["ISlotGroup"] = GetDefInfo(RwImplSerialization.slotGroupTypes, TypeHash);
dict["ISlotGroupParent"] = GetDefInfo(RwImplSerialization.slotGroupParents, TypeHash);
dict["Designator"] = GetDefInfo(RwImplSerialization.designatorTypes, TypeHash);
dict["DefTypes"] = GetDefInfo(DefSerialization.DefTypes, TypeHash);

dict["GameComponent"] = GetDefInfo(RwImplSerialization.gameCompTypes, TypeHash);
dict["WorldComponent"] = GetDefInfo(RwImplSerialization.worldCompTypes, TypeHash);
dict["MapComponent"] = GetDefInfo(RwImplSerialization.mapCompTypes, TypeHash);
dict["ISyncSimple"] = GetDefInfo(ImplSerialization.syncSimples, TypeHash);
dict["ISession"] = GetDefInfo(ImplSerialization.sessions, TypeHash);
dict["GameComponent"] = GetDefInfo(CompSerialization.gameCompTypes, TypeHash);
dict["WorldComponent"] = GetDefInfo(CompSerialization.worldCompTypes, TypeHash);
dict["MapComponent"] = GetDefInfo(CompSerialization.mapCompTypes, TypeHash);
dict["ISyncSimple"] = GetDefInfo(ApiSerialization.syncSimples, TypeHash);
dict["ISession"] = GetDefInfo(ApiSerialization.sessions, TypeHash);

dict["PawnBio"] = GetDefInfo(SolidBioDatabase.allBios, b => b.name.GetHashCode());

Expand Down
1 change: 1 addition & 0 deletions Source/Client/MultiplayerGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using LudeonTK;
using Multiplayer.API;
using Multiplayer.Client.AsyncTime;
using Multiplayer.Client.Comp;
Expand Down
7 changes: 4 additions & 3 deletions Source/Client/MultiplayerStatic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,17 +348,18 @@ void TryPatch(MethodBase original, HarmonyMethod prefix = null, HarmonyMethod po
var randomBoltMesh = typeof(LightningBoltMeshPool).GetProperty(nameof(LightningBoltMeshPool.RandomBoltMesh))!.GetGetMethod();
var drawTrackerCtor = typeof(Pawn_DrawTracker).GetConstructor(new[] { typeof(Pawn) });
var randomHair = typeof(PawnStyleItemChooser).GetMethod(nameof(PawnStyleItemChooser.RandomHairFor));
var cannotAssignReason = typeof(Dialog_BeginRitual).GetMethod(nameof(Dialog_BeginRitual.CannotAssignReason), BindingFlags.NonPublic | BindingFlags.Instance);
// todo for 1.5
// var cannotAssignReason = typeof(Dialog_BeginRitual).GetMethod(nameof(Dialog_BeginRitual.CannotAssignReason), BindingFlags.NonPublic | BindingFlags.Instance);
var canEverSpectate = typeof(RitualRoleAssignments).GetMethod(nameof(RitualRoleAssignments.CanEverSpectate));

var effectMethods = new MethodBase[] { subSustainerStart, sampleCtor, subSoundPlay, effecterTick, effecterTrigger, effecterCleanup, randomBoltMesh, drawTrackerCtor, randomHair };
var moteMethods = typeof(MoteMaker).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.Name != "MakeBombardmentMote"); // Special case, just calls MakeBombardmentMote_NewTmp, prevents Hugslib complains
.Where(m => m.Name != "MakeBombardmentMote"); // Special case, just calls MakeBombardmentMote_NewTmp, prevents Hugslib complaints
var fleckMethods = typeof(FleckMaker).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.ReturnType == typeof(void))
.Concat(typeof(FleckManager).GetMethods() // FleckStatic uses Rand in Setup method, FleckThrown uses RandomInRange in TimeInterval. May as well catch all in case mods do the same.
.Where(m => m.ReturnType == typeof(void)));
var ritualMethods = new[] { cannotAssignReason, canEverSpectate };
var ritualMethods = new[] { canEverSpectate };

foreach (MethodBase m in effectMethods.Concat(moteMethods).Concat(fleckMethods).Concat(ritualMethods))
TryPatch(m, randPatchPrefix, randPatchPostfix);
Expand Down
2 changes: 1 addition & 1 deletion Source/Client/Patches/ArbiterPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static IEnumerable<MethodBase> TargetMethods()
yield return AccessTools.Method(typeof(Prefs), nameof(Prefs.Save));
yield return AccessTools.Method(typeof(FloatMenuOption), nameof(FloatMenuOption.SetSizeMode));
yield return AccessTools.Method(typeof(Section), nameof(Section.RegenerateAllLayers));
yield return AccessTools.Method(typeof(Section), nameof(Section.RegenerateLayers));
yield return AccessTools.Method(typeof(Section), nameof(Section.RegenerateDirtyLayers));
yield return AccessTools.Method(typeof(SectionLayer), nameof(SectionLayer.DrawLayer));
yield return AccessTools.Method(typeof(Map), nameof(Map.MapUpdate));
yield return AccessTools.Method(typeof(GUIStyle), nameof(GUIStyle.CalcSize));
Expand Down
Loading

0 comments on commit 63b50f1

Please sign in to comment.