From 5e9380ab85c1365dbc4fde262628bc9095f3a294 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Tue, 8 Oct 2019 00:18:29 +0200 Subject: [PATCH] Fix forge blockstates and custom model loading (#6154) * Reimplement forge blockstates variant through the use of a pseudo-model that handles the model loading, retexturing, custom data, etc. on behalf of the blockstates loader. This model gets injected into the model registry with an autogenerated unique name, to not collide with other model locations. * Fix model loaders not being properly initialized by calling the reload method from the loader register function. In 1.12, registering a reload listener caused the listener to be called right away from the register method. This is not true anymore. --- .../model/BlockModelDefinition.java.patch | 6 +- .../renderer/model/ModelBakery.java.patch | 32 +++- .../client/renderer/model/Variant.java.patch | 11 +- .../client/model/BlockStateLoader.java | 173 +++++++++--------- .../client/model/ISmartVariant.java | 1 + .../client/model/ModelLoader.java | 5 +- .../client/model/ModelLoaderRegistry.java | 3 + .../resources/META-INF/accesstransformer.cfg | 1 + .../model/ForgeBlockStatesLoaderTest.java | 123 ++----------- src/test/resources/META-INF/mods.toml | 2 + .../blockstates/cobblestone_wall.json | 36 ---- .../blockstates/custom_wall.json | 33 ++++ .../blockstates/mossy_cobblestone_wall.json | 36 ---- 13 files changed, 168 insertions(+), 294 deletions(-) delete mode 100644 src/test/resources/assets/forgeblockstatesloader/blockstates/cobblestone_wall.json create mode 100644 src/test/resources/assets/forgeblockstatesloader/blockstates/custom_wall.json delete mode 100644 src/test/resources/assets/forgeblockstatesloader/blockstates/mossy_cobblestone_wall.json diff --git a/patches/minecraft/net/minecraft/client/renderer/model/BlockModelDefinition.java.patch b/patches/minecraft/net/minecraft/client/renderer/model/BlockModelDefinition.java.patch index 49d3007c6..572f963b7 100644 --- a/patches/minecraft/net/minecraft/client/renderer/model/BlockModelDefinition.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/model/BlockModelDefinition.java.patch @@ -7,11 +7,11 @@ + @Deprecated public static BlockModelDefinition func_209577_a(BlockModelDefinition.ContainerHolder p_209577_0_, Reader p_209577_1_) { - return JSONUtils.func_193839_a(p_209577_0_.field_209575_a, p_209577_1_, BlockModelDefinition.class); -+ return fromJson(p_209577_0_, p_209577_1_, null); ++ return fromJson(p_209577_0_, p_209577_1_, null, null, null); } -+ public static BlockModelDefinition fromJson(BlockModelDefinition.ContainerHolder containerHolderIn, Reader readerIn, @Nullable net.minecraft.util.ResourceLocation location) { -+ return net.minecraftforge.client.model.BlockStateLoader.load(readerIn, location, containerHolderIn.field_209575_a); ++ public static BlockModelDefinition fromJson(BlockModelDefinition.ContainerHolder containerHolderIn, Reader readerIn, @Nullable net.minecraft.util.ResourceLocation location, @Nullable ModelBakery bakery, @Nullable java.util.function.BiConsumer modelConsumer) { ++ return net.minecraftforge.client.model.BlockStateLoader.load(readerIn, location, containerHolderIn.field_209575_a, bakery, modelConsumer); + } + public BlockModelDefinition(Map p_i46572_1_, Multipart p_i46572_2_) { diff --git a/patches/minecraft/net/minecraft/client/renderer/model/ModelBakery.java.patch b/patches/minecraft/net/minecraft/client/renderer/model/ModelBakery.java.patch index cf326a00a..35ad18cc1 100644 --- a/patches/minecraft/net/minecraft/client/renderer/model/ModelBakery.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/model/ModelBakery.java.patch @@ -8,8 +8,26 @@ + private final Map, IBakedModel> field_217850_G = Maps.newHashMap(); private final Map field_217851_H = Maps.newHashMap(); private final Map field_217852_I = Maps.newHashMap(); - private final AtlasTexture.SheetData field_217853_J; -@@ -142,12 +142,19 @@ + private AtlasTexture.SheetData field_217853_J; +@@ -107,9 +107,17 @@ + }); + + public ModelBakery(IResourceManager p_i51735_1_, AtlasTexture p_i51735_2_, BlockColors p_i51735_3_, IProfiler p_i51735_4_) { ++ this(p_i51735_1_, p_i51735_2_, p_i51735_3_, true); ++ processLoading(p_i51735_4_); ++ } ++ ++ protected ModelBakery(IResourceManager p_i51735_1_, AtlasTexture p_i51735_2_, BlockColors p_i51735_3_, boolean vanillaBakery) { + this.field_177598_f = p_i51735_1_; + this.field_177609_j = p_i51735_2_; + this.field_225365_D = p_i51735_3_; ++ } ++ ++ protected void processLoading(IProfiler p_i51735_4_) { + p_i51735_4_.func_76320_a("missing_model"); + + try { +@@ -142,12 +150,19 @@ p_i51735_4_.func_219895_b("special"); this.func_217843_a(new ModelResourceLocation("minecraft:trident_in_hand#inventory")); @@ -29,16 +47,16 @@ set.forEach((p_217833_0_) -> { field_177603_c.warn("Unable to resolve texture reference: {}", (Object)p_217833_0_); }); -@@ -288,7 +295,7 @@ +@@ -288,7 +303,7 @@ { lvt_13_5_ = this.field_177598_f.func_199004_b(resourcelocation1).stream().map((p_217839_1_) -> { try (InputStream inputstream = p_217839_1_.func_199027_b()) { - Pair pair2 = Pair.of(p_217839_1_.func_199026_d(), BlockModelDefinition.func_209577_a(this.field_209610_F, new InputStreamReader(inputstream, StandardCharsets.UTF_8))); -+ Pair pair2 = Pair.of(p_217839_1_.func_199026_d(), BlockModelDefinition.fromJson(this.field_209610_F, new InputStreamReader(inputstream, StandardCharsets.UTF_8), p_209598_1_)); ++ Pair pair2 = Pair.of(p_217839_1_.func_199026_d(), BlockModelDefinition.fromJson(this.field_209610_F, new InputStreamReader(inputstream, StandardCharsets.UTF_8), p_209598_1_, this, this::func_209593_a)); return pair2; } catch (Exception exception1) { throw new ModelBakery.BlockStateDefinitionException(String.format("Exception loading blockstate definition: '%s' in resourcepack: '%s': %s", p_217839_1_.func_199029_a(), p_217839_1_.func_199026_d(), exception1.getMessage())); -@@ -404,7 +411,12 @@ +@@ -404,7 +419,12 @@ @Nullable public IBakedModel func_217845_a(ResourceLocation p_217845_1_, ISprite p_217845_2_) { @@ -52,7 +70,7 @@ if (this.field_217850_G.containsKey(triple)) { return this.field_217850_G.get(triple); } else { -@@ -412,11 +424,11 @@ +@@ -412,11 +432,11 @@ if (iunbakedmodel instanceof BlockModel) { BlockModel blockmodel = (BlockModel)iunbakedmodel; if (blockmodel.func_178310_f() == field_177606_o) { @@ -66,7 +84,7 @@ this.field_217850_G.put(triple, ibakedmodel); return ibakedmodel; } -@@ -471,6 +483,10 @@ +@@ -471,6 +491,10 @@ return this.field_225367_M; } diff --git a/patches/minecraft/net/minecraft/client/renderer/model/Variant.java.patch b/patches/minecraft/net/minecraft/client/renderer/model/Variant.java.patch index 7a77bc38b..e60c7ec3c 100644 --- a/patches/minecraft/net/minecraft/client/renderer/model/Variant.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/model/Variant.java.patch @@ -9,7 +9,7 @@ private final ResourceLocation field_188050_a; private final ModelRotation field_188051_b; private final boolean field_188052_c; -@@ -30,10 +30,16 @@ +@@ -30,6 +30,7 @@ return this.field_188050_a; } @@ -17,12 +17,3 @@ public ModelRotation func_188048_b() { return this.field_188051_b; } - -+ @Override -+ public net.minecraftforge.common.model.IModelState getState() { -+ return this.field_188051_b; -+ } -+ - public boolean func_188049_c() { - return this.field_188052_c; - } diff --git a/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java b/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java index 66cf81976..69d4fbe77 100644 --- a/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java +++ b/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java @@ -24,17 +24,11 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Optional; +import java.util.function.BiConsumer; -import net.minecraft.client.renderer.model.IUnbakedModel; -import net.minecraft.client.renderer.model.BlockModelDefinition; -import net.minecraft.client.renderer.model.ModelRotation; -import net.minecraft.client.renderer.model.Variant; -import net.minecraft.client.renderer.model.VariantList; +import net.minecraft.client.renderer.model.*; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.TRSRTransformation; @@ -61,7 +55,9 @@ public class BlockStateLoader .create(); private static final Logger LOGGER = LogManager.getLogger(); - + + private static long internalGeneratedModelId = 1; + /** * Loads a BlockStates json file. * Will attempt to parse it as a Forge Enhanced version if possible. @@ -75,7 +71,7 @@ public class BlockStateLoader * * @return Model definition including variants for all known combinations. */ - public static BlockModelDefinition load(Reader reader, ResourceLocation location, final Gson vanillaGSON) + public static BlockModelDefinition load(Reader reader, ResourceLocation location, final Gson vanillaGSON, ModelBakery bakery, BiConsumer modelConsumer) { try { @@ -98,10 +94,21 @@ public class BlockStateLoader boolean uvLock = var.getUvLock().orElse(false); int weight = var.getWeight().orElse(1); - if (var.isVanillaCompatible()) - mcVars.add(new Variant(var.getModel(), (ModelRotation)var.getState().orElse(ModelRotation.X0_Y0), uvLock, weight)); - else - mcVars.add(new ForgeVariant(location, var.getModel(), var.getState().orElse(TRSRTransformation.identity()), uvLock, var.getSmooth(), var.getGui3d(), weight, var.getTextures(), var.getOnlyPartsVariant(), var.getCustomData())); + ResourceLocation modelLocation = var.getModel(); + if (!var.isVanillaCompatible() && bakery != null) + { + modelLocation = new ResourceLocation( + "internal", + String.format("%d/%s/%s/%s", internalGeneratedModelId++, location.getNamespace(), location.getPath(), + entry.getKey().replace("=","_").replace(",","_")) + ); + + IUnbakedModel model = ForgeVariantHelper.prepareInjectedModel((ModelLoader)bakery, modelLocation, var.getModel(), var.getSmooth(), var.getGui3d(), var.getTextures(), var.getOnlyPartsVariant(), var.getCustomData()); + + modelConsumer.accept(modelLocation, model); + } + + mcVars.add(new ForgeVariant(modelLocation, var.getState().orElse(ModelRotation.X0_Y0), uvLock, weight)); } variants.put(entry.getKey(), new VariantList(mcVars)); } @@ -123,7 +130,7 @@ public class BlockStateLoader public int forge_marker = -1; } - //This is here specifically so that we do not have a hard reference to ForgeBlockStateV1.Variant in ForgeVariant + //This is here specifically so that we do not have a hard reference to ForgeBlockStateV1.Variant in this code public static class SubModel { private final IModelState state; @@ -154,76 +161,14 @@ public class BlockStateLoader public ImmutableMap getCustomData() { return customData; } } - private static class ForgeVariant extends Variant implements ISmartVariant + private static class ForgeVariant extends Variant { - private final ResourceLocation blockstateLocation; - private final ImmutableMap textures; - private final ImmutableMap parts; - private final ImmutableMap customData; - private final Optional smooth; - private final Optional gui3d; private final IModelState state; - ForgeVariant(ResourceLocation blockstateLocation, @Nullable ResourceLocation model, IModelState state, boolean uvLock, Optional smooth, Optional gui3d, int weight, ImmutableMap textures, ImmutableMap parts, ImmutableMap customData) + ForgeVariant(ResourceLocation model, IModelState state, boolean uvLock, int weight) { - super(model == null ? new ResourceLocation("builtin/missing") : model, state instanceof ModelRotation ? (ModelRotation)state : ModelRotation.X0_Y0, uvLock, weight); - this.blockstateLocation = blockstateLocation; - this.textures = textures; - this.parts = parts; - this.customData = customData; + super(model, state instanceof ModelRotation ? (ModelRotation)state : ModelRotation.X0_Y0, uvLock, weight); this.state = state; - this.smooth = smooth; - this.gui3d = gui3d; - } - - private IUnbakedModel runModelHooks(IUnbakedModel base, Optional smooth, Optional gui3d, ImmutableMap textureMap, ImmutableMap customData) - { - base = base.process(customData); - base = base.retexture(textureMap); - base = smooth.map(base::smoothLighting).orElse(base); - base = gui3d.map(base::gui3d).orElse(base); - return base; - } - - /** - * Used to replace the base model with a re-textured model containing sub-models. - */ - @Override - public IUnbakedModel process(IUnbakedModel base) - { - int size = parts.size(); - // FIXME: should missing base be handled this way? - boolean hasBase = base != ModelLoaderRegistry.getMissingModel(); - - if (hasBase) - { - base = runModelHooks(base, smooth, gui3d, textures, customData); - - if (size <= 0) - return base; - } - - ImmutableMap.Builder> models = ImmutableMap.builder(); - for (Entry entry : parts.entrySet()) - { - SubModel part = entry.getValue(); - - final ResourceLocation modelLocation = part.getModelLocation(); - final IUnbakedModel model; - if (modelLocation == null) - { - LOGGER.error("model not found for variant {} for blockstate {}", entry.getKey(), blockstateLocation); - model = ModelLoaderRegistry.getMissingModel(blockstateLocation, new Throwable()); - } - else - { - model = ModelLoaderRegistry.getModelOrLogError(modelLocation, "Unable to load block sub-model: \'" + modelLocation); - } - - models.put(entry.getKey(), Pair.of(runModelHooks(model, Optional.of(part.smooth), Optional.of(part.gui3d), part.getTextures(), part.getCustomData()), part.getState())); - } - - return new MultiModel(getModelLocation(), hasBase ? base : null, models.build()); } @Override @@ -233,13 +178,67 @@ public class BlockStateLoader } @Override - public String toString() + public String toString() { + return "Forge" + super.toString(); + } + } + + private static class ForgeVariantHelper + { + public static IUnbakedModel prepareInjectedModel(ModelLoader bakery, ResourceLocation blockstateLocation, @Nullable ResourceLocation modelLocation, Optional smooth, Optional gui3d, ImmutableMap textures, ImmutableMap parts, ImmutableMap customData) { - StringBuilder buf = new StringBuilder(); - buf.append("TexturedVariant:"); - for (Entry e: this.textures.entrySet()) - buf.append(" ").append(e.getKey()).append(" = ").append(e.getValue()); - return buf.toString(); + int size = parts.size(); + + IUnbakedModel base = null; + if (modelLocation != null) + { + try + { + base = ModelLoaderRegistry.getModel(modelLocation); + + if (base != null) + { + base = base.process(customData); + base = base.retexture(textures); + base = smooth.map(base::smoothLighting).orElse(base); + base = gui3d.map(base::gui3d).orElse(base); + + if (size <= 0) + return base; + } + } + catch (Exception e) + { + LOGGER.error("Error processing base model for forge blockstates pseudo-model: '" + blockstateLocation, e); + } + } + + ImmutableMap.Builder> models = ImmutableMap.builder(); + for (Entry entry : parts.entrySet()) + { + SubModel part = entry.getValue(); + + final ResourceLocation location = part.getModelLocation(); + final IUnbakedModel model; + if (location == null) + { + LOGGER.error("model not found for variant {} for blockstate {}", entry.getKey(), blockstateLocation); + model = ModelLoaderRegistry.getMissingModel(blockstateLocation, new Throwable()); + } + else + { + model = ModelLoaderRegistry.getModelOrLogError(location, "Unable to load block sub-model '" + entry.getKey() + "': '" + location + "'"); + } + + IUnbakedModel base1 = model; + base1 = base1.process(part.getCustomData()); + base1 = base1.retexture(part.getTextures()); + base1 = Optional.of(part.smooth).map(base1::smoothLighting).orElse(base1); + base1 = Optional.of(part.gui3d).map(base1::gui3d).orElse(base1); + models.put(entry.getKey(), Pair.of(base1, part.getState())); + } + + return new MultiModel(modelLocation, base, models.build()); } } } diff --git a/src/main/java/net/minecraftforge/client/model/ISmartVariant.java b/src/main/java/net/minecraftforge/client/model/ISmartVariant.java index f459339ac..975e96320 100644 --- a/src/main/java/net/minecraftforge/client/model/ISmartVariant.java +++ b/src/main/java/net/minecraftforge/client/model/ISmartVariant.java @@ -21,6 +21,7 @@ package net.minecraftforge.client.model; import net.minecraft.client.renderer.model.IUnbakedModel; +@Deprecated public interface ISmartVariant { default IUnbakedModel process(IUnbakedModel base) { diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoader.java b/src/main/java/net/minecraftforge/client/model/ModelLoader.java index 4f2465ae5..d25a854a9 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoader.java @@ -136,10 +136,11 @@ public final class ModelLoader extends ModelBakery public ModelLoader(IResourceManager manager, AtlasTexture map, BlockColors colours, IProfiler profiler) { - super(manager, map, colours, profiler); + super(manager, map, colours, false); VanillaLoader.INSTANCE.setLoader(this); VariantLoader.INSTANCE.setLoader(this); ModelLoaderRegistry.clearModelCache(manager); + processLoading(profiler); } private static Set specialModels = new HashSet<>(); @@ -483,8 +484,6 @@ public final class ModelLoader extends ModelBakery model = ModelLoaderRegistry.getModel(loc); } - // FIXME: is this the place? messes up dependency and texture resolution - model = v.process(model); for(ResourceLocation location : model.getDependencies()) { ModelLoaderRegistry.getModelOrMissing(location); diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java b/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java index 4f100f6a8..763e24206 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java @@ -78,6 +78,9 @@ public class ModelLoaderRegistry { loaders.add(loader); ((IReloadableResourceManager) Minecraft.getInstance().getResourceManager()).addReloadListener(loader); + // FIXME: Existing model loaders expect to receive a call as soon as they are registered, which was the old behaviour pre-1.13 + // without this, their manager field is never initialized. + loader.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } public static boolean loaded(ResourceLocation location) diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 784a1de08..073a68f9f 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -44,6 +44,7 @@ public net.minecraft.client.renderer.model.ModelBakery field_177604_a # MODEL_MI protected net.minecraft.client.renderer.model.ModelBakery field_177606_o # MODEL_GENERATED protected net.minecraft.client.renderer.model.ModelBakery field_177609_j # textureMap protected net.minecraft.client.renderer.model.ModelBakery field_177616_r # MODEL_ENTITY +private-f net.minecraft.client.renderer.model.ModelBakery field_217853_J # field_217853_J - need to un-finalize so that we can delay initialization to after calling super() in ModelLoader protected net.minecraft.client.renderer.model.ModelBakery func_177594_c(Lnet/minecraft/util/ResourceLocation;)Lnet/minecraft/client/renderer/model/BlockModel; # loadModel private-f net.minecraft.client.renderer.tileentity.PistonTileEntityRenderer field_178462_c # blockRenderer - it's static so we need to un-finalize in case this class loads to early. public net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher field_147557_n # fontRenderer - needed for rendering text in TESR items before entering world diff --git a/src/test/java/net/minecraftforge/debug/client/model/ForgeBlockStatesLoaderTest.java b/src/test/java/net/minecraftforge/debug/client/model/ForgeBlockStatesLoaderTest.java index e1d83778d..de86f76c3 100644 --- a/src/test/java/net/minecraftforge/debug/client/model/ForgeBlockStatesLoaderTest.java +++ b/src/test/java/net/minecraftforge/debug/client/model/ForgeBlockStatesLoaderTest.java @@ -17,146 +17,45 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - - package net.minecraftforge.debug.client.model; -import com.google.common.collect.Maps; import net.minecraft.block.Block; -import net.minecraft.block.BlockWall; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.model.ModelResourceLocation; -import net.minecraft.client.renderer.block.statemap.IStateMapper; -import net.minecraft.client.renderer.block.statemap.StateMap; -import net.minecraft.init.Blocks; +import net.minecraft.block.WallBlock; +import net.minecraft.block.material.Material; +import net.minecraft.item.BlockItem; import net.minecraft.item.Item; -import net.minecraft.item.ItemMultiTexture; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.ModelRegistryEvent; -import net.minecraftforge.client.model.ModelLoader; +import net.minecraft.item.ItemGroup; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; +import net.minecraftforge.registries.ObjectHolder; -import java.util.Map; -import java.util.Map.Entry; - -//@Mod(modid = ForgeBlockStatesLoaderTest.MODID, name = "ForgeBlockStatesLoader", version = "1.0", acceptableRemoteVersions = "*") -//@Mod.EventBusSubscriber +@Mod(ForgeBlockStatesLoaderTest.MODID) +@Mod.EventBusSubscriber(modid = ForgeBlockStatesLoaderTest.MODID, bus= Mod.EventBusSubscriber.Bus.MOD) public class ForgeBlockStatesLoaderTest { public static final String MODID = "forgeblockstatesloader"; - public static final String ASSETS = "forgeblockstatesloader:"; @ObjectHolder(MODID) public static class BLOCKS { - public static final BlockWall custom_wall = null; - } - - @ObjectHolder(MODID) - public static class ITEMS - { - public static final ItemMultiTexture custom_wall = null; + public static final WallBlock custom_wall = null; } @SubscribeEvent public static void registerBlocks(RegistryEvent.Register event) { event.getRegistry().registerAll( - new BlockWall(Blocks.COBBLESTONE) - .setUnlocalizedName(MODID + ".customWall") + new WallBlock(Block.Properties.create(Material.ROCK)) .setRegistryName(MODID, "custom_wall") ); } - @net.minecraftforge.eventbus.api.SubscribeEvent + @SubscribeEvent public static void registerItems(RegistryEvent.Register event) { event.getRegistry().registerAll( - new ItemMultiTexture( - BLOCKS.custom_wall, BLOCKS.custom_wall, - stack -> BlockWall.EnumType.byMetadata(stack.getMetadata()).getUnlocalizedName() - ).setRegistryName(BLOCKS.custom_wall.getRegistryName()) + new BlockItem(BLOCKS.custom_wall, new Item.Properties().group(ItemGroup.DECORATIONS)).setRegistryName(BLOCKS.custom_wall.getRegistryName()) ); } - - //public static final Block blockCustom = new CustomMappedBlock(); - - //@Mod.EventBusSubscriber(value = Side.CLIENT, modid = MODID) - public static class ClientEventHandler - { - @net.minecraftforge.eventbus.api.SubscribeEvent - public static void registerModels(ModelRegistryEvent event) - { - //ModelLoader.setCustomStateMapper(blockCustom, new StateMap.Builder().withName(CustomMappedBlock.VARIANT).build()); - - ModelLoader.setCustomStateMapper(BLOCKS.custom_wall, new IStateMapper() - { - StateMap stateMap = new StateMap.Builder().withName(BlockWall.VARIANT).withSuffix("_wall").build(); - - @Override - public Map putStateModelLocations(Block block) - { - Map map = stateMap.putStateModelLocations(block); - Map newMap = Maps.newHashMap(); - - for (Entry e : map.entrySet()) - { - ModelResourceLocation loc = e.getValue(); - newMap.put(e.getKey(), new ModelResourceLocation(ASSETS + loc.getResourcePath(), loc.getVariant())); - } - - return newMap; - } - }); - ModelLoader.setCustomModelResourceLocation(ITEMS.custom_wall, 0, new ModelResourceLocation(ASSETS + "cobblestone_wall", "inventory")); - ModelLoader.setCustomModelResourceLocation(ITEMS.custom_wall, 1, new ModelResourceLocation(ASSETS + "mossy_cobblestone_wall", "inventory")); - } - } - - // this block is never actually used, it's only needed for the error message on load to see the variant it maps to - // disabling until we can make it a proper test - */ -/*public static class CustomMappedBlock extends Block - { - public static final PropertyEnum VARIANT = PropertyEnum.create("type", CustomVariant.class); - - protected CustomMappedBlock() { - super(Material.rock); - - this.setUnlocalizedName(MODID + ".customMappedBlock"); - } - - @Override - protected BlockStateContainer createBlockState() { - return new BlockStateContainer(this, VARIANT); - } - - @Override - public int getMetaFromState(IBlockState state) - { - return ((CustomVariant)state.getValue(VARIANT)).ordinal(); - } - - @Override - public IBlockState getStateFromMeta(int meta) - { - if(meta > CustomVariant.values().length || meta < 0) - meta = 0; - - return this.getDefaultState().withProperty(VARIANT, CustomVariant.values()[meta]); - } - - public static enum CustomVariant implements IStringSerializable { - type_a, - type_b; - - public String getName() { return this.toString(); }; - } - }*//* - } -*/ diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 2dceda89f..32c28d058 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -53,3 +53,5 @@ loaderVersion="[28,)" modId="piston_event_test" [[mods]] modId="flower_pot_test" +[[mods]] + modId="forgeblockstatesloader" \ No newline at end of file diff --git a/src/test/resources/assets/forgeblockstatesloader/blockstates/cobblestone_wall.json b/src/test/resources/assets/forgeblockstatesloader/blockstates/cobblestone_wall.json deleted file mode 100644 index b2cf17f13..000000000 --- a/src/test/resources/assets/forgeblockstatesloader/blockstates/cobblestone_wall.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "forge_marker": 1, - "defaults": { - "textures": {"wall": "blocks/cobblestone"}, - "model": "cobblestone_wall_post", - "uvlock": true, // This and all other properties of "defaults" will be inherited by simple submodels. They will NOT be inherited by named submodels. - "transform": "forge:default-block" - }, - "variants": { - "north": { - "true": {"submodel": "forgeblockstatesloader:wall_connect"}, // Simple submodel declaration. You can also specify multiple submodels for a variant. - "false": {} - }, - "south": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 180}, - "false": {} - }, - "east": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 90}, // Submodel will be rotated. - "false": {} - }, - "west": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 270}, - "false": {} - }, - "up": {"true": {}, "false": {}}, // Must have this in here or the blockstates loader will not know of all the properties and values, and it will create the wrong vanilla state strings. - "east=false,north=true,south=true,up=false,west=false": {"model": null}, // Fully specified variant, will inherit from variants above, but remove the model set in "defaults", removing the wall post. - "east=true,north=false,south=false,up=false,west=true": {"model": null}, - "inventory": [{ // inventory variant can be specified here too, and it will inherit properties from "defaults" - "submodel": { - "north": { "model": "forgeblockstatesloader:wall_connect" }, - "south": { "model": "forgeblockstatesloader:wall_connect", "y": 180 } - } - }] - } -} diff --git a/src/test/resources/assets/forgeblockstatesloader/blockstates/custom_wall.json b/src/test/resources/assets/forgeblockstatesloader/blockstates/custom_wall.json new file mode 100644 index 000000000..b559303d4 --- /dev/null +++ b/src/test/resources/assets/forgeblockstatesloader/blockstates/custom_wall.json @@ -0,0 +1,33 @@ +{ + "forge_marker": 1, + "defaults": { + "textures": {"wall": "block/obsidian"}, + "model": "block/cobblestone_wall_post", + "uvlock": true, // This and all other properties of "defaults" will be inherited by simple submodels. They will NOT be inherited by named submodels. + "transform": "forge:default-block" + }, + "variants": { + "north": { + "true": {"submodel": "forgeblockstatesloader:block/wall_connect"}, // Simple submodel declaration. You can also specify multiple submodels for a variant. + "false": {} + }, + "south": { + "true": {"submodel": "forgeblockstatesloader:block/wall_connect", "y": 180}, + "false": {} + }, + "east": { + "true": {"submodel": "forgeblockstatesloader:block/wall_connect", "y": 90}, // Submodel will be rotated. + "false": {} + }, + "west": { + "true": {"submodel": "forgeblockstatesloader:block/wall_connect", "y": 270}, + "false": {} + }, + "up": {"true": {}, "false": {}}, // Must have this in here or the blockstates loader will not know of all the properties and values, and it will create the wrong vanilla state strings. + "waterlogged": {"true": {}, "false": {}}, + "east=false,north=true,south=true,up=false,waterlogged=false,west=false": {"model": null}, // Fully specified variant, will inherit from variants above, but remove the model set in "defaults", removing the wall post. + "east=true,north=false,south=false,up=false,waterlogged=false,west=true": {"model": null}, + "east=false,north=true,south=true,up=false,waterlogged=true,west=false": {"model": null}, + "east=true,north=false,south=false,up=false,waterlogged=true,west=true": {"model": null} + } +} diff --git a/src/test/resources/assets/forgeblockstatesloader/blockstates/mossy_cobblestone_wall.json b/src/test/resources/assets/forgeblockstatesloader/blockstates/mossy_cobblestone_wall.json deleted file mode 100644 index b66a20720..000000000 --- a/src/test/resources/assets/forgeblockstatesloader/blockstates/mossy_cobblestone_wall.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "forge_marker": 1, - "defaults": { - "textures": {"wall": "blocks/cobblestone_mossy"}, - "model": "cobblestone_wall_post", - "uvlock": true, - "transform": "forge:default-block" - }, - "variants": { - "north": { - "true": {"submodel": "forgeblockstatesloader:wall_connect"}, - "false": {} - }, - "south": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 180}, - "false": {} - }, - "east": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 90}, - "false": {} - }, - "west": { - "true": {"submodel": "forgeblockstatesloader:wall_connect", "y": 270}, - "false": {} - }, - "up": {"true": {}, "false": {}}, - "east=false,north=true,south=true,up=false,west=false": {"model": null}, - "east=true,north=false,south=false,up=false,west=true": {"model": null}, - "inventory": [{ // inventory variant can be specified here too, and it will inherit properties from "defaults" - "submodel": { - "north": { "model": "forgeblockstatesloader:wall_connect" }, - "south": { "model": "forgeblockstatesloader:wall_connect", "y": 180 } - } - }] - } -}