Added the variant name to the missing model. (#3328)
This commit is contained in:
parent
1e7eb6fb09
commit
bbc107de96
6 changed files with 425 additions and 5 deletions
|
@ -0,0 +1,223 @@
|
|||
package net.minecraftforge.client.model;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.ForgeModContainer;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.vecmath.Quat4f;
|
||||
import javax.vecmath.Vector3f;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
final class FancyMissingModel implements IModel
|
||||
{
|
||||
private static final ResourceLocation font = new ResourceLocation("minecraft", "textures/font/ascii.png");
|
||||
private static final ResourceLocation font2 = new ResourceLocation("minecraft", "font/ascii");
|
||||
private static final TRSRTransformation smallTransformation = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(null, null, new Vector3f(.25f, .25f, .25f), null));
|
||||
private static final LoadingCache<VertexFormat, SimpleModelFontRenderer> fontCache = CacheBuilder.newBuilder().maximumSize(3).build(new CacheLoader<VertexFormat, SimpleModelFontRenderer>()
|
||||
{
|
||||
public SimpleModelFontRenderer load(VertexFormat format) throws Exception
|
||||
{
|
||||
Matrix4f m = new Matrix4f();
|
||||
m.m20 = 1f / 128f;
|
||||
m.m01 = m.m12 = -m.m20;
|
||||
m.m33 = 1;
|
||||
m.setTranslation(new Vector3f(1, 1 + 1f / 0x100, 0));
|
||||
return new SimpleModelFontRenderer(
|
||||
Minecraft.getMinecraft().gameSettings,
|
||||
font,
|
||||
Minecraft.getMinecraft().getTextureManager(),
|
||||
false,
|
||||
m,
|
||||
format
|
||||
) {
|
||||
@Override
|
||||
protected float renderUnicodeChar(char c, boolean italic)
|
||||
{
|
||||
return super.renderDefaultChar(126, italic);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
private final IModel missingModel;
|
||||
private final String message;
|
||||
|
||||
public FancyMissingModel(IModel missingModel, String message)
|
||||
{
|
||||
this.missingModel = missingModel;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getTextures()
|
||||
{
|
||||
return ImmutableList.of(font2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
IBakedModel bigMissing = missingModel.bake(state, format, bakedTextureGetter);
|
||||
IModelState smallState = new ModelStateComposition(state, smallTransformation);
|
||||
IBakedModel smallMissing = missingModel.bake(smallState, format, bakedTextureGetter);
|
||||
return new BakedModel(bigMissing, smallMissing, fontCache.getUnchecked(format), message, bakedTextureGetter.apply(font2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModelState getDefaultState()
|
||||
{
|
||||
return TRSRTransformation.identity();
|
||||
}
|
||||
|
||||
private static final class BakedModel implements IPerspectiveAwareModel
|
||||
{
|
||||
private final SimpleModelFontRenderer fontRenderer;
|
||||
private final String message;
|
||||
private final TextureAtlasSprite fontTexture;
|
||||
private final IBakedModel missingModel;
|
||||
private final IBakedModel otherModel;
|
||||
private final boolean big;
|
||||
private ImmutableList<BakedQuad> quads;
|
||||
|
||||
public BakedModel(IBakedModel bigMissing, IBakedModel smallMissing, SimpleModelFontRenderer fontRenderer, String message, TextureAtlasSprite fontTexture)
|
||||
{
|
||||
this.missingModel = bigMissing;
|
||||
otherModel = new BakedModel(smallMissing, fontRenderer, message, fontTexture, this);
|
||||
this.big = true;
|
||||
this.fontRenderer = fontRenderer;
|
||||
this.message = message;
|
||||
this.fontTexture = fontTexture;
|
||||
}
|
||||
|
||||
public BakedModel(IBakedModel smallMissing, SimpleModelFontRenderer fontRenderer, String message, TextureAtlasSprite fontTexture, BakedModel big)
|
||||
{
|
||||
this.missingModel = smallMissing;
|
||||
otherModel = big;
|
||||
this.big = false;
|
||||
this.fontRenderer = fontRenderer;
|
||||
this.message = message;
|
||||
this.fontTexture = fontTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
if (side == null)
|
||||
{
|
||||
if (quads == null)
|
||||
{
|
||||
fontRenderer.setSprite(fontTexture);
|
||||
fontRenderer.setFillBlanks(true);
|
||||
String[] lines = message.split("\\r?\\n");
|
||||
List<String> splitLines = Lists.newArrayList();
|
||||
for (int y = 0; y < lines.length; y++)
|
||||
{
|
||||
splitLines.addAll(fontRenderer.listFormattedStringToWidth(lines[y], 0x80));
|
||||
}
|
||||
for (int y = 0; y < splitLines.size(); y++)
|
||||
{
|
||||
fontRenderer.drawString(splitLines.get(y), 0, (int)((y - splitLines.size() / 2f) * fontRenderer.FONT_HEIGHT) + 0x40, 0xFF00FFFF);
|
||||
}
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
builder.addAll(missingModel.getQuads(state, side, rand));
|
||||
builder.addAll(fontRenderer.build());
|
||||
quads = builder.build();
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
return missingModel.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() { return true; }
|
||||
|
||||
@Override
|
||||
public boolean isGui3d() { return false; }
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() { return false; }
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() { return fontTexture; }
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() { return ItemCameraTransforms.DEFAULT; }
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() { return ItemOverrideList.NONE; }
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType)
|
||||
{
|
||||
TRSRTransformation transform = TRSRTransformation.identity();
|
||||
boolean big = true;
|
||||
switch (cameraTransformType)
|
||||
{
|
||||
|
||||
case THIRD_PERSON_LEFT_HAND:
|
||||
break;
|
||||
case THIRD_PERSON_RIGHT_HAND:
|
||||
break;
|
||||
case FIRST_PERSON_LEFT_HAND:
|
||||
transform = new TRSRTransformation(new Vector3f(-0.62f, 0.5f, -.5f), new Quat4f(1, -1, -1, 1), null, null);
|
||||
big = false;
|
||||
break;
|
||||
case FIRST_PERSON_RIGHT_HAND:
|
||||
transform = new TRSRTransformation(new Vector3f(-0.5f, 0.5f, -.5f), new Quat4f(1, 1, 1, 1), null, null);
|
||||
big = false;
|
||||
break;
|
||||
case HEAD:
|
||||
break;
|
||||
case GUI:
|
||||
if (ForgeModContainer.zoomInMissingModelTextInGui)
|
||||
{
|
||||
transform = new TRSRTransformation(null, new Quat4f(1, 1, 1, 1), new Vector3f(4, 4, 4), null);
|
||||
big = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = new TRSRTransformation(null, new Quat4f(1, 1, 1, 1), null, null);
|
||||
big = true;
|
||||
}
|
||||
break;
|
||||
case FIXED:
|
||||
transform = new TRSRTransformation(null, new Quat4f(-1, -1, 1, 1), null, null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (big != this.big)
|
||||
{
|
||||
return Pair.of(otherModel, transform.getMatrix());
|
||||
}
|
||||
return Pair.of(this, transform.getMatrix());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -262,7 +262,7 @@ public final class ModelLoader extends ModelBakery
|
|||
catch(Exception e)
|
||||
{
|
||||
storeException(location, e);
|
||||
model = getMissingModel();
|
||||
model = ModelLoaderRegistry.getMissingModel(location, e);
|
||||
}
|
||||
stateModels.put(location, model);
|
||||
}
|
||||
|
@ -348,11 +348,12 @@ public final class ModelLoader extends ModelBakery
|
|||
exception = new ItemLoadingException("Could not load item model either from the normal location " + file + " or from the blockstate", normalException, blockstateException);
|
||||
}
|
||||
}
|
||||
stateModels.put(memory, model);
|
||||
if(exception != null)
|
||||
{
|
||||
storeException(memory, exception);
|
||||
model = ModelLoaderRegistry.getMissingModel(memory, exception);
|
||||
}
|
||||
stateModels.put(memory, model);
|
||||
}
|
||||
}
|
||||
ProgressManager.pop(itemBar);
|
||||
|
|
|
@ -189,7 +189,7 @@ public class ModelLoaderRegistry
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return getMissingModel();
|
||||
return getMissingModel(location, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ public class ModelLoaderRegistry
|
|||
catch(Exception e)
|
||||
{
|
||||
FMLLog.getLogger().error(error, e);
|
||||
return getMissingModel();
|
||||
return getMissingModel(location, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,14 @@ public class ModelLoaderRegistry
|
|||
return ModelLoader.VanillaLoader.INSTANCE.getLoader().getMissingModel();
|
||||
}
|
||||
|
||||
static IModel getMissingModel(ResourceLocation location, Throwable cause)
|
||||
{
|
||||
//IModel model = new FancyMissingModel(ExceptionUtils.getStackTrace(cause).replaceAll("\\t", " "));
|
||||
IModel model = new FancyMissingModel(getMissingModel(), location.toString());
|
||||
textures.addAll(model.getTextures());
|
||||
return model;
|
||||
}
|
||||
|
||||
public static void clearModelCache(IResourceManager manager)
|
||||
{
|
||||
ModelLoaderRegistry.manager = manager;
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
package net.minecraftforge.client.model;
|
||||
|
||||
import javax.vecmath.Matrix3f;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.vecmath.Vector3f;
|
||||
import javax.vecmath.Vector4f;
|
||||
|
||||
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public abstract class SimpleModelFontRenderer extends FontRenderer {
|
||||
|
||||
private float r, g, b, a;
|
||||
private final Matrix4f matrix;
|
||||
private ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
private final VertexFormat format;
|
||||
private final Vector3f normal = new Vector3f(0, 0, 1);
|
||||
private final EnumFacing orientation;
|
||||
private boolean fillBlanks = false;
|
||||
|
||||
private TextureAtlasSprite sprite;
|
||||
|
||||
public SimpleModelFontRenderer(GameSettings settings, ResourceLocation font, TextureManager manager, boolean isUnicode, Matrix4f matrix, VertexFormat format)
|
||||
{
|
||||
super(settings, font, manager, isUnicode);
|
||||
manager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
this.matrix = new Matrix4f(matrix);
|
||||
Matrix3f nm = new Matrix3f();
|
||||
this.matrix.getRotationScale(nm);
|
||||
nm.invert();
|
||||
nm.transpose();
|
||||
this.format = format;
|
||||
nm.transform(normal);
|
||||
normal.normalize();
|
||||
orientation = EnumFacing.getFacingFromVector(normal.x, normal.y, normal.z);
|
||||
}
|
||||
|
||||
public void setSprite(TextureAtlasSprite sprite)
|
||||
{
|
||||
this.sprite = sprite;
|
||||
super.onResourceManagerReload(null);
|
||||
}
|
||||
|
||||
public void setFillBlanks(boolean fillBlanks)
|
||||
{
|
||||
this.fillBlanks = fillBlanks;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float renderDefaultChar(int pos, boolean italic)
|
||||
{
|
||||
float x = (pos % 16) / 16f;
|
||||
float y = (pos / 16) / 16f;
|
||||
float sh = italic ? 1f : 0f;
|
||||
float w = charWidth[pos] - 1.01f;
|
||||
float h = FONT_HEIGHT - 1.01f;
|
||||
float wt = w / 128f;
|
||||
float ht = h / 128f;
|
||||
|
||||
UnpackedBakedQuad.Builder quadBuilder = new UnpackedBakedQuad.Builder(format);
|
||||
quadBuilder.setQuadOrientation(orientation);
|
||||
|
||||
addVertex(quadBuilder, posX + sh, posY, x, y);
|
||||
addVertex(quadBuilder, posX - sh, posY + h, x, y + ht);
|
||||
addVertex(quadBuilder, posX + w + sh, posY + h, x + wt, y + ht);
|
||||
addVertex(quadBuilder, posX + w - sh, posY, x + wt, y);
|
||||
builder.add(quadBuilder.build());
|
||||
|
||||
if(fillBlanks)
|
||||
{
|
||||
float cuv = 15f / 16f;
|
||||
|
||||
quadBuilder = new UnpackedBakedQuad.Builder(format);
|
||||
quadBuilder.setQuadOrientation(orientation);
|
||||
|
||||
addVertex(quadBuilder, posX + w + sh, posY, cuv, cuv);
|
||||
addVertex(quadBuilder, posX + w - sh, posY + h, cuv, cuv);
|
||||
addVertex(quadBuilder, posX + charWidth[pos] + sh, posY + h, cuv, cuv);
|
||||
addVertex(quadBuilder, posX + charWidth[pos] - sh, posY, cuv, cuv);
|
||||
builder.add(quadBuilder.build());
|
||||
|
||||
quadBuilder = new UnpackedBakedQuad.Builder(format);
|
||||
quadBuilder.setQuadOrientation(orientation);
|
||||
|
||||
addVertex(quadBuilder, posX + sh, posY + h, cuv, cuv);
|
||||
addVertex(quadBuilder, posX - sh, posY + FONT_HEIGHT, cuv, cuv);
|
||||
addVertex(quadBuilder, posX + charWidth[pos] + sh, posY + FONT_HEIGHT, cuv, cuv);
|
||||
addVertex(quadBuilder, posX + charWidth[pos] - sh, posY + h, cuv, cuv);
|
||||
builder.add(quadBuilder.build());
|
||||
}
|
||||
return charWidth[pos];
|
||||
}
|
||||
|
||||
private final Vector4f vec = new Vector4f();
|
||||
|
||||
private void addVertex(UnpackedBakedQuad.Builder quadBuilder, float x, float y, float u, float v)
|
||||
{
|
||||
vec.x = x;
|
||||
vec.y = y;
|
||||
vec.z = 0;
|
||||
vec.w = 1;
|
||||
matrix.transform(vec);
|
||||
for(int e = 0; e < format.getElementCount(); e++)
|
||||
{
|
||||
switch(format.getElement(e).getUsage())
|
||||
{
|
||||
case POSITION:
|
||||
quadBuilder.put(e, vec.x, vec.y, vec.z, vec.w);
|
||||
break;
|
||||
case UV:
|
||||
quadBuilder.put(e, sprite.getInterpolatedU(u * 16), sprite.getInterpolatedV(v * 16), 0, 1);
|
||||
break;
|
||||
case COLOR:
|
||||
quadBuilder.put(e, r, g, b, a);
|
||||
break;
|
||||
case NORMAL:
|
||||
//quadBuilder.put(e, normal.x, normal.y, normal.z, 1);
|
||||
quadBuilder.put(e, 0, 0, 1, 1);
|
||||
break;
|
||||
default:
|
||||
quadBuilder.put(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager)
|
||||
{
|
||||
super.onResourceManagerReload(resourceManager);
|
||||
String p = locationFontTexture.getResourcePath();
|
||||
if(p.startsWith("textures/")) p = p.substring("textures/".length(), p.length());
|
||||
if(p.endsWith(".png")) p = p.substring(0, p.length() - ".png".length());
|
||||
String f = locationFontTexture.getResourceDomain() + ":" + p;
|
||||
sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract float renderUnicodeChar(char c, boolean italic);
|
||||
|
||||
@Override
|
||||
protected void doDraw(float shift)
|
||||
{
|
||||
posX += (int)shift;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setColor(float r, float g, float b, float a)
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
@Override public void enableAlpha()
|
||||
{
|
||||
}
|
||||
|
||||
public ImmutableList<BakedQuad> build()
|
||||
{
|
||||
ImmutableList<BakedQuad> ret = builder.build();
|
||||
builder = ImmutableList.builder();
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -112,6 +112,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
public static boolean disableVersionCheck = false;
|
||||
public static boolean forgeLightPipelineEnabled = true;
|
||||
public static boolean replaceVanillaBucketModel = true;
|
||||
public static boolean zoomInMissingModelTextInGui = false;
|
||||
public static long java8Reminder = 0;
|
||||
public static boolean disableStairSlabCulling = false; // Also known as the "DontCullStairsBecauseIUseACrappyTexturePackThatBreaksBasicBlockShapesSoICantTrustBasicBlockCulling" flag
|
||||
public static boolean alwaysSetupTerrainOffThread = false; // In RenderGlobal.setupTerrain, always force the chunk render updates to be queued to the thread
|
||||
|
@ -283,12 +284,19 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
|
||||
// Client-Side only properties
|
||||
propOrder = new ArrayList<String>();
|
||||
|
||||
prop = config.get(Configuration.CATEGORY_CLIENT, "replaceVanillaBucketModel", Boolean.FALSE,
|
||||
"Replace the vanilla bucket models with Forges own dynamic bucket model. Unifies bucket visuals if a mod uses the Forge bucket model.");
|
||||
prop.setLanguageKey("forge.configgui.replaceBuckets").setRequiresMcRestart(true);
|
||||
replaceVanillaBucketModel = prop.getBoolean(Boolean.FALSE);
|
||||
propOrder.add(prop.getName());
|
||||
|
||||
prop = config.get(Configuration.CATEGORY_CLIENT, "zoomInMissingModelTextInGui", Boolean.TRUE,
|
||||
"Toggle off to make missing model text in the gui fit inside the slot.");
|
||||
zoomInMissingModelTextInGui = prop.getBoolean(Boolean.FALSE);
|
||||
prop.setLanguageKey("forge.configgui.zoomInMissingModelTextInGui");
|
||||
propOrder.add(prop.getName());
|
||||
|
||||
prop = config.get(Configuration.CATEGORY_CLIENT, "java8Reminder", java8Reminder,
|
||||
"The timestamp of the last reminder to update to Java 8 in number of milliseconds since January 1, 1970, 00:00:00 GMT. Nag will show only once every 24 hours. To disable it set this to some really high number.");
|
||||
java8Reminder = prop.getLong(java8Reminder);
|
||||
|
|
|
@ -49,6 +49,7 @@ forge.configgui.replaceBuckets=Use Forge's bucket model
|
|||
forge.configgui.forgeLightPipelineEnabled=Forge Light Pipeline Enabled
|
||||
forge.configgui.java8Reminder=Java 8 Reminder timestamp
|
||||
forge.configgui.disableStairSlabCulling=Disable Stair/Slab culling.
|
||||
forge.configgui.zoomInMissingModelTextInGui=Zoom in Missing model text in the GUI
|
||||
forge.configgui.disableStairSlabCulling.tooltip=Enable this if you see through blocks touching stairs/slabs with your resource pack.
|
||||
forge.configgui.alwaysSetupTerrainOffThread=Force threaded chunk rendering
|
||||
forge.configgui.alwaysSetupTerrainOffThread.tooltip=Enable forge to queue all chunk updates to the Chunk Update thread. May increase FPS significantly, but may also cause weird rendering lag. Not recommended for computers without a significant number of cores available.
|
||||
|
@ -186,4 +187,4 @@ fml.button.continue=Continue
|
|||
fml.button.open.mods.folder=Open Mods Folder
|
||||
fml.button.open.file=Open %s
|
||||
|
||||
forge.container.enchant.limitedEnchantability=Limited Enchantability
|
||||
forge.container.enchant.limitedEnchantability=Limited Enchantability
|
||||
|
|
Loading…
Reference in a new issue