Added "gui3d" and "smooth_lighting" options to the forge blockstate. Implemented them for vanilla and B3D models. Added generic types to IModel subinterfaces, to simplify chaining.

This commit is contained in:
RainWarrior 2016-02-02 12:22:06 +03:00
parent 7103862bf9
commit 3bdc75ad49
12 changed files with 170 additions and 53 deletions

View File

@ -63,12 +63,14 @@ public class BlockStateLoader
for (ForgeBlockStateV1.Variant var : entry.getValue())
{
boolean uvLock = var.getUvLock().or(false);
boolean smooth = var.getSmooth().or(true);
boolean gui3d = var.getGui3d().or(true);
int weight = var.getWeight().or(1);
if (var.getModel() != null && var.getSubmodels().size() == 0 && var.getTextures().size() == 0 && var.getCustomData().size() == 0 && var.getState().orNull() instanceof ModelRotation)
mcVars.add(new ModelBlockDefinition.Variant(var.getModel(), (ModelRotation)var.getState().get(), uvLock, weight));
else
mcVars.add(new ForgeVariant(var.getModel(), var.getState().or(TRSRTransformation.identity()), uvLock, weight, var.getTextures(), var.getOnlyPartsVariant(), var.getCustomData()));
mcVars.add(new ForgeVariant(var.getModel(), var.getState().or(TRSRTransformation.identity()), uvLock, smooth, gui3d, weight, var.getTextures(), var.getOnlyPartsVariant(), var.getCustomData()));
}
variants.add(new ModelBlockDefinition.Variants(entry.getKey(), mcVars));
}
@ -96,14 +98,24 @@ public class BlockStateLoader
{
private final IModelState state;
private final boolean uvLock;
private final boolean smooth;
private final boolean gui3d;
private final ImmutableMap<String, String> textures;
private final ResourceLocation model;
private final ImmutableMap<String, String> customData;
@Deprecated // remove in 1.9
public SubModel(IModelState state, boolean uvLock, ImmutableMap<String, String> textures, ResourceLocation model, ImmutableMap<String, String> customData)
{
this(state, uvLock, true, true, textures, model, customData);
}
public SubModel(IModelState state, boolean uvLock, boolean smooth, boolean gui3d, ImmutableMap<String, String> textures, ResourceLocation model, ImmutableMap<String, String> customData)
{
this.state = state;
this.uvLock = uvLock;
this.smooth = smooth;
this.gui3d = gui3d;
this.textures = textures;
this.model = model;
this.customData = customData;
@ -121,27 +133,36 @@ public class BlockStateLoader
private final ImmutableMap<String, String> textures;
private final ImmutableMap<String, SubModel> parts;
private final ImmutableMap<String, String> customData;
private final boolean smooth;
private final boolean gui3d;
private final IModelState state;
public ForgeVariant(ResourceLocation model, IModelState state, boolean uvLock, int weight, ImmutableMap<String, String> textures, ImmutableMap<String, SubModel> parts, ImmutableMap<String, String> customData)
public ForgeVariant(ResourceLocation model, IModelState state, boolean uvLock, boolean smooth, boolean gui3d, int weight, ImmutableMap<String, String> textures, ImmutableMap<String, SubModel> parts, ImmutableMap<String, String> customData)
{
super(model == null ? new ResourceLocation("builtin/missing") : model, state instanceof ModelRotation ? (ModelRotation)state : ModelRotation.X0_Y0, uvLock, weight);
this.textures = textures;
this.parts = parts;
this.customData = customData;
this.state = state;
this.smooth = smooth;
this.gui3d = gui3d;
}
protected IModel runModelHooks(IModel base, ImmutableMap<String, String> textureMap, ImmutableMap<String, String> customData)
private IModel runModelHooks(IModel base, boolean smooth, boolean gui3d, ImmutableMap<String, String> textureMap, ImmutableMap<String, String> customData)
{
if (!customData.isEmpty() && base instanceof IModelCustomData)
{
base = ((IModelCustomData)base).process(customData);
base = ((IModelCustomData<?>)base).process(customData);
}
if (!textureMap.isEmpty() && base instanceof IRetexturableModel)
{
base = ((IRetexturableModel)base).retexture(textureMap);
base = ((IRetexturableModel<?>)base).retexture(textureMap);
}
if (base instanceof IModelSimpleProperties<?>)
{
base = ((IModelSimpleProperties<?>) base).smoothLighting(smooth).gui3d(gui3d);
}
return base;
@ -158,7 +179,7 @@ public class BlockStateLoader
if (hasBase)
{
base = runModelHooks(base, textures, customData);
base = runModelHooks(base, smooth, gui3d, textures, customData);
if (size <= 0)
return base;
@ -187,7 +208,7 @@ public class BlockStateLoader
IModelState partState = new ModelStateComposition(baseTr, part.getState());
if (part.isUVLock()) partState = new ModelLoader.UVLock(partState);
models.put(entry.getKey(), Pair.<IModel, IModelState>of(runModelHooks(model, part.getTextures(), part.getCustomData()), partState));
models.put(entry.getKey(), Pair.<IModel, IModelState>of(runModelHooks(model, part.smooth, part.gui3d, part.getTextures(), part.getCustomData()), partState));
}
return new MultiModel(getModelLocation(), hasBase ? base : null, baseTr, models.build());

View File

@ -275,6 +275,8 @@ public class ForgeBlockStateV1 extends Marker
private boolean modelSet = false;
private Optional<IModelState> state = Optional.absent();
private Optional<Boolean> uvLock = Optional.absent();
private Optional<Boolean> smooth = Optional.absent();
private Optional<Boolean> gui3d = Optional.absent();
private Optional<Integer> weight = Optional.absent();
private Map<String, String> textures = Maps.newHashMap();
private Map<String, List<ForgeBlockStateV1.Variant>> submodels = Maps.newHashMap();
@ -292,6 +294,8 @@ public class ForgeBlockStateV1 extends Marker
this.modelSet = other.modelSet;
this.state = other.state;
this.uvLock = other.uvLock;
this.smooth = other.smooth;
this.gui3d = other.gui3d;
this.weight = other.weight;
this.textures.putAll(other.textures);
this.mergeModelPartVariants(this.submodels, other.submodels);
@ -311,6 +315,8 @@ public class ForgeBlockStateV1 extends Marker
}
if (!this.state.isPresent()) this.state = parent.state;
if (!this.uvLock.isPresent()) this.uvLock = parent.uvLock;
if (!this.smooth.isPresent()) this.smooth = parent.smooth;
if (!this.gui3d.isPresent()) this.gui3d = parent.gui3d;
if (!this.weight.isPresent()) this.weight = parent.weight;
for (Entry<String, String> e : parent.textures.entrySet())
@ -400,6 +406,16 @@ public class ForgeBlockStateV1 extends Marker
}
}
public Optional<Boolean> getSmooth()
{
return smooth;
}
public Optional<Boolean> getGui3d()
{
return gui3d;
}
public static class Deserializer implements JsonDeserializer<ForgeBlockStateV1.Variant>
{
static Variant.Deserializer INSTANCE = new Deserializer();
@ -593,6 +609,16 @@ public class ForgeBlockStateV1 extends Marker
ret.uvLock = Optional.of(JsonUtils.getBoolean(json, "uvlock"));
}
if (json.has("smooth_lighting"))
{
ret.smooth = Optional.of(JsonUtils.getBoolean(json, "smooth_lighting"));
}
if (json.has("gui3d"))
{
ret.gui3d = Optional.of(JsonUtils.getBoolean(json, "gui3d"));
}
if (json.has("weight"))
{ // Load weight.
ret.weight = Optional.of(JsonUtils.getInt(json, "weight"));

View File

@ -2,11 +2,13 @@ package net.minecraftforge.client.model;
import com.google.common.collect.ImmutableMap;
public interface IModelCustomData extends IModel
public interface IModelCustomData<M extends IModelCustomData<M>> extends IModel
{
/**
* Allows the model to process custom data from the variant definition
* @return a new model, with data applied
* Allows the model to process custom data from the variant definition.
* If unknown data is encountered it should be skipped.
* @return a new model, with data applied.
*/
// 1.9: change IModel to M
IModel process(ImmutableMap<String, String> customData);
}

View File

@ -2,7 +2,7 @@ package net.minecraftforge.client.model;
import com.google.common.collect.ImmutableMap;
public interface IRetexturableModel extends IModel
public interface IRetexturableModel<M extends IRetexturableModel<M>> extends IModel
{
/**
* Applies new textures to the model.
@ -21,5 +21,6 @@ public interface IRetexturableModel extends IModel
* @param textures New
* @return Model with textures applied.
*/
// 1.9: change IModel to M
IModel retexture(ImmutableMap<String, String> textures);
}

View File

@ -26,7 +26,7 @@ import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
public class ItemLayerModel implements IRetexturableModel
public class ItemLayerModel implements IRetexturableModel<ItemLayerModel>
{
public static final ItemLayerModel instance = new ItemLayerModel(ImmutableList.<ResourceLocation>of());
@ -68,7 +68,7 @@ public class ItemLayerModel implements IRetexturableModel
return TRSRTransformation.identity();
}
public IModel retexture(ImmutableMap<String, String> textures)
public ItemLayerModel retexture(ImmutableMap<String, String> textures)
{
ImmutableList.Builder<ResourceLocation> builder = ImmutableList.builder();
for(int i = 0; i < textures.size() + this.textures.size(); i++)

View File

@ -27,7 +27,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Map;
public class ModelDynBucket implements IModel, IModelCustomData, IRetexturableModel
public class ModelDynBucket implements IModel, IModelCustomData<ModelDynBucket>, IRetexturableModel<ModelDynBucket>
{
public static final ModelResourceLocation LOCATION = new ModelResourceLocation(new ResourceLocation("forge", "dynbucket"), "inventory");
@ -140,7 +140,7 @@ public class ModelDynBucket implements IModel, IModelCustomData, IRetexturableMo
* If the fluid can't be found, water is used
*/
@Override
public IModel process(ImmutableMap<String, String> customData)
public ModelDynBucket process(ImmutableMap<String, String> customData)
{
String fluidName = customData.get("fluid");
Fluid fluid = FluidRegistry.getFluid(fluidName);
@ -171,7 +171,7 @@ public class ModelDynBucket implements IModel, IModelCustomData, IRetexturableMo
* If no liquid is given a hardcoded variant for the bucket is used.
*/
@Override
public IModel retexture(ImmutableMap<String, String> textures)
public ModelDynBucket retexture(ImmutableMap<String, String> textures)
{
ResourceLocation base = baseLocation;

View File

@ -43,7 +43,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
@SuppressWarnings("deprecation")
public class ModelFluid implements IModelCustomData
public class ModelFluid implements IModelCustomData<ModelFluid>
{
public static final ModelFluid waterModel = new ModelFluid(FluidRegistry.WATER);
public static final ModelFluid lavaModel = new ModelFluid(FluidRegistry.LAVA);
@ -397,7 +397,7 @@ public class ModelFluid implements IModelCustomData
}
@Override
public IModel process(ImmutableMap<String, String> customData)
public ModelFluid process(ImmutableMap<String, String> customData)
{
if(!customData.containsKey("fluid")) return this;

View File

@ -407,7 +407,7 @@ public class ModelLoader extends ModelBakery
textures.addAll(model.getTextures());
}
private class VanillaModelWrapper implements IRetexturableModel, IAnimatedModel
private class VanillaModelWrapper implements IRetexturableModel<VanillaModelWrapper>, IModelSimpleProperties<VanillaModelWrapper>, IAnimatedModel
{
private final ResourceLocation location;
private final ModelBlock model;
@ -591,7 +591,7 @@ public class ModelLoader extends ModelBakery
}
@Override
public IModel retexture(ImmutableMap<String, String> textures)
public VanillaModelWrapper retexture(ImmutableMap<String, String> textures)
{
if (textures.isEmpty())
return this;
@ -665,8 +665,35 @@ public class ModelLoader extends ModelBakery
{
return ModelRotation.X0_Y0;
}
@Override
public VanillaModelWrapper smoothLighting(boolean value)
{
if(model.ambientOcclusion == value)
{
return this;
}
ModelBlock newModel = new ModelBlock(model.getParentLocation(), model.getElements(), model.textures, value, model.isGui3d(), model.func_181682_g());
newModel.parent = model.parent;
newModel.name = model.name;
return new VanillaModelWrapper(location, newModel, animation);
}
@Override
public VanillaModelWrapper gui3d(boolean value)
{
if(model.isGui3d() == value)
{
return this;
}
ModelBlock newModel = new ModelBlock(model.getParentLocation(), model.getElements(), model.textures, model.ambientOcclusion, value, model.func_181682_g());
newModel.parent = model.parent;
newModel.name = model.name;
return new VanillaModelWrapper(location, newModel, animation);
}
}
@Deprecated // rework in 1.9
public static class UVLock implements IModelState
{
private final IModelState parent;

View File

@ -32,7 +32,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class MultiLayerModel implements IModelCustomData
public class MultiLayerModel implements IModelCustomData<MultiLayerModel>
{
public static final MultiLayerModel instance = new MultiLayerModel(ImmutableMap.<Optional<EnumWorldBlockLayer>, ModelResourceLocation>of());
@ -94,7 +94,7 @@ public class MultiLayerModel implements IModelCustomData
}
@Override
public IModel process(ImmutableMap<String, String> customData)
public MultiLayerModel process(ImmutableMap<String, String> customData)
{
ImmutableMap.Builder<Optional<EnumWorldBlockLayer>, ModelResourceLocation> builder = ImmutableMap.builder();
for(String key : customData.keySet())

View File

@ -26,20 +26,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelCustomData;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.IRetexturableModel;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.client.model.ISmartItemModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.ModelStateComposition;
import net.minecraftforge.client.model.TRSRTransformation;
import net.minecraftforge.client.model.*;
import net.minecraftforge.client.model.animation.IClip;
import net.minecraftforge.client.model.animation.IAnimatedModel;
import net.minecraftforge.client.model.animation.IJoint;
@ -471,7 +458,7 @@ public class B3DLoader implements ICustomModelLoader
* @deprecated Use ModelWrapper, this will be removed in 1.9
*/
@Deprecated
public static class Wrapper extends PartWrapper<Mesh> implements IRetexturableModel, IModelCustomData
public static class Wrapper extends PartWrapper<Mesh> implements IRetexturableModel<Wrapper>, IModelCustomData<Wrapper>
{
private final ResourceLocation location;
private final ImmutableSet<String> meshes;
@ -593,7 +580,7 @@ public class B3DLoader implements ICustomModelLoader
}
@Override
public IModel retexture(ImmutableMap<String, String> textures)
public Wrapper retexture(ImmutableMap<String, String> textures)
{
ImmutableMap.Builder<String, ResourceLocation> builder = ImmutableMap.builder();
for(Map.Entry<String, ResourceLocation> e : this.textures.entrySet())
@ -615,7 +602,7 @@ public class B3DLoader implements ICustomModelLoader
}
@Override
public IModel process(ImmutableMap<String, String> customData)
public Wrapper process(ImmutableMap<String, String> customData)
{
return this;
}
@ -627,25 +614,41 @@ public class B3DLoader implements ICustomModelLoader
}
}
public static class ModelWrapper implements IRetexturableModel, IModelCustomData, IAnimatedModel
public static class ModelWrapper implements IRetexturableModel<ModelWrapper>, IModelCustomData<ModelWrapper>, IModelSimpleProperties<ModelWrapper>, IAnimatedModel
{
private final ResourceLocation modelLocation;
private final B3DModel model;
private final ImmutableSet<String> meshes;
private final ImmutableMap<String, ResourceLocation> textures;
private final boolean smooth;
private final boolean gui3d;
private final int defaultKey;
@Deprecated // remove in 1.9
public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet<String> meshes, int defaultKey)
{
this(modelLocation, model, meshes, defaultKey, buildTextures(model.getTextures()));
this(modelLocation, model, meshes, true, true, defaultKey);
}
public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet<String> meshes, boolean smooth, boolean gui3d, int defaultKey)
{
this(modelLocation, model, meshes, smooth, gui3d, defaultKey, buildTextures(model.getTextures()));
}
@Deprecated // remove in 1.9
public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet<String> meshes, int defaultKey, ImmutableMap<String, ResourceLocation> textures)
{
this(modelLocation, model, meshes, true, true, defaultKey, textures);
}
public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet<String> meshes, boolean smooth, boolean gui3d, int defaultKey, ImmutableMap<String, ResourceLocation> textures)
{
this.modelLocation = modelLocation;
this.model = model;
this.meshes = meshes;
this.textures = textures;
this.smooth = smooth;
this.gui3d = gui3d;
this.defaultKey = defaultKey;
}
@ -705,11 +708,11 @@ public class B3DLoader implements ICustomModelLoader
}
}
builder.put("missingno", missing);
return new BakedWrapper(model.getRoot(), state, format, meshes, builder.build());
return new BakedWrapper(model.getRoot(), state, smooth, gui3d, format, meshes, builder.build());
}
@Override
public IModel retexture(ImmutableMap<String, String> textures)
public ModelWrapper retexture(ImmutableMap<String, String> textures)
{
ImmutableMap.Builder<String, ResourceLocation> builder = ImmutableMap.builder();
for(Map.Entry<String, ResourceLocation> e : this.textures.entrySet())
@ -731,7 +734,7 @@ public class B3DLoader implements ICustomModelLoader
}
@Override
public IModel process(ImmutableMap<String, String> data)
public ModelWrapper process(ImmutableMap<String, String> data)
{
if(data.containsKey("mesh"))
{
@ -792,12 +795,34 @@ public class B3DLoader implements ICustomModelLoader
{
return new B3DState(model.getRoot().getAnimation(), defaultKey, defaultKey, 0);
}
@Override
public ModelWrapper smoothLighting(boolean value)
{
if(value == smooth)
{
return this;
}
return new ModelWrapper(modelLocation, model, meshes, value, gui3d, defaultKey, textures);
}
@Override
public ModelWrapper gui3d(boolean value)
{
if(value == gui3d)
{
return this;
}
return new ModelWrapper(modelLocation, model, meshes, smooth, value, defaultKey, textures);
}
}
private static class BakedWrapper implements IFlexibleBakedModel, ISmartBlockModel, ISmartItemModel, IPerspectiveAwareModel
{
private final Node<?> node;
private final IModelState state;
private final boolean smooth;
private final boolean gui3d;
private final VertexFormat format;
private final ImmutableSet<String> meshes;
private final ImmutableMap<String, TextureAtlasSprite> textures;
@ -805,9 +830,15 @@ public class B3DLoader implements ICustomModelLoader
private ImmutableList<BakedQuad> quads;
public BakedWrapper(final Node<?> node, final IModelState state, final VertexFormat format, final ImmutableSet<String> meshes, final ImmutableMap<String, TextureAtlasSprite> textures)
@Deprecated // remove in 1.9
public BakedWrapper(Node<?> node, IModelState state, VertexFormat format, ImmutableSet<String> meshes, ImmutableMap<String, TextureAtlasSprite> textures)
{
this(node, state, format, meshes, textures, CacheBuilder.newBuilder()
this(node, state, true, true, format, meshes, textures);
}
public BakedWrapper(final Node<?> node, final IModelState state, final boolean smooth, final boolean gui3d, final VertexFormat format, final ImmutableSet<String> meshes, final ImmutableMap<String, TextureAtlasSprite> textures)
{
this(node, state, smooth, gui3d, format, meshes, textures, CacheBuilder.newBuilder()
.maximumSize(128)
.expireAfterAccess(2, TimeUnit.MINUTES)
.<Integer, BakedWrapper>build(new CacheLoader<Integer, BakedWrapper>()
@ -821,14 +852,23 @@ public class B3DLoader implements ICustomModelLoader
B3DState ps = (B3DState)parent;
parent = ps.getParent();
}
return new BakedWrapper(node, new B3DState(newAnimation, frame, frame, 0, parent), format, meshes, textures);
return new BakedWrapper(node, new B3DState(newAnimation, frame, frame, 0, parent), smooth, gui3d, format, meshes, textures);
}
}));
}
@Deprecated // remove in 1.9
public BakedWrapper(Node<?> node, IModelState state, VertexFormat format, ImmutableSet<String> meshes, ImmutableMap<String, TextureAtlasSprite> textures, LoadingCache<Integer, BakedWrapper> cache)
{
this(node, state, true, true, format, meshes, textures, cache);
}
public BakedWrapper(Node<?> node, IModelState state, boolean smooth, boolean gui3d, VertexFormat format, ImmutableSet<String> meshes, ImmutableMap<String, TextureAtlasSprite> textures, LoadingCache<Integer, BakedWrapper> cache)
{
this.node = node;
this.state = state;
this.smooth = smooth;
this.gui3d = gui3d;
this.format = format;
this.meshes = meshes;
this.textures = textures;
@ -948,12 +988,12 @@ public class B3DLoader implements ICustomModelLoader
public boolean isAmbientOcclusion()
{
return true;
return smooth;
}
public boolean isGui3d()
{
return true;
return gui3d;
}
public boolean isBuiltInRenderer()

View File

@ -33,7 +33,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelCustomData;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IModelState;
@ -64,7 +63,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@SuppressWarnings("deprecation")
public class OBJModel implements IRetexturableModel, IModelCustomData
public class OBJModel implements IRetexturableModel<OBJModel>, IModelCustomData<OBJModel>
{
//private Gson GSON = new GsonBuilder().create();
private MaterialLibrary matLib;
@ -132,14 +131,14 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
@Override
public IModel process(ImmutableMap<String, String> customData)
public OBJModel process(ImmutableMap<String, String> customData)
{
OBJModel ret = new OBJModel(this.matLib, this.modelLocation, new CustomData(this.customData, customData));
return ret;
}
@Override
public IModel retexture(ImmutableMap<String, String> textures)
public OBJModel retexture(ImmutableMap<String, String> textures)
{
OBJModel ret = new OBJModel(this.matLib.makeLibWithReplacements(textures), this.modelLocation, this.customData);
return ret;

View File

@ -114,6 +114,7 @@ protected net.minecraft.block.state.BlockState$StateImplementation <init>(Lnet/m
protected net.minecraft.block.state.BlockState$StateImplementation field_177238_c # propertyValueTable
public net.minecraft.client.renderer.block.model.ModelBlock field_178318_c # textures
public net.minecraft.client.renderer.block.model.ModelBlock field_178315_d # parent
public net.minecraft.client.renderer.block.model.ModelBlock field_178322_i # ambientOcclusion
protected net.minecraft.client.resources.model.ModelBakery field_177602_b # LOCATIONS_BUILTIN_TEXTURES
protected net.minecraft.client.resources.model.ModelBakery field_177598_f # resourceManager
protected net.minecraft.client.resources.model.ModelBakery field_177599_g # sprites