DONE: Fix compress method of AFILEPACKAGE

This commit is contained in:
MinhHai
2026-02-27 15:50:32 +07:00
parent a9eb777799
commit b342407c9f
7 changed files with 164 additions and 19 deletions
@@ -49,3 +49,5 @@ MonoBehaviour:
prefab: {fileID: 1126053271199039253, guid: 526d462bd8c87b74c9e461e80d028cb2, type: 3}
- id: DlgPlayerOptions
prefab: {fileID: 1813565726936289741, guid: a0e02be030755ab4a917523764fe4eef, type: 3}
- id: Win_Message2
prefab: {fileID: 1590197940424963217, guid: 0c248d0510a114829b58d62d2ecc3b5e, type: 3}
@@ -0,0 +1,84 @@
using System;
using System.Runtime.InteropServices;
using EditorAttributes;
// using NaughtyAttributes;
using UnityEngine;
namespace BrewMonster
{
public class TestByteNumber : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
[ContextMenu("Test")]
public void Test()
{
var origin = Marshal.SizeOf<EC_COMPUTER_AIDED_SETTING>();
var diff = Marshal.SizeOf<EC_GAME_SETTING>() - Marshal.SizeOf<EC_GAME_SETTING_TEST>();
BMLogger.Log($" Origin : {origin } - diff = {diff}"); // 255
}
[ContextMenu(" TestCompress")]
public void TestCompress()
{
int value = 123456;
byte[] src = BitConverter.GetBytes(value);
int dstLen = 10000;
byte[] dst = new byte[dstLen];
int res = AFilePackage.Compress( src, 0, src.Length, dst, 0, ref dstLen);
BMLogger.Log($" Res : {res} - srcLen = {src.Length} - dstLen = {dstLen} - compressed data: {BitConverter.ToString(dst, 0, dstLen)}");
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct EC_GAME_SETTING_TEST
{
[MarshalAs(UnmanagedType.U1)] public bool bNoTeamRequest;
[MarshalAs(UnmanagedType.U1)] public bool bNoTradeRequest;
[MarshalAs(UnmanagedType.U1)] public bool bTurnaround;
[MarshalAs(UnmanagedType.U1)] public bool bReverseWheel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_USERCHANNEL_NUM * 15,
ArraySubType = UnmanagedType.I1)] // GP_CHAT_MAX = 15; I1 = 1 byte per bool to match C++ bool[6][15]
public byte[] bChannel;
[MarshalAs(UnmanagedType.U1)]
public bool bAutoReply;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)]
public string szAutoReply;
[MarshalAs(UnmanagedType.U1)] public float fCamTurnSpeed;
public float fCamZoomSpeed;
public byte nFontSize;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_Player;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoMafia;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoWhite;
[MarshalAs(UnmanagedType.U1)] public bool bFontBold;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoRed;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoMafia;
[MarshalAs(UnmanagedType.U1)] public bool bBls_Self;
[MarshalAs(UnmanagedType.U1)] public bool bBlsRefuse_Neutral;
[MarshalAs(UnmanagedType.U1)] public bool bHideAutoGuide;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoAlliance;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoAlliance;
[MarshalAs(UnmanagedType.U1)] public bool bBlsRefuse_NonTeammate;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoForce;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoForce;
[MarshalAs(UnmanagedType.U1)] public bool bLockQuickBar;
[MarshalAs(UnmanagedType.U1)] public bool bPetAutoSkill;
[MarshalAs(UnmanagedType.U1)] public bool bAutoTeamForTask;
[MarshalAs(UnmanagedType.U1)] public bool bDisableAutoWikiHelp;
[MarshalAs(UnmanagedType.U1)] public bool bExclusiveAwardMode;
[MarshalAs(UnmanagedType.U1)] public bool bHideIceThunderBall;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 67551ceb317224e67b8140cbe7175c44
@@ -1515,7 +1515,7 @@ namespace CSNetwork
/// </summary>
public void SaveConfigData(byte[] pBuf, int len)
{
BMLogger.Log($"[MH] Session SaveConfigData len={len}");
BMLogger.Log($"[MH] Session.SaveConfigData | len={len}");
if (pBuf == null || len <= 0) return;
var p = new setuiconfig();
@@ -1526,7 +1526,7 @@ namespace CSNetwork
p.Ui_config = new Octets(slice);
// TODO: open later
return;
// return;
SendProtocol(p);
}
@@ -2000,5 +2000,17 @@ namespace CSNetwork
gamedatasend.Data = C2SCommandFactory.CreateDebugCmd(icmd, param1);
SendProtocol(gamedatasend);
}
// Cross-server get in (C++: c2s_CmdNPCSevCrossServerGetIn) — TODO: implement C2S packet when needed
public void c2s_CmdNPCSevCrossServerGetIn()
{
// TODO: C2SCommandFactory.CreateNPCSevCrossServerGetInCmd() and SendProtocol
}
// Cross-server get out (C++: c2s_CmdNPCSevCrossServerGetOut) — TODO: implement C2S packet when needed
public void c2s_CmdNPCSevCrossServerGetOut()
{
// TODO: C2SCommandFactory.CreateNPCSevCrossServerGetOutCmd() and SendProtocol
}
}
}
@@ -9,8 +9,8 @@ namespace BrewMonster
#if UNITY_EDITOR
private void Update()
{
// if (Input.GetKeyDown(KeyCode.S) )
// OnSkillDragDrop();
if (Input.GetKeyDown(KeyCode.S) )
OnSkillDragDrop();
}
#endif
public void OnSkillDragDrop()
@@ -35,29 +35,53 @@ namespace BrewMonster
}
/// <summary>
/// Compress data (raw deflate). Caller should allocate dst with size >= dstOffset + srcLen * 2 for safety.
/// 压缩数据(原始 deflate)。调用方应分配 dst 大小 >= dstOffset + srcLen * 2
/// Compress data in zlib format (2-byte header + deflate + 4-byte Adler-32), matching what UnCompress expects.
/// 压缩为 zlib 格式(2 字节头 + deflate + 4 字节 Adler-32),与 UnCompress 一致
/// </summary>
/// <param name="dstOffset">Start index in dst where compressed bytes are written. 压缩数据写入 dst 的起始下标。</param>
/// <param name="dstLen">On input max length; on output actual compressed length. 输入为最大长度,输出为实际压缩长度。</param>
/// <returns>0 ok, non-zero error</returns>
public static int Compress(byte[] src, int srcLen, byte[] dst, int dstOffset, ref int dstLen)
public static int Compress(byte[] src, int srcOffset, int srcLen, byte[] dst, int dstOffset, ref int dstLen)
{
try
{
using (var output = new MemoryStream())
// Raw deflate into temporary buffer (same as decompression uses DeflateStream)
byte[] deflateBytes;
using (var deflateOutput = new MemoryStream())
{
using (var deflate = new DeflateStream(output, CompressionLevel.Fastest))
using (var deflate = new DeflateStream(deflateOutput, CompressionLevel.Optimal))
{
deflate.Write(src, 0, srcLen);
deflate.Write(src, srcOffset, srcLen);
}
byte[] compressed = output.ToArray();
if (dstOffset + compressed.Length > dst.Length)
return Z_BUF_ERROR;
Buffer.BlockCopy(compressed, 0, dst, dstOffset, compressed.Length);
dstLen = compressed.Length;
return Z_OK;
deflateBytes = deflateOutput.ToArray();
}
// Zlib format: 2-byte header + deflate + 4-byte Adler-32 (matches ZlibUnCompressDeflate which skips 2, length-6)
const int zlibHeaderLen = 2;
const int zlibFooterLen = 4;
int totalLen = zlibHeaderLen + deflateBytes.Length + zlibFooterLen;
if (dstOffset + totalLen > dst.Length)
return Z_BUF_ERROR;
int writeAt = dstOffset;
// 2-byte zlib header (deflate, 32K window, default compression)
dst[writeAt++] = 0x78;
dst[writeAt++] = 0x9C;
Buffer.BlockCopy(deflateBytes, 0, dst, writeAt, deflateBytes.Length);
writeAt += deflateBytes.Length;
// 4-byte Adler-32 of uncompressed data (big-endian)
uint adler = Adler32(src, srcOffset, srcLen);
dst[writeAt++] = (byte)(adler >> 24);
dst[writeAt++] = (byte)(adler >> 16);
dst[writeAt++] = (byte)(adler >> 8);
dst[writeAt++] = (byte)(adler);
dstLen = totalLen;
return Z_OK;
}
catch (Exception e)
{
@@ -66,6 +90,19 @@ namespace BrewMonster
}
}
private static uint Adler32(byte[] data, int offset, int length)
{
const uint Mod = 65521u;
uint a = 1u, b = 0u;
for (int i = 0; i < length; i++)
{
byte c = data[offset + i];
a = (a + c) % Mod;
b = (b + a) % Mod;
}
return (b << 16) | a;
}
private static int ZlibUnCompress(byte[] dest, ref int destLen, byte[] source, int sourceLen)
{
try
+11 -3
View File
@@ -329,6 +329,8 @@ public partial class CECGameRun
/// <returns>True if loaded successfully / 加载成功返回true</returns>
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
{
BMLogger.Log($"MH CECGameRun.LoadConfigsFromServer, iDataSize = {iDataSize}");
if (pDataBuf == null || iDataSize == 0)
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, configs data is empty");
@@ -829,6 +831,7 @@ public partial class CECGameRun
// pData += sizeof (DWORD);
Buffer.BlockCopy(BitConverter.GetBytes(USERCFG_VERSION), 0, pDataBuf, offset, sizeof(uint));
offset += sizeof(uint);
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after version)");
// *((int*)pData) = iHostSize;
// pData += sizeof (int);
@@ -836,8 +839,9 @@ public partial class CECGameRun
// pData += iHostSize;
Buffer.BlockCopy(BitConverter.GetBytes(iHostSize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pHost.SaveConfigData(pDataBuf, ref iHostSize, offset);
pHost.SaveConfigData(pDataBuf, ref iHostSize, offset); // TODO: converted but need to check
offset += iHostSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after host config, iHostSize={iHostSize})");
// *((int*)pData) = (int)dwUISize;
// pData += sizeof (int);
@@ -847,6 +851,7 @@ public partial class CECGameRun
offset += sizeof(int);
pGameUI.GetUserLayout(pDataBuf, ref dwUISize); // TODO: Check if this is needed here
offset += (int)dwUISize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after UI layout, dwUISize={dwUISize})");
// *((int*)pData) = iSettingSize;
// pData += sizeof (int);
@@ -856,6 +861,7 @@ public partial class CECGameRun
offset += sizeof(int);
EC_Game.GetConfigs().SaveUserConfigData(pDataBuf, offset, out iSettingSize);
offset += iSettingSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after user config, iSettingSize={iSettingSize}), iTotalSize={iTotalSize}");
// if (m_pCfgDataBuf) {
// if (m_iCfgDataSize == iTotalSize && !memcmp(m_pCfgDataBuf, pDataBuf, iTotalSize)) { a_freetemp(pDataBuf); return 1; }
@@ -887,10 +893,12 @@ public partial class CECGameRun
// dwCompLen -= iVerLen;
// int iRes = AFilePackage::Compress(pSrc, iTotalSize - iVerLen, pDst, &dwCompLen);
int iVerLen = sizeof(uint);
int compLen = (iTotalSize - iVerLen) * 2;
// int compLen = (iTotalSize - iVerLen) * 2;
int compLen = iTotalSize * 2;
byte[] pCompBuf = new byte[iVerLen + compLen];
compLen -= iVerLen;
Buffer.BlockCopy(pDataBuf, 0, pCompBuf, 0, iVerLen);
int iRes = AFilePackage.Compress(pDataBuf, iTotalSize - iVerLen, pCompBuf, iVerLen, ref compLen);
int iRes = AFilePackage.Compress(pDataBuf, iVerLen,iTotalSize - iVerLen, pCompBuf, iVerLen, ref compLen);
// if (0 == iRes) { g_pGame->GetGameSession()->SaveConfigData(pCompBuf, dwCompLen+iVerLen); iRes = 2; }
// else { a_LogOutput(1, "CECGameRun::SaveConfigsToServer, Failed to compress config data (%d:%d)", iRes, iTotalSize); iRes = 0; }