Skip to content

Releases: Boarlock/FoodTracker

Summary: FoodTracker v1.3.0 Release Changes

Choose a tag to compare

@Boarlock Boarlock released this 01 Sep 11:26

This release represents a major architectural refactor of the nutrition tracking system. Here are the key changes:

Core Architecture Overhaul

Replaced the component system:

  • Removed CompPartialNutrition (stored single nutrition value)
  • Introduced CompFoodTracker (dual-mode nutrition tracking system)
  • Singleton state (PartialNutrition): Tracks individual meal nutrition when stack size = 1
  • Stack state (NutritionEntries list): Tracks individual nutrition values for multi-item stacks
  • Automatically initializes based on stack count during PostSpawnSetup()

Enhanced State Tracking

New IngestionState properties:

  • TraceID: Internal ID to track each ingestion event (for debugging/logging)
  • TotalNutrition: Total nutrition of entire stack being consumed
  • NutritionEntriesBefore: Captures nutritional state before eating
  • IngredientsBefore: Captures ingredients before eating
  • FoodToDestroy & DestroyFoodAfterIngestion: Deferred destruction handling
  • FoodDef, BaseDef: Better food definition tracking

Improved Nutrition Calculation

  • Replaced simple linear nutrition calculations with granular meal-by-meal tracking
  • Eating duration now based on TotalNutrition / 0.9f (scaled with new NutritionConsumptionRateMultiplier)
  • Adjusted MealCompletionThreshold from 0.995f to 0.99f (less strict)
  • Added MealQualifierThreshold (0.225f) to classify batch vs. partial foods

Unified Nutrition Application

  • ApplyNutritionToPawn() now takes IngestionState instead of just Pawn
  • Better encapsulation of nutrition correction logic
  • Removed deprecated GetRemainingNutrition() and SetRemainingNutrition() methods

New Features

1.Stack merging & splitting (MergeAndSplitPatches.cs):

  • Handles Thing.SplitOff() to properly distribute nutrition entries
  • Handles Thing.TryAbsorbStack() to merge nutrition lists
  • Converts between singleton/stack states automatically

2.Nutrition tooltip display (GetExplanationPatch.cs):

  • Inspect screen now shows multiple partial nutrition values for stacked meals
  • Lists individual meal nutrition values for single meals

3.Enhanced destruction handling (DeferredFoodDestruction.cs):

  • Defers food destruction until after ingestion completes
  • Prevents conflicts with vanilla's Thing lifecycle

4.FoodTracker meal detection:

  • New method to handle destroyed FT meals separately (HandleDestroyedFoodTrackerMeal())
  • Better distinction between vanilla foods and FT-tracked foods

Code Quality Improvements

  • Comprehensive logging with TraceID for easier debugging
  • Better validation and error messages
  • Improved handling of edge cases (partial eating, stack disruptions)
  • Cleaner separation of batch food vs. partial-creating meal logic

Removed Components

  • InspectStatOverride.cs (replaced by GetExplanationPatch.cs)
  • CompPartialNutrition.cs (replaced by CompFoodTracker.cs)
  • Project file excludes for unused/replaced files

This release focuses on robustness and precision in nutrition tracking, especially for edge cases like interrupted meals, stack operations, and merging of partial meals.

Full Changelog: v1.2.3...v1.3.0

FoodTracker 1.2.0 - Stable Release

Choose a tag to compare

@Boarlock Boarlock released this 28 Aug 23:30

FoodTracker 1.2.0

First stable release of the redesigned food tracking system.

Highlights

  • You can now view leftover nutrition on the inspect screen
  • Dynamic generation of FoodTracker meal ThingDefs
  • Improved handling of destroyed food Things during ingestion
  • Corrected eating duration scaling based on remaining nutrition
  • Improved stack accounting for interrupted batch food consumption
  • Removed the previous static meal Def/Patch requirements in favor of runtime generation
  • Now compatible with all custom meal types!

Stability

Tested across normal meals, partial meals, interrupted meals, destroyed food Things, repeated partial-meal consumption, multiple meal types, and batch foods.

Full Changelog: v1.1.0...v1.2.0

FoodTracker

Choose a tag to compare

@Boarlock Boarlock released this 28 Aug 00:57

Big update for base mod, even though the original version you could play with it the constant errors from the base game about destroyed food had to be fixed. The issue is completely resolved now and this update has been tested thoroughly.

- Fixed the 0.002–0.005 nutrition / false-interruption issue

This was the biggest bug from v1.0, essentially due to timing inconsistencies with the game's tick system, the mod was going out-of-sync with the vanilla game. Specifically with our wrapped ChewIngestible toil and vanilla's FinalizeIngest(). The interruption handler could run even though vanilla was only a few ticks away from completing the ingestion. So I added a completion threshold, if consumption is over 99.5% then FoodTracker doesn't touch it, it doesn't invoke the interruption handler, it doesn't manipulate the food Thing, it lets vanilla own the Thing lifecycle. This specifically prevents FoodTracker from interfering with vanilla when the ingestion is effectively finished. This does mean interruption can happen past this point that FoodTracker misses, but 99.5% on a normal meal (0.9 nutrition) is about 0.002 nutrition, which in game ticks translate to 1-3 most likely. It'd be very difficult to consistently interrupt you pawns eating jobs 2 ticks from completion.

- Redesigned IngestionState

