Jump to content

Recommended Posts

Posted

Help, I created an Entity which summonable by right-clicking an item but when i spawn it, it dies instantly and i dont know why, this just happened after i added something and changed a part of the code, before it worked fine and the entity didn't died.

 

 

here the summon code in the item class:

 

/**
     * Called whenever this item is equipped and the right mouse button is pressed. Args: itemStack, world, entityPlayer
     */
    public ItemStack onItemRightClick(ItemStack itemStackIn, World world, EntityPlayer player)
    {	
    	NBTTagCompound nbtTagCompound = itemStackIn.getTagCompound();
    	if (!world.isRemote)
        {	
    		/*if (nbtTagCompound != null && nbtTagCompound.hasKey("IS_SUMMONED") && nbtTagCompound.getBoolean("IS_SUMMONED") == true ) { 
    			EntityNikora entitynikora = new EntityNikora(world, player); 
        		player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora."));
    			entitynikora.spawnExplosionParticle();
    			entitynikora.setDead();
    			setIsSummoned(itemStackIn, false);
    		}*/
    		
    		if (nbtTagCompound != null && nbtTagCompound.hasKey("IS_SUMMONED") && nbtTagCompound.getBoolean("IS_SUMMONED") == false ) { 
    		//PacketDispatcher.sendToServer(new SpellToServer(10, 10));
    			EntityNikora entitynikora = new EntityNikora(world, player); 
    			entitynikora.setPosition(player.posX, player.posY+1,player.posZ-2); 
    			world.spawnEntityInWorld(entitynikora);
    			player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.GREEN + "You summoned Nikora!"));
    		}
        }
	return itemStackIn;
    }

 

 

the entity:

 

public class EntityNikora extends EntityTameable implements IEntityOwnable
{
private int tick;
private int manacost = 5;

private double spirit_damage = 2.0D;
private double spirit_health = 20.0D;

    public EntityNikora(World w)
    {
    	this(w, null);
    	
    }
    
    public EntityNikora(World world, Entity caster)
    {
        super(world);
    this.setSize(1, 1);
    ((PathNavigateGround)this.getNavigator()).func_179690_a(true);
        this.tasks.addTask(1, new EntityAISwimming(this));
        this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
        this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0D, true));
        this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 2F, 5F));
        this.tasks.addTask(6, new EntityAIMate(this, 1.0D));
        this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
        this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
        this.tasks.addTask(9, new EntityAILookIdle(this));
        this.targetTasks.addTask(1, new EntityAIOwnerHurtByTarget(this));
        this.targetTasks.addTask(2, new EntityAIOwnerHurtTarget(this));
        this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityMob.class, true));
        this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true, new Class[0]));

    if (caster != null)
    {
        this.setTamed(true);
		this.setAttackTarget((EntityLivingBase)null);
		this.setOwnerId(caster.getUniqueID().toString());
		this.worldObj.setEntityState(this, (byte)7);
    }
    }
    
    /**
     * Returns true if the newer Entity AI code should be run
     */
    public boolean isAIEnabled()
    {
        return true;
    }

    protected void applyEntityAttributes()
    {
        super.applyEntityAttributes();
        this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(this.spirit_health);
        this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(this.spirit_damage);
    }
    
    @Override
    public void onLivingUpdate() {
    	
    	if(getOwner() != null){
     	EntityPlayer player = (EntityPlayer)getOwner();
     	ExtendedPlayer props = ExtendedPlayer.get(player);
     	tick++;
     	if(!worldObj.isRemote){
     	if(tick > 300){
     	if(props.getCurrentMana() >= manacost){
     		props.consumeMana(manacost);
     		tick = 0;
     	}
     	
     	if(props.getCurrentMana() < manacost){
     		player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned."));
     		this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0);
     		this.setDead();	
     	}
     	}
     	}
     	super.onLivingUpdate();
    	}
    	
     }

    /**
     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
     * use this to react to sunlight and start to burn.
     * @param entity 
     */
    public void onLivingUpdate(EntityPlayer entity)
    {
        super.onLivingUpdate();

        if(!(entity instanceof EntityPlayer))
	{
		this.setAttackTarget(entity);
	}
    }
    


    protected Item getDropItem()
    {
        return (null);
    }

@Override
public EntityAgeable createChild(EntityAgeable ageable)
{
	return (null);
}
}

 

 

note no error, but it dies by his self. thanks for any help!

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

