Jump to content

[1.19.2] Dynamic change of texture and model, item JSON


Luckydel

Recommended Posts

 

I would like to add a sight to the weapon, a silencer, as a layer (If possible) and change item texture.

As far as I understand, I need BakedModel. But it looks like I'm doing something wrong. ( I don't go to methods. )

Spoiler
public class Makarov extends ProjectileWeaponItem implements BakedModel {
	@Override
    public List<BakedQuad> getQuads(@Nullable BlockState p_235039_, @Nullable Direction p_235040_, RandomSource p_235041_) {
        return null;
    }

    @Override
    public boolean useAmbientOcclusion() {
        return false;
    }

    @Override
    public boolean isGui3d() {
        return false;
    }

    @Override
    public boolean usesBlockLight() {
        return false;
    }

    @Override
    public boolean isCustomRenderer() {
        return false;
    }

    @Override
    public TextureAtlasSprite getParticleIcon() {
        return null;
    }

    @Override
    public ItemOverrides getOverrides() {
        return null;
    }
    ...
}

 

Maybe I still need ItemOverrides

But, my json looks different (Blockbench), I don't have "model". I have vertices and groups of them in JSON
 

Spoiler
{
	"textures": {
		"0": "mod:item/makarov/main",
		"1": "mod:item/makarov/aim",
		"particle": "block/main"
	},
	"elements": [
		{
			"from": [6.4, 10.4, 7.1],
			"to": [14, 10.5, 8.6],
			"rotation": {"angle": 0, "axis": "y", "origin": [6, 4.7, 7.1]},
			"faces": {
				"north": {"uv": [1, 11, 4.8125, 11.0625], "texture": "#0"},
				"east": {"uv": [11.5, 12.5, 12.25, 12.5625], "texture": "#0"},
				"south": {"uv": [11, 2.5, 14.8125, 2.5625], "texture": "#0"},
				"west": {"uv": [12.5, 12.5, 13.25, 12.5625], "texture": "#0"},
				"up": {"uv": [3.8125, 0.75, 0, 0], "texture": "#0"},
				"down": {"uv": [3.8125, 1, 0, 1.75], "texture": "#0"}
			}
		},
	...

	"groups": [
		{
			"name": "group",
			"origin": [0, 0, 0],
			"color": 0,
			"nbt": "{}",
			"armAnimationEnabled": false,
			"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]
		},
		{
			"name": "aim",
			"origin": [8, 8, 8],
			"color": 0,
			"nbt": "{}",
			"armAnimationEnabled": false,
			"children": [37, 38, 39, 40]
		}
	]

 

 

Edited by Luckydel
Link to comment
Share on other sites

On 10/29/2022 at 11:19 AM, Luckydel said:

As far as I understand, I need BakedModel. But it looks like I'm doing something wrong. ( I don't go to methods. )

 

The baked model is necessary as it represents the model, but it doesn't do anything if you don't register an associated ModelLoader to read the JSONs as that format. This process is not well documented and has recently gotten a massive overhaul, so the best thing to do is look at other model loaders already present and mimic them. Also, if everything is null, things will crash.

On 10/29/2022 at 11:19 AM, Luckydel said:

Maybe I still need ItemOverrides

Yes, they are for the context of an ItemStack, getQuads is typically in the context of the world (so, blocks).

On 10/29/2022 at 11:19 AM, Luckydel said:

But, my json looks different (Blockbench), I don't have "model". I have vertices and groups of them in JSON

You can have those, though whether they'll be read depends on if the vanilla model accepts them (don't think they do for some of the group fields).

Link to comment
Share on other sites

On 10/31/2022 at 2:48 PM, ChampionAsh5357 said:
 

The baked model is necessary as it represents the model, but it doesn't do anything if you don't register an associated ModelLoader to read the JSONs as that format. This process is not well documented and has recently gotten a massive overhaul, so the best thing to do is look at other model loaders already present and mimic them. Also, if everything is null, things will crash.

Yes, they are for the context of an ItemStack, getQuads is typically in the context of the world (so, blocks).

You can have those, though whether they'll be read depends on if the vanilla model accepts them (don't think they do for some of the group fields).

Then, for regular json, do I need to use UnbakedModel? Something does not work.

Link to comment
Share on other sites

18 hours ago, Luckydel said:

Then, for regular json, do I need to use UnbakedModel? Something does not work.

That's not what I said? You can bake the models in using the normal procedure and just have your custom model loader consume the baked models and render them all at specific offsets. Once again, take a look at existing custom model loaders (the composite model loader comes to mind here).

