Automap (client) [VS plugin mod]
リビジョン | c1220183978b395e68d28c9fc3a6c254bc07a3db (tree) |
---|---|
日時 | 2021-06-18 10:19:09 |
作者 | melchior <melchior@user...> |
コミッター | melchior |
1/2 Fix; Truncation of Protocol-buffer POI data
Auto-assigned Designators, Teleport tracking...
@@ -74,6 +74,10 @@ | ||
74 | 74 | <HintPath>VS_libs\Newtonsoft.Json.dll</HintPath> |
75 | 75 | <Private>False</Private> |
76 | 76 | </Reference> |
77 | + <Reference Include="0Harmony"> | |
78 | + <HintPath>VS_libs\0Harmony.dll</HintPath> | |
79 | + <Private>False</Private> | |
80 | + </Reference> | |
77 | 81 | </ItemGroup> |
78 | 82 | <ItemGroup> |
79 | 83 | <Compile Include="AutomapMod.cs" /> |
@@ -3,6 +3,9 @@ using System.Collections.Generic; | ||
3 | 3 | using System.Collections.ObjectModel; |
4 | 4 | using System.Drawing; |
5 | 5 | using System.Runtime.Serialization; |
6 | +using System.Linq; | |
7 | + | |
8 | +using HarmonyLib; | |
6 | 9 | |
7 | 10 | using Newtonsoft.Json; |
8 | 11 |
@@ -63,31 +66,20 @@ namespace Automap | ||
63 | 66 | |
64 | 67 | public override string ToString() |
65 | 68 | { |
66 | - return Pattern.ToShortString() + "|" + OverwriteColor.Name + "|" + Material ?? ""; | |
69 | + return $"{Pattern.ToShortString()} | {OverwriteColor.Name} | {(Material.HasValue ? Material.ToString() : "?")} | [{SpecialActionName}]"; | |
67 | 70 | } |
68 | 71 | |
69 | 72 | [OnDeserialized] |
70 | 73 | public void RelinkDesignator(StreamingContext sCtx ) |
71 | - { | |
72 | - //TODO: properly Via reflection - and support for external designators? | |
74 | + { | |
73 | 75 | if (SpecialAction == null && !String.IsNullOrEmpty(SpecialActionName)) { |
74 | - switch (SpecialActionName) { | |
75 | - | |
76 | - case "DecodeSign": | |
77 | - SpecialAction = DefaultDesignators.DecodeSign; | |
78 | - break; | |
79 | - | |
80 | - case "DecodePostSign": | |
81 | - SpecialAction = DefaultDesignators.DecodePostSign; | |
82 | - break; | |
83 | - | |
84 | - case "DecodeTranslocator": | |
85 | - SpecialAction = DefaultDesignators.DecodeTranslocator; | |
86 | - break; | |
87 | - | |
88 | - } | |
89 | - } | |
76 | + //TODO: still not truely dynamic... | |
90 | 77 | |
78 | + BlockDesignator delegateTarget = DefaultDesignators.DefaultBlockDesignators.FirstOrDefault((BlockDesignator arg) => arg.SpecialActionName == SpecialActionName); | |
79 | + | |
80 | + if (delegateTarget != null) this.SpecialAction = delegateTarget?.SpecialAction; | |
81 | + | |
82 | + } | |
91 | 83 | } |
92 | 84 | } |
93 | 85 | } |
@@ -3,6 +3,7 @@ using System.Collections.Generic; | ||
3 | 3 | using System.Collections.ObjectModel; |
4 | 4 | using System.Drawing; |
5 | 5 | using System.Runtime.Serialization; |
6 | +using System.Linq; | |
6 | 7 | |
7 | 8 | using Newtonsoft.Json; |
8 | 9 |
@@ -68,19 +69,18 @@ namespace Automap | ||
68 | 69 | [OnDeserialized] |
69 | 70 | public void RelinkDesignator(StreamingContext sCtx) |
70 | 71 | { |
71 | - //TODO: properly Via reflection - and support for external designators? | |
72 | - if (SpecialAction == null && !String.IsNullOrEmpty(SpecialActionName)) { | |
73 | - switch (SpecialActionName) { | |
72 | + | |
73 | + if (SpecialAction == null && !String.IsNullOrEmpty(SpecialActionName)) | |
74 | + { | |
75 | + //TODO: still not truely dynamic... | |
74 | 76 | |
75 | - case "KeepTrackOfMerchant": | |
76 | - SpecialAction = DefaultDesignators.KeepTrackOfMerchant; | |
77 | - break; | |
77 | + EntityDesignator delegateTarget = DefaultDesignators.DefaultEntityDesignators.FirstOrDefault((EntityDesignator arg) => arg.SpecialActionName == SpecialActionName); | |
78 | 78 | |
79 | - | |
80 | - } | |
81 | - } | |
79 | + if (delegateTarget != null) this.SpecialAction = delegateTarget?.SpecialAction; | |
82 | 80 | |
81 | + } | |
83 | 82 | } |
83 | + | |
84 | 84 | } |
85 | 85 | } |
86 | 86 |
@@ -35,8 +35,8 @@ namespace Automap | ||
35 | 35 | { |
36 | 36 | |
37 | 37 | if (defaults) { |
38 | - BlockDesignators = DefaultDesignators.DefaultBlockDesignators( ); | |
39 | - EntityDesignators= DefaultDesignators.DefaultEntityDesignators( ); | |
38 | + BlockDesignators = DefaultDesignators.DefaultBlockDesignators; | |
39 | + EntityDesignators= DefaultDesignators.DefaultEntityDesignators; | |
40 | 40 | } |
41 | 41 | |
42 | 42 | } |
@@ -3,7 +3,7 @@ using System.Collections.Generic; | ||
3 | 3 | using System.Drawing; |
4 | 4 | using System.Text; |
5 | 5 | using System.Text.RegularExpressions; |
6 | - | |
6 | +using HarmonyLib; | |
7 | 7 | using Vintagestory.API.Client; |
8 | 8 | using Vintagestory.API.Common; |
9 | 9 | using Vintagestory.API.Common.Entities; |
@@ -14,7 +14,9 @@ using Vintagestory.GameContent; | ||
14 | 14 | namespace Automap |
15 | 15 | { |
16 | 16 | public static class DefaultDesignators |
17 | - { | |
17 | + { | |
18 | + #region Defaults | |
19 | + | |
18 | 20 | public static BlockDesignator Roads = |
19 | 21 | new BlockDesignator( |
20 | 22 | new AssetLocation("game", "stonepath"), |
@@ -54,6 +56,14 @@ namespace Automap | ||
54 | 56 | DecodeTranslocator |
55 | 57 | ); |
56 | 58 | |
59 | + public static BlockDesignator Teleporters = | |
60 | + new BlockDesignator( | |
61 | + new AssetLocation("game", "teleporterbase"), | |
62 | + Color.SeaGreen, | |
63 | + EnumBlockMaterial.Wood, | |
64 | + DecodeTeleport | |
65 | + ); | |
66 | + | |
57 | 67 | public static EntityDesignator Traders = |
58 | 68 | new EntityDesignator( |
59 | 69 | new AssetLocation("game", "humanoid-trader"), |
@@ -66,163 +76,200 @@ namespace Automap | ||
66 | 76 | /// Not just blocks, but block-entities as well! |
67 | 77 | /// </summary> |
68 | 78 | /// <returns>The block designators.</returns> |
69 | - public static List<BlockDesignator> DefaultBlockDesignators() | |
79 | + public static List<BlockDesignator> DefaultBlockDesignators | |
70 | 80 | { |
71 | - return new List<BlockDesignator>{ | |
72 | - DefaultDesignators.Roads, | |
73 | - DefaultDesignators.GroundSigns, | |
74 | - DefaultDesignators.WallSigns, | |
75 | - DefaultDesignators.PostSigns, | |
76 | - DefaultDesignators.Translocators, | |
77 | - }; | |
81 | + get | |
82 | + { | |
83 | + return new List<BlockDesignator>{ | |
84 | + DefaultDesignators.Roads, | |
85 | + DefaultDesignators.GroundSigns, | |
86 | + DefaultDesignators.WallSigns, | |
87 | + DefaultDesignators.PostSigns, | |
88 | + DefaultDesignators.Translocators, | |
89 | + DefaultDesignators.Teleporters, | |
90 | + }; | |
91 | + } | |
78 | 92 | } |
79 | 93 | |
80 | - public static List<EntityDesignator> DefaultEntityDesignators() | |
94 | + public static List<EntityDesignator> DefaultEntityDesignators | |
81 | 95 | { |
82 | - return new List<EntityDesignator>{ | |
83 | - DefaultDesignators.Traders, | |
84 | - }; | |
96 | + get | |
97 | + { | |
98 | + return new List<EntityDesignator>{ | |
99 | + DefaultDesignators.Traders, | |
100 | + }; | |
101 | + } | |
85 | 102 | } |
86 | 103 | |
104 | + #endregion | |
105 | + | |
106 | + | |
87 | 107 | #region Designators |
88 | 108 | |
89 | 109 | internal static void DecodeSign(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block) |
90 | 110 | { |
91 | 111 | #if DEBUG |
92 | - clientAPI.Logger.VerboseDebug("Sign Designator Invoked!"); | |
112 | + clientAPI.Logger.VerboseDebug("Sign Designator Invoked!"); | |
93 | 113 | #endif |
94 | - //sign Text into a POI field... | |
95 | - BlockEntitySign signEntity = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntitySign; | |
114 | + //sign Text into a POI field... | |
115 | + BlockEntitySign signEntity = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntitySign; | |
96 | 116 | |
97 | - if (signEntity != null && !String.IsNullOrEmpty(signEntity.text)) | |
98 | - { | |
117 | + if (signEntity != null && !String.IsNullOrEmpty(signEntity.text)) { | |
99 | 118 | |
100 | - poi.AddReplace( | |
101 | - new PointOfInterest | |
102 | - { | |
103 | - Name = "Sign", | |
104 | - PrettyLocation = posn.PrettyCoords(clientAPI), | |
105 | - Location = posn.Copy(), | |
106 | - Notes = signEntity.text, | |
107 | - Timestamp = DateTime.UtcNow, | |
108 | - } | |
109 | - ); | |
110 | - } | |
119 | + poi.AddReplace( | |
120 | + new PointOfInterest { | |
121 | + Name = "Sign", | |
122 | + PrettyLocation = posn.PrettyCoords(clientAPI), | |
123 | + Location = posn.Copy( ), | |
124 | + Notes = signEntity.text, | |
125 | + Timestamp = DateTime.UtcNow, | |
126 | + } | |
127 | + ); | |
128 | + } | |
111 | 129 | } |
112 | 130 | |
113 | 131 | |
114 | 132 | internal static void DecodePostSign(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block) |
115 | 133 | { |
116 | 134 | #if DEBUG |
117 | - clientAPI.Logger.VerboseDebug("Post-sign Designator Invoked!"); | |
135 | + clientAPI.Logger.VerboseDebug("Post-sign Designator Invoked!"); | |
118 | 136 | #endif |
119 | - //sign post Text into a POI field... | |
120 | - BlockEntitySignPost signEntity = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntitySignPost; | |
137 | + //sign post Text into a POI field... | |
138 | + BlockEntitySignPost signEntity = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntitySignPost; | |
121 | 139 | |
122 | - if (signEntity != null && signEntity.textByCardinalDirection?.Length > 0) | |
123 | - { | |
140 | + if (signEntity != null && signEntity.textByCardinalDirection?.Length > 0) { | |
124 | 141 | |
125 | - poi.AddReplace( | |
126 | - new PointOfInterest | |
127 | - { | |
128 | - Name = "Signpost", | |
129 | - PrettyLocation = posn.PrettyCoords(clientAPI), | |
130 | - Location = posn.Copy(), | |
131 | - Notes = string.Join(",", signEntity.textByCardinalDirection), | |
132 | - Timestamp = DateTime.UtcNow, | |
133 | - } | |
134 | - ); | |
135 | - } | |
142 | + poi.AddReplace( | |
143 | + new PointOfInterest { | |
144 | + Name = "Signpost", | |
145 | + PrettyLocation = posn.PrettyCoords(clientAPI), | |
146 | + Location = posn.Copy( ), | |
147 | + Notes = string.Join(",", signEntity.textByCardinalDirection), | |
148 | + Timestamp = DateTime.UtcNow, | |
149 | + } | |
150 | + ); | |
151 | + } | |
136 | 152 | } |
137 | 153 | |
138 | 154 | internal static void KeepTrackOfMerchant(ICoreClientAPI clientAPI, EntitiesOfInterest poi, BlockPos posn, Entity entity) |
139 | 155 | { |
140 | - //clientAPI.Logger.VerboseDebug("Trader: {0} @ {1}", entity.GetName(), posn); | |
141 | - | |
142 | - var traderJoe = entity as EntityTrader; | |
143 | - var traderName = entity.GetBehavior<EntityBehaviorNameTag>()?.DisplayName; | |
144 | - string code; | |
145 | - // this makes me ill | |
146 | - switch (entity.Code.Path) { | |
147 | - case "humanoid-trader-artisan": | |
148 | - code = "{0} the artisan"; | |
149 | - break; | |
150 | - case "humanoid-trader-treasurehunter": | |
151 | - code = "{0} the treasure hunter"; | |
152 | - break; | |
153 | - case "humanoid-trader-buildmaterials": | |
154 | - code = "{0} the building materials trader"; | |
155 | - break; | |
156 | - case "humanoid-trader-clothing": | |
157 | - code = "{0} the clothing merchant"; | |
158 | - break; | |
159 | - case "humanoid-trader-commodities": | |
160 | - code = "{0} the commodities merchant"; | |
161 | - break; | |
162 | - case "humanoid-trader-foods": | |
163 | - code = "{0} the foods supplier"; | |
164 | - break; | |
165 | - case "humanoid-trader-furniture": | |
166 | - code = "{0} the furniture trader"; | |
167 | - break; | |
168 | - case "humanoid-trader-luxuries": | |
169 | - code = "{0} the luxuries merchant"; | |
170 | - break; | |
171 | - case "humanoid-trader-survivalgoods": | |
172 | - code = "{0} the survival goods supplier"; | |
173 | - break; | |
174 | - default: | |
175 | - code = ""; | |
176 | - break; | |
177 | - } | |
178 | - var message = string.Format(code, traderName); | |
179 | - if (traderJoe.TradeProps != null) | |
180 | - { | |
181 | - message += $" - Gears: {traderJoe.TradeProps.Money}, "; | |
182 | - } | |
183 | - poi.AddReplace(new EntityOfInterest | |
184 | - { | |
185 | - Name = "Trader", | |
186 | - PrettyLocation = posn.PrettyCoords(clientAPI), | |
187 | - Location = posn.Copy(), | |
188 | - Notes = message, | |
189 | - Timestamp = DateTime.UtcNow, | |
190 | - EntityId = entity.EntityId | |
191 | - }); | |
156 | + //clientAPI.Logger.VerboseDebug("Trader: {0} @ {1}", entity.GetName(), posn); | |
157 | + | |
158 | + var traderJoe = entity as EntityTrader; | |
159 | + var traderName = entity.GetBehavior<EntityBehaviorNameTag>( )?.DisplayName; | |
160 | + string code; | |
161 | + // this makes me ill | |
162 | + switch (entity.Code.Path) { | |
163 | + case "humanoid-trader-artisan": | |
164 | + code = "{0} the artisan"; | |
165 | + break; | |
166 | + case "humanoid-trader-treasurehunter": | |
167 | + code = "{0} the treasure hunter"; | |
168 | + break; | |
169 | + case "humanoid-trader-buildmaterials": | |
170 | + code = "{0} the building materials trader"; | |
171 | + break; | |
172 | + case "humanoid-trader-clothing": | |
173 | + code = "{0} the clothing merchant"; | |
174 | + break; | |
175 | + case "humanoid-trader-commodities": | |
176 | + code = "{0} the commodities merchant"; | |
177 | + break; | |
178 | + case "humanoid-trader-foods": | |
179 | + code = "{0} the foods supplier"; | |
180 | + break; | |
181 | + case "humanoid-trader-furniture": | |
182 | + code = "{0} the furniture trader"; | |
183 | + break; | |
184 | + case "humanoid-trader-luxuries": | |
185 | + code = "{0} the luxuries merchant"; | |
186 | + break; | |
187 | + case "humanoid-trader-survivalgoods": | |
188 | + code = "{0} the survival goods supplier"; | |
189 | + break; | |
190 | + default: | |
191 | + code = ""; | |
192 | + break; | |
193 | + } | |
194 | + var message = string.Format(code, traderName); | |
195 | + if (traderJoe.TradeProps != null) { | |
196 | + message += $" - Gears: {traderJoe.TradeProps.Money}, "; | |
197 | + } | |
198 | + poi.AddReplace(new EntityOfInterest { | |
199 | + Name = "Trader", | |
200 | + PrettyLocation = posn.PrettyCoords(clientAPI), | |
201 | + Location = posn.Copy( ), | |
202 | + Notes = message, | |
203 | + Timestamp = DateTime.UtcNow, | |
204 | + EntityId = entity.EntityId | |
205 | + }); | |
192 | 206 | } |
193 | 207 | |
194 | 208 | internal static void DecodeTranslocator(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block) |
195 | 209 | { |
196 | - #if DEBUG | |
210 | +#if DEBUG | |
197 | 211 | clientAPI.Logger.VerboseDebug("TRANSLOCATOR Designator Invoked!"); |
212 | +#endif | |
213 | + //Where to? and from! | |
214 | + | |
215 | + BlockEntityStaticTranslocator te = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntityStaticTranslocator; | |
216 | + | |
217 | + if (te != null) { | |
218 | + //FIXME: Delayed rescan ? | |
219 | + StringBuilder textTarget = new StringBuilder( ); | |
220 | + //translocatorEntity.GetBlockInfo(clientAPI.World.Player, textTarget); | |
221 | + textTarget.Append(te.FullyRepaired ? "Functional, " : "Broken, "); | |
222 | + textTarget.Append(te.Activated ? "Online, " : "Offline, "); | |
223 | + textTarget.Append(" Target: [ "); | |
224 | + textTarget.Append(te.TargetLocation != null ? "Set ]" : "Invalid ]");//Or ABS coords? | |
225 | + textTarget.AppendFormat(", Range ({0} ~ {1})", te.MinTeleporterRangeInBlocks, te.MaxTeleporterRangeInBlocks); | |
226 | + poi.AddReplace( | |
227 | + new PointOfInterest { | |
228 | + Name = "Translocator", | |
229 | + PrettyLocation = posn.PrettyCoords(clientAPI), | |
230 | + Location = posn.Copy( ), | |
231 | + Notes = textTarget.ToString( ), | |
232 | + Timestamp = DateTime.UtcNow, | |
233 | + Destination = te.TargetLocation != null ? new BlockPosJson(te.TargetLocation.Copy( )) : null | |
234 | + } | |
235 | + ); | |
236 | + } | |
237 | + } | |
238 | + | |
239 | + | |
240 | + internal static void DecodeTeleport(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block) | |
241 | + { | |
242 | + #if DEBUG | |
243 | + clientAPI.Logger.VerboseDebug("Teleport Designator Invoked!"); | |
198 | 244 | #endif |
199 | - //Where to? and from! | |
245 | + | |
200 | 246 | |
201 | - BlockEntityStaticTranslocator te = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntityStaticTranslocator; | |
247 | + BlockEntityTeleporter tele = clientAPI.World.BlockAccessor.GetBlockEntity(posn) as BlockEntityTeleporter; | |
202 | 248 | |
203 | - if (te != null) | |
249 | + if (tele != null) | |
204 | 250 | { |
205 | - //FIXME: Delayed rescan ? | |
206 | - StringBuilder textTarget = new StringBuilder(); | |
207 | - //translocatorEntity.GetBlockInfo(clientAPI.World.Player, textTarget); | |
208 | - textTarget.Append(te.FullyRepaired ? "Functional, " : "Broken, "); | |
209 | - textTarget.Append(te.Activated ? "Online, " : "Offline, "); | |
210 | - textTarget.Append(" Target: [ "); | |
211 | - textTarget.Append(te.TargetLocation != null ? "Set ]" : "Invalid ]");//Or ABS coords? | |
212 | - textTarget.AppendFormat(", Range ({0} ~ {1})", te.MinTeleporterRangeInBlocks, te.MaxTeleporterRangeInBlocks); | |
213 | - poi.AddReplace( | |
214 | - new PointOfInterest | |
215 | - { | |
216 | - Name = "Translocator", | |
217 | - PrettyLocation = posn.PrettyCoords(clientAPI), | |
218 | - Location = posn.Copy(), | |
219 | - Notes = textTarget.ToString(), | |
220 | - Timestamp = DateTime.UtcNow, | |
221 | - Destination = te.TargetLocation != null ? new BlockPosJson(te.TargetLocation.Copy()) : null | |
222 | - } | |
223 | - ); | |
251 | + //TeleporterManager teleManager = clientAPI.ModLoader.GetModSystem<TeleporterManager>(); | |
252 | + TeleporterLocation location = AccessTools.FieldRefAccess<BlockEntityTeleporter, TeleporterLocation>(tele, @"tpLocation");//TeleporterLocation tpLocation; | |
253 | + | |
254 | + if (location != null) | |
255 | + { | |
256 | + StringBuilder textTarget = new StringBuilder( ); | |
257 | + textTarget.Append(" Target: [ "); | |
258 | + textTarget.Append($" '{location.SourceName}' @ {location.SourcePos?.PrettyCoords(clientAPI)} -> '{location.TargetName}' @ {location.TargetPos?.PrettyCoords(clientAPI)} ");//Or ABS coords? | |
259 | + textTarget.Append(" ]"); | |
260 | + poi.AddReplace( | |
261 | + new PointOfInterest { | |
262 | + Name = "Teleport", | |
263 | + PrettyLocation = posn.PrettyCoords(clientAPI), | |
264 | + Location = posn.Copy( ), | |
265 | + Notes = textTarget.ToString( ), | |
266 | + Timestamp = DateTime.UtcNow, | |
267 | + Destination = location.TargetPos != null ? new BlockPosJson(location.TargetPos.Copy( )) : null | |
268 | + } | |
269 | + ); | |
224 | 270 | } |
225 | 271 | } |
272 | + } | |
226 | 273 | |
227 | 274 | #endregion |
228 | 275 | } |
@@ -116,7 +116,7 @@ namespace Automap | ||
116 | 116 | { |
117 | 117 | |
118 | 118 | #if DEBUG |
119 | - CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count); | |
119 | + //CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count); | |
120 | 120 | #endif |
121 | 121 | //If Brute force won't work; use GROOT FORCE! |
122 | 122 | //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0); |
@@ -159,7 +159,7 @@ namespace Automap | ||
159 | 159 | } |
160 | 160 | |
161 | 161 | #if DEBUG |
162 | - CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount); | |
162 | + //CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount); | |
163 | 163 | #endif |
164 | 164 | } |
165 | 165 |
@@ -399,7 +399,7 @@ namespace Automap | ||
399 | 399 | |
400 | 400 | if (this.POIs.Count > 0) |
401 | 401 | { |
402 | - using (var poiFile = File.OpenWrite(poiPath)) | |
402 | + using (var poiFile = File.Open(poiPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) | |
403 | 403 | { |
404 | 404 | Serializer.Serialize<PointsOfInterest>(poiFile, this.POIs); |
405 | 405 | } |
@@ -407,7 +407,7 @@ namespace Automap | ||
407 | 407 | |
408 | 408 | if (this.EOIs.Count > 0) |
409 | 409 | { |
410 | - using (var eoiFile = File.OpenWrite(eoiPath)) | |
410 | + using (var eoiFile = File.Open(eoiPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) | |
411 | 411 | { |
412 | 412 | Serializer.Serialize<EntitiesOfInterest>(eoiFile, this.EOIs); |
413 | 413 | } |
@@ -626,10 +626,10 @@ namespace Automap | ||
626 | 626 | |
627 | 627 | foreach (var blockEnt in worldChunk.BlockEntities) |
628 | 628 | { |
629 | - if (blockEnt.Value != null && blockEnt.Value.Block != null && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId)) | |
629 | + if (blockEnt.Key != null && blockEnt.Value != null && blockEnt.Value.Block != null && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId)) | |
630 | 630 | { |
631 | 631 | var designator = BlockID_Designators[blockEnt.Value.Block.BlockId]; |
632 | - designator.SpecialAction(ClientAPI, POIs, blockEnt.Value.Pos.Copy(), blockEnt.Value.Block); | |
632 | + designator?.SpecialAction(ClientAPI, POIs, blockEnt.Value.Pos.Copy(), blockEnt.Value.Block); | |
633 | 633 | } |
634 | 634 | } |
635 | 635 | } |
@@ -9,5 +9,5 @@ | ||
9 | 9 | "dependencies": { |
10 | 10 | "game": "1.14.10" |
11 | 11 | }, |
12 | - "website": "http://nowebsite.nope" | |
12 | + "website": "http://automap.osdn.io/" | |
13 | 13 | } |
\ No newline at end of file |