feat: fake block models

- Instead of registering a block for the jukebox top, we can now render models without a block being registered at all
- This opens up a lot of interesting new visuals in the near future :)
This commit is contained in:
Martin Prokoph
2025-01-26 14:29:21 +01:00
parent 9dd620515c
commit 1ae9580315
52 changed files with 78 additions and 108 deletions

View File

@@ -0,0 +1,69 @@
package eu.midnightdust.visualoverhaul;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.model.ModelNameSupplier;
import net.minecraft.client.model.SpriteGetter;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.LOGGER;
public class FakeBlocks {
private static final Baker BAKER = new FakeBaker();
private static final Map<Identifier, BakedModel> FAKE_MODELS = new HashMap<>();
private static final BlockRenderManager renderManager = MinecraftClient.getInstance().getBlockRenderManager();
public static void reload(ResourceManager manager) {
manager.findResources("models", path -> path.getPath().startsWith("models/fakeblock") && path.getPath().endsWith(".json")).forEach((id, resource) -> {
try {
JsonUnbakedModel unbaked = JsonUnbakedModel.deserialize(resource.getReader());
BakedModel baked = unbaked.bake(new ModelTextures.Builder().addFirst(unbaked.getTextures()).build(() -> "#fakeblock"), BAKER,
new ModelBakeSettings(){}, Boolean.TRUE.equals(unbaked.getAmbientOcclusion()), unbaked.getGuiLight() != null && unbaked.getGuiLight().isSide(), unbaked.getTransformation());
Identifier fakeId = Identifier.of(id.getNamespace(), id.getPath().replace("models/fakeblock/", "").replace(".json", ""));
FAKE_MODELS.put(fakeId, baked);
if (VOConfig.debug) LOGGER.info("Successfully loaded fake block model: {}", fakeId);
} catch (IOException e) {
LOGGER.error("Error occurred while loading fake block model {}", id.toString(), e);
}
});
}
public static void renderFakeBlock(Identifier id, BlockPos pos, BlockRenderView world, MatrixStack matrices, VertexConsumer vertexConsumer) {
renderManager.getModelRenderer().render(world, FAKE_MODELS.get(id), Blocks.DIRT.getDefaultState(), // State is just needed for a few generic checks
pos, matrices, vertexConsumer, false, Random.create(), 0, OverlayTexture.DEFAULT_UV);
}
public static class FakeBaker implements Baker {
public BakedModel bake(Identifier id, ModelBakeSettings settings) {
return null; // Not used in Json models, so we just leave ít like this and cross our fingers.
}
@Override
public SpriteGetter getSpriteGetter() {
return new SpriteGetter() {
static final SpriteIdentifier MISSING = new SpriteIdentifier(Identifier.ofVanilla("textures/atlas/blocks.png"), Identifier.ofVanilla("missingno"));
@Override public Sprite get(SpriteIdentifier spriteId) { return spriteId.getSprite(); }
@Override public Sprite getMissing(String textureId) { return MISSING.getSprite(); }
};
}
public ModelNameSupplier getModelNameSupplier() { return () -> "#fakeblock"; }
}
}

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.LOGGER;
import static eu.midnightdust.visualoverhaul.util.VOColorUtil.alphaAndBrightness;
public class IconicButtons {
@@ -126,7 +127,7 @@ public class IconicButtons {
ICONS.put(iconId, textureId);
}
} catch (Exception e) {
LogManager.getLogger("Iconic").error("Error occurred while loading texture.properties {}", id.toString(), e);
LOGGER.error("Error occurred while loading texture.properties for button icon {}", id.toString(), e);
}
});
}

View File

