#region License // Copyright (C) 2020 Reetus // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace ClassicAssist.UO.Data { public class Statics { private static string _dataPath; private static readonly Lazy[] _staticData = new Lazy[6]; private static int[,] _defaultMapSize { get; } = { { 7168, 4096 }, { 7168, 4096 }, { 2304, 1600 }, { 2560, 2048 }, { 1448, 1448 }, { 1280, 4096 } }; internal static void Initialize( string dataPath ) { _dataPath = dataPath; for ( int i = 0; i < 6; i++ ) { int map = i; _staticData[i] = new Lazy( () => LoadStatics( map ) ); } } private static StaticRecord[][] LoadStatics( int map ) { string staticIndexFile = Path.Combine( _dataPath, $"staidx{map}.mul" ); string staticMulFile = Path.Combine( _dataPath, $"statics{map}.mul" ); if ( !File.Exists( staticIndexFile ) ) { return null; } if ( !File.Exists( staticMulFile ) ) { return null; } byte[] indexBytes = File.ReadAllBytes( staticIndexFile ); StaticRecord[][] staticItems = new StaticRecord[indexBytes.Length / 12][]; using ( FileStream fileStream = new FileStream( staticMulFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) ) { using ( BinaryReader binaryReader = new BinaryReader( fileStream ) ) { for ( int x = 0; x < indexBytes.Length / 12; x++ ) { int offset = x * 12; int start = BitConverter.ToInt32( indexBytes, offset ); int length = BitConverter.ToInt32( indexBytes, offset + 4 ); if ( start == -1 ) { continue; } fileStream.Seek( start, SeekOrigin.Begin ); staticItems[x] = new StaticRecord[length / 7]; for ( int y = 0; y < length / 7; y++ ) { staticItems[x][y].ID = binaryReader.ReadUInt16(); staticItems[x][y].X = binaryReader.ReadByte(); staticItems[x][y].Y = binaryReader.ReadByte(); staticItems[x][y].Z = binaryReader.ReadSByte(); staticItems[x][y].Hue = binaryReader.ReadUInt16(); } } } } return staticItems; } public static StaticTile[] GetStatics( int map, int x, int y ) { if ( _staticData?[map]?.Value == null ) { return null; } int blockIndex = x / 8 * ( _defaultMapSize[map, 1] / 8 ) + y / 8; int cellX = x % 8; int cellY = y % 8; StaticRecord[] blockStatics = _staticData[map].Value[blockIndex]; if ( blockStatics == null ) { return null; } IEnumerable statics = blockStatics.Where( i => i.X == cellX && i.Y == cellY ); List tiles = new List(); foreach ( StaticRecord staticRecord in statics ) { StaticTile tile = TileData.GetStaticTile( staticRecord.ID ); tile.X = x; tile.Y = y; tile.Z = staticRecord.Z; tile.Hue = staticRecord.Hue; tiles.Add( tile ); } return tiles.ToArray(); } private struct StaticRecord { public ushort ID { get; set; } public byte X { get; set; } public byte Y { get; set; } public sbyte Z { get; set; } public int Hue { get; set; } } } }