private static void PopulateBlockPalette() { BlockPalette.Add("Air", new Block("Air", BlockTypes.Air, Textures["Air"], dummyPosition)); BlockPalette.Add("FuelCell", new FuelCell("FuelCell", Textures["FuelCell"], dummyPosition)); foreach (Cooler cooler in coolers) { BlockPalette.Add(cooler.CoolerType.ToString(), cooler); } foreach (Moderator moderator in moderators) { BlockPalette.Add(moderator.ModeratorType.ToString(), moderator); } }
static BlockFactory() { for (int i = 0; i < byte.MaxValue * 2; i++) { var block = GetBlockById(i); if (block != null) { if (block.IsTransparent) { TransparentBlocks[block.Id] = 1; } if (block.LightLevel > 0) { LuminousBlocks[block.Id] = (byte)block.LightLevel; } } } NameToId = BuildNameToId(); for (int i = 0; i < LegacyToRuntimeId.Length; ++i) { LegacyToRuntimeId[i] = -1; } var assembly = Assembly.GetAssembly(typeof(Block)); lock (lockObj) { Dictionary <string, int> idMapping = new Dictionary <string, int>(ResourceUtil.ReadResource <Dictionary <string, int> >("block_id_map.json", typeof(Block), "Data"), StringComparer.OrdinalIgnoreCase); int runtimeId = 0; BlockPalette = new BlockPalette(); using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".Data.canonical_block_states.nbt")) { do { var compound = Packet.ReadNbtCompound(stream, true); var container = GetBlockStateContainer(compound); container.RuntimeId = runtimeId++; BlockPalette.Add(container); } while (stream.Position < stream.Length); } List <R12ToCurrentBlockMapEntry> legacyStateMap = new List <R12ToCurrentBlockMapEntry>(); using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".Data.r12_to_current_block_map.bin")) { while (stream.Position < stream.Length) { var length = VarInt.ReadUInt32(stream); byte[] bytes = new byte[length]; stream.Read(bytes, 0, bytes.Length); string stringId = Encoding.UTF8.GetString(bytes); bytes = new byte[2]; stream.Read(bytes, 0, bytes.Length); var meta = BitConverter.ToInt16(bytes); var compound = Packet.ReadNbtCompound(stream, true); legacyStateMap.Add(new R12ToCurrentBlockMapEntry(stringId, meta, GetBlockStateContainer(compound))); } } Dictionary <string, List <int> > idToStatesMap = new Dictionary <string, List <int> >(StringComparer.OrdinalIgnoreCase); for (var index = 0; index < BlockPalette.Count; index++) { var state = BlockPalette[index]; List <int> candidates; if (!idToStatesMap.TryGetValue(state.Name, out candidates)) { candidates = new List <int>(); } candidates.Add(index); idToStatesMap[state.Name] = candidates; } foreach (var pair in legacyStateMap) { if (!idMapping.TryGetValue(pair.StringId, out int id)) { continue; } var data = pair.Meta; if (data > 15) { continue; } var mappedState = pair.State; var mappedName = pair.State.Name; if (!idToStatesMap.TryGetValue(mappedName, out var matching)) { continue; } foreach (var match in matching) { var networkState = BlockPalette[match]; var thisStates = new HashSet <IBlockState>(mappedState.States); var otherStates = new HashSet <IBlockState>(networkState.States); otherStates.IntersectWith(thisStates); if (otherStates.Count == thisStates.Count) { BlockPalette[match].Id = id; BlockPalette[match].Data = data; BlockPalette[match].ItemInstance = new ItemPickInstance() { Id = (short)id, Metadata = data, WantNbt = false }; LegacyToRuntimeId[(id << 4) | (byte)data] = match; break; } } } foreach (var record in BlockPalette) { var states = new List <NbtTag>(); foreach (IBlockState state in record.States) { NbtTag stateTag = null; switch (state) { case BlockStateByte blockStateByte: stateTag = new NbtByte(state.Name, blockStateByte.Value); break; case BlockStateInt blockStateInt: stateTag = new NbtInt(state.Name, blockStateInt.Value); break; case BlockStateString blockStateString: stateTag = new NbtString(state.Name, blockStateString.Value); break; default: throw new ArgumentOutOfRangeException(nameof(state)); } states.Add(stateTag); } var nbt = new NbtFile() { BigEndian = false, UseVarInt = true, RootTag = new NbtCompound("states", states) }; byte[] nbtBinary = nbt.SaveToBuffer(NbtCompression.None); record.StatesCacheNbt = nbtBinary; } } BlockStates = new HashSet <BlockStateContainer>(BlockPalette); }
static BlockFactory() { for (int i = 0; i < byte.MaxValue * 2; i++) { var block = GetBlockById(i); if (block != null) { if (block.IsTransparent) { TransparentBlocks[block.Id] = 1; } if (block.LightLevel > 0) { LuminousBlocks[block.Id] = (byte)block.LightLevel; } } } NameToId = BuildNameToId(); for (int i = 0; i < LegacyToRuntimeId.Length; ++i) { LegacyToRuntimeId[i] = -1; } var assembly = Assembly.GetAssembly(typeof(Block)); lock (lockObj) { Dictionary <string, int> idMapping; using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".block_id_map.json")) using (var reader = new StreamReader(stream)) { idMapping = JsonConvert.DeserializeObject <Dictionary <string, int> >(reader.ReadToEnd()); } Dictionary <string, short> itemIdMapping; using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".item_id_map.json")) using (var reader = new StreamReader(stream)) { itemIdMapping = JsonConvert.DeserializeObject <Dictionary <string, short> >(reader.ReadToEnd()); } int runtimeId = 0; BlockPalette = new BlockPalette(); using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".canonical_block_states.nbt")) { var reader = new NbtFile(); reader.UseVarInt = true; reader.AllowAlternativeRootTag = true; do { reader.LoadFromStream(stream, NbtCompression.AutoDetect); var record = new BlockStateContainer(); var tag = reader.RootTag; string name = tag["name"].StringValue; record.Name = name; record.States = new List <IBlockState>(); if (idMapping.TryGetValue(name, out var id)) { record.Id = id; } var states = tag["states"]; if (states != null && states is NbtCompound compound) { foreach (var stateEntry in compound) { switch (stateEntry) { case NbtInt nbtInt: record.States.Add(new BlockStateInt() { Name = nbtInt.Name, Value = nbtInt.Value }); break; case NbtByte nbtByte: record.States.Add(new BlockStateByte() { Name = nbtByte.Name, Value = nbtByte.Value }); break; case NbtString nbtString: record.States.Add(new BlockStateString() { Name = nbtString.Name, Value = nbtString.Value }); break; } } } if (itemIdMapping.TryGetValue(name, out var itemId)) { record.ItemInstance = new ItemPickInstance() { Id = itemId, WantNbt = false, Metadata = 0 }; } record.RuntimeId = runtimeId++; BlockPalette.Add(record); } while (stream.Position < stream.Length); } /*using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".blockstates.json")) * using (var reader = new StreamReader(stream)) * { * BlockPalette = BlockPalette.FromJson(reader.ReadToEnd()); * }*/ foreach (var record in BlockPalette) { var states = new List <NbtTag>(); foreach (IBlockState state in record.States) { NbtTag stateTag = null; switch (state) { case BlockStateByte blockStateByte: stateTag = new NbtByte(state.Name, blockStateByte.Value); break; case BlockStateInt blockStateInt: stateTag = new NbtInt(state.Name, blockStateInt.Value); break; case BlockStateString blockStateString: stateTag = new NbtString(state.Name, blockStateString.Value); break; default: throw new ArgumentOutOfRangeException(nameof(state)); } states.Add(stateTag); } var nbt = new NbtFile() { BigEndian = false, UseVarInt = true, RootTag = new NbtCompound("states", states) }; byte[] nbtBinary = nbt.SaveToBuffer(NbtCompression.None); record.StatesCacheNbt = nbtBinary; } } int palletSize = BlockPalette.Count; for (int i = 0; i < palletSize; i++) { if (BlockPalette[i].Data > 15) { continue; // TODO: figure out why palette contains blocks with meta more than 15 } if (BlockPalette[i].Data == -1) { continue; // These are blockstates that does not have a metadata mapping } LegacyToRuntimeId[(BlockPalette[i].Id << 4) | (byte)BlockPalette[i].Data] = i; } BlockStates = new HashSet <BlockStateContainer>(BlockPalette); }
public BlockPalette ReadAlternateBlockPalette() { var result = new BlockPalette(); uint count = ReadUnsignedVarInt(); //Log.Info($"Block count startgame: {count}"); for (int runtimeId = 0; runtimeId < count; runtimeId++) { var record = new BlockStateContainer(); record.RuntimeId = runtimeId; record.Id = record.RuntimeId; record.Name = ReadString(); record.States = new List<IBlockState>(); var nbt = NetworkUtils.ReadNewNbt(_reader); var rootTag = nbt.NbtFile.RootTag; if (rootTag is NbtList nbtList) { foreach (NbtTag tag in nbtList) { var s = tag["states"]; if (s is NbtCompound compound) { foreach (NbtTag stateTag in compound) { IBlockState state = null; switch (stateTag.TagType) { case NbtTagType.Byte: state = new BlockStateByte() {Name = stateTag.Name, Value = stateTag.ByteValue}; break; case NbtTagType.Int: state = new BlockStateInt() {Name = stateTag.Name, Value = stateTag.IntValue}; break; case NbtTagType.String: state = new BlockStateString() { Name = stateTag.Name, Value = stateTag.StringValue }; break; default: throw new ArgumentOutOfRangeException(); } record.States.Add(state); } } else if (s is NbtList list) { foreach (NbtTag stateTag in list) { IBlockState state = null; switch (stateTag.TagType) { case NbtTagType.Byte: state = new BlockStateByte() {Name = stateTag.Name, Value = stateTag.ByteValue}; break; case NbtTagType.Int: state = new BlockStateInt() {Name = stateTag.Name, Value = stateTag.IntValue}; break; case NbtTagType.String: state = new BlockStateString() { Name = stateTag.Name, Value = stateTag.StringValue }; break; default: throw new ArgumentOutOfRangeException(); } record.States.Add(state); } } result.Add(record); } } else if (rootTag is NbtCompound c) { foreach (NbtTag tag in c) { var s = tag["states"]; if (s is NbtCompound compound) { foreach (NbtTag stateTag in compound) { IBlockState state = null; switch (stateTag.TagType) { case NbtTagType.Byte: state = new BlockStateByte() { Name = stateTag.Name, Value = stateTag.ByteValue }; break; case NbtTagType.Int: state = new BlockStateInt() { Name = stateTag.Name, Value = stateTag.IntValue }; break; case NbtTagType.String: state = new BlockStateString() { Name = stateTag.Name, Value = stateTag.StringValue }; break; default: throw new ArgumentOutOfRangeException(); } record.States.Add(state); } } else if (s is NbtList list) { foreach (NbtTag stateTag in list) { IBlockState state = null; switch (stateTag.TagType) { case NbtTagType.Byte: state = new BlockStateByte() { Name = stateTag.Name, Value = stateTag.ByteValue }; break; case NbtTagType.Int: state = new BlockStateInt() { Name = stateTag.Name, Value = stateTag.IntValue }; break; case NbtTagType.String: state = new BlockStateString() { Name = stateTag.Name, Value = stateTag.StringValue }; break; default: throw new ArgumentOutOfRangeException(); } record.States.Add(state); } } result.Add(record); } } } return result; }