Link to comment
Share on other sites

7 hours ago, ChampionAsh5357 said:

That's not what I said? You can bake the models in using the normal procedure and just have your custom model loader consume the baked models and render them all at specific offsets. Once again, take a look at existing custom model loaders (the composite model loader comes to mind here).

Thank you for your patience.
Okay, I've created a custom model loader, how do I tell the item to use it?

Link to comment
Share on other sites

I am reluctant to get involved in this thread since I know virtually nothing about custom model loaders. 🙂

I just want to suggest you look at what ForgeClientMod ClientForgeMod does.

This is just another mod, the only thing special about it, is that it is preinstalled with forge.

e.g. it creates the composite loader mentioned above, along with others.

 

You might also want to look at: https://docs.minecraftforge.net/en/1.19.x/rendering/modelloaders/#custom-model-loaders

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

2 hours ago, Luckydel said:

Okay, I've created a custom model loader, how do I tell the item to use it?

You'll need to register it with `ModelEvent$RegisterGeometryLoaders` if you haven't already, which will register your loader with the name `modid:name`. Then you supply that within the main model of your item with the `loader` key.

Link to comment
Share on other sites

13 hours ago, ChampionAsh5357 said:

You'll need to register it with `ModelEvent$RegisterGeometryLoaders` if you haven't already, which will register your loader with the name `modid:name`. Then you supply that within the main model of your item with the `loader` key.

It looks like I misunderstood something

Custom model loader is CompositeModelBuilder or CompositeModel$Loader ?
EDIT:

Can you give more details about the `loader` key, or a link to the documentation

Edited by Luckydel
Link to comment
Share on other sites

2 hours ago, Luckydel said:

Custom model loader is CompositeModelBuilder or CompositeModel$Loader ?

`CompositeModel$Loader`, the builder is used to make the baked model from quads, which can be obtained from other baked models.

2 hours ago, Luckydel said:

Can you give more details about the `loader` key, or a link to the documentation

It's just a key that points to the name you registered the loader under. There is currently no actual documentation on this yet.

{
  "loader": "modid:loader_name",
  // ... Rest of the model json
}
Link to comment
Share on other sites

3 hours ago, ChampionAsh5357 said:

`CompositeModel$Loader`, the builder is used to make the baked model from quads, which can be obtained from other baked models.

It's just a key that points to the name you registered the loader under. There is currently no actual documentation on this yet.

{
  "loader": "modid:loader_name",
  // ... Rest of the model json
}

I'm doing something wrong. Doesn't go to registration event.
 

Spoiler
public class modSubscribeEvents {
    public static final String ModelLoader = "CustomModelLoader";
	//work
    @SubscribeEvent
    public static void test(RenderGuiOverlayEvent.Pre event){
        int d=3;
    }
	//don't work
    @SubscribeEvent
    public static void registryModelLoader(ModelEvent.RegisterGeometryLoaders event){
        event.register(Main.MODID+":"+ModelLoader, ExampleModelBuilder.Loader.INSTANCE);
    }

}

 

Model loader class, as a basis I used ElementsModel.

Spoiler
public class ExampleModelBuilder extends SimpleUnbakedGeometry<ExampleModelBuilder> {
    private static final Logger LOGGER = LogManager.getLogger();

    private final List<BlockElement> elements;
    private final boolean deprecatedLoader;

    public ExampleModelBuilder(List<BlockElement> elements)
    {
        this(elements, false);
    }

    private ExampleModelBuilder(List<BlockElement> elements, boolean deprecatedLoader)
    {
        this.elements = elements;
        this.deprecatedLoader = deprecatedLoader;
    }

    @Override
    protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
    {
        if (deprecatedLoader)
            LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"minecraft:elements\" instead of \"forge:elements\". This loader will be removed in 1.20.");