@@ -1,7 +1,6 @@
package eu.midnightdust.visualoverhaul;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.block.Block;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.MOD_ID;
@@ -11,8 +10,6 @@ public class VisualOverhaulClient {
public static int grassColor = -8934609;
public static int potionColor = -13083194;
public static Block JukeBoxTop;
public static void onInitializeClient() {
VOConfig.init(MOD_ID, VOConfig.class);
}

View File

@@ -3,6 +3,8 @@ package eu.midnightdust.visualoverhaul;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.ArrayList;
@@ -12,6 +14,7 @@ import java.util.UUID;
public class VisualOverhaulCommon {
public static final String MOD_ID = "visualoverhaul";
public static final Logger LOGGER = LoggerFactory.getLogger("VisualOverhaul");
public static final List<UUID> playersWithMod = new ArrayList<>();
public static final Map<BlockPos, ItemStack> jukeboxItems = new HashMap<>();

View File

@@ -1,26 +0,0 @@
package eu.midnightdust.visualoverhaul.block;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.Properties;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.id;
public class JukeboxTop extends Block {
private static final BooleanProperty HAS_RECORD = Properties.HAS_RECORD;
public JukeboxTop() {
super(AbstractBlock.Settings.copy(Blocks.JUKEBOX).registryKey(RegistryKey.of(RegistryKeys.BLOCK, id("jukebox_top"))));
this.setDefaultState(this.stateManager.getDefaultState().with(HAS_RECORD,false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(HAS_RECORD);
}
}

View File

@@ -1,10 +0,0 @@
{
"variants": {
"has_record=true": {
"model": "visualoverhaul:block/jukebox_top_playing"
},
"has_record=false": {
"model": "visualoverhaul:block/jukebox_top_stopped"
}
}
}

View File

@@ -1,44 +0,0 @@
{
"variants": {
"playing=true,channel=0": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_0"},
"playing=false,channel=0": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_0"},
"playing=true,channel=1": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_1"},
"playing=false,channel=1": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_1"},
"playing=true,channel=2": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_2"},
"playing=false,channel=2": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_2"},
"playing=true,channel=3": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_3"},
"playing=false,channel=3": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_3"},
"playing=true,channel=4": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_4"},
"playing=false,channel=4": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_4"},
"playing=true,channel=5": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_5"},
"playing=false,channel=5": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_5"},
"playing=true,channel=6": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_6"},
"playing=false,channel=6": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_6"},
"playing=true,channel=7": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_7"},
"playing=false,channel=7": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_7"},
"playing=true,channel=8": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_8"},
"playing=false,channel=8": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_8"},
"playing=true,channel=9": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_9"},
"playing=false,channel=9": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_9"},
"playing=true,channel=10": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_10"},
"playing=false,channel=10": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_10"},
"playing=true,channel=11": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_11"},
"playing=false,channel=11": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_11"},
"playing=true,channel=12": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_12"},
"playing=false,channel=12": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_12"},
"playing=true,channel=13": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_13"},
"playing=false,channel=13": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_13"},
"playing=true,channel=14": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_14"},
"playing=false,channel=14": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_14"},
"playing=true,channel=15": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_15"},
"playing=false,channel=15": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_15"},
"playing=true,channel=16": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_16"},
"playing=false,channel=16": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_16"},
"playing=true,channel=17": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_17"},
"playing=false,channel=17": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_17"},
"playing=true,channel=18": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_18"},
"playing=false,channel=18": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_18"},
"playing=true,channel=19": {"model": "visualoverhaul:block/phonos/jukebox_top_playing_19"},
"playing=false,channel=19": {"model": "visualoverhaul:block/phonos/jukebox_top_stopped_19"}
}
}

View File

@@ -1,8 +1,8 @@
package eu.midnightdust.visualoverhaul.fabric;
import eu.midnightdust.visualoverhaul.FakeBlocks;
import eu.midnightdust.visualoverhaul.IconicButtons;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.block.JukeboxTop;
import eu.midnightdust.visualoverhaul.block.model.FurnaceWoodenPlanksModel;
import eu.midnightdust.visualoverhaul.block.renderer.BrewingStandBlockEntityRenderer;
import eu.midnightdust.visualoverhaul.block.renderer.FurnaceBlockEntityRenderer;
@@ -14,7 +14,6 @@ import eu.midnightdust.visualoverhaul.util.VOColorUtil;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
@@ -28,17 +27,8 @@ import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.BrewingStandBlockEntity;
import net.minecraft.client.color.world.BiomeColors;
import net.minecraft.client.data.ModelProvider;
import net.minecraft.client.data.Models;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.ModelData;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactories;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.Items;
import net.minecraft.potion.Potions;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier;
@@ -51,14 +41,10 @@ public class VisualOverhaulClientFabric implements ClientModInitializer {
@Override
public void onInitializeClient() {
VisualOverhaulClient.onInitializeClient();
JukeBoxTop = new JukeboxTop();
// Block only registered on client, because it's just used for the renderer //
Registry.register(Registries.BLOCK, id("jukebox_top"), JukeBoxTop);
EntityModelLayerRegistry.registerModelLayer(FurnaceWoodenPlanksModel.WOODEN_PLANKS_MODEL_LAYER, FurnaceWoodenPlanksModel::getTexturedModelData);
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.JUKEBOX, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(JukeBoxTop, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.FURNACE, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.SMOKER, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.BLAST_FURNACE, RenderLayer.getCutout());
@@ -131,6 +117,7 @@ public class VisualOverhaulClientFabric implements ClientModInitializer {
@Override
public void reload(ResourceManager manager) {
IconicButtons.reload(manager);
FakeBlocks.reload(manager);
}
});
}

View File

@@ -1,5 +1,6 @@
package eu.midnightdust.visualoverhaul.neoforge;
import eu.midnightdust.visualoverhaul.FakeBlocks;
import eu.midnightdust.visualoverhaul.IconicButtons;
import eu.midnightdust.visualoverhaul.block.model.FurnaceWoodenPlanksModel;
import eu.midnightdust.visualoverhaul.block.renderer.BrewingStandBlockEntityRenderer;
@@ -49,6 +50,7 @@ public class VisualOverhaulClientEvents {
@Override
public void reload(ResourceManager manager) {
IconicButtons.reload(manager);
FakeBlocks.reload(manager);
}
}
@SubscribeEvent

View File

@@ -1,7 +1,6 @@
package eu.midnightdust.visualoverhaul.neoforge;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.block.JukeboxTop;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import eu.midnightdust.visualoverhaul.util.VOColorUtil;
import net.minecraft.block.Block;
@@ -12,14 +11,12 @@ import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.registry.Registries;
import net.minecraft.resource.ResourcePackProfile;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.apache.commons.compress.utils.Lists;
import java.util.List;
import java.util.Objects;
import static eu.midnightdust.visualoverhaul.VisualOverhaulClient.*;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.*;
@@ -32,12 +29,6 @@ public class VisualOverhaulClientForge {
public static void initClient() {
VisualOverhaulClient.onInitializeClient();
// Block only registered on client, because it's just used for the renderer //
BLOCKS.register(Objects.requireNonNull(ModLoadingContext.get().getActiveContainer().getEventBus()));
BLOCKS.register("jukebox_top", () -> {
VisualOverhaulClient.JukeBoxTop = new JukeboxTop();
return VisualOverhaulClient.JukeBoxTop;
});
NeoForge.EVENT_BUS.addListener(VisualOverhaulClientForge::doClientTick);
RenderLayers.setRenderLayer(Blocks.JUKEBOX, RenderLayer.getCutout());