|
| 1 | +using Microsoft.Data.Sqlite; |
| 2 | +using System; |
| 3 | +using System.Collections.Generic; |
| 4 | +using System.IO; |
| 5 | +using System.Linq; |
| 6 | + |
| 7 | +namespace DynmapFilesToSQLite.Converter.Reader.impl { |
| 8 | + public class TilesReader : DynReader { |
| 9 | + private MapTypesReader mapTypesReader; |
| 10 | + private Dictionary<TileChunk, byte[]> tileHashes = new Dictionary<TileChunk, byte[]>(); |
| 11 | + private bool isJpeg; |
| 12 | + |
| 13 | + public TilesReader(DirectoryInfo myDir, MapTypesReader mapTypesReader, bool isJpeg) : base(myDir) { |
| 14 | + this.mapTypesReader = mapTypesReader; |
| 15 | + this.isJpeg = isJpeg; |
| 16 | + } |
| 17 | + |
| 18 | + public override void ExecuteSqliteCommands(SqliteTransaction transaction) { |
| 19 | + int x = 0; |
| 20 | + List<DirectoryInfo> worldNames = new List<DirectoryInfo>(); |
| 21 | + worldNames.AddRange(myDir.EnumerateDirectories().Where(dir => { |
| 22 | + return !dir.Name.Equals("_markers_") && !dir.Name.Equals("faces"); |
| 23 | + })); |
| 24 | + |
| 25 | + foreach (DirectoryInfo world in worldNames) { |
| 26 | + string worldName = world.Name; |
| 27 | + |
| 28 | + foreach (FileInfo hashFile in world.EnumerateFiles()) { |
| 29 | + if (!hashFile.Name.EndsWith(".hash")) |
| 30 | + continue; |
| 31 | + |
| 32 | + string hashFileName = hashFile.Name; |
| 33 | + |
| 34 | + byte[] hashBytes = File.ReadAllBytes(hashFile.FullName); |
| 35 | + string mapId = hashFileName.Split('_')[0]; |
| 36 | + int tcx = int.Parse(hashFileName.Split('_')[1]); |
| 37 | + int tcy = int.Parse(hashFileName.Split('_')[2].Split('.')[0]); |
| 38 | + |
| 39 | + tileHashes.Add(new TileChunk { |
| 40 | + tcx = tcx, |
| 41 | + tcy = tcy, |
| 42 | + type = new MapTypesReader.MapType { |
| 43 | + mapId = mapId, |
| 44 | + worldName = worldName, |
| 45 | + variant = "STANDARD" |
| 46 | + } |
| 47 | + }, hashBytes); |
| 48 | + } |
| 49 | + |
| 50 | + foreach (DirectoryInfo mapId in world.EnumerateDirectories()) { |
| 51 | + string mapIdName = mapId.Name; |
| 52 | + MapTypesReader.MapType mapType = new MapTypesReader.MapType { |
| 53 | + mapId = mapIdName, |
| 54 | + worldName = worldName, |
| 55 | + variant = "STANDARD" |
| 56 | + }; |
| 57 | + int mapTypeId = this.mapTypesReader.GetMapTypeId(mapType); |
| 58 | + |
| 59 | + foreach(DirectoryInfo chunkId in mapId.EnumerateDirectories()) { |
| 60 | + string chunkIdName = chunkId.Name; |
| 61 | + int tcx = int.Parse(chunkIdName.Split('_')[0]); |
| 62 | + int tcy = int.Parse(chunkIdName.Split('_')[1]); |
| 63 | + |
| 64 | + foreach(FileInfo tile in chunkId.EnumerateFiles()) { |
| 65 | + string tileName = tile.Name; |
| 66 | + int zoom = 0; |
| 67 | + int tx = 0; |
| 68 | + int ty = 0; |
| 69 | + |
| 70 | + if (tileName.StartsWith("z")) { |
| 71 | + zoom = tileName.Count(ch => ch == 'z'); |
| 72 | + } |
| 73 | + tx = int.Parse(tileName.Split('_')[zoom > 0 ? 1 : 0]); |
| 74 | + ty = int.Parse(tileName.Split('_')[zoom > 0 ? 2 : 1].Split('.')[0]); |
| 75 | + |
| 76 | + long crc = GetCRCFromTile(new TileChunk { |
| 77 | + tcx = tcx, |
| 78 | + tcy = tcy, |
| 79 | + type = mapType |
| 80 | + }, tx, ty); |
| 81 | + long lastUpdate = (long)File.GetLastWriteTimeUtc(tile.FullName).Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000L; |
| 82 | + |
| 83 | + SqliteCommand cmd = new SqliteCommand(); |
| 84 | + cmd.CommandText = "INSERT INTO Tiles VALUES (@MapId, @TX, @TY, @Zoom, @Hash, @LastUpdate, @Format, @ImageBytes);"; |
| 85 | + |
| 86 | + cmd.Parameters.AddWithValue("@MapId", mapTypeId); |
| 87 | + cmd.Parameters.AddWithValue("@TX", tx); |
| 88 | + cmd.Parameters.AddWithValue("@TY", ty); |
| 89 | + cmd.Parameters.AddWithValue("@Zoom", zoom); |
| 90 | + cmd.Parameters.AddWithValue("@Hash", crc); |
| 91 | + cmd.Parameters.AddWithValue("@LastUpdate", lastUpdate); |
| 92 | + cmd.Parameters.AddWithValue("@Format", isJpeg ? 1 : 0); |
| 93 | + cmd.Parameters.AddWithValue("@ImageBytes", File.ReadAllBytes(tile.FullName)); |
| 94 | + |
| 95 | + cmd.Transaction = transaction; |
| 96 | + cmd.Connection = transaction.Connection; |
| 97 | + cmd.ExecuteNonQuery(); |
| 98 | + |
| 99 | + } |
| 100 | + Console.WriteLine("Added new chunk tile: " + " " + tcx + " " + tcy + " " + worldName + " " + mapIdName); |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + // Transpiled from https://github.com/webbukkit/dynmap/blob/49ea99b7038bc855d7c70ae952c52399a3f82d21/DynmapCore/src/main/java/org/dynmap/storage/filetree/TileHashManager.java#L104 |
| 107 | + private long GetCRCFromTile(TileChunk chunk, int tx, int ty) { |
| 108 | + byte[] crcbuf = tileHashes[chunk]; |
| 109 | + |
| 110 | + int off = (128 * (ty & 0x1F)) + (4 * (tx & 0x1F)); |
| 111 | + long crc = 0; |
| 112 | + for (int i = 0; i < 4; i++) |
| 113 | + crc = (crc << 8) + (0xFF & crcbuf[off + i]); |
| 114 | + return crc; |
| 115 | + } |
| 116 | + |
| 117 | + private struct TileChunk { |
| 118 | + public int tcx, tcy; |
| 119 | + public MapTypesReader.MapType type; |
| 120 | + } |
| 121 | + } |
| 122 | +} |
0 commit comments