Jump to content

Recommended Posts

Posted

Hello, i need to write some data (boolean) to Entites , i'm not sure how to do it, so far i was using custom name tags  :-X but i'm sure there are better ways to do it, because players can edit name tags. I tried to write nbt but there is only get function for entites.

:D
Posted

diesienben07,

Since she is looking at name tags, she will probably need to sync it to the client.

 

That brings up a question I'm hoping you have some experience with.

 

I set mine up so that when the entity extended data constructed on the client, it send a packet to the server asking to be updated with its latest info.  All the other updates after that works fine.  However, the first one gets ugly because the entity has the wrong ID for a somewhat random time.  So, what I did was set it up so that the extendedproperties kept the entity's Id and watched for it to change.  when it changes, it asks for an update. Most often the initial ID would e something very low, 1, 2, ect and be a minecart.

 

Any advice or experience on that?

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

diesieben07,

one more question on this.  When the client stops tracking the entity, does it deconstruct the entity? 

 

The reason i'm asking is that I'm tracking the valid extended properties on the client in order to do a clientside tick on them  I found 'a' way to do this, but I'm a little fuzzy on when the client destroys the entity and then reconstructs it.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Client logical side has only entites that are loaded by player.

 

If you are (your client) not tracking server's entity, you don't have it's instance (thus, no IEEP). (Edit: So the answer is 'yes').

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

Posted

Thanks you. 

 

 

On a side note, I have a hard time reading the comments next to your post with the shaking dog image. It really pulls your attention away.  Its epic.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

diesieben07,

I implemented this but the onStartTracking method doesn't work. 

 

When i send my packet to client (entityId, and NBT data), the client says the entity doesn't exist yet.  Sure enough, with checking my old code that watches for the client entity ID to update itself, this hasn't happened yet.

 

The server has not informed the client yet of what its entityID should be by the time onStartTracking event has fired for the player on the server.

 

 

Thoughts?

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

http://greyminecraftcoder.blogspot.com.au/2015/01/thread-safety-with-network-messages.html

 

If you implement this, it MUST work.

StartTracking is fired when server's EntityPlayer starts being in range to other entity. It will get called server side and if you ensure thread safety it WILL be handled on client after spawn packet is sent (spawn packet will arrive 1st, then yours will update additional data).

 

If it doesn't - post full code (packets/handlers/event and any other utils) - in new thread. :D

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

Posted

Thanks Ernio,

that was the ticket. 

 

Sorry if I stretched this topic, but I thought it was tied to it and would help the OP.

 

For those that are out there looking for an example packet to update extendedentity data, here you go.

 

 

 

 

package clandoolittle.custom_npc.Common.Utilities.Networking.Packets;

 

import clandoolittle.custom_npc.Custom_NPC;

import clandoolittle.custom_npc.Common.Entities.Data.MyEntityLivingBaseData;

import io.netty.buffer.ByteBuf;

import net.minecraft.client.Minecraft;

import net.minecraft.entity.EntityLivingBase;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraftforge.fml.common.network.ByteBufUtils;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;

import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

 

public class EntityLivingBaseData_Update implements IMessage {

 

// Setup References

    protected static Custom_NPC instance = Custom_NPC.instance;

 

// Setup Variables

    private int ID;

    private NBTTagCompound nbt = new NBTTagCompound();;

 

public EntityLivingBaseData_Update() {

 

}

 

public EntityLivingBaseData_Update(int ID, NBTTagCompound nbt) {

 

// Initialize variables

this.ID = ID;

if (nbt != null) {this.nbt = nbt;}

 

}

 

 

public NBTTagCompound nbt() {

 

return nbt;

 

}

 

public int ID() {

 

return ID;

 

}

 

@Override

public void fromBytes(ByteBuf buffer) {

 

// Read the data

        ID = buffer.readInt();

nbt = ByteBufUtils.readTag(buffer);

 

}

 

@Override

public void toBytes(ByteBuf buffer) {

//System.out.println("  - start");

 

// Write the data

buffer.writeInt(ID);

ByteBufUtils.writeTag(buffer, nbt);

 

 

}

 

 

public static class Handler implements IMessageHandler<EntityLivingBaseData_Update, IMessage> {

       

// Receive the message

