Jump to content

SerpentDagger

Members
  • Posts

    160
  • Joined

  • Last visited

  • Days Won

    4

Everything posted by SerpentDagger

  1. I am putting together a spellcasting system, and the spells will have visual effects. I have a Capability which holds the player's active Spell, as well as whichever passive Spells may still be causing residual effects. I would like to access these Spells through a rendering event (I was thinking RenderWorldLastEvent), and perform the relevant rendering. The problem is that I would like to define these rendering methods in a neat way, rather than dumping them willy-nilly into the event class, especially as there are potentially many Spells, each with potentially different rendering specifications. That would get horrible quite quickly, and I'd have to check each Spell to find the appropriate rendering method. As an alternative, I was thinking of having Spell#render methods which could easily be called from the render event, and would be overridden by extensions of the base class. These methods, though, would crash a dedicated server when the given Spell was loaded, if I understand things correctly, even though they would never be called. Looking at the Item class, it seems a solution to a similar problem is accomplished with @OnlyIn, which I think would work here too, but the Documentation says "Only use it if you are overriding a vanilla method that already has @OnlyIn defined. In most other cases ..., use DistExecutor instead." I've heard some dissuasion around DistExecutor, though, too (and I'm less sure how it works). What would be an appropriate way of separating this code, without producing a mess?
  2. Hello, I recently got re-interested in modding, and have been going through the documentation to brush up my knowledge. I'm working on a BlockStateProvider to take care of mass-producing simple files. I have verified that its event code is being run, but BlockStateProvider#registerStatesAndModels() is never called (I am using runData). Any help would be appreciated. EventSubscriber and registration BlockStateProvider build.gradle
  3. This is checking from (x, y, z) to (x, y + 1, z), which is a box of width 0, depth 0, and height 1. It seems unlikely that an item would fit within that one. Beyond that... This will never be true. The ItemStack stored in this EntityItem will never == that new ItemStack() you created above. You need to compare the two by their ItemStack#getItem() methods.
  4. Yes. The box you create exists as the coordinates with which you create it. Since you're currently setting it up to range from (0, 0, 0) to (1, 1, 1), you need to offset it by the position of your block, or create it with coordinates derived from the position of the block in the first place.
  5. You're currently checking for entities at (0, 0, 0). You need to offset the box's position by the position of the block being clicked. As a side note, you should also never mix tabs and spaces for your indentation. Choose one and treat the other like plague.
  6. It depends on the order in which things are drawn, by default. You can either draw the tab before everything else draws (the feasibility of this depends on where your draw method's called), trim the texture so that it doesn't poke past where it ought to (or the equivalent with u/v changes), or do some funny business with Gui#zLevel. Gui#drawTexturedModalRect() draws at the current zLevel, so you should be able to altar that value (and then reset it) if you're in the right situation (it's protected). Also, if you're using Eclipse, Ctrl+Shift+F is your friend (code formatter). You can set it up in the preferences somewhere.
  7. Could you show an example of this? I'm not sure what you mean. That seems odd. For example, when I disable depth in one of my rendering sections, the arms and rendering turn out like this. (It's an opaque sphere.) I think you may have been looking in the wrong location there. In fact, I can't find any reference to GlStateManager#disableDepth() within ItemRenderer#renderItemInFirstPerson(), ItemRenderer#renderArmFirstPerson(), RenderPlayer#renderRightArm(), or ModelRenderer#doRender(). Moreover, cull is actually disabled in RenderLivingBase#doRender(). To solve your problem, then, I think you need to disable culling, and enable depth. That might just get you back to your original issue, but I'd like to make sure I understand what that is before I try and help there.
  8. You can subscribe to ItemTossEvent and keep track of relevant items, then check to see if your conditions are met within one of the TickEvents. Keep in mind that there's no guarantee that the items remain in the world once thrown, so your list of items should update to remove those that should no longer exist. Yes. Within the inventory, items are ItemStack objects, while on the ground they're EntityItem objects. You can get the ItemStack represented by an EntityItem through EntityItem#getItem().
  9. You can create an AxisAlignedBB in the location of interest and use one of World's get-entities-within-bounding-box methods. One of these is World#getEntitiesWithinAABBExcludingEntity(), but there are several, each with slightly different names/purposes.
  10. Having finished cleaning up the concepts above, I though't I'd take a moment To summarize and clarify the answer to the question for future readers, while the memory is fresh. If you have a TESR or FastTESR that doesn't change its vertices every frame, or that only translates the vertices every frame, then you have at least two options for improving performance. As I stated in previous posts, I actually managed a 7-10 times performance improvement. The first option is to use call lists, while the second is to adapt the Tessellator slightly (from now on, the adapted Tessellator will be referenced as ATess). In both cases, you can reuse the Tessellator rendering code you've probably already got. I should note that you can also take advantage of VBOs with the call list system, and gain a bit of extra performance, but only when the graphics card supports them. Because of that, you can't rely on VBOs alone. I never got them working well, and so I won't be discussing them further, but there's "example" code in RenderGlobal. The benefit of using call lists over ATess is that you won't impact performance (or at least, you will impact it much less) when the player isn't looking at the object being rendered. The benefit of using ATess is that it is about 25% faster than the call lists (in my experience) when you are looking at the object, and it allows you to sort vertices to weed out transparency issues. Call lists are stored by OpenGL, and accessed through integer IDs. To create and use call lists, you can do the following: - Check to see if the list has already been created, and destroy it if so, using GlAllocation#deleteDisplayLists(). - Get an instance of the Tessellator and its BufferBuilder. - Allocate a rendering ID through GlAllocation#generateDisplayLists(). - Create a new list with the generated ID by using GlStateManager#glNewList(). - Begin drawing with your BufferBuilder. - Add vertices to the buffer in the same manner as with the Tessellator. - Call Tessellator#draw(). - Finish the list with GlStateManager#glEndList(). - You can now render this call list by using GlStateManager#callList(), and passing in the ID you stored earlier. The adapted Tessellator (ATess) and adapted BufferBuilder (ABuff from now on) are only different in that you can swap the ABuff into and out from the ATess, and in that the ABuff doesn't reset when drawn. This allows you to not constantly reload all the data into the buffer. The code for these adaptations is shown below. To use them: - Create a new ATess instance, and get its ABuff. - I ended up storing the ABuffs within an array, which allowed me to mostly reuse the render ID system stated above in the call list section. This isn't necessary, though. - Begin drawing with the ABuff. - Add vertices as you would with the standard Tessellator and BufferBuilder. - Call ATess#draw(). - Save the ABuff somewhere for later use. It now contains your rendering data. - You can now render this ABuff by swapping it into an ATess and calling ATess#draw(). You can also sort the vertex data, since ABuff extends BufferBuilder. ATess and ABuff classes:
  11. Skulls, I'm afraid, don't have rotated collision boxes. Unfortunately, I don't think there's any easy way for you to do this, but I can't say that for certain, of course.
  12. Ah, in that case you need not worry about the Tessellator or BufferBuilder#lightmap(), they're applicable in different scenarios than the one you seem to be dealing with. Sorry about that. The Tessellator is a commonly used method of rendering things directly in the world. In using it, you first apply various settings using the GlStateManager, then add vertices into the Tessellator's buffer, draw the buffer with Tessellator#draw(), and then reset the necessary settings with the GlStateManager. A VertexFormat is applied when beginning to add vertices to the buffer, and it dictates what information each vertex requires. For example: you might use DefaultVertexFormats#POSITION_COLOR, in which case you would need to add position information, followed immediately by color information, to the vertex you're building. Some general information about how the Tessellator works can be found here, but it's a bit outdated, so you should refer to my answer here for exact steps. Here's a simple example, but that was back when I was just learning about this stuff, so I got the translation wrong (as explained in the answer I followed up with). The rest's fine. Like I said, though, it seems you've got a different situation here, so that's mostly just in case you have an insatiable thirst for MInecraft rendering knowledge.
  13. Having implemented this, the transparency is proper in that respect too. I keep an ordered array of graphs, and render according to that order. I decided to only sort vertices and graphs every 10 frames, to mitigate the performance impact. This works fairly well, but results in regular lag spikes when the graph is complicated enough to cause them. That seems better, however, than constant lag of the same magnitude. I've noticed that the method of swapping BufferBuilders into the Tessellator and rendering with Tessellator#draw() is actually ~25% faster than using call lists, but that the call list only impacts performance significantly when you're actually looking at the graph, while the Tessellator method is constant, no matter where you look. This is a bit of a dilemma, as I'm not sure which is less intrusive-- constant but lesser lag, or higher lag only when you're looking at the graph. I'm sort of leaning towards the latter. After all, there's no point in impacting performance if you're not looking at the thing, right? Thoughts on the above would be appreciated.
  14. That's because you never do anything with the compound you made. You need to set the stack's NBT to be the tag, using ItemStack#setTagCompound().
  15. I decided to switch away from call lists for translucent graphs, trying instead to use the Tessellator / BufferBuilder combo in order to have access to BufferBuilder#sortVertexData(). I wanted to be efficient, and store the BufferBuilder for later once I generated it, swapping it into a Tessellator during rendering. As it turns out, the Tessellator system is rigged such that there's no way to do that. The BufferBuilder is reset after every draw, and the BufferBuilder field of the Tessellator is private and final. In order to get around that, I created a new Tessellator with a public non-final BufferBuilder, and an extension of BufferBuilder who's reset() and finishDrawing() methods are altered to not reset and not finish. This allows me to store and reuse my BufferBuilder objects, instead of throwing them away and rebuilding them constantly (a very expensive endeavor). I can now also use BufferBuilder#sortVertexData() on the buffer being swapped into the Tessellator, and my transparent graphs are properly rendered. This all maintaining a similar 7-fold performance improvement over the standard system.
  16. I realized that the FastTESR method of rendering (add vertices to a communal buffer, render buffer, throw away buffer and ask for more vertices) is, at least for my purposes, extremely wasteful. In my current situation, nothing changes location, so there's no need to discard the data after every frame, and reload it before the next. As a result of this concept, I've mostly circumvented the system: no longer contributing to the buffer, and simply using the method as one that is called for each frame, for each tile entity. Instead, when the graph is first loaded, I use the GlStateManager to generate a new call list (and delete the old one if it existed), and store the reference to this list within the TileEntity that I was given during FastTESR#renderTileEntityFast(). During subsequent frames, I then simply use GlStateManager#callList() to render the call list whose reference index is stored in the TileEntity. It isn't a standard use of the FastTESR system, but it does produce a 7-fold performance improvement, or much more, depending on the circumstances. The only problem this presents is that I'm no longer able to take advantage of the depth-sorting that's run on the vertices of the batched FastTESR buffer. This means that graphs are rendered "out of order," which is especially a problem for translucent ones. I can fix the problem of individual graphs rendering out of order (e.g: a graph behind is rendered on top of one in front) by moving the actual rendering over to one of the rendering events, and then drawing the furthest graph first, etc, but I'm not sure if there's a way of fixing the order within a graph being off, while keeping to call lists (BufferBulder#sortVertexData() isn't applicable to call lists). I'll keep looking, though.
  17. It's used within Minecraft's rendering code, one example being located within BlockFluidRenderer#renderFluid(). I personally haven't used it extensively, so I'm not the best one to try and explain this, but the two ints seem to correspond to brightness, and range from 0 to ~220. I think they're (u, v) coordinates on Minecraft's lightmap texture. In the fluid class I pointed to earlier, though, they result from the manipulation of the value returned from IBlockProperties#getPackedLightmapCoords(). What I've done with them is contour 3D graphs, which is independent of the world's lighting, so I'm not sure how to do that myself. In my work, I used the first as a sort of "base" brightness, and manipulated the second to alter it from there. I don't know if that's the generally used method, though. It's worth noting, in case you're unfamiliar with the Tessellator, that this method should be used in accordance with the vertex format at hand, which is something you should learn a little about if you haven't already.
  18. I think you need to use World#getBlockState() instead of IBlockState#getActualState() in this context. To understand the difference, take a look at the documentation on this topic.
  19. I wouldn't go that far. There's a reason RayTraceResult has an entityHit field.
  20. Code Style #3, but that's the least of the problems. Why are you overriding onBlockActivated in BlockTileEntity if you do nothing with it? And what's with all the floating abstract methods? This: @Override public boolean hasTileEntity(IBlockState state) { // TODO Auto-generated method stub return super.hasTileEntity(state); } @Override public TileEntity createTileEntity(World world, IBlockState state) { // TODO Auto-generated method stub return super.createTileEntity(world, state); } does nothing. Block#hasTileEntity() returns false by default, unless you're using ITileEntityProvider. Block#createTileEntity() returns null unless you're using ITileEntityProvider. That said, you shouldn't use ITileEntityProvider. Just return something useful from those two methods instead. As a result, public TE getTileEntity(IBlockAccess world, BlockPos pos) {  return (TE)world.getTileEntity(pos); } will return null on the position of the Block, because no TileEntity will ever be created, so it doesn't matter whether you've successfully registered the TileEntity or not. In this: if(pos.down() == ModBlocks.MAGIC_BLOCK.getDefaultState()) { if(playerIn.inventory.getCurrentItem().getItem() == glass) { BlockTileEntity.spawnAsEntity(worldIn, pos,glass2); return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); } } pos.down(), which returns a BlockPos, is never going to == an IBlockState. It's a small wonder, then, that the code inside that check never runs. In addition, Block#spawnAsEntity() is not what you're looking for to spawn a visual item. It'll spawn a normal item that players can pick up, will be moved by water, etc. You should create your own EntityItem, set it's properties to fit your needs, and then use World#spawnEntity(). Alternatively, you could set up a TileEntitySpecialRenderer if you need something more customized. As an aside, can you get rid of all the auto-generated comments?
  21. Post the actual crash log, please. A couple problems, if this is all the relevant code: -You assume that the result is always an Entity. This is not necessarily the case. -You assume that the result always contains a BlockPos. This not necessarily the case, and, in fact, this and the previous assumption are mutually exclusive. No Entity result has a BlockPos, and no Block result has an Entity. -Unless you know what you're doing, you should probably remove ", 11" from your call of setBlockState() to use the standard one. I suggest you take a look at EntitySmallFireball#onImpact().
  22. The context depends on the context, naturally, but I think what you're looking for is generally going to be the BufferBuilder#lightmap() method, if you're using the Tessellator. Otherwise, more specific questioning would be appreciated.
  23. Those two lines of code do not do the same thing. If you don't want a TESR, and you haven't already registered your tile entity, then cool. If that's not the case, however, I fear you may be disappointed.
×
×
  • Create New...

Important Information

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