Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. I don't think it is really that costly for performance really. You only need to update the "map" when someone places a block and only check the map when someone tries to break a block. And booleans can be stored as a bit map if you need to keep things compressed (cause you probably need to store this as world save data). EDIT: of course you should keep track of breakable blocks, not unbreakable, since I would expect that the player-placed blocks would be much less than the naturally generated ones.
  2. That's honestly the easy part, the difficult part is knowing whether the additional chunks that aren't generated yet will be suitable for your structure. imagine you start generating a big castle and then the next chunk ends up being a mountainside or ocean or ravine. As Draco18s says, the chunk +1, +1 is generated so you can check its suitability but I expect some people need to span even more chunks than that. I think the easiest solution is to simply accept that Minecraft sometimes generates some weird stuff and do your best to have the structure work in all situations. Vanilla villages often generate on some weird hills, but that is fun when it happens. To do this approach you can make your structure also include the blocks underneath and above so that if it does end up getting generated in the middle of a lava lake it basically creates an island for it to be on, and if it gets generated in a mountain side it sort of chops out the mountain above it.
  3. While having a placeholder block can definitely simplify the generation logic, I don't think it helps this particular issue. The problem here is that he didn't want the structure gen to force the load of a chunk, but without loading the chunk you won't know if the next chunk is suitable for continuing the structure. You'd have the same problem with your placeholder block -- it wouldn't be able to generate the structure even on the next tick because the next chunk wouldn't necessarily be loaded. There is really only three possible strategies. 1) When a chunk seems suitable to start a structure go ahead and force the additional chunks to load and then determine whether the overall area is suitable for your structure, 2) You can make the presence of the start of your structure force the next chunks to be suitable, 3) design your structure so it kinda works in all possible cases -- like can extend into the ocean or into a mountainside or ravine, etc. I kinda like strategy #2 in terms of liking creating the best result (because the surrounding chunks will be purposefully generated to be suitable).
  4. I'm not sure but I think it can happen if you don't have admin permissions. Are your running the script from a console with administrator rights?
  5. Well, if you actually want to know if you're in the main screen I think you can just handle the GuiOpen event and check if it is the main screen gui. Otherwise, you can use the FML lifecycle events and assume that something like the post-init event should be after all the mods are loaded. Really depends on what you're specifically trying to do.
  6. I don't think that should be a problem specifically. The chunk behind you is still loaded. I think maybe though it does cause bug for the frustum checking though. Does it happen to something that isn't riding the entity too? Like if you're watching it from the side? Also, is it a temporary thing or can you "park" your vehicle in a location where it won't render?
  7. You can intercept when a lake or lava lake is being generated by handling the PopulateChunkEvent.Populate event and checking if the event type is LAKE or LAVA.
  8. Well, the difficulties you're facing are pretty typical. If you try to only generate the portion of your structure in the loaded chunk there is potential that when the next chunk is generated that it isn't suitable for your structure. With smaller structures it kinda works because the village houses can be on a hillside or something, but it can look strange if your castle is halfway into a cliff or something. But like you said you can't wait until all the chunks are loaded to check for suitabiliy because then the structure will sort of "pop up" as you said. And also, it is true that there are vanilla structures to look at but the code is kinda complicated. Also, depending on the structure it may not always make sense to break it up in same way as vanilla. One solution could be that the generation of the chunk depends on whether there is a structure rather than the other way around. Like lets say the natural generation happens and then eventually provides a suitable place to start your structure. Well, then the next chunk maybe shouldn't be fully "natural" generation. Instead you can control it so you know it is suitable for the remainder of the structure. Basically prevent it from creating an ocean, lake or mountainside in the way of the structure you need to create. In fact, if parts of your structure cover a whole chunk, you could basically make sure that that chunk is generated as a "flat" structure. Another solution was whenever you find a place that might be suitable for your structure to start, that you force the generation of the addtional chunks and then only build your structure if the overall area is suitable for it. Overall, there isn't really a good general way to generate a structure because it really depends on the structure. For example, if your structure is very regular and symmetrical you might be able to generate it with a formula, but if it is very intricate and asymmetric then you will need to generate it block by block from a blueprint. If some parts of the structure are repeated then you will want to break it up into smaller pieces. If the structure has a lot of randonmess you will have to figure out how to ensure it all fits together. And so forth.
  9. I believe player speed is actually not set by an attribute. Instead it is set by the walkSpeed player capability.
  10. If your problem is general -- moving a project from Eclipse to IntelliJ -- then don't tag it with 1.7.10. Code specific to that version is not supported, but this sounds to me like a more general question.
  11. You can send the entity's UUID in the packet. You should look at how the packets that get entities to emit particles when under potion effect work. Like you said it isn't a good idea to send packet every tick so probably send once when effect starts and then either has timer or stops when a follow-up packet is sent to indicate potion has worn off.
  12. First it depends what you mean by "outdated". A projectile is an entity and I think entity rendering and models haven't changed like forever.
  13. I think you can handle the EntityJoinWorld (or possibly the EntityConstructing) event and create your your new entity, copy the position and direction of motion and kill the original one.
  14. Okay, but it is a really simple block. No TE at all. So I found the culprit. It is a rendering performance issue. If you set the shouldSideBeRendered() method to return true, it lags horribly then crashes on its own. This block class lags horribly: public class BlockCloud extends BlockIce { public BlockCloud() { super(); // DEBUG System.out.println("BlockCloud constructor"); setTickRandomly(false); } @Override @SideOnly(Side.CLIENT) public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { return true; } } Removing the shouldSideBeRendered() and it works great, no lag or crash. I suppose it makes sense as it is a larger rendering burden. However, I was hoping to enable this because these cloud blocks are translucent but when you mine down into them if you don't have the shouldSideBeRendered enabled then they become invisible which I didn't want... I don't suppose anyone knows of a solution? Guess it is expected if you have a bunch of translucent blocks being rendered fully...?
  15. You can think of a "registry" as simply a map. It might be implemented a bit more complicatedly but basically there are "entries" that have instances of a thing (which you are registering) and some sort of key (ID) to look it up. The point is that then you don't have to reference instances directly unless needed. The entries can be simple in case of singleton classes. For an Item or Block, there is only one instance (per side) in the game so the registry for those references that instance directly. For things like Entities which have many instances in the game, there is the need to build a more complicaed entry which acts more like a factory -- when you get an entity from the registry you get a new one. But for the purposes here, just think of the registries as a list of things (dimensions in this case) associated with a list of IDs. In most of the modern Forge registries the key/ID is actually a resource location made up of your modID plus the registry name. So the rest is just regular Java. You can grab the registries from anywhere in your code since the classes are public. You should literally be able to write ForgeRegistries.BIOMES and your IDE should be able to use it provided your build paths are correct. I personally have Eclipse set up to automatically find the imports on saving, but you can also hover over anything and it should suggest an import. Is that what you mean when you say you can't get the classes? So if you want a list of all biomes, you just say List<Biome> myList = ForgeRegistries.BIOMES.getValues(). Then you can do anything you would normally do with a Java list -- iterate through it, check if it contains() a value you care about and so forth. The list will contain actual Biome instances. Anyway, bit confused on what the problem is. You have classes available with methods that we already explained give standard Java collections as return value. The rest is standard Java.
  16. So your code generates a totally empty dimension, right? At least I didn't see anywhere where you generated blocks. Just checking if that is what you intended. Also, I'm assuming that your registration code is called properly from somewhere. You didn't create a new WorldType. Don't know if that is a problem, as I usually do a new world type along with my new dimensions. How is the player entering your dimension?
  17. So I was working on making a mod that has a new dimension with terrain made from custom blocks. But I found the dimension was lagging a lot (actually it seemingly would run out of memory). I thought it was a bug in my code, so I kept simplifying until all my chunk generator did was generate a sea-level's worth of a single custom block. It was still laggy and running out of memory. So then I tried using a vanilla block and it worked much much better. I was starting to sense that it wasn't my chunk generator logic at all but rather something about the performance of custom blocks. My custom block is super simple. It is copied after Block.ICE and except having its own texture and different slipperiness value I don't think there is any difference. I can show my code except I've been really ripping it up to try to debug so whenever you look at it I can't promise it is in working state: https://github.com/jabelar/ExampleMod-1.12 So then I decided to do a very simple experiment. I created a SuperFlat preset that made 1 layer of bedrock then 64 layers of my custom block. It also lags horribly then finally runs out of memory! I then did same preset using vanilla ice block and it works fine. I'm suspecting it has to do with rendering, but may have to do with the generation itself since the generation seems to lag, but it really seems performance (or memory usage) is noticeably worse with a simple custom block. Has anyone generally experienced more lag when creating a dimension with custom blocks? if you get a chance, try comparing superflat with 64 layers of one of your custom blocks versus vanilla block... My computer has decent specs -- i5 3GHz CPU with 8GB ram and GTX760 graphics card. I could try it on my gaming PC with GTX1080 instead, but I feel this PC should be sufficient. I have the VM getting 4GB heap.
  18. Well, you can probably do it a few different ways. I think having separate types helps for some things (like maybe needed for allowing user to select from new world menu). Also it really depends on how much customization you're doing in the world gen. I've personally found that reusing the vanilla dimension types can cause trouble because the dimension type is what points to the WorldProvider. So for example if you're making modifications to the world provider I think it is best to have new type. In any case, at some point you need to register the dimension to the DimensionManager. I personally use same registration ID for that as for the DimensionType, but again that is because I tend to do new DimensionType as well. note that the DimensionType also has a name which can be used to make it easier to remember which is which. But at the point where you are calling the DimensionManager.register() method, you will know the ID. But I should warn you -- you say you're new to Java and to modding and I have to say that doing new dimensions can be one of the most complicated things to do, especially without being strong in Java. This is because the code is very convoluted -- there are many, many classes involved and they sort of cross reference each other. I have a bit of an explanation here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-biome-quick-tips.html. You may want to follow this tutorial here: https://wiki.mcjty.eu/modding/index.php?title=Dimensions-1.12
  19. I think they are probably using bytecode manipulation (ASM). I see some code that does the same thing here: https://github.com/BoxOfFlex/CynTweaks/blob/master/src/main/java/cynfoxwell/cyntweaks/glint/RenderEffectVisitor.java It actually doesn't look that "difficult" to code up, but I'm not that familiar with doing byte code manipulation, and it isn't really a good way to make mods. Basically the guy has created some config options for a base color, whether you want it to change "rainbow mode" and a speed for the rainbow mode. Based on that, there is a field for the resulting color, and that seems to be injected somewhere (obviously wherever the glint color is stored/used in the vanilla code) I think in item renderer. If that is too advanced, the next option I can think of is maybe you can have several colorized glint PNG stored and change the resource location based on the setting. You wouldn't want to do it quickly (like probably not good for rainbow effect) but could still be a user or code-based control. For armor for example, LayerArmorBase.ENCHANTED_ITEM_GLINT_BASE is the field but has protected scope so you maybe use reflection to access it. Otherwise, you need to intercept the layers somehow. Not sure if there is an event that is targeted enough but there might be. But you could also do things like make your own replacement LayerBipedArmor class and put it into the RenderLivingBase.layerRenderers list. Again though this is protected scope so would likely need reflection. Or maybe you can intercept elsewhere, like replacing the minecraft ItemRenderer with your own version. Anyway, just saying that the rendering probably has some interesting places to intercept it, but you need to be pretty good with Java to track it down and implement it. .
  20. Do you want all the glint to change to the same color? Although you can't fully control the color, apparently by using resource pack technique to replace the grayscale glint PNG with one that is colorized, you can change the color for ALL glint. However, the color is blended with the vanilla (purple) so you can't just make it any color. But you can tweak it. Just saying that if you want to change the color for all glint in the game and want the new color to be one you can create by blending with the vanilla color, then you can change it by directly colorizing the glint PNG asset.
  21. No. That would only tell you that both entities are looking in opposite directions, no matter where they are positioned. I gave you an example of the code in my previous comment. You need to subtract the positions and normalize the result and then dot product that. Actually though you also need to clarify something. You asked about figuring out if an entity is "behind". That can actually mean a few different things. For example, the look vector is actually the look vector based on the head position. So if for example you really wanted to make sure it was behind the back (i.e. based on body rotation instead of head) you might want to do it a bit differently.
  22. You know when I was first answering this I actually wrote to use the ForgeRegistries.BIOMES but then edited it because I like to check in IDE when I give an answer and went looking for the ForgeRegistries class and couldn't find it so figured I'd "mis-remembered". The reason I couldn't find it was because it wasn't in the net.minecraftforge.registries package where I expected it and I didn't bother doing a java search since I didn't imagine there would be another place for it. But you're right, it is in the net.minecraftforge.common.registry package instead... Okay, that is the easier way.
  23. You can test for DimensionType. You shouldn't really have to code using the ID as the registered DimensionType should give you enough information.
  24. Okay, so dot product basically represents the "amount" of a vector is in same direction as another vector. In this particular case of trying to find out if one entity is behind another, you need to be very careful about which two vectors exactly you're using. As Draco18s mentioned, a "vector" can be used to indicate a position or a direction (really a relative position). So one vector of course should be the look vector (make sure it is look vector from the correct entity). But the other vector must be constructed in the right way. It needs to be the vector going from the position of the entity that is "sneaking up behind" to the entity that is looking. Furthermore, you mentioned normalization. This is important two. You need both vectors to be normalized, meaning that the length of the vector is 1.0. I believe the look vector should already be normalized, but for the second vector you'll want to normalize it. I believe Vec3d has method for normalizing. So basically I'm saying that the getPostionVector() part of your code is probably wrong. You don't want the position of either entity, you want the vector the represents the difference in position BETWEEN them, and you need to consider the direction otherwise the dot product will be negative what you expect/ I didn't test this, but (otherEntity.getPositionVector().subtract(entity.getPositionVector()).normalize().dotProduct(otherEntity.getLookVec()) < -0.8. The reason why Draco18s and I are recommending a value of 0.8 is that the concept of "behind" isn't really exact. So this would mean that the direction is mostly (80%) overlapping the negative direction.
  25. It looks close, but you should probably look at the implementation of the vanilla block slab wood blocks and try making your code even closer. For example, in your constructor you set the block state based without any variant. Now that could make sense in your case, if you only have one type of slab you're making. However, it could also screw up your blockstates and model files unless you know what you're doing. So you're close, but I would personally work back and copy more of the vanilla stuff until you get it working, and only then change things if you think you need to.
×
×
  • Create New...

Important Information

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