From 46abfcba3bb6272bec0646685e3e33d95ed1bea5 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 24 Dec 2018 11:29:06 -0500 Subject: [PATCH] Multipart model loading --- build.gradle | 3 +- .../client/MissingMultipartBakedModel.java | 24 ----- .../client/MultipartBakedModel.java | 12 ++- .../client/MultipartContainerBakedModel.java | 21 +++-- .../client/MultipartModelProvider.java | 87 +++++++++++++++++++ .../client/MultipartModels.java | 31 ------- .../client/SimpleMultipartClient.java | 31 +++++-- .../mixin/client/MixinModelLoader.java | 14 ++- .../simplemultipart/multipart/Multipart.java | 3 + .../multipart/MultipartSlot.java | 8 +- src/main/resources/fabric.mod.json | 2 +- .../simplemultipart/test/GreenMultipart.java | 34 -------- .../simplemultipart/test/MultipartTest.java | 35 -------- .../test/MultipartTestMod.java | 25 ++++++ .../simplemultipart/test/RedMultipart.java | 25 ------ .../simplemultipart/test/TestMultipart.java | 64 ++++++++++++++ .../test/TestMultipartModel.java | 66 -------------- .../models/multipart/bottom.json | 18 ++++ .../models/multipart/vertical.json | 18 ++++ .../multipartstates/test_part.json | 10 +++ 20 files changed, 296 insertions(+), 235 deletions(-) delete mode 100644 src/main/java/net/shadowfacts/simplemultipart/client/MissingMultipartBakedModel.java create mode 100644 src/main/java/net/shadowfacts/simplemultipart/client/MultipartModelProvider.java delete mode 100644 src/main/java/net/shadowfacts/simplemultipart/client/MultipartModels.java delete mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/GreenMultipart.java delete mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/MultipartTest.java create mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/MultipartTestMod.java delete mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/RedMultipart.java create mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/TestMultipart.java delete mode 100644 src/test/java/net/shadowfacts/simplemultipart/test/TestMultipartModel.java create mode 100644 src/test/resources/assets/multipart_test/models/multipart/bottom.json create mode 100644 src/test/resources/assets/multipart_test/models/multipart/vertical.json create mode 100644 src/test/resources/assets/multipart_test/multipartstates/test_part.json diff --git a/build.gradle b/build.gradle index 129c68e..ae3124f 100644 --- a/build.gradle +++ b/build.gradle @@ -18,5 +18,6 @@ dependencies { modCompile "net.fabricmc:fabric-loader:0.3.0.73" // Fabric API. This is technically optional, but you probably want it anyway. - modCompile "net.fabricmc:fabric:0.1.2.62" +// modCompile "net.fabricmc:fabric:0.1.2.62" + modCompile files("fabric-0.1.2.local.jar") // temporary, until fabric-api #39 is merged } diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/MissingMultipartBakedModel.java b/src/main/java/net/shadowfacts/simplemultipart/client/MissingMultipartBakedModel.java deleted file mode 100644 index a024dda..0000000 --- a/src/main/java/net/shadowfacts/simplemultipart/client/MissingMultipartBakedModel.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.shadowfacts.simplemultipart.client; - -import com.google.common.collect.ImmutableList; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.util.math.Direction; -import net.shadowfacts.simplemultipart.multipart.MultipartSlot; -import net.shadowfacts.simplemultipart.multipart.MultipartState; - -import java.util.List; -import java.util.Random; - -/** - * @author shadowfacts - */ -public class MissingMultipartBakedModel implements MultipartBakedModel { - - // TODO: actual missing model - - @Override - public List getQuads(MultipartState state, MultipartSlot slot, Direction side, Random random) { - return ImmutableList.of(); - } - -} diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartBakedModel.java b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartBakedModel.java index f8d1b48..60d0689 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartBakedModel.java +++ b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartBakedModel.java @@ -1,8 +1,9 @@ package net.shadowfacts.simplemultipart.client; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.util.math.Direction; -import net.shadowfacts.simplemultipart.multipart.MultipartSlot; import net.shadowfacts.simplemultipart.multipart.MultipartState; import java.util.List; @@ -11,8 +12,13 @@ import java.util.Random; /** * @author shadowfacts */ -public interface MultipartBakedModel { +public interface MultipartBakedModel extends BakedModel { - List getQuads(MultipartState state, MultipartSlot slot, Direction side, Random random); + List getMultipartQuads(MultipartState state, Direction side, Random random); + + @Override + default List getQuads(BlockState state, Direction side, Random random) { + return getMultipartQuads(null, side, random); + } } diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartContainerBakedModel.java b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartContainerBakedModel.java index 1613d4f..2401efd 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartContainerBakedModel.java +++ b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartContainerBakedModel.java @@ -2,12 +2,16 @@ package net.shadowfacts.simplemultipart.client; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.block.BlockModels; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList; import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; +import net.shadowfacts.simplemultipart.SimpleMultipart; import net.shadowfacts.simplemultipart.container.MultipartContainerBlockState; import net.shadowfacts.simplemultipart.multipart.MultipartSlot; import net.shadowfacts.simplemultipart.multipart.MultipartState; @@ -28,13 +32,18 @@ public class MultipartContainerBakedModel implements BakedModel { return null; } MultipartContainerBlockState containerState = (MultipartContainerBlockState)state; - Map parts = containerState.getParts(); - MultipartModels models = SimpleMultipartClient.getMultipartModels(); // TODO: would manually building the list be more efficient? - return parts.entrySet().stream() - .flatMap(entry -> { - MultipartBakedModel partModel = models.getModel(entry.getValue()); - return partModel.getQuads(entry.getValue(), entry.getKey(), side, random).stream(); + return containerState.getParts().values().stream() + .flatMap(partState -> { + Identifier partId = SimpleMultipart.MULTIPART.getId(partState.getMultipart()); + String variant = BlockModels.propertyMapToString(partState.getEntries()); + ModelIdentifier modelId = new ModelIdentifier(partId, variant); + BakedModel model = MinecraftClient.getInstance().getBakedModelManager().getModel(modelId); + if (model instanceof MultipartBakedModel) { + return ((MultipartBakedModel)model).getMultipartQuads(partState, side, random).stream(); + } else { + return model.getQuads(null, side, random).stream(); + } }) .collect(Collectors.toList()); } diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModelProvider.java b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModelProvider.java new file mode 100644 index 0000000..7fe4199 --- /dev/null +++ b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModelProvider.java @@ -0,0 +1,87 @@ +package net.shadowfacts.simplemultipart.client; + +import net.fabricmc.fabric.api.client.model.ModelProvider; +import net.fabricmc.fabric.api.client.model.ModelProviderException; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.client.render.model.json.ModelVariantMap; +import net.minecraft.client.render.model.json.WeightedUnbakedModel; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.resource.Resource; +import net.minecraft.util.Identifier; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; + +/** + * @author shadowfacts + */ +public class MultipartModelProvider implements ModelProvider { + + private final Map unbakedModels = new HashMap<>(); + + @Override + public UnbakedModel load(Identifier id, Context context) throws ModelProviderException { + if (!(id instanceof ModelIdentifier)) { + return null; + } + ModelIdentifier modelId = (ModelIdentifier)id; + + + if (!SimpleMultipartClient.multipartModels.contains(modelId)) { + return null; + } + + try { + return getOrLoadPartModel(modelId); + } catch (IOException e) { + throw new ModelProviderException("Exception encountered while loading model " + id, e); + } + } + + private UnbakedModel getOrLoadPartModel(ModelIdentifier id) throws ModelProviderException, IOException { + UnbakedModel existing = unbakedModels.get(id); + if (existing != null) { + return existing; + } + + return loadModel(id); + } + + private UnbakedModel loadModel(ModelIdentifier id) throws ModelProviderException, IOException { + Identifier partStateId = new Identifier(id.getNamespace(), "multipartstates/" + id.getPath() + ".json"); + ModelVariantMap variantMap = loadVariantMap(partStateId); + Map variants = variantMap.method_3423(); + variants.forEach((variant, model) -> { + unbakedModels.put(new ModelIdentifier(new Identifier(id.getNamespace(), id.getPath()), variant), model); + }); + + UnbakedModel model = unbakedModels.get(id); + if (model == null) { + throw new ModelProviderException("Loaded multipart state " + partStateId + " for model " + id + " but still missing model"); + } + return model; + } + + private ModelVariantMap loadVariantMap(Identifier id) throws IOException { + Resource resource = null; + Reader reader = null; + try { + resource = MinecraftClient.getInstance().getResourceManager().getResource(id); + reader = new InputStreamReader(resource.getInputStream()); + + ModelVariantMap.class_791 context = new ModelVariantMap.class_791(); + // context.stateFactory = + // TODO: ^ blockstate translation + return ModelVariantMap.method_3424(context, reader); + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(resource); + } + } + +} diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModels.java b/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModels.java deleted file mode 100644 index ac17374..0000000 --- a/src/main/java/net/shadowfacts/simplemultipart/client/MultipartModels.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.shadowfacts.simplemultipart.client; - -import net.shadowfacts.simplemultipart.multipart.MultipartState; - -import java.util.IdentityHashMap; -import java.util.Map; - -/** - * @author shadowfacts - */ -public class MultipartModels { - - private final Map models = new IdentityHashMap<>(); - private final MultipartBakedModel missingModel = new MissingMultipartBakedModel(); - - public MultipartBakedModel getMissingModel() { - return missingModel; - } - - public MultipartBakedModel getModel(MultipartState state) { - MultipartBakedModel model = models.get(state); - if (model == null) { - return getMissingModel(); - } - return model; - } - - public void register(MultipartState state, MultipartBakedModel model) { - models.put(state, model); - } -} diff --git a/src/main/java/net/shadowfacts/simplemultipart/client/SimpleMultipartClient.java b/src/main/java/net/shadowfacts/simplemultipart/client/SimpleMultipartClient.java index d6c2fc3..23cf965 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/client/SimpleMultipartClient.java +++ b/src/main/java/net/shadowfacts/simplemultipart/client/SimpleMultipartClient.java @@ -1,25 +1,42 @@ package net.shadowfacts.simplemultipart.client; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.impl.client.model.ModelLoadingRegistryImpl; +import net.minecraft.client.render.block.BlockModels; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.shadowfacts.simplemultipart.SimpleMultipart; +import net.shadowfacts.simplemultipart.multipart.Multipart; import net.shadowfacts.simplemultipart.multipart.MultipartState; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Consumer; + /** * @author shadowfacts */ public class SimpleMultipartClient implements ClientModInitializer { - private static MultipartModels multipartModels = new MultipartModels(); + public static final Set multipartModels = new HashSet<>(); @Override public void onInitializeClient() { + ModelLoadingRegistryImpl.INSTANCE.registerAppender(SimpleMultipartClient::registerMultipartModels); + ModelLoadingRegistryImpl.INSTANCE.registerProvider(resourceManager -> new MultipartModelProvider()); } - public static MultipartModels getMultipartModels() { - return multipartModels; - } - - public static void registerModel(MultipartState state, MultipartBakedModel model) { - getMultipartModels().register(state, model); + private static void registerMultipartModels(ResourceManager resourceManager, Consumer adder) { + for (Multipart part : SimpleMultipart.MULTIPART) { + Identifier partId = SimpleMultipart.MULTIPART.getId(part); + for (MultipartState state : part.getStateFactory().getStates()) { + String variant = BlockModels.propertyMapToString(state.getEntries()); + ModelIdentifier id = new ModelIdentifier(partId, variant); + multipartModels.add(id); + adder.accept(id); + } + } } } diff --git a/src/main/java/net/shadowfacts/simplemultipart/mixin/client/MixinModelLoader.java b/src/main/java/net/shadowfacts/simplemultipart/mixin/client/MixinModelLoader.java index d9c84d7..ecedb7f 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/mixin/client/MixinModelLoader.java +++ b/src/main/java/net/shadowfacts/simplemultipart/mixin/client/MixinModelLoader.java @@ -7,6 +7,7 @@ import net.minecraft.client.util.ModelIdentifier; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; import net.shadowfacts.simplemultipart.client.MultipartContainerBakedModel; +import net.shadowfacts.simplemultipart.client.SimpleMultipartClient; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -19,14 +20,25 @@ import java.util.Map; * @author shadowfacts */ @Mixin(ModelLoader.class) -public class MixinModelLoader { +public abstract class MixinModelLoader { @Shadow private Map bakedModels; + @Shadow + public abstract void addModel(ModelIdentifier id); + @Inject(method = "", at = @At("RETURN")) public void addMultipartModel(ResourceManager manager, SpriteAtlasTexture texture, CallbackInfo info) { bakedModels.put(new ModelIdentifier("simplemultipart:container#"), new MultipartContainerBakedModel()); } +// // temporary workaround until fabric-api #39 is merged +// @Inject(method = "addModel", at = @At("HEAD")) +// public void injectMultipartModels(ModelIdentifier id, CallbackInfo info) { +// if (id == ModelLoader.MISSING) { +// SimpleMultipartClient.getMultipartModelIds().forEach(this::addModel); +// } +// } + } diff --git a/src/main/java/net/shadowfacts/simplemultipart/multipart/Multipart.java b/src/main/java/net/shadowfacts/simplemultipart/multipart/Multipart.java index 4afbf0b..9f04492 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/multipart/Multipart.java +++ b/src/main/java/net/shadowfacts/simplemultipart/multipart/Multipart.java @@ -5,6 +5,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.StateFactory; +import net.minecraft.state.property.EnumProperty; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; @@ -22,6 +23,8 @@ import java.util.List; */ public abstract class Multipart { + public static final EnumProperty SLOT = EnumProperty.create("slot", MultipartSlot.class); + private StateFactory stateFactory; private MultipartState defaultState; diff --git a/src/main/java/net/shadowfacts/simplemultipart/multipart/MultipartSlot.java b/src/main/java/net/shadowfacts/simplemultipart/multipart/MultipartSlot.java index 8130e9b..1327487 100644 --- a/src/main/java/net/shadowfacts/simplemultipart/multipart/MultipartSlot.java +++ b/src/main/java/net/shadowfacts/simplemultipart/multipart/MultipartSlot.java @@ -1,11 +1,12 @@ package net.shadowfacts.simplemultipart.multipart; +import net.minecraft.util.StringRepresentable; import net.minecraft.util.math.Direction; /** * @author shadowfacts */ -public enum MultipartSlot { +public enum MultipartSlot implements StringRepresentable { TOP, BOTTOM, NORTH, @@ -31,4 +32,9 @@ public enum MultipartSlot { } throw new RuntimeException("Unreachable: got direction outside of DUNSWE"); } + + @Override + public String asString() { + return name().toLowerCase(); + } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 565fda8..022702c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -7,7 +7,7 @@ "initializers": [ "net.shadowfacts.simplemultipart.SimpleMultipart", "net.shadowfacts.simplemultipart.client.SimpleMultipartClient", - "net.shadowfacts.simplemultipart.test.MultipartTest" + "net.shadowfacts.simplemultipart.test.MultipartTestMod" ], "requires": { "fabric": "*" diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/GreenMultipart.java b/src/test/java/net/shadowfacts/simplemultipart/test/GreenMultipart.java deleted file mode 100644 index 22d7b78..0000000 --- a/src/test/java/net/shadowfacts/simplemultipart/test/GreenMultipart.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.shadowfacts.simplemultipart.test; - -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; -import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity; -import net.shadowfacts.simplemultipart.multipart.Multipart; -import net.shadowfacts.simplemultipart.multipart.MultipartSlot; -import net.shadowfacts.simplemultipart.multipart.MultipartState; - -/** - * @author shadowfacts - */ -public class GreenMultipart extends Multipart { - - @Override - public boolean isValidSlot(MultipartSlot slot) { - return slot == MultipartSlot.NORTH; - } - - @Override - @Deprecated - public VoxelShape getBoundingShape(MultipartState state, MultipartSlot slot, MultipartContainerBlockEntity container) { - return VoxelShapes.cube(0, 0, 0, 1, 1, 1/16f); - } - - @Override - @Deprecated - public boolean activate(MultipartState state, MultipartSlot slot, MultipartContainerBlockEntity container, PlayerEntity player, Hand hand) { - System.out.println("part activated"); - return true; - } -} diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTest.java b/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTest.java deleted file mode 100644 index 1df7959..0000000 --- a/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.shadowfacts.simplemultipart.test; - -import net.fabricmc.api.ModInitializer; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.shadowfacts.simplemultipart.SimpleMultipart; -import net.shadowfacts.simplemultipart.client.SimpleMultipartClient; -import net.shadowfacts.simplemultipart.item.ItemMultipart; - -/** - * @author shadowfacts - */ -public class MultipartTest implements ModInitializer { - - public static final String MODID = "multipart_test"; - - public static final RedMultipart red = new RedMultipart(); - public static final GreenMultipart green = new GreenMultipart(); - - public static final ItemMultipart redItem = new ItemMultipart(red); - public static final ItemMultipart greenItem = new ItemMultipart(green); - - @Override - public void onInitialize() { - Registry.register(SimpleMultipart.MULTIPART, new Identifier(MODID, "red"), red); - Registry.register(SimpleMultipart.MULTIPART, new Identifier(MODID, "green"), green); - - Registry.register(Registry.ITEM, new Identifier(MODID, "red"), redItem); - Registry.register(Registry.ITEM, new Identifier(MODID, "green"), greenItem); - - SimpleMultipartClient.registerModel(red.getDefaultState(), new TestMultipartModel(true)); - SimpleMultipartClient.registerModel(green.getDefaultState(), new TestMultipartModel(false)); - } - -} diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTestMod.java b/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTestMod.java new file mode 100644 index 0000000..c5ec6d6 --- /dev/null +++ b/src/test/java/net/shadowfacts/simplemultipart/test/MultipartTestMod.java @@ -0,0 +1,25 @@ +package net.shadowfacts.simplemultipart.test; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.shadowfacts.simplemultipart.SimpleMultipart; +import net.shadowfacts.simplemultipart.item.ItemMultipart; + +/** + * @author shadowfacts + */ +public class MultipartTestMod implements ModInitializer { + + public static final String MODID = "multipart_test"; + + public static final TestMultipart testPart = new TestMultipart(); + public static final ItemMultipart testItem = new ItemMultipart(testPart); + + @Override + public void onInitialize() { + Registry.register(SimpleMultipart.MULTIPART, new Identifier(MODID, "test_part"), testPart); + Registry.register(Registry.ITEM, new Identifier(MODID, "test_part"), testItem); + } + +} diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/RedMultipart.java b/src/test/java/net/shadowfacts/simplemultipart/test/RedMultipart.java deleted file mode 100644 index a351eb8..0000000 --- a/src/test/java/net/shadowfacts/simplemultipart/test/RedMultipart.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.shadowfacts.simplemultipart.test; - -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; -import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity; -import net.shadowfacts.simplemultipart.multipart.Multipart; -import net.shadowfacts.simplemultipart.multipart.MultipartSlot; -import net.shadowfacts.simplemultipart.multipart.MultipartState; - -/** - * @author shadowfacts - */ -public class RedMultipart extends Multipart { - - @Override - public boolean isValidSlot(MultipartSlot slot) { - return slot == MultipartSlot.BOTTOM; - } - - @Override - @Deprecated - public VoxelShape getBoundingShape(MultipartState state, MultipartSlot slot, MultipartContainerBlockEntity container) { - return VoxelShapes.cube(0, 0, 0, 1, 1/16f, 1); - } -} diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipart.java b/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipart.java new file mode 100644 index 0000000..fb888c5 --- /dev/null +++ b/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipart.java @@ -0,0 +1,64 @@ +package net.shadowfacts.simplemultipart.test; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.state.StateFactory; +import net.minecraft.util.Hand; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity; +import net.shadowfacts.simplemultipart.multipart.Multipart; +import net.shadowfacts.simplemultipart.multipart.MultipartSlot; +import net.shadowfacts.simplemultipart.multipart.MultipartState; + +/** + * @author shadowfacts + */ +public class TestMultipart extends Multipart { + + public TestMultipart() { + setDefaultState(getDefaultState().with(SLOT, MultipartSlot.BOTTOM)); + } + + @Override + protected void appendProperties(StateFactory.Builder builder) { + super.appendProperties(builder); + builder.with(SLOT); + } + + @Override + public boolean isValidSlot(MultipartSlot slot) { + return slot != MultipartSlot.CENTER; + } + + @Override + public MultipartState getPlacementState(MultipartSlot slot, MultipartContainerBlockEntity container) { + return getDefaultState().with(SLOT, slot); + } + + @Override + @Deprecated + public VoxelShape getBoundingShape(MultipartState state, MultipartSlot slot, MultipartContainerBlockEntity container) { + switch (slot) { + case TOP: + return VoxelShapes.cube(0, 15/16f, 0, 1, 1, 1); + case BOTTOM: + return VoxelShapes.cube(0, 0, 0, 1, 1/16f, 1); + case NORTH: + return VoxelShapes.cube(0, 0, 0, 1, 1, 1/16f); + case SOUTH: + return VoxelShapes.cube(0, 0, 15/16f, 1, 1, 1); + case WEST: + return VoxelShapes.cube(0, 0, 0, 1/16f, 1, 1); + case EAST: + return VoxelShapes.cube(15/16f, 0, 0, 1, 1, 1); + } + return VoxelShapes.empty(); + } + + @Override + @Deprecated + public boolean activate(MultipartState state, MultipartSlot slot, MultipartContainerBlockEntity container, PlayerEntity player, Hand hand) { + System.out.println("part activated: " + slot); + return true; + } +} diff --git a/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipartModel.java b/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipartModel.java deleted file mode 100644 index f88ed21..0000000 --- a/src/test/java/net/shadowfacts/simplemultipart/test/TestMultipartModel.java +++ /dev/null @@ -1,66 +0,0 @@ -package net.shadowfacts.simplemultipart.test; - -import com.google.common.collect.ImmutableList; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.render.model.BakedQuadFactory; -import net.minecraft.client.render.model.ModelRotationContainer; -import net.minecraft.client.render.model.json.ModelElementFace; -import net.minecraft.client.render.model.json.ModelElementTexture; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.client.util.math.Vector3f; -import net.minecraft.util.math.Direction; -import net.shadowfacts.simplemultipart.client.MultipartBakedModel; -import net.shadowfacts.simplemultipart.multipart.MultipartSlot; -import net.shadowfacts.simplemultipart.multipart.MultipartState; - -import java.util.List; -import java.util.Random; - -/** - * @author shadowfacts - */ -public class TestMultipartModel implements MultipartBakedModel { - - private static final BakedQuadFactory QUAD_FACTORY = new BakedQuadFactory(); - - private boolean flag; - - public TestMultipartModel(boolean flag) { - this.flag = flag; - } - - @Override - public List getQuads(MultipartState state, MultipartSlot slot, Direction side, Random random) { - if (side == null) { - return ImmutableList.of(createQuad()); - } - return ImmutableList.of(); - } - - private BakedQuad createQuad() { - ModelElementTexture elementTexture = new ModelElementTexture(new float[]{0, 0, 16, 16}, 0); - ModelElementFace face; - Vector3f from; - Vector3f to; - Direction side; - String texture; - if (flag) { - from = new Vector3f(0, 0, 0); - to = new Vector3f(16, 1, 16); - side = Direction.UP; - texture = "block/iron_block"; - } else { - from = new Vector3f(0, 0, 0); - to = new Vector3f(16, 16, 1); - side = Direction.SOUTH; - texture = "block/gold_block"; - } - face = new ModelElementFace(null, -1, "#texture", elementTexture); - Sprite sprite = MinecraftClient.getInstance().getSpriteAtlas().getSprite(texture); - ModelRotationContainer rotationContainer = new ModelRotationContainer() {}; - return QUAD_FACTORY.bake(from, to, face, sprite, side, rotationContainer, null, false); - } - -} diff --git a/src/test/resources/assets/multipart_test/models/multipart/bottom.json b/src/test/resources/assets/multipart_test/models/multipart/bottom.json new file mode 100644 index 0000000..d2beea9 --- /dev/null +++ b/src/test/resources/assets/multipart_test/models/multipart/bottom.json @@ -0,0 +1,18 @@ +{ + "textures": { + "texture": "block/iron_block" + }, + "elements": [ + { "from": [ 0, 0, 0 ], + "to": [ 16, 1, 16 ], + "faces": { + "down": { "texture": "#texture", "cullface": "down" }, + "up": { "texture": "#texture" }, + "north": { "texture": "#texture", "cullface": "north" }, + "south": { "texture": "#texture", "cullface": "south" }, + "west": { "texture": "#texture", "cullface": "west" }, + "east": { "texture": "#texture", "cullface": "east" } + } + } + ] +} diff --git a/src/test/resources/assets/multipart_test/models/multipart/vertical.json b/src/test/resources/assets/multipart_test/models/multipart/vertical.json new file mode 100644 index 0000000..21c3a10 --- /dev/null +++ b/src/test/resources/assets/multipart_test/models/multipart/vertical.json @@ -0,0 +1,18 @@ +{ + "textures": { + "texture": "block/gold_block" + }, + "elements": [ + { "from": [ 0, 0, 0 ], + "to": [ 16, 16, 1 ], + "faces": { + "down": { "texture": "#texture", "cullface": "down" }, + "up": { "texture": "#texture", "cullface": "up" }, + "north": { "texture": "#texture", "cullface": "north" }, + "south": { "texture": "#texture" }, + "west": { "texture": "#texture", "cullface": "west" }, + "east": { "texture": "#texture", "cullface": "east" } + } + } + ] +} diff --git a/src/test/resources/assets/multipart_test/multipartstates/test_part.json b/src/test/resources/assets/multipart_test/multipartstates/test_part.json new file mode 100644 index 0000000..114bf38 --- /dev/null +++ b/src/test/resources/assets/multipart_test/multipartstates/test_part.json @@ -0,0 +1,10 @@ +{ + "variants": { + "slot=bottom": { "model": "multipart_test:multipart/bottom" }, + "slot=top": { "model": "multipart_test:multipart/bottom", "x": 180 }, + "slot=north": { "model": "multipart_test:multipart/vertical" }, + "slot=south": { "model": "multipart_test:multipart/vertical", "y": 180 }, + "slot=east": { "model": "multipart_test:multipart/vertical", "y": 90 }, + "slot=west": { "model": "multipart_test:multipart/vertical", "y": 270 } + } +} \ No newline at end of file