Where do you remove the item from the player? That needs to be done on the server, too, not just the adding of money.
How do you know that your money is not persisting across death / re-log-in ? Do you print the amount to the console? Keep in mind that there are TWO money variables, one on the server and one on the client, and you need to print them both to see if they are what they should be. My guess is that the server has the correct value, but you are seeing 0 on the client because you never tell the client (by sending a packet) how much money the player has.
Btw, you should seriously consider rewriting your depostAllMoney method... and please name your ExtendedPlayer String either EXTENDED_PLAYER or extendedPlayer - right now it looks like a class name I used to have a good link for Java naming conventions, but it's broken, so I'll leave it to you to do a search.
I currently remove the item from the player with the depositAllMoney method that runs from the server when I send the packet. I didn't copy all of my GUI class, there I retrieve the money, that's how I know it is not persisting. Currently it does display the correct value. And finally, you are right, my depositAllMoney method is ugly, I'm rewriting it asap. Also I know what you mean when you said it looks like a class name, I do know some naming conventions, I was just a mistake by my part. I hope I made things clearer. I have no clue why it is not persisting. And by the way, thanks for the time you are taking to reply my messages and helping me.
No problem Okay, yeah, I see that you're removing money items now, but my point still stands: if you are relying on the Gui to prove that your data is persisting or not, and you are not telling the client how much money the server player has, then you cannot say for sure your data is not persisting.
Please print out how much money the player has using 'println' statements in your loadNBTData method, in your depositAllMoney method, and wherever else you think it may be interesting to see; be sure to include the side the player is on so you can get a clearer picture:
System.out.printf("Player's current money: %d; On client? %s", pmoney, player.worldObj.isRemote);
My bet is you will see output like this:
Player's current money: 0; On client? TRUE
Player's current money: 100; On client? FALSE
Player's current money: 0; On client? TRUE
Player's current money: 100; On client? FALSE
You MUST send a packet from the server to the client to tell the client what the value of pmoney is if you want that value available in the Gui. A pretty large section of my tutorial was devoted to explaining this concept - please read the section on creating a Mana Bar very carefully.
I called this method in my depositAllMoney method, in my event handler, on onEntityJoinWorld, and when I retrive the extended property.
My results:
When I deposit:
Player's current money: 20; On client? truePlayer's current money: 20; On client? true
On dying:
saving..., which i printed from saveProxyData
Player's current money: 0; On client? falseloading...Player's current money: 0; On client? truePlayer's current money: 0; On client? true
"loading..." is printed from loadProxyData
And if I deposit again and relog:
Player's current money: 0; On client? falsePlayer's current money: 0; On client? truePlayer's current money: 0; On client? true
So the value of money on the server is always 0, why is this if I'm actually just changing the value in the server? Is in the code I already posted, in case you want to check it again. And also what about the item removing problem, will this be solved to? I have noticed that apart from the problem that I already told you, when you click on the block that opens up the GUI, sometimes the money you deposited will appear on your inventory, with the extended property being unchange by this.
"Player's current money: 20; On client? true Player's current money: 20; On client? true"
Yet you say that is when you deposit, which is supposed to be on the server. So you can see that you are never actually doing anything on the server, but still trying to set data on the client, which is why it does not save.
Try putting println statements in your packet handling class to see if it is doing what you think it should be doing on the side you think it should be doing it on. Println is one of the most powerful debug tools at your disposal, but only if you use it.
Well I know that the packet handler of the packet that tells the server to deposit the money is working because it is the only place where I call the depositAllMoney method. If it is doing it on the server side, I choose that when I register the packet, right?
Well I know that the packet handler of the packet that tells the server to deposit the money is working because it is the only place where I call the depositAllMoney method. If it is doing it on the server side, I choose that when I register the packet, right?
Yes, but your println statements are telling a different story, so either you printed the wrong value to the screen (e.g. NOT world.isRemote instead of world.isRemote), or your code is really only running on the client side, for whatever reason.
Oh, the joys of SimpleNetworkWrapper. What version of Forge are you using? Try updating to the latest, as SNW has been hounded by problems throughout its entire existence, which is why no one used it for a long time (you actually couldn't, because it didn't work at all).
If that doesn't work, honestly I'd say just abandon SNW and try your hand at FMLProxyPacket or even use the old PacketPipeline code - at least then you will know your packets are working as you would expect. SanAndreasP has an open source implementation of FMLProxyPacket which may be useful, but I haven't tried it yet myself.
Oh, the joys of SimpleNetworkWrapper. What version of Forge are you using? Try updating to the latest, as SNW has been hounded by problems throughout its entire existence, which is why no one used it for a long time (you actually couldn't, because it didn't work at all).
If that doesn't work, honestly I'd say just abandon SNW and try your hand at FMLProxyPacket or even use the old PacketPipeline code - at least then you will know your packets are working as you would expect. SanAndreasP has an open source implementation of FMLProxyPacket which may be useful, but I haven't tried it yet myself.
OMG finally! I had the latest version of forge already, so I had to change from SNW to the PacketPipeline code in this tutorial, finally it works. Thank you coolAlias for your time, I learned a lot from you.
OMG finally! I had the latest version of forge already, so I had to change from SNW to the PacketPipeline code in this tutorial, finally it works. Thank you coolAlias for your time, I learned a lot from you.
No problem. Be aware that the PacketPipeline is reported to have memory leaks and is not recommended anymore, but it has always worked perfectly for me and I've never noticed any memory leaks with it; your mileage may vary, and I will be sure to update the tutorial when a better networking solution comes along. I just can't recommend SimpleNetworkWrapper, though, as it does not seem to be very reliable.
Anyway, glad it finally works xD You will still need to send a packet to the client, however, when your player joins the world for the first time, otherwise your client won't know how much money you had saved.
No problem. Be aware that the PacketPipeline is reported to have memory leaks and is not recommended anymore, but it has always worked perfectly for me and I've never noticed any memory leaks with it; your mileage may vary, and I will be sure to update the tutorial when a better networking solution comes along. I just can't recommend SimpleNetworkWrapper, though, as it does not seem to be very reliable.
Anyway, glad it finally works xD You will still need to send a packet to the client, however, when your player joins the world for the first time, otherwise your client won't know how much money you had saved.
I was aware of the PacketPipeline problems, that's why I went with SimpleNetworkWrapper in first place. If it starts causing me problems I will use FMLProxyPacket. And yeah, I'm syncing data when player joins the world, just like you showed in this tutorial.
For anyone still struggling with the new packet system, I have updated my demo mod code to 1.7.10 and SimpleNetworkWrapper.
I also wrote a tutorial on it, though much of the formatting got screwed up by the forum editor and has refused all attempts to correct it - luckily, it's all implemented in the demo mod linked above.
The Meaning of Life, the Universe, and Everything.
Join Date:
11/1/2010
Posts:
56
Minecraft:
yay899
Member Details
I seem to be having some trouble with step 4.1, everywhere ExtendedEntity is mentioned I get an error. I've tried importing to no avail, and ExtendedEntity isn't mentioned anywhere else in the tutorial. Did I miss defining it at some point?
public class ExtendedLivingBase implements IExtendedEntityProperties {
public final static String EXT_PROP_NAME = "ExtendedLivingBase";
private final EntityLivingBase entity;
private int grist;
public ExtendedLivingBase(EntityLivingBase entity) {
this.entity = entity;
}
public static final void register(EntityLivingBase entity) {
entity.registerExtendedProperties(ExtendedLiving.EXT_PROP_NAME, new ExtendedLiving(entity));
}
public static final ExtendedLiving get(EntityLivingBase entity) {
return (ExtendedLiving) entity.getExtendedProperties(EXT_PROP_NAME);
}
@Override
public void saveNBTData(NBTTagCompound compound) {
compound.setInteger("Grist", this.grist);
}
@Override
public void loadNBTData(NBTTagCompound compound) {
I named my class 'ExtendedEntity', even though it was for EntityLivingBase type entities. Sorry that it may not have been very clear, I just didn't feel like typing a long name the whole time
@ForgeSubscribe(priority = EventPriority.NORMAL)
public void onRenderExperienceBar(RenderGameOverlayEvent event) {
// We draw after the ExperienceBar has drawn. The event raised by GuiIngameForge.pre()
// will return true from isCancelable. If you call event.setCanceled(true) in
// that case, the portion of rendering which this event represents will be canceled.
// We want to draw *after* the experience bar is drawn, so we make sure isCancelable() returns
// false and that the eventType represents the ExperienceBar event.
if (event.isCancelable() || event.type != ElementType.EXPERIENCE)
{
return;
}
ExtendedPlayer props = ExtendedPlayer.get(this.mc.thePlayer);
// Don't render if (for some reason) it doesn't exist
if(props == null || props.getMaxTP() == 0) {
return;
}
// Where the gui should start rendering. TODO: find the perf location
int xPos = 2;
int yPos = 2;
// setting all color values to 1.0F will render the texture as it looks in your texture file
//GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
// Somewhere in Minecraft vanilla code it says to do this because of a lighting bug
//GL11.glDisable(GL11.GL_LIGHTING);
// Bind your texture to the render engine
this.mc.getTextureManager().bindTexture(texturePath);
// Add this block of code before you draw the section of your texture containing TRANSPARENCY
GL11.glEnable(GL11.GL_BLEND);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDepthMask(false);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_ALPHA_TEST);
// Here we draw the background bar which contains a transparent section; note the new size
drawTexturedModalRect(xPos, yPos, 0, 0, 5, 50);
// TODO: Change "48" according to how tall the texture is
int timePointsHeight = (int)(((float) props.getCurrentTP() / props.getMaxTP()) * 48);
drawTexturedModalRect(xPos + 1, yPos + 1, 6, 48 - timePointsHeight, 3, 48);
// NOTE: be sure to reset the openGL settings after you're done or your character model will be messed up
GL11.glDisable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthMask(true);
}
2) My point-system isn't working... I sort of debugged it and found that in my addTP(int amount) method, it's not really adding it. The problem is, I have a System.out that outputs the sum of current + amount (which is 1), then I update the DataWatcher, and when I System.out the DataWatcher, I get 0.....
1) Make sure your texture supports alpha layers - the easiest way to get this (for me) is to copy a vanilla texture with the alpha layer and go from there - the hotbar slots are a good example of a texture with alpha transparency, or you could use the one from my git repo.
2) Where are you calling your addTP and other methods from? Make sure it is on the server, and not on the client <ahem>GUI<ahem>. As a general rule, only ever set variables on the server, especially for DataWatcher.
Does your mana_bar_2.png support alpha layers? (Honestly, I'm really lazy, and if I don't have to, I'd rather not look for the hotbar gui... :S) EDIT: sorry I didn't fully read your message >.< I'm so tired...
I'm calling it in a HarvestDropsEvent. I have an !event.world.isRemote check in there... If it helps, I'm also tracking the points through one of my random items using props.getCurrentTP() in addInformation.
Thanks for the fast reply too ;p
EDIT: While I'm asking, would you also mind helping me how to get the player seeing a block's GUI? I want to display the players' points on the Gui...
I *think* I got the tileEntity to recognize which player is using it.
In "onBlockActivated(__)," I got the instance of the tileentity (world.getBlockTileEntity()) & passed it to a method in the tileentity, which initialized the variable "player"
I currently remove the item from the player with the depositAllMoney method that runs from the server when I send the packet. I didn't copy all of my GUI class, there I retrieve the money, that's how I know it is not persisting. Currently it does display the correct value. And finally, you are right, my depositAllMoney method is ugly, I'm rewriting it asap. Also I know what you mean when you said it looks like a class name, I do know some naming conventions, I was just a mistake by my part. I hope I made things clearer. I have no clue why it is not persisting. And by the way, thanks for the time you are taking to reply my messages and helping me.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumPlease print out how much money the player has using 'println' statements in your loadNBTData method, in your depositAllMoney method, and wherever else you think it may be interesting to see; be sure to include the side the player is on so you can get a clearer picture:
System.out.printf("Player's current money: %d; On client? %s", pmoney, player.worldObj.isRemote);My bet is you will see output like this:
You MUST send a packet from the server to the client to tell the client what the value of pmoney is if you want that value available in the Gui. A pretty large section of my tutorial was devoted to explaining this concept - please read the section on creating a Mana Bar very carefully.
On dying:
And if I deposit again and relog:
My packet class:
I called this method in my depositAllMoney method, in my event handler, on onEntityJoinWorld, and when I retrive the extended property.
On dying:
And if I deposit again and relog:
-
View User Profile
-
View Posts
-
Send Message
Curse Premium"Player's current money: 20; On client? true Player's current money: 20; On client? true"
Yet you say that is when you deposit, which is supposed to be on the server. So you can see that you are never actually doing anything on the server, but still trying to set data on the client, which is why it does not save.
Try putting println statements in your packet handling class to see if it is doing what you think it should be doing on the side you think it should be doing it on. Println is one of the most powerful debug tools at your disposal, but only if you use it.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYes, but your println statements are telling a different story, so either you printed the wrong value to the screen (e.g. NOT world.isRemote instead of world.isRemote), or your code is really only running on the client side, for whatever reason.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumIf that doesn't work, honestly I'd say just abandon SNW and try your hand at FMLProxyPacket or even use the old PacketPipeline code - at least then you will know your packets are working as you would expect. SanAndreasP has an open source implementation of FMLProxyPacket which may be useful, but I haven't tried it yet myself.
OMG finally!
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumNo problem. Be aware that the PacketPipeline is reported to have memory leaks and is not recommended anymore, but it has always worked perfectly for me and I've never noticed any memory leaks with it; your mileage may vary, and I will be sure to update the tutorial when a better networking solution comes along. I just can't recommend SimpleNetworkWrapper, though, as it does not seem to be very reliable.
Anyway, glad it finally works xD You will still need to send a packet to the client, however, when your player joins the world for the first time, otherwise your client won't know how much money you had saved.
I was aware of the PacketPipeline problems, that's why I went with SimpleNetworkWrapper in first place. If it starts causing me problems I will use FMLProxyPacket. And yeah, I'm syncing data when player joins the world, just like you showed in this tutorial.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumDo you know what a NullPointerException is? If not, Google it. You will probably find the solution as well (i.e. check for null).
-
View User Profile
-
View Posts
-
Send Message
Curse Premium-
View User Profile
-
View Posts
-
Send Message
Curse PremiumI also wrote a tutorial on it, though much of the formatting got screwed up by the forum editor and has refused all attempts to correct it - luckily, it's all implemented in the demo mod linked above.
public class ExtendedLivingBase implements IExtendedEntityProperties {
public final static String EXT_PROP_NAME = "ExtendedLivingBase";
private final EntityLivingBase entity;
private int grist;
public ExtendedLivingBase(EntityLivingBase entity) {
this.entity = entity;
}
public static final void register(EntityLivingBase entity) {
entity.registerExtendedProperties(ExtendedLiving.EXT_PROP_NAME, new ExtendedLiving(entity));
}
public static final ExtendedLiving get(EntityLivingBase entity) {
return (ExtendedLiving) entity.getExtendedProperties(EXT_PROP_NAME);
}
@Override
public void saveNBTData(NBTTagCompound compound) {
compound.setInteger("Grist", this.grist);
}
@Override
public void loadNBTData(NBTTagCompound compound) {
this.grist = compound.getInteger("Grist");
System.out.println("[LIVING BASE] Grist from NBT: " + this.grist);
}
@Override
public void init(Entity entity, World world) {
this.grist = world.rand.nextInt(30);
System.out.println("[LIVING BASE] Grist: " + this.grist);
}
}
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumI think I got through all your steps, but 2 major things are happening:
1) The GUI (w/ transparency) isn't working.
http://imgur.com/N6CgkcD
sorry the gui is so small...
Code:
*Is this copyright? I re-typed it verbatim*
@ForgeSubscribe(priority = EventPriority.NORMAL) public void onRenderExperienceBar(RenderGameOverlayEvent event) { // We draw after the ExperienceBar has drawn. The event raised by GuiIngameForge.pre() // will return true from isCancelable. If you call event.setCanceled(true) in // that case, the portion of rendering which this event represents will be canceled. // We want to draw *after* the experience bar is drawn, so we make sure isCancelable() returns // false and that the eventType represents the ExperienceBar event. if (event.isCancelable() || event.type != ElementType.EXPERIENCE) { return; } ExtendedPlayer props = ExtendedPlayer.get(this.mc.thePlayer); // Don't render if (for some reason) it doesn't exist if(props == null || props.getMaxTP() == 0) { return; } // Where the gui should start rendering. TODO: find the perf location int xPos = 2; int yPos = 2; // setting all color values to 1.0F will render the texture as it looks in your texture file //GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); // Somewhere in Minecraft vanilla code it says to do this because of a lighting bug //GL11.glDisable(GL11.GL_LIGHTING); // Bind your texture to the render engine this.mc.getTextureManager().bindTexture(texturePath); // Add this block of code before you draw the section of your texture containing TRANSPARENCY GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glDepthMask(false); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GL11.glDisable(GL11.GL_ALPHA_TEST); // Here we draw the background bar which contains a transparent section; note the new size drawTexturedModalRect(xPos, yPos, 0, 0, 5, 50); // TODO: Change "48" according to how tall the texture is int timePointsHeight = (int)(((float) props.getCurrentTP() / props.getMaxTP()) * 48); drawTexturedModalRect(xPos + 1, yPos + 1, 6, 48 - timePointsHeight, 3, 48); // NOTE: be sure to reset the openGL settings after you're done or your character model will be messed up GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glDepthMask(true); }2) My point-system isn't working... I sort of debugged it and found that in my addTP(int amount) method, it's not really adding it. The problem is, I have a System.out that outputs the sum of current + amount (which is 1), then I update the DataWatcher, and when I System.out the DataWatcher, I get 0.....
Code: http://pastebin.com/kCDJVPuV
:3
-
View User Profile
-
View Posts
-
Send Message
Curse Premium2) Where are you calling your addTP and other methods from? Make sure it is on the server, and not on the client <ahem>GUI<ahem>. As a general rule, only ever set variables on the server, especially for DataWatcher.
3) You're welcome xD
Does your mana_bar_2.png support alpha layers? (Honestly, I'm really lazy, and if I don't have to, I'd rather not look for the hotbar gui... :S)EDIT: sorry I didn't fully read your message >.< I'm so tired...I'm calling it in a HarvestDropsEvent. I have an !event.world.isRemote check in there... If it helps, I'm also tracking the points through one of my random items using props.getCurrentTP() in addInformation.
Thanks for the fast reply too ;p
EDIT: While I'm asking, would you also mind helping me how to get the player seeing a block's GUI? I want to display the players' points on the Gui...
I *think* I got the tileEntity to recognize which player is using it.
In "onBlockActivated(__)," I got the instance of the tileentity (world.getBlockTileEntity()) & passed it to a method in the tileentity, which initialized the variable "player"
:3