Pot prototype (WIP)

This commit is contained in:
paulevsGitch 2021-07-11 00:46:44 +03:00
parent 4040597a6d
commit 287e25bbcf
2 changed files with 80 additions and 114 deletions

View file

@ -1,44 +1,68 @@
package ru.betterend.blocks;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.math.Matrix4f;
import com.mojang.math.Quaternion;
import com.mojang.math.Transformation;
import com.mojang.math.Vector3f;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.renderer.block.model.MultiVariant;
import net.minecraft.client.renderer.block.model.Variant;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.Mth;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import ru.bclib.blocks.BaseBlockNotFull;
import ru.bclib.client.models.BlockModelProvider;
import ru.betterend.client.models.MergedModel;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.ModelsHelper.MultiPartBuilder;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.IRenderTyped;
import ru.bclib.util.JsonFactory;
import ru.bclib.util.MHelper;
import ru.betterend.BetterEnd;
import ru.betterend.interfaces.PottablePlant;
import ru.betterend.registry.EndBlocks;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
public class FlowerPotBlock extends BaseBlockNotFull {
public class FlowerPotBlock extends BaseBlockNotFull implements IRenderTyped {
private static final VoxelShape SHAPE = Block.box(4, 4, 4, 12, 12, 12);
private static final IntegerProperty PLANT_ID = EndBlockProperties.PLANT_ID;
private final Block[] blocks;
private final ResourceLocation[] blocks;
@Environment(EnvType.CLIENT)
private UnbakedModel source;
public FlowerPotBlock(Block source) {
super(FabricBlockSettings.copyOf(source));
List<Block> blocks = Lists.newArrayList();
List<ResourceLocation> blocks = Lists.newArrayList();
EndBlocks.getModBlocks().forEach(block -> {
if (block instanceof PottablePlant) {
blocks.add(block);
if (block instanceof PottablePlant && block.getStateDefinition().getProperties().isEmpty()) {
blocks.add(Registry.BLOCK.getKey(block));
}
});
this.blocks = blocks.toArray(new Block[] {});
this.blocks = blocks.toArray(new ResourceLocation[] {});
}
@Override
@ -50,27 +74,56 @@ public class FlowerPotBlock extends BaseBlockNotFull {
@Override
@Environment(EnvType.CLIENT)
public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
int id = blockState.getValue(PLANT_ID);
if (id == 0 || id > blocks.length) {
if (id == 0) {
source = super.getModelVariant(stateId, blockState, modelCache);
}
return source;
}
registerModel(stateId, blockState, modelCache);
MergedModel model = new MergedModel(blockState, source);
Block plant = blocks[id - 1];
if (plant instanceof BlockModelProvider) {
ResourceLocation location = Registry.BLOCK.getKey(plant);
//model.addModel(((BlockModelProvider) plant).getBlockModel(location, plant.defaultBlockState()));
model = new MergedModel(blockState, ((BlockModelProvider) plant).getBlockModel(location, plant.defaultBlockState()));
System.out.println("Plant " + id + " is instance!");
}
return model;
ModelResourceLocation key = new ModelResourceLocation(stateId.getNamespace(), stateId.getPath(), "plant_age=0");
if (modelCache.containsKey(key)) {
return modelCache.get(key);
}
private void registerModel(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath());
registerBlockModel(stateId, modelId, blockState, modelCache);
MultiPartBuilder model = MultiPartBuilder.create(stateDefinition);
model.part(new ResourceLocation("block/flower_pot")).add();
Transformation offset = new Transformation(new Vector3f(0, 0.5F, 0), null, null, null);
for (int i = 0; i < blocks.length; i++) {
final int compareID = i + 1;
ResourceLocation modelPath = blocks[i];
ResourceLocation objSource = new ResourceLocation(modelPath.getNamespace(), "block/potted_" + modelPath.getPath() + ".json");
if (Minecraft.getInstance().getResourceManager().hasResource(objSource)) {
objSource = new ResourceLocation(modelPath.getNamespace(), "block/potted_" + modelPath.getPath());
model.part(objSource).setTransformation(offset).setCondition(state -> state.getValue(PLANT_ID) == compareID).add();
continue;
}
objSource = new ResourceLocation(modelPath.getNamespace(), "blockstates/" + modelPath.getPath() + ".json");
JsonObject obj = JsonFactory.getJsonObject(objSource);
if (obj != null) {
JsonElement variants = obj.get("variants").getAsJsonObject().get("");
String path = null;
if (variants.isJsonArray()) {
path = variants.getAsJsonArray().get(0).getAsJsonObject().get("model").getAsString();
}
else {
path = variants.getAsJsonObject().get("model").getAsString();
}
model.part(new ResourceLocation(path)).setTransformation(offset).setCondition(state -> state.getValue(PLANT_ID) == compareID).add();
}
}
UnbakedModel result = model.build();
modelCache.put(key, result);
return result;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
}

View file

@ -1,87 +0,0 @@
package ru.betterend.client.models;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.SimpleBakedModel;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import ru.bclib.util.BlocksHelper;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
public class MergedModel implements UnbakedModel {
private final List<UnbakedModel> models = Lists.newArrayList();
private final UnbakedModel source;
private final BlockState state;
public MergedModel(BlockState state, UnbakedModel source) {
this.source = source;
this.state = state;
}
public void addModel(UnbakedModel model) {
models.add(model);
}
@Override
public Collection<ResourceLocation> getDependencies() {
Set<ResourceLocation> dependencies = Sets.newHashSet();
dependencies.addAll(source.getDependencies());
models.forEach(model -> dependencies.addAll(model.getDependencies()));
return dependencies;
}
@Override
public Collection<Material> getMaterials(Function<ResourceLocation, UnbakedModel> function, Set<Pair<String, String>> set) {
Set<Material> material = Sets.newHashSet();
material.addAll(source.getMaterials(function, set));
models.forEach(model -> material.addAll(model.getMaterials(function, set)));
return material;
}
@Nullable
@Override
public BakedModel bake(ModelBakery modelBakery, Function<Material, TextureAtlasSprite> function, ModelState modelState, ResourceLocation resourceLocation) {
Random random = new Random(resourceLocation.toString().hashCode());
BakedModel baked = source.bake(modelBakery, function, modelState, resourceLocation);
Map<Direction, List<BakedQuad>> map = makeMap();
List<BakedQuad> quads = Lists.newArrayList();
processModel(baked, map, quads, random);
models.forEach(model -> {
BakedModel baked2 = source.bake(modelBakery, function, modelState, resourceLocation);
processModel(baked2, map, quads, random);
});
return new SimpleBakedModel(quads, map, baked.useAmbientOcclusion(), baked.usesBlockLight(), baked.isGui3d(), baked.getParticleIcon(), baked.getTransforms(), baked.getOverrides());
}
private Map<Direction, List<BakedQuad>> makeMap() {
Map<Direction, List<BakedQuad>> map = Maps.newEnumMap(Direction.class);
for (Direction dir : BlocksHelper.DIRECTIONS) {
map.put(dir, Lists.newArrayList());
}
return map;
}
private void processModel(BakedModel model, Map<Direction, List<BakedQuad>> map, List<BakedQuad> quads, Random random) {
for (Direction dir : BlocksHelper.DIRECTIONS) {
map.get(dir).addAll(model.getQuads(state, dir, random));
}
quads.addAll(model.getQuads(state, null, random));
}
}