diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc4da8..74b5130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 2023.3.1 + * Fixed a rare crash when the plugin was completely unable to find Rimworld + * Fixed automatic Rimworld detection when Rimworld is installed through Steam on the C: drive + * Fixed some false positives on error checking in XML + * Added more mod folders to the XML Project that gets added automatically + ## 2023.3 * Rimworld XML will now exist as it's own project * Added some new problem analyzers to catch simple typing errors in Rimworld XML diff --git a/buildPlugin.ps1 b/buildPlugin.ps1 index f7f22f9..eb50b81 100644 --- a/buildPlugin.ps1 +++ b/buildPlugin.ps1 @@ -1,5 +1,5 @@ Param( - $Version = "2023.3" + $Version = "2023.3.1" ) Set-StrictMode -Version Latest diff --git a/gradle.properties b/gradle.properties index f01793c..49bd14d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ DotnetPluginId=ReSharperPlugin.RimworldDev DotnetSolution=ReSharperPlugin.RimworldDev.sln RiderPluginId=com.jetbrains.rider.plugins.rimworlddev -PluginVersion=2023.3 +PluginVersion=2023.3.1 BuildConfiguration=Release diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/ProblemAnalyzers/CustomXmlAnalysisStageProcess.cs b/src/dotnet/ReSharperPlugin.RimworldDev/ProblemAnalyzers/CustomXmlAnalysisStageProcess.cs index 3927856..76e56dd 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/ProblemAnalyzers/CustomXmlAnalysisStageProcess.cs +++ b/src/dotnet/ReSharperPlugin.RimworldDev/ProblemAnalyzers/CustomXmlAnalysisStageProcess.cs @@ -89,9 +89,15 @@ void IRecursiveElementProcessor.ProcessAfterInterior(ITreeNode element) case "System.Int32": ProcessInt(fullText, range); return; + case "System.Single": + ProcessFloat(fullText, range); + return; case "Verse.IntRange": ProcessIntRange(fullText, range); return; + case "Verse.FloatRange": + ProcessFloatRange(fullText, range); + return; case "System.String": break; case "UnityEngine.Vector2": @@ -100,7 +106,15 @@ void IRecursiveElementProcessor.ProcessAfterInterior(ITreeNode element) case "UnityEngine.Vector3": ProcessVector3(fullText, range); break; + case "UnityEngine.Rect": + case "UnityEngine.Color": + case "RimWorld.PsychicDroneLevel": + case "RimWorld.FoodTypeFlags": + case "Verse.DevelopmentalStage": + case "Verse.ColorInt": + case "Verse.IntVec3": case "Verse.IntVec2": + case "Verse.WorkTags": break; default: if (context.GetType().Name == "Enum") @@ -124,23 +138,30 @@ private void ProcessBoolean(string textValue, DocumentRange range) { if (textValue.ToLower() is "true" or "false") return; - IHighlighting error = new XmlErrorHighlighting("Value must be \"true\" or \"false\"", range, Array.Empty()); - - myConsumer.AddHighlighting(error, range); + AddError("Value must be \"true\" or \"false\"", range); } private void ProcessInt(string textValue, DocumentRange range) { if (int.TryParse(textValue, out _)) return; - IHighlighting error = new XmlErrorHighlighting("Value must be a whole number with no decimal points", range, Array.Empty()); - - myConsumer.AddHighlighting(error, range); + AddError("Value must be a whole number with no decimal points", range); + } + + private void ProcessFloat(string textValue, DocumentRange range) + { + if (float.TryParse(textValue, out _)) return; + + AddError("Value must be a valid number", range); } private void ProcessIntRange(string textValue, DocumentRange range) { var strArray = textValue.Split('~'); + + // For some reason IntRange also just accepts a single number instead of a range + if (strArray.Length == 1 && int.TryParse(strArray[0], out _)) return; + if (strArray.Length != 2) { AddError("Your value must be two integers in a format similar to \"1~2\"", range); @@ -159,12 +180,40 @@ private void ProcessIntRange(string textValue, DocumentRange range) return; } } + + private void ProcessFloatRange(string textValue, DocumentRange range) + { + var strArray = textValue.Split('~'); + // For some reason FloatRange also just accepts a single number instead of a range + if (strArray.Length == 1 && float.TryParse(strArray[0], out _)) return; + + if (strArray.Length != 2) + { + AddError("Your value must be two integers in a format similar to \"1~2\"", range); + return; + } + + if (!float.TryParse(strArray[0], out _)) + { + AddError($"\"{strArray[0]}\" is not a valid float", range); + return; + } + + if (!float.TryParse(strArray[1], out _)) + { + AddError($"\"{strArray[1]}\" is not a valid float", range); + return; + } + } private void ProcessVector2(string textValue, DocumentRange range) { var match = Regex.Match(textValue.Trim(), @"^\((.*?),(.*?)\)$"); if (!match.Success) { + // For some reason Vector2 allows us to pass in just a single number instead of a vector? + if (float.TryParse(textValue, out _)) return; + AddError("Your value must be in a format similar to (1,2)", range); return; } diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.Rider.csproj b/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.Rider.csproj index eb67dc4..535a3ca 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.Rider.csproj +++ b/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.Rider.csproj @@ -15,6 +15,11 @@ $(DefineConstants);RIDER + + false + true + + diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.csproj b/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.csproj index 065ce23..cae39f7 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.csproj +++ b/src/dotnet/ReSharperPlugin.RimworldDev/ReSharperPlugin.RimworldDev.csproj @@ -14,6 +14,11 @@ false + + false + true + + diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Project/RimworldXmlProjectHost.cs b/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Project/RimworldXmlProjectHost.cs index 0fc0c4f..b8eaa53 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Project/RimworldXmlProjectHost.cs +++ b/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Project/RimworldXmlProjectHost.cs @@ -154,6 +154,6 @@ public bool Filter(VirtualFileSystemPath path) => path.Name.Equals("bin", StringComparison.OrdinalIgnoreCase) || path.Name.EndsWith(".DotSettings.user", StringComparison.OrdinalIgnoreCase) || path.Name.Equals("node_modules", StringComparison.OrdinalIgnoreCase) || - (!path.FullPath.Contains("About") && !path.FullPath.Contains("Defs")); + !new List {"About", "Defs", "Patches", "Languages", "Sounds", "Textures", "News"}.Any(it => path.FullPath.Contains(it)); } } \ No newline at end of file diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Solution/RimworldSolutionMarkProvider.cs b/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Solution/RimworldSolutionMarkProvider.cs index 843636e..943fc89 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Solution/RimworldSolutionMarkProvider.cs +++ b/src/dotnet/ReSharperPlugin.RimworldDev/RimworldXmlProject/Solution/RimworldSolutionMarkProvider.cs @@ -35,7 +35,17 @@ public ISolutionMark TryCreate(RdSolutionDescription solutionDescription) } var directory = VirtualFileSystemPath.TryParse(solutionDirectory, InteractionContext.SolutionContext); - var aboutFile = directory.TryCombine("About/About.xml"); + var projectDirectory = directory; + var aboutFile = projectDirectory.TryCombine("About/About.xml"); + var parentAttempts = 0; + while (!aboutFile.ExistsFile) + { + parentAttempts++; + projectDirectory = projectDirectory.Parent; + if (projectDirectory.Exists == FileSystemPath.Existence.Missing || parentAttempts >= 5) break; + + aboutFile = projectDirectory.TryCombine("About/About.xml"); + } if (!aboutFile.ExistsFile) return null; diff --git a/src/dotnet/ReSharperPlugin.RimworldDev/ScopeHelper.cs b/src/dotnet/ReSharperPlugin.RimworldDev/ScopeHelper.cs index 52767d7..a0b60aa 100644 --- a/src/dotnet/ReSharperPlugin.RimworldDev/ScopeHelper.cs +++ b/src/dotnet/ReSharperPlugin.RimworldDev/ScopeHelper.cs @@ -121,6 +121,8 @@ public static FileSystemPath FindRimworldDll(string currentPath) { var rimworldLocation = FindRimworldDirectory(currentPath); + if (rimworldLocation == null) return null; + var fileRelativePaths = new List { "RimWorldWin64_Data/Managed/Assembly-CSharp.dll", @@ -132,6 +134,8 @@ public static FileSystemPath FindRimworldDll(string currentPath) var location = fileRelativePaths.FirstOrDefault(path => FileSystemPath.ParseRelativelyTo(path, rimworldLocation).ExistsFile); + if (location == null) return null; + var path = FileSystemPath.ParseRelativelyTo(location, rimworldLocation); return path.ExistsFile ? path : null; @@ -163,9 +167,9 @@ private static IEnumerable GetSteamLocations() { var locations = new List { - @"C:\Program Files (x86)\Steam\", - @"C:\Program Files\Steam\", - "~/.steam/steam/" + @"C:\Program Files (x86)\Steam\steamapps\", + @"C:\Program Files\Steam\steamapps\", + "~/.steam/steam/steamapps/" }; locations.AddRange( diff --git a/src/rider/main/kotlin/run/RunState.kt b/src/rider/main/kotlin/run/RunState.kt index 0fac648..c6e51a4 100644 --- a/src/rider/main/kotlin/run/RunState.kt +++ b/src/rider/main/kotlin/run/RunState.kt @@ -6,6 +6,7 @@ import com.intellij.execution.configurations.RunProfileState import com.intellij.execution.process.* import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.ProgramRunner +import com.intellij.util.system.OS import com.jetbrains.rider.debugger.DebuggerWorkerProcessHandler import com.jetbrains.rider.plugins.unity.run.configurations.UnityAttachProfileState import com.jetbrains.rider.run.configurations.remote.RemoteConfiguration @@ -23,19 +24,32 @@ class RunState( targetName: String ) : UnityAttachProfileState(remoteConfiguration, executionEnvironment, targetName), RunProfileState { - private val resources = listOf( - ".doorstop_version", - "doorstop_config.ini", - "winhttp.dll", - - "Doorstop/0Harmony.dll", - "Doorstop/dnlib.dll", - "Doorstop/Doorstop.dll", - "Doorstop/Doorstop.pdb", - "Doorstop/HotReload.dll", - "Doorstop/Mono.Cecil.dll", - "Doorstop/Mono.CompilerServices.SymbolWriter.dll", - "Doorstop/pdb2mdb.exe", + private val resources = mapOf( + OS.Windows to listOf( + ".doorstop_version", + "doorstop_config.ini", + "winhttp.dll", + + "Doorstop/0Harmony.dll", + "Doorstop/dnlib.dll", + "Doorstop/Doorstop.dll", + "Doorstop/Doorstop.pdb", + "Doorstop/HotReload.dll", + "Doorstop/Mono.Cecil.dll", + "Doorstop/Mono.CompilerServices.SymbolWriter.dll", + "Doorstop/pdb2mdb.exe", + ), + OS.macOS to listOf( + ".doorstop_version", + ".doorstop_config.ini", + + "Doorstop/0Harmony.dll", + "Doorstop/Doorstop.dll", + "Doorstop/Doorstop.pdb", + "Doorstop/Mono.Cecil.dll", + "Doorstop/Mono.CompilerServices.SymbolWriter.dll", + "Doorstop/pdb2mdb.exe", + ) ) override fun execute( @@ -67,6 +81,8 @@ class RunState( } private fun setupDoorstop() { + val currentResources = resources[OS.CURRENT] ?: return + val rimworldDir = Path(rimworldLocation).parent.toFile() val copyResource = fun(basePath: String, name: String) { @@ -84,12 +100,13 @@ class RunState( fileWriteStream.close() } - resources.forEach { - copyResource("/UnityDoorstop/Win64/", it) + currentResources.forEach { + copyResource("/UnityDoorstop/${OS.CURRENT}/", it) } } private fun removeDoorstep() { + val currentResources = resources[OS.CURRENT] ?: return Thread.sleep(50) val rimworldDir = Path(rimworldLocation).parent.toFile() @@ -99,7 +116,7 @@ class RunState( file.delete() } - resources.forEach { + currentResources.forEach { removeResource(it) } diff --git a/src/rider/main/kotlin/spellchecker/DictionaryProvider.kt b/src/rider/main/kotlin/spellchecker/DictionaryProvider.kt new file mode 100644 index 0000000..22e43ec --- /dev/null +++ b/src/rider/main/kotlin/spellchecker/DictionaryProvider.kt @@ -0,0 +1,7 @@ +package RimworldDev.Rider.spellchecker + +import com.intellij.spellchecker.BundledDictionaryProvider + +class DictionaryProvider: BundledDictionaryProvider { + override fun getBundledDictionaries(): Array = arrayOf("/spellchecker/rimworld.dic") +} \ No newline at end of file diff --git a/src/rider/main/resources/META-INF/plugin.xml b/src/rider/main/resources/META-INF/plugin.xml index b5933ec..1a50fcd 100644 --- a/src/rider/main/resources/META-INF/plugin.xml +++ b/src/rider/main/resources/META-INF/plugin.xml @@ -1,7 +1,7 @@ com.jetbrains.rider.plugins.rimworlddev Rimworld Development Environment - 2023.3 + 2023.3red.1 Garethp com.intellij.modules.rider @@ -18,8 +18,10 @@ in your mods!

    -
  • Rimworld XML will now exist as it's own project
  • -
  • Added some new problem analyzers to catch simple typing errors in Rimworld XML
  • +
  • Fixed a rare crash when the plugin was completely unable to locate Rimworld
  • +
  • Fixed automatic Rimworld detection when Rimworld is installed through Steam on the C: drive
  • +
  • Fixed some false positives on error checking in XML
  • +
  • Added more mod folders to the XML Project that gets added automatically

]]>
@@ -34,6 +36,8 @@ in your mods!