        @Override

        public IMessage onMessage(EntityLivingBaseData_Update message, MessageContext ctx) {

               

        // Determine side

        if (ctx.side.isClient()) {

       

        Minecraft.getMinecraft().addScheduledTask(new Scheduled_Update(message, ctx));

       

        } else {

       

        ctx.getServerHandler().playerEntity.getServerForPlayer().addScheduledTask(new Scheduled_Update(message, ctx));

       

        }

       

        // Default Return

        return null;

 

        }

       

       

        public class Scheduled_Update implements Runnable {

       

        // Setup Variables

        private EntityLivingBaseData_Update message;

        private MessageContext ctx;

       

        public Scheduled_Update(EntityLivingBaseData_Update message, MessageContext ctx) {

       

        // Initialize

        this.message = message;

        this.ctx = ctx;

       

        }

 

@Override

public void run() {

 

// Determine side

        if (ctx.side.isClient()) {

       

        // Try and get entity

        EntityLivingBase entityLivingBase = (EntityLivingBase) instance.functions_common().getEntityByID(ctx.side, message.ID());

        if (entityLivingBase != null) {

       

        // Check for properties

        MyEntityLivingBaseData properties = MyEntityLivingBaseData.get(entityLivingBase);

        if (properties != null) {

       

        // read in the nbt

        properties.loadNBTData(message.nbt());

       

        // Add to Entity_Manager

        instance.entity_manager().extendedDataEntities(entityLivingBase);

       

        }

       

        }

       

        } else {

       

        // Try and get entity

        EntityLivingBase entityLivingBase = (EntityLivingBase) instance.functions_common().getEntityByID(ctx.side, message.ID());

        if (entityLivingBase != null) {

       

        // Check for properties

        MyEntityLivingBaseData properties = MyEntityLivingBaseData.get(entityLivingBase);

        if (properties != null) {

       

        // Mark for update to client

        properties.markDirty();

       

        }

       

        }

       

        }

 

       

        }

       

    }

 

}

 

 

 

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

@delpi

Damn, it is hard to even read your code.

It seems like you have some leftover bad habits from Bukkit coding, also there are (at least) 3 mistakes:

 

1. Tracking events are server side ONLY - you don't need additional checks.

 

2. Either I don't understand your design, or it is bad:

* You should NOT manipulate NBT of IEEP on your own.

* IEEP can hold fields and fields > NBT (yes I know NBT is a field, you know what I ment)

 

3. You should NEVER every store Entities in your own list - let World/ForgeEvents take care of everything.

 

EDIT

Delpi, bruh - you edited post :D (pasted wrong class before, my comments are regarding that one).

This one:

 

 

package clandoolittle.custom_npc.Common.Entities;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.event.entity.player.PlayerEvent.StartTracking;
import net.minecraftforge.event.entity.player.PlayerEvent.StopTracking;
import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.relauncher.Side;
import clandoolittle.custom_npc.Custom_NPC;
import clandoolittle.custom_npc.Common.Entities.Data.MyEntityLivingBaseData;
import clandoolittle.custom_npc.Common.Entities.Records.Entity_Record;
import clandoolittle.custom_npc.Common.Entities.Types.Special.Spell_Types.Blind;
import clandoolittle.custom_npc.Common.Entities.Types.Special.Spell_Types.Fireball;
import clandoolittle.custom_npc.Common.Entities.Types.Special.Spell_Types.Nausea;
import clandoolittle.custom_npc.Common.Entities.Types.Special.Spell_Types.Snare;
import clandoolittle.custom_npc.Common.Entities.Types.Special.Spell_Types.Weakness;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Guard_Types.Castle_Guard;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Guard_Types.Dimension_Guard;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Guard_Types.Mercenary;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Guard_Types.Peacekeeper;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Special.Herobrine;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Special.Notch;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Wizard_Types.Apprentice_Wizard;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Wizard_Types.Hedge_Wizard;
import clandoolittle.custom_npc.Common.Entities.Types.Types_Sub.Wizard_Types.High_Wizard;
import clandoolittle.custom_npc.Common.Items.Item.SpawnEggs.Info.My_Spawn_Egg_Info;
import clandoolittle.custom_npc.Common.Utilities.Networking.Packets.EntityLivingBaseData_Update;

public class Entity_Manager {
   
