using CommonAI.Zone.ZoneEditor; using CommonLang.IO; using ET; using System; using System.Collections.Generic; using System.IO; public class SceneDataLoader : ISceneDataLoader { public struct FileOffset { internal int position; internal int len; } static SceneData LoadFromStream(Stream stream, bool client_data, IExternalizableFactory factory) { var input = new InputStream(stream, factory); int typeID = input.GetS32(); Type type = factory.GetType(typeID); if (typeof(SceneData).Equals(type)) { var info = new SceneData(); if (client_data) { info.ReadExternalByClient(input); } else { info.ReadExternal(input); } return info; } else { Log.Error($"scene ex data read type({type}) error"); } return null; } private readonly MemoryStream binDataStream; private readonly Dictionary filesDic; public SceneDataLoader(byte[] binData) { if (binData == null) { binDataStream = null; return; } binDataStream = new MemoryStream(binData); filesDic = new Dictionary(); var br = new BinaryReader(binDataStream); var count = br.ReadInt32(); var names = new string[count]; var sizes = new int[count]; for (int i = 0; i < count; i++) { names[i] = br.ReadString(); sizes[i] = br.ReadInt32(); } var offset = (int)binDataStream.Position; for (int i = 0; i < count; i++) { filesDic[names[i]] = new FileOffset() { position = offset, len = sizes[i] }; offset += sizes[i]; } } private readonly MemoryStream msSceneDataCache = new MemoryStream(); private int preSceneDataId = 0; public SceneData Load(int sceneId, bool client_data, IExternalizableFactory factory) { if (binDataStream == null) { return null; } if (sceneId != preSceneDataId) { FileOffset fileOffset; if (!filesDic.TryGetValue(sceneId.ToString(), out fileOffset)) { return null; } binDataStream.Position = fileOffset.position; msSceneDataCache.Position = 0; //LZMAHelper.Decompress(binDataStream, fileOffset.len, msSceneDataCache); binDataStream.CopyTo(msSceneDataCache, fileOffset.len); preSceneDataId = sceneId; } msSceneDataCache.Position = 0; var sd = LoadFromStream(msSceneDataCache, client_data, factory); return sd; } }