mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
178 lines
5.8 KiB
C#
178 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Frozen;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Text.Json;
|
|
using Avalonia.Media;
|
|
using MinecraftClient.Mapping;
|
|
|
|
namespace MinecraftClient.Tui
|
|
{
|
|
public enum MobCategory
|
|
{
|
|
Hostile,
|
|
Passive,
|
|
Neutral,
|
|
Player,
|
|
NonLiving,
|
|
}
|
|
|
|
public enum MinimapPosition
|
|
{
|
|
top_left,
|
|
top_right,
|
|
center,
|
|
bottom_left,
|
|
bottom_right,
|
|
}
|
|
|
|
public sealed class NameDisplayConfig
|
|
{
|
|
public volatile bool Players = false;
|
|
public volatile bool Hostile = false;
|
|
public volatile bool Neutral = false;
|
|
public volatile bool Passive = false;
|
|
|
|
public bool AnyEnabled => Players || Hostile || Neutral || Passive;
|
|
|
|
public void SetAll(bool value)
|
|
{
|
|
Players = value;
|
|
Hostile = value;
|
|
Neutral = value;
|
|
Passive = value;
|
|
}
|
|
|
|
public bool ShouldShowName(MobCategory category) => category switch
|
|
{
|
|
MobCategory.Player => Players,
|
|
MobCategory.Hostile => Hostile,
|
|
MobCategory.Neutral => Neutral,
|
|
MobCategory.Passive => Passive,
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classifies entities into minimap categories using data extracted from
|
|
/// Minecraft's MobCategory assignments. Categories are loaded from the
|
|
/// embedded MinimapEntityCategories.json resource generated by
|
|
/// tools/gen_entity_category_map.py.
|
|
/// </summary>
|
|
public static class MinimapEntityClassifier
|
|
{
|
|
public static readonly Color HostileColor = Color.FromRgb(255, 68, 68);
|
|
public static readonly Color PassiveColor = Color.FromRgb(68, 255, 68);
|
|
public static readonly Color NeutralColor = Color.FromRgb(255, 170, 0);
|
|
public static readonly Color PlayerColor = Color.FromRgb(255, 255, 255);
|
|
public static readonly Color FadedGray = Color.FromRgb(100, 100, 100);
|
|
|
|
private static readonly FrozenDictionary<EntityType, MobCategory> CategoryTable;
|
|
|
|
static MinimapEntityClassifier()
|
|
{
|
|
var table = new Dictionary<EntityType, MobCategory>();
|
|
|
|
try
|
|
{
|
|
using var stream = Assembly.GetExecutingAssembly()
|
|
.GetManifestResourceStream("MinimapEntityCategories.json");
|
|
if (stream is not null)
|
|
{
|
|
using var doc = JsonDocument.Parse(stream);
|
|
var root = doc.RootElement;
|
|
|
|
LoadCategory(root, "hostile", MobCategory.Hostile, table);
|
|
LoadCategory(root, "passive", MobCategory.Passive, table);
|
|
LoadCategory(root, "neutral", MobCategory.Neutral, table);
|
|
LoadCategory(root, "non_living", MobCategory.NonLiving, table);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ConsoleIO.WriteLogLine($"[Minimap] Failed to load entity categories: {ex.Message}");
|
|
}
|
|
|
|
CategoryTable = table.ToFrozenDictionary();
|
|
}
|
|
|
|
private static void LoadCategory(JsonElement root, string key,
|
|
MobCategory category, Dictionary<EntityType, MobCategory> table)
|
|
{
|
|
if (!root.TryGetProperty(key, out var arr))
|
|
return;
|
|
|
|
foreach (var el in arr.EnumerateArray())
|
|
{
|
|
var name = el.GetString();
|
|
if (name is not null && Enum.TryParse<EntityType>(name, out var et))
|
|
table.TryAdd(et, category);
|
|
}
|
|
}
|
|
|
|
public static MobCategory Classify(EntityType type)
|
|
{
|
|
if (type == EntityType.Player)
|
|
return MobCategory.Player;
|
|
return CategoryTable.GetValueOrDefault(type, MobCategory.NonLiving);
|
|
}
|
|
|
|
public static Color GetBaseColor(MobCategory category) => category switch
|
|
{
|
|
MobCategory.Hostile => HostileColor,
|
|
MobCategory.Passive => PassiveColor,
|
|
MobCategory.Neutral => NeutralColor,
|
|
MobCategory.Player => PlayerColor,
|
|
_ => FadedGray,
|
|
};
|
|
|
|
public static Color ApplyDepthFade(Color baseColor, double playerY, double entityY)
|
|
{
|
|
double depth = playerY - entityY;
|
|
|
|
if (depth <= 5.0)
|
|
return baseColor;
|
|
|
|
if (depth >= 15.0)
|
|
return FadedGray;
|
|
|
|
double t = (depth - 5.0) / 10.0;
|
|
return Lerp(baseColor, FadedGray, t);
|
|
}
|
|
|
|
public static bool ShouldDisplay(MobCategory category, double playerY, double entityY)
|
|
{
|
|
if (category == MobCategory.Player)
|
|
return true;
|
|
if (entityY >= playerY)
|
|
return true;
|
|
return playerY - entityY <= 15.0;
|
|
}
|
|
|
|
public static int GetPriority(MobCategory category) => category switch
|
|
{
|
|
MobCategory.Hostile => 4,
|
|
MobCategory.Player => 3,
|
|
MobCategory.Neutral => 2,
|
|
MobCategory.Passive => 1,
|
|
_ => 0,
|
|
};
|
|
|
|
public static string GetCategoryLabel(MobCategory category) => category switch
|
|
{
|
|
MobCategory.Hostile => Translations.tui_minimap_legend_hostile,
|
|
MobCategory.Passive => Translations.tui_minimap_legend_passive,
|
|
MobCategory.Neutral => Translations.tui_minimap_legend_neutral,
|
|
MobCategory.Player => Translations.tui_minimap_legend_player,
|
|
_ => "?",
|
|
};
|
|
|
|
private static Color Lerp(Color a, Color b, double t)
|
|
{
|
|
byte r = (byte)(a.R + (b.R - a.R) * t);
|
|
byte g = (byte)(a.G + (b.G - a.G) * t);
|
|
byte bl = (byte)(a.B + (b.B - a.B) * t);
|
|
return Color.FromRgb(r, g, bl);
|
|
}
|
|
}
|
|
}
|