jabelar
Members-
Posts
3266 -
Joined
-
Last visited
-
Days Won
39
Everything posted by jabelar
-
The most important thing to understand is that in Minecraft, both Item and Block classes are used as "singletons". This means there is only one instance created for each (e.g. new ItemAxe()) in the entire game. But of course while playing the game it seems like there are lots of items and lots of blocks, so how does that happen? Well, items and blocks do it differently... Items always exist in an ItemStack instance (which adds quantity, damage, other NBT data to make the stack unique). So there is only one ItemAxe instance but there could be lots of ItemStack(ItemAxe) instances. Even for a single item there is an item stack with quantity 1. So each Item class (which is what gets registered) has only one instance, and all item stacks related to that item point to that one instance. Blocks use a different way of propagating in the world. The presence of a block in the world is stored very compactly in the chunk/world data. There is not a new Block instance created for each block placed, instead the chunk just gets a reference that says "in this BlockPos there is this type of block". Additionally, the same block can have somewhat different behavior/looks though so each block is allowed 4 bits (16 values) of "metadata". The metadata represents a Property of the block at that location -- for example, the direction a furnace is facing would be stored in the metadata. Back to the registries: My point then is that there is only one instance of each Item class and each Block class in the entire game. The registries contain these. This is important because it means that you can do a full comparison using Java == and otherwise it keeps the memory and disk space more compact. Tip: You don't have to use the registries to access the instances. There are constants that represent them for vanilla, and you should do the same. For example, Blocks.VINE or Items.SWORD. Note that Entity classes do not work that way -- a new instance is created every time. So the entity registry works a bit differently and is more like a factory. This is okay because there are a lot less entities in the world than blocks (a single chunk can have 65,536 blocks!).
-
Is there any error in the console related to loading the loot table? When I copy your loot table into a JSON verifier (https://jsonlint.com/) it seems you have some extra characters in your file that are causing trouble. Just go to that link, paste in your JSON text, and hit the validate button and you'll see the errors.
-
If you're planning a career in software, yes you need to get intimate understanding of how git command line works. In fact it is common interview question. However, it is also 2018 and all the concepts of revision control lend themselves very well to a graphical representation. In fact pretty much every tutorial for using git ends up drawing all sorts of diagrams to show the head and commits, and such. For most hobbyists a git GUI (I recommend SourceTree) works very well. In any case, I'd rather have everyone using source control rather than not, and a GUI makes it a lot more accessible to beginners.
-
He did answer your question and even gave you the code. Regarding "documentation" in general, you really just need to look at the source code and see how it works for similar vanilla behavior. Some big topics like blockstates have official documentation, and many people like myself try to write tutorials, but honestly we really all just figure it out by reading the source directly.
-
[1.12.2] Problem with my proxies [Totally solved]
jabelar replied to Legenes's topic in Modder Support
While I respect diesieben07's objection to the common proxy approach, even the actual javadocs written by cpw for the proxy system suggest using a common proxy. So it is understandable that a lot of people have used it that way, and mostly It does works except logically you don't need code that runs on both sides to be in a proxy at all. So the term "common proxy" hurts our brains and I agree it probably further causes unnecessary confusion about the whole concept. So the more modern recommendation is to have all the common stuff just run directly in your main mod class (or wherever you handle the FML loading events like pre-init and such) and then only call the proxy methods for things that actually differ between client and server. For those, you create an interface (e.g. IProxy) and a client and server class that implement that interface each with their own version of the method. -
Change appearance of a block (add vines) by using a custom item
jabelar replied to modder819's topic in Modder Support
I agree he mentioned that he wanted the appearance. But he also said: I think maybe he doesn't understand that vanilla vines are more than just appearance, and that having something that could change the appearance of any block would (as you're already explaining to him) be quite difficult to achieve. -
Change appearance of a block (add vines) by using a custom item
jabelar replied to modder819's topic in Modder Support
Actually, I think it is the opposite. It isn't THAT hard to make a block that copies vanilla vine behavior, including making it climbable (you just need to override the isLadder() method to return true and make sure the collision box is amenable. It would be harder, almost impossible, to create a visual vine effect without making a block. In any case, what have you tried so far? Why not start by copying the vanilla block code, or maybe even just extending it? The fields in BlockVine are either public or protected, so extending it would work well. -
What problem are you trying to solve?
-
[1.12.2] Custom Message on Player Join [SOLVED]
jabelar replied to ModMCdl's topic in Modder Support
Your method needs to be static. Like the other ones in that class. Right now it is actually not registering properly as the @EventBusSubscriber annotation requires static methods. -
diesieben07 is being helpful by providing additional review to your code. Even though it may not be directly related to your reported problem, these are in fact problems. Note that sometimes when code is "unhealthy" it is not immediately clear there is a problem -- bugs can lurk without causing full crashes -- so you can't just say that it is fine because you think it is working elsewhere. For example, because you don't serialize the BURNING property your saves will be screwed up. diesieben07 took the time to write up that list of common problems for a reason -- many mods have had trouble due to them.
-
Yes, that is the method I mentioned. You have to create your own version of that method, create your own version of the AI class that calls the method, then replace the AI every time an Enderman joins the world.
-
Do you mean you're creating a new pickaxe that can do this, or do you want the regular pickaxe to do it (maybe when using a potion or something)? I'm assuming you want to make a new pickaxe. In that case, just like said above you'd keep the rest of the vanilla pickaxe code but you'd change the code where it breaks the block, and simply add lines to break all the neighboring blocks. Simply add to the block position and break the block there. Of course depending on how you want it to work you'd probably need to check what type of blocks are there and make sure they are breakable or should break -- like just because you break an easy-to-break block you don't want the neighboring hard-to-break blocks to also break. So I assume you'd also check that they are the same type as the original broken block.
-
AIFindPlayer is actually a sub-class within the EntityEnderman class itself. So just look at the source for the EntityEnderman class.
-
You can replace any entity's AI with your own version, since their AI task list is a public list. So whenever an Enderman spawns you would clear the AI target list and recreate it, but using your own version of the EntityEnderman.AIFindPlayer. So basically you would create your own class and copy the AIFindPlayer code into it. But you would modify it by replacing all the calls to shouldAttackPlayer() with your own version that look for PUMPKIN or your other item. Then you would handle the entity joins world event, check if the entity is an instanceof EntityEnderman and if it is you would clear the AI target list, and rebuilt it using your version of the AI class.
-
How to fix the random player used in debugging?
jabelar replied to pkmnfrk's topic in Modder Support
In Eclipse you can enter this by going to the Run menu, selecting Run Configurations, selection the configuration you want, going to the Arguments tab and then in the Program Arguments field enter --username=<your username here>. -
[1.12] Cascading worldgen lag during structure generation
jabelar replied to JoieNL's topic in Modder Support
You may already know this but here is more information on what causes cascading worldgen: https://www.reddit.com/r/feedthebeast/comments/5x0twz/investigating_extreme_worldgen_lag/?st=jjge6795&sh=f1603e42 The key point is: and the solution is: If you look at the vanilla world gen you'll often see a +8 or similar in the locations. To debug your problem, I would add console statements that, at each place where you generate a block in your worldgen, right before you place the block, print out the x, y location and also whether the chunk is already loaded or not. Actually, that might print out too much, so instead maybe have it print out only if the chunk is not already loaded. Basically you need to debug the cascading. One thing to think about as well is you can't have to much randomness in your x, y positions or it will greatly increase the chance of cascading. You should basically offset everything by +8, +8 and allow no more than 8 blocks of randomness. -
You're getting mixed up on some Java concepts. Here's some clarification (hopefully). In Java, when you pass a object instance as a parameter it is accessible by the method. It is not a copy. This differs from some other programming languages. Also, when you use the assignment (=) it does not make a copy. So if you say Object A = B and then change something in A it will also change in B. To make a copy in Java, you have to go to explicit work to make the copy. It is good programming practice with your custom classes to create a proper copy() method. To make a copy the basic idea (there are other "levels" of copying) create a new instance and go through an find all the primitive fields and copy their values over. Generally, you'll only get a copy if a new instance is created. Otherwise it is passed on through. Passing through is how method "chaining" works (allowing you to take the returned value and apply additional methods). For example, if you have a method that takes in an ItemStack and then returns it, it is the same instance. But if the method takes in the ItemStack, creates a new ItemStack and returns that then it would be a copy. Now the other Java concept you need to understand better is interfaces. You also said: That is only partially right. You get the whole instance but are only guaranteed that it supports the interface. However, if you have confidence that it is actually a certain class type you can access its methods too. To check if something is actually a certain class you can use the instanceof operator and then cast. Like there are many methods in modding that have a EntityLiving passed in, but you can check if it is actually instanceof EntityPlayer and if it is then cast it to EntityPlayer and then you're allowed to access the rest of the EntityPlayer methods.
-
Oh I'm using 1.12.2. Not sure when these events were added. But also note that we don't support such old versions here anymore either. In fact these sorts of improvements are why you should upgrade.
-
There are events for this. There is ClientChatEvent which is for when client wants to send chat to server, and a ClientChatReceivedEvent for when chat is received. Both are cancelable, but if you just want to change the chat I don't think you need to cancel but rather just change the content of the related fields.
-
Can you give examples of things that would need this? There are so many things that you can do before the core modding. There are: 1) Many fields that are fully public already. You can directly replace those with your own versions without core mode. For example, you want your own TextureManager, simply replace it. Want your own RenderGlobal, just replace it. You want EntityZombie to have different AI just replace it. And so forth. (Of course if multiple mods try to do the same replacement there would be an incompatibility, but coremodding already presents that concern.) 2) You can use Java reflection to do the same type of replacements for any of the private fields. For example, if you want your own version of the LanguageManager use reflection to replace it. 3) Forge provides tons of events that allow you to intercept most common vanilla processing and replace it with your own. So let us know what you're trying to do and see if you really, really need a core mod.
-
Draw a line/vector and get all blocks inbetween
jabelar replied to tomato3017's topic in Modder Support
You just use the same idea as ray tracing but don't stop at the first block it hits. Usually the logic is pretty simple, probably something like this. Create a field or collection to hold the results. In your case sounds like it could just be a float that gets adjusted as you find blocks. find the difference vector (basically subtract the two BlockPos) which will get a vector of (x2-x1, y2-y1, z2-z1). find the incremental vector you want to step along, which is the difference vector divided by the length of the difference vector. make a for loop that will loop a number of times of the length of the difference vector, and the loop starts either at your TE or player position and adds the incremental vector each loop and checks the resulting block at that position. If the block found should adjust your field or collection from Step 1, adjust it. That's pretty much it. However, there is an important detail to think about. in Step 3 setting the increments like that may miss some little corners of blocks that are technically in the path. So you probably want to make the steps smaller. Like if you want to catch even 1/10th of a block you would divide the incremental vector by 10 and also in Step 4 loop 10 times more. But that cause the opposite problem where you might count the same block multiple times. So there is probably a bit of code you need in Step 4 to remember the last block you found and don't count it twice. The main difference between what you want and the vanilla ray tracing is the fact that you need to prevent double-counting a block. Since the vanilla stops at first block found it can have a fine step without worrying about that. So mostly simple, needs a bit of thought and detail. Note. If you're not familiar with it already, there is a Vec3D class which is useful as it has ability to do things like subtract and divide and add exactly as you need and it works well with BlockPos class. -
Did you try something like: ItemCameraTransforms.DEFAULT.applyTransform(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND)
-
Well the official documentation is here: https://mcforge.readthedocs.io/en/latest/models/advanced/imodel/ Did you do some google searching there are a lot of forum threads related to using IModel. Not sure if any specifically talk about your problem, but you should look through them and maybe you'll get an idea. Generally I think though that there is probably a transform required in the json file for the rendering while being held. Deprecated isn't always a bad thing. It can just mean it is not recommended for modders. And in any case in this particular version it is still present so if it is truly deprecated (meaning it goes away in the next version) it should be obvious what the replacement is then.
-
Is the block a custom block, or you want to change a vanilla block texture?
-
How to deal with items that can take more than 65536 damage
jabelar replied to [NoOneButNo]'s topic in Modder Support
Yes, that's supposed to happen. Any item stack that gets damage of that amount is considered empty. The code for ItemStack.isEmpty() method is: public boolean isEmpty() { if (this == EMPTY) { return true; } else if (this.getItemRaw() != null && this.getItemRaw() != Item.getItemFromBlock(Blocks.AIR)) { if (this.stackSize <= 0) { return true; } else { return this.itemDamage < -32768 || this.itemDamage > 65535; } } else { return true; } }