4
4
using System . Linq ;
5
5
using System . Reflection ;
6
6
using System . Reflection . Emit ;
7
+ using System . Runtime . Serialization ;
7
8
using HarmonyLib ;
8
9
using Multiplayer . API ;
9
10
using RimWorld ;
@@ -48,6 +49,7 @@ public VanillaExpandedFramework(ModContentPack mod)
48
49
( PatchWorkGiverDeliverResources , "Building stuff requiring non-construction skill" , false ) ,
49
50
( PatchExpandableProjectile , "Expandable projectile" , false ) ,
50
51
( PatchStaticCaches , "Static caches" , false ) ,
52
+ ( PatchGraphicCustomizationDialog , "Graphic Customization Dialog" , true ) ,
51
53
] ;
52
54
53
55
foreach ( var ( patchMethod , componentName , latePatch ) in patches )
@@ -1521,5 +1523,180 @@ private static bool NeverTimeoutDueToRealTime(ref bool __result, ref int ___Upda
1521
1523
}
1522
1524
1523
1525
#endregion
1526
+
1527
+ #region Graphic Customization Dialog
1528
+
1529
+ // Dialog_GraphicCustomization
1530
+ private static Type graphicCustomizationDialogType ;
1531
+ internal static AccessTools . FieldRef < Window , ThingComp > graphicCustomizationCompField ;
1532
+ private static AccessTools . FieldRef < Window , ThingComp > graphicCustomizationGeneratedNamesCompField ;
1533
+ private static AccessTools . FieldRef < Window , Pawn > graphicCustomizationPawnField ;
1534
+ private static AccessTools . FieldRef < Window , IList > graphicCustomizationCurrentVariantsField ;
1535
+ private static AccessTools . FieldRef < Window , string > graphicCustomizationCurrentNameField ;
1536
+
1537
+ // TextureVariant
1538
+ private static SyncType variantsListType ;
1539
+ private static AccessTools . FieldRef < object , string > textureVariantTexNameField ;
1540
+ private static AccessTools . FieldRef < object , string > textureVariantTextureField ;
1541
+ private static AccessTools . FieldRef < object , string > textureVariantOutlineField ;
1542
+ private static AccessTools . FieldRef < object , object > textureVariantTextureVariantOverrideField ;
1543
+ private static AccessTools . FieldRef < object , float > textureVariantChanceOverrideField ;
1544
+
1545
+ // TextureVariantOverride
1546
+ private static SyncType textureVariantOverrideType ;
1547
+ private static AccessTools . FieldRef < object , float > textureVariantOverrideChanceField ;
1548
+ private static AccessTools . FieldRef < object , string > textureVariantOverrideGroupNameField ;
1549
+ private static AccessTools . FieldRef < object , string > textureVariantOverrideTexNameField ;
1550
+
1551
+ private static void PatchGraphicCustomizationDialog ( )
1552
+ {
1553
+ var type = graphicCustomizationDialogType = AccessTools . TypeByName ( "GraphicCustomization.Dialog_GraphicCustomization" ) ;
1554
+ graphicCustomizationCompField = AccessTools . FieldRefAccess < ThingComp > ( type , "comp" ) ;
1555
+ graphicCustomizationGeneratedNamesCompField = AccessTools . FieldRefAccess < ThingComp > ( type , "compGeneratedName" ) ;
1556
+ graphicCustomizationPawnField = AccessTools . FieldRefAccess < Pawn > ( type , "pawn" ) ;
1557
+ graphicCustomizationCurrentVariantsField = AccessTools . FieldRefAccess < IList > ( type , "currentVariants" ) ;
1558
+ graphicCustomizationCurrentNameField = AccessTools . FieldRefAccess < string > ( type , "currentName" ) ;
1559
+ // Accept customization
1560
+ var method = MpMethodUtil . GetLambda ( type , nameof ( Window . DoWindowContents ) , 0 ) ;
1561
+ MP . RegisterSyncMethod ( method ) ;
1562
+ MpCompat . RegisterLambdaMethod ( type , nameof ( Window . DoWindowContents ) , 0 ) ;
1563
+ MP . RegisterSyncWorker < Window > ( SyncGraphicCustomizationDialog , type , true ) ;
1564
+ MpCompat . harmony . Patch ( AccessTools . DeclaredMethod ( type , "DrawConfirmButton" ) ,
1565
+ prefix : new HarmonyMethod ( CloseGraphicCustomizationDialogOnAccept ) ) ;
1566
+ MpCompat . harmony . Patch ( AccessTools . DeclaredMethod ( type , nameof ( Window . DoWindowContents ) ) ,
1567
+ prefix : new HarmonyMethod ( CloseGraphicCustomizationWhenNoLongerValid ) ) ;
1568
+
1569
+ type = AccessTools . TypeByName ( "GraphicCustomization.TextureVariant" ) ;
1570
+ variantsListType = typeof ( List < > ) . MakeGenericType ( type ) ;
1571
+ textureVariantTexNameField = AccessTools . FieldRefAccess < string > ( type , "texName" ) ;
1572
+ textureVariantTextureField = AccessTools . FieldRefAccess < string > ( type , "texture" ) ;
1573
+ textureVariantOutlineField = AccessTools . FieldRefAccess < string > ( type , "outline" ) ;
1574
+ textureVariantChanceOverrideField = AccessTools . FieldRefAccess < float > ( type , "chanceOverride" ) ;
1575
+ textureVariantTextureVariantOverrideField = AccessTools . FieldRefAccess < object > ( type , "textureVariantOverride" ) ;
1576
+ MP . RegisterSyncWorker < object > ( SyncTextureVariant , type , shouldConstruct : true ) ;
1577
+
1578
+ textureVariantOverrideType = type = AccessTools . TypeByName ( "GraphicCustomization.TextureVariantOverride" ) ;
1579
+ textureVariantOverrideChanceField = AccessTools . FieldRefAccess < float > ( type , "chance" ) ;
1580
+ textureVariantOverrideGroupNameField = AccessTools . FieldRefAccess < string > ( type , "groupName" ) ;
1581
+ textureVariantOverrideTexNameField = AccessTools . FieldRefAccess < string > ( type , "texName" ) ;
1582
+ MP . RegisterSyncWorker < object > ( SyncTextureVariantOverride , type , shouldConstruct : true ) ;
1583
+ }
1584
+
1585
+ private static void CloseGraphicCustomizationDialogOnAccept ( Window __instance , ref Action action )
1586
+ {
1587
+ // The action is a synced method, and it handles closing the dialog. Since
1588
+ // the method ends up being synced the closing does not happen. This will
1589
+ // ensure that the dialog is closed when the accept button is pressed
1590
+ // and the proper method will be synced as well.
1591
+ var nonRefAction = action ;
1592
+ action = ( ( ) => __instance . Close ( ) ) + nonRefAction ;
1593
+ }
1594
+
1595
+ private static void CloseGraphicCustomizationWhenNoLongerValid ( Window __instance , ThingComp ___comp , Pawn ___pawn )
1596
+ {
1597
+ // Since the dialog doesn't pause, ensure we close it if the comp's parent
1598
+ // or the pawn ever get destroyed, despawned, or end up on different maps.
1599
+ if ( MP . IsInMultiplayer && ! IsGraphicCustomizationDialogValid ( ___comp , ___pawn ) )
1600
+ __instance . Close ( ) ;
1601
+ }
1602
+
1603
+ private static bool CancelGraphicCustomizationExecutionIfNoLongerValid ( ThingComp ___comp , Pawn ___pawn )
1604
+ => ! MP . IsInMultiplayer || IsGraphicCustomizationDialogValid ( ___comp , ___pawn ) ;
1605
+
1606
+ private static bool IsGraphicCustomizationDialogValid ( ThingComp comp , Pawn pawn )
1607
+ => comp . parent != null && pawn != null &&
1608
+ comp . parent . Spawned && pawn . Spawned &&
1609
+ ! comp . parent . Destroyed && ! pawn . Destroyed &&
1610
+ ! pawn . Dead && comp . parent . Map == pawn . Map ;
1611
+
1612
+ private static void SyncGraphicCustomizationDialog ( SyncWorker sync , ref Window dialog )
1613
+ {
1614
+ ThingComp comp = null ;
1615
+
1616
+ if ( sync . isWriting )
1617
+ {
1618
+ sync . Write ( graphicCustomizationCompField ( dialog ) ) ;
1619
+ }
1620
+ else
1621
+ {
1622
+ // Skip constructor since it has a bunch of initialization we don't care about.
1623
+ dialog = ( Window ) FormatterServices . GetUninitializedObject ( graphicCustomizationDialogType ) ;
1624
+
1625
+ comp = sync . Read < ThingComp > ( ) ;
1626
+ graphicCustomizationCompField ( dialog ) = comp ;
1627
+ }
1628
+
1629
+ SyncGraphicCustomizationDialog ( sync , ref dialog , comp ) ;
1630
+ }
1631
+
1632
+ internal static void SyncGraphicCustomizationDialog ( SyncWorker sync , ref Window dialog , ThingComp graphicCustomizationComp )
1633
+ {
1634
+ if ( sync . isWriting )
1635
+ {
1636
+ sync . Write ( graphicCustomizationPawnField ( dialog ) ) ;
1637
+ sync . Write ( graphicCustomizationCurrentVariantsField ( dialog ) , variantsListType ) ;
1638
+ sync . Write ( graphicCustomizationCurrentNameField ( dialog ) ) ;
1639
+ }
1640
+ else
1641
+ {
1642
+ graphicCustomizationGeneratedNamesCompField ( dialog ) = graphicCustomizationComp ? . parent . GetComp < CompGeneratedNames > ( ) ;
1643
+ graphicCustomizationPawnField ( dialog ) = sync . Read < Pawn > ( ) ;
1644
+ graphicCustomizationCurrentVariantsField ( dialog ) = sync . Read < IList > ( variantsListType ) ;
1645
+ graphicCustomizationCurrentNameField ( dialog ) = sync . Read < string > ( ) ;
1646
+ }
1647
+ }
1648
+
1649
+ private static void SyncTextureVariant ( SyncWorker sync , ref object variant )
1650
+ {
1651
+ if ( sync . isWriting )
1652
+ {
1653
+ if ( variant == null )
1654
+ {
1655
+ sync . Write ( false ) ;
1656
+ return ;
1657
+ }
1658
+
1659
+ sync . Write ( true ) ;
1660
+
1661
+ sync . Write ( textureVariantTexNameField ( variant ) ) ;
1662
+ sync . Write ( textureVariantTextureField ( variant ) ) ;
1663
+ sync . Write ( textureVariantOutlineField ( variant ) ) ;
1664
+ sync . Write ( textureVariantTextureVariantOverrideField ( variant ) , textureVariantOverrideType ) ;
1665
+ sync . Write ( textureVariantChanceOverrideField ( variant ) ) ;
1666
+ }
1667
+ else if ( sync . Read < bool > ( ) )
1668
+ {
1669
+ textureVariantTexNameField ( variant ) = sync . Read < string > ( ) ;
1670
+ textureVariantTextureField ( variant ) = sync . Read < string > ( ) ;
1671
+ textureVariantOutlineField ( variant ) = sync . Read < string > ( ) ;
1672
+ textureVariantTextureVariantOverrideField ( variant ) = sync . Read < object > ( textureVariantOverrideType ) ;
1673
+ textureVariantChanceOverrideField ( variant ) = sync . Read < float > ( ) ;
1674
+ }
1675
+ }
1676
+
1677
+ private static void SyncTextureVariantOverride ( SyncWorker sync , ref object variantOverride )
1678
+ {
1679
+ if ( sync . isWriting )
1680
+ {
1681
+ if ( variantOverride == null )
1682
+ {
1683
+ sync . Write ( false ) ;
1684
+ return ;
1685
+ }
1686
+
1687
+ sync . Write ( true ) ;
1688
+ sync . Write ( textureVariantOverrideChanceField ( variantOverride ) ) ;
1689
+ sync . Write ( textureVariantOverrideGroupNameField ( variantOverride ) ) ;
1690
+ sync . Write ( textureVariantOverrideTexNameField ( variantOverride ) ) ;
1691
+ }
1692
+ else if ( sync . Read < bool > ( ) )
1693
+ {
1694
+ textureVariantOverrideChanceField ( variantOverride ) = sync . Read < float > ( ) ;
1695
+ textureVariantOverrideGroupNameField ( variantOverride ) = sync . Read < string > ( ) ;
1696
+ textureVariantOverrideTexNameField ( variantOverride ) = sync . Read < string > ( ) ;
1697
+ }
1698
+ }
1699
+
1700
+ #endregion
1524
1701
}
1525
1702
}
0 commit comments