Jump to content

Function problem-- Screwed up the datawatcher, or lack of a packet?(SOLVED)


Cyan

Recommended Posts

So, I have started on a journey of making a "level up" of sorts for my entities. The problem is, that everytime that you start the game up, the level resets back to 0. Now this seems like to me that the levels are never reaching the server, or perhaps aren't getting back to the client.

 

I thought that a datawatcher would solve the issue, but that doesn't seem to have worked. Is my understanding of what a datawatcher does incorrect, or have I screwed it up somewhere along the way?

 

Here are all the functions that are relevant to my code.

 

public EntityTest(World world)
    {
        super(world);
      dataWatcher.addObject(2, level); // Level
}

public void writeEntityToNBT(NBTTagCompound nbt)
    {
        super.writeEntityToNBT(nbt);
      
          nbt.setShort("level", getLevel());
}

public void readEntityFromNBT(NBTTagCompound nbt)
    {
       super.readEntityFromNBT(nbt);
       setLevel(nbt.getShort("level"));
}

public void onLivingUpdate()
    {
        
        if (getNeededExp() <= 0)
        {
            level++;
            exp = 0;
            dataWatcher.updateObject(2, level); 
            
        }

public void setLevel(short level)
    {
    	dataWatcher.updateObject(2, level);
    }

public short getLevel()
    { 
    	return dataWatcher.getWatchableObjectShort(2);
    }
        
       
public int getExp()
    {
        return exp;
    }

    public int getNeededExp()
    {
        int maxNeeded = baseExp + level * factor;
        return maxNeeded - exp;
    }
        super.onLivingUpdate();
    }

 

Thanks for any insight you may be able to provide.

Link to comment
Share on other sites

You are stuck where I was. It works best when you use the dataWatcher inside the nbt methods. This is how I fixed the situation:

 

package gff.companime.entity.companions;

import java.util.Random;

import gff.companime.Companime;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.DataWatcher;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.ai.EntityAIAvoidEntity;
import net.minecraft.entity.ai.EntityAIFollowGolem;
import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
import net.minecraft.entity.ai.EntityAIMoveIndoors;
import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction;
import net.minecraft.entity.ai.EntityAIOpenDoor;
import net.minecraft.entity.ai.EntityAIPlay;
import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.ai.EntityAITradePlayer;
import net.minecraft.entity.ai.EntityAIVillagerMate;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityAIWatchClosest2;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

public class EntityGal extends EntityAgeable
{
public int haircolor;

public EntityGal(World par1World)
    {
        super(par1World);
        this.texture = "/textures/mob/gal/gal.png";
        this.moveSpeed = 0.5F;
        this.setSize(0.6F, 1.8F);
        this.getNavigator().setBreakDoors(true);
        this.getNavigator().setAvoidsWater(true);
        // AI tasks for the entity to perform
        this.tasks.addTask(0, new EntityAISwimming(this));
        this.tasks.addTask(1, new EntityAITempt(this, 0.3F, Companime.braceletItem.itemID, false));
        this.tasks.addTask(2, new EntityAIMoveIndoors(this));        
        this.tasks.addTask(3, new EntityAIOpenDoor(this, true));
        this.tasks.addTask(4, new EntityAIMoveTwardsRestriction(this, 0.3F));
        this.tasks.addTask(5, new EntityAIWatchClosest2(this, EntityPlayer.class, 3.0F, 1.0F));
        this.tasks.addTask(5, new EntityAIWatchClosest2(this, EntityGal.class, 5.0F, 0.02F));
        this.tasks.addTask(5, new EntityAIWander(this, 0.3F));
        this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityGal.class, 8.0F));
        
        // Generate instance specific data
        Random rnd = new Random();
        this.setHairColor(rnd.nextInt(0xffffff));
        this.haircolor = this.getHairColor();
    }

    public void entityInit()
    {
        super.entityInit();
        // Create a data watcher for hair color
        this.dataWatcher.addObject(20, Integer.valueOf(0));
        
    }

// writes persistent values that is saved to the world server side
    public void writeEntityToNBT(NBTTagCompound nbt)
    {
    	super.writeEntityToNBT(nbt);
    	
    	nbt.setInteger("haircolor", this.getHairColor());  	        	    	
    }
    
// reads a persistant value from the server's world
    public void readEntityFromNBT(NBTTagCompound nbt)
    {
    	super.readEntityFromNBT(nbt);
    	
    	this.setHairColor(nbt.getInteger("haircolor"));        	    	       
    }   
    
    // This function will set an RGB color
    // It is called later with EntityGal.getHairColor() in the renderer
    public void setHairColor(int color)
    {
        this.dataWatcher.updateObject(20, Integer.valueOf(color));
    }
    
    // Returns the value set by setHairColor as "haircolor" in the Entities NBTTagCompound
    public int getHairColor()
    {
        return this.dataWatcher.getWatchableObjectInt(20);
    }
    
@Override
public EntityAgeable createChild(EntityAgeable entityageable) {
	// TODO Auto-generated method stub
	return null;
}

@Override
public int getMaxHealth() {
	// TODO Auto-generated method stub
	return 10;
}

public boolean interact(EntityPlayer par1EntityPlayer)
    {
        ItemStack itemstack = par1EntityPlayer.inventory.getCurrentItem();
        
        System.out.println(this.worldObj);
        System.out.println("ID: "+this.entityId);
        System.out.println("isRemote = "+this.worldObj.isRemote);
        System.out.println(this.haircolor); // Example of how to get this entity haircolor
        return true;
    }

}

Link to comment
Share on other sites

Actually, a packet that is sent from the server to the client everytime the player "relogs" the world (logs in again) containing the information wanted is all you need. (I think... I am pretty sure its that)

I am Mew. The Legendary Psychic. I behave oddly and am always playing practical jokes.

 

I have also found that I really love making extremely long and extremely but sometimes not so descriptive variables. Sort of like what I just did there xD

Link to comment
Share on other sites

I'm new here so forgive me if I'm wrong, but the guidlines for SMP modding suggests datawatchers over packets. I was under the impression that using datawatchers was the best way when dealing with NBT persistent data. Perhaps the guidelines are out of date. Is the DataWatcher class being depreciated in favor of packets?

 

