311 lines
9.3 KiB
C#
311 lines
9.3 KiB
C#
using BrewMonster;
|
|
using BrewMonster.Network;
|
|
using CSNetwork.GPDataType;
|
|
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using UnityEngine;
|
|
|
|
public static class EC_Utility
|
|
{
|
|
public static byte glb_CompressDirH(float x, float z)
|
|
{
|
|
const float fInvInter = 256.0f / 360.0f;
|
|
|
|
if (Math.Abs(x) < 0.00001f)
|
|
{
|
|
if (z > 0.0f)
|
|
return 64;
|
|
else
|
|
return 192;
|
|
}
|
|
else
|
|
{
|
|
// atan2 trong C# trả về radian, cần đổi sang độ
|
|
float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI));
|
|
|
|
// đảm bảo góc nằm trong [0, 360)
|
|
if (fDeg < 0)
|
|
fDeg += 360.0f;
|
|
|
|
return (byte)(fDeg * fInvInter);
|
|
}
|
|
}
|
|
public static bool BinaryEquals<T1, T2>(T1 a, T2 b)
|
|
where T1 : struct
|
|
where T2 : struct
|
|
{
|
|
ReadOnlySpan<byte> bytesA = MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref a, 1));
|
|
ReadOnlySpan<byte> bytesB = MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref b, 1));
|
|
|
|
// if sizes differ → not equal
|
|
if (bytesA.Length != bytesB.Length)
|
|
return false;
|
|
|
|
return bytesA.SequenceEqual(bytesB);
|
|
}
|
|
public static float FIX8TOFLOAT(int x) => x / 256.0f;
|
|
public static T ByteArrayToStructure<T>(byte[] data) where T : struct
|
|
{
|
|
int size = Marshal.SizeOf(typeof(T));
|
|
if (data.Length < size)
|
|
throw new ArgumentException($"Data length {data.Length} < struct size {size}");
|
|
|
|
IntPtr ptr = Marshal.AllocHGlobal(size);
|
|
try
|
|
{
|
|
Marshal.Copy(data, 0, ptr, size);
|
|
return Marshal.PtrToStructure<T>(ptr);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(ptr);
|
|
}
|
|
}
|
|
public static Vector3 glb_DecompressDirH(byte byDir)
|
|
{
|
|
const float fInter = 360.0f / 256.0f;
|
|
float fRad = Mathf.Deg2Rad * (byDir * fInter);
|
|
|
|
Vector3 v;
|
|
v.x = Mathf.Cos(fRad);
|
|
v.z = Mathf.Sin(fRad);
|
|
v.y = 0.0f;
|
|
|
|
return v;
|
|
}
|
|
public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v)
|
|
{
|
|
return new System.Numerics.Vector3(v.x, v.y, v.z);
|
|
}
|
|
public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v)
|
|
{
|
|
return new A3DVECTOR3(v.x, v.y, v.z);
|
|
}
|
|
public static Vector3 ToVector3(A3DVECTOR3 a3DVECTOR3)
|
|
{
|
|
return new Vector3(a3DVECTOR3.x, a3DVECTOR3.y, a3DVECTOR3.z);
|
|
}
|
|
public static float MagnitudeH(this Vector3 v)
|
|
{
|
|
return Mathf.Sqrt(v.x * v.x + v.z * v.z);
|
|
}
|
|
public static string FixGBKString(string input)
|
|
{
|
|
// Giả sử input hiện đang là "Æð"
|
|
// B1: lấy bytes theo "Latin1" (mỗi ký tự 1 byte giữ nguyên giá trị gốc)
|
|
byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(input);
|
|
|
|
// B2: giải mã lại bằng GBK (Code page 936)
|
|
string decoded = Encoding.GetEncoding(936).GetString(bytes);
|
|
|
|
return decoded;
|
|
}
|
|
public static string BuildActionName(PLAYER_ACTION action, int weaponType, string tail = "")
|
|
{
|
|
string prefix = action.data.ActionPrefix ?? string.Empty;
|
|
string suffix = string.Empty;
|
|
|
|
if (action.data.action_weapon_suffix != null
|
|
&& weaponType >= 0
|
|
&& weaponType < action.data.action_weapon_suffix.Length)
|
|
{
|
|
suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
|
|
}
|
|
var tailFixed = FixGBKString(tail);
|
|
return $"{prefix}_{suffix}{tail}";
|
|
}
|
|
public static string BuildActionName(PLAYER_ACTION_INFO_CONFIG data, int weaponType, string midBody = "")
|
|
{
|
|
string prefix = data.ActionPrefix ?? string.Empty;
|
|
string suffix = string.Empty;
|
|
|
|
if (data.action_weapon_suffix != null
|
|
&& weaponType >= 0
|
|
&& weaponType < data.action_weapon_suffix.Length)
|
|
{
|
|
suffix = data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
|
|
}
|
|
var midBodyFixed = FixGBKString(midBody);
|
|
return $"{prefix}{midBodyFixed}{suffix}";
|
|
}
|
|
public static byte glb_BuildBLSMask()
|
|
{
|
|
byte byMask = 0;
|
|
CECConfigs pConfigs = EC_Game.GetConfigs();
|
|
|
|
/* if (pConfigs->GetGameSettings().bBls_NoRed)
|
|
byMask |= GP_BLSMASK_NORED;
|
|
|
|
if (pConfigs->GetGameSettings().bBls_NoMafia)
|
|
byMask |= GP_BLSMASK_NOMAFIA;
|
|
|
|
if (pConfigs->GetGameSettings().bBls_Self)
|
|
byMask |= GP_BLSMASK_SELF;
|
|
|
|
if (pConfigs->GetGameSettings().bBls_NoAlliance)
|
|
byMask |= GP_BLSMASK_NOALLIANCE;
|
|
|
|
if (pConfigs->GetGameSettings().bBls_NoForce)
|
|
byMask |= GP_BLSMASK_NOFORCE;*/
|
|
|
|
return byMask;
|
|
}
|
|
public static byte glb_BuildPVPMask(bool bForceAttack)
|
|
{
|
|
byte byMask = 0;
|
|
if (bForceAttack)
|
|
byMask |= (byte)PVP_mask.GP_PVPMASK_FORCE;
|
|
//else
|
|
//{
|
|
// CECConfigs* pConfigs = g_pGame->GetConfigs();
|
|
|
|
// if (pConfigs->GetGameSettings().bAtk_Player)
|
|
// {
|
|
// byMask |= GP_PVPMASK_FORCE;
|
|
|
|
// if (pConfigs->GetGameSettings().bAtk_NoMafia)
|
|
// byMask |= GP_PVPMASK_NOMAFIA;
|
|
|
|
// if (pConfigs->GetGameSettings().bAtk_NoWhite)
|
|
// byMask |= GP_PVPMASK_NOWHITE;
|
|
|
|
// if (pConfigs->GetGameSettings().bAtk_NoAlliance)
|
|
// byMask |= GP_PVPMASK_NOALLIANCE;
|
|
|
|
// if (pConfigs->GetGameSettings().bAtk_NoForce)
|
|
// byMask |= GP_PVPMASK_NOFORCE;
|
|
// }
|
|
//}
|
|
|
|
return byMask;
|
|
}
|
|
|
|
public static T a_ClampFloor<T>(T x, T min) where T : IComparable<T>
|
|
{
|
|
return (x.CompareTo(min) < 0) ? min : x;
|
|
}
|
|
|
|
public static T a_Min<T>(T x, T y) where T : IComparable<T>
|
|
{
|
|
return (y.CompareTo(x) < 0) ? y : x;
|
|
}
|
|
|
|
public static bool STRING_TO_A3DCOLOR(string str, out Color clr)
|
|
{
|
|
// ��� A3DCOLOR_TO_STRING ������ת��
|
|
// [English] Parse according to A3DCOLOR_TO_STRING conversion format
|
|
|
|
bool ret = false;
|
|
clr = Color.white;
|
|
|
|
byte[] rgb = new byte[6];
|
|
|
|
int nLen = str != null ? str.Length : 0;
|
|
while (nLen == 7)
|
|
{
|
|
// ����ĸ��ת����Сд
|
|
// [English] Convert uppercase letters to lowercase
|
|
str = str.ToLowerInvariant();
|
|
|
|
if (str[0] != '^')
|
|
break;
|
|
|
|
char c;
|
|
int i;
|
|
for (i = 1; i < nLen; ++i)
|
|
{
|
|
c = str[i];
|
|
if (c >= '0' && c <= '9')
|
|
{
|
|
rgb[i - 1] = (byte)(c - '0');
|
|
}
|
|
else if (c >= 'a' && c <= 'f')
|
|
{
|
|
rgb[i - 1] = (byte)(10 + (c - 'a'));
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (i < nLen)
|
|
break;
|
|
|
|
byte r = (byte)((rgb[0] << 4) + rgb[1]);
|
|
byte g = (byte)((rgb[2] << 4) + rgb[3]);
|
|
byte b = (byte)((rgb[4] << 4) + rgb[5]);
|
|
clr = new Color(r / 255f, g / 255f, b / 255f, 1f);
|
|
|
|
ret = true;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
// ===== Text/Color helpers moved from EC_InventoryUI =====
|
|
public static string FormatForLegacyText(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text))
|
|
return string.Empty;
|
|
|
|
StringBuilder result = new StringBuilder(text);
|
|
result.Replace("\\r", "\n");
|
|
return ProcessColorCodesForLegacy(result);
|
|
}
|
|
|
|
public static string FormatForTextMeshPro(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text))
|
|
return string.Empty;
|
|
|
|
StringBuilder result = new StringBuilder(text);
|
|
result.Replace("\\r", "\n");
|
|
return ProcessColorCodes(result);
|
|
}
|
|
|
|
public static string ProcessColorCodes(StringBuilder text)
|
|
{
|
|
string pattern = @"\^([0-9A-Fa-f]{6})";
|
|
return Regex.Replace(text.ToString(), pattern, match =>
|
|
{
|
|
string hexColor = match.Groups[1].Value;
|
|
return $"<color=#{hexColor}>";
|
|
}, RegexOptions.None);
|
|
}
|
|
|
|
public static string ProcessColorCodesForLegacy(StringBuilder text)
|
|
{
|
|
string pattern = @"\^([0-9A-Fa-f]{6})";
|
|
return Regex.Replace(text.ToString(), pattern, match =>
|
|
{
|
|
string hexColor = match.Groups[1].Value;
|
|
Color color = HexToColor(hexColor);
|
|
return $"<color=#{ColorUtility.ToHtmlStringRGB(color)}>";
|
|
}, RegexOptions.None);
|
|
}
|
|
|
|
private static Color HexToColor(string hex)
|
|
{
|
|
if (hex == null || hex.Length != 6)
|
|
return Color.white;
|
|
try
|
|
{
|
|
int r = Convert.ToInt32(hex.Substring(0, 2), 16);
|
|
int g = Convert.ToInt32(hex.Substring(2, 2), 16);
|
|
int b = Convert.ToInt32(hex.Substring(4, 2), 16);
|
|
return new Color(r / 255f, g / 255f, b / 255f, 1f);
|
|
}
|
|
catch
|
|
{
|
|
return Color.white;
|
|
}
|
|
}
|
|
}
|