• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

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

修订版266e3e3fbc60bc37e3e76954998ebd35f1616c84 (tree)
时间2021-05-04 06:17:02
作者melchior <melchior@user...>
Commitermelchior

Log Message

W.I.P. Almost working harmonized B.E.A.

更改概述

差异

--- a/AnvilMetalRecovery/AnvilMetalRecovery.csproj
+++ b/AnvilMetalRecovery/AnvilMetalRecovery.csproj
@@ -72,7 +72,6 @@
7272 <ItemGroup>
7373 <Compile Include="MetalRecoverySystem.cs" />
7474 <Compile Include="Properties\AssemblyInfo.cs" />
75- <Compile Include="BlockEntities\MetalRecovery_BlockEntityAnvil.cs" />
7675 <Compile Include="Helpers.cs" />
7776 <Compile Include="EntityBehaviors\HotbarObserverBehavior.cs" />
7877 <Compile Include="EntityBehaviors\HotbarObserverData.cs" />
@@ -110,6 +109,7 @@
110109 <None Include="assets\fma\itemtypes\metal\fragments.json">
111110 <CopyToOutputDirectory>Always</CopyToOutputDirectory>
112111 </None>
112+ <None Include="BlockEntities\MetalRecovery_BlockEntityAnvil.cs" />
113113 </ItemGroup>
114114 <ItemGroup>
115115 <Folder Include="assets\" />
--- a/AnvilMetalRecovery/Harmony/AnvilDaptor.cs
+++ b/AnvilMetalRecovery/Harmony/AnvilDaptor.cs
@@ -1,4 +1,5 @@
11 using System;
2+using System.Linq;
23 using System.Text;
34
45 using HarmonyLib;
@@ -11,7 +12,7 @@ using Vintagestory.GameContent;
1112 namespace AnvilMetalRecovery
1213 {
1314 /// <summary>
14- /// Harmony patcher class to generate Bus-Events from Anvil, and other-effects
15+ /// Harmony patcher class to wrap B.E. Anvil class
1516 /// </summary>
1617 [HarmonyPatch(typeof(BlockEntityAnvil))]
1718 public class AnvilDaptor
@@ -21,9 +22,9 @@ namespace AnvilMetalRecovery
2122 [HarmonyPatch(nameof(BlockEntityAnvil.OnSplit))]
2223 private static void Prefix_OnSplit(Vec3i voxelPos, BlockEntityAnvil __instance)
2324 {
24- SmithAssist anvil = __instance as SmithAssist;
25+ var anvil = new SmithAssist(__instance);
2526
26- if (anvil.IsShavable && anvil.Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] == ( byte )EnumVoxelMaterial.Metal) {
27+ if (anvil.IsShavable && anvil.Voxel(voxelPos.X, voxelPos.Y, voxelPos.Z) == EnumVoxelMaterial.Metal) {
2728 #if DEBUG
2829 anvil.Logger.VerboseDebug("Split some {0} @{1}, Total:{2}", anvil.BaseMetal, voxelPos, anvil.SplitCount);
2930 #endif
@@ -34,31 +35,53 @@ namespace AnvilMetalRecovery
3435
3536 [HarmonyPostfix]
3637 [HarmonyPatch(nameof(BlockEntityAnvil.GetBlockInfo))]
37- private static void Postfix_GetBlockInfo(IPlayer forPlayer, StringBuilder dsc, BlockEntityAnvil __instance)
38+ private static void Postfix_GetBlockInfo(IPlayer forPlayer, ref StringBuilder dsc, BlockEntityAnvil __instance)
3839 {
39- SmithAssist anvil = __instance as SmithAssist;
40+ var anvil = new SmithAssist(__instance);
4041
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}"));
42+ if (anvil.BaseMaterial != null && anvil.IsShavable && anvil.SplitCount > 0)
43+ {
44+ dsc.AppendFormat("[ {0} ÷ {1} ] : {2}", anvil.SplitCount, SmithAssist.shavingValue, Lang.GetUnformatted($"fma:item-metal_shaving-{anvil.BaseMetal}"));
45+ }
4346 }
4447
48+ [HarmonyPrefix]
49+ [HarmonyPatch(nameof(BlockEntityAnvil.CheckIfFinished))]
50+ private static void Prefix_CheckIfFinished(IPlayer byPlayer, BlockEntityAnvil __instance)
51+ {
52+ var anvil = new SmithAssist(__instance);
53+ if (anvil.WorkMatchesRecipe( ))
54+ {
55+ anvil.IssueShavings(byPlayer );
56+ }
4557 }
4658
59+ /* [HarmonyReversePatch]
60+ private bool MatchesRecipe() //But faster?
61+ */
62+
4763
4864 }
4965
5066 /// <summary>
5167 /// Special tools for handling the Anvil's data/state, ect...
5268 /// </summary>
53- internal class SmithAssist : BlockEntityAnvil
69+ internal class SmithAssist
5470 {
71+ private readonly BlockEntityAnvil bea;
72+
5573 internal const string splitCountKey = @"splitCount";
56- internal const uint splitValue = 5;
74+ internal const uint shavingValue = 5;
75+
76+ internal SmithAssist(BlockEntityAnvil a)
77+ {
78+ this.bea = a;
79+ }
5780
5881 internal ILogger Logger {
5982 get
6083 {
61- return Api.World.Logger;
84+ return bea.Api.World.Logger;
6285 }
6386 }
6487
@@ -69,15 +92,21 @@ namespace AnvilMetalRecovery
6992 }
7093 }
7194
95+ // public byte[,,] Voxels = new byte[16, 6, 16];
96+ internal EnumVoxelMaterial Voxel( int X , int Y , int Z )
97+ {
98+ return (EnumVoxelMaterial)bea.Voxels[X, Y, Z];
99+ }
100+
72101
73102 internal int SplitCount {
74103 get
75104 {
76- return this.WorkItemStack?.Attributes.TryGetInt(splitCountKey) ?? 0;
105+ return bea.WorkItemStack?.Attributes.TryGetInt(splitCountKey) ?? 0;
77106 }
78107 set
79108 {
80- this.WorkItemStack?.Attributes.SetInt(splitCountKey, value);
109+ bea.WorkItemStack?.Attributes.SetInt(splitCountKey, value);
81110 }
82111 }
83112
@@ -85,14 +114,14 @@ namespace AnvilMetalRecovery
85114 get
86115 {
87116 //this.SelectedRecipe <-- things that are recoverable?
88- return this.WorkItemStack?.Collectible?.FirstCodePart( ).Equals(@"ironbloom") == false;
117+ return bea.WorkItemStack?.Collectible?.FirstCodePart( ).Equals(@"ironbloom") == false;
89118 }
90119 }
91120
92121 internal IAnvilWorkable AnvilWorkpiece {
93122 get
94123 {
95- if (this.WorkItemStack != null && this.WorkItemStack.Collectible is IAnvilWorkable) { return this.WorkItemStack.Collectible as IAnvilWorkable; }
124+ if (bea.WorkItemStack != null && bea.WorkItemStack.Collectible is IAnvilWorkable) { return bea.WorkItemStack.Collectible as IAnvilWorkable; }
96125
97126 return null;
98127 }
@@ -101,7 +130,7 @@ namespace AnvilMetalRecovery
101130 internal ItemStack BaseMaterial {
102131 get
103132 {
104- if (this.WorkItemStack != null) return AnvilWorkpiece.GetBaseMaterial(this.WorkItemStack);//Right??
133+ if (bea.WorkItemStack != null) return AnvilWorkpiece.GetBaseMaterial(bea.WorkItemStack);//Right??
105134 return null;
106135 }
107136 }
@@ -112,6 +141,63 @@ namespace AnvilMetalRecovery
112141 return this?.BaseMaterial?.Collectible.LastCodePart( );
113142 }
114143 }
144+
145+ internal int MetalVoxelCount {
146+ get { return bea.Voxels.OfType<byte>( ).Count(vox => vox == (byte)EnumVoxelMaterial.Metal); }
147+ }
148+
149+
150+ internal void IssueShavings(IPlayer byPlayer )
151+ {
152+ if (this.SplitCount > 0) {
153+ int shavingsCount = ( int )(SplitCount / shavingValue);
154+
155+ if (shavingsCount > 0)
156+ {
157+ #if DEBUG
158+ Logger.VerboseDebug("RecoveryAnvil: Smithing done - recover: {0} shavings of {1}", shavingsCount, BaseMaterial);
159+ #endif
160+
161+ Item metalShavingsItem = bea.Api.World.GetItem(MetalShavingsCode.WithPathAppendix("-" + BaseMaterial));
162+
163+ if (metalShavingsItem != null)
164+ {
165+ ItemStack metalShavingsStack = new ItemStack(metalShavingsItem, shavingsCount);
166+
167+ if (byPlayer != null) {
168+ if (byPlayer.InventoryManager.TryGiveItemstack(metalShavingsStack, false) == false) { byPlayer.Entity.World.SpawnItemEntity(metalShavingsStack, byPlayer.Entity.Pos.XYZ); }
169+ }
170+ }
171+ else
172+ {
173+ Logger.Warning("Missing or Invalid Item: {0} ", MetalShavingsCode.WithPathAppendix("-" + BaseMaterial));
174+ }
175+ this.SplitCount = 0;
176+ }
177+ }
178+ }
179+
180+ /// <summary>
181+ /// Copy-Paste, from 'BEAnvil.cs'
182+ /// </summary>
183+ /// <returns>The matches recipe.</returns>
184+ internal bool WorkMatchesRecipe()
185+ {
186+ if (bea.SelectedRecipe == null) return false;
187+
188+ int ymax = Math.Min(6, bea.SelectedRecipe.QuantityLayers);//Why ignore higher layers?
189+
190+ var theRecipie = bea.recipeVoxels; //RotatedRecipeVoxels
191+
192+ for (int x = 0; x < 16; x++) {
193+ for (int y = 0; y < ymax; y++) {
194+ for (int z = 0; z < 16; z++) {
195+ byte desiredMat = ( byte )(theRecipie[x, y, z] ? EnumVoxelMaterial.Metal : EnumVoxelMaterial.Empty);
196+
197+ if (bea.Voxels[x, y, z] != desiredMat) { return false; } } } }
198+
199+ return true;
200+ }
115201 }
116202 }
117203
--- a/AnvilMetalRecovery/Items/SmartSmeltableItem.cs
+++ b/AnvilMetalRecovery/Items/SmartSmeltableItem.cs
@@ -27,13 +27,13 @@ namespace AnvilMetalRecovery
2727
2828 protected void RegenerateCombustablePropsByVariant(ItemSlot slot)
2929 {
30- if (this.CombustibleProps != null || slot.Itemstack.Collectible.CombustibleProps != null) return;
30+ if (this.CombustibleProps != null || ( slot.Empty == false && slot.Itemstack.Collectible.CombustibleProps != null)) return;
3131
3232 var ingotAssetCode = _ingotPrefix.AppendPathVariant(Metal);//Wildcard find? excluding domain?
3333 var ingotEntry = api.World.GetItem(ingotAssetCode);
3434 var metalSmeltProps = ingotEntry?.CombustibleProps?.Clone( );
3535
36- if (metalSmeltProps != null)
36+ if ((ingotEntry != null || !ingotEntry.IsMissing) && metalSmeltProps != null)
3737 {
3838 metalSmeltProps.SmeltedRatio = Ratio;
3939
@@ -46,7 +46,7 @@ namespace AnvilMetalRecovery
4646 else
4747 {
4848 #if DEBUG
49- api.Logger.VerboseDebug("Non-existant Ingot: {0}", ingotAssetCode.ToString( ));
49+ api.Logger.VerboseDebug("Non-existant Ingot or C.Props: {0}", ingotAssetCode.ToString( ));
5050 #endif
5151 }
5252 }
--- a/AnvilMetalRecovery/Items/VariableMetalItem.cs
+++ b/AnvilMetalRecovery/Items/VariableMetalItem.cs
@@ -42,7 +42,7 @@ namespace AnvilMetalRecovery
4242 protected string MetalName(ItemStack itemStack)
4343 {
4444 //TODO: generic 'material' Language entries...
45- if (itemStack == null || itemStack.Attributes == null) return String.Empty;
45+ if (itemStack == null || itemStack.Attributes == null) return @"?";
4646 var sliced = Lang.GetUnformatted("item-"+MetalCode(itemStack).Path).Split(' ');
4747 return String.Join(" ", sliced.Take(sliced.Length - 1));
4848 }
@@ -129,7 +129,7 @@ namespace AnvilMetalRecovery
129129
130130 public override void OnModifiedInInventorySlot(IWorldAccessor world, ItemSlot slot, ItemStack extractedStack = null)
131131 {
132- RegenerateCombustablePropsFromStack(slot.Itemstack);
132+ if (!slot.Empty) RegenerateCombustablePropsFromStack(slot.Itemstack);
133133 }
134134
135135 //Merge (same) metal piles together? Upto 100 units.
@@ -155,8 +155,10 @@ namespace AnvilMetalRecovery
155155
156156 if (metalCode != null )
157157 {
158- var sourceMetalItem = api.World.GetItem(metalCode);
159-
158+ var sourceMetalItem = api.World.GetItem(metalCode);
159+
160+ if (sourceMetalItem == null || sourceMetalItem.IsMissing || sourceMetalItem.CombustibleProps == null) return;
161+
160162 CombustibleProps = new CombustibleProperties( ) {
161163 SmeltingType = EnumSmeltType.Smelt,
162164 MeltingPoint = sourceMetalItem.CombustibleProps.MeltingPoint,
@@ -169,7 +171,7 @@ namespace AnvilMetalRecovery
169171 contStack.Collectible.CombustibleProps = CombustibleProps.Clone( );
170172
171173 #if DEBUG
172- api.Logger.VerboseDebug("Melt point: {0}, Duration: {1}, Ratio: {2}, Out.stk: {3} * {4}", this.CombustibleProps.MeltingPoint,this.CombustibleProps.MeltingDuration,this.CombustibleProps.SmeltedRatio, this.CombustibleProps.SmeltedStack.ResolvedItemstack.Item.Code.ToString(),this.CombustibleProps.SmeltedStack.StackSize );
174+ api.Logger.VerboseDebug("Melt point: {0}, Duration: {1}, Ratio: {2}, Out.stk: {3} * {4}", this.CombustibleProps.MeltingPoint,this.CombustibleProps.MeltingDuration,this.CombustibleProps.SmeltedRatio, this.CombustibleProps.SmeltedStack.ResolvedItemstack.Item.Code.ToString(),this.CombustibleProps.SmeltedStack.StackSize );
173175 #endif
174176 }
175177
--- a/AnvilMetalRecovery/MetalRecoverySystem.cs
+++ b/AnvilMetalRecovery/MetalRecoverySystem.cs
@@ -1,16 +1,13 @@
1-using System;
2-using System.Collections.Generic;
1+using System.Collections.Generic;
32 using System.Linq;
4-using System.Linq.Expressions;
3+
4+using HarmonyLib;
55
66 using Vintagestory.API.Client;
77 using Vintagestory.API.Common;
8-using Vintagestory.API.Datastructures;
98 using Vintagestory.API.Server;
109 using Vintagestory.Client.NoObf;
11-using Vintagestory.Common;
1210 using Vintagestory.Server;
13-using Vintagestory.ServerMods;
1411
1512 namespace AnvilMetalRecovery
1613 {
@@ -71,7 +68,11 @@ namespace AnvilMetalRecovery
7168
7269 RegisterItemMappings( );
7370
74- //TODO: Setup HARMONY Patches
71+ #if DEBUG
72+ //Harmony.DEBUG = true;
73+ #endif
74+ var harmony = new Harmony(this.Mod.Info.ModID);
75+ harmony.PatchAll( );
7576
7677 base.Start(api);
7778 }
@@ -89,9 +90,7 @@ namespace AnvilMetalRecovery
8990 return;
9091 }
9192
92- //ServerAPI.ClassRegistry.GetBlockEntityClass
93- //ServerAPI.RegisterBlockEntityClass(anvilKey, typeof(MetalRecovery_BlockEntityAnvil));
94- ServerCore.ClassRegistryNative.ReplaceBlockEntityType(anvilKey, typeof(MetalRecovery_BlockEntityAnvil));
93+ //ServerCore.ClassRegistryNative.ReplaceBlockEntityType(anvilKey, typeof(MetalRecovery_BlockEntityAnvil));
9594
9695 ServerCore.Event.ServerRunPhase(EnumServerRunPhase.GameReady, MaterialDataGathering);
9796
@@ -118,7 +117,7 @@ namespace AnvilMetalRecovery
118117 return;
119118 }
120119
121- ClientCore.ClassRegistryNative.ReplaceBlockEntityType(anvilKey, typeof(MetalRecovery_BlockEntityAnvil));
120+ //ClientCore.ClassRegistryNative.ReplaceBlockEntityType(anvilKey, typeof(MetalRecovery_BlockEntityAnvil));
122121
123122 Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be installed...");
124123 }
--- a/AnvilMetalRecovery/assets/fma/shapes/item/metal/fragments.json
+++ b/AnvilMetalRecovery/assets/fma/shapes/item/metal/fragments.json
@@ -8,7 +8,7 @@
88 "textureSizes": {
99 },
1010 "textures": {
11- "metal": "game:block/metal/plate/copper"
11+ "metal": "block/metal/ingot/lead"
1212 },
1313 "elements": [
1414 {
@@ -16,12 +16,12 @@
1616 "from": [ 5.0, 0.0, 5.0 ],
1717 "to": [ 9.0, 2.0, 8.0 ],
1818 "faces": {
19- "north": { "texture": "#metal", "uv": [ 0.0, 0.0, 4.0, 2.0 ] },
20- "east": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.0, 2.0 ] },
21- "south": { "texture": "#metal", "uv": [ 0.0, 0.0, 4.0, 2.0 ] },
22- "west": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.0, 2.0 ] },
23- "up": { "texture": "#metal", "uv": [ 0.0, 0.0, 4.0, 3.0 ] },
24- "down": { "texture": "#metal", "uv": [ 0.0, 0.0, 4.0, 3.0 ] }
19+ "north": { "texture": "#metal", "uv": [ 1.0, 2.5, 5.0, 4.5 ] },
20+ "east": { "texture": "#metal", "uv": [ 5.5, 5.5, 8.5, 7.5 ] },
21+ "south": { "texture": "#metal", "uv": [ 8.5, 3.0, 12.5, 5.0 ] },
22+ "west": { "texture": "#metal", "uv": [ 10.0, 7.0, 13.0, 9.0 ] },
23+ "up": { "texture": "#metal", "uv": [ 7.0, 8.5, 11.0, 11.5 ] },
24+ "down": { "texture": "#metal", "uv": [ 8.0, 3.0, 12.0, 6.0 ] }
2525 },
2626 "children": [
2727 {
@@ -32,12 +32,12 @@
3232 "rotationX": 51.0,
3333 "rotationY": 3.0,
3434 "faces": {
35- "north": { "texture": "#metal", "uv": [ 0.0, 0.0, 8.0, 1.0 ] },
36- "east": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.0, 1.0 ] },
37- "south": { "texture": "#metal", "uv": [ 0.0, 0.0, 8.0, 1.0 ] },
38- "west": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.0, 1.0 ] },
39- "up": { "texture": "#metal", "uv": [ 0.0, 0.0, 8.0, 1.0 ] },
40- "down": { "texture": "#metal", "uv": [ 0.0, 0.0, 8.0, 1.0 ] }
35+ "north": { "texture": "#metal", "uv": [ 7.5, 12.5, 15.5, 13.5 ] },
36+ "east": { "texture": "#metal", "uv": [ 7.0, 8.0, 8.0, 9.0 ] },
37+ "south": { "texture": "#metal", "uv": [ 1.5, 3.0, 9.5, 4.0 ] },
38+ "west": { "texture": "#metal", "uv": [ 6.5, 6.0, 7.5, 7.0 ] },
39+ "up": { "texture": "#metal", "uv": [ 4.0, 4.5, 12.0, 5.5 ] },
40+ "down": { "texture": "#metal", "uv": [ 2.5, 6.5, 10.5, 7.5 ] }
4141 }
4242 },
4343 {
@@ -78,12 +78,12 @@
7878 "rotationX": -14.0,
7979 "rotationZ": -25.0,
8080 "faces": {
81- "north": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.5, 1.5 ] },
82- "east": { "texture": "#metal", "uv": [ 0.0, 0.0, 6.0, 1.5 ] },
83- "south": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.5, 1.5 ] },
84- "west": { "texture": "#metal", "uv": [ 0.0, 0.0, 6.0, 1.5 ] },
85- "up": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.5, 6.0 ] },
86- "down": { "texture": "#metal", "uv": [ 0.0, 0.0, 1.5, 6.0 ] }
81+ "north": { "texture": "#metal", "uv": [ 9.5, 3.5, 11.0, 5.0 ] },
82+ "east": { "texture": "#metal", "uv": [ 5.5, 5.5, 11.5, 7.0 ] },
83+ "south": { "texture": "#metal", "uv": [ 8.5, 9.5, 10.0, 11.0 ] },
84+ "west": { "texture": "#metal", "uv": [ 5.0, 7.0, 11.0, 8.5 ] },
85+ "up": { "texture": "#metal", "uv": [ 12.0, 5.5, 13.5, 11.5 ] },
86+ "down": { "texture": "#metal", "uv": [ 1.0, 5.5, 2.5, 11.5 ] }
8787 }
8888 },
8989 {
@@ -93,12 +93,12 @@
9393 "rotationOrigin": [ -1.0, 0.0, -1.0 ],
9494 "rotationY": -53.0,
9595 "faces": {
96- "north": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 0.5 ] },
97- "east": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.5, 0.5 ] },
98- "south": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 0.5 ] },
99- "west": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.5, 0.5 ] },
100- "up": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 3.5 ] },
101- "down": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 3.5 ] }
96+ "north": { "texture": "#metal", "uv": [ 3.5, 3.0, 4.0, 3.5 ] },
97+ "east": { "texture": "#metal", "uv": [ 7.5, 5.0, 11.0, 5.5 ] },
98+ "south": { "texture": "#metal", "uv": [ 4.5, 4.5, 5.0, 5.0 ] },
99+ "west": { "texture": "#metal", "uv": [ 7.0, 7.0, 10.5, 7.5 ] },
100+ "up": { "texture": "#metal", "uv": [ 6.5, 9.0, 7.0, 12.5 ] },
101+ "down": { "texture": "#metal", "uv": [ 6.0, 6.5, 6.5, 10.0 ] }
102102 }
103103 },
104104 {
@@ -169,11 +169,11 @@
169169 "rotationY": 174.0,
170170 "faces": {
171171 "north": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 0.5 ] },
172- "east": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.5, 0.5 ] },
172+ "east": { "texture": "#metal", "uv": [ 5.5, 3.5, 9.0, 4.0 ] },
173173 "south": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 0.5 ] },
174- "west": { "texture": "#metal", "uv": [ 0.0, 0.0, 3.5, 0.5 ] },
175- "up": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 3.5 ] },
176- "down": { "texture": "#metal", "uv": [ 0.0, 0.0, 0.5, 3.5 ] }
174+ "west": { "texture": "#metal", "uv": [ 4.5, 6.0, 8.0, 6.5 ] },
175+ "up": { "texture": "#metal", "uv": [ 6.5, 9.0, 7.0, 12.5 ] },
176+ "down": { "texture": "#metal", "uv": [ 4.5, 5.5, 5.0, 9.0 ] }
177177 }
178178 },
179179 {