Entities (that aren't EntityItem)

 

Yes. At the very least, you need to tell Forge to register an EntityTracker for clients to receive spawn packets about your Entities. Whenever your mod spawns an Entity, make sure the World is not a remote World (so worldObj.isRemote must be false), or you will have a dummy dupe Entity.

You will usually need to network field values from server to client (prominent vanilla example being taming). Read the vanilla code on DataWatchers, the Wolf taming code is an excellent learning example. Use DataWatchers whenever possible. When selecting a value for your DataWatcher better leave space to the Overclasses DataWatcher values - you never know if and when they decide to occupy more numbers. Hint: Make sure the client cannot *write* to dataWatchers or there will be a merciless update battle.

For stuff you absolutely cannot do through dataWatchers, perhaps because response time is critical, read up on Forge Packets and how to use them.

If you implement the Forge ISpawnHandler Interface, it will automatically pass an additional ByteStream to newly spawned Entities of yours, and you can put anything you desire and need into that stream.

Remember: Your client simulates any given Entity with basically the same code the server is running. But it needs to have the same data! So if your World changes something in your Entity, make sure the client gets notified about it!

 

http://www.minecraftforge.net/wiki/SMP_Coding_Guidelines

Link to comment
Share on other sites

The suggestions from the guideline there was kinda my train of thought as well. Unfortunately I still have had no success, even after incorporating the datawatchers into the nbt methods.

 

I guess that leaves me with trying a packet, but that is sort of my weak point in coding so far. All my packet does it crash :D, more likely because I am just plain doing it wrong.

 

I already have the channel and packethandler set up correctly, but if anyone would like to help me write out the actual packet for this mess as something I could go by, I would be extremely grateful.

 

 

Link to comment
Share on other sites

Have you looked at http://www.minecraftforge.net/wiki/Packet_Handling? I still think datawatcher is a  superior means, you are just confused on how to use them like I was. Here's all I went through so far... maybe it'll be of assistance:

 

If you are using Eclipse and have a solid understanding of Java, the magical groking tool is Ctrl+H. you can search for already existing methods in the mods, minecraft, and minecraftforge packages. It will highlight the search term in each java file it finds as well as make little boxes on the right hand side next to the scroll bar, showing you exactly where in the source the words appear in the open java file.

 

Also, ctrl+F is the find type search it does the same but for the open java file. In an open java file you can click the mouse cursor over a single word, like a class name, field, or method it will highlight each instance of that word in the open .java file just like when you use the ctrl+H.

 

Also, know java intimately... or at least as well as a good friend. I'm not making any assumptions on anyone's skills but it's detrimental.

 

That said, use those techniques to look at the EntityPlayer.java file. It may help you get a method that works for you better as you'll have an good understanding.

 

This is a simplified break down of using datawatchers with the Entity NBT read/write methods. It's written with the intent to be a tutorial so don't take it personally if you already know it all. Otherwise, pay attention to the comments I made in it for usage and tips. Feel free to ask about anything but I want you to work hard on your own with this. Even if it takes you days to get something you'll learn so much more on your own getting in touch with the source on a personal level. Zen Programming.

 

package yourname.yourmod.client.renderer.entity;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

public class EntityThingy extends Entity// Replace Entity with the parent class you are extending your Entity from.
// I did this to make sure you are paying attention to my commented lines! 

// This is not needed but allows you to access the data with this.persistantValue
    // though you can use the getValue method to the same ends. 
    public int aValue; // the data you wish to save. 
    

public EntityThingy(World par1World)
    {
        super(par1World);
               
        this.setValue(42);
        
        // again this isn't really needed as the this.getValue() method will return the value
        // but I used it in my example.
        this.aValue = this.getValue();
    }

    public void entityInit()
    {
    	// note: you cannot do this super with Entity as the parent class
    	// as it's an abstract class with no constructor. However, if you
    	// use a non abstract entity to base your own on, make sure you use
    	// super to invoke the original entityInit.
    	// Again: just making sure you are reading these and not in hypergleen mode.
    	super.entityInit(); 
        
        // Create a data watcher for the value
        
        this.dataWatcher.addObject(20, Integer.valueOf(0));
        // the 20 is the id... it cannot use a value the parent class
        // you are extending from uses. 
        // In this example the Entity class already has a data watcher, access through this.datawatcher.
        // It uses 0 and 1... so don't use them...
        
        //the maximum id is 31... use
        // it wisely.
        
    } 
    
    // only call a get/set method for any data you need in read/writeEntityToNBT 
    // or maybe where isRemote is false and if you know where/when you need it!!!
    // This is where most confusion from datawatchers comes from in my experience.
    public void setValue(int value)
    {
        
        this.dataWatcher.updateObject(20, Integer.valueOf(value));
    }

    public int getValue()
    {
        return this.dataWatcher.getWatchableObjectInt(20);
    }
    
        // Here are the parts that make it work. Note all the work is being done in the NBT reader/writer method.
    // This is important as they only work from the Server, they don't fire from the Client. That would cause
    // an exception to be thrown in the data watcher
    
// writes persistent values that is saved to the world server side
    // Again, due to the fact that Entity is abstract, it cannot be supered 
    // so make sure you use the class you need in your own EntityThingy... or whatever you call it.
    public void writeEntityToNBT(NBTTagCompound nbt)
    {
    	super.writeEntityToNBT(nbt);
    	
    	nbt.setInteger("Value", this.getValue());  	    	
    }
    
// reads a persistant value from the server's world
    public void readEntityFromNBT(NBTTagCompound nbt)
    {
    	super.readEntityFromNBT(nbt);
    	
    	this.setValue(nbt.getInteger("Value"));        	    	       
    }  

}

 

I hope this serves as a solid, simple, and good example. You'll have to come up with the personal implementation of course.

Link to comment
Share on other sites

[hidden]

Have you looked at http://www.minecraftforge.net/wiki/Packet_Handling? I still think datawatcher is a  superior means, you are just confused on how to use them like I was. Here's all I went through so far... maybe it'll be of assistance:

 

If you are using Eclipse and have a solid understanding of Java, the magical groking tool is Ctrl+H. you can search for already existing methods in the mods, minecraft, and minecraftforge packages. It will highlight the search term in each java file it finds as well as make little boxes on the right hand side next to the scroll bar, showing you exactly where in the source the words appear in the open java file.

 

Also, ctrl+F is the find type search it does the same but for the open java file. In an open java file you can click the mouse cursor over a single word, like a class name, field, or method it will highlight each instance of that word in the open .java file just like when you use the ctrl+H.

 

Also, know java intimately... or at least as well as a good friend. I'm not making any assumptions on anyone's skills but it's detrimental.

 

That said, use those techniques to look at the EntityPlayer.java file. It may help you get a method that works for you better as you'll have an good understanding.

 

This is a simplified break down of using datawatchers with the Entity NBT read/write methods. It's written with the intent to be a tutorial so don't take it personally if you already know it all. Otherwise, pay attention to the comments I made in it for usage and tips. Feel free to ask about anything but I want you to work hard on your own with this. Even if it takes you days to get something you'll learn so much more on your own getting in touch with the source on a personal level. Zen Programming.

 

package yourname.yourmod.client.renderer.entity;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

public class EntityThingy extends Entity// Replace Entity with the parent class you are extending your Entity from.
// I did this to make sure you are paying attention to my commented lines! 

// This is not needed but allows you to access the data with this.persistantValue
    // though you can use the getValue method to the same ends. 
    public int aValue; // the data you wish to save. 
    

