Jump to content

Recommended Posts

Posted (edited)

Hello mcForge modding community, i'm not really known with 1.12 TileEntities and i am currently working on TileEntities with inventory and gui, i found a tutorial on shadowfact's website about it but i dont really understand the code so could someone send me some good tutorial for it?

 

PS: I dont want to use vanilla classes because i know that forge has a better alterative then the IInventory from minecraft itsself.

 

GitHub: https://github.com/Eaglesmoddingteam/Back-to-Eco 

Edited by tebreca
Posted

I dont really understand the part of creating the instance of the container, drawing the inventory, i got a advanced inventory looking like this

I get that he draws the inventory but i cant really get how i add the places in my own inventory gui and do the progression bar 

 

i also cant find anything i at the docs

Posted (edited)

An inventory or GUI consists out of two things. The main Client side GuiContainer and the server side container.  These are bound together with a guiHandler 

 

With the handler you're basically connecting the two. The way to add 'slots' to your GUI is to add slots to the container. You're using 

SlotItemHandler

for your custom inventory .Which is the proper way to do it. 

 

Your problem might be that you haven't implemented an IGuiHandler. At least I can't find it in your GitHub. I might be blind.

 

 

Anyway, to draw the bar you'll want to pass a variable with the percentage done to the client side guiContainer. Then use a 

 

drawTexturedModalRect(xPosition, yPosition, xStart, yStart, x, y);

 

to draw the arrow. The way you do this is to set the 'start' of the draw texture to the left top corner of your texture. Then make the x the 'percentage' of your arrow. If the arrow is 50 pixels long and your machine is 50% done you set the x to 50*percentage where the double percentage is equal to 0.5

 

I'm writing from my phone. But I think that should be enough to get you going. 

 

 

Edit: When you pass a variable as '50' instead of a value with decimals and divide it by 100 to get a multiplier. Make sure you're using a double and casting one of the numbers to double so you actually GET a double.  I know you probably already know this since it's basic. But I made the mistake once and when you do, you only get 1 or 0, don't be a dummy.

Edited by oldcheese
Use a double.
  • Like 1
Posted
26 minutes ago, oldcheese said:

An inventory or GUI consists out of two things. The main Client side GuiContainer and the server side container.  These are bound together with a guiHandler 

 

With the handler you're basically connecting the two. The way to add 'slots' to your GUI is to add slots to the container. You're using 


SlotItemHandler

for your custom inventory .Which is the proper way to do it. 

 

Your problem might be that you haven't implemented an IGuiHandler. At least I can't find it in your GitHub. I might be blind.

 

 

Anyway, to draw the bar you'll want to pass a variable with the percentage done to the client side guiContainer. Then use a 

 


drawTexturedModalRect(xPosition, yPosition, xStart, yStart, x, y);

 

to draw the arrow. The way you do this is to set the 'start' of the draw texture to the left top corner of your texture. Then make the x the 'percentage' of your arrow. If the arrow is 50 pixels long and your machine is 50% done you set the x to 50*percentage where the double percentage is equal to 0.5

 

I'm writing from my phone. But I think that should be enough to get you going. 

thx, that was some handy info,i think i can figure it out myselves, only how can i adjust where the boxes are going to be in the container/gui?

Posted (edited)

With boxes do you mean slots?

 

when you add a slot to your container like such: 

			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 9; j++) {
					addSlotToContainer(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
				}
			}

you're doing the following: You add 3 rows with each 9 slots. Every time i increases it goes 18 pixels down (slots are 18 big, 2 pixels around the 16 width item.) and every time j increases it goes 18 pixels to the right for the same reasons.

The second value is the index, this is increased by 1 for every new slot basically. So every i adds 9, every j adds 1. 

addSlotToContainer(new Slot(inventoryToUse, slotIndex, xCoordinate, yCoordinate));

 

basically  the slotindex is the index of the slot within the inventory. Vanilla inventory uses 0-35 for the items with 0-8 being the hotbar. slots 35-38 are armour.

 

the xCoordinate is the spot within your GUI where you want to put your slot. The y Coordinate is the height from the top where your slot is. 

 

When you draw your Container the point '0' in x and y are the top left corner. in the GuiContainer (client side) you want to make your own 0 point, since 0 is the top left corner of the screen, not the gui.

 

You have already declared the two variables for x and y in your gui using the following code however :

		int x = (width - xSize) / 2;
		int y = (height - ySize) / 2;

 

so if you want something in the GuiContainer to be 15 pixels to the right and 10 pixels down(From the top left corner of your gui) you want to use 

 

drawTexturedModalRect(x+15, y+10, startOfTextureX, startOfTextureY, rectWidth, rectHeight);

 

obviously if you want something to be in the corner of the screen you can just use 0 instead of x+number

 

 

To clarify. the Container is your class extending container. the GuiContainer is the class extending GuiContainer. You probably know this. I'm just clarifying.

Edited by oldcheese
As draco said. Slots are 18 big, ITEMS are 16 big.
  • Like 1
Posted
15 minutes ago, oldcheese said:

With boxes do you mean slots?

 

when you add a slot to your container like such: 


			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 9; j++) {
					addSlotToContainer(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
				}
			}

you're doing the following: You add 3 rows with each 9 slots. Every time i increases it goes 18 pixels down (slots are 16 big, 2 pixels between the rows) and every time j increases it goes 18 pixels to the right for the same reasons.

The second value is the index, this is increased by 1 for every new slot basically. So every i adds 9, every j adds 1. 


addSlotToContainer(new Slot(inventoryToUse, slotIndex, xCoordinate, yCoordinate));

 

basically  the slotindex is the index of the slot within the inventory. Vanilla inventory uses 0-35 for the items with 0-8 being the hotbar. slots 35-38 are armour.

 

the xCoordinate is the spot within your GUI where you want to put your slot. The y Coordinate is the height from the top where your slot is. 

 

When you draw your Container the point '0' in x and y are the top left corner. in the GuiContainer (client side) you want to make your own 0 point, since 0 is the top left corner of the screen, not the gui.

 

You have already declared the two variables for x and y in your gui using the following code however :


		int x = (width - xSize) / 2;
		int y = (height - ySize) / 2;

 

so if you want something in the GuiContainer to be 15 pixels to the right and 10 pixels down(From the top left corner of your gui) you want to use 

 


drawTexturedModalRect(x+15, y+10, startOfTextureX, startOfTextureY, rectWidth, rectHeight);

 

obviously if you want something to be in the corner of the screen you can just use 0 instead of x+number

 

 

To clarify. the Container is your class extending container. the GuiContainer is the class extending GuiContainer. You probably know this. I'm just clarifying.

thx, yes i meant the boxes

Posted
2 minutes ago, tebreca said:

thx, yes i meant the boxes

No problem. If you have another problem in the future or can't get it to work, feel free to post again. Also make sure to distinguish between slots and rectangles. Since both are shaped like a box. A box really isn't anything! 

 

Anyway, good luck.

Posted
4 hours ago, oldcheese said:

Every time i increases it goes 18 pixels down (slots are 16 big, 2 pixels between the rows)

Actually, its the items that are 16 pixels. An actual slot graphic is 18x18. The 1 pixel border that gives the slot some "depth" extends beyond the 16x16 bounds.

But otherwise you're correct.

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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