        var rootTransform = context.getRootTransform();
        if (!rootTransform.isIdentity())
            modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());

        for (BlockElement element : elements)
        {
            for (Direction direction : element.faces.keySet())
            {
                var face = element.faces.get(direction);
                var sprite = spriteGetter.apply(context.getMaterial(face.texture));
                var quad = BlockModel.bakeFace(element, face, sprite, direction, modelState, modelLocation);

                if (face.cullForDirection == null)
                    modelBuilder.addUnculledFace(quad);
                else
                    modelBuilder.addCulledFace(modelState.getRotation().rotateTransform(face.cullForDirection), quad);
            }
        }
    }

    @Override
    public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
    {
        Set<Material> textures = Sets.newHashSet();
        if (context.hasMaterial("particle"))
            textures.add(context.getMaterial("particle"));
        for (BlockElement part : elements)
        {
            for (BlockElementFace face : part.faces.values())
            {
                Material texture = context.getMaterial(face.texture);
                if (texture.texture().equals(MissingTextureAtlasSprite.getLocation()))
                    missingTextureErrors.add(Pair.of(face.texture, context.getModelName()));
                textures.add(texture);
            }
        }

        return textures;
    }

    public static final class Loader implements IGeometryLoader<ExampleModelBuilder>
    {
        public static final ExampleModelBuilder.Loader INSTANCE = new ExampleModelBuilder.Loader(false);
        @Deprecated(forRemoval = true, since = "1.19")
        public static final ExampleModelBuilder.Loader INSTANCE_DEPRECATED = new ExampleModelBuilder.Loader(true);

        private final boolean deprecated;

        private Loader(boolean deprecated)
        {
            this.deprecated = deprecated;
        }

        @Override
        public ExampleModelBuilder read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException
        {
            if (!jsonObject.has("elements"))
                throw new JsonParseException("An element model must have an \"elements\" member.");

            List<BlockElement> elements = new ArrayList<>();
            for (JsonElement element : GsonHelper.getAsJsonArray(jsonObject, "elements"))
            {
                elements.add(deserializationContext.deserialize(element, BlockElement.class));
            }

            return new ExampleModelBuilder(elements, deprecated);
        }
    }
}

 

 

 

I have another question, after I register it and set "loader". I will be able to interact with the model via IUnbakedGeometry#bake in item  class or am I misunderstanding something?

Link to comment
Share on other sites

ModelEvent$RegisterGeometryLoaders is on the mod event bus as the event says on its javadocs.

Do not copy-paste the raw loader. The reason why I mentioned using the composite loader is because it does something similar to what you want but requires you to thing about what to implement.

19 hours ago, Luckydel said:

I have another question, after I register it and set "loader". I will be able to interact with the model via IUnbakedGeometry#bake in item  class or am I misunderstanding something?

You read it into an unbaked geometry and then bake it into a model after everything has been loaded. You should not be able to access the geometry from the item class. If you want to provide overrides depending on the stack, you need to provide your own custom ItemOverrides to and specifying that for this stack use this model.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • How can I add drops when killing an entity? Now there are no drops. How can I add an @override to change the attack speed to 1.6 and show "when in main hand...attack damage,...attack speed"? also, how can I make the item enchantable? 
    • Ok. Thanks. by the way, will this crash in any circumstances? public boolean onLeftClickEntity(ItemStack stack, Player player, Entity entity) { if (entity instanceof LivingEntity){ LivingEntity victim = (LivingEntity) entity; if(!victim.isDeadOrDying() && victim.getHealth()>0){ victim.setHealth(0); return true; } } return false; }  
    • You shouldn't be extracting the mod .jar, just place it in your mods folder.
    • so basically another rundown of my probelm. Im the admin of a 1.20.1 modded server. Were using forge 47.2.0 but tested this issue in other forge versions too on sevrer and client side. so the forge version isnt the issue. The bug happens in following instances. Were using the attacks of the jujutsucraft mod by orca normally. And for everyone that stands there nothing changes. But everyone who wasnt in the chunks before or who relogins again those chunks will appear invisible for the most part. I tried fixing this be removing and adding following mods in many combinations. Embeddium, canary, memoryleakfix, ai improvements, Krypton reforges, better chunkloading, radium reforged, embeddium plus, farsight, betterchunkloading, oculus I tested most of these mods alone and in differents combinations with each other and without the mods. What i noticed is zhat when i removed  . most invisible chunks will return or semi return. and only ine or two chunks stay invisible. I rechanged those mids mostly on the cöient side but also some in the serveside. Ir most likely isnt an issue with another non performance mod since i noticed this thing with embeddium. Ans also the problem wasnt there im the beginning of the server. Granted since then we updated some of the mods that add content and their lib mod. But i went to every big mods discord and community that we have and i didnt find someone else havinf that chunk problem. Heres the link to a video of the Problem. https://streamable.com/9v1if2     heres the link to the modlist: https://ibb.co/myF8dtX     Pleaee im foghting for months with this problem. All the performance mods kn the modlist are for sure not the issue i tested without all of them.
    • It looks like you're only setting the health if the thing you are hitting is a player.  
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.