Skip to content

Commit 5a35dfe

Browse files
committed
Custom tribe previews implemented
1 parent 0b85239 commit 5a35dfe

File tree

2 files changed

+187
-127
lines changed

2 files changed

+187
-127
lines changed

src/ModLoader.cs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.IO.Compression;
1212
using System.Reflection;
1313
using System.Text.Json;
14+
using System.Text.Json.Serialization;
1415
using System.Text.RegularExpressions;
1516
using UnityEngine;
1617

@@ -51,7 +52,13 @@ public string GetPrettyStatus()
5152
}
5253
}
5354

54-
public record Preview(); //TODO: preview structure
55+
public record PreviewTile(
56+
int? idx = null,
57+
Polytopia.Data.TerrainData.Type terrainType = Polytopia.Data.TerrainData.Type.None,
58+
ResourceData.Type resourceType = Polytopia.Data.ResourceData.Type.None,
59+
UnitData.Type unitType = Polytopia.Data.UnitData.Type.None,
60+
ImprovementData.Type improvementType = Polytopia.Data.ImprovementData.Type.None
61+
);
5562

5663
private static int autoidx = Plugin.AUTOIDX_STARTS_FROM;
5764
private static readonly Stopwatch stopwatch = new();
@@ -61,6 +68,7 @@ public record Preview(); //TODO: preview structure
6168
public static Dictionary<int, string> gldDictionaryInversed = new();
6269
public static Dictionary<string, Mod> mods = new();
6370
public static Dictionary<int, int> climateToTribeData = new();
71+
public static Dictionary<string, List<PreviewTile>> tribePreviews = new();
6472
public static int climateAutoidx = (int)Enum.GetValues(typeof(TribeData.Type)).Cast<TribeData.Type>().Last();
6573
public static bool shouldInitializeSprites = true;
6674

@@ -362,12 +370,6 @@ private static void GameLogicDataPatch(JObject gld, JObject patch)
362370
skins.Merge(originalSkins);
363371
}
364372
}
365-
366-
if (token["preview"] != null)
367-
{
368-
Preview? preview = JsonSerializer.Deserialize<Preview>(token["preview"].ToString());
369-
//TODO: use preview
370-
}
371373
}
372374

373375
foreach (JToken jtoken in patch.SelectTokens("$.*.*").ToArray())
@@ -413,6 +415,29 @@ private static void GameLogicDataPatch(JObject gld, JObject patch)
413415
}
414416
}
415417

418+
foreach (JToken jtoken in patch.SelectTokens("$.tribeData.*").ToArray())
419+
{
420+
JObject token = jtoken.Cast<JObject>();
421+
422+
if (token["preview"] != null)
423+
{
424+
var options = new JsonSerializerOptions
425+
{
426+
Converters =
427+
{
428+
new JsonStringEnumConverter()
429+
}
430+
};
431+
432+
List<PreviewTile>? preview = JsonSerializer.Deserialize<List<PreviewTile>>(token["preview"].ToString(), options); // TODO: FIX CUSTOM ENUM VALUES
433+
434+
if (preview != null)
435+
{
436+
tribePreviews[GetJTokenName(token)] = preview;
437+
}
438+
}
439+
}
440+
416441
gld.Merge(patch, new() { MergeArrayHandling = MergeArrayHandling.Replace, MergeNullValueHandling = MergeNullValueHandling.Merge });
417442
}
418443

src/SpriteLoader.cs

