Skip to content

Commit 00e3463

Browse files
authored
Merge pull request #31 from ihsoft/smartpower-1.7
Release SmartPower v1.7
2 parents 98d0a2e + 21ef925 commit 00e3463

23 files changed

+408
-571
lines changed

AllMods.sln.DotSettings

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=blockable/@EntryIndexedValue">True</s:Boolean>
3+
<s:Boolean x:Key="/Default/UserDictionary/Words/=constructible/@EntryIndexedValue">True</s:Boolean>
4+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bindito/@EntryIndexedValue">True</s:Boolean>
5+
<s:Boolean x:Key="/Default/UserDictionary/Words/=enterable/@EntryIndexedValue">True</s:Boolean>
6+
<s:Boolean x:Key="/Default/UserDictionary/Words/=growables/@EntryIndexedValue">True</s:Boolean>
7+
<s:Boolean x:Key="/Default/UserDictionary/Words/=manufactory/@EntryIndexedValue">True</s:Boolean>
8+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Timberborn/@EntryIndexedValue">True</s:Boolean>
9+
</wpf:ResourceDictionary>

SmartPower/Core/Configurator.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
using Timberborn.PowerGenerating;
1313
using IgorZ.TimberDev.Utils;
1414
using Timberborn.Workshops;
15+
using UnityDev.Utils.LogUtilsLite;
1516