Since vanilla destroys the object in a pawns hands when a pawn is drafted and then un-drafted (especially while standing on a food stack), postfixing the ChewIngestible() method would not capture certain variables that FoodTracker needed. Specifically the Food Thing object, this also meant it couldn't derive the foodDef with food.def (because it's destroyed), couldn't query .stackCount, couldn't access our nutrition component, etc.. So now it captures anything it needs during the Prefix portion (when it normally calculates eating duration).
Food Thing reference, ThingDef, nutrition, etc.. Anything derived from the food Thing that may become unavailable later should be captured before vanilla can invalidate it.

- Moved ValidateFoodEatingAttempt() into the Prefix

I specifically changed validation to happen as early as possible. The Prefix now determines whether the eating attempt is something FoodTracker should care about before doing unnecessary work. This also could help performance.

- Made the helper methods defensive

Essentially all the Helper methods that receive a Thing food reference checks to see if it has been destroyed. All the logging and references have been safely nullified, so it shouldn't throw an exception even if something totally unexpected occurs.

- Reworked nutrition application

I discovered that directly doing pawn.needs.food.CurLevel += nutrition; wasn't the best way to apply the correction. The new nutrition application accounts for how much hunger the pawn actually has. So FoodTracker no longer blindly pushes nutrition into the pawn beyond its maximum and keeps the nutrition record synchronized with the actual amount applied.

- Cleaned up naming and code organization

I went through the code and renamed methods to make their responsibilities more explicit. The overall intent was to make it much easier to understand. What validates an eating attempt, what tracks an ingestion, what recovers destroyed food, etc.. I was trying to tighten the separation of responsibilities.

Things to work on still:

1. Removing redundant XML component dependency where possible

This is part of a broader redesign thinking around compatibility. I want to eliminate the second part because it created unnecessary compatibility concerns with modded meals, whether the other mod already has a node, load order, XPath targeting. The new direction was that full meals shouldn't need to carry thetracking component at all. FoodTracker can track the full meal through code and only the partial meals needs the actual partial nutrition component.

Secondary Bug Fixes:
These are small fixes that cropped up during development and I was able to iron out relatively easily.

Fixing the __state, local state assignment mistake that caused the NullReferenceException.
Correcting stack handling in the replacement path after discovering the captured Thing represented the whole stack.
Refining the destroyed-food recovery behavior.
Cleaning up logging so it uses stable food definitions rather than misleading historical Thing.Label values such as MealSurvivalPack x9.

Tested
Testing zero nutrition/zero items eaten edge cases.
Testing lone meals vs. stacked meals.
Testing destroyed Thing vs. surviving Thing paths.
Testing batch foods extensively.

Full Changelog: v1.0...v1.1.0

Food Tracker (Partial Meals)

Choose a tag to compare

@Boarlock Boarlock released this 26 Aug 09:20

Mod Description

Ever had a pawn get interrupted 95% of the way through a lavish meal, only to watch the entire meal yield zero nutrition? Partial Meals fixes this vanilla quirk by granting pawns proportional nutrition based on how long they actually spent chewing before getting interrupted.

Installation instructions

Download the zip file. Open it and place the FoodTracker folder inside your Rimworld/Mods folder. 

Main features

Proportional Nutrition for Meals: If a pawn is interrupted while eating a single-item meal (Simple, Fine, Lavish, etc.), the remaining food isn't wasted. A custom tracking component saves the remaining nutrition directly to that specific food item.
Smart Resumption: When a pawn picks up a partially eaten meal (or batch food item(s)), the chewing duration is automatically reduced to match the remaining portion/nutrition available.
Batch Food Scaling: For bulk foods like Pemmican, Berries, or Raw Corn, the mod scales the stack count. If a pawn grabs 10 pieces, chews for half the duration, and gets interrupted, they consume 5 pieces and drop the remaining 5 back into the world.
Zero Bloat: Lightweight C# patches with minimal impact on performance.
Current Limitations & Caveats (v1.0)
Partially Eaten Meals Cannot Stack: To prevent RimWorld from merging a partially eaten meal into a fresh stack (which would erase its tracked nutrition data), meals with remaining nutrition are un-stackable. 
Visual Tracking: Currently, partial meals retain their standard item labels, (Partial) has been appended to their Description in game when you go to extra information. (Planned for a future update: UI/tooltip integration showing exact remaining percentages, e.g., "Fine Meal - 42% Remaining").

Requirements

Harmony - Hard Requirement, this mod will not work without it!

Compatibility & Mod Authors

Batch Foods: Works out-of-the-box with custom batch/bulk foods added by other mods, as long as they use standard vanilla stack/ingestible structures.
Custom Single Meals: Modded meals will function normally, but they require a quick XML patch to enable partial eating tracking.
How to Patch Your Custom Meals: If you want your mod's meals to support partial eating, add their
ThingDef, defName, label, description, graphicData, statBases, comps, etc..
 to
Defs/PartialNutritionComp.xml
inside this mod's folder.

<--Example Structure Inside .xml file -->
<ThingDef ParentName="MealCooked">
    <defName>InGame_defName/defName>
    <label>In-Game Name</label>
    <stackLimit>1</stackLimit>

    <description>Whatever you want the in game description to be.</description>

    <graphicData>
      <texPath>Things/Item/Meal/Simple</texPath>
      <graphicClass>Graphic_MealVariants</graphicClass>
    </graphicData>

    <statBases>
      <MarketValue>15</MarketValue>
      <WorkToMake>300</WorkToMake>
      <Nutrition>0.9</Nutrition>
    </statBases>

    <comps>
 <li Class="FoodTracker.CompProperties_PartialNutrition" /><!---For your meals to be compatible with this mod this component must be present!--->
      <li Class="Any custom components you might have for your meals" />
    </comps>
  </ThingDef>

Have feedback or run into an issue? Drop a comment below!