Lines changed: 155 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Globalization;
12
using HarmonyLib;
23
using Polytopia.Data;
34
using UnityEngine;
@@ -131,72 +132,103 @@ private static void SpriteAtlasManager_GetSpriteFromAtlas(ref Sprite __result, S
131132
[HarmonyPatch(typeof(UIWorldPreview), nameof(UIWorldPreview.SetPreview), new Type[] { })]
132133
private static void UIWorldPreview_SetPreview(UIWorldPreview __instance) // TODO
133134
{
135+
if(Plugin.config.debug)
136+
{
137+
RectMask2D mask = __instance.gameObject.GetComponent<UnityEngine.UI.RectMask2D>();
138+
UnityEngine.GameObject.Destroy(mask);
139+
__instance.gameObject.transform.localScale = new Vector3(0.5f, 0.5f, 1f);
140+
__instance.gameObject.transform.position -= new Vector3(-5f, 35f, 0f);
141+
}
142+
134143
string style = EnumCache<TribeData.Type>.GetName(__instance.tribeData.type);
135144
if (__instance.skinType != SkinType.Default)
136145
{
137146
style = EnumCache<SkinType>.GetName(__instance.skinType);
138147
}
139-
foreach (UITile tile in __instance.tiles)
148+
149+
List<PolyMod.ModLoader.PreviewTile>? preview = null;
150+
if(ModLoader.tribePreviews.ContainsKey(style))
140151
{
141-
if ((int)__instance.tribeData.type >= Plugin.AUTOIDX_STARTS_FROM)
142-
{
143-
if ((tile.Position.x == -1 && tile.Position.y == 3) || (tile.Position.x == 1 && tile.Position.y == 2))
144-
{
145-
tile.Forest.gameObject.SetActive(true);
146-
tile.Animal.gameObject.SetActive(true);
147-
}
148-
else if ((tile.Position.x == -1 && tile.Position.y == -1) || (tile.Position.x == 1 && tile.Position.y == 5) || (tile.Position.x == 0 && tile.Position.y == 2))
149-
{
150-
tile.Mountain.gameObject.SetActive(true);
151-
}
152-
else if ((tile.Position.x == 0 && tile.Position.y == -1) || (tile.Position.x == 1 && tile.Position.y == 0))
153-
{
154-
tile.Resource.gameObject.SetActive(true);
155-
}
156-
}
157-
string terrainType = tile.Tile.sprite.name;
158-
if (terrainType == "ground")
159-
{
160-
terrainType = "field";
161-
}
162-
Sprite? tileSprite = ModLoader.GetSprite(terrainType, style);
163-
if (tileSprite != null)
164-
{
165-
tile.Tile.sprite = tileSprite;
166-
}
167-
Sprite? forestSprite = ModLoader.GetSprite("forest", style);
168-
if (forestSprite != null)
169-
{
170-
tile.Forest.sprite = forestSprite;
171-
}
172-
Sprite? mountainSprite = ModLoader.GetSprite("mountain", style);
173-
if (mountainSprite != null)
152+
preview = ModLoader.tribePreviews[style];
153+
}
154+
List<UITile> tiles = __instance.tiles.ToArray().ToList();
155+
List<UITile> sortedTiles = tiles
156+
.OrderBy(tile => tile.Position.y)
157+
.ThenBy(tile => tile.Position.x)
158+
.ToList();
159+
160+
int i = 0;
161+
foreach (UITile tile in sortedTiles)
162+
{
163+
if(Plugin.config.debug)
174164
{
175-
tile.Mountain.sprite = mountainSprite;
176-
tile.Mountain.transform.localScale = new Vector3(1f, 0.7f, 0);
165+
tile.DebugText.text = i.ToString();
166+
tile.DebugText.gameObject.SetActive(true);
177167
}
178-
string resourceType = EnumCache<Polytopia.Data.ResourceData.Type>.GetName(ResourceData.Type.Fruit).ToLower();
179-
foreach (var enumValue in Enum.GetValues<ResourceData.Type>())
168+
if(preview != null && preview.Count - 1 >= i)
180169
{
181-
string resource = EnumCache<Polytopia.Data.ResourceData.Type>.GetName((ResourceData.Type)enumValue).ToLower();
182-
if (tile.Resource.sprite.name.Contains(resource))
170+
ModLoader.PreviewTile? previewTile = preview.FirstOrDefault(tile => tile.idx == i); //TODO: FIX IDX
171+
if(previewTile != null)
183172
{
184-
resourceType = resource;
185-
break;
173+
tile.Tile.gameObject.SetActive(false);
174+
tile.Mountain.gameObject.SetActive(false);
175+
tile.Forest.gameObject.SetActive(false);
176+
tile.Resource.gameObject.SetActive(false);
177+
tile.Animal.gameObject.SetActive(false);
178+
tile.Improvement.gameObject.SetActive(false);
179+
180+
181+
SkinVisualsTransientData data = new SkinVisualsTransientData();
182+
data.tileClimateSettings = new TribeAndSkin(__instance.tribeData.type, __instance.skinType);
183+
UIUtils.SkinnedTerrainSprites skinnedTerrainSprites = UIUtils.GetTerrainSprite(data, previewTile.terrainType, GameManager.GetSpriteAtlasManager());
184+
if(skinnedTerrainSprites.groundTerrain != null)
185+
{
186+
tile.Tile.sprite = skinnedTerrainSprites.groundTerrain;
187+
}
188+
if(skinnedTerrainSprites.forestOrMountainTerrain != null)
189+
{
190+
tile.Mountain.sprite = skinnedTerrainSprites.forestOrMountainTerrain;
191+
tile.Forest.sprite = skinnedTerrainSprites.forestOrMountainTerrain;
192+
}
193+
switch(previewTile.terrainType)
194+
{
195+
case Polytopia.Data.TerrainData.Type.None:
196+
break;
197+
case Polytopia.Data.TerrainData.Type.Mountain:
198+
tile.Tile.gameObject.SetActive(true);
199+
tile.Mountain.gameObject.SetActive(true);
200+
break;
201+
case Polytopia.Data.TerrainData.Type.Forest:
202+
tile.Tile.gameObject.SetActive(true);
203+
tile.Forest.gameObject.SetActive(true);
204+
break;
205+
default:
206+
tile.Tile.gameObject.SetActive(true);
207+
break;
208+
}
209+
Sprite? resourceSprite = UIUtils.GetResourceSprite(data, previewTile.resourceType, GameManager.GetSpriteAtlasManager());
210+
if(resourceSprite != null)
211+
{
212+
tile.Animal.sprite = resourceSprite;
213+
tile.Resource.sprite = resourceSprite;
214+
}
215+
switch(previewTile.resourceType)
216+
{
217+
case Polytopia.Data.ResourceData.Type.Game:
218+
tile.Animal.gameObject.SetActive(true);
219+
break;
220+
default:
221+
tile.Resource.gameObject.SetActive(true);
222+
break;
223+
}
224+
if(previewTile.improvementType != Polytopia.Data.ImprovementData.Type.None)
225+
{
226+
tile.Improvement.sprite = UIUtils.GetImprovementSprite(previewTile.improvementType, __instance.tribeData.type, __instance.skinType, GameManager.GetSpriteAtlasManager()); // TODO: FIX
227+
tile.Improvement.gameObject.SetActive(true);
228+
}
186229
}
187230
}
188-
Sprite? resourceSprite = ModLoader.GetSprite(resourceType, style);
189-
if (resourceSprite != null)
190-
{
191-
tile.Resource.sprite = resourceSprite;
192-
tile.Resource.transform.localScale = new Vector3(0.6f, 1.2f, 0);
193-
}
194-
Sprite? animalSprite = ModLoader.GetSprite("game", style);
195-
if (animalSprite != null)
196-
{
197-
tile.Animal.sprite = animalSprite;
198-
tile.Animal.transform.localScale = new Vector3(0.9f, 0.6f, 0);
199-
}
231+
i++;
200232
}
201233
}
202234

@@ -269,75 +301,21 @@ private static void UIUnitRenderer_CreateUnit(UIUnitRenderer __instance)
269301
private static void UIUtils_GetTile(ref RectTransform __result, Polytopia.Data.TerrainData.Type type, int climate, SkinType skin)
270302
{
271303
RectTransform rectTransform = __result;
272-
Sprite? sprite;
273304
TribeData.Type tribeTypeFromStyle = GameManager.GameState.GameLogicData.GetTribeTypeFromStyle(climate);
274-
if (type == Polytopia.Data.TerrainData.Type.Mountain)
275-
{
276-
Sprite? fieldSprite;
277-
Sprite? mountainSprite;
278-
rectTransform = new GameObject
279-
{
280-
name = "UIMountainContainer"
281-
}.AddComponent<RectTransform>();
282-
283-
sprite = ModLoader.GetSprite("field", EnumCache<SkinType>.GetName(skin));
284-
if (sprite == null)
285-
{
286-
sprite = ModLoader.GetSprite("field", EnumCache<TribeData.Type>.GetName(tribeTypeFromStyle));
287-
if (sprite == null)
288-
{
289-
return;
290-
}
291-
}
292-
fieldSprite = sprite;
305+
SkinVisualsTransientData data = new SkinVisualsTransientData();
306+
data.tileClimateSettings = new TribeAndSkin(tribeTypeFromStyle, skin);
307+
UIUtils.SkinnedTerrainSprites skinnedTerrainSprites = UIUtils.GetTerrainSprite(data, type, GameManager.GetSpriteAtlasManager());
293308

294-
sprite = ModLoader.GetSprite("mountain", EnumCache<SkinType>.GetName(skin));
295-
if (sprite == null)
296-
{
297-
sprite = ModLoader.GetSprite(
298-
"mountain",
299-
EnumCache<TribeData.Type>.GetName(tribeTypeFromStyle)
300-
);
301-
if (sprite == null)
302-
{
303-
return;
304-
}
305-
}
306-
mountainSprite = sprite;
307-
Image fieldImage = UIUtils.GetImage();
308-
fieldImage.name = fieldSprite.name;
309-
fieldImage.sprite = fieldSprite;
310-
fieldImage.SetNativeSize();
311-
312-
Image mountainImage = UIUtils.GetImage();
313-
mountainImage.name = mountainSprite.name;
314-
mountainImage.sprite = mountainSprite;
315-
mountainImage.SetNativeSize();
316-
fieldImage.SetNativeSize();
317-
mountainImage.SetNativeSize();
318-
fieldImage.raycastTarget = false;
319-
mountainImage.raycastTarget = false;
320-
RectTransform rectTransform2 = fieldImage.rectTransform;
321-
RectTransform rectTransform3 = mountainImage.rectTransform;
322-
rectTransform2.SetParent(rectTransform, false);
323-
rectTransform3.SetParent(rectTransform, false);
324-
rectTransform2.anchoredPosition = Vector2.zero;
325-
rectTransform3.anchoredPosition = new Vector2(0.19f, 15.52f);
326-
}
327-
else
309+
int count = 0;
310+
foreach (Il2CppSystem.Object child in rectTransform)
328311
{
329-
Image image = UIUtils.GetImage();
330-
sprite = ModLoader.GetSprite(
331-
EnumCache<Polytopia.Data.TerrainData.Type>.GetName(type),
332-
EnumCache<TribeData.Type>.GetName(tribeTypeFromStyle)
333-
);
334-
if (sprite != null)
335-
{
336-
image.name = sprite.name;
337-
image.sprite = sprite;
338-
image.SetNativeSize();
339-
rectTransform = image.rectTransform;
340-
}
312+
Transform childTransform = child.Cast<Transform>();
313+
Image image = childTransform.GetComponent<Image>();
314+
Sprite? sprite = count == 0 ? skinnedTerrainSprites.groundTerrain : skinnedTerrainSprites.forestOrMountainTerrain;
315+
image.name = sprite.name;
316+
image.sprite = sprite;
317+
image.SetNativeSize();
318+
count++;
341319
}
342320
__result = rectTransform;
343321
}
@@ -358,6 +336,63 @@ private static void UIUtils_GetImprovementSprite(ref Sprite __result, Improvemen
358336
}
359337
}
360338