public EntityThingy(World par1World)
    {
        super(par1World);
               
        this.setValue(42);
        
        // again this isn't really needed as the this.getValue() method will return the value
        // but I used it in my example.
        this.aValue = this.getValue();
    }

    public void entityInit()
    {
    	// note: you cannot do this super with Entity as the parent class
    	// as it's an abstract class with no constructor. However, if you
    	// use a non abstract entity to base your own on, make sure you use
    	// super to invoke the original entityInit.
    	// Again: just making sure you are reading these and not in hypergleen mode.
    	super.entityInit(); 
        
        // Create a data watcher for the value
        
        this.dataWatcher.addObject(20, Integer.valueOf(0));
        // the 20 is the id... it cannot use a value the parent class
        // you are extending from uses. 
        // In this example the Entity class already has a data watcher, access through this.datawatcher.
        // It uses 0 and 1... so don't use them...
        
        //the maximum id is 31... use
        // it wisely.
        
    } 
    
    // only call a get/set method for any data you need in read/writeEntityToNBT 
    // or maybe where isRemote is false and if you know where/when you need it!!!
    // This is where most confusion from datawatchers comes from in my experience.
    public void setValue(int value)
    {
        
        this.dataWatcher.updateObject(20, Integer.valueOf(value));
    }

    public int getValue()
    {
        return this.dataWatcher.getWatchableObjectInt(20);
    }
    
        // Here are the parts that make it work. Note all the work is being done in the NBT reader/writer method.
    // This is important as they only work from the Server, they don't fire from the Client. That would cause
    // an exception to be thrown in the data watcher
    
// writes persistent values that is saved to the world server side
    // Again, due to the fact that Entity is abstract, it cannot be supered 
    // so make sure you use the class you need in your own EntityThingy... or whatever you call it.
    public void writeEntityToNBT(NBTTagCompound nbt)
    {
    	super.writeEntityToNBT(nbt);
    	
    	nbt.setInteger("Value", this.getValue());  	    	
    }
    
// reads a persistant value from the server's world
    public void readEntityFromNBT(NBTTagCompound nbt)
    {
    	super.readEntityFromNBT(nbt);
    	
    	this.setValue(nbt.getInteger("Value"));        	    	       
    }  

}

 

I hope this serves as a solid, simple, and good example. You'll have to come up with the personal implementation of course.

[/hidden]

 

I wasn't saying use a packet for EVERYTHING, I was saying that I use a packet to update the client from its "dumb" stage to a slightly knowledgable level so that the client displays correct data. I am not entirely sure about datawatchers and if they update the client or not...

I am Mew. The Legendary Psychic. I behave oddly and am always playing practical jokes.

 

I have also found that I really love making extremely long and extremely but sometimes not so descriptive variables. Sort of like what I just did there xD

Link to comment
Share on other sites

[hidden]

Have you looked at http://www.minecraftforge.net/wiki/Packet_Handling? I still think datawatcher is a  superior means, you are just confused on how to use them like I was. Here's all I went through so far... maybe it'll be of assistance:

 

If you are using Eclipse and have a solid understanding of Java, the magical groking tool is Ctrl+H. you can search for already existing methods in the mods, minecraft, and minecraftforge packages. It will highlight the search term in each java file it finds as well as make little boxes on the right hand side next to the scroll bar, showing you exactly where in the source the words appear in the open java file.

 

Also, ctrl+F is the find type search it does the same but for the open java file. In an open java file you can click the mouse cursor over a single word, like a class name, field, or method it will highlight each instance of that word in the open .java file just like when you use the ctrl+H.

 

Also, know java intimately... or at least as well as a good friend. I'm not making any assumptions on anyone's skills but it's detrimental.

 

That said, use those techniques to look at the EntityPlayer.java file. It may help you get a method that works for you better as you'll have an good understanding.

 

This is a simplified break down of using datawatchers with the Entity NBT read/write methods. It's written with the intent to be a tutorial so don't take it personally if you already know it all. Otherwise, pay attention to the comments I made in it for usage and tips. Feel free to ask about anything but I want you to work hard on your own with this. Even if it takes you days to get something you'll learn so much more on your own getting in touch with the source on a personal level. Zen Programming.

 

package yourname.yourmod.client.renderer.entity;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

public class EntityThingy extends Entity// Replace Entity with the parent class you are extending your Entity from.
// I did this to make sure you are paying attention to my commented lines! 

// This is not needed but allows you to access the data with this.persistantValue
    // though you can use the getValue method to the same ends. 
    public int aValue; // the data you wish to save. 
    

public EntityThingy(World par1World)
    {
        super(par1World);
               
        this.setValue(42);
        
        // again this isn't really needed as the this.getValue() method will return the value
        // but I used it in my example.
        this.aValue = this.getValue();
    }

    public void entityInit()
    {
    	// note: you cannot do this super with Entity as the parent class
    	// as it's an abstract class with no constructor. However, if you
    	// use a non abstract entity to base your own on, make sure you use
    	// super to invoke the original entityInit.
    	// Again: just making sure you are reading these and not in hypergleen mode.
    	super.entityInit(); 
        
        // Create a data watcher for the value
        
        this.dataWatcher.addObject(20, Integer.valueOf(0));
        // the 20 is the id... it cannot use a value the parent class
        // you are extending from uses. 
        // In this example the Entity class already has a data watcher, access through this.datawatcher.
        // It uses 0 and 1... so don't use them...
        
        //the maximum id is 31... use
        // it wisely.
        
    } 
    
    // only call a get/set method for any data you need in read/writeEntityToNBT 
    // or maybe where isRemote is false and if you know where/when you need it!!!
    // This is where most confusion from datawatchers comes from in my experience.
    public void setValue(int value)
    {
        
        this.dataWatcher.updateObject(20, Integer.valueOf(value));
    }

    public int getValue()
    {
        return this.dataWatcher.getWatchableObjectInt(20);
    }
    
        // Here are the parts that make it work. Note all the work is being done in the NBT reader/writer method.
    // This is important as they only work from the Server, they don't fire from the Client. That would cause
    // an exception to be thrown in the data watcher
    
// writes persistent values that is saved to the world server side
    // Again, due to the fact that Entity is abstract, it cannot be supered 
    // so make sure you use the class you need in your own EntityThingy... or whatever you call it.
    public void writeEntityToNBT(NBTTagCompound nbt)
    {
    	super.writeEntityToNBT(nbt);
    	
    	nbt.setInteger("Value", this.getValue());  	    	
    }
    
// reads a persistant value from the server's world
    public void readEntityFromNBT(NBTTagCompound nbt)
    {
    	super.readEntityFromNBT(nbt);
    	
    	this.setValue(nbt.getInteger("Value"));        	    	       
    }  

}

 

I hope this serves as a solid, simple, and good example. You'll have to come up with the personal implementation of course.

[/hidden]

 

I wasn't saying use a packet for EVERYTHING, I was saying that I use a packet to update the client from its "dumb" stage to a slightly knowledgable level so that the client displays correct data. I am not entirely sure about datawatchers and if they update the client or not...

 

I didn't think you did say that mate, sorry you thought I meant something by it. It's all good.

 

Yeah data watchers update in my example. It's kinda-sorta like a pointer... the trick is declaring it in the Init so that you kinda have that pointer to the client and having the NBT read/write do the work server side. you can either call the Entity.getValue() function or set the getValue() to a field in it if you'd rather not have to keep calling the getValue() method to retrieve persistent data. Also, this is exactly how vanilla does it.

Link to comment
Share on other sites

Ahh. I see now :D I may use this more often now... Thanks for that mate :D

I am Mew. The Legendary Psychic. I behave oddly and am always playing practical jokes.

 

I have also found that I really love making extremely long and extremely but sometimes not so descriptive variables. Sort of like what I just did there xD

Link to comment
Share on other sites

[hidden]

