static void Postfix(ref bool __result, Thing __state, IntVec3 loc, Map map, ref Thing resultingThing, Action <Thing, int> placedAction) { Thing thing = __state; // First check if we're dropping off in Deep Storage: SlotGroup slotGroup = loc.GetSlotGroup(map); if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) || ((ThingWithComps)slotGroup.parent).TryGetComp <CompDeepStorage>() == null) { Utils.Warn(TryPlaceDirect, " (placed " + __state + " NOT in Deep Storage: with result " + __result + ")"); return; } if (resultingThing != null) { // Two cases here if resultingThing exists: // 1. There's a new object on the map // (so resultingThing is the original thing, we don't have anyting to put down) // 2. Everything we put down was able to stack with something on the map // (so nothing else to put down!) // (case three - something weird going on possibly involving carrying?) // (all bets are off anyway >_< ) // Probably, the pawn put down what they were carrying, and all is good. Utils.Warn(TryPlaceDirect, " successfully placed " + resultingThing.stackCount + resultingThing.ToString() + " (" + __result + ")"); Utils.TidyStacksOf(resultingThing); return; } // Ok, so we still have something we want to place, and it goes in Deep Storage // (We will still return __result=false if we can't place everything in the desired space.) Utils.Err(TryPlaceDirect, "LWM:TryPlaceDirect tried to place " + thing.ToString() + " in " + slotGroup.ToString()); // Let's see if there's still room in the Deep Storage area the pawn is using: List <Thing> list = map.thingGrid.ThingsListAt(loc); int maxNumberStacks = ((ThingWithComps)slotGroup.parent).GetComp <CompDeepStorage>().maxNumberStacks; // We know there was at least one thing here, and it either doesn't stack with our thing // or its stack is full. // So, we go thru the items that are there int thingsHere = 0; for (int i = 0; i < list.Count; i++) { Thing thing2 = list[i]; if (!thing2.def.EverStorable(false)) { //not an object we count continue; } thingsHere++; Utils.Warn(TryPlaceDirect, " Currently there are " + thingsHere + " things here, max: " + maxNumberStacks); if (thingsHere == 1) { // (should be safe because 1st haulable stack would already have been // tested by default vanilla function) continue; } //unfortunately, we have to duplicate some of the original code: if (!thing2.CanStackWith(thing)) { Utils.Warn(TryPlaceDirect, "...ignoring \"other\" stack " + thing2.ToString()); continue; // am carrying wood, but this is sheep. Or rock, whatever. } // Okay, can stack. if (thing2.stackCount >= thing2.def.stackLimit) { Utils.Warn(TryPlaceDirect, "...ignoring full stack " + thing2.ToString()); continue; // stack is full. } // Put some down in the non-full stack! var origStackCount = thing.stackCount; if (thing2.TryAbsorbStack(thing, true)) { // the "thing2" stack could hold everything we wanted to put down! Utils.Warn(TryPlaceDirect, "... Object " + thing2.ToString() + " absorbed ALL of " + thing.ToString()); resultingThing = thing2; // Okay, I like this notation: only call if non-null: placedAction?.Invoke(thing2, origStackCount); Utils.TidyStacksOf(thing2); __result = true; // Could put down everything! return; } Utils.Warn(TryPlaceDirect, "... Object " + thing2.ToString() + " absorbed SOME of " + thing.ToString()); // Since we tried to put some down in that stack, do we do placedAction? if (placedAction != null && origStackCount != thing.stackCount) { placedAction(thing2, origStackCount - thing.stackCount); } // ...but there's still more to place, so keep going: } // end loop of objects in this location if (thingsHere >= maxNumberStacks) // Ran out of room in the storage object but still want to put stuff down ;_; { Utils.Warn(TryPlaceDirect, "...But ran out of stack space here: all " + maxNumberStacks + " filled"); __result = false; return; // no need to TidyStacks here - they have to be all full } // if we reach here, we found an empty space, // so put something down! Utils.Warn(TryPlaceDirect, "...Found empty stack space at " + loc.ToString() + ". Trying to create from " + thing.ToString()); // In some circumstances (e.g., butchering a large animal), a pawn can be putting // down way more than stackLimit of something. We deal with that scenario here //////////////////////// NOTE: POSSIBLE PROBLEM: //////////////////// // resultingThing is set to only the last thing here - it's possible we miss something // important by placing as much as we can at once: while (thing.stackCount > thing.def.stackLimit) // put down part of a carried load? { Thing thing2 = thing.SplitOff(thing.def.stackLimit); resultingThing = GenSpawn.Spawn(thing2, loc, map); Utils.Warn(TryPlaceDirect, "...put down one full stack (" + resultingThing.ToString() + "); " + thing.stackCount + " left"); placedAction?.Invoke(thing2, thing2.stackCount); thingsHere++; if (thingsHere >= maxNumberStacks) // Oh dear. There was still at least SOME left... { Utils.Warn(TryPlaceDirect, "...But ran out of stack space here: all " + maxNumberStacks + " filled but still have " + thing.stackCount + " left"); __result = false; // couldn't put things down return; // no need to TidyStacks - they all have to be full } } // Either Spawn the thing (or Spawn the final part of the thing): resultingThing = GenSpawn.Spawn(thing, loc, map); __result = true; // nothing unplaced! Utils.Warn(TryPlaceDirect, "...created " + resultingThing.ToString()); placedAction?.Invoke(thing, thing.stackCount); // Okay, I like this notation Utils.TidyStacksOf(resultingThing); return; // with __result=!flag (probably "true"); } // end TryPlaceDirect's Postfix
public DataCollection<CommonSearchClass> GetTargetVonBis (SlotGroup TargetSlot, DateTime? From = null, DateTime? To = null, int MaxNumber = 10) { Data.DbServer3.WPMediaAddOnData.LoadAll_IfHasNotBeenLoaded(); Data.DbServer3.MultiMedia.LoadAll_IfHasNotBeenLoaded(); String SpecificWhereAddOn = String.Empty; List<String> TableNames = new List<string>(); List<Guid> MMUnitTypenIds = new List<Guid>(); if (TargetSlot == SlotGroup.NoInformation) { SpecificWhereAddOn = $" TypID = '{DataDependencyEnums.FDDIDsForNichtDefiniert.TypNichtDefiniert}' "; } else { foreach (TableDefinition tableDefinition in Data.DbServer3.WPMediaAddOnData.TableDefinitions .Where(sel => sel.SlotGroup == TargetSlot.ToString())) { TableNames.Add(tableDefinition.TableName); MMUnitTypenIds.Add(tableDefinition.Id); } SpecificWhereAddOn = " ID in " + "(select InformationenID from InformationenAddOn where Tabelle = 'ProcessConnector' and ID in " + "(select InformationenAddOnID from ProcessConnector " + "where (not TableID is NULL and not TableID = '00000000-0000-0000-0000-000000000000') " + "and (TableName = '" + String.Join("' or TableName = '", TableNames) + "')))"; } DataCollection<CommonSearchClass> Result = DataModell.CommonSearchClassCacheInstance.GetVonBisAllAdvanced (DateTime.Now.AddDays(-2).Date, DateTime.Now.AddMonths(3).Date, null, null, SpecificWhereAddOn); List<Guid> InformationenGuids = new List<Guid>(); foreach (CommonSearchClass commonSearchClass in Result) { InformationenGuids.Add(commonSearchClass.InformationenConnectedEntry.ID); } if (InformationenGuids.Count > 0) { DbEntities.dbserver3.alterlaainfo.rows.Timing[] AssoziatedTimings = Data.DbServer3.AltErlaaInfo.Timings .Load_via_ConnectedIds(InformationenGuids); foreach (CommonSearchClass commonSearchClass in Result) { foreach (DbEntities.dbserver3.alterlaainfo.rows.Timing timing in AssoziatedTimings .Where(sel => sel.ConnectedId == commonSearchClass.InformationenConnectedEntry.ID)) { commonSearchClass.InformationenTimings.Add(timing); } } } DataCollection<CommonSearchClass> ResultWithoutInformation = new DataCollection<CommonSearchClass>(); List<Guid> MMUnitGuids = new List<Guid>(); foreach (MMUnit mMUnit in Data.DbServer3.MultiMedia.MMUnits .GetMMUnitsWithoutInformation(DateTime.Now.AddDays(-2).Date, DateTime.Now.AddMonths(3).Date, new List<string>( ) { "EventVonBis", "AktivVonBis", "AnzVonBis", "VonBis" }, TableNames)) { ResultWithoutInformation.Add(new CommonSearchClass(mMUnit)); MMUnitGuids.Add(mMUnit.Id); } foreach (CommonSearchClass commonSearchClass in ResultWithoutInformation) { foreach (MMUnitTiming mmUnitTiming in Data.DbServer3.MultiMedia.MMUnitTimings .Where(sel => sel.MMUnitId == commonSearchClass.MMUnitConnectedEntry.Id)) { commonSearchClass.MmUnitTimings.Add(mmUnitTiming); } } Result.AddRange(ResultWithoutInformation); return new DataCollection<CommonSearchClass>(Result.OrderBy(ord => ord.TimeA).ToList()); }