Would it be possible to replenish the mana over time? If so, how would I do this?
Yes; all you need to do is make some kind of counter, increment or decrement it during any one of the update ticks that are available (see the first post for more about tick events and alternatives), and then replenish your mana by whatever amount you want when the counter reaches zero or some other value you decide on. There is an example of this in my sample 1.7.2 mod in my github repo, linked in the main post.
Is it also possible to get this IExtendedEntityProperties, so I can use these Variables in any Class?
No, they only work for classes that extend Minecraft's Entity class. If you need to add variables to other Minecraft classes, you'll have to find some other way to do it (such as Reflection or ASM byte-code manipulation).
Hey, quick question:
I've had this working for a long time now. Recently updating to 1.7.2, I again looked at this tutorial and got my packets working and everything. However, now there's a memory leak in the Netty packet handling. Not sure how much it affects everything, but I can't seem to figure out how to fix it. Do you know how to use a "SimpleNetworkWrapper", as most people reference? There seem to be no tutorials or anything on how packet handling works now.
Hey, quick question:
I've had this working for a long time now. Recently updating to 1.7.2, I again looked at this tutorial and got my packets working and everything. However, now there's a memory leak in the Netty packet handling. Not sure how much it affects everything, but I can't seem to figure out how to fix it. Do you know how to use a "SimpleNetworkWrapper", as most people reference? There seem to be no tutorials or anything on how packet handling works now.
Thanks,
LittleBreadLoaf
Not much to it - basically the AbstractPacket class we had before no longer extends anything, but instead implements IMessage and IMessageHandler; this will give you basically the same functionality but with renamed methods, and you don't need the packet pipeline anymore. See EquivalentExchange3 code for an example. Unlike the explicit packet IDs in Pahimar's code, however, I recommend using a self-incrementing index when registering packets - it makes it much easier for you when adding new packets if you are OCD like me and like your packets alphabetically and numerically ordered
EDIT AGAIN: This Tutorial didn't worked for me, Mana Bar isn't updating if i consume Mana.
You must have missed one or two of the steps. Try following the tutorial again, making sure to open every spoiler in every single section; each step builds on the last, so if you skip any part of it, chances are your code will have some problems. If you need further help, you can go to the linked github repository and see my 1.7.2 example mod, but be aware that I haven't updated the network from the supposed 'memory-leak' causing version (I say 'supposed' because I have yet to see evidence that it actually causes any problems, but I also haven't looked too closely at the code).
I've checked over this entire thing 4 times now.
((ExtendedPlayer)(event.entity.getExtendedProperties(ExtendedPlayer.EXT_PROP_NAME))).syncExtendedProperties();
whatt syncExtendedProperties() is supposed to be is never covered. There is .sync() but that code is no longer valid for 1.7.2
It is explained in section 3.3:
Okay, well that will send a packet whenever we call it. Problem is, we don't call it anywhere yet. You could do it in onLivingUpdate or some such, but that would unnecessarily spam packets which would be no good. We only want to call it when any of the information stored in ExtendedPlayer changes, in our case, when current or max mana is modified.
Here you can see my implementations for setCurrentMana and setMaxMana:
/**
* Sets current mana to amount or maxMana, whichever is lesser
*/
public void setCurrentMana(int amount)
{
this.currentMana = (amount < this.maxMana ? amount : this.maxMana);
this.sync();
}
/**
* Sets max mana to amount or 0 if amount is less than 0
*/
public void setMaxMana(int amount)
{
this.maxMana = (amount > 0 ? amount : 0);
this.sync();
}
Note that we add a call to sync() our ExtendedProperties in each of these methods because they changed our stored variables. We also need to sync the properties in any other methods that do so, like consumeMana and replenishMana.
The only point of the sync method was to build an appropriate packet, back in the day when people thought it was a good idea to build packets from scratch all over the place, rather than placing such code inside of individual packet classes. You could still keep the sync method if you want, but ideally you will create whatever packets you require and just send them when appropriate; instead of calling props.sync() when your mana changes, you will instead send PacketManaChanged or whatever directly from the methods involved (e.g. setCurrentMana, etc.).
But does anyone know how i regenerate Mana? I already created a TickHandler but don't know how i should start.
Please see the first post about events, specifically TickEvents and when you shouldn't use them In this case, if you only ever plan on players having mana, you can get away with it.
Any time you want to do something in Java, you need to think about it in logical steps. How can you regenerate mana? Well, what is regeneration? Regeneration could be defined as recovering some amount x every y number of time units; phrased another way, for every y amount of time that passes, you gain x amount of mana.
You have a class/method that is called by Minecraft every tick, and a tick is a unit of time; 20 ticks = 1 second. How can you keep track of how much time has passed? Typical programming tactic is to create a variable, and every time the method is called (remember, it's called every tick!), you increment the variable - voilá, time tracked. Now you just need to decide how much time needs to pass before you regain one point of mana, and implement that.
This is really about as basic as it gets, so if you are having trouble, you may need to spend some time reviewing basic Java concepts such as variables, methods, and conditional statements, as well as the basic logic operators and how they are used. Really, almost everything in Java (and other programming languages) boils down to logic; if you can explain how a mechanic ought to work in words, then you very likely can implement said mechanic in any language you want.
int ticks = 0;
@SubscribeEvent
public void onPlayerTick(PlayerTickEvent event) {
EntityPlayer player = (EntityPlayer) event.player;
ExtendedPlayer props = ExtendedPlayer.get(player);
int mana = props.getCurrentMana();
int maxmana = props.getMaxMana();
if (mana < maxmana)
{
if (event.phase == Phase.START) {
}
if (event.phase == Phase.END) {
ticks = ticks + 1;
System.out.println("Current Ticks:" + ticks);
if(ticks > 600)
{
props.increaseMana(10);
ticks = 0;
}
}
}
SO IM THANKING YOU SO MUCH FOR AWESOME TUTORIALS LIKE THIS!
Sure thing guys xD
For your implementation, make sure that your increaseMana() method, when called on the server side, sends the correct current amount to the client, or you could end up with different amounts; better yet, only run that code when you are on the server, and only during one of the phases:
@SubscribeEvent
public void onPlayerTick(PlayerTickEvent event) {
// checking first will remove unnecessary processing:
if (event.phase == Phase.END && !event.player.worldObj.isRemote) { // END phase and on server
ExtendedPlayer props = ExtendedPlayer.get(event.player); // not really necessary to cast when you've got EntityPlayer already
// code for timer and mana regen
}
}
Another thing that I do is instead of updating things inside the tick handler, I instead have it call an update method within my extended properties, so I can keep everything related to extended properties within the same 'package', so to speak (not the technical Java term).
@SubscribeEvent
public void onPlayerTick(PlayerTickEvent event) {
ExtendedPlayer.get(event.player).onUpdate();
}
// in extended properties:
private int timer;
public void onUpdate() {
++timer;
if (timer > 600) {
regenMana(10);
timer = 0;
}
}
Nothing wrong with the way you did it, just my personal organizational preference.
If you want, you can see my full ExtendedPlayer implementation here, including mana regen and custom inventory slots.
Ok, I can't figure out what I've done wrong. Code runs, nothing saves or carries over after death. Maybe someone could take a look and let me know what I've done wrong? Really quite new to Forge Modding, I really badly want to make this mod I have in mind though and this is the building point for it.
Ok, I can't figure out what I've done wrong. Code runs, nothing saves or carries over after death. Maybe someone could take a look and let me know what I've done wrong? Really quite new to Forge Modding, I really badly want to make this mod I have in mind though and this is the building point for it.
Did you read step 5?
See the following classes in my demo implementation:
Yea I've read step 5, I will take a look at it as soon as I've got some time and report back...hopefully with great success! lol
So 1: I had getCurrentMana() and setCurrentMana() reversed (no idea how I managed that, I did read word for word.
I've gone over this again, and it still will not save any data. I am supposed to be using .getDisplayName() since .username does not exist correct?
Would it be possible for you to just update your 1.7.2 tutorial files to implement persistence? I learn best by looking at code, following tutorials tends to be very difficult for me, especially when I have to follow it for 1.6.4 then transition to 1.7.2 and continue to follow code written for 1.6.4 and try to figure out how it needs to be modified.
Sorry if I sound demanding or rude or anything, I am just frustrated.
Would it be possible for you to just update your 1.7.2 tutorial files to implement persistence? I learn best by looking at code, following tutorials tends to be very difficult for me, especially when I have to follow it for 1.6.4 then transition to 1.7.2 and continue to follow code written for 1.6.4 and try to figure out how it needs to be modified.
The demo mod already does implement persistent data. I use player.getCommandSenderName(), but you should be able to use whatever you want as long as it is unique to each player and the same each time the player logs on.
The concepts demonstrated in this tutorial should be identical regardless of Minecraft version, though the implementation details will differ slightly. I've tried to explain the why of each step as best as possible, as once you understand that, the rest falls into place much more easily.
It helps, of course, if you did some modding in 1.6.4 first, but that's why I put up the 1.7.2 demo mod. It implements everything in this tutorial as well as the Custom Inventory tutorial, and you can even download the entire code base from Github and try it out for yourself.
The demo mod already does implement persistent data. I use player.getCommandSenderName(), but you should be able to use whatever you want as long as it is unique to each player and the same each time the player logs on.
The concepts demonstrated in this tutorial should be identical regardless of Minecraft version, though the implementation details will differ slightly. I've tried to explain the why of each step as best as possible, as once you understand that, the rest falls into place much more easily.
It helps, of course, if you did some modding in 1.6.4 first, but that's why I put up the 1.7.2 demo mod. It implements everything in this tutorial as well as the Custom Inventory tutorial, and you can even download the entire code base from Github and try it out for yourself.
Ok, so maybe I am just entirely confused at all ends. You are saying the Tutorial-1.7.2 demo mod code IS persistent? Then I may have just not understood anything at all from the beginning lol and I apologize if that is the case. Now I really just need to figure out why data is not persisting for me if that is the case, I die... everything is reset to the original numbers.
Hey Alias, i have a Problem with my created Mob do you know a method that my custom mob attack's my other custom mob pls dont this AI Method cause if i rewrite the Entity to AI then my Mob can't use the Fireballs of Blaze that he needs.
If you don't want to use AI, you have to code it manually. That's a good question for the Modification Development section
Ok, so maybe I am just entirely confused at all ends. You are saying the Tutorial-1.7.2 demo mod code IS persistent? Then I may have just not understood anything at all from the beginning lol and I apologize if that is the case. Now I really just need to figure out why data is not persisting for me if that is the case, I die... everything is reset to the original numbers.
No worries. You only need to do 2 things to get your data to persist correctly, and an optional 3rd:
1. When the player dies, store the data as NBT somewhere (I use a HashMap in CommonProxy)
2. When the player re-joins the world, overwrite the player's current data with the data that was stored for them
3. (Optional) Send a packet to the client if you want the client side to have the correct values (only needed for rendering, GUI, etc.)
I'm guessing you missed the 3rd step, so it looks like your data is not the same. Put some println statements printing the value of your data and the current side that you are on (println("Is client side? " + player.worldObj.isRemote) will print true or false for you), then you will see where the discrepancy lies and further debug if needed.
Hi, coolAlias, I've read your tutorial and personally I think It's one of the bests tutorial about minecraft events.
It helped me a lot but now I have a problem: I'd like to check when the FlowerPot is right clicked with a new flower of my mod (currently equipped to the player) and to replace the vanilla flower pot with my own version.
Is there an event regarding the flower pots? Or maybe an event about block right clicking?
Thanks.
Thanks, yes, there is PlayerInteractEvent, which has an enumerated field named 'action' which is either LEFT_CLICK_BLOCK, RIGHT_CLICK_BLOCK, or (I think) RIGHT_CLICK_AIR. If the event posts as RIGHT_CLICK_BLOCK, then you'll have coordinates to check if it's a flower pot that way, as well as the player to see if they are holding your flowers. The event is, of course, cancelable, but you may not need to worry about that if your flowers don't interact normally with blocks.
Another option, if your custom flowers have their own item class, is to just use the override onItemUse method in your class, as that's called every time you right click on a block with your item and has the coordinates clicked. Overriding class methods when possible is much better than using events.
The Meaning of Life, the Universe, and Everything.
Location:
Vancouver, WA USA
Join Date:
1/21/2014
Posts:
73
Member Details
I'm trying to find an event hook for my onEnchantment method, but I don't see one anywhere. How would you create an achievement for placing a certain enchantment on any book or item? Placing any enchantment on a certain item?
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumSend a packet to the client with the new level and/or display name
Yes; all you need to do is make some kind of counter, increment or decrement it during any one of the update ticks that are available (see the first post for more about tick events and alternatives), and then replenish your mana by whatever amount you want when the counter reaches zero or some other value you decide on. There is an example of this in my sample 1.7.2 mod in my github repo, linked in the main post.
if(mc.gameSettings.language == "en_US")
{
blablabla...
}
Make high-quality models in the Techne. And do the model in Blender.
instead
Art by me: [email protected]
This work, thank you =D
Make high-quality models in the Techne. And do the model in Blender.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumNo, they only work for classes that extend Minecraft's Entity class. If you need to add variables to other Minecraft classes, you'll have to find some other way to do it (such as Reflection or ASM byte-code manipulation).
I've had this working for a long time now. Recently updating to 1.7.2, I again looked at this tutorial and got my packets working and everything. However, now there's a memory leak in the Netty packet handling. Not sure how much it affects everything, but I can't seem to figure out how to fix it. Do you know how to use a "SimpleNetworkWrapper", as most people reference? There seem to be no tutorials or anything on how packet handling works now.
Thanks,
LittleBreadLoaf
Bleach Mod
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumNot much to it - basically the AbstractPacket class we had before no longer extends anything, but instead implements IMessage and IMessageHandler; this will give you basically the same functionality but with renamed methods, and you don't need the packet pipeline anymore. See EquivalentExchange3 code for an example. Unlike the explicit packet IDs in Pahimar's code, however, I recommend using a self-incrementing index when registering packets - it makes it much easier for you when adding new packets if you are OCD like me and like your packets alphabetically and numerically ordered
Sorry, that's beyond the scope of this tutorial.
You must have missed one or two of the steps. Try following the tutorial again, making sure to open every spoiler in every single section; each step builds on the last, so if you skip any part of it, chances are your code will have some problems. If you need further help, you can go to the linked github repository and see my 1.7.2 example mod, but be aware that I haven't updated the network from the supposed 'memory-leak' causing version (I say 'supposed' because I have yet to see evidence that it actually causes any problems, but I also haven't looked too closely at the code).
-
View User Profile
-
View Posts
-
Send Message
Curse Premium((ExtendedPlayer)(event.entity.getExtendedProperties(ExtendedPlayer.EXT_PROP_NAME))).syncExtendedProperties();
whatt syncExtendedProperties() is supposed to be is never covered. There is .sync() but that code is no longer valid for 1.7.2
You'll have to use the screen height/width and divide it to get your image size/position if I am not mistaken.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumIt is explained in section 3.3:
Okay, well that will send a packet whenever we call it. Problem is, we don't call it anywhere yet. You could do it in onLivingUpdate or some such, but that would unnecessarily spam packets which would be no good. We only want to call it when any of the information stored in ExtendedPlayer changes, in our case, when current or max mana is modified.
Here you can see my implementations for setCurrentMana and setMaxMana:
/** * Sets current mana to amount or maxMana, whichever is lesser */ public void setCurrentMana(int amount) { this.currentMana = (amount < this.maxMana ? amount : this.maxMana); this.sync(); } /** * Sets max mana to amount or 0 if amount is less than 0 */ public void setMaxMana(int amount) { this.maxMana = (amount > 0 ? amount : 0); this.sync(); }Please see the first post about events, specifically TickEvents and when you shouldn't use them
Any time you want to do something in Java, you need to think about it in logical steps. How can you regenerate mana? Well, what is regeneration? Regeneration could be defined as recovering some amount x every y number of time units; phrased another way, for every y amount of time that passes, you gain x amount of mana.
You have a class/method that is called by Minecraft every tick, and a tick is a unit of time; 20 ticks = 1 second. How can you keep track of how much time has passed? Typical programming tactic is to create a variable, and every time the method is called (remember, it's called every tick!), you increment the variable - voilá, time tracked. Now you just need to decide how much time needs to pass before you regain one point of mana, and implement that.
This is really about as basic as it gets, so if you are having trouble, you may need to spend some time reviewing basic Java concepts such as variables, methods, and conditional statements, as well as the basic logic operators and how they are used. Really, almost everything in Java (and other programming languages) boils down to logic; if you can explain how a mechanic ought to work in words, then you very likely can implement said mechanic in any language you want.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumThank you very much ErtuKN for the helpful information =)
Note: No more 30+ hour coding sessions lol.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumSure thing guys xD
For your implementation, make sure that your increaseMana() method, when called on the server side, sends the correct current amount to the client, or you could end up with different amounts; better yet, only run that code when you are on the server, and only during one of the phases:
@SubscribeEvent public void onPlayerTick(PlayerTickEvent event) { // checking first will remove unnecessary processing: if (event.phase == Phase.END && !event.player.worldObj.isRemote) { // END phase and on server ExtendedPlayer props = ExtendedPlayer.get(event.player); // not really necessary to cast when you've got EntityPlayer already
// code for timer and mana regen
}
}Another thing that I do is instead of updating things inside the tick handler, I instead have it call an update method within my extended properties, so I can keep everything related to extended properties within the same 'package', so to speak (not the technical Java term).
@SubscribeEvent public void onPlayerTick(PlayerTickEvent event) { ExtendedPlayer.get(event.player).onUpdate(); } // in extended properties: private int timer; public void onUpdate() { ++timer; if (timer > 600) { regenMana(10); timer = 0; } }If you want, you can see my full ExtendedPlayer implementation here, including mana regen and custom inventory slots.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumCommon Proxy
Event Handler
ExtendedPlayer
ExtendedLiving
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumDid you read step 5?
See the following classes in my demo implementation:
EventHandler | ExtendedPlayer | CommonProxy
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumSo 1: I had getCurrentMana() and setCurrentMana() reversed (no idea how I managed that, I did read word for word.
I've gone over this again, and it still will not save any data. I am supposed to be using .getDisplayName() since .username does not exist correct?
Would it be possible for you to just update your 1.7.2 tutorial files to implement persistence? I learn best by looking at code, following tutorials tends to be very difficult for me, especially when I have to follow it for 1.6.4 then transition to 1.7.2 and continue to follow code written for 1.6.4 and try to figure out how it needs to be modified.
Sorry if I sound demanding or rude or anything, I am just frustrated.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumThe demo mod already does implement persistent data. I use player.getCommandSenderName(), but you should be able to use whatever you want as long as it is unique to each player and the same each time the player logs on.
The concepts demonstrated in this tutorial should be identical regardless of Minecraft version, though the implementation details will differ slightly. I've tried to explain the why of each step as best as possible, as once you understand that, the rest falls into place much more easily.
It helps, of course, if you did some modding in 1.6.4 first, but that's why I put up the 1.7.2 demo mod. It implements everything in this tutorial as well as the Custom Inventory tutorial, and you can even download the entire code base from Github and try it out for yourself.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumOk, so maybe I am just entirely confused at all ends. You are saying the Tutorial-1.7.2 demo mod code IS persistent? Then I may have just not understood anything at all from the beginning lol and I apologize if that is the case. Now I really just need to figure out why data is not persisting for me if that is the case, I die... everything is reset to the original numbers.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumIf you don't want to use AI, you have to code it manually. That's a good question for the Modification Development section
No worries. You only need to do 2 things to get your data to persist correctly, and an optional 3rd:
1. When the player dies, store the data as NBT somewhere (I use a HashMap in CommonProxy)
2. When the player re-joins the world, overwrite the player's current data with the data that was stored for them
3. (Optional) Send a packet to the client if you want the client side to have the correct values (only needed for rendering, GUI, etc.)
I'm guessing you missed the 3rd step, so it looks like your data is not the same. Put some println statements printing the value of your data and the current side that you are on (println("Is client side? " + player.worldObj.isRemote) will print true or false for you), then you will see where the discrepancy lies and further debug if needed.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumThanks, yes, there is PlayerInteractEvent, which has an enumerated field named 'action' which is either LEFT_CLICK_BLOCK, RIGHT_CLICK_BLOCK, or (I think) RIGHT_CLICK_AIR. If the event posts as RIGHT_CLICK_BLOCK, then you'll have coordinates to check if it's a flower pot that way, as well as the player to see if they are holding your flowers. The event is, of course, cancelable, but you may not need to worry about that if your flowers don't interact normally with blocks.
Another option, if your custom flowers have their own item class, is to just use the override onItemUse method in your class, as that's called every time you right click on a block with your item and has the coordinates clicked. Overriding class methods when possible is much better than using events.
-
View User Profile
-
View Posts
-
Send Message
Curse Premium