jabelar
Members-
Posts
3266 -
Joined
-
Last visited
-
Days Won
39
Everything posted by jabelar
-
Change protected foodStats in an EntityPlayer?
jabelar replied to Alix_The_Alicorn's topic in Modder Support
This is where I trip up in Java (compared to some other languages), but I think diesieben07 is confirming that the getter is actually passing the reference (people argue whether this is technically pass by reference or not, but that's the way I think of it) to the actual private field and so you can modify it once it is passed to you. In other words, the returned value from the getter is not a copy, but rather the original field! (In contrast, if the getter was properly encapsulated I think it would either have to create a copy, or otherwise break down the getting so that the private field wasn't passed in a modifiable way.) If you look at the comment for the getter it says it gets the FoodStats object. That's Java for you. Note that I think this works differently with primitive types because Java doesn't make those objects. So a getter for a list or something will pass the list, but getter for an int should not allow it to be modified. I'm really just groping here though so you should get it confirmed from more reputable Java programmer. -
I think the problem is that the vanilla enitities do have number of packets traversing around to keep things in sync, and it is entirely possible that the golem attackTimer is somehow sync'ed with those. I poked around in the various packets (e.g. look in net.minecraft.network.play.server and net.minecraft.network.play.client packages) and couldn't find an actual reference to this, but you can see from the sheer wealth of packet types that it is very possible that this sync is happening. I think you could possibly use the DataWatcher to do the syncing, especially if your counter could be contained in a single byte. I haven't used DataWatcher much, but it is basically a very small amount of data that is kept in sync for you. It is really only suitable for passing booleans and bytes.
-
Looking for API Documentation or Reference documentation
jabelar replied to crazycodr's topic in Modder Support
I like documentation too. That is why I've been trying to write a number of text tutorials that actually explain (rather than just give example). Since it is a really big project and I assume you'd want to allow multiple contributors, I think wiki format would be suitable. But I think the problem is still the format of the information. Do you want this to just be a simple API documentation where every public method is explained? The question then is what the level of explanation is. For example, listing methods and parameter types isn't much more useful than the code itself in my opinion. That is why I've been concentrating on tutorials -- they may be haphazard in terms of topics covered, but when they cover a topic a tutorial give a lot of explanation that is difficult to document except in the context of trying to implement something specific. Anyway, can you give an example of what kind of documentation you're really interested in providing/collecting? -
You could probably fake the effect by just changing the texture of the entity so that the back has a fully open window (none of the lattice between the panes).
-
Change protected foodStats in an EntityPlayer?
jabelar replied to Alix_The_Alicorn's topic in Modder Support
Okay, scope is one area of Java that I find a little different than other languages, so maybe I'm wrong. The FoodStats() class has public methods, but the foodStats field in the EntityPlayer is a protected instance of FoodStats. So I don't think he can call the methods, right? EntityPlayer does have an addExhaustion() method that is public and affects foodStats, but that seems to be about it. -
Minecraft has the KeyBinding class that maps all the keycodes and their pressed state, and it has public method to set the state of whether it is pressed. So I suspect it is possible to interact with that from your serial processing code. The only thing I'm not sure of is whether it would fire the proper key press events. I think in that case you might need to copy the code that normally happens during key press event, maybe in your own custom event to give some equivalence. Anyway, I think tracing from the KeyBinding code might be good place to start.
-
When mob is attacking or colliding with a block
jabelar replied to Soulas97's topic in Modder Support
This would cool but would be very difficult. It is difficult because normally all entities use "path finding" to move between locations or to move towards and attack target. So you'd have to first find a way to get the entity to "want" to move through the blocks. Secondly, in addition to path finding, there are other methods that prevent an actual collision -- an entity simply can't move into most blocks so it can't really "collide" with a block. I can think of a couple of approaches but I think they would be pretty difficult. For example, you could replace the blocks between the entity and its target with some custom blocks that allow path finding to go through them, then as the entity went through them you could destroy them. Another approach would be to take full control of the entity's movement when it was "angry" (i.e. had a non-null attack target) and have it go straight at the target and try to destroy the vanilla blocks just before the entity collides with them. -
I posted correction on your other thread with topic on the attacking, but I made mistake in the code for the mob attack -- instead of the movementSpeed attribute it should be (of course) the attackDamage attribute. Be sure to correct your code.
-
Correction, previously the code I posted I put in the movementSpeed attribute when of course it should be the attackDamage attribute. I've corrected it above. I'll all PM you to make sure you are aware of the correction.
-
You said "game object" but what exactly did you mean. Is it an entity, or a block, or an item, or special item like armor? More importantly is it a custom object or a vanilla object? If it is a custom object, then most of the main classes you'd extend will have some sort of method like onUpdate(), or onLivingUpdate() or similar. Those methods are automatically called every tick, and since it is your own custom class you can override those methods to do what you want. If it is a vanilla object, then you need to do event handling. You can subscribe to a tick event, like the server tick event, and then find the game objects you care about (like search through all EntityCow if you wanted to modify the cows) and then do what you want. So basically it depends on exactly what object you want to affect.
-
HELP! Weird Entity behaviour with setPositionAndRotation
jabelar replied to Bedrock_Miner's topic in Modder Support
The built-in fields for entities should be automatically synced between client and server. You only have to worry about syncing when you add custom fields. So assuming you're using built-in posX type fields, then they should be synced. Note that perhaps you have a typo or perhaps you have accidently declared local variables that are actually being accessed. In Eclipse you should hover over the posX variables and see what Eclipse says about where they are declared. You want to confirm that they are the ones you inherited from the Entity class, not something you declared yourself. -
I currently use that system for controlling my animations, yes. It does work, and I've used it for this purpose. Recently, however, there seems to be confidence that we can switch to using the SimpleNetworkWrapper implementation provided by Forge. I think if you're going to invest in implementing a packet system, you should try that first since it should be the one people use going forward. I personally plan to switch over when I can find some time. But mine does work fine too. I think my tutorial is still good to teach the basic concepts -- all the Netty-based systems need to do the same general things, which I explain.
-
Oh, well one of the problems with doing animations is that the animation is done on the client side but usually the logic that controls the logic is done on the server side. So you often need to use a packet to sync the two sides. For example, you probably need to send a custom packet to keep the attackTimer synced. It is a pain, but as far as I know necessary. To prove this, you should print out debug statements that show what side the code is executing on (i.e. the worldObj.isRemote kind of check). I think you'll see that your attackTimer is being set on server and checked on client.
-
This is due to your Eclipse setup. If you follow most setup tutorials they give you certain application parameters to use in your Run configuration. However, if they don't tell you about username, then every time you login you get a random player username. So if you want the player to have consistent association to other code (like owner id for a tamed pet) then you need to specify the username. I think (just google for it) that in your run configuration you should add the parameter --username testUser or similar. I think you can put any name in for the test user. Then every time you run it should have same user and then things like taming should persist.
-
That looks fairly correct. I suggest just putting in some console messages (with System.out.println() method) to print out where you are in the code and what the attackTimer value is at that time to help trace the code logic. You should have console message when you first set the attackTimer to 50, then again after each if statement that tests the value. That should tell you a fair bit.
-
Can you post the code from your entity class that declares and changes the variable that you're using to control the animation? I expect maybe you declared the field as a static?
-
HELP! Weird Entity behaviour with setPositionAndRotation
jabelar replied to Bedrock_Miner's topic in Modder Support
Is the actual collision box of the entity up in the air, or just the rendered model? If you really want to visually check where the entity is on the client side you should press F3+B while playing the game -- this will show you the bounding box of the entity. I recommend doing that with all custom entities. Anyway, I'm suggesting that your entity might actually be in proper position but your model might be rendering in wrong position. If that is the case, you'll see the bounding box isn't on the entity when you view it. To fix that you'd have to check whether your model has correct rotation points, or you can also just translate the model during rendering. -
The way I do animation cycle is with a 2D array of rotation values. Each row by default represents 1 tick of the game. So if you want to adjust the speed of the animation cycle you would add extra rows to the cycle (ideally with angles that are in between the angles of the rows above and below to ensure smooth animation). That creates a cycle, but sometimes you want a cycle to happen once and sometimes you want it to happen repeatedly for some amount of time or sometimes you want it to happen continuously. To control animations you will need some booleans and maybe int counters in your custom entity class, and you'll need to check those in your Model class to control the animation. For example I have an EntityElephant that will rear up when attacked instead of running away. So in the elephant class I create a public boolean field called isRearing and set it to true when attacked. Then in the model I check the state of the isRearing variable and if true I set angles based on the animation cycle for rearing. When the cycle index counter gets to the end of the animation I clear the isRearing field. So this makes a one time animation. But yes you could use a timer counter as well. The main point is you do need other variables to control the animations, and it really depends on your situation. For example another entity I created is a snake and so I control the animation based on movement -- I want it to slither when moving. Another entity I created is an eagle and it has a lot of different types of animations -- the way it flaps its wings is different when it is soaring versus when it is diving.
-
Looking for API Documentation or Reference documentation
jabelar replied to crazycodr's topic in Modder Support
@crazycodr, I think you have to understand what Minecraft modding is. Minecraft was not really meant to be modded -- so Mojang does not document and in fact obfuscates their code. So any modding has to essentially be reverse engineered by the community of interested modders. The people that are reverse engineering it are (as far as I know) essentially a volunteer group that is painstakingly tracing the undocumented result of decompilation and creating mapping to human-readable method and field names and adding comments to the code. Then there is FML and Forge, which again are volunteer group adding hooks to the code to make it easier to intercept and interact with the vanilla code. The key here is that this is volunteer community. So the work is incomplete and inconsistent, and even buggy at times. There are some functions that are well understood and named well and documented well, and there are others that are still called something like f_423435_a() with no documentation at all. I've found bugs where things are mis-named, sometimes dangerously (i.e. the logic is backwards). Lastly, every time Mojang does a major update the entire process has to be done over again. That is why there are only a couple supported versions of Forge (common are 1.6.4 and 1.7.2) and frankly 1.7.2 is still a work in progress (although it is pretty useable now). Basically I'm saying you're asking for too much. There is no commercial company providing this, there are several different contributors that are loosely working together, and it is still a work in progress. So the best way to learn it is simply to follow the decompiled source provided and put that together with your knowledge of Minecraft (like if you see code that treats an anvil differently, you should know that is because an anvil is different in behavior in Minecraft) and get hints from tutorials. -
I've got a tutorial that might help: http://jabelarminecraft.blogspot.com/p/complex-entity-models-including.html
-
The damage done during an attack is actually very convoluted in the Minecraft code. It is done in the attackEntityAsMob() method which you need to override (it is inherited in EntityLivingBase class where it does nothing but update the last attacker) In the EntityWolf class I think it does something like: @Override public boolean attackEntityAsMob(Entity par1Entity) { int i = isTamed() ? 4 : 2; return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), i); } However that isn't really good coding because it should really call the super method to ensure the last attacker is updated and also it should get the damage value from the attribute instead of hard-coded as 2 (or 4 if tamed). However, the weird thing is that I think the EntityLivingBase attackEntityAsMob() method has an error in it -- it has this.setLastAttacker(par1Entity) but that is backwards I think -- should be par1Entity.setLastAttacker(this). Anyone else agree. Anyway, since the wolf class seems to not care about setting last attacker and because it seems backwards to me, I guess just leave it out. But normally you'd want to consider calling or copying the super method. Overall, to get damage occurring you can modify the method to be something like: @Override public boolean attackEntityAsMob(Entity par1Entity) { return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), (float) getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue()); } As you can see, this doesn't deal damage directly because it wants to let the entity that is hit fully process the attack (for example maybe it has hurt resistance in effect) before fully deciding the damage to deal. Anyway, hope this helps.
-
The damage done during an attack is actually very convoluted in the Minecraft code. It is done in the attackEntityAsMob() method which you need to override (it is inherited in EntityLivingBase class where it does nothing but update the last attacker) In the EntityWolf class I think it does something like: @Override public boolean attackEntityAsMob(Entity par1Entity) { int i = isTamed() ? 4 : 2; return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), i); } However that isn't really good coding because it should really call the super method to ensure the last attacker is updated and also it should get the damage value from the attribute instead of hard-coded as 2 (or 4 if tamed). However, the weird thing is that I think the EntityLivingBase attackEntityAsMob() method has an error in it -- it has this.setLastAttacker(par1Entity) but that is backwards I think -- should be par1Entity.setLastAttacker(this). Anyone else agree. Anyway, since the wolf class seems to not care about setting last attacker and because it seems backwards to me, I guess just leave it out. But normally you'd want to consider calling or copying the super method. Overall, to get damage occurring you can modify the method to be something like: @Override public boolean attackEntityAsMob(Entity par1Entity) { return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), (float) getEntityAttribute(SharedMonsterAttributes.attackDamage).getAttributeValue()); } As you can see, this doesn't deal damage directly because it wants to let the entity that is hit fully process the attack (for example maybe it has hurt resistance in effect) before fully deciding the damage to deal. Anyway, hope this helps.
-
Not sure what you mean by this. I think all Java interfaces are public by definition. The extended properties loadNBTData() and saveNBTData() classes are public. The vampire class is your own custom entity class, right? In that case, even if you had private information in that class you can create public "getter" and "setter" methods for any information that is available in the class.
-
As I think you've figured out, most of the stuff you've encountered is related to AI. I have a tutorial on it that might be of interest: http://jabelarminecraft.blogspot.com/p/custom-entity-ai.html Regarding the attacking without damage, I think I had the same thing once. I think it was related to the entity attributes -- by default there is no attack damage registered for Entities. You have to both register and set that attribute. Here is my tutorial on that: http://jabelarminecraft.blogspot.com/p/stylebackground-color-white-color.html
-
Another thing with API is you need to make sure it works in the deployed situation and not just in the development environment (like Eclipse). There are pretty much 3 parts to API development: 1) Decide on what methods you want to expose as an API. If you expose an interface then you have to make sure you have a way of letting your mod know that it has been used, either by a registry, or by checking all instances in the game for instanceof your interface. You can also expose actual public methods so that people can directly control the code in your mod. In other words, the API can be used to extend and/or control your mod. 2) Set up your Eclipse development environment so the two projects work together. I always get a bit confused about whether it should be a reference project or a linked source, but in any case the build path has to be set up correctly. 3) Set up your build (i.e. build.gradle) so that the interface methods aren't obfuscated -- assuming you want people to be able to access the API without having to build with it. Anyway, it is kinda obvious but I find each of the steps can be a bit confusing and I have to usually work through them. Not sure if that helps...