mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 00:37:52 +00:00
Minecraft 1.21.4
This commit is contained in:
219 files changed
+1841
-2621
No files matched your search
@@ -8,6 +8,10 @@ package net.minecraftforge.client;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
@@ -17,6 +21,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.math.Constants;
|
||||
import com.mojang.math.Transformation;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.FileUtil;
|
||||
@@ -26,7 +31,6 @@ import net.minecraft.client.ClientRecipeBook;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.color.item.ItemColors;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.ChatComponent;
|
||||
@@ -57,6 +61,8 @@ import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.ShaderDefines;
|
||||
import net.minecraft.client.renderer.ShaderProgram;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
@@ -85,6 +91,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceMetadata;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
@@ -139,6 +146,8 @@ import net.minecraftforge.client.extensions.common.IClientMobEffectExtensions;
|
||||
import net.minecraftforge.client.gui.ClientTooltipComponentManager;
|
||||
import net.minecraftforge.client.gui.ModMismatchDisconnectedScreen;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import net.minecraftforge.client.model.geometry.GeometryLoaderManager;
|
||||
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.client.textures.ForgeTextureMetadata;
|
||||
import net.minecraftforge.client.textures.TextureAtlasSpriteLoaderManager;
|
||||
import net.minecraftforge.common.ForgeConfig;
|
||||
@@ -175,6 +184,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -281,10 +291,6 @@ public class ForgeHooksClient {
|
||||
ModLoader.get().postEvent(new RegisterColorHandlersEvent.Block(blockColors));
|
||||
}
|
||||
|
||||
public static void onItemColorsInit(ItemColors itemColors, BlockColors blockColors) {
|
||||
ModLoader.get().postEvent(new RegisterColorHandlersEvent.Item(itemColors, blockColors));
|
||||
}
|
||||
|
||||
public static Model getArmorModel(HumanoidRenderState state, ItemStack itemStack, EquipmentSlot slot, HumanoidModel<?> _default) {
|
||||
return IClientItemExtensions.of(itemStack).getGenericArmorModel(state, itemStack, slot, _default);
|
||||
}
|
||||
@@ -414,71 +420,27 @@ public class ForgeHooksClient {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void onModifyBakingResult(Map<ModelResourceLocation, BakedModel> models, ModelBakery modelBakery) {
|
||||
ModLoader.get().postEvent(new ModelEvent.ModifyBakingResult(models, modelBakery));
|
||||
public static void onModifyBakingResult(ModelBakery modelBakery, ModelBakery.BakingResult results) {
|
||||
ModLoader.get().postEvent(new ModelEvent.ModifyBakingResult(modelBakery, results));
|
||||
}
|
||||
|
||||
public static void onModelBake(ModelManager modelManager, Map<ModelResourceLocation, BakedModel> models, ModelBakery modelBakery) {
|
||||
ModLoader.get().postEvent(new ModelEvent.BakingCompleted(modelManager, Collections.unmodifiableMap(models), modelBakery));
|
||||
public static void onModelBake(ModelManager modelManager, ModelBakery modelBakery) {
|
||||
ModLoader.get().postEvent(new ModelEvent.BakingCompleted(modelManager, modelBakery));
|
||||
}
|
||||
|
||||
public static TextureAtlasSprite[] getFluidSprites(BlockAndTintGetter level, BlockPos pos, FluidState fluidStateIn) {
|
||||
IClientFluidTypeExtensions props = IClientFluidTypeExtensions.of(fluidStateIn);
|
||||
ResourceLocation overlayTexture = props.getOverlayTexture(fluidStateIn, level, pos);
|
||||
@SuppressWarnings("deprecation")
|
||||
var BLOCKS = TextureAtlas.LOCATION_BLOCKS;
|
||||
var atlas = Minecraft.getInstance().getTextureAtlas(BLOCKS);
|
||||
return new TextureAtlasSprite[] {
|
||||
Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(props.getStillTexture(fluidStateIn, level, pos)),
|
||||
Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(props.getFlowingTexture(fluidStateIn, level, pos)),
|
||||
overlayTexture == null ? null : Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(overlayTexture),
|
||||
atlas.apply(props.getStillTexture(fluidStateIn, level, pos)),
|
||||
atlas.apply(props.getFlowingTexture(fluidStateIn, level, pos)),
|
||||
overlayTexture == null ? null : atlas.apply(overlayTexture),
|
||||
};
|
||||
}
|
||||
|
||||
public static Material getBlockMaterial(ResourceLocation loc) {
|
||||
return new Material(InventoryMenu.BLOCK_ATLAS, loc);
|
||||
}
|
||||
|
||||
/*
|
||||
public static void fillNormal(int[] faceData, Direction facing) {
|
||||
fillNormal(faceData, facing, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* internal, relies on fixed format of FaceBakery
|
||||
* /
|
||||
// TODO Do we need this?
|
||||
public static void fillNormal(int[] faceData, Direction facing, boolean calculateNormals) {
|
||||
Vector3f v2;
|
||||
if (calculateNormals) {
|
||||
Vector3f v1 = getVertexPos(faceData, 3);
|
||||
Vector3f t1 = getVertexPos(faceData, 1);
|
||||
v2 = getVertexPos(faceData, 2);
|
||||
Vector3f t2 = getVertexPos(faceData, 0);
|
||||
v1.sub(t1);
|
||||
v2.sub(t2);
|
||||
v2.cross(v1);
|
||||
v2.normalize();
|
||||
} else
|
||||
v2 = new Vector3f(facing.getNormal().getX(), facing.getNormal().getY(), facing.getNormal().getZ());
|
||||
int x = ((byte) Math.round(v2.x() * 127)) & 0xFF;
|
||||
int y = ((byte) Math.round(v2.y() * 127)) & 0xFF;
|
||||
int z = ((byte) Math.round(v2.z() * 127)) & 0xFF;
|
||||
|
||||
int normal = x | (y << 0x08) | (z << 0x10);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
faceData[i * 8 + 7] = normal;
|
||||
}
|
||||
*/
|
||||
|
||||
private static Vector3f getVertexPos(int[] data, int vertex) {
|
||||
int idx = vertex * 8;
|
||||
|
||||
float x = Float.intBitsToFloat(data[idx]);
|
||||
float y = Float.intBitsToFloat(data[idx + 1]);
|
||||
float z = Float.intBitsToFloat(data[idx + 2]);
|
||||
|
||||
return new Vector3f(x, y, z);
|
||||
}
|
||||
|
||||
public static boolean calculateFaceWithoutAO(BlockAndTintGetter getter, BlockState state, BlockPos pos, BakedQuad quad, boolean isFaceCubic, float[] brightness, int[] lightmap) {
|
||||
if (quad.hasAmbientOcclusion())
|
||||
return false;
|
||||
@@ -933,4 +895,39 @@ public class ForgeHooksClient {
|
||||
|| screen.mouseDragged(mouseX, mouseY, mouseButton, dragX, dragY)
|
||||
|| ForgeEventFactoryClient.onScreenMouseDragPost(screen, mouseX, mouseY, mouseButton, dragX, dragY);
|
||||
}
|
||||
|
||||
public static BlockModel deserializeBlockModel(BlockModel model, List<BlockElement> elements, JsonObject json, JsonDeserializationContext context) {
|
||||
IUnbakedGeometry<?> geometry = null;
|
||||
if (json.has("loader")) {
|
||||
var name = ResourceLocation.parse(GsonHelper.getAsString(json, "loader"));
|
||||
var loader = GeometryLoaderManager.get(name);
|
||||
if (loader == null)
|
||||
throw new JsonParseException(String.format(Locale.ENGLISH, "Model loader '%s' not found. Registered loaders: %s", name, GeometryLoaderManager.getLoaderList()));
|
||||
|
||||
geometry = loader.read(json, context);
|
||||
}
|
||||
|
||||
if (geometry != null) {
|
||||
elements.clear();
|
||||
model.customData.setCustomGeometry(geometry);
|
||||
}
|
||||
|
||||
if (json.has("transform")) {
|
||||
JsonElement transform = json.get("transform");
|
||||
model.customData.setRootTransform(context.deserialize(transform, Transformation.class));
|
||||
}
|
||||
|
||||
if (json.has("render_type")) {
|
||||
var renderTypeHintName = GsonHelper.getAsString(json, "render_type");
|
||||
model.customData.setRenderTypeHint(ResourceLocation.parse(renderTypeHintName));
|
||||
}
|
||||
|
||||
if (json.has("visibility")) {
|
||||
var visibility = GsonHelper.getAsJsonObject(json, "visibility");
|
||||
for (var part : visibility.entrySet())
|
||||
model.customData.visibilityData.setVisibilityState(part.getKey(), part.getValue().getAsBoolean());
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import net.minecraft.client.renderer.RenderStateShard.TextureStateShard;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.TriState;
|
||||
@@ -23,17 +25,22 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public enum ForgeRenderTypes {
|
||||
ITEM_LAYERED_SOLID(()-> getItemLayeredSolid(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_LAYERED_CUTOUT(()-> getItemLayeredCutout(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_LAYERED_CUTOUT_MIPPED(()-> getItemLayeredCutoutMipped(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_LAYERED_TRANSLUCENT(()-> getItemLayeredTranslucent(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_UNSORTED_TRANSLUCENT(()-> getUnsortedTranslucent(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(InventoryMenu.BLOCK_ATLAS)),
|
||||
ITEM_UNSORTED_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(InventoryMenu.BLOCK_ATLAS, false)),
|
||||
TRANSLUCENT_ON_PARTICLES_TARGET(() -> getTranslucentParticlesTarget(InventoryMenu.BLOCK_ATLAS));
|
||||
ITEM_LAYERED_SOLID(()-> getItemLayeredSolid(blockAtlas())),
|
||||
ITEM_LAYERED_CUTOUT(()-> getItemLayeredCutout(blockAtlas())),
|
||||
ITEM_LAYERED_CUTOUT_MIPPED(()-> getItemLayeredCutoutMipped(blockAtlas())),
|
||||
ITEM_LAYERED_TRANSLUCENT(()-> getItemLayeredTranslucent(blockAtlas())),
|
||||
ITEM_UNSORTED_TRANSLUCENT(()-> getUnsortedTranslucent(blockAtlas())),
|
||||
ITEM_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(blockAtlas())),
|
||||
ITEM_UNSORTED_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(blockAtlas(), false)),
|
||||
TRANSLUCENT_ON_PARTICLES_TARGET(() -> getTranslucentParticlesTarget(blockAtlas()));
|
||||
|
||||
public static TriState enableTextTextureLinearFiltering = TriState.FALSE;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final ResourceLocation blockAtlas() {
|
||||
return TextureAtlas.LOCATION_BLOCKS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A RenderType fit for multi-layer solid item rendering.
|
||||
*/
|
||||
@@ -348,7 +355,7 @@ public enum ForgeRenderTypes {
|
||||
this.mipmap = mipmap.get();
|
||||
TextureManager manager = Minecraft.getInstance().getTextureManager();
|
||||
var texture = manager.getTexture(resLoc);
|
||||
texture.setFilter(this.blur.toBoolean(texture.getDefaultBlur()), this.mipmap);
|
||||
texture.setFilter(this.blur, this.mipmap);
|
||||
RenderSystem.setShaderTexture(0, resLoc);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.renderer.special.SpecialModelRenderer;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
public class CreateSpecialBlockRendererEvent extends Event {
|
||||
private final Map<Block, SpecialModelRenderer.Unbaked> map;
|
||||
|
||||
public CreateSpecialBlockRendererEvent(Map<Block, SpecialModelRenderer.Unbaked> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void register(Block block, SpecialModelRenderer.Unbaked renderer) {
|
||||
this.map.put(block, renderer);
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@@ -201,20 +202,11 @@ public abstract class EntityRenderersEvent extends Event implements IModBusEvent
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static class CreateSkullModels extends EntityRenderersEvent {
|
||||
private final ImmutableMap.Builder<Type, SkullModelBase> builder;
|
||||
private final EntityModelSet entityModelSet;
|
||||
private final ImmutableMap.Builder<Type, Function<EntityModelSet, SkullModelBase>> builder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public CreateSkullModels(ImmutableMap.Builder<Type, SkullModelBase> builder, EntityModelSet entityModelSet) {
|
||||
public CreateSkullModels(ImmutableMap.Builder<Type, Function<EntityModelSet, SkullModelBase>> builder) {
|
||||
this.builder = builder;
|
||||
this.entityModelSet = entityModelSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the set of entity models}
|
||||
*/
|
||||
public EntityModelSet getEntityModelSet() {
|
||||
return entityModelSet;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +220,7 @@ public abstract class EntityRenderersEvent extends Event implements IModBusEvent
|
||||
* {@link EntityModelSet#bakeLayer(ModelLayerLocation)} and pass it to the constructor for
|
||||
* {@link SkullModel}.
|
||||
*/
|
||||
public void registerSkullModel(SkullBlock.Type type, SkullModelBase model) {
|
||||
public void registerSkullModel(SkullBlock.Type type, Function<EntityModelSet, SkullModelBase> model) {
|
||||
builder.put(type, model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ package net.minecraftforge.client.event;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
@@ -17,6 +19,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -32,6 +35,8 @@ import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.model.SkullModelBase;
|
||||
import net.minecraft.client.model.geom.EntityModelSet;
|
||||
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
@@ -45,6 +50,7 @@ import net.minecraft.client.renderer.entity.state.EntityRenderState;
|
||||
import net.minecraft.client.renderer.entity.state.ItemFrameRenderState;
|
||||
import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
|
||||
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
|
||||
import net.minecraft.client.renderer.special.SpecialModelRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin.Model;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.sounds.SoundEngine;
|
||||
@@ -57,6 +63,8 @@ import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SkullBlock.Type;
|
||||
import net.minecraftforge.client.event.sound.PlaySoundSourceEvent;
|
||||
import net.minecraftforge.client.event.sound.PlayStreamingSourceEvent;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
@@ -86,8 +94,9 @@ public final class ForgeEventFactoryClient {
|
||||
/**
|
||||
* Post an event to the {@link ModLoader#get()} event bus
|
||||
*/
|
||||
private static <T extends Event & IModBusEvent> void postModBus(T e) {
|
||||
private static <T extends Event & IModBusEvent> T postModBus(T e) {
|
||||
ML.postEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
public static void onGatherLayers(Map<EntityType<?>, EntityRenderer<?, ?>> renderers, Map<Model, EntityRenderer<? extends Player, ?>> playerRenderers, Context context) {
|
||||
@@ -279,4 +288,14 @@ public final class ForgeEventFactoryClient {
|
||||
public static ComputeFovModifierEvent fireFovModifierEvent(Player entity, float modifier, float scale) {
|
||||
return fire(new ComputeFovModifierEvent(entity, modifier, scale));
|
||||
}
|
||||
|
||||
public static void onCreateSpecialBlockRenderers(Map<Block, SpecialModelRenderer.Unbaked> map) {
|
||||
post(new CreateSpecialBlockRendererEvent(map));
|
||||
}
|
||||
|
||||
public static Map<Type, Function<EntityModelSet, SkullModelBase>> onCreateSkullModels() {
|
||||
var builder = ImmutableMap.<Type, Function<EntityModelSet, SkullModelBase>>builder();
|
||||
postModBus(new EntityRenderersEvent.CreateSkullModels(builder));
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -46,20 +46,20 @@ public abstract class ModelEvent extends Event {
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static class ModifyBakingResult extends ModelEvent implements IModBusEvent {
|
||||
private final Map<ModelResourceLocation, BakedModel> models;
|
||||
private final ModelBakery modelBakery;
|
||||
private final ModelBakery.BakingResult results;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ModifyBakingResult(Map<ModelResourceLocation, BakedModel> models, ModelBakery modelBakery) {
|
||||
this.models = models;
|
||||
public ModifyBakingResult(ModelBakery modelBakery, ModelBakery.BakingResult results) {
|
||||
this.modelBakery = modelBakery;
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the modifiable registry map of models and their model names
|
||||
*/
|
||||
public Map<ModelResourceLocation, BakedModel> getModels() {
|
||||
return models;
|
||||
public ModelBakery.BakingResult getResults() {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +83,11 @@ public abstract class ModelEvent extends Event {
|
||||
*/
|
||||
public static class BakingCompleted extends ModelEvent implements IModBusEvent {
|
||||
private final ModelManager modelManager;
|
||||
private final Map<ModelResourceLocation, BakedModel> models;
|
||||
private final ModelBakery modelBakery;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public BakingCompleted(ModelManager modelManager, Map<ModelResourceLocation, BakedModel> models, ModelBakery modelBakery) {
|
||||
public BakingCompleted(ModelManager modelManager, ModelBakery modelBakery) {
|
||||
this.modelManager = modelManager;
|
||||
this.models = models;
|
||||
this.modelBakery = modelBakery;
|
||||
}
|
||||
|
||||
@@ -100,13 +98,6 @@ public abstract class ModelEvent extends Event {
|
||||
return modelManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an unmodifiable view of the registry map of models and their model names
|
||||
*/
|
||||
public Map<ModelResourceLocation, BakedModel> getModels() {
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the model loader
|
||||
*/
|
||||
|
||||
@@ -8,11 +8,8 @@ package net.minecraftforge.client.event;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.color.block.BlockColor;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
import net.minecraft.client.color.item.ItemColors;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
@@ -71,56 +68,6 @@ public abstract class RegisterColorHandlersEvent extends Event implements IModBu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired for registering item color handlers.
|
||||
*
|
||||
* <p>The block colors should only be used for referencing or delegating item colors to their respective block
|
||||
* colors. Use {@link RegisterColorHandlersEvent.Block} for registering your block color handlers.</p>
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static class Item extends RegisterColorHandlersEvent {
|
||||
private final ItemColors itemColors;
|
||||
private final BlockColors blockColors;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Item(ItemColors itemColors, BlockColors blockColors) {
|
||||
this.itemColors = itemColors;
|
||||
this.blockColors = blockColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the item colors registry}
|
||||
*
|
||||
* @see ItemColors#register(ItemColor, ItemLike...)
|
||||
*/
|
||||
public ItemColors getItemColors() {
|
||||
return itemColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the block colors registry}
|
||||
* This should only be used for referencing or delegating item colors to their respective block colors.
|
||||
*/
|
||||
public BlockColors getBlockColors() {
|
||||
return blockColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link ItemColor} instance for a set of blocks.
|
||||
*
|
||||
* @param itemColor The color provider
|
||||
* @param items The items
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void register(ItemColor itemColor, ItemLike... items) {
|
||||
itemColors.register(itemColor, items);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows registration of custom {@link ColorResolver} implementations to be used with
|
||||
* {@link net.minecraft.world.level.BlockAndTintGetter#getBlockTint(BlockPos, ColorResolver)}.
|
||||
|
||||
+6
-4
@@ -6,6 +6,8 @@
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.BiMap;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.textures.ITextureAtlasSpriteLoader;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
@@ -16,8 +18,6 @@ import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Allows users to register custom {@link ITextureAtlasSpriteLoader texture atlas sprite loaders}.
|
||||
*
|
||||
@@ -27,10 +27,10 @@ import java.util.Map;
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public class RegisterTextureAtlasSpriteLoadersEvent extends Event implements IModBusEvent {
|
||||
private final Map<ResourceLocation, ITextureAtlasSpriteLoader> loaders;
|
||||
private final BiMap<ResourceLocation, ITextureAtlasSpriteLoader> loaders;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RegisterTextureAtlasSpriteLoadersEvent(Map<ResourceLocation, ITextureAtlasSpriteLoader> loaders) {
|
||||
public RegisterTextureAtlasSpriteLoadersEvent(BiMap<ResourceLocation, ITextureAtlasSpriteLoader> loaders) {
|
||||
this.loaders = loaders;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ public class RegisterTextureAtlasSpriteLoadersEvent extends Event implements IMo
|
||||
* Registers a custom {@link ITextureAtlasSpriteLoader sprite loader}.
|
||||
*/
|
||||
public void register(String name, ITextureAtlasSpriteLoader loader) {
|
||||
@SuppressWarnings("removal")
|
||||
var key = ResourceLocation.fromNamespaceAndPath(ModLoadingContext.get().getActiveNamespace(), name);
|
||||
Preconditions.checkArgument(!loaders.containsKey(key), "Sprite loader already registered: " + key);
|
||||
Preconditions.checkArgument(!loaders.containsValue(loader), "Sprite loader already registered as " + loaders.inverse().get(loader));
|
||||
loaders.put(key, loader);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemFrameRenderer;
|
||||
import net.minecraft.client.renderer.entity.state.ItemFrameRenderState;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
@@ -46,13 +45,6 @@ public class RenderItemInFrameEvent extends Event {
|
||||
this.packedLight = packedLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the item stack being rendered}
|
||||
*/
|
||||
public ItemStack getItemStack() {
|
||||
return getItemFrameState().itemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the item frame entity}
|
||||
*/
|
||||
|
||||
@@ -89,9 +89,11 @@ public interface IForgeBakedModel {
|
||||
*
|
||||
* @see #getRenderPasses(ItemStack, boolean)
|
||||
*/
|
||||
/*
|
||||
default List<RenderType> getRenderTypes(ItemStack itemStack, boolean fabulous) {
|
||||
return List.of(RenderTypeHelper.getFallbackItemRenderType(itemStack, self()));
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets an ordered list of baked models used to render this model as an item.
|
||||
@@ -101,7 +103,9 @@ public interface IForgeBakedModel {
|
||||
*
|
||||
* @see #getRenderTypes(ItemStack, boolean)
|
||||
*/
|
||||
/*
|
||||
default List<BakedModel> getRenderPasses(ItemStack itemStack, boolean fabulous) {
|
||||
return List.of(self());
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.extensions;
|
||||
|
||||
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.ModelState;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface IForgeModelBaker {
|
||||
@Nullable
|
||||
BakedModel bake(ResourceLocation location, ModelState state, Function<Material, TextureAtlasSprite> sprites);
|
||||
|
||||
Function<Material, TextureAtlasSprite> getModelTextureGetter();
|
||||
}
|
||||
+3
-5
@@ -5,16 +5,14 @@
|
||||
|
||||
package net.minecraftforge.client.extensions.common;
|
||||
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.FogParameters;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.ScreenEffectRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -137,10 +135,10 @@ public interface IClientFluidTypeExtensions {
|
||||
* @param mc the client instance
|
||||
* @param poseStack the transformations representing the current rendering position
|
||||
*/
|
||||
default void renderOverlay(Minecraft mc, PoseStack poseStack) {
|
||||
default void renderOverlay(Minecraft mc, PoseStack poseStack, MultiBufferSource buffer) {
|
||||
ResourceLocation texture = this.getRenderOverlayTexture(mc);
|
||||
if (texture != null)
|
||||
ScreenEffectRenderer.renderFluid(mc, poseStack, texture);
|
||||
ScreenEffectRenderer.renderFluid(mc, poseStack, buffer, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
package net.minecraftforge.client.extensions.common;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.Model;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
|
||||
import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
@@ -22,7 +19,6 @@ import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.IArmPoseTransformer;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
@@ -142,18 +138,6 @@ public interface IClientItemExtensions {
|
||||
*/
|
||||
default void renderHelmetOverlay(ItemStack stack, Player player, int width, int height, float partialTick) { }
|
||||
|
||||
/**
|
||||
* Queries this item's renderer.
|
||||
* <p>
|
||||
* Only used if {@link BakedModel#isCustomRenderer()} returns {@code true} or {@link BlockState#getRenderShape()}
|
||||
* returns {@link net.minecraft.world.level.block.RenderShape#ENTITYBLOCK_ANIMATED}.
|
||||
* <p>
|
||||
* By default, returns vanilla's block entity renderer.
|
||||
*/
|
||||
default BlockEntityWithoutLevelRenderer getCustomRenderer() {
|
||||
return Minecraft.getInstance().getItemRenderer().getBlockEntityRenderer();
|
||||
}
|
||||
|
||||
enum FontContext {
|
||||
/**
|
||||
* Used to display the amount of items in the {@link ItemStack}.
|
||||
|
||||
@@ -103,11 +103,6 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||
warnings.forEach(w->addEntry(new LoadingMessageEntry(Component.literal(w.formatToString()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollbarPosition() {
|
||||
return this.getRight() - 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowWidth() {
|
||||
return this.width;
|
||||
|
||||
@@ -22,7 +22,6 @@ import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.client.gui.widget.ModListWidget;
|
||||
import net.minecraftforge.client.gui.widget.ScrollPanel;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.maven.artifact.versioning.ComparableVersion;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@@ -58,6 +57,7 @@ import net.minecraft.network.chat.Style;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class ModListScreen extends Screen {
|
||||
private static final ResourceLocation LOGO = ResourceLocation.fromNamespaceAndPath("forge", "mod_logo");
|
||||
private static String stripControlCodes(String value) { return net.minecraft.util.StringUtil.stripColor(value); }
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private enum SortType implements Comparator<IModInfo> {
|
||||
@@ -378,6 +378,9 @@ public class ModListScreen extends Screen {
|
||||
updateCache();
|
||||
}
|
||||
|
||||
record Logo(ResourceLocation texture, Size2i size) {}
|
||||
private static final Logo NONE = new Logo(null, new Size2i(0, 0));
|
||||
|
||||
private void updateCache() {
|
||||
if (selected == null) {
|
||||
this.configButton.active = false;
|
||||
@@ -390,8 +393,9 @@ public class ModListScreen extends Screen {
|
||||
List<String> lines = new ArrayList<>();
|
||||
VersionChecker.CheckResult vercheck = VersionChecker.getResult(selectedMod);
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
Pair<ResourceLocation, Size2i> logoData = selectedMod.getLogoFile().map(logoFile -> {
|
||||
var logoData = NONE;
|
||||
var logoFile = selectedMod.getLogoFile().orElse(null);
|
||||
if (logoFile != null) {
|
||||
TextureManager tm = this.minecraft.getTextureManager();
|
||||
|
||||
try {
|
||||
@@ -404,20 +408,26 @@ public class ModListScreen extends Screen {
|
||||
}
|
||||
|
||||
if (logo != null) {
|
||||
return Pair.of(tm.register("modlogo", new DynamicTexture(logo) {
|
||||
|
||||
var texture = new DynamicTexture(logo) {
|
||||
@Override
|
||||
public void upload() {
|
||||
this.bind();
|
||||
NativeImage td = this.getPixels();
|
||||
// Use custom "blur" value which controls texture filtering (nearest-neighbor vs linear)
|
||||
this.getPixels().upload(0, 0, 0, 0, 0, td.getWidth(), td.getHeight(), selectedMod.getLogoBlur(), false, false, false);
|
||||
var pixels = this.getPixels();
|
||||
if (pixels != null) {
|
||||
this.bind();
|
||||
// Use custom "blur" value which controls texture filtering (nearest-neighbor vs linear)
|
||||
pixels.upload(0, 0, 0, selectedMod.getLogoBlur());
|
||||
}
|
||||
}
|
||||
}), new Size2i(logo.getWidth(), logo.getHeight()));
|
||||
};
|
||||
|
||||
tm.register(LOGO, texture);
|
||||
var size = new Size2i(logo.getWidth(), logo.getHeight());
|
||||
|
||||
logoData = new Logo(LOGO, size);
|
||||
}
|
||||
} catch (IOException e) { }
|
||||
|
||||
return Pair.<ResourceLocation, Size2i>of(null, new Size2i(0, 0));
|
||||
}).orElse(Pair.of(null, new Size2i(0, 0)));
|
||||
}
|
||||
|
||||
lines.add(selectedMod.getDisplayName());
|
||||
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.version", MavenVersionStringHelper.artifactVersionToString(selectedMod.getVersion())));
|
||||
@@ -461,7 +471,7 @@ public class ModListScreen extends Screen {
|
||||
}
|
||||
}
|
||||
|
||||
modInfo.setInfo(lines, logoData.getLeft(), logoData.getRight());
|
||||
modInfo.setInfo(lines, logoData.texture(), logoData.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,11 +35,6 @@ public class ModListWidget extends ObjectSelectionList<ModListWidget.ModEntry> {
|
||||
this.refreshList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollbarPosition() {
|
||||
return this.listWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowWidth() {
|
||||
return this.listWidth;
|
||||
|
||||
@@ -7,7 +7,6 @@ package net.minecraftforge.client.model;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedOverrides;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
@@ -16,7 +15,6 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||
@@ -68,11 +66,6 @@ public abstract class BakedModelWrapper<T extends BakedModel> implements BakedMo
|
||||
return originalModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer() {
|
||||
return originalModel.isCustomRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleIcon() {
|
||||
return originalModel.getParticleIcon();
|
||||
@@ -83,11 +76,6 @@ public abstract class BakedModelWrapper<T extends BakedModel> implements BakedMo
|
||||
return originalModel.getTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedOverrides overrides() {
|
||||
return originalModel.overrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel applyTransform(ItemDisplayContext cameraTransformType, PoseStack poseStack, boolean applyLeftHandTransform) {
|
||||
return originalModel.applyTransform(cameraTransformType, poseStack, applyLeftHandTransform);
|
||||
@@ -114,14 +102,4 @@ public abstract class BakedModelWrapper<T extends BakedModel> implements BakedMo
|
||||
public ChunkRenderTypeSet getRenderTypes(@NotNull BlockState state, @NotNull RandomSource rand, @NotNull ModelData data) {
|
||||
return originalModel.getRenderTypes(state, rand, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RenderType> getRenderTypes(ItemStack itemStack, boolean fabulous) {
|
||||
return originalModel.getRenderTypes(itemStack, fabulous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedModel> getRenderPasses(ItemStack itemStack, boolean fabulous) {
|
||||
return originalModel.getRenderPasses(itemStack, fabulous);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
@@ -64,9 +65,8 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
Material particleLocation = context.getMaterial("particle");
|
||||
TextureAtlasSprite particle = spriteGetter.apply(particleLocation);
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots textures, ModelState modelState) {
|
||||
var particle = baker.sprites().maybeMissing(textures, "particle");
|
||||
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
@@ -78,7 +78,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
|
||||
if (!context.isComponentVisible(name, true))
|
||||
continue;
|
||||
var model = entry.getValue();
|
||||
bakedPartsBuilder.put(name, model.bake(baker, spriteGetter, modelState));
|
||||
bakedPartsBuilder.put(name, model.bake(textures, baker, modelState, model.getAmbientOcclusion(), model.getGuiLight().lightLikeBlock(), model.getTransforms()));
|
||||
}
|
||||
var bakedParts = bakedPartsBuilder.build();
|
||||
|
||||
@@ -158,11 +158,6 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
|
||||
return isSideLit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleIcon() {
|
||||
return particle;
|
||||
@@ -181,11 +176,6 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
|
||||
return ChunkRenderTypeSet.union(sets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedModel> getRenderPasses(ItemStack itemStack, boolean fabulous) {
|
||||
return itemPasses;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BakedModel getPart(String name) {
|
||||
return children.get(name);
|
||||
@@ -223,7 +213,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
|
||||
}
|
||||
|
||||
private void addLayer(RenderTypeGroup renderTypes, List<BakedQuad> quads) {
|
||||
var modelBuilder = IModelBuilder.of(isAmbientOcclusion, isSideLit, isGui3d, transforms, particle, renderTypes);
|
||||
var modelBuilder = IModelBuilder.of(isAmbientOcclusion, isSideLit, isGui3d, transforms, particle/*, renderTypes*/);
|
||||
quads.forEach(modelBuilder::addUnculledFace);
|
||||
children.add(modelBuilder.build());
|
||||
}
|
||||
|
||||
@@ -5,27 +5,21 @@
|
||||
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedOverrides;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.BlockModelRotation;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.ForgeRenderTypes;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
|
||||
@@ -34,18 +28,10 @@ import net.minecraftforge.client.model.geometry.IGeometryLoader;
|
||||
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.client.model.geometry.StandaloneGeometryBakingContext;
|
||||
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
|
||||
import net.minecraftforge.fluids.FluidUtil;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static net.minecraftforge.client.model.geometry.StandaloneGeometryBakingContext.LOCATION;
|
||||
|
||||
/**
|
||||
* A dynamic fluid container model, capable of re-texturing itself at runtime to match the contained fluid.
|
||||
* <p>
|
||||
@@ -85,18 +71,21 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
return new DynamicFluidContainerModel(newFluid, flipGas, coverIsMask, applyFluidLuminosity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
Material particleLocation = context.hasMaterial("particle") ? context.getMaterial("particle") : null;
|
||||
Material baseLocation = context.hasMaterial("base") ? context.getMaterial("base") : null;
|
||||
Material fluidMaskLocation = context.hasMaterial("fluid") ? context.getMaterial("fluid") : null;
|
||||
Material coverLocation = context.hasMaterial("cover") ? context.getMaterial("cover") : null;
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots textures, ModelState modelState) {
|
||||
Material fluidMaskLocation = textures.getMaterial("fluid");
|
||||
Material stillMaterial = null;
|
||||
if (fluid != Fluids.EMPTY) {
|
||||
var stillTexture = IClientFluidTypeExtensions.of(fluid).getStillTexture();
|
||||
stillMaterial = new Material(TextureAtlas.LOCATION_BLOCKS, stillTexture);
|
||||
}
|
||||
|
||||
TextureAtlasSprite baseSprite = baseLocation != null ? spriteGetter.apply(baseLocation) : null;
|
||||
TextureAtlasSprite fluidSprite = fluid != Fluids.EMPTY ? spriteGetter.apply(ForgeHooksClient.getBlockMaterial(IClientFluidTypeExtensions.of(fluid).getStillTexture())) : null;
|
||||
TextureAtlasSprite coverSprite = (coverLocation != null && (!coverIsMask || baseLocation != null)) ? spriteGetter.apply(coverLocation) : null;
|
||||
|
||||
TextureAtlasSprite particleSprite = particleLocation != null ? spriteGetter.apply(particleLocation) : null;
|
||||
var sprites = baker.sprites();
|
||||
var baseSprite = sprites.maybeMissing(textures, "base");
|
||||
var fluidSprite = stillMaterial == null ? null : sprites.get(stillMaterial);
|
||||
var coverSprite = sprites.maybeMissing(textures, "cover"); // (coverLocation != null && (!coverIsMask || baseLocation != null)) ? textures.apply(coverLocation) : null;
|
||||
var particleSprite = sprites.maybeMissing(textures, "particle");
|
||||
|
||||
if (particleSprite == null) particleSprite = fluidSprite;
|
||||
if (particleSprite == null) particleSprite = baseSprite;
|
||||
@@ -110,12 +99,12 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
}
|
||||
|
||||
// We need to disable GUI 3D and block lighting for this to render properly
|
||||
var itemContext = StandaloneGeometryBakingContext.builder(context).withGui3d(false).withUseBlockLight(false).build(LOCATION);
|
||||
var itemContext = StandaloneGeometryBakingContext.builder(context).withGui3d(false).withUseBlockLight(false).build();
|
||||
var modelBuilder = CompositeModel.Baked.builder(itemContext, particleSprite, /*new ContainedFluidOverrideHandler(baker, itemContext, this),*/ context.getTransforms());
|
||||
|
||||
var normalRenderTypes = getLayerRenderTypes(false);
|
||||
|
||||
if (baseLocation != null && baseSprite != null) {
|
||||
if (baseSprite != null) {
|
||||
// Base texture
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(0, baseSprite.contents());
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> baseSprite, modelState);
|
||||
@@ -123,7 +112,7 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
}
|
||||
|
||||
if (fluidMaskLocation != null && fluidSprite != null) {
|
||||
TextureAtlasSprite templateSprite = spriteGetter.apply(fluidMaskLocation);
|
||||
TextureAtlasSprite templateSprite = sprites.get(fluidMaskLocation);
|
||||
if (templateSprite != null) {
|
||||
// Fluid layer
|
||||
var transformedState = new SimpleModelState(modelState.getRotation().compose(FLUID_TRANSFORM), modelState.isUvLocked());
|
||||
@@ -154,17 +143,13 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
return modelBuilder.build();
|
||||
}
|
||||
|
||||
public static final class Loader implements IGeometryLoader<DynamicFluidContainerModel>
|
||||
{
|
||||
public static final class Loader implements IGeometryLoader<DynamicFluidContainerModel> {
|
||||
public static final Loader INSTANCE = new Loader();
|
||||
|
||||
private Loader()
|
||||
{
|
||||
}
|
||||
private Loader() { }
|
||||
|
||||
@Override
|
||||
public DynamicFluidContainerModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext)
|
||||
{
|
||||
public DynamicFluidContainerModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) {
|
||||
if (!jsonObject.has("fluid"))
|
||||
throw new RuntimeException("Bucket model requires 'fluid' value.");
|
||||
|
||||
@@ -180,52 +165,4 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
return new DynamicFluidContainerModel(fluid, flip, coverIsMask, applyFluidLuminosity);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ContainedFluidOverrideHandler extends BakedOverrides {
|
||||
private final Map<String, BakedModel> cache = Maps.newHashMap(); // contains all the baked models since they'll never change
|
||||
private final BakedOverrides nested;
|
||||
private final ModelBaker baker;
|
||||
private final IGeometryBakingContext owner;
|
||||
private final DynamicFluidContainerModel parent;
|
||||
|
||||
private ContainedFluidOverrideHandler(BakedOverrides nested, ModelBaker baker, IGeometryBakingContext owner, DynamicFluidContainerModel parent) {
|
||||
this.nested = nested;
|
||||
this.baker = baker;
|
||||
this.owner = owner;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel findOverride(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
|
||||
BakedModel overridden = nested.findOverride(stack, level, entity, seed);
|
||||
if (overridden != null)
|
||||
return overridden;
|
||||
|
||||
var fluidStack = FluidUtil.getFluidContained(stack).orElse(null);
|
||||
if (fluidStack == null)
|
||||
return null;
|
||||
|
||||
Fluid fluid = fluidStack.getFluid();
|
||||
String name = ForgeRegistries.FLUIDS.getKey(fluid).toString();
|
||||
|
||||
if (!cache.containsKey(name)) {
|
||||
DynamicFluidContainerModel unbaked = this.parent.withFluid(fluid);
|
||||
BakedModel bakedModel = unbaked.bake(owner, baker, Material::sprite, BlockModelRotation.X0_Y0);//, nested);
|
||||
cache.put(name, bakedModel);
|
||||
return bakedModel;
|
||||
}
|
||||
|
||||
return cache.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Colors implements ItemColor {
|
||||
@Override
|
||||
public int getColor(@NotNull ItemStack stack, int tintIndex) {
|
||||
if (tintIndex != 1) return 0xFFFFFFFF;
|
||||
return FluidUtil.getFluidContained(stack)
|
||||
.map(fluidStack -> IClientFluidTypeExtensions.of(fluidStack.getFluid()).getTintColor(fluidStack))
|
||||
.orElse(0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,15 +11,11 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.client.resources.model.SimpleBakedModel;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryLoader;
|
||||
@@ -29,18 +25,17 @@ import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
|
||||
/**
|
||||
* A model composed of vanilla {@linkplain BlockElement block elements}.
|
||||
*/
|
||||
public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
{
|
||||
public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel> {
|
||||
private final List<BlockElement> elements;
|
||||
|
||||
public ElementsModel(List<BlockElement> elements)
|
||||
{
|
||||
public ElementsModel(List<BlockElement> elements) {
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState)
|
||||
{
|
||||
protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelState) {
|
||||
//protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
// If there is a root transform, undo the ModelState transform, apply it, then re-apply the ModelState transform.
|
||||
// This is necessary because of things like UV locking, which should only respond to the ModelState, and as such
|
||||
// that is the only transform that should be applied during face bake.
|
||||
@@ -48,14 +43,13 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
postTransform = UnbakedGeometryHelper.applyRootTransform(modelState, rootTransform);
|
||||
var sprites = baker.sprites();
|
||||
|
||||
for (BlockElement element : elements)
|
||||
{
|
||||
for (Direction direction : element.faces.keySet())
|
||||
{
|
||||
for (var element : elements) {
|
||||
for (var direction : element.faces.keySet()) {
|
||||
var face = element.faces.get(direction);
|
||||
var sprite = spriteGetter.apply(context.getMaterial(face.texture()));
|
||||
var quad = BlockModel.bakeFace(element, face, sprite, direction, modelState);
|
||||
var sprite = sprites.maybeMissing(textures, face.texture());
|
||||
var quad = SimpleBakedModel.bakeFace(element, face, sprite, direction, modelState);
|
||||
postTransform.processInPlace(quad);
|
||||
|
||||
if (face.cullForDirection() == null)
|
||||
@@ -66,25 +60,18 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Loader implements IGeometryLoader<ElementsModel>
|
||||
{
|
||||
public static final class Loader implements IGeometryLoader<ElementsModel> {
|
||||
public static final Loader INSTANCE = new Loader();
|
||||
|
||||
private Loader()
|
||||
{
|
||||
}
|
||||
private Loader() { }
|
||||
|
||||
@Override
|
||||
public ElementsModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException
|
||||
{
|
||||
public ElementsModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException {
|
||||
if (!jsonObject.has("elements"))
|
||||
throw new JsonParseException("An element model must have an \"elements\" member.");
|
||||
|
||||
List<BlockElement> elements = new ArrayList<>();
|
||||
for (JsonElement element : GsonHelper.getAsJsonArray(jsonObject, "elements"))
|
||||
{
|
||||
elements.add(deserializationContext.deserialize(element, BlockElement.class));
|
||||
}
|
||||
|
||||
return new ElementsModel(elements);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,16 @@ package net.minecraftforge.client.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
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.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.SimpleBakedModel;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryLoader;
|
||||
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
@@ -37,20 +36,20 @@ public class EmptyModel extends SimpleUnbakedGeometry<EmptyModel> {
|
||||
private EmptyModel() { }
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform) {
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelTransform) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots spriteGetter, ModelState modelState) {
|
||||
return BAKED;
|
||||
}
|
||||
|
||||
private static class Baked extends SimpleBakedModel {
|
||||
private static final Material MISSING_TEXTURE = new Material(InventoryMenu.BLOCK_ATLAS, MissingTextureAtlasSprite.getLocation());
|
||||
private static final Material MISSING_TEXTURE = new Material(TextureAtlas.LOCATION_BLOCKS, MissingTextureAtlasSprite.getLocation());
|
||||
|
||||
public Baked() {
|
||||
super(List.of(), Map.of(), false, false, false, UnitTextureAtlasSprite.INSTANCE, ItemTransforms.NO_TRANSFORMS, RenderTypeGroup.EMPTY);
|
||||
super(List.of(), Map.of(), false, false, false, UnitTextureAtlasSprite.INSTANCE, ItemTransforms.NO_TRANSFORMS/*, RenderTypeGroup.EMPTY*/);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockElementFace;
|
||||
import net.minecraft.client.renderer.block.model.BlockFaceUV;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverride;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransform;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraftforge.client.model.geometry.GeometryLoaderManager;
|
||||
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.common.util.TransformationHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A version of {@link BlockModel.Deserializer} capable of deserializing models with custom loaders, as well as other
|
||||
* changes introduced to the spec by Forge.
|
||||
*/
|
||||
public class ExtendedBlockModelDeserializer extends BlockModel.Deserializer
|
||||
{
|
||||
public static final Gson INSTANCE = (new GsonBuilder())
|
||||
.registerTypeAdapter(BlockModel.class, new ExtendedBlockModelDeserializer())
|
||||
.registerTypeAdapter(BlockElement.class, new BlockElement.Deserializer())
|
||||
.registerTypeAdapter(BlockElementFace.class, new BlockElementFace.Deserializer())
|
||||
.registerTypeAdapter(BlockFaceUV.class, new BlockFaceUV.Deserializer())
|
||||
.registerTypeAdapter(ItemTransform.class, new ItemTransform.Deserializer())
|
||||
.registerTypeAdapter(ItemTransforms.class, new ItemTransforms.Deserializer())
|
||||
.registerTypeAdapter(ItemOverride.class, new ItemOverride.Deserializer())
|
||||
.registerTypeAdapter(Transformation.class, new TransformationHelper.Deserializer())
|
||||
.create();
|
||||
|
||||
public BlockModel deserialize(JsonElement element, Type targetType, JsonDeserializationContext deserializationContext) throws JsonParseException
|
||||
{
|
||||
BlockModel model = super.deserialize(element, targetType, deserializationContext);
|
||||
JsonObject jsonobject = element.getAsJsonObject();
|
||||
IUnbakedGeometry<?> geometry = deserializeGeometry(deserializationContext, jsonobject);
|
||||
|
||||
List<BlockElement> elements = model.getElements();
|
||||
if (geometry != null)
|
||||
{
|
||||
elements.clear();
|
||||
model.customData.setCustomGeometry(geometry);
|
||||
}
|
||||
|
||||
if (jsonobject.has("transform"))
|
||||
{
|
||||
JsonElement transform = jsonobject.get("transform");
|
||||
model.customData.setRootTransform(deserializationContext.deserialize(transform, Transformation.class));
|
||||
}
|
||||
|
||||
if (jsonobject.has("render_type"))
|
||||
{
|
||||
var renderTypeHintName = GsonHelper.getAsString(jsonobject, "render_type");
|
||||
model.customData.setRenderTypeHint(ResourceLocation.parse(renderTypeHintName));
|
||||
}
|
||||
|
||||
if (jsonobject.has("visibility"))
|
||||
{
|
||||
JsonObject visibility = GsonHelper.getAsJsonObject(jsonobject, "visibility");
|
||||
for (Map.Entry<String, JsonElement> part : visibility.entrySet())
|
||||
{
|
||||
model.customData.visibilityData.setVisibilityState(part.getKey(), part.getValue().getAsBoolean());
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IUnbakedGeometry<?> deserializeGeometry(JsonDeserializationContext deserializationContext, JsonObject object) throws JsonParseException
|
||||
{
|
||||
if (!object.has("loader"))
|
||||
return null;
|
||||
|
||||
var name = ResourceLocation.parse(GsonHelper.getAsString(object, "loader"));
|
||||
var loader = GeometryLoaderManager.get(name);
|
||||
if (loader == null)
|
||||
throw new JsonParseException(String.format(Locale.ENGLISH, "Model loader '%s' not found. Registered loaders: %s", name, GeometryLoaderManager.getLoaderList()));
|
||||
|
||||
return loader.read(object, deserializationContext);
|
||||
}
|
||||
}
|
||||
@@ -11,25 +11,26 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.SimpleBakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base interface for any object that collects culled and unculled faces and bakes them into a model.
|
||||
* <p>
|
||||
* Provides a generic base implementation via {@link #of(boolean, boolean, boolean, ItemTransforms, ItemOverrides, TextureAtlasSprite, RenderTypeGroup)}
|
||||
* Provides a generic base implementation via {@link #of(boolean, boolean, boolean, ItemTransforms, ItemOverrides, TextureAtlasSprite)}
|
||||
* and a quad-collecting alternative via {@link #collecting(List)}.
|
||||
*/
|
||||
public interface IModelBuilder<T extends IModelBuilder<T>> {
|
||||
/**
|
||||
* Creates a new model builder that uses the provided attributes in the final baked model.
|
||||
*/
|
||||
static IModelBuilder<?> of(boolean hasAmbientOcclusion, boolean usesBlockLight, boolean isGui3d,
|
||||
ItemTransforms transforms, TextureAtlasSprite particle,
|
||||
RenderTypeGroup renderTypes
|
||||
static IModelBuilder<?> of(
|
||||
boolean hasAmbientOcclusion,
|
||||
boolean usesBlockLight,
|
||||
boolean isGui3d,
|
||||
ItemTransforms transforms,
|
||||
TextureAtlasSprite particle
|
||||
){
|
||||
return new Simple(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms, particle, renderTypes);
|
||||
return new Simple(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms, particle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,13 +49,12 @@ public interface IModelBuilder<T extends IModelBuilder<T>> {
|
||||
|
||||
class Simple implements IModelBuilder<Simple> {
|
||||
private final SimpleBakedModel.Builder builder;
|
||||
private final RenderTypeGroup renderTypes;
|
||||
|
||||
private Simple(boolean hasAmbientOcclusion, boolean usesBlockLight, boolean isGui3d,
|
||||
ItemTransforms transforms, TextureAtlasSprite particle, RenderTypeGroup renderTypes
|
||||
private Simple(
|
||||
boolean hasAmbientOcclusion, boolean usesBlockLight, boolean isGui3d,
|
||||
ItemTransforms transforms, TextureAtlasSprite particle
|
||||
) {
|
||||
this.builder = new SimpleBakedModel.Builder(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms).particle(particle);
|
||||
this.renderTypes = renderTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,7 +72,7 @@ public interface IModelBuilder<T extends IModelBuilder<T>> {
|
||||
@Deprecated
|
||||
@Override
|
||||
public BakedModel build() {
|
||||
return builder.renderTypes(renderTypes).build();
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
@@ -27,8 +27,6 @@ import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Forge reimplementation of vanilla's {@link ItemModelGenerator}, i.e. builtin/generated models with some tweaks:
|
||||
* - Represented as {@link IUnbakedGeometry} so it can be baked as usual instead of being special-cased
|
||||
@@ -46,17 +44,19 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots spriteGetter, ModelState modelState) {
|
||||
if (textures == null) {
|
||||
ImmutableList.Builder<Material> builder = ImmutableList.builder();
|
||||
for (int i = 0; context.hasMaterial("layer" + i); i++)
|
||||
builder.add(context.getMaterial("layer" + i));
|
||||
int i = 0;
|
||||
Material material;
|
||||
while ((material = spriteGetter.getMaterial("layer" + i++)) != null) {
|
||||
builder.add(material);
|
||||
}
|
||||
textures = builder.build();
|
||||
}
|
||||
|
||||
TextureAtlasSprite particle = spriteGetter.apply(
|
||||
context.hasMaterial("particle") ? context.getMaterial("particle") : textures.get(0)
|
||||
);
|
||||
Material particleMaterial = spriteGetter.getMaterial("particle");
|
||||
var particle = baker.sprites().get(particleMaterial == null ? textures.get(0) : particleMaterial);
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
modelState = UnbakedGeometryHelper.composeRootTransformIntoModelState(modelState, rootTransform);
|
||||
@@ -64,7 +64,7 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel> {
|
||||
var normalRenderTypes = new RenderTypeGroup(RenderType.translucent(), ForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get());
|
||||
var builder = CompositeModel.Baked.builder(context, particle, context.getTransforms());
|
||||
for (int i = 0; i < textures.size(); i++) {
|
||||
var sprite = spriteGetter.apply(textures.get(i));
|
||||
var sprite = baker.sprites().get(textures.get(i));
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(i, sprite.contents());
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> sprite, modelState);
|
||||
var renderTypeName = renderTypeNames.get(i);
|
||||
|
||||
@@ -13,14 +13,13 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
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.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
@@ -49,16 +48,17 @@ public class SeparateTransformsModel implements IUnbakedGeometry<SeparateTransfo
|
||||
this.perspectives = perspectives;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots textures, ModelState modelState) {
|
||||
return new Baked(
|
||||
context.useAmbientOcclusion(),
|
||||
context.isGui3d(),
|
||||
context.useBlockLight(),
|
||||
spriteGetter.apply(context.getMaterial("particle")),
|
||||
baseModel.bake(spriteGetter, modelState, context.useBlockLight()),
|
||||
baker.sprites().maybeMissing(textures, "particle"),
|
||||
baseModel.bake(textures, baker, modelState),
|
||||
ImmutableMap.copyOf(Maps.transformValues(perspectives, value -> {
|
||||
return value.bake(spriteGetter, modelState, context.useBlockLight());
|
||||
return value.bake(textures, baker, modelState, context.useBlockLight(), value.getGuiLight().lightLikeBlock(), value.getTransforms());
|
||||
}))
|
||||
);
|
||||
}
|
||||
@@ -107,11 +107,6 @@ public class SeparateTransformsModel implements IUnbakedGeometry<SeparateTransfo
|
||||
return isSideLit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleIcon() {
|
||||
return particle;
|
||||
|
||||
@@ -23,12 +23,12 @@ import com.mojang.math.Transformation;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BlockFaceUV;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel.GuiLight;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockElementFace;
|
||||
import net.minecraft.client.renderer.block.model.BlockElementRotation;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransform;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.UnbakedModel.GuiLight;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
+20
-24
@@ -11,6 +11,7 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
@@ -41,18 +42,20 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelName() {
|
||||
return owner.name;
|
||||
}
|
||||
|
||||
public boolean hasCustomGeometry() {
|
||||
return getCustomGeometry() != null;
|
||||
}
|
||||
|
||||
private BlockGeometryBakingContext parentContext() {
|
||||
return owner.parent instanceof BlockModel block ? block.customData : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IUnbakedGeometry<?> getCustomGeometry() {
|
||||
return owner.parent != null && customGeometry == null ? owner.parent.customData.getCustomGeometry() : customGeometry;
|
||||
if (customGeometry != null)
|
||||
return customGeometry;
|
||||
var pctx = parentContext();
|
||||
return pctx == null ? null : pctx.getCustomGeometry();
|
||||
}
|
||||
|
||||
public void setCustomGeometry(IUnbakedGeometry<?> geometry) {
|
||||
@@ -61,19 +64,10 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
|
||||
@Override
|
||||
public boolean isComponentVisible(String part, boolean fallback) {
|
||||
return owner.parent != null && !visibilityData.hasCustomVisibility(part) ?
|
||||
owner.parent.customData.isComponentVisible(part, fallback) :
|
||||
visibilityData.isVisible(part, fallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaterial(String name) {
|
||||
return owner.hasTexture(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getMaterial(String name) {
|
||||
return owner.getMaterial(name);
|
||||
var pctx = parentContext();
|
||||
if (pctx == null || visibilityData.hasCustomVisibility(part))
|
||||
return visibilityData.isVisible(part, fallback);
|
||||
return pctx.isComponentVisible(part, fallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,7 +82,7 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return owner.hasAmbientOcclusion();
|
||||
return owner.getAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +94,8 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
public Transformation getRootTransform() {
|
||||
if (rootTransform != null)
|
||||
return rootTransform;
|
||||
return owner.parent != null ? owner.parent.customData.getRootTransform() : Transformation.identity();
|
||||
var pctx = parentContext();
|
||||
return pctx == null ? Transformation.identity() : pctx.getRootTransform();
|
||||
}
|
||||
|
||||
public void setRootTransform(Transformation rootTransform) {
|
||||
@@ -112,7 +107,8 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
public ResourceLocation getRenderTypeHint() {
|
||||
if (renderTypeHint != null)
|
||||
return renderTypeHint;
|
||||
return owner.parent != null ? owner.parent.customData.getRenderTypeHint() : null;
|
||||
var pctx = parentContext();
|
||||
return pctx == null ? null: pctx.getRenderTypeHint();
|
||||
}
|
||||
|
||||
public void setRenderTypeHint(ResourceLocation renderTypeHint) {
|
||||
@@ -131,11 +127,11 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext {
|
||||
this.gui3d = other.gui3d;
|
||||
}
|
||||
|
||||
public BakedModel bake(ModelBaker baker, Function<Material, TextureAtlasSprite> bakedTextureGetter, ModelState modelTransform) {
|
||||
public BakedModel bake(ModelBaker baker, TextureSlots textures, ModelState modelTransform) {
|
||||
IUnbakedGeometry<?> geometry = getCustomGeometry();
|
||||
if (geometry == null)
|
||||
throw new IllegalStateException("Can not use custom baking without custom geometry");
|
||||
return geometry.bake(this, baker, bakedTextureGetter, modelTransform);
|
||||
return geometry.bake(this, baker, textures, modelTransform);
|
||||
}
|
||||
|
||||
public static class VisibilityData {
|
||||
|
||||
@@ -22,27 +22,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @see BlockGeometryBakingContext
|
||||
*/
|
||||
public interface IGeometryBakingContext {
|
||||
/**
|
||||
* {@return the name of the model being baked for logging and caching purposes.}
|
||||
*/
|
||||
String getModelName();
|
||||
|
||||
/**
|
||||
* Checks if a material is present in the model.
|
||||
*
|
||||
* @param name The name of the material
|
||||
* @return true if the material is present, false otherwise
|
||||
*/
|
||||
boolean hasMaterial(String name);
|
||||
|
||||
/**
|
||||
* Resolves the final texture name, taking into account texture aliases and replacements.
|
||||
*
|
||||
* @param name The name of the material
|
||||
* @return The material, or the missing texture if not found
|
||||
*/
|
||||
Material getMaterial(String name);
|
||||
|
||||
/**
|
||||
* {@return true if this model should render in 3D in a GUI, false otherwise}
|
||||
*/
|
||||
|
||||
@@ -9,9 +9,8 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
@@ -19,17 +18,17 @@ import net.minecraft.client.resources.model.UnbakedModel;
|
||||
/**
|
||||
* General interface for any model that can be baked, superset of vanilla {@link UnbakedModel}.
|
||||
* <p>
|
||||
* Instances of this class ar usually created via {@link IGeometryLoader}.
|
||||
* Instances of this class are usually created via {@link IGeometryLoader}.
|
||||
*
|
||||
* @see IGeometryLoader
|
||||
* @see IGeometryBakingContext
|
||||
*/
|
||||
public interface IUnbakedGeometry<T extends IUnbakedGeometry<T>> {
|
||||
BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState);
|
||||
BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots spriteGetter, ModelState modelState);
|
||||
|
||||
/**
|
||||
* Resolve parents of nested {@link BlockModel}s which are later used in
|
||||
* {@link IUnbakedGeometry#bake(IGeometryBakingContext, ModelBaker, Function, ModelState)}
|
||||
* {@link IUnbakedGeometry#bake(IGeometryBakingContext, ModelBaker, TextureSlots, ModelState)}
|
||||
* via {@link BlockModel#resolveParents(Function)}
|
||||
*/
|
||||
default void resolveDependencies(UnbakedModel.Resolver resolver, IGeometryBakingContext context) { }
|
||||
|
||||
@@ -5,15 +5,11 @@
|
||||
|
||||
package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
import net.minecraftforge.client.model.IModelBuilder;
|
||||
|
||||
/**
|
||||
@@ -22,18 +18,18 @@ import net.minecraftforge.client.model.IModelBuilder;
|
||||
*/
|
||||
public abstract class SimpleUnbakedGeometry<T extends SimpleUnbakedGeometry<T>> implements IUnbakedGeometry<T> {
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
TextureAtlasSprite particle = spriteGetter.apply(context.getMaterial("particle"));
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots textures, ModelState modelState) {
|
||||
var particle = baker.sprites().maybeMissing(textures, "particle");
|
||||
|
||||
var renderTypeHint = context.getRenderTypeHint();
|
||||
var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;
|
||||
//var renderTypeHint = context.getRenderTypeHint();
|
||||
//var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;
|
||||
IModelBuilder<?> builder = IModelBuilder.of(context.useAmbientOcclusion(), context.useBlockLight(), context.isGui3d(),
|
||||
context.getTransforms(), particle, renderTypes);
|
||||
context.getTransforms(), particle/*, renderTypes*/);
|
||||
|
||||
addQuads(context, builder, baker, spriteGetter, modelState);
|
||||
addQuads(context, builder, baker, textures, modelState);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected abstract void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform);
|
||||
protected abstract void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelTransform);
|
||||
}
|
||||
+4
-67
@@ -5,21 +5,13 @@
|
||||
|
||||
package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.mojang.math.Transformation;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A {@linkplain IGeometryBakingContext geometry baking context} that is not bound to block/item model loading.
|
||||
@@ -27,23 +19,8 @@ import java.util.function.Predicate;
|
||||
public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
public static final ResourceLocation LOCATION = ResourceLocation.fromNamespaceAndPath("forge", "standalone");
|
||||
|
||||
public static final StandaloneGeometryBakingContext INSTANCE = create(LOCATION);
|
||||
public static final StandaloneGeometryBakingContext INSTANCE = builder().build();
|
||||
|
||||
public static StandaloneGeometryBakingContext create(ResourceLocation modelName) {
|
||||
return builder().build(modelName);
|
||||
}
|
||||
|
||||
public static StandaloneGeometryBakingContext create(Map<String, ResourceLocation> textures) {
|
||||
return create(LOCATION, textures);
|
||||
}
|
||||
|
||||
public static StandaloneGeometryBakingContext create(ResourceLocation modelName, Map<String, ResourceLocation> textures) {
|
||||
return builder().withTextures(textures, MissingTextureAtlasSprite.getLocation()).build(modelName);
|
||||
}
|
||||
|
||||
private final ResourceLocation modelName;
|
||||
private final Predicate<String> materialCheck;
|
||||
private final Function<String, Material> materialLookup;
|
||||
private final boolean isGui3d;
|
||||
private final boolean useBlockLight;
|
||||
private final boolean useAmbientOcclusion;
|
||||
@@ -54,16 +31,12 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
private final BiPredicate<String, Boolean> visibilityTest;
|
||||
|
||||
private StandaloneGeometryBakingContext(
|
||||
ResourceLocation modelName, Predicate<String> materialCheck,
|
||||
Function<String, Material> materialLookup, boolean isGui3d,
|
||||
boolean isGui3d,
|
||||
boolean useBlockLight, boolean useAmbientOcclusion,
|
||||
ItemTransforms transforms, Transformation rootTransform,
|
||||
@Nullable ResourceLocation renderTypeHint,
|
||||
BiPredicate<String, Boolean> visibilityTest
|
||||
) {
|
||||
this.modelName = modelName;
|
||||
this.materialCheck = materialCheck;
|
||||
this.materialLookup = materialLookup;
|
||||
this.isGui3d = isGui3d;
|
||||
this.useBlockLight = useBlockLight;
|
||||
this.useAmbientOcclusion = useAmbientOcclusion;
|
||||
@@ -73,21 +46,6 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
this.visibilityTest = visibilityTest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelName() {
|
||||
return modelName.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaterial(String name) {
|
||||
return materialCheck.test(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getMaterial(String name) {
|
||||
return materialLookup.apply(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return isGui3d;
|
||||
@@ -133,9 +91,6 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private static final Material NO_MATERIAL = new Material(InventoryMenu.BLOCK_ATLAS, MissingTextureAtlasSprite.getLocation());
|
||||
private Predicate<String> materialCheck = Predicates.alwaysFalse();
|
||||
private Function<String, Material> materialLookup = $ -> NO_MATERIAL;
|
||||
private boolean isGui3d = true;
|
||||
private boolean useBlockLight = true;
|
||||
private boolean useAmbientOcclusion = true;
|
||||
@@ -148,8 +103,6 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
private Builder() { }
|
||||
|
||||
private Builder(IGeometryBakingContext parent) {
|
||||
this.materialCheck = parent::hasMaterial;
|
||||
this.materialLookup = parent::getMaterial;
|
||||
this.isGui3d = parent.isGui3d();
|
||||
this.useBlockLight = parent.useBlockLight();
|
||||
this.useAmbientOcclusion = parent.useAmbientOcclusion();
|
||||
@@ -159,22 +112,6 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
this.visibilityTest = parent::isComponentVisible;
|
||||
}
|
||||
|
||||
public Builder withTextures(Map<String, ResourceLocation> textures, ResourceLocation defaultTexture) {
|
||||
return withTextures(InventoryMenu.BLOCK_ATLAS, textures, defaultTexture);
|
||||
}
|
||||
|
||||
public Builder withTextures(ResourceLocation atlasLocation, Map<String, ResourceLocation> textures, ResourceLocation defaultTexture) {
|
||||
this.materialCheck = textures::containsKey;
|
||||
this.materialLookup = name -> new Material(atlasLocation, textures.getOrDefault(name, defaultTexture));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withMaterials(Map<String, Material> materials, Material defaultMaterial) {
|
||||
this.materialCheck = materials::containsKey;
|
||||
this.materialLookup = name -> materials.getOrDefault(name, defaultMaterial);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withGui3d(boolean isGui3d) {
|
||||
this.isGui3d = isGui3d;
|
||||
return this;
|
||||
@@ -211,8 +148,8 @@ public class StandaloneGeometryBakingContext implements IGeometryBakingContext {
|
||||
return this;
|
||||
}
|
||||
|
||||
public StandaloneGeometryBakingContext build(ResourceLocation modelName) {
|
||||
return new StandaloneGeometryBakingContext(modelName, materialCheck, materialLookup, isGui3d, useBlockLight, useAmbientOcclusion, transforms, rootTransform, renderTypeHint, visibilityTest);
|
||||
public StandaloneGeometryBakingContext build() {
|
||||
return new StandaloneGeometryBakingContext(isGui3d, useBlockLight, useAmbientOcclusion, transforms, rootTransform, renderTypeHint, visibilityTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,13 @@ import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockElementFace;
|
||||
import net.minecraft.client.renderer.block.model.BlockFaceUV;
|
||||
import net.minecraft.client.renderer.block.model.FaceBakery;
|
||||
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -25,6 +27,8 @@ import net.minecraftforge.client.model.IModelBuilder;
|
||||
import net.minecraftforge.client.model.IQuadTransformer;
|
||||
import net.minecraftforge.client.model.QuadTransformers;
|
||||
import net.minecraftforge.client.model.SimpleModelState;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@@ -39,6 +43,7 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* Helper for dealing with unbaked models and geometries.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public class UnbakedGeometryHelper {
|
||||
private static final FaceBakery FACE_BAKERY = new FaceBakery();
|
||||
|
||||
@@ -64,11 +69,11 @@ public class UnbakedGeometryHelper {
|
||||
* <p>
|
||||
* The target atlas will always be {@link InventoryMenu#BLOCK_ATLAS}.
|
||||
*/
|
||||
public static Material resolveDirtyMaterial(@Nullable String tex, IGeometryBakingContext owner) {
|
||||
public static Material resolveDirtyMaterial(@Nullable String tex, TextureSlots textures) {
|
||||
if (tex == null)
|
||||
return new Material(InventoryMenu.BLOCK_ATLAS, MissingTextureAtlasSprite.getLocation());
|
||||
return new Material(TextureAtlas.LOCATION_BLOCKS, MissingTextureAtlasSprite.getLocation());
|
||||
if (tex.startsWith("#"))
|
||||
return owner.getMaterial(tex);
|
||||
return textures.getMaterial(tex);
|
||||
|
||||
// Attempt to convert a common (windows/linux/mac) filesystem path to a ResourceLocation.
|
||||
// This makes no promises, if it doesn't work, too bad, fix your mtl file.
|
||||
@@ -79,9 +84,10 @@ public class UnbakedGeometryHelper {
|
||||
tex = namespace != null ? namespace + ":" + path : path;
|
||||
}
|
||||
|
||||
return new Material(InventoryMenu.BLOCK_ATLAS, ResourceLocation.parse(tex));
|
||||
return new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.parse(tex));
|
||||
}
|
||||
|
||||
private static final ItemModelGenerator ITEM_MODEL_GENERATOR = new ItemModelGenerator();
|
||||
/**
|
||||
* Creates a list of {@linkplain BlockElement block elements} in the shape of the specified sprite contents.
|
||||
* These can later be baked using the same, or another texture.
|
||||
@@ -89,7 +95,7 @@ public class UnbakedGeometryHelper {
|
||||
* The {@link Direction#NORTH} and {@link Direction#SOUTH} faces take up the whole surface.
|
||||
*/
|
||||
public static List<BlockElement> createUnbakedItemElements(int layerIndex, SpriteContents spriteContents) {
|
||||
return ModelBakery.ITEM_MODEL_GENERATOR.processFrames(layerIndex, "layer" + layerIndex, spriteContents);
|
||||
return ITEM_MODEL_GENERATOR.processFrames(layerIndex, "layer" + layerIndex, spriteContents);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +168,7 @@ public class UnbakedGeometryHelper {
|
||||
public static void bakeElements(IModelBuilder<?> builder, List<BlockElement> elements, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState) {
|
||||
for (BlockElement element : elements) {
|
||||
element.faces.forEach((side, face) -> {
|
||||
var sprite = spriteGetter.apply(new Material(InventoryMenu.BLOCK_ATLAS, ResourceLocation.parse(face.texture())));
|
||||
var sprite = spriteGetter.apply(new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.parse(face.texture())));
|
||||
var quad = bakeElementFace(element, face, sprite, side, modelState, element.lightEmission);
|
||||
if (face.cullForDirection() == null)
|
||||
builder.addUnculledFace(quad);
|
||||
|
||||
@@ -11,11 +11,11 @@ import com.google.common.collect.Sets;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.TextureSlots;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -43,9 +43,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A model loaded from an OBJ file.
|
||||
@@ -53,14 +51,13 @@ import java.util.stream.Stream;
|
||||
* Supports positions, texture coordinates, normals and colors. The {@link ObjMaterialLibrary material library}
|
||||
* has support for numerous features, including support for {@link ResourceLocation} textures (non-standard).
|
||||
*/
|
||||
public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
{
|
||||
public class ObjModel extends SimpleUnbakedGeometry<ObjModel> {
|
||||
private static final Vector4f COLOR_WHITE = new Vector4f(1, 1, 1, 1);
|
||||
private static final Vec2[] DEFAULT_COORDS = {
|
||||
new Vec2(0, 0),
|
||||
new Vec2(0, 1),
|
||||
new Vec2(1, 1),
|
||||
new Vec2(1, 0),
|
||||
new Vec2(0, 0),
|
||||
new Vec2(0, 1),
|
||||
new Vec2(1, 1),
|
||||
new Vec2(1, 0),
|
||||
};
|
||||
|
||||
private final Map<String, ModelGroup> parts = Maps.newLinkedHashMap();
|
||||
@@ -81,8 +78,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
|
||||
public final ResourceLocation modelLocation;
|
||||
|
||||
private ObjModel(ModelSettings settings)
|
||||
{
|
||||
private ObjModel(ModelSettings settings) {
|
||||
this.modelLocation = settings.modelLocation;
|
||||
this.automaticCulling = settings.automaticCulling;
|
||||
this.shadeQuads = settings.shadeQuads;
|
||||
@@ -91,8 +87,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
this.mtlOverride = settings.mtlOverride;
|
||||
}
|
||||
|
||||
public static ObjModel parse(ObjTokenizer tokenizer, ModelSettings settings) throws IOException
|
||||
{
|
||||
public static ObjModel parse(ObjTokenizer tokenizer, ModelSettings settings) throws IOException {
|
||||
var modelLocation = settings.modelLocation;
|
||||
var materialLibraryOverrideLocation = settings.mtlOverride;
|
||||
var model = new ObjModel(settings);
|
||||
@@ -115,8 +110,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
|
||||
boolean objAboveGroup = false;
|
||||
|
||||
if (materialLibraryOverrideLocation != null)
|
||||
{
|
||||
if (materialLibraryOverrideLocation != null) {
|
||||
String lib = materialLibraryOverrideLocation;
|
||||
if (lib.contains(":"))
|
||||
mtllib = ObjLoader.INSTANCE.loadMaterialLibrary(ResourceLocation.parse(lib));
|
||||
@@ -125,12 +119,9 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
|
||||
String[] line;
|
||||
while ((line = tokenizer.readAndSplitLine(true)) != null)
|
||||
{
|
||||
switch (line[0])
|
||||
{
|
||||
case "mtllib": // Loads material library
|
||||
{
|
||||
while ((line = tokenizer.readAndSplitLine(true)) != null) {
|
||||
switch (line[0]) {
|
||||
case "mtllib": { // Loads material library
|
||||
if (materialLibraryOverrideLocation != null)
|
||||
break;
|
||||
|
||||
@@ -141,28 +132,18 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
mtllib = ObjLoader.INSTANCE.loadMaterialLibrary(ResourceLocation.fromNamespaceAndPath(modelDomain, modelPath + lib));
|
||||
break;
|
||||
}
|
||||
|
||||
case "usemtl": // Sets the current material (starts new mesh)
|
||||
{
|
||||
|
||||
case "usemtl": { // Sets the current material (starts new mesh)
|
||||
String mat = Arrays.asList(Arrays.copyOfRange(line, 1, line.length)).stream().collect(Collectors.joining(" "));
|
||||
ObjMaterialLibrary.Material newMat = mtllib.getMaterial(mat);
|
||||
if (!Objects.equals(newMat, currentMat))
|
||||
{
|
||||
if (!Objects.equals(newMat, currentMat)) {
|
||||
currentMat = newMat;
|
||||
if (currentMesh != null && currentMesh.mat == null && currentMesh.faces.isEmpty())
|
||||
{
|
||||
currentMesh.mat = currentMat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start new mesh
|
||||
else // Start new mesh
|
||||
currentMesh = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "v": // Vertex
|
||||
model.positions.add(parseVector4To3(line));
|
||||
break;
|
||||
@@ -175,20 +156,13 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
case "vc": // Vertex color (non-standard)
|
||||
model.colors.add(parseVector4(line));
|
||||
break;
|
||||
|
||||
case "f": // Face
|
||||
{
|
||||
if (currentMesh == null)
|
||||
{
|
||||
case "f": { // Face
|
||||
if (currentMesh == null) {
|
||||
currentMesh = model.new ModelMesh(currentMat, currentSmoothingGroup);
|
||||
if (currentObject != null)
|
||||
{
|
||||
currentObject.meshes.add(currentMesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentGroup == null)
|
||||
{
|
||||
else {
|
||||
if (currentGroup == null) {
|
||||
currentGroup = model.new ModelGroup("");
|
||||
model.parts.put("", currentGroup);
|
||||
}
|
||||
@@ -197,65 +171,39 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
|
||||
int[][] vertices = new int[line.length - 1][];
|
||||
for (int i = 0; i < vertices.length; i++)
|
||||
{
|
||||
for (int i = 0; i < vertices.length; i++) {
|
||||
String vertexData = line[i + 1];
|
||||
String[] vertexParts = vertexData.split("/");
|
||||
int[] vertex = Arrays.stream(vertexParts).mapToInt(num -> num == null || num.isEmpty() ? 0 : Integer.parseInt(num)).toArray();
|
||||
if (vertex[0] < 0) vertex[0] = model.positions.size() + vertex[0];
|
||||
else vertex[0]--;
|
||||
if (vertex.length > 1)
|
||||
{
|
||||
if (vertex[1] < 0) vertex[1] = model.texCoords.size() + vertex[1];
|
||||
else vertex[1]--;
|
||||
if (vertex.length > 2)
|
||||
{
|
||||
if (vertex[2] < 0) vertex[2] = model.normals.size() + vertex[2];
|
||||
else vertex[2]--;
|
||||
if (vertex.length > 3)
|
||||
{
|
||||
if (vertex[3] < 0) vertex[3] = model.colors.size() + vertex[3];
|
||||
else vertex[3]--;
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 4 && x < vertex.length; x++) {
|
||||
if (vertex[x] < 0)
|
||||
vertex[x] = model.positions.size() + vertex[x];
|
||||
else
|
||||
vertex[x]--;
|
||||
}
|
||||
vertices[i] = vertex;
|
||||
}
|
||||
|
||||
currentMesh.faces.add(vertices);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "s": // Smoothing group (starts new mesh)
|
||||
{
|
||||
case "s": { // Smoothing group (starts new mesh)
|
||||
String smoothingGroup = "off".equals(line[1]) ? null : line[1];
|
||||
if (!Objects.equals(currentSmoothingGroup, smoothingGroup))
|
||||
{
|
||||
if (!Objects.equals(currentSmoothingGroup, smoothingGroup)) {
|
||||
currentSmoothingGroup = smoothingGroup;
|
||||
if (currentMesh != null && currentMesh.smoothingGroup == null && currentMesh.faces.isEmpty())
|
||||
{
|
||||
currentMesh.smoothingGroup = currentSmoothingGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start new mesh
|
||||
else // Start new mesh
|
||||
currentMesh = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "g":
|
||||
{
|
||||
case "g": {
|
||||
String name = line[1];
|
||||
if (objAboveGroup)
|
||||
{
|
||||
if (objAboveGroup) {
|
||||
currentObject = model.new ModelObject(currentGroup.name() + "/" + name);
|
||||
currentGroup.parts.put(name, currentObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
currentGroup = model.new ModelGroup(name);
|
||||
model.parts.put(name, currentGroup);
|
||||
currentObject = null;
|
||||
@@ -264,20 +212,15 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
currentMesh = null;
|
||||
break;
|
||||
}
|
||||
|
||||
case "o":
|
||||
{
|
||||
case "o": {
|
||||
String name = line[1];
|
||||
if (objAboveGroup || currentGroup == null)
|
||||
{
|
||||
if (objAboveGroup || currentGroup == null) {
|
||||
objAboveGroup = true;
|
||||
|
||||
currentGroup = model.new ModelGroup(name);
|
||||
model.parts.put(name, currentGroup);
|
||||
currentObject = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
currentObject = model.new ModelObject(currentGroup.name() + "/" + name);
|
||||
currentGroup.parts.put(name, currentObject);
|
||||
}
|
||||
@@ -290,30 +233,25 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
return model;
|
||||
}
|
||||
|
||||
private static Vector3f parseVector4To3(String[] line)
|
||||
{
|
||||
private static Vector3f parseVector4To3(String[] line) {
|
||||
Vector4f vec4 = parseVector4(line);
|
||||
return new Vector3f(
|
||||
vec4.x() / vec4.w(),
|
||||
vec4.y() / vec4.w(),
|
||||
vec4.z() / vec4.w()
|
||||
vec4.x() / vec4.w(),
|
||||
vec4.y() / vec4.w(),
|
||||
vec4.z() / vec4.w()
|
||||
);
|
||||
}
|
||||
|
||||
private static Vec2 parseVector2(String[] line)
|
||||
{
|
||||
return switch (line.length)
|
||||
{
|
||||
private static Vec2 parseVector2(String[] line) {
|
||||
return switch (line.length) {
|
||||
case 1 -> new Vec2(0, 0);
|
||||
case 2 -> new Vec2(Float.parseFloat(line[1]), 0);
|
||||
default -> new Vec2(Float.parseFloat(line[1]), Float.parseFloat(line[2]));
|
||||
};
|
||||
}
|
||||
|
||||
private static Vector3f parseVector3(String[] line)
|
||||
{
|
||||
return switch (line.length)
|
||||
{
|
||||
private static Vector3f parseVector3(String[] line) {
|
||||
return switch (line.length) {
|
||||
case 1 -> new Vector3f();
|
||||
case 2 -> new Vector3f(Float.parseFloat(line[1]), 0, 0);
|
||||
case 3 -> new Vector3f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), 0);
|
||||
@@ -321,10 +259,8 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
};
|
||||
}
|
||||
|
||||
static Vector4f parseVector4(String[] line)
|
||||
{
|
||||
return switch (line.length)
|
||||
{
|
||||
static Vector4f parseVector4(String[] line) {
|
||||
return switch (line.length) {
|
||||
case 1 -> new Vector4f();
|
||||
case 2 -> new Vector4f(Float.parseFloat(line[1]), 0, 0, 1);
|
||||
case 3 -> new Vector4f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), 0, 1);
|
||||
@@ -334,20 +270,19 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform)
|
||||
{
|
||||
parts.values().stream().filter(part -> owner.isComponentVisible(part.name(), true))
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation));
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelTransform) {
|
||||
for (var part : parts.values()) {
|
||||
if (owner.isComponentVisible(part.name(), true))
|
||||
part.addQuads(owner, modelBuilder, baker, textures, modelTransform, modelLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getRootComponentNames()
|
||||
{
|
||||
public Set<String> getRootComponentNames() {
|
||||
return rootComponentNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConfigurableComponentNames()
|
||||
{
|
||||
public Set<String> getConfigurableComponentNames() {
|
||||
if (allComponentNames != null)
|
||||
return allComponentNames;
|
||||
var names = new HashSet<String>();
|
||||
@@ -356,16 +291,13 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
return allComponentNames = Collections.unmodifiableSet(names);
|
||||
}
|
||||
|
||||
private Pair<BakedQuad, Direction> makeQuad(int[][] indices, int tintIndex, Vector4f colorTint, Vector4f ambientColor, TextureAtlasSprite texture, Transformation transform)
|
||||
{
|
||||
private Pair<BakedQuad, Direction> makeQuad(int[][] indices, int tintIndex, Vector4f colorTint, Vector4f ambientColor, TextureAtlasSprite texture, Transformation transform) {
|
||||
boolean needsNormalRecalculation = false;
|
||||
for (int[] ints : indices)
|
||||
{
|
||||
needsNormalRecalculation |= ints.length < 3;
|
||||
}
|
||||
|
||||
Vector3f faceNormal = new Vector3f();
|
||||
if (needsNormalRecalculation)
|
||||
{
|
||||
if (needsNormalRecalculation) {
|
||||
Vector3f a = positions.get(indices[0][0]);
|
||||
Vector3f ab = positions.get(indices[1][0]);
|
||||
Vector3f ac = positions.get(indices[2][0]);
|
||||
@@ -384,16 +316,12 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
quadBaker.setTintIndex(tintIndex);
|
||||
|
||||
int uv2 = 0;
|
||||
if (emissiveAmbient)
|
||||
{
|
||||
if (emissiveAmbient) {
|
||||
int fakeLight = (int) ((ambientColor.x() + ambientColor.y() + ambientColor.z()) * 15 / 3.0f);
|
||||
uv2 = LightTexture.pack(fakeLight, fakeLight);
|
||||
quadBaker.setShade(fakeLight == 0 && shadeQuads);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else
|
||||
quadBaker.setShade(shadeQuads);
|
||||
}
|
||||
|
||||
boolean hasTransform = !transform.isIdentity();
|
||||
// The incoming transform is referenced on the center of the block, but our coords are referenced on the corner
|
||||
@@ -402,16 +330,14 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
Vector4f[] pos = new Vector4f[4];
|
||||
Vector3f[] norm = new Vector3f[4];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int[] index = indices[Math.min(i, indices.length - 1)];
|
||||
Vector4f position = new Vector4f(positions.get(index[0]), 1);
|
||||
Vec2 texCoord = index.length >= 2 && !texCoords.isEmpty() ? texCoords.get(index[1]) : DEFAULT_COORDS[i];
|
||||
Vector3f norm0 = !needsNormalRecalculation && index.length >= 3 && !normals.isEmpty() ? normals.get(index[2]) : faceNormal;
|
||||
Vector3f normal = norm0;
|
||||
Vector4f color = index.length >= 4 && !colors.isEmpty() ? colors.get(index[3]) : COLOR_WHITE;
|
||||
if (hasTransform)
|
||||
{
|
||||
if (hasTransform) {
|
||||
normal = new Vector3f(norm0);
|
||||
transformation.transformPosition(position);
|
||||
transformation.transformNormal(normal);
|
||||
@@ -430,16 +356,13 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
quadBaker.setUv2(uv2 & 0xFFFF, uv2 >> 16 & 0xFFFF);
|
||||
quadBaker.setNormal(normal.x(), normal.y(), normal.z());
|
||||
if (i == 0)
|
||||
{
|
||||
quadBaker.setDirection(Direction.getApproximateNearest(normal.x(), normal.y(), normal.z()));
|
||||
}
|
||||
pos[i] = position;
|
||||
norm[i] = normal;
|
||||
}
|
||||
|
||||
Direction cull = null;
|
||||
if (automaticCulling)
|
||||
{
|
||||
if (automaticCulling) {
|
||||
if (Mth.equal(pos[0].x(), 0) && // vertex.position.x
|
||||
Mth.equal(pos[1].x(), 0) &&
|
||||
Mth.equal(pos[2].x(), 0) &&
|
||||
@@ -493,143 +416,123 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
return Pair.of(quadBaker.build(), cull);
|
||||
}
|
||||
|
||||
public CompositeRenderable bakeRenderable(IGeometryBakingContext configuration)
|
||||
{
|
||||
public CompositeRenderable bakeRenderable(TextureSlots textures) {
|
||||
var builder = CompositeRenderable.builder();
|
||||
|
||||
for (var entry : parts.entrySet())
|
||||
{
|
||||
for (var entry : parts.entrySet()) {
|
||||
var name = entry.getKey();
|
||||
var part = entry.getValue();
|
||||
part.bake(builder.child(name), configuration);
|
||||
part.bake(builder.child(name), textures);
|
||||
}
|
||||
|
||||
return builder.get();
|
||||
}
|
||||
|
||||
public class ModelObject
|
||||
{
|
||||
private class ModelObject {
|
||||
public final String name;
|
||||
|
||||
List<ModelMesh> meshes = Lists.newArrayList();
|
||||
|
||||
ModelObject(String name)
|
||||
{
|
||||
ModelObject(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String name()
|
||||
{
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
for (ModelMesh mesh : meshes)
|
||||
{
|
||||
mesh.addQuads(owner, modelBuilder, spriteGetter, modelTransform);
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelTransform, ResourceLocation modelLocation) {
|
||||
for (var mesh : meshes)
|
||||
mesh.addQuads(owner, modelBuilder, baker, textures, modelTransform, modelLocation);
|
||||
}
|
||||
|
||||
protected void bake(CompositeRenderable.PartBuilder<?> builder, TextureSlots textures) {
|
||||
for (var mesh : this.meshes)
|
||||
mesh.bake(builder, textures);
|
||||
}
|
||||
|
||||
protected Collection<Material> getTextures(IGeometryBakingContext owner, TextureSlots textures, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
|
||||
var ret = new HashSet<Material>();
|
||||
for (var mesh : meshes) {
|
||||
if (mesh.mat != null)
|
||||
ret.add(UnbakedGeometryHelper.resolveDirtyMaterial(mesh.mat.diffuseColorMap, textures));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void bake(CompositeRenderable.PartBuilder<?> builder, IGeometryBakingContext configuration)
|
||||
{
|
||||
for (ModelMesh mesh : this.meshes)
|
||||
{
|
||||
mesh.bake(builder, configuration);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Material> getTextures(IGeometryBakingContext owner, Function<ResourceLocation, UnbakedModel> modelGetter, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
return meshes.stream()
|
||||
.flatMap(mesh -> mesh.mat != null
|
||||
? Stream.of(UnbakedGeometryHelper.resolveDirtyMaterial(mesh.mat.diffuseColorMap, owner))
|
||||
: Stream.of())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
protected void addNamesRecursively(Set<String> names)
|
||||
{
|
||||
protected void addNamesRecursively(Set<String> names) {
|
||||
names.add(name());
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelGroup extends ModelObject
|
||||
{
|
||||
private class ModelGroup extends ModelObject {
|
||||
final Map<String, ModelObject> parts = Maps.newLinkedHashMap();
|
||||
|
||||
ModelGroup(String name)
|
||||
{
|
||||
ModelGroup(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots spriteGetter, ModelState modelTransform, ResourceLocation modelLocation) {
|
||||
super.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation);
|
||||
|
||||
parts.values().stream().filter(part -> owner.isComponentVisible(part.name(), true))
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bake(CompositeRenderable.PartBuilder<?> builder, IGeometryBakingContext configuration)
|
||||
{
|
||||
super.bake(builder, configuration);
|
||||
|
||||
for (var entry : parts.entrySet())
|
||||
{
|
||||
var name = entry.getKey();
|
||||
var part = entry.getValue();
|
||||
part.bake(builder.child(name), configuration);
|
||||
for (var part : parts.values()) {
|
||||
if (owner.isComponentVisible(part.name(), true))
|
||||
part.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IGeometryBakingContext owner, Function<ResourceLocation, UnbakedModel> modelGetter, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
public void bake(CompositeRenderable.PartBuilder<?> builder, TextureSlots textures) {
|
||||
super.bake(builder, textures);
|
||||
|
||||
for (var entry : parts.entrySet()) {
|
||||
var name = entry.getKey();
|
||||
var part = entry.getValue();
|
||||
part.bake(builder.child(name), textures);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IGeometryBakingContext owner, TextureSlots textures, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
|
||||
Set<Material> combined = Sets.newHashSet();
|
||||
combined.addAll(super.getTextures(owner, modelGetter, missingTextureErrors));
|
||||
combined.addAll(super.getTextures(owner, textures, missingTextureErrors));
|
||||
for (ModelObject part : parts.values())
|
||||
combined.addAll(part.getTextures(owner, modelGetter, missingTextureErrors));
|
||||
combined.addAll(part.getTextures(owner, textures, missingTextureErrors));
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNamesRecursively(Set<String> names)
|
||||
{
|
||||
protected void addNamesRecursively(Set<String> names) {
|
||||
super.addNamesRecursively(names);
|
||||
for (ModelObject object : parts.values())
|
||||
object.addNamesRecursively(names);
|
||||
}
|
||||
}
|
||||
|
||||
private class ModelMesh
|
||||
{
|
||||
private class ModelMesh {
|
||||
@Nullable
|
||||
public ObjMaterialLibrary.Material mat;
|
||||
@Nullable
|
||||
public String smoothingGroup;
|
||||
public final List<int[][]> faces = Lists.newArrayList();
|
||||
|
||||
public ModelMesh(@Nullable ObjMaterialLibrary.Material currentMat, @Nullable String currentSmoothingGroup)
|
||||
{
|
||||
public ModelMesh(@Nullable ObjMaterialLibrary.Material currentMat, @Nullable String currentSmoothingGroup) {
|
||||
this.mat = currentMat;
|
||||
this.smoothingGroup = currentSmoothingGroup;
|
||||
}
|
||||
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform)
|
||||
{
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, TextureSlots textures, ModelState modelTransform, ResourceLocation modelLocation) {
|
||||
if (mat == null)
|
||||
return;
|
||||
TextureAtlasSprite texture = spriteGetter.apply(UnbakedGeometryHelper.resolveDirtyMaterial(mat.diffuseColorMap, owner));
|
||||
var material = UnbakedGeometryHelper.resolveDirtyMaterial(mat.diffuseColorMap, textures);
|
||||
var texture = baker.sprites().get(material);
|
||||
int tintIndex = mat.diffuseTintIndex;
|
||||
Vector4f colorTint = mat.diffuseColor;
|
||||
|
||||
var rootTransform = owner.getRootTransform();
|
||||
var transform = rootTransform.isIdentity() ? modelTransform.getRotation() : modelTransform.getRotation().compose(rootTransform);
|
||||
for (int[][] face : faces)
|
||||
{
|
||||
for (int[][] face : faces) {
|
||||
Pair<BakedQuad, Direction> quad = makeQuad(face, tintIndex, colorTint, mat.ambientColor, texture, transform);
|
||||
if (quad.getRight() == null)
|
||||
modelBuilder.addUnculledFace(quad.getLeft());
|
||||
@@ -638,8 +541,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
}
|
||||
|
||||
public void bake(CompositeRenderable.PartBuilder<?> builder, IGeometryBakingContext configuration)
|
||||
{
|
||||
public void bake(CompositeRenderable.PartBuilder<?> builder, TextureSlots textures) {
|
||||
ObjMaterialLibrary.Material mat = this.mat;
|
||||
if (mat == null)
|
||||
return;
|
||||
@@ -648,13 +550,12 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
|
||||
final List<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
for (var face : this.faces)
|
||||
{
|
||||
for (var face : this.faces) {
|
||||
var pair = makeQuad(face, tintIndex, colorTint, mat.ambientColor, UnitTextureAtlasSprite.INSTANCE, Transformation.identity());
|
||||
quads.add(pair.getLeft());
|
||||
}
|
||||
|
||||
ResourceLocation textureLocation = UnbakedGeometryHelper.resolveDirtyMaterial(mat.diffuseColorMap, configuration).texture();
|
||||
ResourceLocation textureLocation = UnbakedGeometryHelper.resolveDirtyMaterial(mat.diffuseColorMap, textures).texture();
|
||||
ResourceLocation texturePath = textureLocation.withPath(p -> "textures/" + p + ".png");
|
||||
|
||||
builder.addMesh(texturePath, quads);
|
||||
|
||||
@@ -9,13 +9,12 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -57,7 +56,7 @@ public class BakedModelRenderable implements IRenderable<BakedModelRenderable.Co
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, MultiBufferSource bufferSource, ITextureRenderTypeLookup textureRenderTypeLookup, int lightmap, int overlay, float partialTick, Context context) {
|
||||
var buffer = bufferSource.getBuffer(textureRenderTypeLookup.get(InventoryMenu.BLOCK_ATLAS));
|
||||
var buffer = bufferSource.getBuffer(textureRenderTypeLookup.get(TextureAtlas.LOCATION_BLOCKS));
|
||||
var tint = context.tint();
|
||||
var randomSource = context.randomSource();
|
||||
for (var direction : context.faces()) {
|
||||
|
||||
@@ -15,8 +15,7 @@ import net.minecraft.util.Unit;
|
||||
* @param <T> The type of context object used by the rendering logic
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IRenderable<T>
|
||||
{
|
||||
public interface IRenderable<T> {
|
||||
/**
|
||||
* Draws the renderable by adding the geometry to the provided {@link MultiBufferSource}
|
||||
*
|
||||
@@ -37,8 +36,7 @@ public interface IRenderable<T>
|
||||
* @param context The context used for rendering
|
||||
* @return A renderable that accepts {@link Unit#INSTANCE} as context, but uses the provided {@code context} instead
|
||||
*/
|
||||
default IRenderable<Unit> withContext(T context)
|
||||
{
|
||||
default IRenderable<Unit> withContext(T context) {
|
||||
return (poseStack, bufferSource, textureRenderTypeLookup, lightmap, overlay, partialTick, unused) ->
|
||||
this.render(poseStack, bufferSource, textureRenderTypeLookup, lightmap, overlay, partialTick, context);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,14 @@
|
||||
package net.minecraftforge.client.textures;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.metadata.MetadataSectionSerializer;
|
||||
import net.minecraft.server.packs.metadata.MetadataSectionType;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The "forge" section of texture metadata files (.mcmeta). Currently used only to specify custom
|
||||
@@ -25,44 +22,26 @@ import java.util.Optional;
|
||||
* @see ITextureAtlasSpriteLoader
|
||||
*/
|
||||
public record ForgeTextureMetadata(@Nullable ITextureAtlasSpriteLoader loader) {
|
||||
|
||||
public static final ForgeTextureMetadata EMPTY = new ForgeTextureMetadata(null);
|
||||
public static final MetadataSectionSerializer<ForgeTextureMetadata> SERIALIZER = new Serializer();
|
||||
|
||||
private static final Codec<ITextureAtlasSpriteLoader> LOADER_CODEC = Codec.<ITextureAtlasSpriteLoader>stringResolver(
|
||||
loader -> {
|
||||
var ret = TextureAtlasSpriteLoaderManager.getKey(loader);
|
||||
return ret == null ? null : ret.toString();
|
||||
},
|
||||
name -> TextureAtlasSpriteLoaderManager.get(ResourceLocation.parse(name))
|
||||
);
|
||||
|
||||
private static final Codec<ForgeTextureMetadata> CODEC = RecordCodecBuilder.create(i ->
|
||||
i.group(
|
||||
LOADER_CODEC.fieldOf("loader").forGetter(ForgeTextureMetadata::loader)
|
||||
).apply(i, ForgeTextureMetadata::new)
|
||||
);
|
||||
|
||||
|
||||
public static final MetadataSectionType<ForgeTextureMetadata> TYPE = new MetadataSectionType<>("forge", CODEC);
|
||||
|
||||
public static ForgeTextureMetadata forResource(Resource resource) throws IOException {
|
||||
Optional<ForgeTextureMetadata> metadata = resource.metadata().getSection(SERIALIZER);
|
||||
return metadata.orElse(EMPTY);
|
||||
return resource.metadata().getSection(TYPE).orElse(EMPTY);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ITextureAtlasSpriteLoader getLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
private static final class Serializer implements MetadataSectionSerializer<ForgeTextureMetadata> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getMetadataSectionName() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ForgeTextureMetadata fromJson(JsonObject json) {
|
||||
@Nullable
|
||||
ITextureAtlasSpriteLoader loader;
|
||||
if (json.has("loader")) {
|
||||
ResourceLocation loaderName = ResourceLocation.parse(GsonHelper.getAsString(json, "loader"));
|
||||
loader = TextureAtlasSpriteLoaderManager.get(loaderName);
|
||||
if (loader == null) {
|
||||
throw new JsonSyntaxException("Unknown TextureAtlasSpriteLoader " + loaderName);
|
||||
}
|
||||
} else {
|
||||
loader = null;
|
||||
}
|
||||
return new ForgeTextureMetadata(loader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+12
-7
@@ -5,23 +5,23 @@
|
||||
|
||||
package net.minecraftforge.client.textures;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.RegisterTextureAtlasSpriteLoadersEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manager for {@link ITextureAtlasSpriteLoader} instances.
|
||||
* <p>
|
||||
* Provides a lookup.
|
||||
* TODO: Convert this into a proper registry
|
||||
*/
|
||||
public final class TextureAtlasSpriteLoaderManager {
|
||||
private static Map<ResourceLocation, ITextureAtlasSpriteLoader> LOADERS;
|
||||
private static BiMap<ResourceLocation, ITextureAtlasSpriteLoader> LOADERS;
|
||||
|
||||
/**
|
||||
* Finds the loader with the given name, or null if none is registered.
|
||||
@@ -31,12 +31,17 @@ public final class TextureAtlasSpriteLoaderManager {
|
||||
return LOADERS.get(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ResourceLocation getKey(ITextureAtlasSpriteLoader value) {
|
||||
return LOADERS.inverse().get(value);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init() {
|
||||
var loaders = new HashMap<ResourceLocation, ITextureAtlasSpriteLoader>();
|
||||
var loaders = HashBiMap.<ResourceLocation, ITextureAtlasSpriteLoader>create();
|
||||
var event = new RegisterTextureAtlasSpriteLoadersEvent(loaders);
|
||||
ModLoader.get().postEventWrapContainerInModOrder(event);
|
||||
LOADERS = ImmutableMap.copyOf(loaders);
|
||||
LOADERS = ImmutableBiMap.copyOf(loaders);
|
||||
}
|
||||
|
||||
private TextureAtlasSpriteLoaderManager() {}
|
||||
|
||||
@@ -685,7 +685,7 @@ public final class ForgeHooks {
|
||||
if (potion != null && potion.unwrapKey().isPresent())
|
||||
return potion.unwrapKey().get().location().getNamespace();
|
||||
} else if (item instanceof SpawnEggItem egg) {
|
||||
var resourceLocation = ForgeRegistries.ENTITY_TYPES.getKey(egg.getType(itemStack));
|
||||
var resourceLocation = EntityType.getKey(egg.getDefaultType());
|
||||
if (resourceLocation != null)
|
||||
return resourceLocation.getNamespace();
|
||||
}
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.dispenser.DispenseItemBehavior;
|
||||
import net.minecraft.util.ARGB;
|
||||
import net.minecraft.world.entity.EntitySpawnReason;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.SpawnEggItem;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ForgeSpawnEggItem extends SpawnEggItem {
|
||||
private static final List<ForgeSpawnEggItem> MOD_EGGS = new ArrayList<>();
|
||||
private static final Map<EntityType<? extends Mob>, ForgeSpawnEggItem> TYPE_MAP = new IdentityHashMap<>();
|
||||
private final Supplier<? extends EntityType<? extends Mob>> typeSupplier;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ForgeSpawnEggItem(Supplier<? extends EntityType<? extends Mob>> type, int backgroundColor, int highlightColor, Properties props) {
|
||||
super((EntityType<? extends Mob>)null, backgroundColor, highlightColor, props);
|
||||
this.typeSupplier = type;
|
||||
|
||||
MOD_EGGS.add(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected DispenseItemBehavior createDispenseBehavior() {
|
||||
return DEFAULT_DISPENSE_BEHAVIOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Nullable
|
||||
public static SpawnEggItem fromEntityType(@Nullable EntityType<?> type) {
|
||||
SpawnEggItem ret = TYPE_MAP.get(type);
|
||||
return ret != null ? ret : SpawnEggItem.byId(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityType<?> getDefaultType() {
|
||||
return this.typeSupplier.get();
|
||||
}
|
||||
|
||||
private static final DispenseItemBehavior DEFAULT_DISPENSE_BEHAVIOR = (source, stack) -> {
|
||||
Direction face = source.state().getValue(DispenserBlock.FACING);
|
||||
EntityType<?> type = ((SpawnEggItem)stack.getItem()).getType(stack);
|
||||
|
||||
try {
|
||||
type.spawn(source.level(), stack, null, source.pos().relative(face), EntitySpawnReason.DISPENSER, face != Direction.UP, false);
|
||||
} catch (Exception exception) {
|
||||
DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), exception);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
stack.shrink(1);
|
||||
source.level().gameEvent(GameEvent.ENTITY_PLACE, source.pos(), GameEvent.Context.of(source.state()));
|
||||
return stack;
|
||||
};
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "forge", bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
private static class CommonHandler {
|
||||
@SubscribeEvent
|
||||
public static void onCommonSetup(FMLCommonSetupEvent event) {
|
||||
MOD_EGGS.forEach(egg -> {
|
||||
DispenseItemBehavior dispenseBehavior = egg.createDispenseBehavior();
|
||||
if (dispenseBehavior != null)
|
||||
DispenserBlock.registerBehavior(egg, dispenseBehavior);
|
||||
|
||||
TYPE_MAP.put(egg.typeSupplier.get(), egg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber(value = Dist.CLIENT, modid = "forge", bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
private static class ColorRegisterHandler {
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public static void registerSpawnEggColors(RegisterColorHandlersEvent.Item event) {
|
||||
for (ForgeSpawnEggItem egg : MOD_EGGS) {
|
||||
event.register((stack, layer) -> {
|
||||
int color = egg.getColor(layer);
|
||||
if (ARGB.alpha(color) == 0)
|
||||
color = ARGB.opaque(color);
|
||||
return color;
|
||||
}, egg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.resources.DelegatingOps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
@@ -36,6 +37,10 @@ public interface ICondition {
|
||||
@ApiStatus.Internal
|
||||
public static ResourceLocation KEY = ResourceLocation.fromNamespaceAndPath("forge", "condition_context");
|
||||
|
||||
default <T, O extends DelegatingOps<T>> O wrap(O ops) {
|
||||
return ops.withContext(KEY, this);
|
||||
}
|
||||
|
||||
IContext EMPTY = new IContext() {
|
||||
@Override
|
||||
public <T> Collection<Holder<T>> getTag(TagKey<T> key) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.common.crafting.ingredients;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
@@ -32,6 +33,15 @@ public abstract class AbstractIngredient extends Ingredient {
|
||||
@Override
|
||||
public abstract IIngredientSerializer<? extends Ingredient> serializer();
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.items().count() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsItem(Holder<Item> item) {
|
||||
return this.items().anyMatch(i -> i.equals(item));
|
||||
}
|
||||
|
||||
/* Hide vanilla ingredient static constructors to reduce errors with constructing custom ingredients */
|
||||
|
||||
|
||||
+5
-3
@@ -9,6 +9,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
@@ -44,14 +46,14 @@ public class CompoundIngredient extends AbstractIngredient {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Holder<Item>> items() {
|
||||
public Stream<Holder<Item>> items() {
|
||||
if (this.items == null) {
|
||||
var tmp = new ArrayList<Holder<Item>>();
|
||||
for (var child : children)
|
||||
tmp.addAll(child.items());
|
||||
child.items().forEach(tmp::add);
|
||||
this.items = Collections.unmodifiableList(tmp);
|
||||
}
|
||||
return this.items;
|
||||
return this.items.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-11
@@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** Ingredient that matches everything from the first ingredient that is not included in the second ingredient */
|
||||
public class DifferenceIngredient extends AbstractIngredient {
|
||||
@@ -49,24 +50,18 @@ public class DifferenceIngredient extends AbstractIngredient {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<Holder<Item>> items() {
|
||||
public Stream<Holder<Item>> items() {
|
||||
if (this.items == null) {
|
||||
var tmp = new ArrayList<Holder<Item>>();
|
||||
|
||||
for (var base : this.base.items()) {
|
||||
boolean match = false;
|
||||
for (var item : this.subtracted.items()) {
|
||||
if (base.is(item)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.base.items().forEach(base -> {
|
||||
boolean match = this.subtracted.items().anyMatch(base::is);
|
||||
if (!match)
|
||||
tmp.add(base);
|
||||
}
|
||||
});
|
||||
this.items = Collections.unmodifiableList(tmp);
|
||||
}
|
||||
return items;
|
||||
return items.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-11
@@ -19,6 +19,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** Ingredient that matches if all child ingredients match */
|
||||
public class IntersectionIngredient extends AbstractIngredient {
|
||||
@@ -61,20 +62,14 @@ public class IntersectionIngredient extends AbstractIngredient {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<Holder<Item>> items() {
|
||||
public Stream<Holder<Item>> items() {
|
||||
if (this.items == null) {
|
||||
var tmp = new ArrayList<Holder<Item>>();
|
||||
|
||||
for (var base : children.get(0).items()) {
|
||||
children.get(0).items().forEach(base -> {
|
||||
boolean allMatch = true;
|
||||
for (int i = 1; i < children.size(); i++) {
|
||||
boolean match = false;
|
||||
for (var item : children.get(i).items()) {
|
||||
if (base.is(item)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean match = children.get(i).items().anyMatch(base::is);
|
||||
if (!match) {
|
||||
allMatch = false;
|
||||
break;
|
||||
@@ -82,10 +77,10 @@ public class IntersectionIngredient extends AbstractIngredient {
|
||||
}
|
||||
if (allMatch)
|
||||
tmp.add(base);
|
||||
}
|
||||
});
|
||||
this.items = Collections.unmodifiableList(tmp);
|
||||
}
|
||||
return items;
|
||||
return items.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,7 +36,6 @@ import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
@@ -271,17 +270,6 @@ public interface IForgeBlock {
|
||||
return self().getExplosionResistance();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when A user uses the creative pick block button on this block
|
||||
*
|
||||
* @param target The full target the player is looking at
|
||||
* @return A ItemStack to add to the player's inventory, empty itemstack if nothing should be added.
|
||||
*/
|
||||
default ItemStack getCloneItemStack(BlockState state, HitResult target, LevelReader level, BlockPos pos, Player player) {
|
||||
return self().getCloneItemStack(level, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a block to override the standard EntityLivingBase.updateFallState
|
||||
* particles, this is a server side method that spawns particles with
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
|
||||
@@ -22,10 +22,8 @@ import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.SignalGetter;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraftforge.common.IPlantable;
|
||||
@@ -200,17 +198,6 @@ public interface IForgeBlockState {
|
||||
return self().getBlock().getExplosionResistance(self(), level, pos, explosion);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when A user uses the creative pick block button on this block
|
||||
*
|
||||
* @param target The full target the player is looking at
|
||||
* @return A ItemStack to add to the player's inventory, empty itemstack if nothing should be added.
|
||||
*/
|
||||
default ItemStack getCloneItemStack(HitResult target, LevelReader level, BlockPos pos, Player player) {
|
||||
return self().getBlock().getCloneItemStack(self(), target, level, pos, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a block to override the standard EntityLivingBase.updateFallState
|
||||
* particles, this is a server side method that spawns particles with
|
||||
|
||||
@@ -17,14 +17,11 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.common.ForgeSpawnEggItem;
|
||||
import net.minecraftforge.common.SoundAction;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.entity.PartEntity;
|
||||
@@ -72,21 +69,6 @@ public interface IForgeEntity extends ICapabilitySerializable<CompoundTag> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user uses the creative pick block button on this entity.
|
||||
*
|
||||
* @param target The full target the player is looking at
|
||||
* @return A ItemStack to add to the player's inventory, empty ItemStack if nothing should be added.
|
||||
*/
|
||||
default ItemStack getPickedResult(HitResult target) {
|
||||
var result = self().getPickResult();
|
||||
if (result == null) {
|
||||
var egg = ForgeSpawnEggItem.fromEntityType(self().getType());
|
||||
result = egg == null ? ItemStack.EMPTY : new ItemStack(egg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a rider of this entity can interact with this entity. Should return true on the
|
||||
* ridden entity if so.
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.resources.FileToIdConverter;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class LootModifierManager extends SimpleJsonResourceReloadListener<JsonElement> {
|
||||
@@ -36,7 +37,7 @@ public class LootModifierManager extends SimpleJsonResourceReloadListener<JsonEl
|
||||
private Map<ResourceLocation, IGlobalLootModifier> modifiers = ImmutableMap.of();
|
||||
|
||||
public LootModifierManager(HolderLookup.Provider registries) {
|
||||
super(registries, ExtraCodecs.JSON, FOLDER);
|
||||
super(registries.createSerializationContext(JsonOps.INSTANCE), ExtraCodecs.JSON, FileToIdConverter.json(FOLDER));
|
||||
this.registries = registries;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.Optional;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.sounds.Music;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.random.SimpleWeightedRandomList;
|
||||
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
|
||||
import net.minecraft.world.level.biome.AmbientMoodSettings;
|
||||
import net.minecraft.world.level.biome.AmbientParticleSettings;
|
||||
@@ -19,10 +20,8 @@ import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
* Extension of the vanilla builder but also provides read access and a copy-from-existing-data helper.
|
||||
* Also, the base builder crashes if certain values aren't specified on build, so this enforces the setting of those.
|
||||
*/
|
||||
public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder
|
||||
{
|
||||
public static BiomeSpecialEffectsBuilder copyOf(BiomeSpecialEffects baseEffects)
|
||||
{
|
||||
public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder {
|
||||
public static BiomeSpecialEffectsBuilder copyOf(BiomeSpecialEffects baseEffects) {
|
||||
BiomeSpecialEffectsBuilder builder = BiomeSpecialEffectsBuilder.create(baseEffects.getFogColor(), baseEffects.getWaterColor(), baseEffects.getWaterFogColor(), baseEffects.getSkyColor());
|
||||
builder.grassColorModifier = baseEffects.getGrassColorModifier();
|
||||
baseEffects.getFoliageColorOverride().ifPresent(builder::foliageColorOverride);
|
||||
@@ -35,13 +34,11 @@ public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static BiomeSpecialEffectsBuilder create(int fogColor, int waterColor, int waterFogColor, int skyColor)
|
||||
{
|
||||
public static BiomeSpecialEffectsBuilder create(int fogColor, int waterColor, int waterFogColor, int skyColor) {
|
||||
return new BiomeSpecialEffectsBuilder(fogColor, waterColor, waterFogColor, skyColor);
|
||||
}
|
||||
|
||||
protected BiomeSpecialEffectsBuilder(int fogColor, int waterColor, int waterFogColor, int skyColor)
|
||||
{
|
||||
protected BiomeSpecialEffectsBuilder(int fogColor, int waterColor, int waterFogColor, int skyColor) {
|
||||
super();
|
||||
this.fogColor(fogColor);
|
||||
this.waterColor(waterColor);
|
||||
@@ -49,63 +46,51 @@ public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder
|
||||
this.skyColor(skyColor);
|
||||
}
|
||||
|
||||
public int getFogColor()
|
||||
{
|
||||
public int getFogColor() {
|
||||
return this.fogColor.getAsInt();
|
||||
}
|
||||
|
||||
public int waterColor()
|
||||
{
|
||||
public int waterColor() {
|
||||
return this.waterColor.getAsInt();
|
||||
}
|
||||
|
||||
public int getWaterFogColor()
|
||||
{
|
||||
public int getWaterFogColor() {
|
||||
return this.waterFogColor.getAsInt();
|
||||
}
|
||||
|
||||
public int getSkyColor()
|
||||
{
|
||||
public int getSkyColor() {
|
||||
return this.skyColor.getAsInt();
|
||||
}
|
||||
|
||||
public BiomeSpecialEffects.GrassColorModifier getGrassColorModifier()
|
||||
{
|
||||
public BiomeSpecialEffects.GrassColorModifier getGrassColorModifier() {
|
||||
return this.grassColorModifier;
|
||||
}
|
||||
|
||||
public Optional<Integer> getFoliageColorOverride()
|
||||
{
|
||||
public Optional<Integer> getFoliageColorOverride() {
|
||||
return this.foliageColorOverride;
|
||||
}
|
||||
|
||||
public Optional<Integer> getGrassColorOverride()
|
||||
{
|
||||
public Optional<Integer> getGrassColorOverride() {
|
||||
return this.grassColorOverride;
|
||||
}
|
||||
|
||||
public Optional<AmbientParticleSettings> getAmbientParticle()
|
||||
{
|
||||
public Optional<AmbientParticleSettings> getAmbientParticle() {
|
||||
return this.ambientParticle;
|
||||
}
|
||||
|
||||
public Optional<Holder<SoundEvent>> getAmbientLoopSound()
|
||||
{
|
||||
public Optional<Holder<SoundEvent>> getAmbientLoopSound() {
|
||||
return this.ambientLoopSoundEvent;
|
||||
}
|
||||
|
||||
public Optional<AmbientMoodSettings> getAmbientMoodSound()
|
||||
{
|
||||
public Optional<AmbientMoodSettings> getAmbientMoodSound() {
|
||||
return this.ambientMoodSettings;
|
||||
}
|
||||
|
||||
public Optional<AmbientAdditionsSettings> getAmbientAdditionsSound()
|
||||
{
|
||||
public Optional<AmbientAdditionsSettings> getAmbientAdditionsSound() {
|
||||
return this.ambientAdditionsSettings;
|
||||
}
|
||||
|
||||
public Optional<Music> getBackgroundMusic()
|
||||
{
|
||||
public Optional<SimpleWeightedRandomList<Music>> getBackgroundMusic() {
|
||||
return this.backgroundMusic;
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,17 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import joptsimple.OptionSpec;
|
||||
|
||||
public class DatagenModLoader {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static ExistingFileHelper existingFileHelper;
|
||||
@@ -33,13 +38,49 @@ public class DatagenModLoader {
|
||||
return runningDataGen;
|
||||
}
|
||||
|
||||
public static void begin(
|
||||
Set<String> patterns, Path output, Collection<Path> inputs, Collection<Path> existingPacks, Set<String> existingMods,
|
||||
boolean genServer, boolean genClient, boolean genDev, boolean genReports,
|
||||
boolean validate, boolean flat, String assetIndex, File assetsDir
|
||||
public static DatagenModLoader setup(OptionParser parser, boolean client) {
|
||||
return new DatagenModLoader(parser, client);
|
||||
}
|
||||
|
||||
private final OptionParser parser;
|
||||
private final boolean client;
|
||||
private final OptionSpec<String> existing;
|
||||
private final OptionSpec<String> existingMod;
|
||||
private final OptionSpec<String> mod;
|
||||
private final OptionSpec<String> assetIndex;
|
||||
private final OptionSpec<File> gameDir;
|
||||
private final OptionSpec<File> assetsDir;
|
||||
private final OptionSpec<Void> flat;
|
||||
|
||||
private DatagenModLoader(OptionParser parser, boolean client) {
|
||||
this.gameDir = parser.accepts("gameDir").withRequiredArg().ofType(java.io.File.class).defaultsTo(new java.io.File(".")).required(); //Need by modlauncher, so lets just eat it
|
||||
this.parser = parser;
|
||||
this.client = client;
|
||||
this.existing = parser.accepts("existing", "Existing resource packs that generated resources can reference").withRequiredArg();
|
||||
this.existingMod = parser.accepts("existing-mod", "Existing mods that generated resources can reference the resource packs of").withRequiredArg();
|
||||
this.mod = parser.accepts("mod", "A modid to dump").withRequiredArg().withValuesSeparatedBy(",");
|
||||
this.flat = parser.accepts("flat", "Do not append modid prefix to output directory when generating for multiple mods");
|
||||
this.assetIndex = parser.accepts("assetIndex").withRequiredArg();
|
||||
this.assetsDir = parser.accepts("assetsDir").withRequiredArg().ofType(java.io.File.class);
|
||||
}
|
||||
|
||||
public boolean hasArgs(OptionSet options) {
|
||||
return options.specs().size() != 1 || !options.has(gameDir);
|
||||
}
|
||||
|
||||
public boolean run(
|
||||
OptionSet options, Path output, Collection<Path> inputs,
|
||||
boolean genServer, boolean genClient, boolean genDev, boolean genReports, boolean validate
|
||||
) {
|
||||
var existingPacks = options.valuesOf(this.existing).stream().map(Paths::get).toList();
|
||||
var existingMods = new HashSet<>(options.valuesOf(this.existingMod));
|
||||
var patterns = new HashSet<>(options.valuesOf(this.mod));
|
||||
var flat = patterns.isEmpty() || options.has(this.flat);
|
||||
var assetIndex = options.valueOf(this.assetIndex);
|
||||
var assetsDir = options.valueOf(this.assetsDir);
|
||||
|
||||
if (patterns.contains("minecraft") && patterns.size() == 1)
|
||||
return;
|
||||
return true;
|
||||
|
||||
runningDataGen = true;
|
||||
Bootstrap.bootStrap();
|
||||
@@ -77,5 +118,7 @@ public class DatagenModLoader {
|
||||
), config, existingFileHelper)
|
||||
);
|
||||
config.runAll();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.server.packs.AbstractPackResources;
|
||||
import net.minecraft.server.packs.PackLocationInfo;
|
||||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.MetadataSectionSerializer;
|
||||
import net.minecraft.server.packs.metadata.MetadataSectionType;
|
||||
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
|
||||
import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.Pack.Metadata;
|
||||
@@ -58,8 +58,8 @@ public class DelegatingPackResources extends AbstractPackResources {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getMetadataSection(MetadataSectionSerializer<T> deserializer) throws IOException {
|
||||
return deserializer.getMetadataSectionName().equals("pack") ? (T) this.packMeta : null;
|
||||
public <T> T getMetadataSection(MetadataSectionType<T> deserializer) throws IOException {
|
||||
return deserializer.name().equals("pack") ? (T) this.packMeta : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user