339+
[HarmonyPostfix]
340+
[HarmonyPatch(typeof(UIUtils), nameof(UIUtils.GetResourceSprite))]
341+
private static void UIUtils_GetResourceSprite(ref Sprite __result, SkinVisualsTransientData data, ResourceData.Type resource, SpriteAtlasManager atlasManager)
342+
{
343+
TribeData.Type tribe = data.tileClimateSettings.tribe;
344+
SkinType skin = data.tileClimateSettings.skin;
345+
string style = EnumCache<TribeData.Type>.GetName(tribe);
346+
if (skin != SkinType.Default)
347+
{
348+
style = EnumCache<SkinType>.GetName(skin);
349+
}
350+
Sprite? sprite = ModLoader.GetSprite(EnumCache<ResourceData.Type>.GetName(resource), style);
351+
if (sprite != null)
352+
{
353+
__result = sprite;
354+
}
355+
}
356+
357+
[HarmonyPostfix]
358+
[HarmonyPatch(typeof(UIUtils), nameof(UIUtils.GetTerrainSprite))]
359+
private static void UIUtils_GetTerrainSprite(ref UIUtils.SkinnedTerrainSprites __result, SkinVisualsTransientData data, Polytopia.Data.TerrainData.Type terrain, SpriteAtlasManager atlasManager)
360+
{
361+
TribeData.Type tribe = data.tileClimateSettings.tribe;
362+
SkinType skin = data.tileClimateSettings.skin;
363+
string style = EnumCache<TribeData.Type>.GetName(tribe);
364+
Sprite? sprite;
365+
Sprite? groundSprite = __result.groundTerrain;
366+
Sprite? forestOrMountainSprite = __result.forestOrMountainTerrain;
367+
if (skin != SkinType.Default)
368+
{
369+
style = EnumCache<SkinType>.GetName(skin);
370+
}
371+
if(terrain == Polytopia.Data.TerrainData.Type.Mountain || terrain == Polytopia.Data.TerrainData.Type.Forest)
372+
{
373+
sprite = ModLoader.GetSprite("field", style);
374+
if (sprite != null)
375+
{
376+
groundSprite = sprite;
377+
}
378+
sprite = ModLoader.GetSprite(EnumCache<Polytopia.Data.TerrainData.Type>.GetName(terrain), style);
379+
if (sprite != null)
380+
{
381+
forestOrMountainSprite = sprite;
382+
}
383+
}
384+
else
385+
{
386+
sprite = ModLoader.GetSprite(EnumCache<Polytopia.Data.TerrainData.Type>.GetName(terrain), style);
387+
if (sprite != null)
388+
{
389+
groundSprite = sprite;
390+
}
391+
}
392+
__result.groundTerrain = groundSprite;
393+
__result.forestOrMountainTerrain = forestOrMountainSprite;
394+
}
395+
361396
[HarmonyPostfix]
362397
[HarmonyPatch(typeof(CityRenderer), nameof(CityRenderer.GetHouse))]
363398
private static void CityRenderer_GetHouse(ref PolytopiaSpriteRenderer __result, CityRenderer __instance, TribeData.Type tribe, int type, SkinType skinType)

0 commit comments

Comments
 (0)