@Agadar The implementations are nothing more than sending a packet, with the methods being remnants from 1.6.4 when sending a packet was a hassle for most people. So to get the value to sync, you need to send whatever sync packet you have when the player respawns - I send mine from EntityJoinWorldEvent, but you could choose the login and respawn events instead.
As for 1.8.9, IEEP is being deprecated in favor of the Capability system. IEEP still works just fine, however, so you don't have to switch over right away, but they may remove it entirely in the future (e.g. 1.9) so you'll probably want to switch at some point.
In the meantime, I had already stumbled upon the updated version of your guide, on github. I nearly fully copied the code, but I'm still getting either nullpointerexceptions from the extended property's get method, or the client isn't receiving the maximum mana update message on (re)spawn.
I've bookmarked the capability page for now, seems like a good read. For now, I'm ending this hours-long struggle with getting my extended properties synched properly, and enjoy a well-deserved rest.
@Agadar If you are getting an NPE from the #get method client side, it sounds like you did not update your IMessageHandler code to handle the fact that 1.8 messages are handled by default on a separate thread.
If you have already updated your message code, then it could be something to do with your actual current / max mana implementation. I know when I was doing some testing a few months ago, I was also having problems syncing but I don't recall exactly why. I ended up having the client player request a sync packet when joining the world and that seemed to work out pretty well.
Unfortunately, the computer with all my coding stuff on it is basically toast at this point and I have yet to take a crack at salvaging it, so I may not be able to help you much further than that
I had, in fact, not updated my IMessageHandler code. I had taken a 1.5 year break from modding, so I guess I missed the memo.
Everything's working like a charm now, and it's all thanks to you. I'll be using your tutorial project on github as a reference and guideline as I continue developing my mods.
Do you intend to update this tutorial for the new Capabilites standard in 1.9? IExtendedEntityProperties is gone
No, because I don't want to delete the IEEP tutorial - it's a good reference for people in the future that want to write mods for earlier versions of Minecraft.
I might, however, do a Capability tutorial that implements the same features, but that will be months from now as the computer I use for coding is toast. Until then, the official documentation not only finally exists but isn't terrible. It should take most people less than a day to figure out how to update from IEEP to the Capability system - most of the concepts (registering the IEEP/capability, syncing to client, handling persistence through death, etc.) are identical, it just has slightly different syntax.
Hmm... So it seems like if my mana is, for example, 13 and I remove 15 it will think that it has enough mana and drain the 13 mana.
You are just not understanding the code:
public final boolean consumeMana(int amount) {
// first line remembers if there was enough mana or not
boolean sufficient = amount <= getCurrentMana();
// second line removes the amount whether or not it was sufficient
setCurrentMana(getCurrentMana() - amount);
// finally, we return true if the player had enough mana to cover the entire amount
return sufficient;
}
That's the way it is written - if you try to use a power that costs more mana than you have, you drain the rest of your mana and the function returns false, meaning that the power should not be allowed to trigger. E.g.:
if (props.consumeMana(power.manaCost)) {
power.activate();
} else {
"Not enough mana and now it's all gone!"
}
Feel free to invent your own logic, it's just an example.
Forgive me if I'm doing something stupid, but my event handler class doesn't seem to be getting called. I'm using forge 1.8.9. Here is my relevant code:
public class WarEventHandler {
@EventHandler
public void onEntityConstructing(EntityConstructing event)
{
Forgive me if I'm doing something stupid, but my event handler class doesn't seem to be getting called. I'm using forge 1.8.9. Here is my relevant code:
public class WarEventHandler {
@EventHandler
public void onEntityConstructing(EntityConstructing event)
{
Pardon me but I was wondering if I can use iExtendedProperties to store a texture that changes depending on circumstances(like right-clicking dye). The problem is dependent on my getter and setter of the color: is that the best way to handle things. I'm worried I will break something if I use the code Eclipse created.
Half (or more) of programming is breaking stuff and then figuring out how to fix it, so just go for it. However, it doesn't sound to me like IEEP is the right tool for the job if what you are trying to do is have an Item change color - use the ItemStack NBT instead. If you are in 1.8.9+, which you probably should be by now, then you should be using the new Capabilities system anyway.
I want to get a handle on IEEP before I start with Capabilities. However none of my custom variables are working. Only the stuff supplied in the tutorial load properly i.e the mana before I commented it out. Tell me what I did wrong please.
package kirbyandfriends.inventory;
import kirbyandfriends.MyCommonProxy;
import kirbyandfriends.packet_handling.PacketDispatcher;
import kirbyandfriends.packet_handling.packets.SyncPlayerPropsMessage;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;
public class ExtendedPlayer implements IExtendedEntityProperties
{
/*
Here I create a constant EXT_PROP_NAME for this class of properties. You need a unique name for every instance of IExtendedEntityProperties you make, and doing it at the top of each class as a constant makes
it very easy to organize and avoid typos. It's easiest to keep the same constant name in every class, as it will be distinguished by the class name: ExtendedPlayer.EXT_PROP_NAME vs. ExtendedEntity.EXT_PROP_NAME
Note that a single entity can have multiple extended properties, so each property should have a unique name. Try to come up with something more unique than the tutorial example.
*/
public final static String EXT_PROP_NAME = "ExtendedPlayer";
// I always include the entity to which the properties belong for easy access
// It's final because we won't be changing which player it is
private final EntityPlayer player;
public final InventoryCustomPlayer inventory = new InventoryCustomPlayer();
// Declare other variables you want to add here
// We're adding mana to the player, so we'll need current and max mana
//private int currentMana;
//private int maxMana;
private String color;
private int PowerId;
private boolean isKirby;
/*
The default constructor takes no arguments, but I put in the Entity so I can initialize the above variable 'player'
Also, it's best to initialize any other variables you may have added, just like in any constructor.
*/
public ExtendedPlayer(EntityPlayer player)
{
this.player = player;
// Start with max mana. Every player starts with the same amount.
//this.currentMana = this.maxMana = 50;
this.color = "Pink";
this.isKirby=true;
this.PowerId = 1;
}
/**
* Used to register these extended properties for the player during EntityConstructing event
* This method is for convenience only; it will make your code look nicer
*/
public static final void register(EntityPlayer player)
{
player.registerExtendedProperties(ExtendedPlayer.EXT_PROP_NAME, new ExtendedPlayer(player));
}
/**
* Returns ExtendedPlayer properties for player
* This method is for convenience only; it will make your code look nicer
*/
public static final ExtendedPlayer get(EntityPlayer player)
{
return (ExtendedPlayer) player.getExtendedProperties(EXT_PROP_NAME);
}
// Save any custom data that needs saving here
@Override
public void saveNBTData(NBTTagCompound compound)
{
// We need to create a new tag compound that will save everything for our Extended Properties
NBTTagCompound properties = new NBTTagCompound();
// We only have 2 variables currently; save them both to the new tag
//properties.setInteger("CurrentMana", this.currentMana);
//properties.setInteger("MaxMana", this.maxMana);
properties.setString("Color", this.color);
properties.setInteger("Power", this.PowerId);
properties.setBoolean("IsKirby", this.isKirby);
this.inventory.writeToNBT(properties);
/*
Now add our custom tag to the player's tag with a unique name (our property's name). This will allow you to save multiple types of properties and distinguish between them. If you only have one type, it isn't as important, but it will still avoid conflicts between your tag names and vanilla tag names. For instance, if you add some "Items" tag, that will conflict with vanilla. Not good. So just use a unique tag name.
*/
compound.setTag(EXT_PROP_NAME, properties);
}
// Load whatever data you saved
@Override
public void loadNBTData(NBTTagCompound compound)
{
// Here we fetch the unique tag compound we set for this class of Extended Properties
NBTTagCompound properties = (NBTTagCompound) compound.getTag(EXT_PROP_NAME);
// Get our data from the custom tag compound
//this.currentMana = properties.getInteger("CurrentMana");
//this.maxMana = properties.getInteger("MaxMana");
this.color = properties.getString("Color");
this.isKirby = properties.getBoolean("IsKirby");
this.inventory.readFromNBT(properties);
this.PowerId =(properties.getInteger("Power"));
// Just so you know it's working, add this line:
System.out.println("[TUT PROPS] from NBT: " + this.isKirby);
}
/*
I personally have yet to find a use for this method. If you know of any,
please let me know and I'll add it in!
*/
@Override
public void init(Entity entity, World world)
{
}
private static final String getSaveKey(EntityPlayer player) {
// no longer a username field, so use the command sender name instead:
return player.getCommandSenderName() + ":" + EXT_PROP_NAME;
}
/**
* Does everything I did in onLivingDeathEvent and it's static,
* so you now only need to use the following in the above event:
* ExtendedPlayer.saveProxyData((EntityPlayer) event.entity));
*/
public static void saveProxyData(EntityPlayer player) {
ExtendedPlayer playerData = ExtendedPlayer.get(player);
NBTTagCompound savedData = new NBTTagCompound();
playerData.saveNBTData(savedData);
// Note that we made the CommonProxy method storeEntityData static,
// so now we don't need an instance of CommonProxy to use it! Great!
MyCommonProxy.storeEntityData(getSaveKey(player), savedData);
}
/**
* This cleans up the onEntityJoinWorld event by replacing most of the code
* with a single line: ExtendedPlayer.loadProxyData((EntityPlayer) event.entity));
*/
public static void loadProxyData(EntityPlayer player) {
ExtendedPlayer playerData = ExtendedPlayer.get(player);
NBTTagCompound savedData = MyCommonProxy.getEntityData(getSaveKey(player));
if(savedData != null) {
playerData.loadNBTData(savedData);
}
// note we renamed 'syncExtendedProperties' to 'syncProperties' because yay, it's shorter
PacketDispatcher.sendTo(new SyncPlayerPropsMessage(player), (EntityPlayerMP) player);
}
/*
That's it for the IExtendedEntityProperties methods, but we need to add a few of our own in order to interact with our new variables. For now, let's make one method to consume mana and one to replenish it.
*/
/**
* Returns true if the amount of mana was consumed or false
* if the player's current mana was insufficient
*/
//public boolean consumeMana(int amount)
//{
//// Does the player have enough mana?
//boolean sufficient = amount <= this.currentMana;
//// Consume the amount anyway; if it's more than the player's current mana,
//// mana will be set to 0
//this.currentMana -= (amount < this.currentMana ? amount : this.currentMana);
//// Return if the player had enough mana
//return sufficient;
//}
//
//
///**
//* Simple method sets current mana to max mana
//*/
//public void replenishMana()
//{
//this.currentMana = this.maxMana;
//}
/**
* @return the color
*/
//public String getColor() {
// if (color == null) {
// return "Pink";
// }
// else{
// return color;
// }
//}
/**
* @param color the color to set
*/
//public void setColor(String color) {
// this.color = color;
//}
/**
* @return the powerId
*/
//public int getPowerId() {
// return PowerId;
//}
/**
* @param powerId the powerId to set
*/
//public void setPowerId(int powerId) {
// PowerId = powerId;
//}
}
What do you mean it isn't loading properly? How do you know?
Btw, are you aware that textures and rendering are all done on the client side only, and by default IEEP data is only loaded on the server? You need to send any information you want to use on the client via packet as I explain in the tutorial.
Capabilities is a totally different system than IEEP - there's not really any overlap in the code, so it's not really possible to update the tutorial so much as completely rewrite it. Since that's the case, I'd prefer to leave it as is for posterity in case anyone still needs to use IEEP. The scope of Capabilities is also much broader, encompassing not only Entities but ItemStacks and TileEntities as well.
There are already several tutorials and examples out there for the Capability system, notably the Forge documentation itself as well as GitHub repos such as that of Choonster.
The Meaning of Life, the Universe, and Everything.
Join Date:
1/18/2011
Posts:
810
Minecraft:
mightydanp
Member Details
I do have a good question. I tried to use a manual Map to load the player inventory without having to use Capabilities but it didnt quite work since all it did was give me a error ... Is there any other way to get it to load without it or ?
23 public static InventoryEotInventory getPlayerBaubles(EntityPlayer player) {
24 if (!playerEotInventory.containsKey(player.getDisplayNameString())) {
25 InventoryEotInventory inventory = new InventoryEotInventory(player);
26 playerEotInventory.put(player.getDisplayNameString(), inventory);
27 }
28 return playerEotInventory.get(player.getDisplayNameString());
29 }
this error is related to the code
at java.util.concurrent.ConcurrentHashMap.get(PlayerHandler.java:28)
at java.util.concurrent.ConcurrentHashMap.containsKey(PlayerHandler.java:24)
at net.minecraftforge.fml.common.eventhandler.EventBus.register(EventBus.java:47)
at com.mightydanp.eot.core.proxy.ClientProxy.registerKeyBindings(ClientProxy.java:50)
at com.mightydanp.eot.Eot.init(Eot.java:109)
I don't know - I haven't worked with 1.8.9 and up at all yet, so I haven't even really looked at the Capability system. However, that strikes me as a very poor way of managing a custom player inventory... you really need to use the Capability system.
Also, ConcurrentModificationExceptions typically happen when you modify Collections in a non-thread-safe fashion, such as when iterating over the contents. Google has lots of information about it, though they can be very difficult to debug if it's not something as simple as the case I mentioned.
@Agadar The implementations are nothing more than sending a packet, with the methods being remnants from 1.6.4 when sending a packet was a hassle for most people. So to get the value to sync, you need to send whatever sync packet you have when the player respawns - I send mine from EntityJoinWorldEvent, but you could choose the login and respawn events instead.
As for 1.8.9, IEEP is being deprecated in favor of the Capability system. IEEP still works just fine, however, so you don't have to switch over right away, but they may remove it entirely in the future (e.g. 1.9) so you'll probably want to switch at some point.
In the meantime, I had already stumbled upon the updated version of your guide, on github. I nearly fully copied the code, but I'm still getting either nullpointerexceptions from the extended property's get method, or the client isn't receiving the maximum mana update message on (re)spawn.
I've bookmarked the capability page for now, seems like a good read. For now, I'm ending this hours-long struggle with getting my extended properties synched properly, and enjoy a well-deserved rest.
Thank you for the quick reply.
My mods: Archmagus, BetterBoneMeal, BetterVanilla, Brewing-API, NaturalArmors, and PluckableChickens!
@Agadar If you are getting an NPE from the #get method client side, it sounds like you did not update your IMessageHandler code to handle the fact that 1.8 messages are handled by default on a separate thread.
If you have already updated your message code, then it could be something to do with your actual current / max mana implementation. I know when I was doing some testing a few months ago, I was also having problems syncing but I don't recall exactly why. I ended up having the client player request a sync packet when joining the world and that seemed to work out pretty well.
Unfortunately, the computer with all my coding stuff on it is basically toast at this point and I have yet to take a crack at salvaging it, so I may not be able to help you much further than that
I had, in fact, not updated my IMessageHandler code. I had taken a 1.5 year break from modding, so I guess I missed the memo.
Everything's working like a charm now, and it's all thanks to you. I'll be using your tutorial project on github as a reference and guideline as I continue developing my mods.
Thank you very much!
My mods: Archmagus, BetterBoneMeal, BetterVanilla, Brewing-API, NaturalArmors, and PluckableChickens!
No, because I don't want to delete the IEEP tutorial - it's a good reference for people in the future that want to write mods for earlier versions of Minecraft.
I might, however, do a Capability tutorial that implements the same features, but that will be months from now as the computer I use for coding is toast. Until then, the official documentation not only finally exists but isn't terrible. It should take most people less than a day to figure out how to update from IEEP to the Capability system - most of the concepts (registering the IEEP/capability, syncing to client, handling persistence through death, etc.) are identical, it just has slightly different syntax.
You are just not understanding the code:
That's the way it is written - if you try to use a power that costs more mana than you have, you drain the rest of your mana and the function returns false, meaning that the power should not be allowed to trigger. E.g.:
Feel free to invent your own logic, it's just an example.
Forgive me if I'm doing something stupid, but my event handler class doesn't seem to be getting called. I'm using forge 1.8.9. Here is my relevant code:
public class WarEventHandler {
@EventHandler
public void onEntityConstructing(EntityConstructing event)
{
if ((event.entity instanceof EntityLiving || event.entity instanceof EntityPlayer) && WarEntity.get(event.entity) == null){
System.out.println("\n\n\n\nInitting\n\n\n\n\n");
WarEntity.register(event.entity);
}
}
}
@EventHandler
public void init(FMLInitializationEvent event) {
WarEventHandler handler = new WarEventHandler();
MinecraftForge.EVENT_BUS.register(handler);
Never mind, I realize now that I was just being stupid :b sry
Pardon me but I was wondering if I can use iExtendedProperties to store a texture that changes depending on circumstances(like right-clicking dye). The problem is dependent on my getter and setter of the color: is that the best way to handle things. I'm worried I will break something if I use the code Eclipse created.
Half (or more) of programming is breaking stuff and then figuring out how to fix it, so just go for it. However, it doesn't sound to me like IEEP is the right tool for the job if what you are trying to do is have an Item change color - use the ItemStack NBT instead. If you are in 1.8.9+, which you probably should be by now, then you should be using the new Capabilities system anyway.
What do you mean it isn't loading properly? How do you know?
Btw, are you aware that textures and rendering are all done on the client side only, and by default IEEP data is only loaded on the server? You need to send any information you want to use on the client via packet as I explain in the tutorial.
Are you going to update this to 1.9/1.0 because i tried to do a capabilities, i couldn't really understand it.
Capabilities is a totally different system than IEEP - there's not really any overlap in the code, so it's not really possible to update the tutorial so much as completely rewrite it. Since that's the case, I'd prefer to leave it as is for posterity in case anyone still needs to use IEEP. The scope of Capabilities is also much broader, encompassing not only Entities but ItemStacks and TileEntities as well.
There are already several tutorials and examples out there for the Capability system, notably the Forge documentation itself as well as GitHub repos such as that of Choonster.
Thanks for the references
I do have a good question. I tried to use a manual Map to load the player inventory without having to use Capabilities but it didnt quite work since all it did was give me a error ... Is there any other way to get it to load without it or ?
23 public static InventoryEotInventory getPlayerBaubles(EntityPlayer player) {
24 if (!playerEotInventory.containsKey(player.getDisplayNameString())) {
25 InventoryEotInventory inventory = new InventoryEotInventory(player);
26 playerEotInventory.put(player.getDisplayNameString(), inventory);
27 }
28 return playerEotInventory.get(player.getDisplayNameString());
29 }
this error is related to the code
at java.util.concurrent.ConcurrentHashMap.get(PlayerHandler.java:28)
at java.util.concurrent.ConcurrentHashMap.containsKey(PlayerHandler.java:24)
at net.minecraftforge.fml.common.eventhandler.EventBus.register(EventBus.java:47)
at com.mightydanp.eot.core.proxy.ClientProxy.registerKeyBindings(ClientProxy.java:50)
at com.mightydanp.eot.Eot.init(Eot.java:109)
I don't know - I haven't worked with 1.8.9 and up at all yet, so I haven't even really looked at the Capability system. However, that strikes me as a very poor way of managing a custom player inventory... you really need to use the Capability system.
Also, ConcurrentModificationExceptions typically happen when you modify Collections in a non-thread-safe fashion, such as when iterating over the contents. Google has lots of information about it, though they can be very difficult to debug if it's not something as simple as the case I mentioned.
Will you create a Capability tutorial in the Future?
I have already tried it and most stuff worked, but I haven't understood it really.
Maby because of lacking English skills or the wrong tutorials.
But I would really love a tutorial about that ^^