Jump to content

Recommended Posts

Posted

So I've been working on a mod and, while I can get textures to bind to json driven blocks, I've got some entities that I've finally (after some work) gotten obj models to work with.  The issue is that the textures refuse to show up.  I don't get any errors on run, and it is calling the getEntityTexture in my renderer....if just won't bind that to the entity model

 

Here's my doRender for the entity:

 

     bakeModel();

      GlStateManager.pushMatrix();
      GlStateManager.translate((float) x, (float) y, (float) z);

      float scale = 0.1F;

      GlStateManager.rotate(90.0F, 0.0F, -1.0F, 0.0F);
      GlStateManager.scale(scale, scale, scale);
      GlStateManager.enableRescaleNormal();

      bindEntityTexture(entity);

      //Actually render this bad boy now
      Tessellator tessellator = Tessellator.getInstance();
      VertexBuffer vertexBuffer = tessellator.getBuffer();
      List<BakedQuad> listQuads = shipBakedModel.getQuads(null, null, 0);
      int k = 0;
      vertexBuffer.begin(7, DefaultVertexFormats.ITEM);
      for (int j = listQuads.size(); k < j; ++k) {
         BakedQuad bakedquad = listQuads.get(k);

         vertexBuffer.addVertexData(bakedquad.getVertexData());

         Vec3i vec3i = bakedquad.getFace().getDirectionVec();
         vertexBuffer.putNormal((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ());

      }
      tessellator.draw();

      GlStateManager.disableRescaleNormal();
      GlStateManager.popMatrix();

      super.doRender(entity, x, y, z, entityYaw, partialTicks);

 

What silly thing am I missing?

 

~@udio~

Posted

I don't think you can bind textures to .obj models. With my own .obj models, I've baked the texture (material) to the UV-map of the model inside the rendering program (Blender in my case), meaning all I need is the accompanying .mtl file in the same folder as the .obj.

Also previously known as eAndPi.

"Pi, is there a station coming up where we can board your train of thought?" -Kronnn

Published Mods: Underworld

Handy links: Vic_'s Forge events Own WIP Tutorials.

Posted

Interesting, when I look into the mtl file, it references the texture, but it doesn't seem to actually be applied at runtime.  I've tried both a true relative path and a minecraft resource path with no avail.

 

Also, if i remove the bindEntityTexture, I get what you would expect....the purple and black.  Add the bindEntityTexture back in, all white (side note:  the texture file is not all white :P ).  This would tell me that it's not finding a texture referenced in the model.  Maybe I'm not baking the model correctly?  Or maybe not applying the texture when I render?  This is my first time having to manually handle the rendering, so I'm shooting in the dark completely.

Posted

Hi

 

Not sure, but some ideas to try:

- is texturing on for the drawing (purple and black implies yes)

- perhaps the texture coordinates on your model quads don't line up with the texture- so (eg) a single texel of your texture is being stretched to cover the entire model - try changing your texture to a different colour?  BakedQuads usually use a texture that has been stitched into a much larger texture sheet, so the BakedQuad u,v values are usually very close to each other, whereas your entity texture probably uses the entire uv space 0 -> 1.

BakedQuadRetextured might be worth checking out.  You could also inspect the BakedQuads to make sure the texture coordinates look right.

 

-TGG

Posted

Still no luck, but I have noticed something interesting.  Following the export of the obj (and related files) from Blender, I was curious and decided to try to do an OBJ import of the exported files.  Upon doing so, I discovered that the texture wasn't being applied there, either.  So at this point I'm fairly certain it's a model issue, not a code issue.

 

As a side note, I'm not doing the models for our code (I'm a meat-headed coder, not an artist).  Our artist uses Cubik, and the default obj that Cubik exported contained "s off" entries, which aren't supported I guess?  It makes sense that OBJ loader wouldn't use these, but the fact that Cubik would export something that Forge couldn't use is, well, frustrating.  Maybe it would be different if we were doing a tile entity and could use the TESR, but it would appear that Cubik isn't really good for anything that couldn't use a json if it needed to.

Posted

Still no luck, but I have noticed something interesting.  Following the export of the obj (and related files) from Blender, I was curious and decided to try to do an OBJ import of the exported files.  Upon doing so, I discovered that the texture wasn't being applied there, either.  So at this point I'm fairly certain it's a model issue, not a code issue.

 

As a side note, I'm not doing the models for our code (I'm a meat-headed coder, not an artist).  Our artist uses Cubik, and the default obj that Cubik exported contained "s off" entries, which aren't supported I guess?  It makes sense that OBJ loader wouldn't use these, but the fact that Cubik would export something that Forge couldn't use is, well, frustrating.  Maybe it would be different if we were doing a tile entity and could use the TESR, but it would appear that Cubik isn't really good for anything that couldn't use a json if it needed to.

Just to be sure, as you do imply that you do not use Blender much at all, but are you sure you had Blender in the correct viewport?

When importing about anything into blender, the default viewport is "solid", where you need either "texture", "material" or "rendered" to view it with "textures".

[spoiler=image]

lYkNhMY.png

 

 

On the Cubik issues. Yes, that is quite odd >_>

As i mentioned before, I would recommend you get the model's texture baked to the UV-map, to make sure that it renders (This should be done inside the modelling software. If Cubik cannot do this, then sorry, it has no business with .obj models at all).

I recommend that you guys use Blender or any other .obj modelling software directly instead of these "minecraft modelling programs" for anything that json files cannot do.

Note: Faces in models (a cube has 6 flat faces aka sides. A 4-sided pyramid got 5 (4 triangles + bottom) etc) can only have 4 or less edges. More are not supported in Forge, and will either cause the model to render without the faces, or not render the model at all (have had both cases happen to me before)

Also previously known as eAndPi.

"Pi, is there a station coming up where we can board your train of thought?" -Kronnn

Published Mods: Underworld

Handy links: Vic_'s Forge events Own WIP Tutorials.

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

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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