EntityNikora entitynikora = new EntityNikora(world, player); 
player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora."));
entitynikora.spawnExplosionParticle();
entitynikora.setDead();

 

what exactly are you triing to do there

Posted

EntityNikora entitynikora = new EntityNikora(world, player); 
player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora."));
entitynikora.spawnExplosionParticle();
entitynikora.setDead();

 

what exactly are you triing to do there

 

That part is commented out.

 

But back to topic.

 

Sure about getCurrentMana() is over manacost?

Not all things in the world are red, there are round objects too!

Posted

EntityNikora entitynikora = new EntityNikora(world, player); 
player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora."));
entitynikora.spawnExplosionParticle();
entitynikora.setDead();

 

what exactly are you triing to do there

 

That part is commented out.

 

But back to topic.

 

Sure about getCurrentMana() is over manacost?

 

Yes im sure, when the current mana is lower than the manacost it will send a Chat Message and a System out print but it doesnt do.

 

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

Tried to debug and breakpoint to trace where the entity dies?

 

By the way which difficulty level are you running the game in?

Not all things in the world are red, there are round objects too!

Posted

First, make sure you are not in peaceful mode.

 

Second:

if(props.getCurrentMana() >= manacost){
     		props.consumeMana(manacost);
     		tick = 0;
     	}
     	
     	if(props.getCurrentMana() < manacost){
     		player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned."));
     		this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0);
     		this.setDead();	
     	}

Let's follow that logic. I don't know your current mana at that point, but let's say you have 6 mana. You have manacost = 5.

 

-

if(props.getCurrentMana() >= manacost)

  Your current mana is 6, and manacost is 5, so that condition is true.

---

props.consumeMana(manacost)

  I suspect

consumeMana

is reducing your current mana with the manacost, leaving you with only 1 mana left.

-

if(props.getCurrentMana() < manacost)

  Your current mana is 1 at this point, and manacost is 5, so that is indeed less and that condition is true.

--- Kill the entity

 

Have you figured it out yet? If you don't have atleast 2*manacost when you start, the entity instantly dies because the second if-statement is true because you already removed the mana from the player. You have to add

else

to the second if-statement.

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

First, make sure you are not in peaceful mode.

 

Second:

if(props.getCurrentMana() >= manacost){
     		props.consumeMana(manacost);
     		tick = 0;
     	}
     	
     	if(props.getCurrentMana() < manacost){
     		player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned."));
     		this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0);
     		this.setDead();	
     	}

Let's follow that logic. I don't know your current mana at that point, but let's say you have 6 mana. You have manacost = 5.

 

-

if(props.getCurrentMana() >= manacost)

  Your current mana is 6, and manacost is 5, so that condition is true.

---

props.consumeMana(manacost)

  I suspect

consumeMana

is reducing your current mana with the manacost, leaving you with only 1 mana left.

-

if(props.getCurrentMana() < manacost)

  Your current mana is 1 at this point, and manacost is 5, so that is indeed less and that condition is true.

--- Kill the entity

 

Have you figured it out yet? If you don't have atleast 2*manacost when you start, the entity instantly dies because the second if-statement is true because you already removed the mana from the player. You have to add

else

to the second if-statement.

 

It seems logical what you mean but i found out that this two variables are the problem, i can fix that with replacing them at applyEntityAttributes with there value, but why i can't use them as variables?

 

private double spirit_damage = 2.0D;
private double spirit_health = 20D;

protected void applyEntityAttributes()
    {
        super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(spirit_health);}

 

The Entity is dying because the health is 0 seems logical, but i would like to know why i can't use this 2 variables that i created. thanks for any help!

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

1. Read about how Java creates instances.

2. Notice that applyEntityAttributes() is called from super-constructor of your entity.

3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles!

4. Ahh... so that's why my entity dies!

EDIT

 

What you need:

Use "static" keyword to make it shared between all entities.

If you need different entities have different health you CANNOT use "SharedMonsterAttributes" - notice word "Shared".

To achieve different values (and make them sync automatically) for different you need to apply AttributeModifier to entity after it's been spawned.

1.7.10 is no longer supported by forge, you are on your own.

Posted

1. Read about how Java creates instances.

2. Notice that applyEntityAttributes() is called from super-constructor of your entity.

3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles!

4. Ahh... so that's why my entity dies!

 

thanks!  ;D

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

1. Read about how Java creates instances.

2. Notice that applyEntityAttributes() is called from super-constructor of your entity.

3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles!

4. Ahh... so that's why my entity dies!

EDIT

 

