Jump to content

Recommended Posts

Posted

I'm currently working on a mod which will eventually modify a player's maximum health depending on a level, and replace the default GUI element with a custom health bar. I currently have the following working;

 

- Vanilla health bar no longer renders

- My custom health bar is rendering (in the center of the screen, this is one of my questions)

- My custom health bar is displaying the correct amount of health ((current health / max health) * bar width)

 

However, I have a few problems/questions:

 

Firstly, the hunger bar no longer renders. This is not a huge issue, as I can just make it render manually, but I'd rather not cancel that particular part of the RenderGameOverlayEvent. Is there any way to only cancel the rendering of the health bar, not the hunger bar?

 

Second, how would I go about finding the X and Y coords of the top-left corner of the VANILLA health (and hunger) bar? As in, the location on the screen where it will render. I currently am using event.resolution.getScaledHeight() / 2 (and width for the x position) to get the center of the screen, but thanks to the helpful variable naming in Minecraft's code, I haven't been able to figure out how they get the position on the screen.

 

Lastly, how exactly would I go about updating the player's maximum health, and do I need to store this in their extended properties (and use packets to sync between client and server)? I already have extended properties set up for the levelling system, and can grab the user's properties (level, exp, etc) at any time.

 

Thanks,

 

Zer0

Posted

When you are drawing something, the point (0,0) is the top left corner. If you were having your health bar drawn in the middle, then it must have been drawing at width / 2 and height / 2

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

When you are drawing something, the point (0,0) is the top left corner. If you were having your health bar drawn in the middle, then it must have been drawing at width / 2 and height / 2

 

That is precisely what I said in my first post. I had it there for testing. I've got the positioning sorted now, anyway.

Posted

You never said that. I was just pointing out what I hadn't read in your post.

 

All crap aside, here is what you want for one of your questions:

@SubscribeEvent
public void on(RenderGameOverlayEvent.PRE event)
{
        if (event.type.equals(RenderGameOverlayEvent.ElementType.HEALTH)
        {
                event.setCanceled(true); // Cancels the rendering of the HEALTH bar. Take a look at all the different ElementType's
        }
}

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

Thanks, but my problem is not cancelling the rendering of the health bar - it's stopping that from cancelling the rendering of the hunger bar. Right now if I stop the health bar from rendering, the hunger bar doesn't render either. I would prefer to implement a custom hunger bar, but I've been unable to get it to display the correct value. What I wanted to know was how to stop the event from cancelling when it renders the hunger bar.

Posted

>.> I said look into the element types didn't I? Yes? Change HEALTH to FOOD and it will only cancel the food bar. Use HEALTH and it will only cancel the health bar.

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

I am fully aware of that. What I am asking is how to NOT cancel the food bar when you cancel the health bar. I have tried setting canceled to false when the event.type is FOOD, but the food bar is still not rendered.

Posted

Okay. First, I apologize for want to punch your face in. I get exasperated easily.

 

Secondly. If you use this code:


@SubscribeEvent
public void on(RenderGameOverlayEvent.PRE event)
{
        if (event.type.equals(RenderGameOverlayEvent.ElementType.HEALTH)
        {
                event.setCanceled(true); // Cancels the rendering of the HEALTH bar. Take a look at all the different ElementType's
        }
}

 

Only the health bar should be canceled, not the food bar. That is what you were asking, no?

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted
@SideOnly(Side.CLIENT)
public class GuiHealthBar extends Gui 
{
private Minecraft mc;
private static final ResourceLocation texLoc = new ResourceLocation("mchardcore", "textures/gui/health_bar.png");

public GuiHealthBar(Minecraft mc)
{
	super();
	this.mc = mc;
}

@SubscribeEvent
public void onRenderHealthBar(RenderGameOverlayEvent.Pre event)
{
	if(event.type == ElementType.HEALTH)
	{
		event.setCanceled(true);

		EntityPlayer player = this.mc.thePlayer;

		float health = player.getHealth();
		float maxHealth = player.getMaxHealth();

		int healthBarWidth = (int)(((float)health/maxHealth)*79);

		int xPos = event.resolution.getScaledWidth() / 2 - 91;
		int yPos = event.resolution.getScaledHeight() - 40;

		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		GL11.glDisable(GL11.GL_LIGHTING);

		this.mc.getTextureManager().bindTexture(texLoc);

		this.drawTexturedModalRect(xPos, yPos, 0, 0, 81, 9);
		this.drawTexturedModalRect(xPos+1, yPos+1, 0, 9, healthBarWidth, 7);

	}
}
}

Posted

Try putting a else statement after the if statement which does event.setCanceled(false); so it de-cancels the rendering if it isn't the health bar.

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

Yep, I tried adding an else statement - still cancels the rendering of everything after the health bar.

 

Kwibble: I did try changing it to the if statement you provided, but it made no difference, so I changed it back to that purely because it's easier to read.

Posted

So I decided that rather than trying to get the default hunger bar to render, I would create a new HUD instead (seems weird that this was actually easier than getting the default elements to render). However, I now have a new fun little bug. Where the old health and hunger bars would have been, I now have weird green shapes that look like they would have been the outlines for the default bars.

 

ii6dT0q.jpg

 

They are coloured green because I set the colour of the string (number in the HUD) to green, as when I change that colour, the colour of the phantom health bar changes too. Therefore, it must be rendering after the event I have cancelled, as the string is the last thing I render to prevent it from turning the armour and air bars green (the grey one is my new armour bar, turns out that got cancelled too).

 

Here is the code for the GUI class: http://pastebin.com/D2jrErz8

 

Does anyone know why this happens or how to fix it?

Posted

Nevermind, I just solved it, although it's a pretty messy method that I'll change if I find a better way of doing it. I just set glColor4f(1, 1, 1, 0), so it's transparent. Works for now.

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.