1617
// ReSharper disable InconsistentNaming
1718
// ReSharper disable UnusedMember.Local
1819
// ReSharper disable once CheckNamespace
1920
namespace IgorZ.SmartPower {
2021

21-
[Configurator(SceneEntrypoint.InGame)]
22+
[Configurator(SceneEntrypoint.All)]
2223
// ReSharper disable once UnusedType.Global
2324
sealed class Configurator : IConfigurator {
2425
static readonly PrefabPatcher.RequiredComponentsDep SmartAttractionDeps =
@@ -28,6 +29,9 @@ sealed class Configurator : IConfigurator {
2829
static readonly string PatchId = typeof(Configurator).FullName;
2930

3031
public void Configure(IContainerDefinition containerDefinition) {
32+
if (Features.DebugExVerboseLogging && DebugEx.LoggingSettings.VerbosityLevel < 5) {
33+
DebugEx.LoggingSettings.VerbosityLevel = 5;
34+
}
3135
CustomizableInstantiator.AddPatcher(
3236
PatchId,
3337
prefab => {

SmartPower/Core/Features.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Timberborn Mod: SmartPower
2+
// Author: igor.zavoychinskiy@gmail.com
3+
// License: Public Domain
4+
5+
using IgorZ.TimberDev.Utils;
6+
using UnityDev.Utils.LogUtilsLite;
7+
8+
// ReSharper disable once CheckNamespace
9+
namespace IgorZ.SmartPower {
10+
11+
static class Features {
12+
/// <summary>Indicates that <see cref="DebugEx.Fine"/> methods should emit record to the log.</summary>
13+
public static bool DebugExVerboseLogging;
14+
15+
/// <summary>
16+
/// Indicates that the power network fragment should show the battery vitals (capacity/charge and flow).
17+
/// </summary>
18+
public static bool NetworkShowBatteryStats;
19+
20+
static Features() {
21+
FeatureController.ReadFeatures(Consume);
22+
}
23+
24+
static bool Consume(string name, bool enabled, string value) {
25+
return name switch {
26+
"DebugEx.VerboseLogging" => FeatureController.SetFlag(ref DebugExVerboseLogging, name, enabled, value),
27+
"Network.ShowBatteryVitals" => FeatureController.SetFlag(ref NetworkShowBatteryStats, name, enabled, value),
28+
_ => false
29+
};
30+
}
31+
}
32+
33+
}

SmartPower/Core/SmartMechanicalBuilding.cs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Timberborn.StatusSystem;
1010
using Timberborn.Workshops;
1111
using UnityDev.Utils.LogUtilsLite;
12-
using UnityDev.Utils.Reflections;
1312

1413
// ReSharper disable once CheckNamespace
1514
namespace IgorZ.SmartPower {
@@ -23,20 +22,17 @@ namespace IgorZ.SmartPower {
2322
/// consumes only a fraction of the nominal power.
2423
/// </remarks>
2524
public class SmartMechanicalBuilding : MechanicalBuilding {
26-
static readonly ReflectedAction<MechanicalBuilding> UpdateActiveAndPoweredMethod = new(
27-
"UpdateActiveAndPowered", throwOnFailure: true);
2825

29-
const string StandbyStatusIcon = "igorz.smartpower/ui_icons/status-icon-standby";
30-
const float NonFuelRecipeIdleStateConsumption = 0.1f;
31-
const string PowerSavingModeLocKey = "IgorZ.SmartPower.MechanicalBuilding.PowerSavingModeStatus";
26+
#region API
3227

33-
MechanicalNode _mechanicalNode;
34-
Manufactory _manufactory;
35-
Enterable _enterable;
36-
ILoc _loc;
37-
StatusToggle _standbyStatus;
28+
/// <summary>Indicates that this building logic must is handled by the smart behavior.</summary>
29+
// ReSharper disable once MemberCanBePrivate.Global
30+
public bool NeedsSmartLogic => _mechanicalNode.IsConsumer && !_mechanicalNode.IsGenerator;
31+
32+
// ReSharper disable once MemberCanBePrivate.Global
33+
/// <summary>Indicates that teh building has a working place that should have workers.</summary>
34+
public bool HasWorkingPlaces { get; private set; }
3835

39-
#region API
4036
/// <summary>
4137
/// Indicates that the building is expected to be staffed and working, but no workers are currently at the working
4238
/// place(s).
@@ -71,53 +67,74 @@ private set {
7167
}
7268
}
7369
bool _idleState;
70+
7471
#endregion
7572

76-
#region MechanicalBuilding overrides
73+
#region TickableComponent overrides
74+
7775
/// <inheritdoc/>
7876
public override void StartTickable() {
7977
base.StartTickable();
80-
_mechanicalNode = GetComponentFast<MechanicalNode>();
81-
_manufactory = GetComponentFast<Manufactory>();
82-
_enterable = GetComponentFast<Enterable>();
83-
_standbyStatus = StatusToggle.CreateNormalStatus(StandbyStatusIcon, _loc.T(PowerSavingModeLocKey));
84-
var subject = GetComponentFast<StatusSubject>();
85-
subject.RegisterStatus(_standbyStatus);
86-
UpdateNodeCharacteristics();
78+
if (NeedsSmartLogic) {
79+
SmartUpdateNodeCharacteristics();
80+
}
8781
}
8882

8983
/// <inheritdoc/>
9084
public override void Tick() {
91-
if (!_mechanicalNode.IsConsumer || _mechanicalNode.IsGenerator) {
85+
if (!NeedsSmartLogic) {
9286
base.Tick();
9387
return;
9488
}
95-
UpdateNodeCharacteristics();
96-
UpdateActiveAndPoweredMethod.Invoke(this);
89+
SmartUpdateNodeCharacteristics();
90+
UpdateActiveAndPowered();
9791
}
92+
9893
#endregion
9994

10095
#region Implementation
101-
#pragma warning disable CS1591
96+
97+
const string StandbyStatusIcon = "igorz.smartpower/ui_icons/status-icon-standby";
98+
const float NonFuelRecipeIdleStateConsumption = 0.1f;
99+
const string PowerSavingModeLocKey = "IgorZ.SmartPower.MechanicalBuilding.PowerSavingModeStatus";
100+
101+
Manufactory _manufactory;
102+
Enterable _enterable;
103+
ILoc _loc;
104+
StatusToggle _standbyStatus;
105+
106+
/// <inheritdoc cref="MechanicalBuilding.Awake" />
107+
public new void Awake() {
108+
base.Awake();
109+
_manufactory = GetComponentFast<Manufactory>();
110+
_enterable = GetComponentFast<Enterable>();
111+
_standbyStatus = StatusToggle.CreateNormalStatus(StandbyStatusIcon, _loc.T(PowerSavingModeLocKey));
112+
var subject = GetComponentFast<StatusSubject>();
113+
subject.RegisterStatus(_standbyStatus);
114+
HasWorkingPlaces = GetComponentFast<Workshop>() != null;
115+
}
116+
117+
/// <summary>It must be public for the injection logic to work.</summary>
102118
[Inject]
103119
public void InjectDependencies(ILoc loc) {
104120
_loc = loc;
105121
}
106122

107-
void UpdateNodeCharacteristics() {
123+
void SmartUpdateNodeCharacteristics() {
108124
if (ConsumptionDisabled) {
109125
_mechanicalNode.UpdateInput(0);
110126
AllWorkersOut = MissingIngredients = BlockedOutput = NoFuel = StandbyMode = false;
111127
return;
112128
}
113129
var hasRecipe = _manufactory.HasCurrentRecipe;
114-
AllWorkersOut = hasRecipe && _enterable != null && _enterable.NumberOfEnterersInside == 0;
130+
AllWorkersOut = HasWorkingPlaces && hasRecipe && _enterable != null && _enterable.NumberOfEnterersInside == 0;
115131
MissingIngredients = hasRecipe && !_manufactory.HasAllIngredients;
116132
BlockedOutput = hasRecipe && !_manufactory.Inventory.HasUnreservedCapacity(_manufactory.CurrentRecipe.Products);
117133
NoFuel = hasRecipe && !_manufactory.HasFuel;
118134
StandbyMode = AllWorkersOut || MissingIngredients || NoFuel || BlockedOutput;
119135
_mechanicalNode.UpdateInput(StandbyMode ? NonFuelRecipeIdleStateConsumption : 1.0f);
120136
}
137+
121138
#endregion
122139
}
123140

SmartPower/Core/SmartPoweredAttraction.cs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,61 @@
22
// Author: igor.zavoychinskiy@gmail.com
33
// License: Public Domain
44

5-
using Timberborn.BaseComponentSystem;
65
using Timberborn.EnterableSystem;
76
using Timberborn.MechanicalSystem;
7+
using Timberborn.Persistence;
8+
using Timberborn.TickSystem;
89
using UnityDev.Utils.LogUtilsLite;
910

1011
// ReSharper disable once CheckNamespace
1112
namespace IgorZ.SmartPower {
1213

1314
/// <summary>Smart version of the stock game powered attraction.</summary>
1415
/// <remarks>It only consumes power if there are attendees in the building.</remarks>
15-
public sealed class SmartPoweredAttraction : BaseComponent {
16-
Enterable _enterable;
16+
public sealed class SmartPoweredAttraction : TickableComponent, IPostInitializableLoadedEntity {
17+
18+
/// <summary>Indicates if the power consumption has been disabled due to no attendees.</summary>
19+
// ReSharper disable once MemberCanBePrivate.Global
20+
public bool ConsumptionDisabled { get; private set; }
21+
22+
#region IPostInitializableLoadedEntity implementation
23+
24+
/// <inheritdoc/>
25+
public void PostInitializeLoadedEntity() {
26+
UpdateConsumingState();
27+
}
28+
29+
#endregion
30+
31+
#region TickableComponent overrides
32+
33+
/// <inheritdoc/>
34+
public override void Tick() {
35+
UpdateConsumingState();
36+
}
37+
38+
#endregion
39+
40+
#region Implementation
41+
1742
MechanicalBuilding _mechanicalBuilding;
18-
43+
Enterable _enterable;
44+
1945
void Awake() {
2046
_mechanicalBuilding = GetComponentFast<MechanicalBuilding>();
2147
_enterable = GetComponentFast<Enterable>();
22-
_enterable.EntererAdded += (_, _) => UpdateConsumingState();
23-
_enterable.EntererRemoved += (_, _) => UpdateConsumingState();
24-
}
25-
26-
void Start() {
27-
UpdateConsumingState();
2848
}
2949

3050
void UpdateConsumingState() {
3151
var newState = _enterable.NumberOfEnterersInside == 0;
32-
if (newState == _mechanicalBuilding.ConsumptionDisabled) {
33-
return;
52+
if (newState != ConsumptionDisabled) {
53+
HostedDebugLog.Fine(this, newState ? "Disable power consumption" : "Enable power consumption");
54+
ConsumptionDisabled = newState;
3455
}
35-
if (newState) {
36-
HostedDebugLog.Fine(this, "Disable power consumption");
37-
} else {
38-
HostedDebugLog.Fine(this, "Enable power consumption");
39-
}
40-
_mechanicalBuilding.ConsumptionDisabled = newState;
56+
_mechanicalBuilding.ConsumptionDisabled = ConsumptionDisabled;
4157
}
58+
59+
#endregion
4260
}
4361

4462
}

SmartPower/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525
//
2626
// You can specify all the values or you can default the Build and Revision Numbers
2727
// by using the '*' as shown below:
28-
[assembly: AssemblyVersion("1.6.*")]
28+
[assembly: AssemblyVersion("1.7.*")]

0 commit comments

Comments
 (0)