/// <inheritdoc /> public bool Passes(IBlockAccess world, Vector3 position, string rule, string value) { if (!MultiPartModels.TryGetBlockface(rule, out BlockFace face)) { return(false); } Vector3 offset = face.GetVector3(); offset = position + offset; if (value == "side|up") { return(IsRedstoneWire(world, offset) || IsRedstoneWire(world, offset + Vector3.Down)); } else if (value == "up") { return(IsRedstoneWire(world, offset + Vector3.Up)); } else if (value == "none") { return(!IsRedstoneWire(world, offset)); } return(false); }
private static BlockModel ResolveModel(ResourceManager resources, McResourcePack resourcePack, BlockState state) { string name = state.Name; if (string.IsNullOrWhiteSpace(name)) { Log.Warn($"State name is null!"); return(null); } if (name.Contains("water")) { return(new LiquidBlockModel() { // IsFlowing = false, IsLava = false, // Level = state.GetTypedValue(Water.LEVEL) }); } if (name.Contains("lava")) { return(new LiquidBlockModel() { // IsFlowing = false, IsLava = true, // Level = state.GetTypedValue(Water.LEVEL) });; } BlockStateResource blockStateResource; if (resourcePack.BlockStates.TryGetValue(name, out blockStateResource)) { if (blockStateResource != null && blockStateResource.Parts != null && blockStateResource.Parts.Length > 0 && blockStateResource.Parts.All(x => x.Apply.All(b => b.Model != null))) { var models = MultiPartModels.GetModels(state, blockStateResource); state.MultiPartHelper = blockStateResource; state.IsMultiPart = true; state.AppliedModels = models.Select(x => x.ModelName).ToArray(); return(new ResourcePackBlockModel(resources, models)); } if (blockStateResource?.Variants == null || blockStateResource.Variants.Count == 0) { return(null); } if (blockStateResource.Variants.Count == 1) { var v = blockStateResource.Variants.FirstOrDefault(); if (v.Value == null) { return(null); } var models = v.Value.Where(x => x.Model?.Elements != null && x.Model.Elements.Length > 0).ToArray(); if (models.Length == 0) { return(null); } return(new ResourcePackBlockModel(resources, models, v.Value.ToArray().Length > 1)); } BlockStateVariant blockStateVariant = null; var data = state.ToDictionary(); // data.Remove("waterlogged"); int closestMatch = 0; KeyValuePair <string, BlockStateVariant> closest = default(KeyValuePair <string, BlockStateVariant>); foreach (var v in blockStateResource.Variants) { int matches = 0; var variantBlockState = Blocks.State.BlockState.FromString(v.Key); foreach (var kv in data) { if (variantBlockState.TryGetValue(kv.Key, out string vValue)) { if (vValue.Equals(kv.Value, StringComparison.InvariantCultureIgnoreCase)) { matches++; } else { break; } } else { break; } } if (matches > closestMatch) { closestMatch = matches; closest = v; if (matches == data.Count) { break; } } } blockStateVariant = closest.Value; if (blockStateVariant == null) { var a = blockStateResource.Variants.FirstOrDefault(); blockStateVariant = a.Value; } var asArray = blockStateVariant.ToArray(); if (asArray.Length == 0 || asArray.Any(x => x.Model?.Elements == null || x.Model.Elements.Length == 0)) { return(null); } return(new ResourcePackBlockModel(resources, asArray, asArray.Length > 1)); } return(null); }
private ChunkMesh GenerateSectionMesh(IWorld world, ScheduleType scheduled, Vector3 chunkPosition, ref ChunkSection section, int yIndex) { var force = section.New || section.MeshCache == null || section.MeshPositions == null; var cached = section.MeshCache; var positionCache = section.MeshPositions; Dictionary <Vector3, ChunkMesh.EntryPosition> positions = new Dictionary <Vector3, ChunkMesh.EntryPosition>(); List <VertexPositionNormalTextureColor> solidVertices = new List <VertexPositionNormalTextureColor>(); List <int> animatedIndexes = new List <int>(); List <int> transparentIndexes = new List <int>(); List <int> solidIndexes = new List <int>(); Dictionary <int, int> processedIndices = new Dictionary <int, int>(); for (var y = 0; y < 16; y++) { for (var x = 0; x < ChunkColumn.ChunkWidth; x++) { for (var z = 0; z < ChunkColumn.ChunkDepth; z++) { var blockPosition = new Vector3(x, y + (yIndex << 4), z) + chunkPosition; bool isScheduled = section.IsScheduled(x, y, z); var neighborsScheduled = HasScheduledNeighbors(world, blockPosition); // bool isLightingScheduled = section.IsLightingScheduled(x, y, z); var isBorderBlock = (scheduled == ScheduleType.Border && (x == 0 || x == 15) || (z == 0 || z == 15)); var blockState = section.Get(x, y, z); if (((blockState == null || !blockState.Block.Renderable) || (!section.New && !neighborsScheduled)) && !force && !isBorderBlock) { continue; } var shouldRebuildVertices = (force || isScheduled || neighborsScheduled || isBorderBlock); var model = blockState.Model; if (blockState != null && shouldRebuildVertices && blockState.Block.RequiresUpdate) { blockState = blockState.Block.BlockPlaced(world, blockState, blockPosition); section.Set(x, y, z, blockState); model = blockState.Model; } if (blockState is BlockState state && state.IsMultiPart && shouldRebuildVertices) { model = new CachedResourcePackModel(Game.Resources, MultiPartModels.GetBlockStateModels(world, blockPosition, state, state.MultiPartHelper)); // blockState.Block.Update(world, blockPosition); } if (!shouldRebuildVertices && positionCache.TryGetValue(new Vector3(x, y, z), out var pos)) { var indices = pos.Animated ? cached.AnimatedIndexes : (pos.Transparent ? cached.TransparentIndexes : cached.SolidIndexes); var indiceIndex = pos.Animated ? animatedIndexes.Count : (pos.Transparent ? transparentIndexes.Count : solidIndexes.Count); for (int index = 0; index < pos.Length; index++) { var indice = indices[pos.Index + index]; if (!processedIndices.TryGetValue(indice, out var newIndex)) { newIndex = solidVertices.Count; var vertice = cached.Vertices[indice]; solidVertices.Add(vertice); processedIndices.Add(indice, newIndex); } if (pos.Animated) { animatedIndexes.Add(newIndex); } else if (pos.Transparent) { transparentIndexes.Add(newIndex); } else { solidIndexes.Add(newIndex); } } positions.TryAdd(new Vector3(x, y, z), new ChunkMesh.EntryPosition(pos.Transparent, pos.Animated, indiceIndex, pos.Length)); } else if (shouldRebuildVertices) { var data = model.GetVertices(world, blockPosition, blockState.Block); if (data.vertices.Length == 0 || data.indexes.Length == 0) { section.SetRendered(x, y, z, false); } if (data.vertices == null || data.indexes == null || data.vertices.Length == 0 || data.indexes.Length == 0) { //section.SetRendered(x, y, z, false); if (isScheduled) { section.SetScheduled(x, y, z, false); } continue; } bool transparent = blockState.Block.Transparent; bool animated = blockState.Block.Animated; if (data.vertices.Length > 0 && data.indexes.Length > 0) { section.SetRendered(x, y, z, true); int startVerticeIndex = solidVertices.Count; foreach (var vert in data.vertices) { solidVertices.Add(vert); } int startIndex = animated ? animatedIndexes.Count : (transparent ? transparentIndexes.Count : solidIndexes.Count); for (int i = 0; i < data.indexes.Length; i++) { var a = data.indexes[i]; if (animated) { animatedIndexes.Add(startVerticeIndex + a); } else if (transparent) { transparentIndexes.Add(startVerticeIndex + a); } else { solidIndexes.Add(startVerticeIndex + a); } } positions.TryAdd(new Vector3(x, y, z), new ChunkMesh.EntryPosition(transparent, animated, startIndex, data.indexes.Length)); } } //if (isLightingScheduled) // section.SetLightingScheduled(x, y, z, false); } } } section.New = false; var mesh = new ChunkMesh(solidVertices.ToArray(), solidIndexes.ToArray(), transparentIndexes.ToArray(), animatedIndexes.ToArray()); section.MeshCache = mesh; section.MeshPositions = positions; return(mesh); }