Jump to content

[1.17.1] I have some doubts about using Capability in this version.


Recommended Posts

Posted

Hello Developers Usually older versions use Capability to save numeric values or other values via CompoundNBT via the forge library but in this version I tried to rebuild Capability but when using getCapability from Player class it turns out that Capability The new class doesn't match the old one. So I looked in vanilla and found CapabilityEnergy, EnergyStorage and IEnergyStorage so I looked at CapabilityEnergy#register because this method should is @SubscribeEvent to register IEnergyStorage But I don't know how to import or register EnergyStorage. I know EnergyStorage implements IEnergyStorage.

What I want to know is EnergyStorage How can it be used?

Posted

--------------------------------------------[1.16.5]--------------------------------------------
I created the IStatus interface, it doesn't implements and extends.
Then I created the class Status implements IStatus.
Next, I created a class StatusStorage implements IStorage<IStatus> to write and read CompoundNBT.
Finally, I created a class StatusProvider implements ICapabilitySerializable<INBT> and applied Capability<IStatus> to LazyOptional#of .

Everything went well.

--------------------------------------------[1.17.1]--------------------------------------------
First, Capability<T> doesn't have getDefaultInstance , so create a newCapability<T> for use with LazyOptional#of() .
Once it was created, I added the getDefaultInstance method to the NewCapability<T> similar to the old version.
But when to take Player#getCapability is used, it turns out CapabilityNew<T> is not Capability<T> , so it cannot be put in Player#getCapability
So I extends Capability<T> into NewCapability<T> , it can be used in Player#getCapability .
Later I ran into a problem: Capability(string) was not public, so I couldn't extends it.

So I would like to use the same method as your library as mentioned above. but i don't know EnergyStorage, can it register?

Below is the code I wrote in 1.16.5 for saving the values to the player. (P.S. besides not having getDefaultInstance and there is no getStorage() yet.)

public interface IStatus
{
    public void setEnergy(int points);
    
    public int getEnergy();
    
    public void setExcretion(int points);
    
    public int getExcretion();
    
    public void setDirty(int points);
    
    public int getDirty();
}

 

public class Status implements IStatus
{
    private int energy;
    private int excretion;
    private int dirty;
    
    public Status() {
    	this.energy = 20;
    	this.excretion = 20;
    	this.dirty = 20;
    }
    
	@Override
	public void setEnergy(int points) {
		this.energy = points;
	}
	
	@Override
	public int getEnergy() {
		return this.energy;
	}

	@Override
	public void setExcretion(int points) {
		this.excretion = points;
	}

	@Override
	public int getExcretion() {
		return this.excretion;
	}

	@Override
	public void setDirty(int points) {
		this.dirty = points;
	}

	@Override
	public int getDirty() {
		return this.dirty;
	}
}

 

public class StatusProvider implements ICapabilitySerializable<INBT>
{
    @CapabilityInject(IStatus.class)
    public static final Capability<IStatus> Status_CAP = null;
    
    private LazyOptional<IStatus> instance = LazyOptional.of(Status_CAP::getDefaultInstance);
    
    @Override
    public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction side)
    {
        return capability == Status_CAP ? instance.cast() : LazyOptional.empty();
    }
    
    @Override
    public INBT serializeNBT()
    {
        return Status_CAP.getStorage().writeNBT(Status_CAP, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null);
    }
    
    @Override
    public void deserializeNBT(INBT nbt)
    {
    	Status_CAP.getStorage().readNBT(Status_CAP, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null, nbt);
    }
}

 

public class StatusStorage implements IStorage<IStatus>
{
    @Override
    public INBT writeNBT(Capability<IStatus> capability, IStatus instance, Direction side)
    {
    	CompoundNBT status = new CompoundNBT();
    	status.putInt("Energy", instance.getEnergy());
    	status.putInt("Excretion", instance.getExcretion());
    	status.putInt("Dirty", instance.getDirty());
        return status;
    }

    @Override
    public void readNBT(Capability<IStatus> capability, IStatus instance, Direction side, INBT nbt)
    {
    	CompoundNBT status = (CompoundNBT)nbt;
    	instance.setEnergy(status.getInt("Energy"));
    	instance.setExcretion(status.getInt("Excretion"));
    	instance.setDirty(status.getInt("Dirty"));
    }
}

 

Posted

I need some advice from you. If you want to write a program to save the values in the player, which objects and methods should be used respectively, or just use CompoundTag? Run it now I'm disturbed

P.S. Your library is awesome.

Posted

Player#getCapability usually uses Capability<T> capability, Direction facing, but I renamed the class to NewCapability<T> I'm not sure. is it related? because originally it was net.minecraftforge.common.capabilities.Capability<T> is not something I created.

Posted
23 minutes ago, zlappedx3 said:

because originally it was net.minecraftforge.common.capabilities.Capability<T> is not something I created.

And you still don't.

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.

Posted
25 minutes ago, Draco18s said:

And you still don't.

Maybe if you change

    Capability(String name)
    {
        this.name = name;
    }

To
 

    public Capability(String name)
    {
        this.name = name;
    }

on package net.minecraftforge.common.capabilities.Capability i can do it :)

Posted

You don't create an instance of the `Capability` class, that is still handled behind the scenes (and the `@CapabilityInject` annotation still works as before).

Where you called `Capability#getDefaultInstance()` before, just create your new instance (of your Capability type, i.e. `new Status()`).

Where you called your Storage class methods (from your Capability Provider), just move your saving/loading stuff directly into those methods of your `StatusProvider`.

Posted
7 minutes ago, zlappedx3 said:

Should I make StatusProvider an instance?

What? You use StatusProvider exactly the same way you did before (attaching it in the AttachCapabilitiesEvent). The only thing you change is in your StatusProvider, you move the old code from your CapabilityRegistry.register(cap_class, storage, default_factory) and put the code from the storage class inside your StatusProvider save/load methods, and the code from your default_factory inside your LazyOptional.

Literally just getting rid of the stuff that no longer exists and calling it directly, instead of through the capability.

Posted
Just now, Luis_ST said:

@Alpvaxthis is 1.16, storage and factory have been removed in 1.17.
please edit the posts you create and remove the wrong information

Yes, that is what I am saying. Remove the old code (from the storage / default factory, which no longer exists) and put it in the Capability Provider directly.

Posted (edited)
21 minutes ago, zlappedx3 said:

Should I make StatusProvider an instance?

do something like that
and use RegisterCapabilitiesEvent to register your Cap

Edited by Luis_ST
  • Like 1

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.