Have you looked at http://www.minecraftforge.net/wiki/Packet_Handling? I still think datawatcher is a  superior means, you are just confused on how to use them like I was. Here's all I went through so far... maybe it'll be of assistance:

 

If you are using Eclipse and have a solid understanding of Java, the magical groking tool is Ctrl+H. you can search for already existing methods in the mods, minecraft, and minecraftforge packages. It will highlight the search term in each java file it finds as well as make little boxes on the right hand side next to the scroll bar, showing you exactly where in the source the words appear in the open java file.

 

Also, ctrl+F is the find type search it does the same but for the open java file. In an open java file you can click the mouse cursor over a single word, like a class name, field, or method it will highlight each instance of that word in the open .java file just like when you use the ctrl+H.

 

Also, know java intimately... or at least as well as a good friend. I'm not making any assumptions on anyone's skills but it's detrimental.

 

That said, use those techniques to look at the EntityPlayer.java file. It may help you get a method that works for you better as you'll have an good understanding.

 

This is a simplified break down of using datawatchers with the Entity NBT read/write methods. It's written with the intent to be a tutorial so don't take it personally if you already know it all. Otherwise, pay attention to the comments I made in it for usage and tips. Feel free to ask about anything but I want you to work hard on your own with this. Even if it takes you days to get something you'll learn so much more on your own getting in touch with the source on a personal level. Zen Programming.

 

package yourname.yourmod.client.renderer.entity;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

public class EntityThingy extends Entity// Replace Entity with the parent class you are extending your Entity from.
// I did this to make sure you are paying attention to my commented lines! 

// This is not needed but allows you to access the data with this.persistantValue
    // though you can use the getValue method to the same ends. 
    public int aValue; // the data you wish to save. 
    

public EntityThingy(World par1World)
    {
        super(par1World);
               
        this.setValue(42);
        
        // again this isn't really needed as the this.getValue() method will return the value
        // but I used it in my example.
        this.aValue = this.getValue();
    }

    public void entityInit()
    {
    	// note: you cannot do this super with Entity as the parent class
    	// as it's an abstract class with no constructor. However, if you
    	// use a non abstract entity to base your own on, make sure you use
    	// super to invoke the original entityInit.
    	// Again: just making sure you are reading these and not in hypergleen mode.
    	super.entityInit(); 
        
        // Create a data watcher for the value
        
        this.dataWatcher.addObject(20, Integer.valueOf(0));
        // the 20 is the id... it cannot use a value the parent class
        // you are extending from uses. 
        // In this example the Entity class already has a data watcher, access through this.datawatcher.
        // It uses 0 and 1... so don't use them...
        
        //the maximum id is 31... use
        // it wisely.
        
    } 
    
    // only call a get/set method for any data you need in read/writeEntityToNBT 
    // or maybe where isRemote is false and if you know where/when you need it!!!
    // This is where most confusion from datawatchers comes from in my experience.
    public void setValue(int value)
    {
        
        this.dataWatcher.updateObject(20, Integer.valueOf(value));
    }

    public int getValue()
    {
        return this.dataWatcher.getWatchableObjectInt(20);
    }
    
        // Here are the parts that make it work. Note all the work is being done in the NBT reader/writer method.
    // This is important as they only work from the Server, they don't fire from the Client. That would cause
    // an exception to be thrown in the data watcher
    
// writes persistent values that is saved to the world server side
    // Again, due to the fact that Entity is abstract, it cannot be supered 
    // so make sure you use the class you need in your own EntityThingy... or whatever you call it.
    public void writeEntityToNBT(NBTTagCompound nbt)
    {
    	super.writeEntityToNBT(nbt);
    	
    	nbt.setInteger("Value", this.getValue());  	    	
    }
    
// reads a persistant value from the server's world
    public void readEntityFromNBT(NBTTagCompound nbt)
    {
    	super.readEntityFromNBT(nbt);
    	
    	this.setValue(nbt.getInteger("Value"));        	    	       
    }  

}

 

I hope this serves as a solid, simple, and good example. You'll have to come up with the personal implementation of course.

[/hidden]

 

I wasn't saying use a packet for EVERYTHING, I was saying that I use a packet to update the client from its "dumb" stage to a slightly knowledgable level so that the client displays correct data. I am not entirely sure about datawatchers and if they update the client or not...

 

I actually had no idea about the ctrl+h. That has become very nifty. Thank you. I have been experimenting all weekend with this to see if I can use the entityInit, and did not get any results. I tried with both an abstract class and a non abstract class for the heck of it, and I would get issues preventing the entities from spawning.

 

I'm going to put up my whole entity file this time in hopes that it may be more useful, because I am kind of getting desperate to figure out why this reset is occurring.

 

Note that this is BEFORE I began experimenting, so this is without the entityInit in it.

(Also pay no attention to the tileentity portions. They are severely out of date)

 

EntityDigimon

 

