• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

First Machine Age's Mods (Combined repo.)


Commit MetaInfo

Révision49d682d12fb187a68433fd53c3deae330f504e4f (tree)
l'heure2021-05-03 07:53:55
Auteurmelchior <melchior@user...>
Commitermelchior

Message de Log

W.I.P. Harmony RT patcher alternative implimentation

Change Summary

Modification

--- a/AnvilMetalRecovery/AnvilMetalRecovery.csproj
+++ b/AnvilMetalRecovery/AnvilMetalRecovery.csproj
@@ -64,6 +64,10 @@
6464 <HintPath>vs_libs\Newtonsoft.Json.dll</HintPath>
6565 <Private>False</Private>
6666 </Reference>
67+ <Reference Include="0Harmony">
68+ <HintPath>vs_libs\0Harmony.dll</HintPath>
69+ <Private>False</Private>
70+ </Reference>
6771 </ItemGroup>
6872 <ItemGroup>
6973 <Compile Include="MetalRecoverySystem.cs" />
@@ -75,6 +79,8 @@
7579 <Compile Include="Data\RecoveryEntry.cs" />
7680 <Compile Include="Items\VariableMetalItem.cs" />
7781 <Compile Include="Items\SmartSmeltableItem.cs" />
82+ <Compile Include="Harmony\AnvilDaptor.cs" />
83+ <Compile Include="MetalRecoverySystem_Components.cs" />
7884 </ItemGroup>
7985 <ItemGroup>
8086 <None Include="modinfo.json">
@@ -124,6 +130,7 @@
124130 <Folder Include="assets\fma\patches\" />
125131 <Folder Include="Data\" />
126132 <Folder Include="Items\" />
133+ <Folder Include="Harmony\" />
127134 </ItemGroup>
128135 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
129136 </Project>
\ No newline at end of file
--- /dev/null
+++ b/AnvilMetalRecovery/Harmony/AnvilDaptor.cs
@@ -0,0 +1,117 @@
1+using System;
2+using System.Text;
3+
4+using HarmonyLib;
5+
6+using Vintagestory.API.Common;
7+using Vintagestory.API.Config;
8+using Vintagestory.API.MathTools;
9+using Vintagestory.GameContent;
10+
11+namespace AnvilMetalRecovery
12+{
13+ /// <summary>
14+ /// Harmony patcher class to generate Bus-Events from Anvil, and other-effects
15+ /// </summary>
16+ [HarmonyPatch(typeof(BlockEntityAnvil))]
17+ public class AnvilDaptor
18+ {
19+
20+ [HarmonyPrefix]
21+ [HarmonyPatch(nameof(BlockEntityAnvil.OnSplit))]
22+ private static void Prefix_OnSplit(Vec3i voxelPos, BlockEntityAnvil __instance)
23+ {
24+ SmithAssist anvil = __instance as SmithAssist;
25+
26+ if (anvil.IsShavable && anvil.Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] == ( byte )EnumVoxelMaterial.Metal) {
27+ #if DEBUG
28+ anvil.Logger.VerboseDebug("Split some {0} @{1}, Total:{2}", anvil.BaseMetal, voxelPos, anvil.SplitCount);
29+ #endif
30+ anvil.SplitCount++;
31+ }
32+
33+ }
34+
35+ [HarmonyPostfix]
36+ [HarmonyPatch(nameof(BlockEntityAnvil.GetBlockInfo))]
37+ private static void Postfix_GetBlockInfo(IPlayer forPlayer, StringBuilder dsc, BlockEntityAnvil __instance)
38+ {
39+ SmithAssist anvil = __instance as SmithAssist;
40+
41+ if (anvil.IsShavable && anvil.SplitCount > 0 && anvil.BaseMaterial != null) {
42+ dsc.AppendFormat("[ {0} ÷ {1} ] = {2}", anvil.SplitCount, SmithAssist.splitValue, Lang.GetUnformatted($"fma:item-metal_shaving-{anvil.BaseMetal}"));
43+ }
44+
45+ }
46+
47+
48+ }
49+
50+ /// <summary>
51+ /// Special tools for handling the Anvil's data/state, ect...
52+ /// </summary>
53+ internal class SmithAssist : BlockEntityAnvil
54+ {
55+ internal const string splitCountKey = @"splitCount";
56+ internal const uint splitValue = 5;
57+
58+ internal ILogger Logger {
59+ get
60+ {
61+ return Api.World.Logger;
62+ }
63+ }
64+
65+ internal static AssetLocation MetalShavingsCode {
66+ get
67+ {
68+ return new AssetLocation(@"fma", @"metal_shaving");
69+ }
70+ }
71+
72+
73+ internal int SplitCount {
74+ get
75+ {
76+ return this.WorkItemStack?.Attributes.TryGetInt(splitCountKey) ?? 0;
77+ }
78+ set
79+ {
80+ this.WorkItemStack?.Attributes.SetInt(splitCountKey, value);
81+ }
82+ }
83+
84+ internal bool IsShavable {
85+ get
86+ {
87+ //this.SelectedRecipe <-- things that are recoverable?
88+ return this.WorkItemStack?.Collectible?.FirstCodePart( ).Equals(@"ironbloom") == false;
89+ }
90+ }
91+
92+ internal IAnvilWorkable AnvilWorkpiece {
93+ get
94+ {
95+ if (this.WorkItemStack != null && this.WorkItemStack.Collectible is IAnvilWorkable) { return this.WorkItemStack.Collectible as IAnvilWorkable; }
96+
97+ return null;
98+ }
99+ }
100+
101+ internal ItemStack BaseMaterial {
102+ get
103+ {
104+ if (this.WorkItemStack != null) return AnvilWorkpiece.GetBaseMaterial(this.WorkItemStack);//Right??
105+ return null;
106+ }
107+ }
108+
109+ internal string BaseMetal {
110+ get
111+ {
112+ return this?.BaseMaterial?.Collectible.LastCodePart( );
113+ }
114+ }
115+ }
116+}
117+
--- a/AnvilMetalRecovery/Items/VariableMetalItem.cs
+++ b/AnvilMetalRecovery/Items/VariableMetalItem.cs
@@ -62,16 +62,17 @@ namespace AnvilMetalRecovery
6262 LoadedTexture texturePlaceholder = new LoadedTexture(capi);
6363 var ingotCode = MetalCode(itemstack);
6464 var textureDonatorItem = capi.World.GetItem(ingotCode);
65+ if (textureDonatorItem != null) {
6566 var newTexture = textureDonatorItem.FirstTexture.Base.WithPathAppendixOnce(".png");
6667
6768 //#if DEBUG
6869 //capi.Logger.VerboseDebug("VariableMetalItem Txr: {0}", newTexture);
69- //#endif
70-
70+ //#endif
71+
7172 capi.Render.GetOrLoadTexture(newTexture, ref texturePlaceholder);
7273
7374 renderinfo.TextureId = texturePlaceholder.TextureId;
74-
75+ }
7576 //Cache TextId# on TempAttributes ?
7677 }
7778
--- a/AnvilMetalRecovery/MetalRecoverySystem.cs
+++ b/AnvilMetalRecovery/MetalRecoverySystem.cs
@@ -69,9 +69,10 @@ namespace AnvilMetalRecovery
6969 {
7070 this.CoreAPI = api;
7171
72-
7372 RegisterItemMappings( );
7473
74+ //TODO: Setup HARMONY Patches
75+
7576 base.Start(api);
7677 }
7778
@@ -136,167 +137,7 @@ namespace AnvilMetalRecovery
136137 ServerCore.Event.RegisterEventBusListener(HotbarEventReciever, 1.0f, HotbarObserverBehavior.HotbarChannelName);
137138 }
138139
139- private void MaterialDataGathering( )
140- {
141- //Count out Voxels in smthing recipes for all metal-ingot(?) derived items;
142- var examineList = ServerAPI.World.SmithingRecipes.Where(sr => sr.Enabled && sr.Ingredient.Type == EnumItemClass.Item && sr.Output.Type == EnumItemClass.Item);
143-
144- foreach (var recipie in examineList)
145- {
146- CollectibleObject metalObject = recipie.Ingredient.Type == EnumItemClass.Item ? ServerAPI.World.GetItem(recipie.Ingredient.Code) : ServerAPI.World.GetBlock(recipie.Ingredient.Code) as CollectibleObject;
147- Item outputItem = ServerAPI.World.GetItem(recipie.Output.Code);
148-
149- if (metalObject.CombustibleProps != null && metalObject.CombustibleProps.SmeltingType == EnumSmeltType.Smelt && metalObject.CombustibleProps.SmeltedRatio > 0) {
150- //Item Input Has a metal Unit value...(Smeltable)
151- //Resolve?
152- int setVoxels = 0;
153- setVoxels = recipie.Voxels.OfType<bool>( ).Count(vox => vox);
154-
155- #if DEBUG
156- Mod.Logger.VerboseDebug($"{recipie.Output.Quantity}* '{outputItem.Code}' -> {setVoxels}x '{metalObject.Code}' voxel = ~{setVoxels * IngotVoxelEquivalent:F1} metal Units");
157- #endif
158- //Direct output *IS* tool or tool-like Durability type item (chisel )
159- if (outputItem.Tool.HasValue || outputItem.Durability > 1)
160- {
161- itemToVoxelLookup.Add(outputItem.Code.Clone( ), new RecoveryEntry(metalObject.Code,
162- ( uint )(setVoxels / recipie.Output.Quantity),
163- metalObject.CombustibleProps.MeltingDuration,
164- metalObject.CombustibleProps.MeltingPoint)
165- );
166- #if DEBUG
167- Mod.Logger.VerboseDebug($"Mapped: ('tool') '{outputItem.Code}' -> ('tool') '{outputItem.Code}'");
168- #endif
169- }
170- else
171- {
172- //Tool-head map to Tool item; decode
173- var itemToolCode = ServerAPI.World.GridRecipes.FirstOrDefault(gr => gr.Ingredients.Any(crg => crg.Value.Code.Equals(outputItem.Code)) && gr.Enabled && gr.Output.Type == EnumItemClass.Item)?.Output.Code;
174- if (itemToolCode != null)
175- {
176- var itemTool = ServerAPI.World.GetItem(itemToolCode);
177- if (itemTool.Tool.HasValue)
178- {
179- itemToVoxelLookup.Add(itemToolCode.Clone( ), new RecoveryEntry(metalObject.Code,
180- ( uint )(setVoxels / recipie.Output.Quantity),
181- metalObject.CombustibleProps.MeltingDuration,
182- metalObject.CombustibleProps.MeltingPoint)
183- );
184- #if DEBUG
185- Mod.Logger.VerboseDebug($"Mapped: (head) '{outputItem.Code}' -> (tool) '{itemToolCode}'");
186- #endif
187- }
188- }
189- }
190- }
191- }
192-
193- }
194-
195- private void HotbarEventReciever(string eventName, ref EnumHandling handling, IAttribute data)
196- {
197- handling = EnumHandling.PassThrough;
198- HotbarObserverData hotbarData = data as HotbarObserverData;
199-
200- #if DEBUG
201- Mod.Logger.VerboseDebug("HotbarEvent Rx: Item:{0} Slot#{1} PlayerUID:{2}", hotbarData.ItemCode.ToString( ), hotbarData.SlotID, hotbarData.PlayerUID);
202- #endif
203-
204- if (ItemFilterList.Contains(hotbarData.ItemCode)) {
205- #if DEBUG
206- RecoveryEntry rec = itemToVoxelLookup[hotbarData.ItemCode];
207- Mod.Logger.VerboseDebug("broken-tool/weap. {0} WORTH: {1:F1}*{2} units", hotbarData.ItemCode.ToString( ),(rec.Quantity*IngotVoxelEquivalent), rec.IngotCode.ToShortString() );
208- #endif
209-
210- var playerTarget = ServerAPI.World.PlayerByUid(hotbarData.PlayerUID);
211- var hotbarInv = playerTarget.InventoryManager.GetHotbarInventory( );
212- var hotSlot = hotbarInv[hotbarData.SlotID];
213- var spim = playerTarget.InventoryManager as ServerPlayerInventoryManager;
214-
215-
216- if (hotSlot.Empty)
217- {
218- #if DEBUG
219- Mod.Logger.VerboseDebug("Directly inserting fragments into hotbar slot# {0}", hotbarData.SlotID);
220- #endif
221-
222- VariableMetalItem variableMetal = ServerAPI.World.GetItem(new AssetLocation(metalFragmentsCode)) as VariableMetalItem;
223- ItemStack metalFragmentsStack = new ItemStack(variableMetal, 1);
224- variableMetal.ApplyMetalProperties(rec, ref metalFragmentsStack);
225- hotSlot.Itemstack = metalFragmentsStack;
226- hotSlot.Itemstack.ResolveBlockOrItem(ServerAPI.World);
227- hotSlot.MarkDirty( );
228- spim.NotifySlot(playerTarget, hotSlot);
229- }
230- else
231- {
232- #if DEBUG
233- Mod.Logger.VerboseDebug("Occupied Hotbar slot# {0}; shoving item in general direction of player...", hotbarData.SlotID);
234- #endif
235-
236- VariableMetalItem variableMetal = ServerAPI.World.GetItem(new AssetLocation(metalFragmentsCode)) as VariableMetalItem;
237- ItemStack metalFragmentsStack = new ItemStack(variableMetal, 1);
238- variableMetal.ApplyMetalProperties(rec, ref metalFragmentsStack);
239- spim.TryGiveItemstack(metalFragmentsStack, true);
240- }
241- }
242-
243- }
244-
245-
246-
247- private void EditDurability(IServerPlayer player, int groupId, CmdArgs args)
248- {
249- if (!player.Entity.RightHandItemSlot.Empty &&
250- player.Entity.RightHandItemSlot.Itemstack.Class == EnumItemClass.Item) {
251- var number = args.PopInt( );
252-
253- player.Entity.RightHandItemSlot.Itemstack.Hitpoints(number ?? 10);
254- player.Entity.RightHandItemSlot.MarkDirty( );
255- }
256-
257- }
258-
259- /// <summary>
260- /// Adds all smelting related 'combustibleProps' fields from known Ingot Codes; (matching variant keys)
261- /// </summary>
262- /// <returns>The combuastable properties by code variant.</returns>
263- /// <param name="updatingCode">PARTIAL Item code.</param>
264- private void ApplySmeltingPropertiesByCodeVariant(AssetLocation updatingCode, int ratioOverride = 1 )
265- {
266- //ALL ????:'ingot-*' type items...
267- var ingotItems = ServerAPI.World.Items.Where(itm => itm.ItemId > 0 && itm.Code != null && itm.Code.BeginingOnly(@"ingot"));
268-
269- #if DEBUG
270- this.Mod.Logger.VerboseDebug("found {0} Ingot type items", ingotItems.Count());
271- #endif
272140
273- foreach (var ingotEntry in ingotItems) {
274- if (ingotEntry == null) continue;
275- string metalName = ingotEntry?.Variant[@"metal"];
276- var metalSmeltProps = ingotEntry?.CombustibleProps?.Clone( );
277-
278- if (metalSmeltProps == null) continue;//SHOULD BE NEVER !
279- if (string.IsNullOrEmpty(metalName)) continue;
280-
281- metalSmeltProps.SmeltedRatio = ratioOverride;
282- AssetLocation shavingCode = updatingCode.AppendPathVariant(metalName);
283- var shavingEquivalentItem = ServerAPI.World.GetItem(shavingCode);
284- if (shavingEquivalentItem != null)
285- {
286- shavingEquivalentItem.CombustibleProps = metalSmeltProps;
287- #if DEBUG
288- ServerAPI.Logger.VerboseDebug("Updated SmeltProps, for: {0}", shavingCode.ToString( ));
289- #endif
290- }
291- else
292- {
293- #if DEBUG
294- ServerAPI.Logger.VerboseDebug("Non-existant item: {0}", shavingCode.ToString( ));
295- #endif
296- }
297- }
298-
299- }
300141 }
301142
302143
--- /dev/null
+++ b/AnvilMetalRecovery/MetalRecoverySystem_Components.cs
@@ -0,0 +1,173 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Linq.Expressions;
5+
6+using Vintagestory.API.Client;
7+using Vintagestory.API.Common;
8+using Vintagestory.API.Datastructures;
9+using Vintagestory.API.Server;
10+using Vintagestory.Client.NoObf;
11+using Vintagestory.Common;
12+using Vintagestory.Server;
13+using Vintagestory.ServerMods;
14+
15+namespace AnvilMetalRecovery
16+{
17+ public partial class MetalRecoverySystem : ModSystem
18+ {
19+ private void MaterialDataGathering( )
20+ {
21+ //Count out Voxels in smthing recipes for all metal-ingot(?) derived items;
22+ var examineList = ServerAPI.World.SmithingRecipes.Where(sr => sr.Enabled && sr.Ingredient.Type == EnumItemClass.Item && sr.Output.Type == EnumItemClass.Item);
23+
24+ foreach (var recipie in examineList) {
25+ CollectibleObject metalObject = recipie.Ingredient.Type == EnumItemClass.Item ? ServerAPI.World.GetItem(recipie.Ingredient.Code) : ServerAPI.World.GetBlock(recipie.Ingredient.Code) as CollectibleObject;
26+ Item outputItem = ServerAPI.World.GetItem(recipie.Output.Code);
27+
28+ if (metalObject.CombustibleProps != null && metalObject.CombustibleProps.SmeltingType == EnumSmeltType.Smelt && metalObject.CombustibleProps.SmeltedRatio > 0) {
29+ //Item Input Has a metal Unit value...(Smeltable)
30+ //Resolve?
31+ int setVoxels = 0;
32+ setVoxels = recipie.Voxels.OfType<bool>( ).Count(vox => vox);
33+
34+ #if DEBUG
35+ Mod.Logger.VerboseDebug($"{recipie.Output.Quantity}* '{outputItem.Code}' -> {setVoxels}x '{metalObject.Code}' voxel = ~{setVoxels * IngotVoxelEquivalent:F1} metal Units");
36+ #endif
37+ //Direct output *IS* tool or tool-like Durability type item (chisel )
38+ if (outputItem.Tool.HasValue || outputItem.Durability > 1) {
39+ itemToVoxelLookup.Add(outputItem.Code.Clone( ), new RecoveryEntry(metalObject.Code,
40+ ( uint )(setVoxels / recipie.Output.Quantity),
41+ metalObject.CombustibleProps.MeltingDuration,
42+ metalObject.CombustibleProps.MeltingPoint)
43+ );
44+ #if DEBUG
45+ Mod.Logger.VerboseDebug($"Mapped: ('tool') '{outputItem.Code}' -> ('tool') '{outputItem.Code}'");
46+ #endif
47+ }
48+ else {
49+ //Tool-head map to Tool item; decode
50+ var itemToolCode = ServerAPI.World.GridRecipes.FirstOrDefault(gr => gr.Ingredients.Any(crg => crg.Value.Code.Equals(outputItem.Code)) && gr.Enabled && gr.Output.Type == EnumItemClass.Item)?.Output.Code;
51+ if (itemToolCode != null) {
52+ var itemTool = ServerAPI.World.GetItem(itemToolCode);
53+ if (itemTool.Tool.HasValue) {
54+ itemToVoxelLookup.Add(itemToolCode.Clone( ), new RecoveryEntry(metalObject.Code,
55+ ( uint )(setVoxels / recipie.Output.Quantity),
56+ metalObject.CombustibleProps.MeltingDuration,
57+ metalObject.CombustibleProps.MeltingPoint)
58+ );
59+ #if DEBUG
60+ Mod.Logger.VerboseDebug($"Mapped: (head) '{outputItem.Code}' -> (tool) '{itemToolCode}'");
61+ #endif
62+ }
63+ }
64+ }
65+ }
66+ }
67+
68+ }
69+
70+ private void HotbarEventReciever(string eventName, ref EnumHandling handling, IAttribute data)
71+ {
72+ handling = EnumHandling.PassThrough;
73+ HotbarObserverData hotbarData = data as HotbarObserverData;
74+
75+ #if DEBUG
76+ Mod.Logger.VerboseDebug("HotbarEvent Rx: Item:{0} Slot#{1} PlayerUID:{2}", hotbarData.ItemCode.ToString( ), hotbarData.SlotID, hotbarData.PlayerUID);
77+ #endif
78+
79+ if (ItemFilterList.Contains(hotbarData.ItemCode)) {
80+ #if DEBUG
81+ RecoveryEntry rec = itemToVoxelLookup[hotbarData.ItemCode];
82+ Mod.Logger.VerboseDebug("broken-tool/weap. {0} WORTH: {1:F1}*{2} units", hotbarData.ItemCode.ToString( ), (rec.Quantity * IngotVoxelEquivalent), rec.IngotCode.ToShortString( ));
83+ #endif
84+
85+ var playerTarget = ServerAPI.World.PlayerByUid(hotbarData.PlayerUID);
86+ var hotbarInv = playerTarget.InventoryManager.GetHotbarInventory( );
87+ var hotSlot = hotbarInv[hotbarData.SlotID];
88+ var spim = playerTarget.InventoryManager as ServerPlayerInventoryManager;
89+
90+
91+ if (hotSlot.Empty) {
92+ #if DEBUG
93+ Mod.Logger.VerboseDebug("Directly inserting fragments into hotbar slot# {0}", hotbarData.SlotID);
94+ #endif
95+
96+ VariableMetalItem variableMetal = ServerAPI.World.GetItem(new AssetLocation(metalFragmentsCode)) as VariableMetalItem;
97+ ItemStack metalFragmentsStack = new ItemStack(variableMetal, 1);
98+ variableMetal.ApplyMetalProperties(rec, ref metalFragmentsStack);
99+ hotSlot.Itemstack = metalFragmentsStack;
100+ hotSlot.Itemstack.ResolveBlockOrItem(ServerAPI.World);
101+ hotSlot.MarkDirty( );
102+ spim.NotifySlot(playerTarget, hotSlot);
103+ }
104+ else {
105+ #if DEBUG
106+ Mod.Logger.VerboseDebug("Occupied Hotbar slot# {0}; shoving item in general direction of player...", hotbarData.SlotID);
107+ #endif
108+
109+ VariableMetalItem variableMetal = ServerAPI.World.GetItem(new AssetLocation(metalFragmentsCode)) as VariableMetalItem;
110+ ItemStack metalFragmentsStack = new ItemStack(variableMetal, 1);
111+ variableMetal.ApplyMetalProperties(rec, ref metalFragmentsStack);
112+ spim.TryGiveItemstack(metalFragmentsStack, true);
113+ }
114+ }
115+
116+ }
117+
118+
119+
120+ private void EditDurability(IServerPlayer player, int groupId, CmdArgs args)
121+ {
122+ if (!player.Entity.RightHandItemSlot.Empty &&
123+ player.Entity.RightHandItemSlot.Itemstack.Class == EnumItemClass.Item) {
124+ var number = args.PopInt( );
125+
126+ player.Entity.RightHandItemSlot.Itemstack.Hitpoints(number ?? 10);
127+ player.Entity.RightHandItemSlot.MarkDirty( );
128+ }
129+
130+ }
131+
132+ /// <summary>
133+ /// Adds all smelting related 'combustibleProps' fields from known Ingot Codes; (matching variant keys)
134+ /// </summary>
135+ /// <returns>The combuastable properties by code variant.</returns>
136+ /// <param name="updatingCode">PARTIAL Item code.</param>
137+ private void ApplySmeltingPropertiesByCodeVariant(AssetLocation updatingCode, int ratioOverride = 1)
138+ {
139+ //ALL ????:'ingot-*' type items...
140+ var ingotItems = ServerAPI.World.Items.Where(itm => itm.ItemId > 0 && itm.Code != null && itm.Code.BeginingOnly(@"ingot"));
141+
142+ #if DEBUG
143+ this.Mod.Logger.VerboseDebug("found {0} Ingot type items", ingotItems.Count( ));
144+ #endif
145+
146+ foreach (var ingotEntry in ingotItems) {
147+ if (ingotEntry == null) continue;
148+ string metalName = ingotEntry?.Variant[@"metal"];
149+ var metalSmeltProps = ingotEntry?.CombustibleProps?.Clone( );
150+
151+ if (metalSmeltProps == null) continue;//SHOULD BE NEVER !
152+ if (string.IsNullOrEmpty(metalName)) continue;
153+
154+ metalSmeltProps.SmeltedRatio = ratioOverride;
155+ AssetLocation shavingCode = updatingCode.AppendPathVariant(metalName);
156+ var shavingEquivalentItem = ServerAPI.World.GetItem(shavingCode);
157+ if (shavingEquivalentItem != null) {
158+ shavingEquivalentItem.CombustibleProps = metalSmeltProps;
159+ #if DEBUG
160+ ServerAPI.Logger.VerboseDebug("Updated SmeltProps, for: {0}", shavingCode.ToString( ));
161+ #endif
162+ }
163+ else {
164+ #if DEBUG
165+ ServerAPI.Logger.VerboseDebug("Non-existant item: {0}", shavingCode.ToString( ));
166+ #endif
167+ }
168+ }
169+
170+ }
171+ }
172+}
173+