   // Setup References
    protected Custom_NPC instance = Custom_NPC.instance;
   
    // Setup Variables
    private List<Entity_Record> entity_records = new ArrayList<Entity_Record>();
    private int entityID = 0;
    private List<EntityLivingBase> extendedDataEntities = new ArrayList<EntityLivingBase>();
   
    public Entity_Manager() {
       
       // Setup
       register_Entities();
       
    }
   
    public void onStartTracking(StartTracking event, Side side) {
       
       // Check server
       if (side.equals(Side.SERVER)) {
       
          // Get properties
          if (event.target instanceof EntityLivingBase) {
             EntityLivingBase entityLivingBase = (EntityLivingBase) event.target;
             MyEntityLivingBaseData properties = MyEntityLivingBaseData.get(entityLivingBase);
             if (properties != null) {          
                
                // Get NBT
                NBTTagCompound nbt = new NBTTagCompound();
                properties.saveNBTData(nbt);
             
               // Send Packet asking for update
               EntityLivingBaseData_Update packet = new EntityLivingBaseData_Update(entityLivingBase.getEntityId(), nbt);
               instance.simpleNetworkWrapper().sendTo(packet, (EntityPlayerMP) event.entityPlayer);
               
             }
          
          }
       
       } else {
          
       }
         
    }
   
    public void onStopTracking(StopTracking event, Side side) {
       
       // Check server
       if (side.equals(Side.SERVER)) {
          
       } else {
          
       }
       
    }
   
    public void extendedDataEntities(EntityLivingBase entityLivingBase) {
   
       // Check for existing
       if (!extendedDataEntities.contains(entityLivingBase)) {extendedDataEntities.add(entityLivingBase);}
   
    }
   
    public void tick(Side side) {
       
       // Call Ticks
       tick_ExtendedDataEntities(side);
       
    }
   
    public void tick_1sec(Side side) {
       
       // Call Ticks
       tick_1sec_ExtendedDataEntities(side);
       
       if (side.equals(Side.SERVER)) {
          
          entity_records_test();
          
       } else {
          
       }
             
   }   
   
   public void tick_30sec(Side side) {
       
      // Call Ticks
         tick_30sec_ExtendedDataEntities(side);
          
    }
   
    private void tick_ExtendedDataEntities(Side side) {
       
       // Setup Variables
       List<EntityLivingBase> deleteList = new ArrayList<EntityLivingBase>();
       
       // Cycle through list
       for (EntityLivingBase item : extendedDataEntities) {
          
          // Check Status
          if (side.equals(Side.SERVER) && item.isDead) {
             
             // add to list
             deleteList.add(item);
             
          } else {
             
             // Tick
             MyEntityLivingBaseData.get(item).tick(side);
             
          }
          
       }
       
       // remove dead
       extendedDataEntities.removeAll(deleteList);       
       
    }
   
    private void tick_1sec_ExtendedDataEntities(Side side) {
       
       // Setup Variables
       List<EntityLivingBase> deleteList = new ArrayList<EntityLivingBase>();
       
       // Cycle through list
       for (EntityLivingBase item : extendedDataEntities) {
          
          // Check Status
          if (side.equals(Side.SERVER) && item.isDead) {
             
             // add to list
             deleteList.add(item);
             
          } else {
             
             // Tick
             MyEntityLivingBaseData.get(item).tick_1sec(side);
             
          }
          
       }
       
       // remove dead
       extendedDataEntities.removeAll(deleteList);       
       
    }
   
   private void tick_30sec_ExtendedDataEntities(Side side) {
      
      // Check Client
      if (side.equals(Side.CLIENT)) {
      
            // Setup Variables
            List<EntityLivingBase> deleteList = new ArrayList<EntityLivingBase>();
            
            // Cycle through list
            for (EntityLivingBase item : extendedDataEntities) {
               
               // Check Status
               if (instance.functions_common().getEntityByID(Side.CLIENT, item.getEntityId()) == null) {
                  
                   // add to list
                   deleteList.add(item);
                  
               }
               
            }
            
            // remove dead
            extendedDataEntities.removeAll(deleteList);    
            
      }
      
   }