public abstract class EntityDigimon extends EntityDigimonEvolution //This is extension is just a bunch of variables,
																// but it goes on to extend EntityTameable
{

 protected EntityDigimonAISit digimonaiSit = new EntityDigimonAISit(this);
    
public EntityDigimon(World world)
    {
        super(world);
      dataWatcher.addObject(2, level); // Level
      dataWatcher.addObject(3, ""); // Nickname
      dataWatcher.addObject(4, ""); //Name
      dataWatcher.addObject(7, (short) 0); //Tamed check
      
    
      
      this.tasks.addTask(1, new EntityDigimonAISwimming(this));
      this.tasks.addTask(2, this.digimonaiSit);
      this.tasks.addTask(3, new EntityDigimonAIFollowOwner(this, this.moveSpeed, 30.0F, 15.0F));
      this.tasks.addTask(4, new EntityDigimonAIAttackOnCollide(this, 0.25F, false));
      this.tasks.addTask(5, new EntityDigimonAITempt(this, 0.3F, digimobs.acorn.itemID, false));
      this.tasks.addTask(6, new EntityDigimonAIWander(this, 0.2F));
      this.tasks.addTask(7, new EntityDigimonAIWatchClosest(this, EntityPlayer.class, 6.0F));
      this.tasks.addTask(7, new EntityDigimonAILookIdle(this));
      this.targetTasks.addTask(1, new EntityDigimonAIOwnerHurtByTarget(this));
      this.targetTasks.addTask(2, new EntityDigimonAIOwnerHurtTarget(this));
      this.targetTasks.addTask(3, new EntityDigimonAIHurtByTarget(this, true));
      newDigimon();
        
       

    }


    public void newDigimon()
    {
    	  dataWatcher.updateObject(2, level);
    	//level = 0;
        name = EntityList.getEntityString(this);
        baseExp = 5;
        baseatk = 1;
        factor = 2;
        owner = "";
        nickname = getNickname();
        minimumRange = 4;
        maximumRange = 6;
       // setLevel((short)(rand.nextInt(4) + 1)); //this will make levels 1-4  rand.nextInt(M-m+1)+m; M= max level m= min level
        exp = 0;
        health = baseHealth = 6;
        health = getMaxHealth();
        attackCounter = 0;
        sitting = false;
        inXros = false;
        home = new Vector3(0, 0, 0);
        atHome = false;
        npc = false;
        range = 2.0F;
      
    }
    
   
    
    public EntityDigimonAISit sittingAI()
    {
        return this.digimonaiSit;
    }


    public EntityDigimon isNpc()
    {
        npc = true;
        return this;
    }

    protected void fall(float f)
    {
        if (!isTamed())
        {
            super.fall(f);
            return;
        }
    }

    public void writeEntityToNBT(NBTTagCompound nbt)
    {
        super.writeEntityToNBT(nbt);
      
        nbt.setDouble("homeX", home.X);
        nbt.setDouble("homeY", home.Y);
        nbt.setDouble("homeZ", home.Z);
        nbt.setShort("level", getLevel());
        nbt.setString("name", dataWatcher.getWatchableObjectString(4));
        nbt.setString("nickname", dataWatcher.getWatchableObjectString(3));
        nbt.setShort("tamed", dataWatcher.getWatchableObjectShort(7));
        nbt.setInteger("exp", exp);
        nbt.setBoolean("sitting", sitting);
        nbt.setBoolean("inXros", inXros);
        nbt.setBoolean("atHome", atHome);
        nbt.setFloat("Hunger", hunger);
        

       
    }
    
   

    public void readEntityFromNBT(NBTTagCompound nbt)
    {
       super.readEntityFromNBT(nbt);
       setLevel(nbt.getShort("level"));
       dataWatcher.updateObject(4, nbt.getString("Name"));

	if (nbt.hasKey("nickname"))
		dataWatcher.updateObject(3, nbt.getString("nickname"));
        dataWatcher.updateObject(3, nbt.getString("nickname"));;
        dataWatcher.updateObject(7, nbt.getShort("tamed"));;
        exp = nbt.getInteger("exp");
        sitting = nbt.getBoolean("sitting");
        inXros = nbt.getBoolean("inXros");
        home = new Vector3(nbt.getDouble("homeX"), nbt.getDouble("homeY"),
                nbt.getDouble("homeZ"));
        atHome = nbt.getBoolean("atHome");
        hunger = nbt.getFloat("hunger");
        if (health == 0)
        {
            health = getMaxHealth();
        }

        
    }
    
    
    public Vector3 getHome()
    {
        return home;
    }

    public void attackEntity(Entity entity, float f)
    {
        if (attackTime <= 0 && f < range && entity.boundingBox.maxY > boundingBox.minY && entity.boundingBox.minY < boundingBox.maxY)
        {
            entity.attackEntityFrom(DamageSource.causeMobDamage(this), getAttack());
            attackTime = 20;
        }
    }
    
    public boolean attackEntityAsMob(Entity entity)
    {
        
        return  entity.attackEntityFrom(DamageSource.causeMobDamage(this), getAttack());
    }
    
    public boolean attackEntityFrom(DamageSource damagesource, int i)
    {
      /*  if (damagesource == digimobs.ropeCapture)
        {
            i = getMaxHealth() / 5;

            if (i >= health)
            {
                i = health - 1;
            }
        }*/

        Entity entity = damagesource.getEntity();

        if (isTamed() && entity instanceof EntityPlayer)
        {
            if (rand.nextInt(3) == 2)
            {
                dropItem(digimobs.digitear.itemID, 1);
            }
        }
        else
        {
            setTarget(entity);
        }

        i = calculateDefense(i);

       /* if  ( health == level/4)
        {
            prepareToTame();
        }
*/
        return super.attackEntityFrom(damagesource, i);
    }

    public void prepareToTame()
    {
        readyToTame = true;
        timeToTame = 200;
    }


    public boolean isHome()
    {
        return atHome;
    }

    public void setAtHome(boolean b)
    {
        atHome = b;
    }
  
    public int calculateDefense(int i)
    {
        int j = level / 10;
        return j >= i ? 0 : i - j;
    }
    
    

    public int getMaxHealth()
    {
        return level / 2 + baseHealth; // Baby 4, Intraining 7, Rookie 12, Champion 17, Ultimate 27, Mega 42
    }

    public void lureMonsters()
    {
        List list = worldObj.getEntitiesWithinAABB(EntityMob.class,
                boundingBox.expand(10D, 10D, 10D));

        for (int i = 0; i < list.size(); i++)
        {
        	
            EntityMob mob = (EntityMob) list.get(i);

          /*\  if (mob instanceof EntitySpider)
            {
                if (worldObj.isDaytime()
                        && mob.entityToAttack != ModLoader
                        .getMinecraftInstance().thePlayer)
                {
                    continue;
                }
            }

            mob.entityToAttack = this;*/
        }
    }

    public void onLivingUpdate()
    {
        if (worldObj.getBlockTileEntity((int) posX, (int) posY - 1, (int) posZ) instanceof TileEntityDigiCage
                && !isTamed())
        {
            TileEntityDigiCage cage = (TileEntityDigiCage) worldObj
                    .getBlockTileEntity((int) posX, (int) posY - 1, (int) posZ);

            if (cage.hasAcorn())
            {
                cage.hasAcorn = false;
                tame(ModLoader.getMinecraftInstance().thePlayer);
                if(entityToAttack==null && isSitting())setPathToEntity(worldObj.getPathEntityToEntity (this,getOwner(),24F,true,false,false,true));
            }
        }

        lureMonsters();

        
        if (getNeededExp() <= 0)
        {
            level++;
            exp = 0;
            dataWatcher.updateObject(2, level); 
            
        }
        
       

        super.onLivingUpdate();
    }

    public void onUpdate()
    {
        if (timeToTame > 0)
        {
            timeToTame--;

            if (timeToTame <= 0)
            {
                readyToTame = false;
            }
        }

        if (!readyToTame)
        {
            super.onUpdate();
        }
        else
        {
            for (int i = 0; i < 7; i++)
            {
                double d = rand.nextGaussian() * 0.02D;
                double d1 = rand.nextGaussian() * 0.02D;
                double d2 = rand.nextGaussian() * 0.02D;
                worldObj.spawnParticle("crit", (posX + (double)(rand.nextFloat() * width * 2.0F)) - (double)width, posY + 0.5D + (double)(rand.nextFloat() * height), (posZ + (double)(rand.nextFloat() * width * 2.0F)) - (double)width, d, d1, d2);
            }
        }

        if (isTamed() && entityToAttack instanceof EntityPlayer)
        {
            entityToAttack = null;
        }
        
       // if (tamed && hunger>0)hunger-=0.0001F;
       // if((int)hunger==(int)getMaxHunger())autoheal();
        
       
      /*  if (agetime >= 100)//24000)
        {
            age++;
            agetime = 0;
            System.out.println("Age up!");
        }
*/
       
    	
    	

        
    }

    public void onDeath(DamageSource ds)
    {
        super.onDeath(ds);

        if (isTamed() && canDropEgg() && worldObj.isRemote == false)
        {
            EntityDigiEgg digiegg = new EntityDigiEgg(worldObj);
            digiegg.randomID = eggDrop();
            digiegg.setPosition(posX, posY, posZ);
            worldObj.spawnEntityInWorld(digiegg);
        }
    }

    
    public void tame(EntityPlayer player)
    {
     	 this.setOwner(player.username);
    	 dataWatcher.updateObject(7, (short) 1);
    	 this.digimonaiSit.setSitting(true);
         //sitting = true;
         motionX = 0;
         motionY = 0;
         motionZ = 0;
         dataWatcher.updateObject(2, level);
         exp = 0;
         atHome = false;
         hostile = false;
         rival = null;
         health = getMaxHealth();
         System.out.println("Digimon tamed!");
         inXros=true;
    }
    
        
    protected boolean isAIEnabled()
      {
          return true;
      }
    
    
    public void evolve()
    {
        if (evolution != null && level >= evolveForm && isTamed() && worldObj.isRemote == false)
        {
        	    	
        	String player = getOwnerName();
            EntityDigimon entitydigimon = evolution;
            evolveAnimation();
           entitydigimon.dataWatcher.updateObject(17, player);
            entitydigimon.dataWatcher.updateObject(7, (short) 1);
            entitydigimon.level = getLevel();
            entitydigimon.nickname = nickname;
            entitydigimon.exp = exp;
            entitydigimon.health = entitydigimon.getMaxHealth();
            entitydigimon.setPosition(posX, posY, posZ);
            funParticles(posX, posY, posZ);
            ModLoader.getMinecraftInstance().thePlayer
            .addChatMessage((new StringBuilder())
                    .append(getNickname())
                    .append(" digivolve to... ")
                    .append(entitydigimon.name)
                    .append("!").toString());
            worldObj.spawnEntityInWorld(entitydigimon);
            setDead();
           
           
        }
        else if (evolution == null && worldObj.isRemote == false)
            ModLoader.getMinecraftInstance().thePlayer
            .addChatMessage((new StringBuilder()).append("Sorry, ")
                    .append(getNickname())
                    .append(" doesn't have an evolution!").toString());
        else if (level < evolveForm && worldObj.isRemote == false)
            ModLoader.getMinecraftInstance().thePlayer
            .addChatMessage((new StringBuilder()).append("Sorry, ")
                    .append(getNickname())
                    .append(" needs more data to digivolve!")
                    .append(" Your digimon's current level is ").append(getLevel()).toString());
    }
    
    public void devolve()
    {
        if (devolution != null || level < evolveForm && isTamed() && worldObj.isRemote == false)
        {
        	String player = getOwnerName();
            EntityDigimon entitydigimon = devolution;
           
           // evolveAnimation();
        
            entitydigimon.dataWatcher.updateObject(7, (short) 1);
            entitydigimon.dataWatcher.updateObject(17, player);
            entitydigimon.level = getLevel();
            entitydigimon.nickname = nickname;
            entitydigimon.owner = owner;
            entitydigimon.exp = exp;
            entitydigimon.health = entitydigimon.getMaxHealth();
            entitydigimon.setPosition(posX, posY, posZ);
            funParticles(posX, posY, posZ);
            ModLoader.getMinecraftInstance().thePlayer
            .addChatMessage((new StringBuilder())
                    .append(getNickname())
                    .append(" degenerate to... ")
                    .append(entitydigimon.name)
                    .append("!").toString());
            worldObj.spawnEntityInWorld(entitydigimon);
            setDead();
    
        }
       
        
    }
    


    public void funParticles(double posX, double posY, double posZ)
    {
        String s = "magicCrit";

        for (int i = 0; i < 7; i++)
        {
            double d = rand.nextGaussian() * 0.52D - rand.nextGaussian();
            double d1 = rand.nextGaussian() * 0.52D - rand.nextGaussian();
            double d2 = rand.nextGaussian() * 0.52D - rand.nextGaussian();
            worldObj.spawnParticle(s, (posX + (double)(rand.nextFloat()
                    * width * 2.0F))
                    - (double) width, posY + 0.5D
                    + (double)(rand.nextFloat() * height),
                    (posZ + (double)(rand.nextFloat() * width * 2.0F))
                    - (double) width, d, d1, d2);
        }
    }


    public boolean interact(EntityPlayer player)
    {
    	
    	 if (!(player instanceof EntityPlayerMP)) 
    		 return false;

    	 ItemStack itemstack = player.inventory.getCurrentItem();

    	
    	    
    	 if (player.username.equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote)
         {
             this.digimonaiSit.setSitting(!this.isSitting());
             this.setPathToEntity((PathEntity)null);
         }

        if (readyToTame && itemstack.itemID == digimobs.digivice.itemID)
        {
            return true;
        }

        if (itemstack == null && isTamed()  )
        {
            sitting = !sitting;
            motionY = 0;
            motionX = 0;
            motionZ = 0;
            return true;
        }
        
        if(itemstack!=null && itemstack.itemID == digimobs.digipedia.itemID)
        {
            itemstack = null;
            return false;
        }

     /*     if(itemstack!=null && itemstack.itemID == digimobs.xros.itemID)
        {
            itemstack = null;
            return false;
        }*/
        
       /* if (itemstack!=null && itemstack.itemID == digimobs.digirope.itemID)
        {
            itemstack = null;
            return false;
        }
        */
        
        if (itemstack!=null && itemstack.itemID == digimobs.tamerdigivice.itemID)
        {	itemstack = null;
        
        tame(player);
        
            return true;
        }
        

        if (isTamed() && itemstack.itemID == digimobs.data.itemID)
        {
        	switch(itemstack.getItemDamage()){
        	case 4:exp-=20;
        	case 3:exp+=45;
        	case 2:exp+=35;
        	case 1:exp+=15;
        	case 0:exp+=10;
        	}
            player.inventory.consumeInventoryItem(itemstack.itemID);
            return true;
        }
        
        if (itemstack != null && itemstack.itemID == digimobs.acorn.itemID && digiLevel == 0)
        {
            acornamount++;
            itemstack.stackSize--;
            if (acornamount >= (rand.nextInt(6) + 5))	
            {
            	tame(player);    
            }
        }
        
        if (itemstack != null && itemstack.itemID == digimobs.acorn.itemID && digiLevel == 1)
        {
            acornamount++;
            itemstack.stackSize--;
            if (acornamount >= (rand.nextInt(6) + 20))	
            {
            	tame(player);    
            }
        }
        
        
       

        if (itemstack!=null && itemstack.getItem().itemID == digimobs.acorn.itemID
                ||itemstack!=null && itemstack.getItem().itemID == digimobs.acorn.itemID)
        {
            heal(2);
            //if((int)hunger!=(int)getMaxHunger() && itemstack!=null && itemstack.getItem() instanceof ItemFood)hunger+=2;
            /*
             * worldObj.playSoundAtEntity( this, "sound.secret", 0.6F,
             * ((rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F) / 0.8F);
             */
            worldObj.spawnParticle("heart", posX, posY + height, posZ, 0,
                    0, 0);
            player.inventory.consumeInventoryItem(itemstack.itemID);
            return true;
        }

        if (isEvolveItem(itemstack) && isTamed())
        {
            evolve();
            return true;
        }
        
        if (isDevolveItem(itemstack) && isTamed())
        {
            devolve();
            return true;
        }

        if (isTamed())
        {
            sitting = !sitting;
            motionY = 0;
            motionX = 0;
            motionZ = 0;
        }

        
    
    	return super.interact(player);      
        

      
        
}

   
    
    
    
    public int getAttack()
    {
    	return level / 5 + baseatk;
    	}

    public String getNickname()
    {
    	if (dataWatcher.getWatchableObjectString(3).equals(""))
    		return name;		
    	return dataWatcher.getWatchableObjectString(3);
    }
    
  //Evolution Items go here
    
    public boolean isDevolveItem(ItemStack itemstack)
    {
        if (itemstack == null)
        {
            return false;
        }

        if (degenLevel == 1)
        {
            return itemstack.itemID == digimobs.digivice.itemID; 
        }
	return false;
    }
        
        
    public boolean isEvolveItem(ItemStack itemstack)
    {
        if (itemstack == null)
        {
            return false;
        }
        
        

        if (digiLevel == 0)
        {
            return itemstack.itemID == digimobs.digivice.itemID; 
        }

        if (digiLevel == 1)
            return itemstack.itemID == digimobs.card.itemID
                    && isCorespondingType(itemstack.getItemDamage());

        if (digiLevel == 2)
            return itemstack.itemID == digimobs.crest.itemID
                    && isCorespondingType(itemstack.getItemDamage());

        if (digiLevel == 3)
            return itemstack.itemID == digimobs.mega.itemID
                    && isCorespondingType(itemstack.getItemDamage());

        //if (digiLevel == 4)
        //return itemstack.itemID == mod_digimon.mega.itemID
        //	&& isCorespondingType(itemstack.getItemDamage());
        return false;
    }

    public boolean isCorespondingType(int i)
    {
        return false;
    }
    //End Evolution Items

    //Drops go here
    protected void dropFewItems(boolean par1, int par2)
    {
    	if(digiLevel==0)entityDropItem(new ItemStack(digimobs.data,1,0),0.3F);
    	if(digiLevel==1)entityDropItem(new ItemStack(digimobs.data,1,1),0.3F);
    	if(digiLevel==2)entityDropItem(new ItemStack(digimobs.data,1,2),0.3F);
    	if(digiLevel==3)entityDropItem(new ItemStack(digimobs.data,1,3),0.3F);	 
    }
    
    
    public boolean canDropEgg()
    {
        return isTamed() && eggDrop() >= 0;
    }
    
    public int eggDrop()
    {
        return -1;
    }
    //End Drops
    
    //Other

    
    public void evolveAnimation()
    {
        // TODO: Get a animation!
    }
    //End Unfinished/Other
    
    protected boolean isMovementCeased()
    {
        return isSitting() && entityToAttack == null;
    }

    protected boolean canDespawn()
    {
        return !isTamed();
    }
    
    public String getName() {
    	
	return dataWatcher.getWatchableObjectString(4);
}
    
    public void setName(String name) {
	dataWatcher.updateObject(4, name);
}

    public void setTamed(boolean tamed)
    {
   if (tamed)
	   dataWatcher.updateObject(7, (short) 1);
	   else
	   dataWatcher.updateObject(7, (short) 0);          
    }
    
    public boolean isTamed()
    {
    	return dataWatcher.getWatchableObjectShort(7) == (short) 1;
    }


    public void setLevel(short level)
    {
    	this.dataWatcher.updateObject(2, level);
    }
    

    public void setNickname(String nickname)
    {
    	dataWatcher.updateObject(3, nickname);
    }
    

    public short getLevel()
    { 
    	return this.dataWatcher.getWatchableObjectShort(2);
    }
    
    public short getDigimonAge()
    {
    	return age;
    }

    /*public boolean isSitting()
    {
        return sitting;
    }*/

    public boolean inXros()
    {
        return inXros;
    }

    public void setinXros(boolean flag)
    {
        inXros = flag;
    }

   /* public void setSitting(boolean flag)
    {
        sitting = flag;
    }*/

    //Exp Stuff
    public int getExp()
    {
        return exp;
    }

    public int getNeededExp()
    {
        int maxNeeded = baseExp + level * factor;
        return maxNeeded - exp;
    }
    
    public int getExperiencePoints(EntityPlayer player)
    {
        return level + (level / 4);
    }
    //End Exp
    
  
}

 

 

