Skip to content

Commit

Permalink
2.1.3: Detour checks, short hash fix
Browse files Browse the repository at this point in the history
- Added checks to detours that ensure correct parameters, return type, etc.
- Added automatic fix for short hash collision errors
- Added Chinese translation
  • Loading branch information
UnlimitedHugs committed Dec 23, 2016
1 parent b0cb447 commit a14bd31
Show file tree
Hide file tree
Showing 11 changed files with 469 additions and 77 deletions.
2 changes: 2 additions & 0 deletions HugsLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@
<Compile Include="Source\Core\KeyBindingDefOf.cs" />
<Compile Include="Source\Core\MapComponent_HugsProxy.cs" />
<Compile Include="Source\Core\PersistentDataManager.cs" />
<Compile Include="Source\Core\ShortHashCollisionResolver.cs" />
<Compile Include="Source\Core\UnityProxyComponent.cs" />
<Compile Include="Source\Core\VersionFile.cs" />
<Compile Include="Source\Core\VersionShort.cs" />
<Compile Include="Source\Core\WindowReplacer.cs" />
<Compile Include="Source\Detour\Attribute.cs" />
<Compile Include="Source\Detour\DetourProvider.cs" />
<Compile Include="Source\Detour\DetourValidator.cs" />
<Compile Include="Source\Detour\Helpers.cs" />
<Compile Include="Source\HugsLibController.cs" />
<Compile Include="Source\Logs\Dialog_PublishLogs.cs" />
Expand Down
2 changes: 1 addition & 1 deletion Mods/HugsLib/About/About.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
<targetVersion>0.16.0</targetVersion>
<description>&lt;color=orange&gt;&lt;b&gt;Important: &lt;/b&gt; This mod should be one of the first to be loaded to work properly.&lt;/color&gt;\n
HugsLib is a library that provides shared functionality to other mods.
Version: 2.1.2
Version: 2.1.3
</description>
</ModMetaData>
2 changes: 1 addition & 1 deletion Mods/HugsLib/About/Version.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<VersionData>
<overrideVersion>2.1.2</overrideVersion>
<overrideVersion>2.1.3</overrideVersion>
<gitHubRepository>UnlimitedHugs/RimworldHugsLib</gitHubRepository>
</VersionData>
Binary file modified Mods/HugsLib/Assemblies/HugsLib.dll
Binary file not shown.
41 changes: 41 additions & 0 deletions Source/Core/ShortHashCollisionResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections;
using System.Collections.Generic;
using HugsLib.Utils;
using Verse;

namespace HugsLib.Core {
/**
* A fix for Defs that ended up being assigned a duplicate short hash.
* Looks through all defs and when a collision is detected assigns a new short has to the Def.
* This is a temporary fix for a vanilla issue.
*/
public class ShortHashCollisionResolver {
public static void ResolveCollisions() {
var seenHashes = new HashSet<ushort>();
var defsToRehash = new List<Def>();
foreach (Type current in GenDefDatabase.AllDefTypesWithDatabases()) {
var type = typeof(DefDatabase<>).MakeGenericType(current);
var property = type.GetProperty("AllDefs");
var getMethod = property.GetGetMethod();
var allDefsInDatabase = (IEnumerable)getMethod.Invoke(null, null);
defsToRehash.Clear();
foreach (Def def in allDefsInDatabase) {
if (seenHashes.Contains(def.shortHash)) {
defsToRehash.Add(def);
} else {
seenHashes.Add(def.shortHash);
}
}
defsToRehash.SortBy(d => d.defName);
for (int i = 0; i < defsToRehash.Count; i++) {
var def = defsToRehash[i];
def.shortHash = 0;
InjectedDefHasher.GiveShortHasToDef(def);
Log.Message(def.defName+" "+def.shortHash);
}
seenHashes.Clear();
}
}
}
}
33 changes: 26 additions & 7 deletions Source/Detour/DetourProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace HugsLib.Source.Detour {
/**
* A tool to detour calls form one method to another. Will use Community Core Library detouring, if available, and its own equivalent otherwise.
*/

public class DetourProvider {
private const string CCLNamespace = "CommunityCoreLibrary";
private const string CCLDetoursClassName = "Detours";
Expand All @@ -28,7 +27,7 @@ public static void CompatibleDetour(MethodInfo source, MethodInfo destination) {
bool result = false;
Exception failureException = null;
try {
result = CompatibleDetourWithPreCheck(source, destination);
result = CompatibleDetourWithExceptions(source, destination);
} catch (Exception e) {
result = false;
failureException = e;
Expand Down Expand Up @@ -67,6 +66,15 @@ public static unsafe bool TryIndepentDetour(MethodInfo source, MethodInfo destin
return false;
}

// check for destination type fields, return type and argument compatibility
if (!DetourValidator.IsValidDetourPair(source, destination)) {
return false;
}
var warning = DetourValidator.GetLastWarning();
if (warning != null) {
HugsLibController.Logger.Warning(warning);
}

// do the detour, and add it to the list
detours.Add(source, destination);

Expand Down Expand Up @@ -118,25 +126,36 @@ public static unsafe bool TryIndepentDetour(MethodInfo source, MethodInfo destin
return true;
}

internal static bool CompatibleDetourWithPreCheck(MethodInfo source, MethodInfo destination) {
internal static bool CompatibleDetourWithExceptions(MethodInfo source, MethodInfo destination) {
if (detours.ContainsKey(source)) {
throw new Exception(String.Format("{0} was already detoured to {1}.", source.FullName(), destination.FullName()));
}
return TryCompatibleDetour(source, destination);
var result = TryCompatibleDetour(source, destination);
if (!result) {
var validatorError = DetourValidator.GetLastError();
if(validatorError!=null) throw new Exception(validatorError);
}
return result;
}

internal static void ThrowClearerDetourException(Exception e, MemberInfo sourceInfo, MemberInfo targetInfo, string detourMode) {
// do a proper breakdown of the cause of the exception, including source, target, and target assembly
var message = string.Format("Failed to detour {0} {1}", detourMode, DetourPairToString(sourceInfo, targetInfo));

throw new Exception(message, e);
}

internal static string DetourPairToString(MemberInfo sourceInfo, MemberInfo targetInfo) {
const string nullRefLabel = "[not found]";
var sourceDeclaringType = sourceInfo != null && sourceInfo.DeclaringType != null ? sourceInfo.DeclaringType.Name : "null";
var targetDeclaringType = targetInfo != null && targetInfo.DeclaringType != null ? targetInfo.DeclaringType.Name : "null";
var message = string.Format("Failed to detour {0} {1} to {2}", detourMode,
var result = string.Format("{0} to {1}",
sourceInfo != null ? sourceDeclaringType + "." + sourceInfo.Name : nullRefLabel,
targetInfo != null ? targetDeclaringType + "." + targetInfo.Name : nullRefLabel);
if (targetInfo != null && targetInfo.DeclaringType != null) {
message += string.Format(" (assembly: {0})", targetInfo.DeclaringType.Assembly.GetName().Name);
result += string.Format(" (assembly: {0})", targetInfo.DeclaringType.Assembly.GetName().Name);
}
throw new Exception(message, e);
return result;
}

private static MethodInfo TryGetCCLDetourMethod() {
Expand Down
Loading

0 comments on commit a14bd31

Please sign in to comment.