    public void entity_records(Entity entity, int timer) {
       
       // Add the entry
        entity_records.add(new Entity_Record(entity, timer));
       
    }
   
    private void register_Entities() {
       
       // Register Castle Gaurds
       registerEntity(Castle_Guard.class, "Castle_Guard", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Dimension Guards
       registerEntity(Dimension_Guard.class, "Dimension_Guard", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Peacekeeper
       registerEntity(Peacekeeper.class, "Peacekeeper", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Mercenary
       registerEntity(Mercenary.class, "Mercenary", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
              
       // Register High Wizard
       registerEntity(High_Wizard.class, "High_Wizard", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Apprentice Wizard
       registerEntity(Apprentice_Wizard.class, "Apprentice_Wizard", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Hedge Wizard
       registerEntity(Hedge_Wizard.class, "Hedge_Wizard", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Notch
       registerEntity(Notch.class, "Notch", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Herobrine
       registerEntity(Herobrine.class, "Herobrine", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), true);
       
       // Register Spells
       registerEntity(Fireball.class, "Fireball_Large", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), false);
       registerEntity(Snare.class, "Snare", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), false);
       registerEntity(Nausea.class, "Nausea", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), false);
       registerEntity(Blind.class, "Blind", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), false);
       registerEntity(Weakness.class, "Weakness", entityID(), instance.properties_common().mob_track_distance(), instance, instance.modid(), false);
       
       
    } 
   
    // Register a mob
    private void registerEntity(Class entityClass, String name, int entityID, int view_distance, Object mod, String modid, boolean egg) {
             
       // Register Entity
       EntityRegistry.registerModEntity(entityClass, name, entityID, mod, view_distance, 1, true);
       
       // Create egg
       if (egg) {
          
          // Setup Variables
         String nameEgg = "spawn_egg" + "_" + name.toLowerCase() + " from " + modid;
          
         // Register Egg       
         instance.item_manager().my_spawn_egg_info(new My_Spawn_Egg_Info(name));
          
       }
             
    }
   
    private int entityID() {
       
       // Incriment ID up
       entityID++;
       
       return entityID;
       
    }

    private void entity_records_test() {
       
        // Setup Variables
        List<Entity_Record> deletion = new ArrayList<Entity_Record>();

        // cycle through the records
        for (Entity_Record item : entity_records) {
           
           // Test to see if this is final step
            if (item.incriment()) {
               
               // Add to the deltion list
                deletion.add(item);
               
            }
           
        }

        // purge necessary records
        for (Entity_Record item : deletion) {
           
           // Delete the entry
            entity_records.remove(item);
           
        }
       
    }
   
}

 

 

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

Posted

Sorry you don't like my style, I program in a lot of different languages and on control systems and this is what I consistently see and use.  Though you could be right with Java and bukkit influence.

 

The additional check was from before.  Left it in there just for reference.  Not being called.

 

On the NBT, why not.  If i have my read/write statements correct, how is that going to hurt?  Its a lot cleaner of a packet send.  If there is something it will hurt, I'm very interested, I just haven't run into any issues.  I originally wrote the packet to pass all the individual variables like I used to, but it had 20 different variables and it was a PAIN to adjust. 

 

I have a reason for storing a list of entities.  I'm careful with it to make sure they are still real.  The world wouldn't cut it because it is only a list of entities I've chosen.  No automatic cut would return it.  Is there another way to track that?  I guess I could write a tag to all those entities an then cycle through them.  Seems very inefficient in comparison.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

I was joking around.  The ... meant my bad.  Sorry you misinterpreted.  Didn't mean to dodge my goof.

 

For the record, I copy/pasted the wrong tab and didn't realize it.  After it was pointed it out, I fixed it to avoid confusion.

Long time Bukkit & Forge Programmer

Happy to try and help

Guest
This topic is now closed to further replies.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • 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?
  • Topics

×
×
  • Create New...

Important Information

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