Files
test/Assets/Scripts/EC_Utility.cs
T
2025-11-18 18:54:56 +07:00

218 lines
6.6 KiB
C#

using BrewMonster;
using CSNetwork.GPDataType;
using System;
using System.Collections;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using static CECPlayer;
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 byte[] UncompressData(byte[] compressedData, int expectedSize)
{
// Bỏ header zlib 2 byte (0x78 0x9C hoặc tương tự)
int start = 2;
int len = compressedData.Length - 6; // bỏ 4 byte ADLER32 cuối
using var ms = new MemoryStream(compressedData, start, len);
using var ds = new DeflateStream(ms, CompressionMode.Decompress);
using var outMs = new MemoryStream(expectedSize);
ds.CopyTo(outMs);
return outMs.ToArray();
}
public static int UncompressData(
byte[] compressedBuffer,
int compressedLength,
byte[] outBuffer,
ref uint outLength)
{
try
{
byte[] result = UncompressData(compressedBuffer, (int)outLength);
if (result.Length > outBuffer.Length)
return -1; // dest buffer quá nhỏ giống C++
Buffer.BlockCopy(result, 0, outBuffer, 0, result.Length);
outLength = (uint)result.Length;
return 0; // OK
}
catch (InvalidDataException)
{
return -2; // inflate failed
}
catch
{
return -2;
}
}
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}{tailFixed}";
}
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}";
}
// Build pvp mask
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;
}
}