mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Add new system for model data, replacing extended states (#5564)
This commit is contained in:
1 parent
a7204b5cd3
commit
9209c3cbfe
29 files changed
+718
-572
No files matched your search
@@ -20,14 +20,28 @@
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunkCache;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
@@ -36,13 +50,10 @@ import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class MinecraftForgeClient
|
||||
{
|
||||
|
||||
@@ -19,17 +19,34 @@
|
||||
|
||||
package net.minecraftforge.client.extensions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public interface IForgeBakedModel
|
||||
{
|
||||
{
|
||||
default IBakedModel getBakedModel()
|
||||
{
|
||||
return (IBakedModel) this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
default List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, @Nonnull Random rand, @Nonnull IModelData extraData)
|
||||
{
|
||||
return getBakedModel().getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
default boolean isAmbientOcclusion(IBlockState state) { return getBakedModel().isAmbientOcclusion(); }
|
||||
|
||||
/*
|
||||
@@ -40,4 +57,9 @@ public interface IForgeBakedModel
|
||||
{
|
||||
return net.minecraftforge.client.ForgeHooksClient.handlePerspective(getBakedModel(), cameraTransformType);
|
||||
}
|
||||
|
||||
default @Nonnull IModelData getModelData(@Nonnull IWorldReader world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull IModelData tileData)
|
||||
{
|
||||
return tileData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class ModelDataManager
|
||||
{
|
||||
private static WeakReference<World> currentWorld = new WeakReference<>(null);
|
||||
|
||||
private static final Map<ChunkPos, Set<BlockPos>> needModelDataRefresh = new HashMap<>();
|
||||
|
||||
private static final LoadingCache<ChunkPos, Map<BlockPos, IModelData>> modelDataCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.concurrencyLevel(5)
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.build(new CacheLoader<ChunkPos, Map<BlockPos, IModelData>>(){
|
||||
|
||||
@Override
|
||||
public Map<BlockPos, IModelData> load(@Nonnull ChunkPos key)
|
||||
{
|
||||
return new ConcurrentHashMap<>();
|
||||
}
|
||||
});
|
||||
|
||||
private static void cleanCaches(World world)
|
||||
{
|
||||
if (world != currentWorld.get())
|
||||
{
|
||||
currentWorld = new WeakReference<>(world);
|
||||
needModelDataRefresh.clear();
|
||||
modelDataCache.invalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static void requestModelDataRefresh(TileEntity te)
|
||||
{
|
||||
World world = te.getWorld();
|
||||
Preconditions.checkNotNull(world, "Tile entity world must not be null");
|
||||
Preconditions.checkArgument(world == Minecraft.getInstance().world, "Cannot request a model data refresh for a world other than the current client world");
|
||||
synchronized (needModelDataRefresh)
|
||||
{
|
||||
cleanCaches(world);
|
||||
needModelDataRefresh.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>()))
|
||||
.add(te.getPos());
|
||||
}
|
||||
}
|
||||
|
||||
private static void refreshModelData(World world, ChunkPos chunk)
|
||||
{
|
||||
Set<BlockPos> needUpdate;
|
||||
synchronized (needModelDataRefresh)
|
||||
{
|
||||
cleanCaches(world);
|
||||
needUpdate = needModelDataRefresh.remove(chunk);
|
||||
}
|
||||
if (needUpdate != null)
|
||||
{
|
||||
Map<BlockPos, IModelData> data = modelDataCache.getUnchecked(chunk);
|
||||
for (BlockPos pos : needUpdate)
|
||||
{
|
||||
TileEntity toUpdate = world.getTileEntity(pos);
|
||||
if (toUpdate != null)
|
||||
{
|
||||
data.put(pos, toUpdate.getModelData());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable IModelData getModelData(World world, BlockPos pos)
|
||||
{
|
||||
return getModelData(world, new ChunkPos(pos)).get(pos);
|
||||
}
|
||||
|
||||
public static Map<BlockPos, IModelData> getModelData(World world, ChunkPos pos)
|
||||
{
|
||||
refreshModelData(world, pos);
|
||||
return modelDataCache.getUnchecked(pos);
|
||||
}
|
||||
}
|
||||
@@ -43,13 +43,13 @@ import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
||||
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
|
||||
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -103,7 +103,7 @@ public final class ModelFluid implements IUnbakedModel
|
||||
bakedTextureGetter.apply(fluid.getFlowing()),
|
||||
Optional.ofNullable(fluid.getOverlay()).map(bakedTextureGetter),
|
||||
fluid.isLighterThanAir(),
|
||||
Optional.empty()
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public final class ModelFluid implements IUnbakedModel
|
||||
}
|
||||
});
|
||||
|
||||
public CachingBakedFluid(Optional<TRSRTransformation> transformation, ImmutableMap<TransformType, TRSRTransformation> transforms, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, Optional<TextureAtlasSprite> overlay, boolean gas, Optional<IExtendedBlockState> stateOption)
|
||||
public CachingBakedFluid(Optional<TRSRTransformation> transformation, ImmutableMap<TransformType, TRSRTransformation> transforms, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, Optional<TextureAtlasSprite> overlay, boolean gas, Optional<IModelData> stateOption)
|
||||
{
|
||||
super(transformation, transforms, format, color, still, flowing, overlay, gas, stateOption.isPresent(), getCorners(stateOption), getFlow(stateOption), getOverlay(stateOption));
|
||||
}
|
||||
@@ -171,12 +171,12 @@ public final class ModelFluid implements IUnbakedModel
|
||||
* while also providing good use of the available value range.
|
||||
* (For fluids with default quanta, this evenly divides the per-block intervals of 1/9 by 96)
|
||||
*/
|
||||
private static int[] getCorners(Optional<IExtendedBlockState> stateOption)
|
||||
private static int[] getCorners(Optional<IModelData> stateOption)
|
||||
{
|
||||
int[] cornerRound = {0, 0, 0, 0};
|
||||
if (stateOption.isPresent())
|
||||
{
|
||||
IExtendedBlockState state = stateOption.get();
|
||||
IModelData state = stateOption.get();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Float level = null; // TODO fluids state.getValue(BlockFluidBase.LEVEL_CORNERS[i]);
|
||||
@@ -193,7 +193,7 @@ public final class ModelFluid implements IUnbakedModel
|
||||
* The value is currently stored as the angle rounded to the nearest degree.
|
||||
* A value of -1000 is used to signify no flow.
|
||||
*/
|
||||
private static int getFlow(Optional<IExtendedBlockState> stateOption)
|
||||
private static int getFlow(Optional<IModelData> stateOption)
|
||||
{
|
||||
Float flow = -1000f;
|
||||
if (stateOption.isPresent())
|
||||
@@ -213,12 +213,12 @@ public final class ModelFluid implements IUnbakedModel
|
||||
* instead of the normal "flowing" texture (if applicable for that fluid).
|
||||
* The sides are stored here by their regular horizontal index.
|
||||
*/
|
||||
private static boolean[] getOverlay(Optional<IExtendedBlockState> stateOption)
|
||||
private static boolean[] getOverlay(Optional<IModelData> stateOption)
|
||||
{
|
||||
boolean[] overlaySides = new boolean[4];
|
||||
if (stateOption.isPresent())
|
||||
{
|
||||
IExtendedBlockState state = stateOption.get();
|
||||
IModelData state = stateOption.get();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Boolean overlay = null; // TODO fluids state.getValue(BlockFluidBase.SIDE_OVERLAYS[i]);
|
||||
@@ -229,11 +229,11 @@ public final class ModelFluid implements IUnbakedModel
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand)
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand, IModelData modelData)
|
||||
{
|
||||
if (side != null && state instanceof IExtendedBlockState)
|
||||
if (side != null)
|
||||
{
|
||||
Optional<IExtendedBlockState> exState = Optional.of((IExtendedBlockState)state);
|
||||
Optional<IModelData> exState = Optional.of(modelData);
|
||||
|
||||
int[] cornerRound = getCorners(exState);
|
||||
int flowRound = getFlow(exState);
|
||||
|
||||
@@ -77,12 +77,12 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.registry.IRegistry;
|
||||
import net.minecraftforge.client.model.animation.AnimationItemOverrideList;
|
||||
import net.minecraftforge.client.model.animation.ModelBlockAnimation;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.Models;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.common.model.animation.IClip;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fml.client.ClientModLoader;
|
||||
@@ -510,20 +510,12 @@ public final class ModelLoader extends ModelBakery
|
||||
private final ItemOverrideList overrides = new AnimationItemOverrideList(VanillaModelWrapper.this, modelState, format, bakedTextureGetter, super.getOverrides());
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand)
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand, IModelData modelData)
|
||||
{
|
||||
if(state instanceof IExtendedBlockState)
|
||||
IModelState newState = modelData.getData(Properties.AnimationProperty);
|
||||
if(newState != null)
|
||||
{
|
||||
IExtendedBlockState exState = (IExtendedBlockState)state;
|
||||
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||
{
|
||||
IModelState newState = exState.getValue(Properties.AnimationProperty);
|
||||
IExtendedBlockState newExState = (IExtendedBlockState) exState.withProperty(Properties.AnimationProperty, null);
|
||||
if(newState != null)
|
||||
{
|
||||
return VanillaModelWrapper.this.bake(modelGetter, bakedTextureGetter, new ModelStateComposition(modelState, newState), uvlock, format).getQuads(newExState, side, rand);
|
||||
}
|
||||
}
|
||||
return VanillaModelWrapper.this.bake(modelGetter, bakedTextureGetter, new ModelStateComposition(modelState, newState), uvlock, format).getQuads(state, side, rand, modelData);
|
||||
}
|
||||
return super.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
+17
-24
@@ -19,26 +19,26 @@
|
||||
|
||||
package net.minecraftforge.client.model.animation;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import net.minecraftforge.client.model.ModelDataManager;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.common.animation.Event;
|
||||
import net.minecraftforge.common.animation.IEventHandler;
|
||||
import net.minecraftforge.common.model.animation.CapabilityAnimation;
|
||||
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Generic {@link TileGameRenderer} that works with the Forge model system and animations.
|
||||
*/
|
||||
@@ -58,30 +58,23 @@ public class TileEntityRendererAnimation<T extends TileEntity> extends TileEntit
|
||||
BlockPos pos = te.getPos();
|
||||
IWorldReader world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
if(state.getBlock().getStateContainer().getProperties().contains(Properties.StaticProperty))
|
||||
IBakedModel model = blockRenderer.getBlockModelShapes().getModel(state);
|
||||
IModelData data = model.getModelData(world, pos, state, ModelDataManager.getModelData(te.getWorld(), pos));
|
||||
if (data.hasProperty(Properties.AnimationProperty))
|
||||
{
|
||||
state = state.with(Properties.StaticProperty, false);
|
||||
}
|
||||
if(state instanceof IExtendedBlockState)
|
||||
{
|
||||
IExtendedBlockState exState = (IExtendedBlockState)state;
|
||||
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||
{
|
||||
float time = Animation.getWorldTime(getWorld(), partialTick);
|
||||
cap
|
||||
.map(asm -> asm.apply(time))
|
||||
.ifPresent(pair -> {
|
||||
handleEvents(te, time, pair.getRight());
|
||||
float time = Animation.getWorldTime(getWorld(), partialTick);
|
||||
cap
|
||||
.map(asm -> asm.apply(time))
|
||||
.ifPresent(pair -> {
|
||||
handleEvents(te, time, pair.getRight());
|
||||
|
||||
// TODO: caching?
|
||||
IBakedModel model = blockRenderer.getBlockModelShapes().getModel(exState.getClean());
|
||||
IExtendedBlockState animState = (IExtendedBlockState) exState.withProperty(Properties.AnimationProperty, pair.getLeft());
|
||||
// TODO: caching?
|
||||
data.setData(Properties.AnimationProperty, pair.getLeft());
|
||||
|
||||
renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());
|
||||
renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());
|
||||
|
||||
blockRenderer.getBlockModelRenderer().renderModel(world, model, animState, pos, renderer, false, new Random(), 42);
|
||||
});
|
||||
}
|
||||
blockRenderer.getBlockModelRenderer().renderModel(world, model, state, pos, renderer, false, new Random(), 42, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,13 +27,33 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.vecmath.Vector3f;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
@@ -59,6 +79,8 @@ import net.minecraftforge.client.model.b3d.B3DModel.Mesh;
|
||||
import net.minecraftforge.client.model.b3d.B3DModel.Node;
|
||||
import net.minecraftforge.client.model.b3d.B3DModel.Texture;
|
||||
import net.minecraftforge.client.model.b3d.B3DModel.Vertex;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
|
||||
import net.minecraftforge.common.model.IModelPart;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
@@ -66,30 +88,8 @@ import net.minecraftforge.common.model.Models;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.common.model.animation.IClip;
|
||||
import net.minecraftforge.common.model.animation.IJoint;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.function.Function;
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/*
|
||||
* Loader for Blitz3D models.
|
||||
* To enable for your mod call instance.addDomain(modId).
|
||||
@@ -599,7 +599,7 @@ public enum B3DLoader implements ICustomModelLoader
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BakedWrapper implements IBakedModel
|
||||
private static final class BakedWrapper implements IDynamicBakedModel
|
||||
{
|
||||
private final Node<?> node;
|
||||
private final IModelState state;
|
||||
@@ -647,34 +647,27 @@ public enum B3DLoader implements ICustomModelLoader
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand)
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand, IModelData data)
|
||||
{
|
||||
if(side != null) return ImmutableList.of();
|
||||
IModelState modelState = this.state;
|
||||
if(state instanceof IExtendedBlockState)
|
||||
IModelState newState = data.getData(Properties.AnimationProperty);
|
||||
if(newState != null)
|
||||
{
|
||||
IExtendedBlockState exState = (IExtendedBlockState)state;
|
||||
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||
// FIXME: should animation state handle the parent state, or should it remain here?
|
||||
IModelState parent = this.state;
|
||||
if(parent instanceof B3DState)
|
||||
{
|
||||
// FIXME: should animation state handle the parent state, or should it remain here?
|
||||
IModelState parent = this.state;
|
||||
if(parent instanceof B3DState)
|
||||
{
|
||||
B3DState ps = (B3DState)parent;
|
||||
parent = ps.getParent();
|
||||
}
|
||||
IModelState newState = exState.getValue(Properties.AnimationProperty);
|
||||
if(newState != null)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
modelState = newState;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelState = new ModelStateComposition(parent, newState);
|
||||
}
|
||||
}
|
||||
B3DState ps = (B3DState)parent;
|
||||
parent = ps.getParent();
|
||||
}
|
||||
if (parent == null)
|
||||
{
|
||||
modelState = newState;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelState = new ModelStateComposition(parent, newState);
|
||||
}
|
||||
}
|
||||
if(quads == null)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.minecraftforge.client.model.data;
|
||||
|
||||
public enum EmptyModelData implements IModelData
|
||||
{
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(ModelProperty<?> prop) { return false; }
|
||||
|
||||
@Override
|
||||
public <T> T getData(ModelProperty<T> prop) { return null; }
|
||||
|
||||
@Override
|
||||
public <T> T setData(ModelProperty<T> prop, T data) { return null; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.minecraftforge.client.model.data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
/**
|
||||
* Convenience interface with default implementation of {@link IBakedModel#getQuads(net.minecraft.block.state.IBlockState, net.minecraft.util.EnumFacing, java.util.Random)}.
|
||||
*/
|
||||
public interface IDynamicBakedModel extends IBakedModel
|
||||
{
|
||||
@Override
|
||||
default @Nonnull List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, @Nonnull Random rand)
|
||||
{
|
||||
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
}
|
||||
|
||||
// Force this to be overriden otherwise this introduces a default cycle between the two overloads.
|
||||
@Override
|
||||
@Nonnull
|
||||
List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, @Nonnull Random rand, @Nonnull IModelData extraData);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.minecraftforge.client.model.data;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IModelData
|
||||
{
|
||||
/**
|
||||
* Check if this data has a property, even if the value is {@code null}. Can be
|
||||
* used by code that intends to fill in data for a render pipeline, such as the
|
||||
* forge animation system.
|
||||
* <p>
|
||||
* IMPORTANT: {@link #getData(ModelProperty)} <em>can</em> return {@code null}
|
||||
* even if this method returns {@code true}.
|
||||
*
|
||||
* @param prop The property to check for inclusion in this model data
|
||||
* @return {@code true} if this data has the given property, even if no value is present
|
||||
*/
|
||||
boolean hasProperty(ModelProperty<?> prop);
|
||||
|
||||
@Nullable
|
||||
<T> T getData(ModelProperty<T> prop);
|
||||
|
||||
@Nullable
|
||||
<T> T setData(ModelProperty<T> prop, T data);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.minecraftforge.client.model.data;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
public class ModelDataMap implements IModelData
|
||||
{
|
||||
private final Map<ModelProperty<?>, Object> backingMap;
|
||||
|
||||
private ModelDataMap(Map<ModelProperty<?>, Object> map)
|
||||
{
|
||||
this.backingMap = new IdentityHashMap<>(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(ModelProperty<?> prop)
|
||||
{
|
||||
return backingMap.containsKey(prop);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getData(ModelProperty<T> prop)
|
||||
{
|
||||
return (T) backingMap.get(prop);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T setData(ModelProperty<T> prop, T data)
|
||||
{
|
||||
Preconditions.checkArgument(prop.test(data), "Value is invalid for this property");
|
||||
return (T) backingMap.put(prop, data);
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private final Map<ModelProperty<?>, Object> defaults = new IdentityHashMap<>();
|
||||
|
||||
public Builder withProperty(ModelProperty<?> prop)
|
||||
{
|
||||
return withInitial(prop, null);
|
||||
}
|
||||
|
||||
public <T> Builder withInitial(ModelProperty<T> prop, T data)
|
||||
{
|
||||
this.defaults.put(prop, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModelDataMap build()
|
||||
{
|
||||
return new ModelDataMap(defaults);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.minecraftforge.client.model.data;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
public class ModelProperty<T> implements Predicate<T> {
|
||||
|
||||
private final Predicate<T> pred;
|
||||
|
||||
public ModelProperty() {
|
||||
this(Predicates.alwaysTrue());
|
||||
}
|
||||
|
||||
public ModelProperty(Predicate<T> pred) {
|
||||
this.pred = pred;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return pred.test(t);
|
||||
}
|
||||
}
|
||||
@@ -54,13 +54,13 @@ import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.*;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
|
||||
import net.minecraftforge.common.model.IModelPart;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.Models;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.IUnlistedProperty;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -1255,36 +1255,7 @@ public class OBJModel implements IUnbakedModel
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum OBJProperty implements IUnlistedProperty<OBJState>
|
||||
{
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "OBJProperty";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(OBJState value)
|
||||
{
|
||||
return value instanceof OBJState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<OBJState> getType()
|
||||
{
|
||||
return OBJState.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String valueToString(OBJState value)
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public class OBJBakedModel implements IBakedModel
|
||||
public class OBJBakedModel implements IDynamicBakedModel
|
||||
{
|
||||
private final OBJModel model;
|
||||
private IModelState state;
|
||||
@@ -1308,26 +1279,18 @@ public class OBJModel implements IUnbakedModel
|
||||
|
||||
// FIXME: merge with getQuads
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(IBlockState blockState, EnumFacing side, Random rand)
|
||||
public List<BakedQuad> getQuads(IBlockState blockState, EnumFacing side, Random rand, IModelData modelData)
|
||||
{
|
||||
if (side != null) return ImmutableList.of();
|
||||
if (quads == null)
|
||||
{
|
||||
quads = buildQuads(this.state);
|
||||
}
|
||||
if (blockState instanceof IExtendedBlockState)
|
||||
IModelState newState = modelData.getData(Properties.AnimationProperty);
|
||||
if (newState != null)
|
||||
{
|
||||
IExtendedBlockState exState = (IExtendedBlockState) blockState;
|
||||
if (exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||
{
|
||||
|
||||
IModelState newState = exState.getValue(Properties.AnimationProperty);
|
||||
if (newState != null)
|
||||
{
|
||||
newState = new ModelStateComposition(this.state, newState);
|
||||
return buildQuads(newState);
|
||||
}
|
||||
}
|
||||
newState = new ModelStateComposition(this.state, newState);
|
||||
return buildQuads(newState);
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -29,6 +31,9 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.model.ModelDataManager;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
|
||||
public interface IForgeTileEntity extends ICapabilitySerializable<NBTTagCompound>
|
||||
@@ -86,7 +91,10 @@ public interface IForgeTileEntity extends ICapabilitySerializable<NBTTagCompound
|
||||
* Called when this is first added to the world (by {@link World#addTileEntity(TileEntity)}).
|
||||
* Override instead of adding {@code if (firstTick)} stuff in update.
|
||||
*/
|
||||
default void onLoad(){}
|
||||
default void onLoad()
|
||||
{
|
||||
requestModelDataUpdate();
|
||||
}
|
||||
|
||||
default boolean shouldRenderInPass(int pass)
|
||||
{
|
||||
@@ -168,4 +176,19 @@ public interface IForgeTileEntity extends ICapabilitySerializable<NBTTagCompound
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
default void requestModelDataUpdate()
|
||||
{
|
||||
TileEntity te = getTileEntity();
|
||||
World world = te.getWorld();
|
||||
if (world != null && world.isRemote)
|
||||
{
|
||||
ModelDataManager.requestModelDataRefresh(te);
|
||||
}
|
||||
}
|
||||
|
||||
default @Nonnull IModelData getModelData()
|
||||
{
|
||||
return EmptyModelData.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.BlockState;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.state.AbstractStateHolder;
|
||||
import net.minecraft.state.IProperty;
|
||||
import net.minecraft.state.IStateHolder;
|
||||
import net.minecraft.state.StateContainer;
|
||||
// TODO Extended states gotta go, I doubt this works at all
|
||||
public class ExtendedStateContainer<O, S extends IExtendedState<S>> extends StateContainer<O, S>
|
||||
{
|
||||
private final ImmutableSet<IUnlistedProperty<?>> unlistedProperties;
|
||||
|
||||
public <A extends AbstractStateHolder<O, S>> ExtendedStateContainer(O blockIn, StateContainer.IFactory<O, S, A> stateFactory, net.minecraft.state.IProperty<?>[] properties, IUnlistedProperty<?>[] unlistedProperties)
|
||||
{
|
||||
super(blockIn, getProxyFactory(unlistedProperties, stateFactory), buildListedMap(properties));// TODO Unlisted properties?, buildUnlistedMap(unlistedProperties));
|
||||
ImmutableSet.Builder<IUnlistedProperty<?>> builder = ImmutableSet.builder();
|
||||
for(IUnlistedProperty<?> property : unlistedProperties)
|
||||
{
|
||||
builder.add(property);
|
||||
}
|
||||
this.unlistedProperties = builder.build();
|
||||
}
|
||||
|
||||
private static <O, S extends IExtendedState<S>, A extends AbstractStateHolder<O, S>>
|
||||
StateContainer.IFactory<O, S, AbstractStateHolder<O,S>> getProxyFactory(IUnlistedProperty<?>[] unlistedProperties, StateContainer.IFactory<O, S, A> proxy)
|
||||
{
|
||||
return (o, props) -> {
|
||||
if (unlistedProperties == null || unlistedProperties.length == 0) return proxy.create(o, props);
|
||||
return new ExtendedStateHolder<O, S>(o, props, buildUnlistedMap(unlistedProperties), null);
|
||||
};
|
||||
}
|
||||
|
||||
public Collection<IUnlistedProperty<?>> getUnlistedProperties()
|
||||
{
|
||||
return unlistedProperties;
|
||||
}
|
||||
|
||||
private static Map<String, IProperty<?>> buildListedMap(IProperty<?>[] properties)
|
||||
{
|
||||
return Arrays.stream(properties).collect(Collectors.toMap(IProperty::getName, Function.identity()));
|
||||
}
|
||||
|
||||
private static ImmutableMap<IUnlistedProperty<?>, Optional<?>> buildUnlistedMap(IUnlistedProperty<?>[] unlistedProperties)
|
||||
{
|
||||
ImmutableMap.Builder<IUnlistedProperty<?>, Optional<?>> builder = ImmutableMap.builder();
|
||||
for(IUnlistedProperty<?> p : unlistedProperties)
|
||||
{
|
||||
builder.put(p, Optional.empty());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected static class ExtendedStateHolder<O, S extends IExtendedState<S>> extends AbstractStateHolder<O, S> implements IExtendedState<S>
|
||||
{
|
||||
private final ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties;
|
||||
private S cleanState;
|
||||
|
||||
protected ExtendedStateHolder(O block, ImmutableMap<IProperty<?>, Comparable<?>> properties, ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties, S clean)
|
||||
{
|
||||
super(block, properties);
|
||||
this.unlistedProperties = unlistedProperties;
|
||||
this.cleanState = clean == null ? (S) this : clean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public <T extends Comparable<T>, V extends T> S with(@Nonnull IProperty<T> property, @Nonnull V value)
|
||||
{
|
||||
S clean = super.with(property, value);
|
||||
if (clean == this.cleanState) {
|
||||
return (S) this;
|
||||
}
|
||||
|
||||
if (this == this.cleanState)
|
||||
{ // no dynamic properties present, looking up in the normal table
|
||||
return clean;
|
||||
}
|
||||
|
||||
return (S) new ExtendedStateHolder(object, ((IStateHolder)clean).getValues(), unlistedProperties, this.cleanState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> S withProperty(IUnlistedProperty<V> property, @Nullable V value)
|
||||
{
|
||||
Optional<?> oldValue = unlistedProperties.get(property);
|
||||
if (oldValue == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " as it does not exist in " + this);
|
||||
}
|
||||
if (Objects.equals(oldValue.orElse(null), value))
|
||||
{
|
||||
return (S) this;
|
||||
}
|
||||
if (!property.isValid(value))
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " to " + value + " on object " + object + ", it is not an allowed value");
|
||||
}
|
||||
boolean clean = true;
|
||||
ImmutableMap.Builder<IUnlistedProperty<?>, Optional<?>> builder = ImmutableMap.builder();
|
||||
for (Map.Entry<IUnlistedProperty<?>, Optional<?>> entry : unlistedProperties.entrySet())
|
||||
{
|
||||
IUnlistedProperty<?> key = entry.getKey();
|
||||
Optional<?> newValue = key.equals(property) ? Optional.ofNullable(value) : entry.getValue();
|
||||
if (newValue.isPresent()) clean = false;
|
||||
builder.put(key, newValue);
|
||||
}
|
||||
if (clean)
|
||||
{ // no dynamic properties, lookup normal state
|
||||
return (S) cleanState;
|
||||
}
|
||||
return (S) new ExtendedStateHolder(object, getValues(), builder.build(), this.cleanState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IUnlistedProperty<?>> getUnlistedNames()
|
||||
{
|
||||
return unlistedProperties.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <V> V getValue(IUnlistedProperty<V> property)
|
||||
{
|
||||
Optional<?> value = unlistedProperties.get(property);
|
||||
if (value == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot get unlisted property " + property + " as it does not exist in " + this);
|
||||
}
|
||||
return property.getType().cast(value.orElse(null));
|
||||
}
|
||||
|
||||
public ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties()
|
||||
{
|
||||
return unlistedProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S getClean()
|
||||
{
|
||||
return cleanState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
public interface IExtendedBlockState extends IExtendedState<IBlockState>, IBlockState
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.state.IStateHolder;
|
||||
|
||||
import java.util.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public interface IExtendedState<C> extends IStateHolder<C>
|
||||
{
|
||||
Collection<IUnlistedProperty<?>> getUnlistedNames();
|
||||
|
||||
<V>V getValue(IUnlistedProperty<V> property);
|
||||
|
||||
<V>C withProperty(IUnlistedProperty<V> property, V value);
|
||||
|
||||
ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties();
|
||||
|
||||
C getClean();
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
public interface IUnlistedProperty<V>
|
||||
{
|
||||
String getName();
|
||||
|
||||
boolean isValid(V value);
|
||||
|
||||
Class<V> getType();
|
||||
|
||||
String valueToString(V value);
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import net.minecraft.state.BooleanProperty;
|
||||
import net.minecraft.state.IProperty;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
|
||||
public class Properties
|
||||
@@ -33,54 +33,5 @@ public class Properties
|
||||
/**
|
||||
* Property holding the IModelState used for animating the model in the TESR.
|
||||
*/
|
||||
public static final IUnlistedProperty<IModelState> AnimationProperty = new IUnlistedProperty<IModelState>()
|
||||
{
|
||||
@Override
|
||||
public String getName() { return "forge_animation"; }
|
||||
@Override
|
||||
public boolean isValid(IModelState state) { return true; }
|
||||
@Override
|
||||
public Class<IModelState> getType() { return IModelState.class; }
|
||||
@Override
|
||||
public String valueToString(IModelState state) { return state.toString(); }
|
||||
};
|
||||
|
||||
public static <V extends Comparable<V>> IUnlistedProperty<V> toUnlisted(IProperty<V> property)
|
||||
{
|
||||
return new PropertyAdapter<V>(property);
|
||||
}
|
||||
|
||||
public static class PropertyAdapter<V extends Comparable<V>> implements IUnlistedProperty<V>
|
||||
{
|
||||
private final IProperty<V> parent;
|
||||
|
||||
public PropertyAdapter(IProperty<V> parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(V value)
|
||||
{
|
||||
return parent.getAllowedValues().contains(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<V> getType()
|
||||
{
|
||||
return parent.getValueClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String valueToString(V value)
|
||||
{
|
||||
return parent.getName(value);
|
||||
}
|
||||
}
|
||||
public static final ModelProperty<IModelState> AnimationProperty = new ModelProperty<IModelState>();
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
public class PropertyFloat implements IUnlistedProperty<Float>
|
||||
{
|
||||
private final String name;
|
||||
private final Predicate<Float> validator;
|
||||
|
||||
public PropertyFloat(String name)
|
||||
{
|
||||
this(name, Predicates.alwaysTrue());
|
||||
}
|
||||
|
||||
public PropertyFloat(String name, float min, float max)
|
||||
{
|
||||
this(name, Range.closed(min, max));
|
||||
}
|
||||
|
||||
public PropertyFloat(String name, Predicate<Float> validator)
|
||||
{
|
||||
this.name = name;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Float value)
|
||||
{
|
||||
return validator.apply(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Float> getType()
|
||||
{
|
||||
return Float.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String valueToString(Float value)
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user