public LoadFromStream ( [ stream, NbtCompression compression ) : long | ||
stream | [ | Stream from which data will be loaded. If compression is set to AutoDetect, this stream must support seeking. |
compression | NbtCompression | Compression method to use for loading/saving this file. |
Résultat | long |
public void Load() { if (IsCorrupt || IsExternal) { return; } var stream = Region.GetStream(); stream.Seek(Offset + 4, SeekOrigin.Begin); int compression = stream.ReadByte(); if (compression == -1) { IsCorrupt = true; Remove(); } else { if ((compression & (1 << 7)) != 0) { IsExternal = true; ExternalCompression = (byte)compression; } else { var file = new fNbt.NbtFile(); try { file.LoadFromStream(stream, NbtCompression.AutoDetect); Compression = file.FileCompression; SetData(file.GetRootTag <NbtCompound>()); } catch { IsCorrupt = true; Remove(); } } } stream.Dispose(); OnLoaded?.Invoke(this, EventArgs.Empty); }
/// <summary> /// Retrieves the requested chunk from the region, or /// generates it if a world generator is provided. /// </summary> /// <param name="position">The position of the requested local chunk coordinates.</param> public Chunk GetChunk(Vector3 position) { // TODO: This could use some refactoring lock (Chunks) { if (!Chunks.ContainsKey(position)) { if (regionFile != null) { // Search the stream for that region lock (regionFile) { var chunkData = GetChunkFromTable(position); if (chunkData == null) { if (WorldGenerator == null) throw new ArgumentException("The requested chunk is not loaded.", "position"); GenerateChunk(position); return Chunks[position]; } regionFile.Seek(chunkData.Item1, SeekOrigin.Begin); int length = new MinecraftStream(regionFile).ReadInt32(); // TODO: Avoid making new objects here, and in the WriteInt32 int compressionMode = regionFile.ReadByte(); switch (compressionMode) { case 1: // gzip break; case 2: // zlib var nbt = new NbtFile(); nbt.LoadFromStream(regionFile, NbtCompression.ZLib, null); var chunk = Chunk.FromNbt(position, nbt); chunk.ParentRegion = this; Chunks.Add(position, chunk); break; default: throw new InvalidDataException("Invalid compression scheme provided by region file."); } } } else if (WorldGenerator == null) throw new ArgumentException("The requested chunk is not loaded.", "position"); else Chunks.Add(position, WorldGenerator.GenerateChunk(position, this)); } return Chunks[position]; } }
public static ChunkColumn GetChunk(ChunkCoordinates coordinates, string basePath, IWorldProvider generator, int yoffset) { int width = 32; int depth = 32; int rx = coordinates.X >> 5; int rz = coordinates.Z >> 5; string filePath = Path.Combine(basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz)); if (!File.Exists(filePath)) return generator.GenerateChunkColumn(coordinates); using (var regionFile = File.OpenRead(filePath)) { byte[] buffer = new byte[8192]; regionFile.Read(buffer, 0, 8192); int xi = (coordinates.X%width); if (xi < 0) xi += 32; int zi = (coordinates.Z%depth); if (zi < 0) zi += 32; int tableOffset = (xi + zi*width)*4; regionFile.Seek(tableOffset, SeekOrigin.Begin); byte[] offsetBuffer = new byte[4]; regionFile.Read(offsetBuffer, 0, 3); Array.Reverse(offsetBuffer); int offset = BitConverter.ToInt32(offsetBuffer, 0) << 4; int length = regionFile.ReadByte(); if (offset == 0 || length == 0) { return generator.GenerateChunkColumn(coordinates); } regionFile.Seek(offset, SeekOrigin.Begin); byte[] waste = new byte[4]; regionFile.Read(waste, 0, 4); int compressionMode = regionFile.ReadByte(); var nbt = new NbtFile(); nbt.LoadFromStream(regionFile, NbtCompression.ZLib); NbtTag dataTag = nbt.RootTag["Level"]; NbtList sections = dataTag["Sections"] as NbtList; ChunkColumn chunk = new ChunkColumn { x = coordinates.X, z = coordinates.Z, biomeId = dataTag["Biomes"].ByteArrayValue }; for (int i = 0; i < chunk.biomeId.Length; i++) { if (chunk.biomeId[i] > 22) chunk.biomeId[i] = 0; } if (chunk.biomeId.Length > 256) throw new Exception(); // This will turn into a full chunk column foreach (NbtTag sectionTag in sections) { int sy = sectionTag["Y"].ByteValue*16; byte[] blocks = sectionTag["Blocks"].ByteArrayValue; byte[] data = sectionTag["Data"].ByteArrayValue; NbtTag addTag = sectionTag["Add"]; byte[] adddata = new byte[2048]; if (addTag != null) adddata = addTag.ByteArrayValue; byte[] blockLight = sectionTag["BlockLight"].ByteArrayValue; byte[] skyLight = sectionTag["SkyLight"].ByteArrayValue; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = 0; y < 16; y++) { int yi = sy + y - yoffset; if (yi < 0 || yi >= 128) continue; int anvilIndex = y*16*16 + z*16 + x; int blockId = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8); // Anvil to PE friendly converstion if (blockId == 125) blockId = 5; else if (blockId == 126) blockId = 158; else if (blockId == 75) blockId = 50; else if (blockId == 76) blockId = 50; else if (blockId == 123) blockId = 89; else if (blockId == 124) blockId = 89; else if (blockId == 152) blockId = 73; else if (_ignore.BinarySearch(blockId) >= 0) blockId = 0; else if (_gaps.BinarySearch(blockId) >= 0) { Debug.WriteLine("Missing material: " + blockId); blockId = 133; } if (blockId > 255) blockId = 41; if (yi == 127 && blockId != 0) blockId = 30; if (yi == 0 && (blockId == 8 || blockId == 9 /*|| blockId == 0*/)) blockId = 7; //if (blockId != 0) blockId = 41; chunk.SetBlock(x, yi, z, (byte) blockId); chunk.SetMetadata(x, yi, z, Nibble4(data, anvilIndex)); chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex)); chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex)); } } } } NbtList entities = dataTag["Entities"] as NbtList; NbtList blockEntities = dataTag["TileEntities"] as NbtList; if (blockEntities != null) { foreach (var nbtTag in blockEntities) { var blockEntityTag = (NbtCompound) nbtTag; string entityId = blockEntityTag["id"].StringValue; int x = blockEntityTag["x"].IntValue; int y = blockEntityTag["y"].IntValue - yoffset; int z = blockEntityTag["z"].IntValue; blockEntityTag["y"] = new NbtInt("y", y); BlockEntity blockEntity = BlockEntityFactory.GetBlockEntityById(entityId); if (blockEntity != null) { blockEntityTag.Name = string.Empty; chunk.SetBlockEntity(new BlockCoordinates(x, y, z), blockEntityTag); } } } NbtList tileTicks = dataTag["TileTicks"] as NbtList; chunk.isDirty = false; return chunk; } }
public ChunkColumn GetChunk(int X, int Z) { var width = 32; var depth = 32; var rx = X >> 5; var rz = Z >> 5; var filePath = Path.Combine(_basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz)); if (!File.Exists(filePath)) return _backEndGenerator.GenerateChunkColumn(new Vector2(X, Z)); using (var regionFile = File.OpenRead(filePath)) { var buffer = new byte[8192]; regionFile.Read(buffer, 0, 8192); var xi = (X%width); if (xi < 0) xi += 32; var zi = (Z%depth); if (zi < 0) zi += 32; var tableOffset = (xi + zi*width)*4; regionFile.Seek(tableOffset, SeekOrigin.Begin); var offsetBuffer = new byte[4]; regionFile.Read(offsetBuffer, 0, 3); Array.Reverse(offsetBuffer); var offset = BitConverter.ToInt32(offsetBuffer, 0) << 4; var length = regionFile.ReadByte(); //if (offset == 0 || length == 0) return _backEndGenerator.GenerateChunkColumn(new Vector2(X, Z)); if (offset == 0 || length == 0) { return _backEndGenerator.GenerateChunkColumn(new Vector2(X,Z)); } regionFile.Seek(offset, SeekOrigin.Begin); var waste = new byte[4]; regionFile.Read(waste, 0, 4); var compressionMode = regionFile.ReadByte(); var nbt = new NbtFile(); nbt.LoadFromStream(regionFile, NbtCompression.ZLib); var dataTag = nbt.RootTag["Level"]; var sections = dataTag["Sections"] as NbtList; var chunk = new ChunkColumn { X = X, Z = Z, BiomeId = dataTag["Biomes"].ByteArrayValue }; for (var i = 0; i < chunk.BiomeId.Length; i++) { if (chunk.BiomeId[i] > 22) chunk.BiomeId[i] = 0; } if (chunk.BiomeId.Length > 256) throw new Exception(); // This will turn into a full chunk column foreach (var sectionTag in sections) { var sy = sectionTag["Y"].ByteValue*16; var blocks = sectionTag["Blocks"].ByteArrayValue; var data = sectionTag["Data"].ByteArrayValue; var addTag = sectionTag["Add"]; var adddata = new byte[2048]; if (addTag != null) adddata = addTag.ByteArrayValue; var blockLight = sectionTag["BlockLight"].ByteArrayValue; var skyLight = sectionTag["SkyLight"].ByteArrayValue; for (var x = 0; x < 16; x++) { for (var z = 0; z < 16; z++) { for (var y = 0; y < 16; y++) { var yi = sy + y - _waterOffsetY; if (yi < 0 || yi >= 256) continue; var anvilIndex = y*16*16 + z*16 + x; var blockId = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8); var b = BlockFactory.GetBlockById((ushort) blockId); b.Metadata = Nibble4(data, anvilIndex); chunk.SetBlock(x, yi, z, b); chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex)); chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex)); } } } } var entities = dataTag["Entities"] as NbtList; var tileEntities = dataTag["TileEntities"] as NbtList; if (tileEntities != null) { foreach (var nbtTag in tileEntities) { var blockEntityTag = (NbtCompound)nbtTag; string entityId = blockEntityTag["id"].StringValue; int x = blockEntityTag["x"].IntValue; int y = blockEntityTag["y"].IntValue - _waterOffsetY; int z = blockEntityTag["z"].IntValue; blockEntityTag["y"] = new NbtInt("y", y); TileEntity blockEntity = TileEntityFactory.GetBlockEntityById(entityId); if (blockEntity != null) { blockEntityTag.Name = string.Empty; chunk.SetBlockEntity(new Vector3(x, y, z), blockEntityTag); } } } var tileTicks = dataTag["TileTicks"] as NbtList; chunk.IsDirty = false; return chunk; } }
/// <summary> /// Retrieves the requested chunk from the region, or /// generates it if a world generator is provided. /// </summary> /// <param name="position">The position of the requested local chunk coordinates.</param> public IChunk GetChunk(Coordinates2D position, bool generate = true) { // TODO: This could use some refactoring lock (Chunks) { if (!Chunks.ContainsKey(position)) { if (regionFile != null) { // Search the stream for that region lock (regionFile) { var chunkData = GetChunkFromTable(position); if (chunkData == null) { if (World.ChunkProvider == null) throw new ArgumentException("The requested chunk is not loaded.", "position"); if (generate) GenerateChunk(position); else return null; return Chunks[position]; } regionFile.Seek(chunkData.Item1, SeekOrigin.Begin); /*int length = */ new MinecraftStream(regionFile).ReadInt32(); // TODO: Avoid making new objects here, and in the WriteInt32 int compressionMode = regionFile.ReadByte(); switch (compressionMode) { case 1: // gzip throw new NotImplementedException("gzipped chunks are not implemented"); case 2: // zlib var nbt = new NbtFile(); nbt.LoadFromStream(regionFile, NbtCompression.ZLib, null); var chunk = Chunk.FromNbt(nbt); Chunks.Add(position, chunk); World.OnChunkLoaded(new ChunkLoadedEventArgs(chunk)); break; default: throw new InvalidDataException("Invalid compression scheme provided by region file."); } } } else if (World.ChunkProvider == null) throw new ArgumentException("The requested chunk is not loaded.", "position"); else { if (generate) GenerateChunk(position); else return null; } } return Chunks[position]; } }
public PlayerEntity LoadPlayer(string name) { PlayerEntity entity = new PlayerEntity(Difficulty); if (LevelDirectory == null || !File.Exists(Path.Combine(LevelDirectory, "players", name + ".dat"))) { // Return default player entity entity.Position = SpawnPoint; entity.SpawnPoint = SpawnPoint; entity.Position += new Vector3(0, PlayerEntity.Height, 0); entity.GameMode = GameMode; return entity; } var file = new NbtFile(); using (Stream stream = File.Open(Path.Combine(LevelDirectory, "players", name + ".dat"), FileMode.Open)) file.LoadFromStream(stream, NbtCompression.GZip, null); var data = file.RootTag; entity.OnGround = data.Get<NbtByte>("OnGround").Value == 1; entity.Air = data.Get<NbtShort>("Air").Value; entity.Health = data.Get<NbtShort>("Health").Value; var dimension = (Dimension)data.Get<NbtInt>("Dimension").Value; // TODO entity.Food = (short)data.Get<NbtInt>("foodLevel").Value; entity.XpLevel = data.Get<NbtInt>("XpLevel").Value; entity.XpTotal = data.Get<NbtInt>("XpTotal").Value; // TODO: Set velocity based on fall distance entity.FoodExhaustion = data.Get<NbtFloat>("foodExhaustionLevel").Value; entity.FoodSaturation = data.Get<NbtFloat>("foodSaturationLevel").Value; entity.XpProgress = data.Get<NbtFloat>("XpP").Value; var equipment = data.Get<NbtList>("Equipment"); var inventory = data.Get<NbtList>("Inventory"); var motion = data.Get<NbtList>("Motion"); var pos = data.Get<NbtList>("Pos"); var rotation = data.Get<NbtList>("Rotation"); var abilities = data.Get<NbtCompound>("abilities"); // Appears to be unused, is overriden by the inventory contents // foreach (var item in equipment.Tags) foreach (var item in inventory) { var slot = ItemStack.FromNbt((NbtCompound)item); slot.Index = DataSlotToNetworkSlot(slot.Index); entity.Inventory[slot.Index] = slot; } entity.Velocity = new Vector3( ((NbtDouble)motion[0]).Value, ((NbtDouble)motion[1]).Value, ((NbtDouble)motion[2]).Value); entity.Position = new Vector3( ((NbtDouble)pos[0]).Value, ((NbtDouble)pos[1]).Value, ((NbtDouble)pos[2]).Value); if (data.Get<NbtInt>("SpawnX") != null) { entity.SpawnPoint = new Vector3( data.Get<NbtInt>("SpawnX").Value, data.Get<NbtInt>("SpawnY").Value, data.Get<NbtInt>("SpawnZ").Value); } entity.Yaw = ((NbtFloat)rotation[0]).Value; entity.Pitch = ((NbtFloat)rotation[1]).Value; // TODO: Abilities return entity; }
private void LoadFromFile(string directory) { NbtFile file = new NbtFile(); using (var stream = File.Open(Path.Combine(LevelDirectory, "level.dat"), FileMode.Open)) file.LoadFromStream(stream, NbtCompression.None, null); var data = file.RootTag.Get<NbtCompound>("Data"); var serializer = new NbtSerializer(typeof(SavedLevel)); SavedLevel level = (SavedLevel)serializer.Deserialize(data); Name = level.LevelName; Time = level.Time; GameMode = (GameMode)level.GameMode; MapFeatures = level.MapFeatures; Seed = level.Seed; // Find world generator string generatorName = level.GeneratorName; WorldGenerator = GetGenerator(generatorName); WorldGenerator.Seed = Seed; GeneratorOptions = level.GeneratorOptions; WorldGenerator.Initialize(this); SpawnPoint = level.SpawnPoint; World = new World(this, WorldGenerator, Path.Combine(directory, "region")); }
public void Save() { NbtFile file = new NbtFile(); var serializer = new NbtSerializer(typeof(SavedLevel)); var level = new SavedLevel { IsRaining = Raining, GeneratorVersion = 0, Time = Time, GameMode = (int)GameMode, MapFeatures = MapFeatures, GeneratorName = WorldGenerator.GeneratorName, Initialized = true, Seed = Seed, SpawnPoint = SpawnPoint, SizeOnDisk = 0, ThunderTime = ThunderTime, RainTime = RainTime, Version = 19133, Thundering = Thundering, LevelName = Name, LastPlayed = DateTime.UtcNow.Ticks }; if (!string.IsNullOrEmpty(PlayerName)) { if (File.Exists(Path.Combine(LevelDirectory, "players", PlayerName + ".dat"))) { var player = new NbtFile(); using (Stream stream = File.Open(Path.Combine(LevelDirectory, "players", PlayerName + ".dat"), FileMode.Open)) player.LoadFromStream(stream, NbtCompression.GZip, null); level.Player = player.RootTag; level.Player.Name = "Player"; } } var data = serializer.Serialize(level); file.RootTag = new NbtCompound(""); file.RootTag.Add(data); using (var stream = File.Create(Path.Combine(LevelDirectory, "level.dat"))) file.SaveToStream(stream, NbtCompression.GZip); if (World.Directory == null) World.Save(Path.Combine(LevelDirectory, "region")); else World.Save(); }