Please post your code using pastebin, and post entire classes (including your Strength class) - it is much more readable.
According to your console log, you are trying to recover some value on both the server and the client, and you can see how the client is always trying to recover 5 whereas the server is trying to recover 10. This is because the server and client tend to have different motion values, not to mention strict equality is very difficult to achieve with floating point values.
Anyway, long story short: ONLY update values on the SERVER, never* the client.
Also, do not use static variables such as "Status.timer++;" bad idea.
Please post your code using pastebin, and post entire classes (including your Strength class) - it is much more readable.
According to your console log, you are trying to recover some value on both the server and the client, and you can see how the client is always trying to recover 5 whereas the server is trying to recover 10. This is because the server and client tend to have different motion values, not to mention strict equality is very difficult to achieve with floating point values.
Anyway, long story short: ONLY update values on the SERVER, never* the client.
Also, do not use static variables such as "Status.timer++;" bad idea.
I reconstruct these classes for a while and they are work now.(Even though I don't know what's exactly going on......orz) But thanks a lot!
BTW, any suggestion for timer update?
I have seen some mods, like iguana tweak, which implement these kind of things(to not calculate every livingupdate cycle) by making a tick handler to handle key tick... (well.. the code of iguana tweak is too tough for me to really understand now)
The first question you must always ask yourself when you think you need a timer is: "Do I really need a timer?"
The second question you should ask is: "Is there already something else keeping track of time that I can use instead?"
For example, if you just want something to happen every 20 ticks and the timer itself does not need to be unique (as in, everything affected by that timer can happen together on the same tick, rather than independently), then you can simply use the world time - this already increments by 1 every single tick. You can use modular division to cause something to happen at any interval you wish, e.g. world.getWorldTime() % 20 == 0 is true every 20 ticks.
To elaborate further on your static timer: since it is static, only one instance exists, so EVERY SINGLE TIME LivingUpdateEvent is for a player, it will increment by 1. Imagine if you had 20 players, each tick it increments 20 times, but if even one of those players sets the timer to 0, ALL players now have a timer at 0. Not good.
Furthermore, please read the first post of the tutorial on events, specifically the section on TickHandlers (which also applies to LivingUpdateEvent). In your specific case, a TickHandler for the PlayerTickEvent actually makes MORE sense to use than LivingUpdateEvent, because you are not doing anything for non-player entities.
Hey i have another problem in my armor class im overriding isValidArmor and checking if my properties (int) is equal to something and if yes then its equal to true ... but what i end up with is that no matter what the int is eqal to it will always go trought the constructor and in the constructor i have "this.CurrentClass = Reference.Unset;" so it will always get the information "Reference.Unset" and i cant do anything with that ... just need to notice it works fine for everything except this. i hope you understand i know my english is really bad but thanks for any help in advance
@KakesRevenge Of course the constructor is called - it HAS to be called, or your properties object will not exist - that's how Objects in Object Oriented Programming work. I think you should spend some time learning the fundamentals of Java before continuing your project. Trust me, it will make a huge difference.
I do understand that but i have no idea how to deal with that
What do you mean? A constructor sets the default state of an object. In Minecraft, every time you load the game everything is in its default state initially, but then loads from the save file(s) setting each value as it was.
When your IEEP reads from NBT, the current class should be set to whatever it was previously. Debug your two write and load NBT methods to see what values you are writing and loading, and compare those with what you think they should be. Chances are, there is a discrepancy.
In step 3.4 of the Extended Entity Properties Tutorial, you mentioned a method called "Sync()", but I am unable to find it anywhere. Would I call this method if I wanted to update a variable on both client and server sides?
I will probably be using both a data watcher, and packets, (unless you think otherwise). data watcher for xp, and packets for the player level. When the player levels up, it isn't synced.
Should I use data watcher instead?
Rollback Post to RevisionRollBack
I complicate easy problems, come begging for help, and leave with a simple solution.
DataWatcher just sends packets, but since DataWatcher has very limited slots available (only 32, many of which are in use), you are better off sending packets to synchronize information on the client.
The 'sync()' method referenced in the tutorial is explained in section 3.3, but that section is very outdated (code from 1.6.4!) and was only ever intended as a sort of general demonstration.
It is much better to put that type of code inside of a packet class and send the packet as needed (i.e. when the player joins the world and only then), and update each individual field as needed with their own individual packets.
those are the best tutorials I've ever read. thank you very, very much for taking the time to write them. I know my post doesn't add anything to the topic, but I had to say this.
those are the best tutorials I've ever read. thank you very, very much for taking the time to write them. I know my post doesn't add anything to the topic, but I had to say this.
Thanks! It's posts like yours that make it worth writing them
i might have missed something, im on 1.8, and my TutorialPacketHandler class doesnt want accept either the IPacketHandler, or the Packet250CustomPayload stuff, can you tell me what i missed and how to fix it?
here is the code that is in my TutorialPacketHandler class
public class TutorialPacketHandler implements IPacketHandler
{
// Don't need to do anything here.
public TutorialPacketHandler() {}
@Override
public void onPacketData(INetHandler manager, Packet250CustomPayload packet, EntityPlayer player)
{
// This is a good place to parse through channels if you have multiple channels
if (packet.channel.equals("tutchannel")) {
handleExtendedProperties(packet, player);
}
}
// Making different methods to handle each channel helps keep things tidy:
private void handleExtendedProperties(Packet250CustomPayload packet, EntityPlayer player)
{
DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data));
ExtendedPlayer props = ExtendedPlayer.get((EntityPlayer) player);
// Everything we read here should match EXACTLY the order in which we wrote it
// to the output stream in our ExtendedPlayer sync() method.
try {
props.setCurrentMana(inputStream.readInt());
} catch (IOException e) {
e.printStackTrace();
return;
}
// Just so you can see in the console that it's working:
System.out.println("[PACKET] Mana from packet: " + props.getCurrentMana() + "/" + props.getMaxMana());
}
@Override
public void onDisconnect(IChatComponent arg0) {
// TODO Auto-generated method stub
i might have missed something, im on 1.8, and my TutorialPacketHandler class doesnt want accept either the IPacketHandler, or the Packet250CustomPayload stuff, can you tell me what i missed and how to fix it?
Well, you see, that packet code is for 1.6.4. There is a link at the top which is also outdated giving information on networking in 1.7.2.
I have better information on updating the network in the inventory tutorial, under the 'Tips on Updating' section. Even better, visit the Github version - the network code there is still from 1.7.2, but it gives you information on how to update it, and it's far less difficult to update that network code to 1.8 than it is to go from the mess that was 1.6.4 packet code.
I would update this tutorial here, but the forum editor has become so capricious that I don't dare try lest the formatting get completely mangled. It's no fun going through and manually fixing it, only to have it 'fixed' yet again by the stupid editor that thinks it knows what I meant better than I do. Sorry - it's an issue I've raised many times to be told 'we are working on it' - a year later and it hasn't improved one bit...
Do you know of any bugs with LivingHurtEvent in a cauldron server? my character broke, I can't get hurt anymore. I'm the server admin, and I've been writing a mod, then I decided to put event handling in it and now im imune to damage. I put a few logger messages inside my event handler and I could notice my HP is set to NaN sometimes, I don't know what's wrong. even if I revert my mod back to the version before the event handling I still can't get hurt.
Do you know of any bugs with LivingHurtEvent in a cauldron server? my character broke, I can't get hurt anymore. I'm the server admin, and I've been writing a mod, then I decided to put event handling in it and now im imune to damage. I put a few logger messages inside my event handler and I could notice my HP is set to NaN sometimes, I don't know what's wrong. even if I revert my mod back to the version before the event handling I still can't get hurt.
Never used cauldron, but it sounds to me like you broke your save data for your character somehow. That wouldn't be a bug with the event, but with your code.
Hey, I'm having a bit of trouble with things not syncing properly when traveling from the End back to the Overworld. Relogging, syncs everything but it would be nice if I could get that fixed. Any suggestions? Thanks in advance.
Rollback Post to RevisionRollBack
Matthew 11:28-30 Come to me, all you who are weary and burdened, and I will give you rest. Take my yoke upon you, and learn from me; for I am gentle and humble in heart: and you will find rest for your souls. For my yoke is light, and my burden is easy.
Please post your code using pastebin, and post entire classes (including your Strength class) - it is much more readable.
According to your console log, you are trying to recover some value on both the server and the client, and you can see how the client is always trying to recover 5 whereas the server is trying to recover 10. This is because the server and client tend to have different motion values, not to mention strict equality is very difficult to achieve with floating point values.
Anyway, long story short: ONLY update values on the SERVER, never* the client.
Also, do not use static variables such as "Status.timer++;" bad idea.
I reconstruct these classes for a while and they are work now.(Even though I don't know what's exactly going on......orz) But thanks a lot!
BTW, any suggestion for timer update?
I have seen some mods, like iguana tweak, which implement these kind of things(to not calculate every livingupdate cycle) by making a tick handler to handle key tick... (well.. the code of iguana tweak is too tough for me to really understand now)
The first question you must always ask yourself when you think you need a timer is: "Do I really need a timer?"
The second question you should ask is: "Is there already something else keeping track of time that I can use instead?"
For example, if you just want something to happen every 20 ticks and the timer itself does not need to be unique (as in, everything affected by that timer can happen together on the same tick, rather than independently), then you can simply use the world time - this already increments by 1 every single tick. You can use modular division to cause something to happen at any interval you wish, e.g. world.getWorldTime() % 20 == 0 is true every 20 ticks.
To elaborate further on your static timer: since it is static, only one instance exists, so EVERY SINGLE TIME LivingUpdateEvent is for a player, it will increment by 1. Imagine if you had 20 players, each tick it increments 20 times, but if even one of those players sets the timer to 0, ALL players now have a timer at 0. Not good.
Furthermore, please read the first post of the tutorial on events, specifically the section on TickHandlers (which also applies to LivingUpdateEvent). In your specific case, a TickHandler for the PlayerTickEvent actually makes MORE sense to use than LivingUpdateEvent, because you are not doing anything for non-player entities.
Wow! That's right! I even forget the case of multiplayer...
I think the modular method is a good idea and I will try it. Thanks a lot again.
Hey i have another problem in my armor class im overriding isValidArmor and checking if my properties (int) is equal to something and if yes then its equal to true ... but what i end up with is that no matter what the int is eqal to it will always go trought the constructor and in the constructor i have "this.CurrentClass = Reference.Unset;" so it will always get the information "Reference.Unset" and i cant do anything with that ... just need to notice it works fine for everything except this. i hope you understand i know my english is really bad but thanks for any help in advance
PlayerClassHandler
package cz.grossik.projektwow.handler;
import cz.grossik.projektwow.help.Reference;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;
/**
@Author KakesRevenge
*/
public class PlayerClassHandler implements IExtendedEntityProperties {
public int CurrentClass;
private final EntityPlayer player;
public final static String Name = "PlayerClass";
public PlayerClassHandler(EntityPlayer player) {
this.player = player;
this.CurrentClass = Reference.Unset;
}
@Override
public void saveNBTData(NBTTagCompound compound) {
NBTTagCompound playerclass = new NBTTagCompound();
playerclass.setInteger("CurrentPlayerClass", this.CurrentClass);
compound.setTag(Name, playerclass);
}
@Override
public void loadNBTData(NBTTagCompound compound) {
NBTTagCompound properties = (NBTTagCompound) compound.getTag(Name);
CurrentClass = properties.getInteger("CurrentPlayerClass");
}
@Override
public void init(Entity entity, World world) {
}
public static final PlayerClassHandler get(EntityPlayer player) {
return (PlayerClassHandler) player.getExtendedProperties(Name);
}
public static String getPropertyName() {
return Name;
}
public static final void register(EntityPlayer player) {
player.registerExtendedProperties(Name, new PlayerClassHandler(player));
}
}
Armor Class
package cz.grossik.projektwow.items.warrior;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatComponentText;
import net.minecraft.world.World;
import cz.grossik.projektwow.handler.PlayerClassHandler;
import cz.grossik.projektwow.help.LogHelper;
import cz.grossik.projektwow.help.Reference;
/** @Autor Grossik
*/
public class WarriorArmor extends ItemArmor {
public WarriorArmor(ItemArmor.ArmorMaterial ArmorMaterial, int int1, int int2) {
super(ArmorMaterial, int1, int2);
}
public ItemStack UseItem(ItemStack itemstack, World world, EntityPlayer player) {
int i = EntityLiving.getArmorPosition(itemstack) - 1;
ItemStack itemstack1 = player.getCurrentArmor(i);
if (itemstack1 == null) {
player.setCurrentItemOrArmor(i + 1, itemstack.copy());
itemstack.stackSize = 0;
}
return itemstack;
}
@Override
public boolean isValidArmor(ItemStack stack, int armorType, Entity entity){
if(entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer)entity;
PlayerClassHandler props = PlayerClassHandler.get(player);
int playerclass = props.CurrentClass;
if(playerclass == Reference.Warrior) {
System.out.println("TRUE");
return true;
} else if (playerclass != Reference.Warrior) {
player.addChatComponentMessage(new ChatComponentText("You need to be a warrior"));
}
LogHelper.info(playerclass);
}
return true;
}
@Override
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer player) {
if(this.isValidArmor(itemstack, armorType, player) == true) {
this.UseItem(itemstack, world, player);
}
return itemstack;
}
}
@KakesRevenge Of course the constructor is called - it HAS to be called, or your properties object will not exist - that's how Objects in Object Oriented Programming work. I think you should spend some time learning the fundamentals of Java before continuing your project. Trust me, it will make a huge difference.
I do understand that but i have no idea how to deal with that
What do you mean? A constructor sets the default state of an object. In Minecraft, every time you load the game everything is in its default state initially, but then loads from the save file(s) setting each value as it was.
When your IEEP reads from NBT, the current class should be set to whatever it was previously. Debug your two write and load NBT methods to see what values you are writing and loading, and compare those with what you think they should be. Chances are, there is a discrepancy.
r
In step 3.4 of the Extended Entity Properties Tutorial, you mentioned a method called "Sync()", but I am unable to find it anywhere. Would I call this method if I wanted to update a variable on both client and server sides?
I will probably be using both a data watcher, and packets, (unless you think otherwise). data watcher for xp, and packets for the player level. When the player levels up, it isn't synced.
Should I use data watcher instead?
I complicate easy problems, come begging for help, and leave with a simple solution.
DataWatcher just sends packets, but since DataWatcher has very limited slots available (only 32, many of which are in use), you are better off sending packets to synchronize information on the client.
The 'sync()' method referenced in the tutorial is explained in section 3.3, but that section is very outdated (code from 1.6.4!) and was only ever intended as a sort of general demonstration.
It is much better to put that type of code inside of a packet class and send the packet as needed (i.e. when the player joins the world and only then), and update each individual field as needed with their own individual packets.
those are the best tutorials I've ever read. thank you very, very much for taking the time to write them. I know my post doesn't add anything to the topic, but I had to say this.
Thanks! It's posts like yours that make it worth writing them
i might have missed something, im on 1.8, and my TutorialPacketHandler class doesnt want accept either the IPacketHandler, or the Packet250CustomPayload stuff, can you tell me what i missed and how to fix it?
here is the code that is in my TutorialPacketHandler class
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetHandler;
import net.minecraft.util.IChatComponent;
public class TutorialPacketHandler implements IPacketHandler
{
// Don't need to do anything here.
public TutorialPacketHandler() {}
@Override
public void onPacketData(INetHandler manager, Packet250CustomPayload packet, EntityPlayer player)
{
// This is a good place to parse through channels if you have multiple channels
if (packet.channel.equals("tutchannel")) {
handleExtendedProperties(packet, player);
}
}
// Making different methods to handle each channel helps keep things tidy:
private void handleExtendedProperties(Packet250CustomPayload packet, EntityPlayer player)
{
DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data));
ExtendedPlayer props = ExtendedPlayer.get((EntityPlayer) player);
// Everything we read here should match EXACTLY the order in which we wrote it
// to the output stream in our ExtendedPlayer sync() method.
try {
props.setCurrentMana(inputStream.readInt());
} catch (IOException e) {
e.printStackTrace();
return;
}
// Just so you can see in the console that it's working:
System.out.println("[PACKET] Mana from packet: " + props.getCurrentMana() + "/" + props.getMaxMana());
}
@Override
public void onDisconnect(IChatComponent arg0) {
// TODO Auto-generated method stub
}
}
Well, you see, that packet code is for 1.6.4. There is a link at the top which is also outdated giving information on networking in 1.7.2.
I have better information on updating the network in the inventory tutorial, under the 'Tips on Updating' section. Even better, visit the Github version - the network code there is still from 1.7.2, but it gives you information on how to update it, and it's far less difficult to update that network code to 1.8 than it is to go from the mess that was 1.6.4 packet code.
I would update this tutorial here, but the forum editor has become so capricious that I don't dare try lest the formatting get completely mangled. It's no fun going through and manually fixing it, only to have it 'fixed' yet again by the stupid editor that thinks it knows what I meant better than I do. Sorry - it's an issue I've raised many times to be told 'we are working on it' - a year later and it hasn't improved one bit...
ok, thanks
Do you know of any bugs with LivingHurtEvent in a cauldron server? my character broke, I can't get hurt anymore. I'm the server admin, and I've been writing a mod, then I decided to put event handling in it and now im imune to damage. I put a few logger messages inside my event handler and I could notice my HP is set to NaN sometimes, I don't know what's wrong. even if I revert my mod back to the version before the event handling I still can't get hurt.
Great tutorial, thanks
Never used cauldron, but it sounds to me like you broke your save data for your character somehow. That wouldn't be a bug with the event, but with your code.
Hey, I'm having a bit of trouble with things not syncing properly when traveling from the End back to the Overworld. Relogging, syncs everything but it would be nice if I could get that fixed. Any suggestions? Thanks in advance.
Matthew 11:28-30 Come to me, all you who are weary and burdened, and I will give you rest. Take my yoke upon you, and learn from me; for I am gentle and humble in heart: and you will find rest for your souls. For my yoke is light, and my burden is easy.
I made a thing:
Forum Thread: http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2091787-1-7-2-tynkyn-v1-3-out-now-elementurtles
Website: https://sites.google.com/site/tynkynwiki/