Jump to content

ojb

Members
  • Posts

    9
  • Joined

  • Last visited

Everything posted by ojb

  1. As a general debugging tip for situations like this in the future: you can comment out something like half of the calls to addFeature() at a time to try and isolate the issue. You've identified that the bug is in this file, and that you've been playing around with the parameters, so it logically follows that the issue is probably to do with one set of those parameters. My approach to isolating the bug would be to comment out like the first four ore types (ditium, minium, etc.) and see if the bug persists with the second half. If it does, I'd try to switch out the commented parts so that you'd keep the first four but not the later ones. The idea being that you significantly cut down the number of lines to check for errors that you need to look at manually. This won't always work (e.g. what if a line in the first set AND a line in the second set are both wrong), but the idea is that you try and make it easier on yourself to find out which one is the bad one. Some general advice to newer coders who might stumble on this thread (not just directed at you, OP): compile often and try not to make too many changes in one go. Sometimes it's tough to deal with longer compile times so there is a balance to strike, but hopefully you're able to identify issues as soon as they come up. Draco has pointed out line 24, which is a line that stands out to me even without knowing what the parameters are for: this line in particular when compared to the others has some repeated values. If you're just using a function call for something you didn't write yourself, it is often good to try and figure out what restrictions on the arguments exist, if any (particularly min, max, whether the second argument must be bigger than the first, etc.). Sometimes the code you're trying to use isn't commented well or documented, so you run into situations like this that can't be avoided. Repeated values, zeros as input, and other potentially noteworthy cases are something to keep in mind just in case of something like a subtraction forcing a zero or a divide by zero that may lead to a crash. Just being aware of things like this is a useful skill to have in your debugging toolkit.
  2. I've been keeping an eye on this thread to see if anyone else responded since I just started learning forge and have been playing around with some similar ideas on my own. I'm still focusing on 1.14 so I don't know the exact specifics of 1.15, but I think I can offer a little bit of help. In this case, it looks like the goal of your item is to speed up the growth of nearby crops. Instead of requesting a tick update on each of those crops it finds, you can skip the middle man and look for some function that will boost the age property of the crops directly. In 1.14, I accomplished that by calling the function grow() which is built into descendants of growable things in vanilla (seeds, carrots, etc.). It's possible that function changed in 1.15 (I don't know), so I would look into the BonemealItem class to see what vanilla does to grow crops and that should point you in the right direction. The basic idea in 1.14 at least is that function updates the age property of the crop, so to grow crops you just need to update the block state with an incremented age. Different crop types (as you've identified already) have different age values (stuff like wheat go from like 0 -> 7 for example), so you'll need to keep that in mind. You'll probably need to add on a little randomness of your own to make it not just instantly grow all the crops around you (the bonemeal effect is pretty strong), but that shouldn't be too difficult to accomplish. As for more general code quality stuff, I can spot a few places where you might take advantage of some refactoring in your port. You have some pretty deeply nested conditionals that can make things difficult to understand at a glance, and a lot of them have some pretty repetitive checks. For one, you check !isRemote() inside of every condition instead of once outside them all. This can be pulled out front and you'll save some lines and clear things up. For my own coding style at least, I see several opportunities to break up some repetitive code into its own functions to help improve the readability and ease of debugging. That's all subjective though, so take that with a grain of salt. As a side note: I've only been on these forums for a short time and didn't realize it at first but when you're adding code examples to a post there's actually a drop down menu in the bottom right where you can change the language from HTML to Java --> it'll automatically put some syntax highlighting to make it much nicer to read. Hope this helps.
  3. It seems to be working and the game will seem to remember the arraylist data on reload / not crash. I do have one additional question: I put a System.out.println debug statement in my read call and I see that both the client and the server threads are reading the NBT I wrote. Is this okay or should this be something that should be server side only (e.g. the client would get the updates from some other forge packet type mechanism and not directly read the NBT on its own)? For anybody interested on how I handled the dynamically sized ArrayList, I just wrote a tag for the length of the list, and then wrote each element one by one with a tag with the name like "Element"+index with index going from 0 to that length. It's quick and dirty and may not be the most elegant solution but it works fine as far as I can tell.
  4. That seems exactly like the kind of sample code I need, thank you. I will go and try and implement something like this for my TileEntity right now. With an overridden read/write like the above (and making sure to markDirty where appropriate, like in my setup call when the list is first generated), is there anything else I would need? Will I have to subscribe to any events or anything like that or should I expect it to just work?
  5. Upon some further forum diving and looking at some source code provided in the MDK, a lot of signs seem to be pointing towards using Capabilities. I found this thread in particular: https://www.minecraftforge.net/forum/topic/78283-1144-data-stored-with-my-custom-capability-attached-to-player-doesnt-seem-to-save-data-into-nbt/ to be a decent starting place and I will try and see if I can understand what they did. I think I've figured out question (1) from the OP on my own [looking at the CompoundNBT class shows that it has some .put functions for various data types], but I guess the overall confusion still exists. Just looking at the Custom Capability class in the above link seems to be ridiculously over engineered at least for my more simple self-contained application. I'm still wondering if there's a way to get away with just the overrides in the original post (i.e write/read nbt) and avoid capabilities all together to try and keep the complexity down and manageable. That's something I'll have to keep playing with on my own unless anyone has some specific experience / knowledge on the topic.
  6. I'm having a bit of trouble wrapping my head around the serialization process for more arbitrary data storage. I think I have at least a workable understanding of the Capability system and was able to implement some basic ItemHandlerCapabilities to have persistant inventories across chunk saves/loads. As I'm still in the playing around and learning phase, I'm trying to understand how this process generalizes to the sort of data that isn't nice and already provided by forge. In particular, say I have an arbitrary ArrayList of some sort of data (for example, a list of floats) that is generated when the block housing the TileEntity is first placed down. What are the recommended ways to serialize this thing so that it remains with the TileEntity when the chunk unloads? The documentation seems to imply that I'll need to override the public CompoundNBT write(CompoundNBT) and public void read(CompoundNBT) functions to convert my ArrayList<float> into some sort of NBT data. So I guess my main questions here are: How is this conversion to NBT done in general (is there some sample code I can look at somewhere?) Is there a better alternative approach that I'm missing? The capability system seems to be designed primarily for types of data that are often shared between mods and blocks (e.g. passing items or energy and stuff like that) but less useful / more tedious to adapt to more arbitrary data (for instance an array list of floats that only this one tile entity needs). Is this a reasonable conclusion or am I mistaking the point of this concept? More concretely, should I be taking a further look at the Capability system to solve this issue? I don't know how useful including the code I have so far would be: it's just your standard tickable TileEntity with a setup() function called when it's first created to generate the ArrayList data, and then a tick() function that will look at the data every X ticks and do something with it. It's very much a toy example just to learn the techniques but I think it encapsulates some design ideas that I would like to use in more useful mods.
  7. You're absolutely correct! I was a dummy and had it checking if (world.isRemote()) instead of if (!world.isRemote()) inside my tick() function with the grow updates. I guess I didn't read the docs too carefully and just assumed the isRemote flag was reversed. This change fixed my issue, and it works as I would expect. Thank you Draco!
  8. Error while parsing is usually a syntax issue. Line 59 of UltimaMod.java just has a curly bracket on it, so this points to a bracket mismatch. In your case, it appears that you open the setup() function with an opening curly brace { twice, one on line 43 and again on line 44. I think one of those is redundant and removing one would fix your compile issue.
  9. I'm new to modding and I figured I'd play around a bit to try and get a handle on the functionality that exists already in the API. I'm implementing a simple TileEntity block that will (~every 20 ticks) apply a bonemeal effect to a crop directly in front of it. I think I have a slight misunderstanding of how BlockStates / Blocks can be updated. To illustrate this problem, I have: BlockPos cropPos -- the XYZ position of the crop block (e.g. the seeds/carrot/potato/etc) BlockState cropState -- the block state of that crop [obtained by world.getBlockState(cropPos)]. (Note: debugging shows it to have one property AGE_0_7 which I'm trying to update) CropsBlock crop -- a (verifiably legal/kosher) casting of cropState.getBlock() Now, inside my TileEntity's tick() function (only on the server, not from a client), I attempt to call crop.grow(), which takes parameters (World, BlockPos, BlockState). Looking inside that API call it seems pretty straightforward: it updates the AGE property towards the maximum age allowed for the particular crop with one (randomized) bonemeal-esque update. It does that by calling something like world.setBlockState(... state.with(updatedAge)...). Visually, the crop seems to grow just fine as it looks like the crop is growing over a short period of time in game. My debugging output will show that if I pull the BlockState of that position from the world after the grow() call, it has an AGE property larger than it started. But it's unfortunately not "real" growth and is just a visual lie: the crop is still only on stage one. This can be verified by breaking the crop when it is supposedly mature (it only gives a single seed, not the regular mature products), or right clicking it with an empty hand, which updates it visually to reveal that it is still just on the initial stage of growth. This is definitely a different effect than what bonemealing a seed does, which leads me to believe I'm not updating the right aspects of the crop block. I believe this is me misunderstanding how BlockState updates can occur, so if anyone can enlighten me on what I'm missing it would be most appreciated.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.