+ +
diff --git a/src/rider/main/resources/UnityDoorstop/Win64/.doorstop_version b/src/rider/main/resources/UnityDoorstop/Windows/.doorstop_version similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/.doorstop_version rename to src/rider/main/resources/UnityDoorstop/Windows/.doorstop_version diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/0Harmony.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/0Harmony.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/0Harmony.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/0Harmony.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Doorstop.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Doorstop.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Doorstop.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Doorstop.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Doorstop.pdb b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Doorstop.pdb similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Doorstop.pdb rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Doorstop.pdb diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/HotReload.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/HotReload.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/HotReload.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/HotReload.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Mono.Cecil.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Mono.Cecil.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Mono.Cecil.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Mono.Cecil.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Mono.CompilerServices.SymbolWriter.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Mono.CompilerServices.SymbolWriter.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/Mono.CompilerServices.SymbolWriter.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/Mono.CompilerServices.SymbolWriter.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/dnlib.dll b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/dnlib.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/dnlib.dll rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/dnlib.dll diff --git a/src/rider/main/resources/UnityDoorstop/Win64/Doorstop/pdb2mdb.exe b/src/rider/main/resources/UnityDoorstop/Windows/Doorstop/pdb2mdb.exe similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/Doorstop/pdb2mdb.exe rename to src/rider/main/resources/UnityDoorstop/Windows/Doorstop/pdb2mdb.exe diff --git a/src/rider/main/resources/UnityDoorstop/Win64/doorstop_config.ini b/src/rider/main/resources/UnityDoorstop/Windows/doorstop_config.ini similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/doorstop_config.ini rename to src/rider/main/resources/UnityDoorstop/Windows/doorstop_config.ini diff --git a/src/rider/main/resources/UnityDoorstop/Win64/winhttp.dll b/src/rider/main/resources/UnityDoorstop/Windows/winhttp.dll similarity index 100% rename from src/rider/main/resources/UnityDoorstop/Win64/winhttp.dll rename to src/rider/main/resources/UnityDoorstop/Windows/winhttp.dll diff --git a/src/rider/main/resources/UnityDoorstop/macOS/.doorstop_version b/src/rider/main/resources/UnityDoorstop/macOS/.doorstop_version new file mode 100644 index 0000000..0c89fc9 --- /dev/null +++ b/src/rider/main/resources/UnityDoorstop/macOS/.doorstop_version @@ -0,0 +1 @@ +4.0.0 \ No newline at end of file diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/0Harmony.dll b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/0Harmony.dll new file mode 100644 index 0000000..e182535 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/0Harmony.dll differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.dll b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.dll new file mode 100644 index 0000000..a454647 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.dll differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.pdb b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.pdb new file mode 100644 index 0000000..2c85685 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Doorstop.pdb differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.Cecil.dll b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.Cecil.dll new file mode 100644 index 0000000..769f317 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.Cecil.dll differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.CompilerServices.SymbolWriter.dll b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.CompilerServices.SymbolWriter.dll new file mode 100644 index 0000000..3e97558 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/Mono.CompilerServices.SymbolWriter.dll differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/pdb2mdb.exe b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/pdb2mdb.exe new file mode 100644 index 0000000..05c4bb7 Binary files /dev/null and b/src/rider/main/resources/UnityDoorstop/macOS/Doorstop/pdb2mdb.exe differ diff --git a/src/rider/main/resources/UnityDoorstop/macOS/doorstop_config.ini b/src/rider/main/resources/UnityDoorstop/macOS/doorstop_config.ini new file mode 100644 index 0000000..462bb6d --- /dev/null +++ b/src/rider/main/resources/UnityDoorstop/macOS/doorstop_config.ini @@ -0,0 +1,45 @@ +# General options for Unity Doorstop +[General] + +# Enable Doorstop? +enabled=true + +# Path to the assembly to load and execute +# NOTE: The entrypoint must be of format `static void Doorstop.Entrypoint.Start()` +target_assembly=Doorstop\Doorstop.dll + +# If true, Unity's output log is redirected to \output_log.txt +redirect_output_log=false + +# If enabled, DOORSTOP_DISABLE env var value is ignored +# USE THIS ONLY WHEN ASKED TO OR YOU KNOW WHAT THIS MEANS +ignore_disable_switch=false + + +# Options specific to running under Unity Mono runtime +[UnityMono] + +# Overrides default Mono DLL search path +# Sometimes it is needed to instruct Mono to seek its assemblies from a different path +# (e.g. mscorlib is stripped in original game) +# This option causes Mono to seek mscorlib and core libraries from a different folder before Managed +# Original Managed folder is added as a secondary folder in the search path +dll_search_path_override= + +# If true, Mono debugger server will be enabled +debug_enabled=true + +# When debug_enabled is true, specifies the address to use for the debugger server +debug_address=127.0.0.1:56000 + +# If true and debug_enabled is true, Mono debugger server will suspend the game execution until a debugger is attached +debug_suspend=false + +# Options sepcific to running under Il2Cpp runtime +[Il2Cpp] + +# Path to coreclr.dll that contains the CoreCLR runtime +coreclr_path= + +# Path to the directory containing the managed core libraries for CoreCLR (mscorlib, System, etc.) +corlib_dir= diff --git a/src/rider/main/resources/spellchecker/rimworld.dic b/src/rider/main/resources/spellchecker/rimworld.dic new file mode 100644 index 0000000..69cf531 --- /dev/null +++ b/src/rider/main/resources/spellchecker/rimworld.dic @@ -0,0 +1,381 @@ +namer +ultratech +techprint +techprints +outlander +trainability +trainables +plasteel +neutroamine +ludeon +archite +chemfuel +hediff +luciferium +genepacks +genepack +deathrest +psylink +neuroformer +polux +arrester +transhumanist +modder +modders +humanlike +humanlikes +rester +smithing +stonecut +stonecutter +stonecutting +undergrounder +bloodlust +lovin +furskin +emanator +joywire +manhunter +manhunting +comms +undrafted +prosthophile +joinable +fava +smokepop +mechanoid +despawned +standable +mechs +mech +ripscanned +ripscanner +perenially +tornados +patienting +prosthophobe +ripscanning +undilluted +bladelink +sanguophage +sanguophages +autofeed +satify +hemogen +undowned +factionless +techprof +subpersona +archotech +painstopper +antigrain +resurrector +flatscreen +megascreen +neurotrainer +hyperweave +warg +razorfangs +dessicated +unbottle +rebalance +mechanoids +xenogenetics +debuff +scaria +abasia +snowhare +superfast +mineable +unforbid +undraft +playstyle +warcall +jailbreaker +wargs +fuelable +xenogerm +kinesthetic +xenogenes +misandrist +insectoid +megascarab +insectoids +eusocial +megaspider +megaspiders +spelopede +boomrat +megasloth +minigun +scyther +pikeman +pikemen +weaponization +shrubland +panthera +housecat +healroot +tribespeople +rimworlds +rimworld +shearable +gestators +thrumbo +thrumbos +alphabeaver +alocasia +rafflesia +cecropia +chokevine +gauranlen +dendrovore +astragalus +daylily +wildboar +dextrously +tinctoria +makeable +glowstool +muffalo +agarilux +bryolux +needlegun +biocodable +pettable +forbiddable +equippable +styleable +makeable +gunsmithing +gladius +unfogged +skyfaller +shortbow +pila +pilum +greatbow +targeter +ikwa +polearm +bugblood +firefoam +impactors +psycast +firefoampop +haygrass +devilstrand +smokeleaf +psychite +psychoid +rottable +pulser +targetable +daylilies +smokeable +buyable +oversized +unfert +fert +ruinable +ingredientless +plainleather +wolfskin +camelhide +bluefur +lightleather +lizardskin +thrumbofur +patchleather +breakdownable +flickable +vanometric +chemreactor +milkable +boomalope +autopistol +ideo +diggable +selfheal +hitpoints +techist +darklight +poisonable +glitterworld +blowback +multibarrel +nanite +assisters +birdskin +foxfur +mechanite +mechanites +refuelable +darktorch +machineable +bestower +smithable +tribalwear +neuro +assistors +synthread +moveable +autodoor +autodoors +deconstructible +damager +cryptosleep +neurotrainers +psytrainers +psytrainer +skilltrainers +underwall +starflight +hibernatable +strawmatting +droner +mannable +autocannon +activable +rocketswarm +hoopstone +unstandable +adjphrase +angsty +boreal +mechtech +repressurizing +manhunters +flashstorm +alphabeavers +archonexus +mechanitor +wastepack +chillax +psyfocus +countertop +agrihand +artable +biocoded +deathresting +diabolus +useable +bossgroup +launchable +stele +steles +businessname +businesstype +capturer +expirable +exoticname +anypawn +indef +scen +planetkiller +logentry +battlename +taleless +pregen +datacrystal +savegame +savegames +flavorsuffix +spiketrap +accepter +flameball +crashlanded +neurosimulator +neurosimulators +galician +byzantinian +bodypart +bodyparts +talktopicheavyfile +talktopiclightfile +failtype +flavortext +nearnameinitial +townname +wordgen +topicalnoun +townend +groupname +townendevil +msyl +smeltable +offworld +deadmans +xenotype +acidifier +planetfall +starscape +terraformer +neuroquake +skygaze +boomrats +boomalopes +hypothermic +bowlcut +lackland +tribesperson +effecter +sustainer +geneline +joywire +joywires +penoxycyline +escortee +yayo +quadrum +quadrums +uncooled +biogel +constructoid +drillable +miniguns +breacher +gladii +longswords +greatbows +autopistols +scav +berserker +firestarter +artstyle +playstyles +psycasts +vatgrown +reprocessor +outlanders +blindsight +tribals +ducktail +urbworld +urbworlds +homeworld +caveworld +midworld +xenohumans +speechcraft +headjack +starfaring +iceworld +empath +vidtube +originaltarget +shotat +woundname +storyname +talkedabout +madefunof +immunizable +archist +craftable +elytra +pronotum +astropolitan +corunan +rustican +kriminul +plastron