Jump to content

[1.8] How to write data to vanilla entities?


Warix

Recommended Posts

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

@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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

Announcements



×
×
  • Create New...

Important Information

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