jabelar
Members-
Posts
3266 -
Joined
-
Last visited
-
Days Won
39
Everything posted by jabelar
-
It's pretty obvious he knows how to mod since he used MCP to make base edits before forge was the standard... He wants to know how to use the event... telling someone to go find it on their own isn't helpful at all... it would be more productive if you would just take the few minutes to explain it to him since I assume you know how to do it... But we literally gave him 5 links on how to use events, all of which have plenty of examples! I already took the time to write several pages of explanation in my tutorial linked above so I don't have to write it over and over again each time someone asks the same questions. Basically we're saying "we've already written you pages and pages of explanation". Go read it and try something. Then we'll be willing to help.
-
TileEntity problems!! Please Help! [SOLVED] [MC 1.7.10]
jabelar replied to TheEpicTekkit's topic in Modder Support
This is basic Java. In Java (and other object-oriented languanges) whenever all of your instances are acting like they have the same value it means you're using static fields wrong. You should study what static means. Static means that all your instances will have the same value. In you code you have the power levels static so all will have same power. Just remove the static declaration and I think it should improve and maybe fix your problems. Please also read about how static works to ensure you fully understand why this was a problem. -
Pretty much half the people trying to implement crops have this problem (null pointer when they actually try to plant) because they assign the block to the seed before the block instance is initialized so they are setting up the seed to plant a null. You need to make sure the block is fully initialized (not just declared) by time you create the item seed. To confirm this is the problem, right before you assign your tomatoSeed, test if blockref.tomatoCrop == null. I'm pretty sure you'll find it is. The solution is you have to make sure that the block instance is created before the seed item. I think you may have some trouble in your approach because you have your addCrop method take in the seed item, which is backwards (the block will be created after the seed).
-
It seems likely to me that that might be the problem -- not appropriate time for a GUI during pre-init. Maybe you can save a boolean that represents a fingerprint violation during the pre-init phase and then test that boolean later at a more appropriate time when GUI is possible.
-
For what you want to do, I don't think you need a custom event. The inventory is a GUI and there is already events for GUIs being open. I would create a handler for GuiOpenEvent and check if event.gui is an instance of an inventory gui. But if you really wanted to create a custom event, here is some further info. To create a custom event, I think that part is probably easy -- you extend an existing event like PlayerEvent and add the fields you additionally want to pass (if needed), you "post" the event to the event bus, and you register a handler for it. To post an event to the bus, you can follow how the regular events are posted. For example, here is the code for a built-in event posting: BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(x, y, z, world, block, meta, fortune, dropChance, drops, player, silkTouch); MinecraftForge.EVENT_BUS.post(event); However, the trick is you have to put the code that posts the event in the place you want it. This is easy for your own code, but might be difficult in other cases.
-
Yes. But like I said you to catch those you can search the world if you're careful about perf (meaning perhaps searching a bit each tick). But yeah if you're coming through from the other side then you know there is one you need to record. You need to separate the detection of location of portals with whether they are lit. I think you can have some sort of array or list field in your main class that can track portals "discovered" and then you can further occasionally check whether they have been lit (or also if they've been destroyed or otherwise changed state). Certainly not easy, but I think with some thought and effort it just might be possible. What exactly are you trying to achieve? Depending on what you want to do, maybe you should make it more like actual discovering the portals -- like if it is within range of the player then you record it. That approach would greatly help performance because you only have to search smaller area (and also check previously discovered portals for changes in state).
-
There must be something better, but possibly you could use the regular populate chunk event and just scan all the blocks to see if any have tile entities. Since the chunk is fairly small it should not be too big of a hit on perf.
-
Actually, I'm not sure you need to do any coding at all to replace sounds. Can't this be done as a resource pack? I'm pretty sure my 10-year-old daughter replaces sounds and textures all the time without coding (of course she probably should be coding at her age!).
-
I think the HarvestBlocksEvent fires after the block is already decided to break (i.e. finished mining). I don't think you can easily use this to make a block "harder" to mine.
-
Actually, I think you could possibly figure out when one is created, and you could also search for one in tick event if you're conscious not try to search the whole world in one tick and instead break it down. For example, you could possibly keep track of all obsidian placed (and even generated by checking each chunk when loaded). There are events for the generation and also events for placement, and you could copy the vanilla code that detects that a portal has been completed. I'm not sure if you meant you wanted to detect when one was activated, but if you kept track of which ones are created block-wise you could poll them in tick event to see if they've lit. Probably a bit of work, and intermediate coding level required, but not impossible I think.
-
No, the @EventHandler is for certain types of events, but not the BreakEvent. You can read more to understand better my tutorial here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-event-handling.html
-
Copy classes rather than extending them, a waste of time?
jabelar replied to ianc1215's topic in Modder Support
I made a tutorial on this question: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-know-when-to-copy.html One of the most important points is that extending a class makes your class get treated same as parent class. Sometimes you don't want this: for example, if you wanted to make an elephant by extending a pig, then any code that checks for instanceof EntityPig will test true for your elephant. This could have unwanted effect. It would be better to copy the pig and modify to make an elephant. On the other hand sometimes you do want the class to get all the benefit of the parent, because similarly there may be instanceof checks you need. For example if you were making a magical pig then you probably would want to extend pig because your class is also a pig. However, I didn't really consider how easy it was to maintain the code either way. I think it is probably easier to maintain extending classes because usually you only change a few things in your extended class and so all the code that you didn't changed will automatically get updated. For example, if you copied the pig to make an elephant and then in an update Minecraft made pigs do something cool, you wouldn't automatically get that for your elephant unless you copied the new stuff in. Anyway, you should choose based on whether you want instanceof to include your class with the parent class or not. -
The problem is that entities' pathfinding code currently tries to find paths around blocks. So for an entity to try to go through blocks (while destroying them) you'd have to make an entirely different pathfinding. However it may be possible to trick the entities to find paths through blocks by playing with the addCollisionBoxesToList and collisionRayTrace methods of the blocks. What you could do is to make your own replacement custom blocks that extend the vanilla blocks that you want to be breakable. You would @Override the addCollisionBoxesToList() and collisionRayTrace() methods such that if the block was at same level as the entity it would have no collision, and then I think the path finding will let it through. Then when it actually goes into it you can break it. Alternatively, perhaps you could override the AI all together and replace with your own AI that always moves in straight line towards the target and when it gets really close to the blocks while trying to get through it will break the block. Note one trick is that standard blocks and entities never really collide, because they keep outside the bounding box. Entities only really go "inside" a block if it is a type that allows it, like a portal or web or similar. Not sure if any of the above suggestions help. Overall it is very difficult to do with vanilla blocks and entities, but might be fairly easy with a custom entity or custom blocks.
-
There are two terms you want to google for -- HUD (heads up display, meaning anything annotated on top of the game display) and GUI (something that comes up in the game that is graphical, like the crafting interface). It sounds like you need more of a HUD. In all these cases, graphics are "rendered". In any video game there is some code running that does all the logic (figures out health and hitpoints and spawning, and then another bunch of code that keeps the display up to date rendering some number of "frames per second" (fps). Most items, entities and blocks have a rendering method that gets called every render cycle, so for custom items, entities and blocks you simply overwrite or register your rendering stuff. Alternatively, there are a bunch of events called when things are rendered. There is for example an event for rendering the player's hand that you see when in 1st person view, and so on. For something like what you're doing, you probably want to use an event. If you're not familiar with event handling you can check out my tutorial, which also lists all the rendering related events: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-event-handling.html I don't do a lot of rendering mods myself, so others can help you better, but I think the RenderGameOverlayEvent (which has Pre and Post sub-events) is probably useful for this. You may want to look at any open source minimap mod, which does similar thing. Inside the rendering, you use OpenGL which is a graphics engine language. You will see GL11 type commands that do things like create vertices, scale, blend, etc. Look at some of the Renderer classes in Minecraft source. You'll probably need to look up a seperate tutorial on this, but it is standard Java so there is plenty of info, especially for simply rendering a flat image.
-
Great analysis. I still think you could achieve the same thing without the second method at all. Basically you would have a canBoneMeal() that would return false either if crop doesn't ever use it or if crop is finished (fully grown) growing. Then you call an implementGrowth() method that could either progress randomly or not. I'm probably still missing something but I don't see why you really two seperate methods to cover the "can" part -- the logic is pretty simple to combine into single method. These methods aren't called anywhere except the applyBoneMeal() method and they are contained within the crop class itself so no need to generalize -- so why not just test conditions and if you want grow steadily or randomly proceed to do so? I'm all for breaking code into small, purposeful methods, but I think it can get silly once you get into methods that only require a one-line return statement. Anyway, it is what is it -- that's modding! Good stuff.
-
To figure out how to approach this, you need to find where the names you want are actually associated. Look in the lang file to find the names you want to display. Then it is simply a matter of getting there from your code. If the item has the name and you have a block then you'd find the item for the block, and so on. If they're hardcoding it somewhere outside the lang file then find that and figure out how to get there. Basically, for the names you want to display where are they currently in lang file or code?
-
I think for first one we're saying the same thing, what I called "stillGrowing" is logically same as "canBoneMeal" for those classes that allow bone meal (since bone meal can only be effective on something not fully grown), but I agree canBoneMeal is better name generally (to cover cases where bone meal is never supposed to work). The second class still seems a bit inconsistent in the vanilla crops, or at least it is weird that it returns a boolean at all. Like BlockCrops itself only does a return true in what you're saying is the doBoneMeal(). Not sure why that function would be tested at all, rather than just performed void. But yeah, no objection to shieldbug's interpretation, does seem a bit more sound.
-
Are you sure it isn't the other way around? In most IGrowable implementing classes in Minecraft the second function doesn't do any real work but just seems to either return true or return some other fairly simple boolean expression. Actually, looking at it closer, I think they can be used either way. Both methods are only used in the applyBoneMeal() method and they are part of a nested if-statement that makes them interchangeable -- basically both have to be true (and must be on server side) to apply bonemeal. Here is the code from the applyBoneMeal() method: if (block instanceof IGrowable) { IGrowable igrowable = (IGrowable)block; if (igrowable.func_149851_a(p_150919_1_, p_150919_2_, p_150919_3_, p_150919_4_, p_150919_1_.isRemote)) { if (!p_150919_1_.isRemote) { if (igrowable.func_149852_a(p_150919_1_, p_150919_1_.rand, p_150919_2_, p_150919_3_, p_150919_4_)) { igrowable.func_149853_b(p_150919_1_, p_150919_1_.rand, p_150919_2_, p_150919_3_, p_150919_4_); } --p_150919_0_.stackSize; } return true; } } So it seems to me, unless my brain is fried from being up late, that you can use them interchangeably. Certainly looking at various Minecraft classes that implement the interface, it seems to be inconsistent.
-
All coding (beyond just following tutorials) is problem solving. You basically know you have a bunch of pieces and you know you want to do something but then need to choose which pieces and how they go together to achieve what you want. I think most people can learn to do this, but I suppose some people may get stuck because it requires both creative and strict technical thought processes to come together. For example, imagine you had (in real life, not in Minecraft) a pile of wood and some construction tools. I think many people could come up with creative ideas on what type of treehouse they could make with the wood, but you wouldn't make a good treehouse unless you had some strict technical skills (like understanding best way to create a strong floor, or how to make a structure that could accommodate the tree moving in the wind without breaking the structure. So back to Minecraft modding, on the one hand you need to be able to vision how the classes and events can be used together and then you have to have the specific Java technical knowledge. I think most people are creative, but the technical knowledge is also key. This forum is full of questions of people who really have desire to mod, know they have a cool idea for a mod, but really get lost quickly in the coding. But there is one more thing -- you have to be able to know what all the pieces and tools you have to build with. My big suggestion here is to learn to use Eclipse (or IntelliJ or whatever IDE you use) to *explore* the Minecraft and Forge code. If you're working with entities, make sure you follow the entire class hierarchy. For example, you can do this by rightclicking on whatever the class you're looking at extends and choose type hierarchy or you can also follow the declarations. Similarly, you should explore what is calling each method by right-clicking and choosing call hierarchy. If you follow posts in these forums, you might find people that seem like they know the answers to everything but really in most cases they just know how to quickly discover the answer. They do this just the way I said -- by exploring the code. So my big tip is to use your IDE to explore the code. The more you understand the way Minecraft and Forge typically work, you can will find that you'll more quickly be able to come up with a technical approach to implement the mod you've dreamed up.
-
Based on my own quick guess at reverse engineering (read it yourself to see if my explanations seem to be correct) func_149851_a is basically a stillGrowing() method. It returns (or should return) true if the growth stage is less than the max growth stage. func_149852_a is basically a canBoneMealSpeedUpGrowth() method. I usually just return true, but depends on your crop. func_149853_b is basically an incrementGrowthStage() method. In vanilla crops the growth stage is stored in metadata so then in this method you would increment it if it wasn't already at maximum and store back in metadata. If you want to see an example of one of my blocks that implements IGrowable, see here: https://github.com/jabelar/RecipesPlus-1.7.10/blob/master/src/main/java/com/blogspot/jabelarminecraft/recipesplus/blocks/RecipeBlockCrops.java
-
I think if you want it to swim like a fish (under the water instead of on the water surface, and smoothly instead of jerky like a squid) you will need custom AI and maybe custom pathfinding. You can use the "new" AI where you create a list of tasks that have priority and mutual exclusivity or you can use the "old" UI which basically just processes all possible movement actions in one method. I suspect that there are some open source code for other fish mods that may implement proper swimming. If you end up coding your own I think to be fish like you'd basically choose some underwater point that you know you can get to and swim towards that and then occasionally (and bit randomly) decide to choose other target location. Like a school of fish moving along and then switching direction. In terms of moving up and down in the water, you'd probably have to check how much water is above and below and decide if it needs to move up or down based on how "deep" (maybe including some randomness) you want it to swim.
-
Before you change something in vanilla you should first consider whether you can accomplish what you need with the following: 1. Check for public methods in the vanilla classes. For example you can completely overwrite the AI for vanilla entities by accessing their tasks and targetTasks because these are public methods. Attack damage, movement speed and so on can be changed. I'm not certain because I haven't tried by i think you can probably register your own models and renderers by accessing the registry. Anyway, look for this type of stuff because it is directly modifiable with standard Java because that is what public fields and methods are for. 2. Check for events that can be used. These are Forge hooks and allow you to cancel (and replace with your own code) all sorts of functionality that is commonly of interest to modders. If you don't want a certain entity to spawn you can intercept the living spawn events, if you want to render something differently you can intercept the render events, you want them to drop different stuff you can intercept the drops events. 3. Java reflection. This is easier than it sounds and allows you to access private fields and methods. You can modify private fields, but you cannot modify methods. Anyway, this opens up a whole bunch more stuff you can do. 4. ASM Access transformers. This is an actual replacement of functional code. Look it up, but it creates a lot of possibilities. With the combination of the above powerful approaches, it is very rare that you need to actually modify base classes or "core" code.
-
I think that means that you have a position outside of the world or something like that. What is your code for walking on water look like now? I suspect you're adjusting the Y position to some value outside the world.
-
[1.7.2] general questions about log blocks/blocks with meta
jabelar replied to pryingtuna85649's topic in Modder Support
Metadata might seem mysterious if you don't understand why they did it and if you aren't familiar with bit representations of data. The makers of Minecraft had a bit of a problem -- the number of blocks in the world is very large. Think about just a 10 x 10 x 10 block of dirt blocks -- it has 1000 blocks in it. In a Minecraft world there are actually over a quadrillion blocks (if you include air blocks which you should because Minecraft has to process air too). So if you had a Java instance for every block, performance and memory space would be big problems. To solve this, they did several things, such as dividing the world into chunks that only appear when needed and they also used a single instance of each block class and instead just recorded the placement of each block in a giant "array". That wasn't enough though because to make Minecraft interesting some blocks needed to be able to have a bit of change -- a door needs to open, torches need to attach to a wall, etc. So they wanted some unique data for some blocks; however it couldn't be too much so they decided to use only four bits of data for each block. That is what they call "metadata". With that metadata, the coder for a block is free to do what they want -- they can use it for different types of wood, or they can use it for the rotation of a ladder, or use it to show whether a door is open or closed. To see the list of metadata uses in Minecraft see this wiki: http://minecraft.gamepedia.com/Data_values#Data One problem though is that the metadata was used inconsistently by the programmers of Minecraft. Especially irritating (if you're trying to code algorithmically like making structures) is rotation. For example, a piston uses 2 for north, 3 for south, 4 for west, 5 for east, while a door uses 0 for west 1 for north, 2 for east, and 3 for south. Anyway, you should read the link of data values as it gives you a good idea on all the uses for meta data. Next you need to understand binary bit representations of numbers. If you want to represent something that has two states (like door open or door closed) you can use one bit. But that bit can be in different locations (place values) in the data. So the bit being 1 could actually mean a value of 1, 2, 4, or 8. For doors it turns out that it uses the thrid place value so door open is value of 4. What gets tricky then is the combination of bit values. You can't just test if the metadata == 4 because the other bits might be different values for other reasons (in case of door the other bits are rotation). So an open door might actually have a metadata value of 4, 5, 6, or 7 -- those are all open doors! What you need to do then is to "mask" the bits before you test them. This requires "bit-wise" operators. To learn about these you really need to read up and study it, but as an example to test if the door is open it is easiest if you make sure all the other bits are 0 by doing a bit-wise AND operation on the value before you test it. So you would do: if ((metadata & 4) == 4). The bit-wise & function only has a bit high in same position as the door open bit so it forces all the other bits to zero and then you can just test against the door value. Hopefully you already know all this, but if not it takes some study to get comfortable. -
Can you show your code again (please put the code tags around so it is easier to read)? In the code you posted before, you had getOwner() and setOwner() as private functions. But they are supposed to be interface functions to override IOwnable interface. That means they should be public. Also, what version of Forge are you using? I know that in 1.7.10 those functions changed a bit.