diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..be6d0f1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,340 @@
+## Development enviroment files ignored for BlueprintReport
+7za_dir.txt
+dist_dir.txt
+rim_dir.txt
+Assembly-CSharp.dll
+Assembly-CSharp-firstpass.dll
+HugsLib.dll
+UnityEngine.dll
+UnityEngine.UI.dll
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
diff --git a/HydroponicsGrowthSync.sln b/HydroponicsGrowthSync.sln
new file mode 100644
index 0000000..9d5ea0c
--- /dev/null
+++ b/HydroponicsGrowthSync.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2026
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HydroponicsGrowthSync", "HydroponicsGrowthSync\HydroponicsGrowthSync.csproj", "{48701804-B385-40B8-8637-4DBACAA8373F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {48701804-B385-40B8-8637-4DBACAA8373F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {48701804-B385-40B8-8637-4DBACAA8373F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {48701804-B385-40B8-8637-4DBACAA8373F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {48701804-B385-40B8-8637-4DBACAA8373F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DDF5B7E3-BDDB-4F5B-B99F-32AFBB3C4F30}
+ EndGlobalSection
+EndGlobal
diff --git a/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/about.xml b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/about.xml
new file mode 100644
index 0000000..c20d90b
--- /dev/null
+++ b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/about.xml
@@ -0,0 +1,20 @@
+
+
+
+ Hydroponics Growth Sync
+ ChippedChap
+ 0.19.0
+ Version 1.0.0
+
+Syncs plant growth such that all plants growing in a group of connected hydroponics tables growing the same plant will reach maturity at roughly the same time.
+
+The plant syncing code used was heavily based on the plant syncing code of\n<b>Plant Growth Sync by Lanilor</b>
+
+<b>Additional Notes:</b>
+This mod only affects plants grown in plant-growing buildings. Check out Plant Growth Sync if you want plants in growing zones to be synced.
+
+Every in-game hour, the mod loops through all plant-growing buildings in the map and makes groups of connected plant-growing buildings that are growing the same plant. The mod then syncs all the plants grown by the plant-growing buildings in each group. This shouldn't slow down your game much because it only runs every in-game hour.
+
+If you think there are any issues with how the mod identifies groups of buildings, open the debug menu and check the DrawGroups option in the TweakValues menu. A number will be drawn on all plant-growing buildings present on the map, with buildings of the same group having the same number. Use this to confirm if there are any issues with group-building.
+
+
\ No newline at end of file
diff --git a/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/preview.png b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/preview.png
new file mode 100644
index 0000000..6752ffc
Binary files /dev/null and b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/About/preview.png differ
diff --git a/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/Assemblies/HydroponicsGrowthSync.dll b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/Assemblies/HydroponicsGrowthSync.dll
new file mode 100644
index 0000000..e154f7d
Binary files /dev/null and b/HydroponicsGrowthSync/Distribution/HydroponicsGrowthSync/Assemblies/HydroponicsGrowthSync.dll differ
diff --git a/HydroponicsGrowthSync/HydroponicsGrowthSync.csproj b/HydroponicsGrowthSync/HydroponicsGrowthSync.csproj
new file mode 100644
index 0000000..b444f9f
--- /dev/null
+++ b/HydroponicsGrowthSync/HydroponicsGrowthSync.csproj
@@ -0,0 +1,130 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {48701804-B385-40B8-8637-4DBACAA8373F}
+ Library
+ Properties
+ HydroponicsGrowthSync
+ HydroponicsGrowthSync
+ v3.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ LocalDev\Refs\Assembly-CSharp.dll
+ False
+
+
+ LocalDev\Refs\Assembly-CSharp-firstpass.dll
+ False
+
+
+
+
+
+
+
+
+ LocalDev\Refs\UnityEngine.dll
+ False
+
+
+ LocalDev\Refs\UnityEngine.UI.dll
+ False
+
+
+
+
+
+
+
+
+
+ @echo $(Targetname)
+SET ModName=HydroponicsGrowthSync
+SET UsingHarmony=false
+SET UsingHugsLib=false
+
+@echo ...
+@echo set lpath vars from LocalDev storage...
+set /p RIM_DIR=<"$(ProjectDir)LocalDev\rim_dir.txt"
+set /p ZA_DIR=<"$(ProjectDir)LocalDev\7za_dir.txt"
+set /p DIST_DIR=<"$(ProjectDir)LocalDev\dist_dir.txt"
+
+@echo Copying RimWorld assemblies from "%25RIM_DIR%25\RimWorldWin_Data\Managed" to "$(ProjectDir)LocalDev\Refs" folder...
+copy /Y "%25RIM_DIR%25\RimWorldWin64_Data\Managed\Assembly-CSharp.dll" "$(ProjectDir)LocalDev\Refs"
+copy /Y "%25RIM_DIR%25\RimWorldWin64_Data\Managed\Assembly-CSharp-firstpass.dll" "$(ProjectDir)LocalDev\Refs"
+copy /Y "%25RIM_DIR%25\RimWorldWin64_Data\Managed\UnityEngine.dll" "$(ProjectDir)LocalDev\Refs"
+copy /Y "%25RIM_DIR%25\RimWorldWin64_Data\Managed\UnityEngine.UI.dll" "$(ProjectDir)LocalDev\Refs"
+
+if %25UsingHarmony%25 EQU true (
+@echo Copying Harmony assembly from "%25RIM_DIR%25\Mods\HugsLib\Assemblies" to "$(ProjectDir)LocalDev\Refs" folder...
+copy /Y "%25RIM_DIR%25\Mods\HugsLib\Assemblies\0Harmony.dll" "$(ProjectDir)LocalDev\Refs"
+)
+if %25UsingHugsLib%25 EQU true (
+@echo Copying HugsLib assembly from "%25RIM_DIR%25\Mods\HugsLib\Assemblies" to "$(ProjectDir)LocalDev\Refs" folder...
+copy /Y "%25RIM_DIR%25\Mods\HugsLib\Assemblies\HugsLib.dll" "$(ProjectDir)LocalDev\Refs"
+)
+
+@echo RimWorld API references copying complete!
+
+
+ @echo $(Targetname)
+SET ModName=HydroponicsGrowthSync
+SET UsingHarmony=false
+SET UseChecker=false
+@echo ...
+@echo set lpath vars from LocalDev storage...
+set /p RIM_DIR=<"$(ProjectDir)LocalDev\rim_dir.txt"
+set /p ZA_DIR=<"$(ProjectDir)LocalDev\7za_dir.txt"
+set /p DIST_DIR=<"$(ProjectDir)LocalDev\dist_dir.txt"
+
+@echo Deleting old assemblies from Distribution...
+del /q "$(ProjectDir)Distribution\%25ModName%25\Assemblies\*"
+@echo Copying assemblies to Distribution $(Targetname) files...
+if not exist "$(ProjectDir)Distribution\%25ModName%25\Assemblies" mkdir "$(ProjectDir)Distribution\%25ModName%25\Assemblies"
+copy /Y "$(TargetDir)"%25ModName%25*.dll "$(ProjectDir)Distribution\%25ModName%25\Assemblies"
+@echo Copying Harmony assembly to Distribution $(Targetname) files...
+if %25UsingHarmony%25 EQU true (
+copy /Y "$(ProjectDir)LocalDev\Refs\"0Harmony.dll "$(ProjectDir)Distribution\%25ModName%25\Assemblies"
+)
+if %25UseChecker%25 EQU true (
+copy /Y "$(ProjectDir)LocalDev\Refs\"$HugsLibChecker.dll "$(ProjectDir)Distribution\%25ModName%25\Assemblies"
+)
+
+@echo deleting previous build ...
+if exist "$(ProjectDir)LocalDev\%25ModName%25.zip" del "$(ProjectDir)LocalDev\%25ModName%25.zip"
+@echo packaging new build...
+call "%25ZA_DIR%25\7za.exe" a -tzip -r "$(ProjectDir)LocalDev\%25ModName%25.zip" "$(ProjectDir)Distribution\*.*"
+
+if exist "%25RIM_DIR%25\Mods\%25ModName%25" (
+@echo Deleting old mod files
+rmdir /s /q "%25RIM_DIR%25\Mods\%25ModName%25"
+)
+@echo Deploy $(ProjectDir) Distribution files to test env: %25RIM_DIR%25\Mods...
+xcopy /E /Y "$(ProjectDir)Distribution\*" "%25RIM_DIR%25\Mods"
+
+
+@echo Build/deploy complete!
+
+
\ No newline at end of file
diff --git a/HydroponicsGrowthSync/LocalDev/Art/ShowTotalsTooltip.xcf b/HydroponicsGrowthSync/LocalDev/Art/ShowTotalsTooltip.xcf
new file mode 100644
index 0000000..2345d82
Binary files /dev/null and b/HydroponicsGrowthSync/LocalDev/Art/ShowTotalsTooltip.xcf differ
diff --git a/HydroponicsGrowthSync/LocalDev/BlueprintTotalsTooltip.zip b/HydroponicsGrowthSync/LocalDev/BlueprintTotalsTooltip.zip
new file mode 100644
index 0000000..5132236
Binary files /dev/null and b/HydroponicsGrowthSync/LocalDev/BlueprintTotalsTooltip.zip differ
diff --git a/HydroponicsGrowthSync/LocalDev/HydroponicsGrowthSync.zip b/HydroponicsGrowthSync/LocalDev/HydroponicsGrowthSync.zip
new file mode 100644
index 0000000..4ff7602
Binary files /dev/null and b/HydroponicsGrowthSync/LocalDev/HydroponicsGrowthSync.zip differ
diff --git a/HydroponicsGrowthSync/LocalDev/Refs/$HugsLibChecker.dll b/HydroponicsGrowthSync/LocalDev/Refs/$HugsLibChecker.dll
new file mode 100644
index 0000000..603578a
Binary files /dev/null and b/HydroponicsGrowthSync/LocalDev/Refs/$HugsLibChecker.dll differ
diff --git a/HydroponicsGrowthSync/LocalDev/Refs/0Harmony.dll b/HydroponicsGrowthSync/LocalDev/Refs/0Harmony.dll
new file mode 100644
index 0000000..488b2ff
Binary files /dev/null and b/HydroponicsGrowthSync/LocalDev/Refs/0Harmony.dll differ
diff --git a/HydroponicsGrowthSync/PlantGrowerGrowthSyncer.cs b/HydroponicsGrowthSync/PlantGrowerGrowthSyncer.cs
new file mode 100644
index 0000000..414d465
--- /dev/null
+++ b/HydroponicsGrowthSync/PlantGrowerGrowthSyncer.cs
@@ -0,0 +1,153 @@
+using RimWorld;
+using System.Collections.Generic;
+using System.Linq;
+using Verse;
+using UnityEngine;
+
+namespace HydroponicsGrowthSync
+{
+ public class PlantGrowerGrowthSyncer : MapComponent
+ {
+ private List> plantGrowerGroups = new List>();
+
+ [TweakValue("PlantGrowerGrowthSyncer")]
+ public static bool DrawGroups = false;
+
+ [TweakValue("PlantGrowerGrowthSyncer", 0f, 2.2f)]
+ public static float SyncRatePerFullGrowth = 1.15f;
+
+ public PlantGrowerGrowthSyncer(Map map) : base(map)
+ {
+ }
+
+ public override void MapComponentTick()
+ {
+ if (Find.TickManager.TicksGame % 2000 == 0)
+ {
+ BuildPlantGrowerGroups();
+ SyncAllGroups();
+ }
+ }
+
+ public override void MapComponentOnGUI()
+ {
+ if (DrawGroups)
+ {
+ for (int i = 0; i < plantGrowerGroups.Count; i++)
+ {
+ for (int j = 0; j < plantGrowerGroups[i].Count; j++)
+ {
+ Vector2 labelPosition = UI.MapToUIPosition(plantGrowerGroups[i][j].DrawPos);
+ Rect labelRect = new Rect(labelPosition.x, labelPosition.y, 999f, 50f);
+ Text.Font = GameFont.Medium;
+ Widgets.Label(labelRect, i.ToString());
+ Text.Font = GameFont.Small;
+ }
+ }
+ }
+ }
+
+ private void BuildPlantGrowerGroups()
+ {
+ plantGrowerGroups.Clear();
+ IEnumerable allPlantGrowers = map.listerThings.ThingsInGroup(ThingRequestGroup.BuildingArtificial).Where(x => x is Building_PlantGrower);
+ HashSet alreadyGrouped = new HashSet();
+ foreach (Thing grower in allPlantGrowers)
+ {
+ if (alreadyGrouped.Contains(grower)) continue;
+ List growerGroup = new List();
+ HashSet queue = new HashSet() { grower };
+ while (queue.Count > 0)
+ {
+ alreadyGrouped.AddRange(queue);
+ growerGroup.AddRange(queue);
+ HashSet oldQueue = new HashSet(queue);
+ queue.Clear();
+ foreach (Building_PlantGrower adjRoot in oldQueue)
+ {
+ foreach (Building_PlantGrower adjAgainst in allPlantGrowers)
+ {
+ if (alreadyGrouped.Contains(adjAgainst)) continue;
+ if (adjRoot.CanBeGroupedTo(adjAgainst))
+ {
+ queue.Add(adjAgainst);
+ }
+ }
+ }
+ }
+ plantGrowerGroups.Add(growerGroup);
+ }
+ }
+
+ private void SyncAllGroups()
+ {
+ for (int i = 0; i < plantGrowerGroups.Count; i++)
+ {
+ ThingDef groupPlantDef = (plantGrowerGroups[i][0] as Building_PlantGrower).GetPlantDefToGrow();
+ /*
+ * NOTE
+ * The following code is heavily based on the plant syncing code in Plant Growth Sync by Lanilor.
+ * This is so that people using this alongside Plant Growth Sync will have their crops synced in a similar way.
+ *
+ * LINKS
+ * https://steamcommunity.com/sharedfiles/filedetails/?id=1454228967&searchtext=Plant+Growth+Sync
+ * https://github.com/Lanilor/Simple-Mods-Collection
+ * */
+
+ List plantsToSync = new List();
+ float averageGrowth = 0f;
+ for (int j = 0; j < plantGrowerGroups[i].Count; j++)
+ {
+ Building_PlantGrower plantGrower = plantGrowerGroups[i][j] as Building_PlantGrower;
+ foreach (Plant plant in plantGrower.PlantsOnMe)
+ {
+ if (plant.def == groupPlantDef && plant.IsCrop && plant.LifeStage == PlantLifeStage.Growing)
+ {
+ plantsToSync.Add(plant);
+ averageGrowth += plant.Growth;
+ }
+ }
+ }
+ if (plantsToSync.Count < 2) continue;
+ averageGrowth /= plantsToSync.Count;
+
+ float marginFromAverage = SyncRatePerFullGrowth / (groupPlantDef.plant.growDays * 30f);
+ int numUnderAverage = 0;
+ int numAboveAverage = 0;
+ for (int k = plantsToSync.Count - 1; 0 <= k; k--)
+ {
+ if (Mathf.Abs(averageGrowth - plantsToSync[k].Growth) <= marginFromAverage)
+ {
+ plantsToSync[k].Growth = averageGrowth;
+ plantsToSync.RemoveAt(k);
+ }
+ else
+ {
+ if (plantsToSync[k].Growth > averageGrowth) numAboveAverage++;
+ if (plantsToSync[k].Growth < averageGrowth) numUnderAverage++;
+ }
+ }
+
+ float underMultiplier = 1f;
+ float aboveMultiplier = 1f;
+ if (numUnderAverage > 0 && numAboveAverage > 0)
+ {
+ if (numUnderAverage > numAboveAverage)
+ {
+ underMultiplier = numAboveAverage / (float)numUnderAverage;
+ }
+ else
+ {
+ aboveMultiplier = numUnderAverage / (float)numAboveAverage;
+ }
+ }
+
+ for (int l = 0; l < plantsToSync.Count; l++)
+ {
+ if (plantsToSync[l].Growth < averageGrowth) plantsToSync[l].Growth += marginFromAverage * underMultiplier;
+ if (plantsToSync[l].Growth > averageGrowth) plantsToSync[l].Growth -= marginFromAverage * aboveMultiplier;
+ }
+ }
+ }
+ }
+}
diff --git a/HydroponicsGrowthSync/Properties/AssemblyInfo.cs b/HydroponicsGrowthSync/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..cb11d28
--- /dev/null
+++ b/HydroponicsGrowthSync/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HydroponicsGrowthSync")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HydroponicsGrowthSync")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("48701804-b385-40b8-8637-4dbacaa8373f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/HydroponicsGrowthSync/ThingAdjUtilities.cs b/HydroponicsGrowthSync/ThingAdjUtilities.cs
new file mode 100644
index 0000000..5646b46
--- /dev/null
+++ b/HydroponicsGrowthSync/ThingAdjUtilities.cs
@@ -0,0 +1,35 @@
+using RimWorld;
+using Verse;
+
+namespace HydroponicsGrowthSync
+{
+ static class ThingAdjUtilities
+ {
+ public static bool CanBeGroupedTo(this Building_PlantGrower lhs, Building_PlantGrower rhs)
+ {
+ return lhs.IsConnectedTo(rhs) && lhs.GetPlantDefToGrow() == rhs.GetPlantDefToGrow();
+ }
+
+ public static bool IsConnectedTo(this Thing lhs, Thing rhs)
+ {
+ CellRect[] lhsAdjacencyRects = lhs.AdjacencyRects();
+ foreach (IntVec3 occupiedTile in rhs.OccupiedRect())
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ if (lhsAdjacencyRects[i].Contains(occupiedTile)) return true;
+ }
+ }
+ return false;
+ }
+
+ public static CellRect[] AdjacencyRects(this Thing thing)
+ {
+ CellRect[] rects = new CellRect[2];
+ CellRect occupiedRect = thing.OccupiedRect();
+ rects[0] = new CellRect(occupiedRect.minX - 1, occupiedRect.minZ, occupiedRect.Width + 2, occupiedRect.Height);
+ rects[1] = new CellRect(occupiedRect.minX, occupiedRect.minZ - 1, occupiedRect.Width, occupiedRect.Height + 2);
+ return rects;
+ }
+ }
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..bde60ce
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..50ff034
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# Hydroponics Growth Sync
+A mod for RimWorld that synchronizes plants growing in hydroponics to make them grow to maturity at the same time.
+
+The plant syncing code used in this mod was heavily based on the plant syncing code used in **[Plant Growth Sync](https://steamcommunity.com/sharedfiles/filedetails/?id=1454228967&searchtext=plant+growth+sync) by Lanilor.**
+
+[Steam Workshop Page](https://steamcommunity.com/sharedfiles/filedetails/?id=1517357184)
+
+[Forum Thread](https://ludeon.com/forums/index.php?topic=43565.0)