Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created September 9, 2018 14:10
Show Gist options
  • Save juntalis/393ae2c547e0bba21ada4889ae51ac5a to your computer and use it in GitHub Desktop.
Save juntalis/393ae2c547e0bba21ada4889ae51ac5a to your computer and use it in GitHub Desktop.
Unofficial configurable maps B19
using System;
using System.Linq;
using Harmony;
using MapReroll.Patches;
using MapReroll.UI;
using RimWorld;
using UnityEngine;
using Verse;
namespace MapReroll.Compat {
/// <summary>
/// Compatibility tweaks to play nicely with Rainbeau's Configurable Maps
/// </summary>
public class Compat_ConfigurableMaps {
private delegate TerrainDef RFRBeachMakerBeachTerrainAt(IntVec3 c, Map map, BiomeDef biome);
private static RFRBeachMakerBeachTerrainAt BeachMakerBeachTerrainAt;
public static void Apply(HarmonyInstance harmonyInst) {
try {
var rfrTerrainGenstep = GenTypes.GetTypeInAnyAssembly("ConfigurableMaps.Maker.CMGenStep_Terrain");
if (rfrTerrainGenstep == null) return; // mod is not loaded
ReflectionCache.BeachMakerType = ReflectionCache.ReflectType("ConfigurableMaps.Maker.CMBeachMaker", rfrTerrainGenstep.Assembly);
if (ReflectionCache.BeachMakerType != null) {
ReflectionCache.BeachMaker_Init = ReflectionCache.ReflectMethod("Init", ReflectionCache.BeachMakerType, typeof(void), new[] {typeof(Map)});
ReflectionCache.BeachMaker_Cleanup = ReflectionCache.ReflectMethod("Cleanup", ReflectionCache.BeachMakerType, typeof(void), new Type[0]);
var rfrBeachTerrainAt = ReflectionCache.ReflectMethod("BeachTerrainAt", ReflectionCache.BeachMakerType, typeof(TerrainDef), new[] {typeof(IntVec3), typeof(Map), typeof(BiomeDef)});
BeachMakerBeachTerrainAt = (RFRBeachMakerBeachTerrainAt)Delegate.CreateDelegate(typeof(RFRBeachMakerBeachTerrainAt), null, rfrBeachTerrainAt);
if (BeachMakerBeachTerrainAt == null) throw new Exception("Failed to create BeachTerrainAt delegate");
}
ReflectionCache.RiverMakerType = ReflectionCache.ReflectType("ConfigurableMaps.Maker.CMRiverMaker");
if (ReflectionCache.RiverMakerType != null) {
ReflectionCache.GenStepTerrain_GenerateRiver = ReflectionCache.ReflectMethod("GenerateRiver", rfrTerrainGenstep, ReflectionCache.RiverMakerType, new[] {typeof(Map)});
ReflectionCache.RiverMaker_TerrainAt = ReflectionCache.ReflectMethod("TerrainAt", ReflectionCache.RiverMakerType, typeof(TerrainDef), new[] {typeof(IntVec3), typeof(bool)});
}
// required on account of different signatures
MapPreviewGenerator.AlternateBeachTerrainAtDelegate = AlternateBeachTerrainAt;
// add button to access settings window
Dialog_MapPreviews.DialogOnGUI -= ExtraMapPreviewsDialogOnGUI;
Dialog_MapPreviews.DialogOnGUI += ExtraMapPreviewsDialogOnGUI;
// ensures the modded BeachMaker is also affected by the "Map generator mode" setting
var beachMakerInit = AccessTools.Method(GenTypes.GetTypeInAnyAssembly("ConfigurableMaps.Maker.CMBeachMaker"), "Init");
if (beachMakerInit == null) throw new Exception("Failed to reflect CMBeachMaker.Init");
var prefix = ((Action<Map>)DeterministicGenerationPatcher.DeterministicBeachSetup).Method;
DeterministicGenerationPatcher.InstrumentMethodForDeterministicGeneration(beachMakerInit, prefix, harmonyInst);
// same for the river generator
var genStepTerrainGenerateRiver = AccessTools.Method(rfrTerrainGenstep, "GenerateRiver", new []{typeof(Map)});
if (genStepTerrainGenerateRiver == null) throw new Exception("Failed to reflect CMGenStep_Terrain.GenerateRiver");
prefix = ((Action<Map>)DeterministicGenerationPatcher.DeterministicRiverSetup).Method;
DeterministicGenerationPatcher.InstrumentMethodForDeterministicGeneration(genStepTerrainGenerateRiver, prefix, harmonyInst);
MapRerollController.Instance.Logger.Message("Applied Configurable Maps compatibility layer");
} catch (Exception e) {
MapRerollController.Instance.Logger.Error("Failed to apply compatibility layer for Configurable Maps:" +e);
}
}
private static TerrainDef AlternateBeachTerrainAt(IntVec3 c, BiomeDef biome) {
return BeachMakerBeachTerrainAt(c, null, biome);
}
// add a button to the previews dialog for easy access to terrain settings
private static void ExtraMapPreviewsDialogOnGUI(Dialog_MapPreviews previewsDialog, Rect inRect) {
var closeButtonSize = new Vector2(120f, 40f);
var configureButtonSize = new Vector2(140f, 40f);
var elementSpacing = 10f;
if (Widgets.ButtonText(new Rect(inRect.width - closeButtonSize.x - elementSpacing - configureButtonSize.x, inRect.yMax - configureButtonSize.y, configureButtonSize.x, configureButtonSize.y), "Reroll2_previews_configureMap".Translate())) {
var mod = LoadedModManager.ModHandles.FirstOrDefault(m => m.GetType().FullName == "ConfigurableMaps.Settings.TerrainSettingsController");
if (mod != null) {
previewsDialog.Close();
var settingsDialog = new Dialog_ModSettings();
// pre-select the terrain settings Mod
ReflectionCache.DialogModSettings_SelMod.SetValue(settingsDialog, mod);
Find.WindowStack.Add(settingsDialog);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment