// All the following is for the tiny lock of doom static void SyncWorkerForSwapControlsHandler(SyncWorker sync, ref object obj) { Pawn pawn = null; if (sync.isWriting) { pawn = (Pawn)SwapControlsHandler_PawnProperty.GetValue(obj, new object[] { }); // If Pawn is null, it was saved and got deleted. if (pawn == null) { sync.Write(false); // Must use more reflection to traverse SimpleSidearms.saveData.handlers // This will desync if unhandled :( throw new ArgumentException("About to desync, tiny lock of doom triggered. Refusing to comply"); } else { sync.Write(true); sync.Write(pawn); } } else { bool exists = sync.Read <bool>(); if (exists) { pawn = sync.Read <Pawn>(); obj = SwapControlsHandler_GetHandlerForPawnMethod.Invoke(null, new object[] { pawn }); } } }
private static void SyncFormTrackerInnerClass(SyncWorker sync, ref object inner) { if (sync.isWriting) { var tracker = innerClassParentField(inner); var comp = formTrackerCompField(tracker); sync.Write(comp); var formList = propsFormsListField(comp.props); var index = formList.IndexOf(innerClassFormField(inner)); sync.Write(index); } else { var comp = sync.Read <ThingComp>(); var tracker = pokemonFormTrackerField(comp); innerClassParentField(inner) = tracker; var index = sync.Read <int>(); if (index >= 0) { var formList = propsFormsListField(comp.props); innerClassFormField(inner) = formList[index]; } } }
private static void SyncZoneData(SyncWorker sync, ref object zoneData) { if (sync.isWriting) { int?id = null; var comp = compCache[Find.CurrentMap]; var zoneRegistry = growZoneRegistryField(comp); foreach (DictionaryEntry entry in zoneRegistry) { if (entry.Value == zoneData) { id = (int)entry.Key; break; } } sync.Write(id); if (id != null) { sync.Write(Find.CurrentMap); } } else { var id = sync.Read <int?>(); if (id != null) { var comp = compCache[sync.Read <Map>()]; var zoneRegistry = growZoneRegistryField(comp); zoneData = zoneRegistry[id.Value]; } } }
private static void SyncFacepaintCombination(SyncWorker sync, ref object obj) { var defs = (IList)orderedFacepaintDefsField.GetValue(null); if (sync.isWriting) { sync.Write((Color)facepaintColourOneField.GetValue(obj)); sync.Write((Color)facepaintColourTwoField.GetValue(obj)); sync.Write(defs.IndexOf(facepaintDefOneField.GetValue(obj))); sync.Write(defs.IndexOf(facepaintDefTwoField.GetValue(obj))); } else { facepaintColourOneField.SetValue(obj, sync.Read <Color>()); facepaintColourTwoField.SetValue(obj, sync.Read <Color>()); int index = sync.Read <int>(); if (index >= 0) { facepaintDefOneField.SetValue(obj, defs[index]); } index = sync.Read <int>(); if (index >= 0) { facepaintDefTwoField.SetValue(obj, defs[index]); } } }
// Sync worker for the Dialog_AssignPreacher (and Dialog_AssignAssistant, as it's implicit worker) private static void SyncDialogAssignPreacher(SyncWorker sync, ref Window obj) { if (sync.isWriting) { var sermon = assignPreacherSermonField(obj); var altar = assignPreacherAltarField(obj) as Building; if (TryGetDataForSermon(sermon, altar, out var index)) { sync.Write(index); sync.Write(altar); sync.Write(obj.GetType() == assignPreacherType); } else { sync.Write(-1); } } else { var index = sync.Read <int>(); if (index >= 0) { var altar = sync.Read <Building>(); var sermon = GetSermon(altar, index); var type = sync.Read <bool>() ? assignPreacherType : assignAssistantType; obj = Activator.CreateInstance(type, altar, sermon) as Window; } } }
// Used for syncing inner, compiler-generated class inside of TempleCardUtility private static void SyncTemplaCardUtilityInnerClass(SyncWorker sync, object obj) { if (sync.isWriting) { var altar = templeCardUtilityInnerAltarField(obj) as Building; var sermon = templeCardUtilityInnerSermonField(obj); if (TryGetDataForSermon(sermon, altar, out var index)) { sync.Write(index); sync.Write(altar); } else { sync.Write(-1); } } else { var index = sync.Read <int>(); if (index >= 0) { var altar = sync.Read <Building>(); templeCardUtilityInnerAltarField(obj) = altar; templeCardUtilityInnerSermonField(obj) = GetSermon(altar, index); } } }
private static void SyncPsykerDisciplineWindowAny(SyncWorker sync, ref object obj, Type windowType) { if (sync.isWriting) { sync.Write((ThingComp)psykerDisciplineWindowCompField.GetValue(obj)); sync.Write(((Def)psykerDisciplineWindowSelectedDefField.GetValue(obj)).shortHash); } else { var comp = sync.Read <ThingComp>(); var hash = sync.Read <ushort>(); var def = getDefByShortHash.Invoke(null, new object[] { hash }); // If the window exists, we try to find a window for the discipline field for that pawn obj = Find.WindowStack.Windows.FirstOrDefault(x => x.GetType() == windowType && (ThingComp)psykerDisciplineWindowCompField.GetValue(x) == comp); // If a specific player doesn't have the psyker menu open we'll have null here, we need to create it for our synced method if (obj == null) { // The Window_Psyker is needed for constructor and the synced method // It won't really do anything useful, but is needed var psykerWindow = Activator.CreateInstance(psykerWindowType, comp); obj = Activator.CreateInstance(windowType, comp, psykerWindow); } // Set the def to the correct one (someone might have another one selected, so make sure the same one is picked for everyone) psykerDisciplineWindowSelectedDefField.SetValue(obj, def); } }
private static void SyncSetIngredientCommand(SyncWorker sync, ref Command command) { var traverse = Traverse.Create(command); var building = traverse.Field("building"); var ingredientList = traverse.Field("things"); if (sync.isWriting) { sync.Write(building.GetValue() as Thing); var list = ingredientList.GetValue() as List <Thing>; sync.Write(list.Count); foreach (var item in list) { sync.Write(item as Thing); } } else { building.SetValue(sync.Read <Thing>()); int count = sync.Read <int>(); var list = new List <Thing>(count); for (int i = 0; i < count; i++) { list.Add(sync.Read <Thing>()); } ingredientList.SetValue(list); } }
private static void SyncSetIngredientCommand(SyncWorker sync, ref Command command) { var traverse = Traverse.Create(command); var building = traverse.Field("building"); var ingredientList = traverse.Field("things"); if (sync.isWriting) { sync.Write(building.GetValue() as Thing); var ingredientListValue = ingredientList.GetValue(); if (ingredientListValue == null) { sync.Write(false); } else { sync.Write(true); sync.Write(ingredientList.GetValue() as List <Thing>); } } else { building.SetValue(sync.Read <Thing>()); if (sync.Read <bool>()) { ingredientList.SetValue(sync.Read <List <Thing> >()); } } }
private static void SyncInnerClassWithPawn(SyncWorker sync, ref object inner) { var traverse = Traverse.Create(inner); if (sync.isWriting) { var comp = (ThingComp)traverse.Field("<>4__this").GetValue(); var pawn = (Pawn)traverse.Field("p").GetValue(); sync.Write(comp); sync.Write(pawn.thingIDNumber); } else { var comp = sync.Read <ThingComp>(); var id = sync.Read <int>(); var pawn = GetPawnFromComp(comp, id); traverse.Field("<>4__this").SetValue(comp); if (pawn != null) { traverse.Field("p").SetValue(pawn); } } }
private static void SyncSurrogateToHackDesignator(SyncWorker sync, ref Designator designator) { if (sync.isWriting) { sync.Write((byte)surrogateToHackHackTypeField(designator)); sync.Write(surrogateToHackTargetField(designator)); var map = surrogateToHackMapField(designator); // Looks like the map and cell are set in only one method, which is never called // so we'll most likely end up never syncing them. I'm leaving it for safety, though. if (map == null) { sync.Write(IntVec3.Invalid); } else { sync.Write(surrogateToHackPosField(designator)); sync.Write(map); } } else { designator = (Designator)surrogateToHackConstructor.Invoke(new object[] { (int)sync.Read <byte>() }); surrogateToHackTargetField(designator) = sync.Read <Pawn>(); var pos = sync.Read <IntVec3>(); if (pos.IsValid) { surrogateToHackPosField(designator) = pos; surrogateToHackMapField(designator) = sync.Read <Map>(); } } }
static void SyncLearnPsycasts(SyncWorker sync, ref Command_Action command) { if (sync.isWriting) { sync.Write(levelField(command)); sync.Write(parentField(command)); } else { command = (Command_Action) Activator.CreateInstance(learnPsycastsType, sync.Read<int>(), sync.Read<Pawn>()); } }
private static void SyncVisitSite(SyncWorker sync, ref TransportPodsArrivalAction_VisitSite transportPodAction) { if (sync.isWriting) { sync.Write((Site)siteField.GetValue(transportPodAction)); sync.Write((PawnsArrivalModeDef)visitSiteArrivalModeField.GetValue(transportPodAction)); } else { transportPodAction = new TransportPodsArrivalAction_VisitSite(sync.Read <Site>(), sync.Read <PawnsArrivalModeDef>()); } }
private static void SyncIntVec3Pair(SyncWorker sync, ref Pair <IntVec3, IntVec3> pair) { if (sync.isWriting) { sync.Write(pair.First); sync.Write(pair.Second); } else { pair = new Pair <IntVec3, IntVec3>(sync.Read <IntVec3>(), sync.Read <IntVec3>()); } }
private static void SyncAttackSettlement(SyncWorker sync, ref TransportPodsArrivalAction_AttackSettlement transportPodAction) { if (sync.isWriting) { sync.Write((Settlement)attackSettlementField.GetValue(transportPodAction)); sync.Write((PawnsArrivalModeDef)attackSettlementArrivalModeField.GetValue(transportPodAction)); } else { transportPodAction = new TransportPodsArrivalAction_AttackSettlement(sync.Read <Settlement>(), sync.Read <PawnsArrivalModeDef>()); } }
private static void SyncCommand(SyncWorker sync, ref Command command) { if (sync.isWriting) { sync.Write(setGenomeListMap(command)); sync.Write(setGenomeListBuilding(command)); } else { setGenomeListMap(command) = sync.Read <Map>(); setGenomeListBuilding(command) = sync.Read <Building>(); } }
private static void SyncLandInSpecificCell(SyncWorker sync, ref TransportPodsArrivalAction_LandInSpecificCell transportPodAction) { if (sync.isWriting) { sync.Write((MapParent)mapParentField.GetValue(transportPodAction)); sync.Write((IntVec3)cellField.GetValue(transportPodAction)); sync.Write((bool)landInShuttleField.GetValue(transportPodAction)); } else { transportPodAction = new TransportPodsArrivalAction_LandInSpecificCell(sync.Read <MapParent>(), sync.Read <IntVec3>(), sync.Read <bool>()); } }
private static void SyncFishingZoneChange(SyncWorker sync, ref Command command) { if (sync.isWriting) { sync.Write(mapField(command)); sync.Write(fishingZoneField(command)); } else { command = (Command)FormatterServices.GetUninitializedObject(commandType); mapField(command) = sync.Read <Map>(); fishingZoneField(command) = sync.Read <Zone>(); } }
private static void SyncFishingZoneChange(SyncWorker sync, ref Command command) { if (sync.isWriting) { sync.Write(((Map)mapField.GetValue(command)).Index); sync.Write((Zone)fishingZoneField.GetValue(command)); } else { command = (Command)FormatterServices.GetUninitializedObject(commandType); mapField.SetValue(command, Find.Maps[sync.Read <int>()]); fishingZoneField.SetValue(command, sync.Read <Zone>()); } }
private static void SyncRitualReferenceInnerClass(SyncWorker sync, ref object obj) { if (sync.isWriting) { var ritualReference = ritualReferenceInnerSelfField.GetValue(obj); var parent = (ThingWithComps)ritualReferenceInnerParentField.GetValue(obj); var rituals = ritualReferenceInnerRitualsField.GetValue(obj); // Get the index of our ritual reference inside of the comp props var comp = parent.AllComps.First(x => x.GetType() == compRitualAltarType); var ritualsList = (IList)ritualCompPropertiesRitualsField.GetValue(comp.props); var index = ritualsList.IndexOf(ritualReference); // We need to be able to retrieve the RitualReference, otherwise we won't really be able to sync // (We could technically sync the Def inside of this object, but it ended up not syncing when I tried) sync.Write(index); if (index >= 0) { sync.Write <Thing>(parent); SyncRitualTracker(sync, ref rituals); } } else { var index = sync.Read <int>(); if (index >= 0) { var parent = sync.Read <Thing>(); object rituals = null; SyncRitualTracker(sync, ref rituals); ritualReferenceInnerParentField.SetValue(obj, parent); ritualReferenceInnerRitualsField.SetValue(obj, rituals); if (index >= 0) { var comp = ((ThingWithComps)parent).AllComps.First(x => x.GetType() == compRitualAltarType); var ritualsList = (IList)ritualCompPropertiesRitualsField.GetValue(comp.props); var ritualReference = ritualsList[index]; ritualReferenceInnerSelfField.SetValue(obj, ritualReference); var def = ritualReferenceDefField.GetValue(ritualReference); var ritualList = ritualTrackerGetRitualMethod.Invoke(rituals, new object[] { def }); ritualReferenceInnerRitualField.SetValue(obj, ritualList); } } } }
// Besides syncing a normal WonderWorker, we also need the info for target and if it was cancelled private static void SyncWonderTargetableWorker(SyncWorker sync, ref object obj) { SyncWonderWorker(sync, ref obj); if (sync.isWriting) { sync.Write(wonderWorkerTargetableCanceledField(obj)); sync.Write(wonderWorkerTargetableTargetField(obj)); } else { wonderWorkerTargetableCanceledField(obj) = sync.Read <bool>(); wonderWorkerTargetableTargetField(obj) = sync.Read <TargetInfo>(); } }
static void SyncLearnPsycasts(SyncWorker sync, ref Command_Action command) { if (sync.isWriting) { sync.Write((int)levelField.GetValue(command)); sync.Write((Pawn)parentField.GetValue(command)); } else { command = (Command_Action)Activator.CreateInstance(learnPsycastsType, new object[] { sync.Read <int>(), sync.Read <Pawn>() }); } }
private static void SyncVerbManager(SyncWorker sync, ref object obj) { if (sync.isWriting) { // Sync the pawn that has the VerbManager sync.Write((Pawn)mvcfPawnGetter.Invoke(obj, Array.Empty <object>())); } else { var pawn = sync.Read <Pawn>(); var comp = mvcfGetWorldCompMethod.Invoke(null, Array.Empty <object>()); var weakTable = mvcfManagersTableField.GetValue(comp); var outParam = new object[] { pawn, null }; // Either try getting the VerbManager from the comp, or create it if it's missing if ((bool)conditionalWeakTableTryGetValueMethod.Invoke(weakTable, outParam)) { obj = outParam[1]; } else { obj = InitVerbManager(pawn, (WorldComponent)comp, table: weakTable); } } }
private static void SyncExtendedPawnData(SyncWorker sync, ref object data) { if (sync.isWriting) { var id = int.MaxValue; foreach (DictionaryEntry dictionaryEntry in pawnStorageDictionary(extendedDataStorageInstance)) { if (dictionaryEntry.Value == data) { id = (int)dictionaryEntry.Key; break; } } sync.Write(id); } else { var id = sync.Read <int>(); if (id != int.MaxValue && thingsById.TryGetValue(id, out var thing) && thing is Pawn) { data = getExtendedDataForPawnMethod.Invoke(extendedDataStorageInstance, new object[] { thing }); } } }
private static void SyncManagedVerb(SyncWorker sync, ref object obj) { if (sync.isWriting) { // Get the VerbManager from inside of the ManagedVerb itself var verbManager = mvcfManagerVerbManagerField.GetValue(obj); // Find the ManagedVerb inside of list of all verbs var managedVerbsList = mvcfVerbsField.GetValue(verbManager) as IList; var index = managedVerbsList.IndexOf(obj); // Sync the index of the verb as well as the manager (if it's valid) sync.Write(index); if (index >= 0) { SyncVerbManager(sync, ref verbManager); } } else { // Read and check if the index is valid var index = sync.Read <int>(); if (index >= 0) { // Read the verb manager object verbManager = null; SyncVerbManager(sync, ref verbManager); // Find the ManagedVerb with specific index inside of list of all verbs var managedVerbsList = mvcfVerbsField.GetValue(verbManager) as IList; obj = managedVerbsList[index]; } } }
void ReallowInStockpileGizmoWorker(SyncWorker sync, ref Command obj) { if (sync.isWriting) { sync.Write(thingDefLabel(obj)); sync.Write(zoneStockpileLabel(obj)); sync.Write(categoryLabel(obj)); } else { obj = (Command)FormatterServices.GetUninitializedObject(reallowGizmoType); thingDefLabel(obj) = sync.Read <ThingDef>(); zoneStockpileLabel(obj) = sync.Read <Zone_Stockpile>(); categoryLabel(obj) = sync.Read <ThingCategoryDef>(); } }
static void SyncRename(SyncWorker sync, ref Dialog_RenameColony rename) { if (sync.isWriting) { sync.Write(rename.changeNameTo); sync.Write(rename.changeSecondNameTo); sync.Write(rename.changingSettlement); } else { string new_faction_name = sync.Read <string>(); string new_base_name = sync.Read <string>(); Settlement new_base_obj = sync.Read <Settlement>(); NamePlayerFactionDialogUtility.Named(new_faction_name); NamePlayerSettlementDialogUtility.Named(new_base_obj, new_base_name); } }
static void SyncCommand(SyncWorker sync, ref Command type) { if (sync.isWriting) { sync.Write(type.actionHash); sync.Write(type.amount); sync.Write(type.boughtBy); } else { Command command = new Command(); command.actionHash = sync.Read <string>(); command.amount = sync.Read <int>(); command.boughtBy = sync.Read <string>(); type = command; } }
private static void SyncOperation(SyncWorker sync, ref object operation) { if (sync.isWriting) { sync.Write(operationPodField(operation)); // Right now we have 2 types it could be, but there could be more in the future sync.Write(operation.GetType()); } else { var pod = sync.Read <ThingComp>(); var type = sync.Read <Type>(); // All the current types right now have 1 argument operation = Activator.CreateInstance(type, pod); } }
static void SyncWorkerForThingDefStuffDefPair(SyncWorker sync, ref object obj) { var traverse = Traverse.Create(obj); var thingField = traverse.Field("thing"); var stuffField = traverse.Field("stuff"); if (sync.isWriting) { sync.Write(thingField.GetValue <ThingDef>()); sync.Write(stuffField.GetValue <ThingDef>()); } else { thingField.SetValue(sync.Read <ThingDef>()); stuffField.SetValue(sync.Read <ThingDef>()); } }