Also, I have looked at the packet tutorial on the wiki, as well as from some other github src to try and make heads or tails of it. I'll put up what I have as well for any critique/suggestions on how to fix it.(note that I don't have the packets in the above entity file at all at the moment)

 

DigimobsPacketHandler

public class DigimobsPacketHandler implements IPacketHandler {


@Override
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) {
	DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(packet.data));


	try {
		int packetID = dataStream.readInt();
			LevelPacket d = new LevelPacket();
			d.readPacketData(dataStream);


	} catch (IOException e) {
		e.printStackTrace();
	}
}


}

 

DigimobsPacket

public abstract class DigimobsPacket extends Packet250CustomPayload
{
//	EnumPackets packetType;


public Packet getPacket()
    {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        DataOutputStream data = new DataOutputStream(bytes);
        try
        {
         
            writePacketData(data);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        Packet250CustomPayload pkt = new Packet250CustomPayload();
        pkt.channel = "Digimobs";
        pkt.data    = bytes.toByteArray();
        pkt.length  = pkt.data.length;
        return pkt;
    }


@Override
public abstract void writePacketData(DataOutputStream par1DataOutputStream) throws IOException;
@Override
public abstract void readPacketData(DataInputStream par1DataInputStream) throws IOException;

;
    public String toString(boolean full)
    {
        return toString();
    }


   
}

 

Level Packet

public class LevelPacket extends DigimobsPacket {

public int level;






public LevelPacket() {


}


public LevelPacket(EntityDigimon d, int level) {


	this.level = level;

}


public LevelPacket (int level) {

	this.level = level;

}





@Override
public void writePacketData(DataOutputStream data) throws IOException {

	data.writeInt(level);

}


@Override
public void readPacketData(DataInputStream data) throws IOException {

	level = data.readInt();

}



}

Link to comment
Share on other sites

Forget anything I said about maybe setting data to a field, this is probably where you are stuck. (btw,y ou should only need a set/getEXP method and calc your level from that return, or at least don't save both ), Anytime you want to get/setEXP it HAS to use the methods, you cannot save them to a variable anywhere and expect to reference it later.

 

What I see is that you are still not implementing it correctly. I don't see the Init method in the Entity, this is probably the best place to create your datawatchers and put them right next to each other for easy reference... not scattered about.

 

Something like nbt.setDouble("homeX", home.X); will do you no good what so ever. It puts something in the NBT and will read it to a field but it won't write it to the client at all. I'll use only the EXP method but you'll do the same for any persistant data sent from the Server.

 

*Make a get and set methods to set the datawatchers value you initiated in the entityInit() method. It's a method in the Entity class, you don't need it but it's a good place to stick stuff after the constructor fires.

 

* the setEXP( int exp) method has one line: this.dataWatcher.updateObject(20, Integer.valueOf(exp));

 

*the getEXP() method has one line:  return this.dataWatcher.getWatchableObjectInt(20);

 

- Notice how they don't reference any data but the watcher? This is important as we can't trust the client for anything... ever... it's a bad naughty client! It's fields are dirty and must be ignored and made to sit in the corner!

 

!!!Never call your setEXP method ( or rather a write or update on a watcher) outside of the writeToNBT!!! That usually causes wonkyness and a struggle by the Server and Client to see who gets to set the data.  !!!NBT is done only Server side!!!

 

*Use something like nbt.setInt("exp", this.getEXP()); in the writeToNBT

 

*Use something like this.setEXP(nbt.getInt("exp"); inside the readToNBT to make sure the system reads the NBT back into the watcher. You will not be using fields unless you come up with some safe way to update them client side (if you ABSOLUTELY had to THIS is what packets are good for), you'll just be using Entity.getEXP() the method to get the values.

 

I think I can safely say that if you wanted to use packets... they use up a lot more code. Also, you cannot use arrays in watchers(I sure as ssssss can't get them to see array Objects), but you can use strings, and strings are practically byte arrays or even data arrays if you use string indexing and offsets. Just a hint for advanced usage when you get there.

 

Use more // and descriptions too. It might be easier to find things in your code for people to help you out with. It's kinda hard to find stuff with no documented code.

 

I don't see the implementation class of your abstract class so I don't know if there would be anything causing problems there but the way the abstract class is written the implementation wouldn't work.

 

Just an update: When I say never call the setEXP method outside... I should clarify that you may call it to set the data inside the class, but it's probably not as safe to do so in something like the render or model of your entity. I think that's the best way to put it...

 

Also: should be *the getEXP() method has one line:  return this.dataWatcher.getWatchableObjectInt(20);

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.


  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • rp.crazyheal.xyz mods  
    • I'm developing a dimension, but it's kinda resource intensive so some times during player teleporting it lags behind making the player phase down into the void, so im trying to implement some kind of pregeneration to force the game loading a small set of chunks in the are the player will teleport to. Some of the things i've tried like using ServerLevel and ServerChunkCache methods like getChunk() dont actually trigger chunk generation if the chunk isn't already on persistent storage (already generated) or placing tickets, but that doesn't work either. Ideally i should be able to check when the task has ended too. I've peeked around some pregen engines, but they're too complex for my current understanding of the system of which I have just a basic understanding (how ServerLevel ,ServerChunkCache  and ChunkMap work) of. Any tips or other classes I should be looking into to understand how to do this correctly?
    • https://mclo.gs/4UC49Ao
    • Way back in the Forge 1.17 days, work started for adding JPMS (Java Platform Module Support) to ModLauncher and ForgeModLoader. This has been used internally by Forge and some libraries for a while now, but mods (those with mods.toml specifically) have not been able to take advantage of it. As of Forge 1.21.1 and 1.21.3, this is now possible!   What is JPMS and what does it mean for modders? JPMS is the Java Platform Module System, introduced in Java 9. It allows you to define modules, which are collections of packages and resources that can be exported or hidden from other modules. This allows for much more fine-tuned control over visibility, cleaner syntax for service declarations and support for sealed types across packages. For example, you might have a mod with a module called `com.example.mod` that exports `com.example.mod.api` and `com.example.mod.impl` to other mods, but hides `com.example.mod.internal` from them. This would allow you to have a clean API for other mods to use, while keeping your internal implementation details hidden from IDE hints, helping prevent accidental usage of internals that might break without prior notice. This is particularly useful if you'd like to use public records with module-private constructors or partially module-private record components, as you can create a sealed interface that only your record implements, having the interface be exported and the record hidden. It's also nice for declaring and using services, as you'll get compile-time errors from the Java compiler for typos and the like, rather than deferring to runtime errors. In more advanced cases, you can also have public methods that are only accessible to specific other modules -- handy if you want internal interactions between multiple of your own mods.   How do I bypass it? We understand there may be drama in implementing a system that prevents mods from accessing each other's internals when necessary (like when a mod is abandoned or you need to fix a compat issue) -- after all, we are already modding a game that doesn't have explicit support for Java mods yet. We have already thought of this and are offering APIs from day one to selectively bypass module restrictions. Let me be clear: Forge mods are not required to use JPMS. If you don't want to use it, you don't have to. The default behaviour is to have fully open, fully exported automatic modules. In Java, you can use the `Add-Opens` and `Add-Exports` manifest attributes to selectively bypass module restrictions of other mods at launch time, and we've added explicit support for these when loading your Forge mods. At compile-time, you can use existing solutions such as the extra-java-module-info Gradle plugin to deal with non-modular dependencies and add extra opens and exports to other modules. Here's an example on how to make the internal package `com.example.examplemod.internal` open to your mod in your build.gradle: tasks.named('jar', Jar) { manifest { attributes([ 'Add-Opens' : 'com.example.examplemod/com.example.examplemod.internal' 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors // (...) ]) } } With the above in your mod's jar manifest, you can now reflectively access the classes inside that internal package. Multiple entries are separated with a space, as per Java's official spec. You can also use Add-Exports to directly call without reflection, however you'd need to use the Gradle plugin mentioned earlier to be able to compile. The syntax for Add-Exports is the same as Add-Opens, and instructions for the compile-time step with the Gradle plugin are detailed later in this post. Remember to prefer the opens and exports keywords inside module-info.java for sources you control. The Add-Opens/Add-Exports attributes are only intended for forcing open other mods.   What else is new with module support? Previously, the runtime module name was always forced to the first mod ID in your `mods.toml` file and all packages were forced fully open and exported. Module names are now distinguished from mod IDs, meaning the module name in your module-info.java can be different from the mod ID in your `mods.toml`. This allows you to have a more descriptive module name that doesn't have to be the same as your mod ID, however we strongly recommend including your mod ID as part of your module name to aid troubleshooting. The `Automatic-Module-Name` manifest attribute is now also honoured, allowing you to specify a module name for your mod without needing to create a `module-info.java` file. This is particularly useful for mods that don't care about JPMS features but want to have a more descriptive module name and easier integration with other mods that do use JPMS.   How do I use it? The first step is to create a `module-info.java` file in your mod's source directory. This file should be in the same package as your main mod class, and should look something like this: open module com.example.examplemod { requires net.minecraftforge.eventbus; requires net.minecraftforge.fmlcore; requires net.minecraftforge.forge; requires net.minecraftforge.javafmlmod; requires net.minecraftforge.mergetool.api; requires org.slf4j; requires logging; } For now, we're leaving the whole module open to reflection, which is a good starting point. When we know we want to close something off, we can remove the open modifier from the module and open or export individual packages instead. Remember that you need to be open to Forge (module name net.minecraftforge.forge), otherwise it can't call your mod's constructor. Next is fixing modules in Gradle. While Forge and Java support modules properly, Gradle does not put automatic modules on the module path by default, meaning that the logging module (from com.mojang:logging) is not found. To fix this, add the Gradle plugin and add a compile-time module definition for that Mojang library: plugins { // (...) id 'org.gradlex.extra-java-module-info' version "1.9" } // (...) extraJavaModuleInfo { failOnMissingModuleInfo = false automaticModule("com.mojang:logging", "logging") } The automatic module override specified in your build.gradle should match the runtime one to avoid errors. You can do the same for any library or mod dependency that is missing either a module-info or explicit Automatic-Module-Name, however be aware that you may need to update your mod once said library adds one. That's all you need to get started with module support in your mods. You can learn more about modules and how to use them at dev.java.
    • Faire la mise à jour grâce à ce lien m'a aider personnellement, merci à @Paint_Ninja. https://www.amd.com/en/support 
  • Topics

×
×
  • Create New...

Important Information

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