public static void LiveFreeze(Mobile from, Map targetMap, Point3D start3d, Point3D end3d) { Dictionary <Point2D, List <Item> > ItemsByBlockLocation = new Dictionary <Point2D, List <Item> >(); if (targetMap != null && start3d != NullP3D && end3d != NullP3D) { Point2D start = targetMap.Bound(new Point2D(start3d)); Point2D end = targetMap.Bound(new Point2D(end3d)); IPooledEnumerable eable = targetMap.GetItemsInBounds(new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1)); Console.WriteLine(string.Format("Invoking live freeze from {0},{1} to {2},{3}", start.X, start.Y, end.X, end.Y)); foreach (Item item in eable) { if (item is Static || item is BaseFloor || item is BaseWall) { Map itemMap = item.Map; if (itemMap == null || itemMap == Map.Internal) { continue; } Point2D p = new Point2D(item.X >> 3, item.Y >> 3); if (!(ItemsByBlockLocation.ContainsKey(p))) { ItemsByBlockLocation.Add(p, new List <Item>()); } ItemsByBlockLocation[p].Add(item); } } eable.Free(); } else { from.SendMessage("That was not a proper area. Please retarget and reissue the command."); return; } TileMatrix matrix = targetMap.Tiles; foreach (KeyValuePair <Point2D, List <Item> > kvp in ItemsByBlockLocation) { StaticTile[][][] blockOfTiles = matrix.GetStaticBlock(kvp.Key.X, kvp.Key.Y); Dictionary <Point2D, List <StaticTile> > newBlockStatics = new Dictionary <Point2D, List <StaticTile> >(); foreach (Item item in kvp.Value) { int xOffset = item.X - (kvp.Key.X * 8); int yOffset = item.Y - (kvp.Key.Y * 8); if (xOffset < 0 || xOffset >= 8 || yOffset < 0 || yOffset >= 8) { continue; } StaticTile newTile = new StaticTile((ushort)item.ItemID, (byte)xOffset, (byte)yOffset, (sbyte)item.Z, (short)item.Hue); Point2D refPoint = new Point2D(xOffset, yOffset); if (!(newBlockStatics.ContainsKey(refPoint))) { newBlockStatics.Add(refPoint, new List <StaticTile>()); } newBlockStatics[refPoint].Add(newTile); item.Delete(); } for (int i = 0; i < blockOfTiles.Length; i++) { for (int j = 0; j < blockOfTiles[i].Length; j++) { for (int k = 0; k < blockOfTiles[i][j].Length; k++) { Point2D refPoint = new Point2D(i, j); if (!(newBlockStatics.ContainsKey(refPoint))) { newBlockStatics.Add(refPoint, new List <StaticTile>()); } newBlockStatics[refPoint].Add(blockOfTiles[i][j][k]); } } } StaticTile[][][] newblockOfTiles = new StaticTile[8][][]; for (int i = 0; i < 8; i++) { newblockOfTiles[i] = new StaticTile[8][]; for (int j = 0; j < 8; j++) { Point2D p = new Point2D(i, j); int length = 0; if (newBlockStatics.ContainsKey(p)) { length = newBlockStatics[p].Count; } newblockOfTiles[i][j] = new StaticTile[length]; for (int k = 0; k < length; k++) { if (newBlockStatics.ContainsKey(p)) { newblockOfTiles[i][j][k] = newBlockStatics[p][k]; } } } } matrix.SetStaticBlock(kvp.Key.X, kvp.Key.Y, newblockOfTiles); int blockNum = ((kvp.Key.X * matrix.BlockHeight) + kvp.Key.Y); List <Mobile> candidates = new List <Mobile>(); int bX = kvp.Key.X * 8; int bY = kvp.Key.Y * 8; IPooledEnumerable eable = targetMap.GetMobilesInRange(new Point3D(bX, bY, 0)); foreach (Mobile m in eable) { if (m.Player) { candidates.Add(m); } } eable.Free(); CRC.InvalidateBlockCRC(targetMap.MapID, blockNum); foreach (Mobile m in candidates) { m.Send(new UpdateStaticsPacket(new Point2D(kvp.Key.X, kvp.Key.Y), m)); } MapChangeTracker.MarkStaticsBlockForSave(targetMap.MapID, kvp.Key); } }
private unsafe int PatchStatics(TileMatrix tileMatrix, string dataPath, string indexPath, string lookupPath) { using (FileStream fsData = FileManager.GetFile(dataPath)) { using (FileStream fsIndex = FileManager.GetFile(indexPath)) { using (FileStream fsLookup = FileManager.GetFile(lookupPath)) { BinaryReader indexReader = new BinaryReader(fsIndex); BinaryReader lookupReader = new BinaryReader(fsLookup); int count = (int)(indexReader.BaseStream.Length / 4); StaticTileList[][] lists = new StaticTileList[8][]; for (int x = 0; x < 8; ++x) { lists[x] = new StaticTileList[8]; for (int y = 0; y < 8; ++y) { lists[x][y] = new StaticTileList(); } } for (int i = 0; i < count; ++i) { int blockID = indexReader.ReadInt32(); int blockX = blockID / tileMatrix.BlockHeight; int blockY = blockID % tileMatrix.BlockHeight; int offset = lookupReader.ReadInt32(); int length = lookupReader.ReadInt32(); lookupReader.ReadInt32(); if (offset < 0 || length <= 0) { tileMatrix.SetStaticBlock(blockX, blockY, tileMatrix.EmptyStaticsBlock); continue; } fsData.Seek(offset, SeekOrigin.Begin); int tileCount = length / 7; if (m_TileBuffer.Length < tileCount) { m_TileBuffer = new StaticTile[tileCount]; } StaticTile[] staticTiles = m_TileBuffer; fixed (StaticTile* pStaticTiles = staticTiles) { SharedMethods.Read(fsData.SafeFileHandle, pStaticTiles, length); StaticTile* pCur = pStaticTiles, pEnd = pStaticTiles + tileCount; while (pCur < pEnd) { lists[pCur->X & 0x07][pCur->Y & 0x07].Add((short)((pCur->ID & 0x3FFF) + 0x4000), pCur->Z); pCur = pCur + 1; } StaticTile[][][] tiles = new StaticTile[8][][]; for (int x = 0; x < 8; ++x) { tiles[x] = new StaticTile[8][]; for (int y = 0; y < 8; ++y) { tiles[x][y] = lists[x][y].ToArray(); } } tileMatrix.SetStaticBlock(blockX, blockY, tiles); } } indexReader.Close(); lookupReader.Close(); return count; } } } }
public static void OnLoad() { Console.WriteLine("Loading Ultima Live map changes"); if (!Directory.Exists(UltimaLiveSettings.UltimaLiveMapChangesSavePath)) { Directory.CreateDirectory(UltimaLiveSettings.UltimaLiveMapChangesSavePath); } string[] filePaths = Directory.GetFiles(UltimaLiveSettings.UltimaLiveMapChangesSavePath, "*.live"); List <string> staticsPaths = new List <string>(); List <string> landPaths = new List <string>(); foreach (string s in filePaths) { if (s.Contains("map")) { landPaths.Add(s); } else if (s.Contains("statics")) { staticsPaths.Add(s); } } landPaths.Sort(); //read map blocks and apply them in order foreach (string s in landPaths) { BinaryReader reader = new BinaryReader(File.Open(Path.Combine(Core.BaseDirectory, s), FileMode.Open)); try { reader.BaseStream.Seek(0, SeekOrigin.Begin); int MapNumber = reader.ReadUInt16(); while (reader.BaseStream.Position < reader.BaseStream.Length) { int x = (int)reader.ReadInt16(); int y = (int)reader.ReadInt16(); LandTile[] blocktiles = new LandTile[64]; for (int j = 0; j < 64; j++) { short id = reader.ReadInt16(); sbyte z = reader.ReadSByte(); LandTile lt = new LandTile(id, z); blocktiles[j] = lt; } List <int> associated; MapRegistry.MapAssociations.TryGetValue(MapNumber, out associated); foreach (int integer in associated) { Map map = Map.Maps[integer]; TileMatrix tm = map.Tiles; tm.SetLandBlock(x, y, blocktiles); } } } catch { Console.WriteLine("An error occured reading land changes at " + reader.BaseStream.Position); } finally { reader.Close(); } } staticsPaths.Sort(); //read statics blocks and apply them in order foreach (string s in staticsPaths) { FileInfo mapFile = new FileInfo(Path.Combine(Core.BaseDirectory, s)); BinaryReader reader = new BinaryReader(File.Open(Path.Combine(Core.BaseDirectory, s), FileMode.Open)); try { reader.BaseStream.Seek(0, SeekOrigin.Begin); int MapNumber = reader.ReadUInt16(); while (reader.BaseStream.Position < reader.BaseStream.Length) { int blockX = (int)reader.ReadInt16(); int blockY = (int)reader.ReadInt16(); int staticCount = reader.ReadInt32(); Dictionary <Point2D, List <StaticTile> > blockStatics = new Dictionary <Point2D, List <StaticTile> >(); for (int staticIndex = 0; staticIndex < staticCount; staticIndex++) { UInt16 id = reader.ReadUInt16(); byte x = reader.ReadByte(); byte y = reader.ReadByte(); sbyte z = reader.ReadSByte(); Int16 hue = reader.ReadInt16(); StaticTile st = new StaticTile(id, x, y, z, hue); Point2D p = new Point2D(x, y); if (!(blockStatics.ContainsKey(p))) { blockStatics.Add(p, new List <StaticTile>()); } blockStatics[p].Add(st); } StaticTile[][][] newblockOfTiles = new StaticTile[8][][]; for (int i = 0; i < 8; i++) { newblockOfTiles[i] = new StaticTile[8][]; for (int j = 0; j < 8; j++) { Point2D p = new Point2D(i, j); int length = 0; if (blockStatics.ContainsKey(p)) { length = blockStatics[p].Count; } newblockOfTiles[i][j] = new StaticTile[length]; for (int k = 0; k < length; k++) { if (blockStatics.ContainsKey(p)) { newblockOfTiles[i][j][k] = blockStatics[p][k]; } } } } List <int> associated; MapRegistry.MapAssociations.TryGetValue(MapNumber, out associated); foreach (int integer in associated) { Map map = Map.Maps[integer]; TileMatrix tm = map.Tiles; tm.SetStaticBlock(blockX, blockY, newblockOfTiles); } } } catch { Console.WriteLine("An error occured reading land changes."); } finally { reader.Close(); } } }