What you need:

Use "static" keyword to make it shared between all entities.

If you need different entities have different health you CANNOT use "SharedMonsterAttributes" - notice word "Shared".

To achieve different values (and make them sync automatically) for different you need to apply AttributeModifier to entity after it's been spawned.

 

Thanks Ernio you're the best, it works, thanks for your help! And thanks to you guys for helping me too.

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

I have one last question, how can i get the summoned Entity that if i right-click again the item, the summoned Entity will disappear?

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

Should be noted:

If you don't know yet - Item is singleton, logically speaking "a description of what you are holding". The thing you are actually holding is ItemStack and only ItemStack can hold per-stack data. To save reference to entity in ItemStack you need to use entity.getUniqueId() which can then be saved in ItemStack's NBT as 2 longs (UUID#getMost/LeastSignificantBits()).

Then you can re-reference entity by getting it from saved UUID - World#getEntityById (or similar method, i don't remember).

Do note that entity might not be found (unloaded), might only be found on server (client is too far to see entity) or other expected or not behaviours - that all needs to be handled properly.

1.7.10 is no longer supported by forge, you are on your own.

Posted

Or.. If im reading you right there could only be one summoned entity, then tell all entities that have the player as caster to disappear?

Not all things in the world are red, there are round objects too!

Posted

Should be noted:

If you don't know yet - Item is singleton, logically speaking "a description of what you are holding". The thing you are actually holding is ItemStack and only ItemStack can hold per-stack data. To save reference to entity in ItemStack you need to use entity.getUniqueId() which can then be saved in ItemStack's NBT as 2 longs (UUID#getMost/LeastSignificantBits()).

Then you can re-reference entity by getting it from saved UUID - World#getEntityById (or similar method, i don't remember).

Do note that entity might not be found (unloaded), might only be found on server (client is too far to see entity) or other expected or not behaviours - that all needs to be handled properly.

 

getEntityByID needs a Int but UUID is a String, so i can't use it.

is there any method to get a Entity by his UUID?

because there is just a method for player UUID, i changed the item class now its saving the UUID of the Entity but i can't do anything with the UUID, when there is no Method for it.

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

Ah, I used bad naming, getEntityByID uses "network" IDs used to sync server and client entity data.

It's just that I have my own utilitiy method that does it for UUID (thus, my confusion).

 

Anyway:

World isntance has "loadedEntityList".

You need to make utility method that will take UUID and return Entity.

Then in that method you will iterate through all entities ("loadedEntityList") and check if entity.getUniqueId().equals(paramUUID), if so - return entity.

 

As one could expect - retrieving UUID from ItemStack's NBT, converting it from 2 longs to "new UUID(least, most)" and then comparing it to list of ALL entities (until found) MIGHT be a little overhead if not used with care - so if you'd ever use it in future to manage per-tick actions - try caching refernce at all cost (not quite possible with ItemStacks).

1.7.10 is no longer supported by forge, you are on your own.

Posted

WorldServer has a method getEntityFromUuid.

 

yes, but the problem is, that the UUID that i save into the Item NBT-Tag, is a String, and getEntityFromUuid needs a UUID, so how can i check that?

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

Ah, I used bad naming, getEntityByID uses "network" IDs used to sync server and client entity data.

It's just that I have my own utilitiy method that does it for UUID (thus, my confusion).

 

Anyway:

World isntance has "loadedEntityList".

You need to make utility method that will take UUID and return Entity.

Then in that method you will iterate through all entities ("loadedEntityList") and check if entity.getUniqueId().equals(paramUUID), if so - return entity.

 

As one could expect - retrieving UUID from ItemStack's NBT, converting it from 2 longs to "new UUID(least, most)" and then comparing it to list of ALL entities (until found) MIGHT be a little overhead if not used with care - so if you'd ever use it in future to manage per-tick actions - try caching refernce at all cost (not quite possible with ItemStacks).

 

i tried to make a method how you said but im getting errors could you give me an example how you did that?

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

UUID#fromString and UUID#toString? Or, using long values instead:

// Writing to NBT:
compound.setLong("YourUUIDMost", uuid.getMostSignificantBits());
compound.setLong("YourUUIDLeast", uuid.getLeastSignificantBits());

// Recreating from NBT:
UUID uuid = new UUID(compound.getLong("YourUUIDMost"), compound.getLong("YourUUIDLeast"));

Posted

UUID#fromString and UUID#toString? Or, using long values instead:

// Writing to NBT:
compound.setLong("YourUUIDMost", uuid.getMostSignificantBits());
compound.setLong("YourUUIDLeast", uuid.getLeastSignificantBits());

// Recreating from NBT:
UUID uuid = new UUID(compound.getLong("YourUUIDMost"), compound.getLong("YourUUIDLeast"));

 

i made an method to return the entity when the UUID is the same with the one that is saved to the NBT, but it seems that its not working it seems that the UUID is not the same with the saved UUID.

 

public static Entity getSummonedEntity(){

    World world = Minecraft.getMinecraft().theWorld;

    int i = 0;

    ItemStack stack = Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem();

    //Entity entity2 = (Entity)world.loadedEntityList.get();

    if(world.loadedEntityList != null){

    for (i = 0; i < world.loadedEntityList.size(); i++)

    {

    if (((Entity)world.loadedEntityList.get(i)) instanceof EntityNikora)

    {

    System.out.println("NIKORA FOUND");

    if (((Entity)world.loadedEntityList.get(i)).getUniqueID().toString().equals(getUUID(stack)))

    {

    System.out.println("NIKORA UUID CHECKED");

    Entity entity = (Entity)world.loadedEntityList.get(i);

    return entity;

    }

    }

    }

    }

return (Entity)world.loadedEntityList.get(i);

    }

 

 

This line isn't called, so it seems that the EntityUUID is not the same, could somebody tell me why?

System.out.println("NIKORA UUID CHECKED");

 

and here the getUUID method:

public static String getUUID(ItemStack stack){
    	NBTTagCompound nbtTagCompound = stack.getTagCompound();
    	if (nbtTagCompound != null){
    	return nbtTagCompound.getString("UUID");
    	}
    	else return "";
    }

 

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

No, No, No, No...

 

Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server.

 

public static UUID getUUID(ItemStack stack)
{
    NBTTagCompound nbt = stack.getTagCompound();
    if (nbtTagCompound != null)
    {
        return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits
    }
    return null;
}

In your Item class you need to write data to NBT on usage:

UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to.
nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack.
nbt.setLong("LSB", uuid.getLeastSignificantBits());

 

Getting actual ref:

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
if (!world.isRemote) // UUIDs ONLY exist on server (not counting players)
{
	UUID uuid = getUUID(itemStack); // 1st method in post
	Entity entity = ((WorldServer) world).getEntityFromUuid(uuid);

 

Do note that srcs above are unsafe and need null handling for NBT/entity/uuid.

1.7.10 is no longer supported by forge, you are on your own.

Posted

No, No, No, No...

 

Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server.

 

public static UUID getUUID(ItemStack stack)
{
    NBTTagCompound nbt = stack.getTagCompound();
    if (nbtTagCompound != null)
    {
        return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits
    }
    return null;
}

In your Item class you need to write data to NBT on usage:

UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to.
nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack.
nbt.setLong("LSB", uuid.getLeastSignificantBits());

 

Getting actual ref:

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
if (!world.isRemote) // UUIDs ONLY exist on server (not counting players)
{
	UUID uuid = getUUID(itemStack); // 1st method in post
	Entity entity = ((WorldServer) world).getEntityFromUuid(uuid);

 

Do note that srcs above are unsafe and need null handling for NBT/entity/uuid.

 

Thanks, i understand what you mean, i'll try that.

"My Crew is World Wide." 「ヤング • エルトウ」

Posted

No, No, No, No...

 

Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server.

 

public static UUID getUUID(ItemStack stack)
{
    NBTTagCompound nbt = stack.getTagCompound();
    if (nbtTagCompound != null)
    {
        return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits
    }
    return null;
}

In your Item class you need to write data to NBT on usage:

UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to.
nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack.
nbt.setLong("LSB", uuid.getLeastSignificantBits());

 

Getting actual ref:

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
if (!world.isRemote) // UUIDs ONLY exist on server (not counting players)
{
	UUID uuid = getUUID(itemStack); // 1st method in post
	Entity entity = ((WorldServer) world).getEntityFromUuid(uuid);

 

Do note that srcs above are unsafe and need null handling for NBT/entity/uuid.

 

THANKS ERNIO, it works perfectly!

It wasn't that hard to understand, but im wondering what uuid.getMostSignificantBits() &  uuid.getLeastSignificantBits() means, does a UUID have this 2 long variables? Can anyone explain me that? :)

"My Crew is World Wide." 「ヤング • エルトウ」

Guest
This topic is now closed to further replies.

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.