Jump to content

SerpentDagger

Members
  • Posts

    160
  • Joined

  • Last visited

  • Days Won

    4

Posts posted by SerpentDagger

  1. 48 minutes ago, That_Martin_Guy said:

    It actually rotates around the z-axis first, if I understand it correctly.

    Matrix transformations actually take effect in the opposite order from that of multiplication, which means that it is indeed how I described.

     

    53 minutes ago, That_Martin_Guy said:

    I'm not sure how I would go about setting up this parent-child relationship when doing the rotations separately with this knowledge. Not the greatest at this sort of math.

    I think the way ModelRenderer works means that you could have a parent instance whose yRot is set based on block rotation, and then add your current ModelRenderer with addChild, but only set its zRot. The child should be rendered when the parent's render method is called.

  2. It looks like the code in ModelRenderer applies rotations X→Y→Z, then translation (Matrix transformations definitely have an order. Sorry, I wasn't thinking). That's why your problem is presenting itself. On the bright side, I think* ModelRenderers can have children which inherit the rotations and translations of the parent. This means that you should be able to have a parent ModelRenderer with the Y rotation, and then the child can have the Z rotation, which is then independent of the block's direction.

    *Never used them before, sorry.

  3. What code is processing these angles? To me, it looks like the rotations are processed in the order X, then Y, then Z. This would make it impossible to get the desired skew result in the East/West directions. Here's what I think is happening:

    Your model starts with the face pointing to Z+, and the tip to Y+. To get it into a skew for the North/South position, you rotate around Y to account for the flip, then around Z for the skew. All good. To get it into a skew for the East/West, you would have to rotate around Y ± π/2, then around X. Problematic, since the X rotation happens first. If you try to rotate around X first, you just tilt the piece forward or backward, as you've seen. If you try and rotate around Z after, the piece is already pointing face to X±, tip to Y+, and at that point the Z rotation will just tilt it forward/back, as you've seen.

    If this is the case, you need to process the rotations in a more useful order, namely with Y first. If you need a more flexible system: I don't think matrix transformations have a specific order*, which would prevent this problem from occurring.

    *Not true. They have a specific order. They take effect in the order opposite that of the original multiplications.

  4. 7 hours ago, Draco18s said:

    Specifically which version are you wanting to go back to?

    I was going to make a tweak in a 1.12.2 mod. (The graphing calculator linked to in my signature.)

    7 hours ago, Draco18s said:

    And honestly, run the setup for it and see what happens.

    I've done that now, and everything works. The 1.12 version of LWJGL didn't overwrite the 1.16 one (Their file paths diverge at the version number of LWJGL), which left me somewhat puzzled as to what happened to the 1.12 stuff to begin with.

    Between these two Minecraft projects, I ported the graphing calculator to a standalone Java application, and installed my own version of LWJGL to work with. I think that must have overwritten the 1.12 set, and then was overwritten by the 1.17 set before I missed the 1.12, leaving me to think that 1.17 was responsible for both. All very irritating. lol

    I ought to apologize for this post, then, since it isn't really a Forge issue. When I do more work with my personal LWJGL projects, I'll install the libraries to a different directory from the one Forge uses, since apparently the installer has the same default. Thanks for the help!

  5. 21 hours ago, Luis_ST said:

    what do you mean by "develop in multiple versions simultaneously" exactly

    I want to develop my 1.16 mod on and off (and update to 1.17), but also be able to tweak mods in older versions of the game, without having to re-download the LWGJL dependencies every time I switch. This would be accomplished by having each version of Forge download LWGJL to an independent directory, instead of the default (which is what causes the new version to overwrite the old).

    21 hours ago, Luis_ST said:

    also note that the last supported version is 1.16.x

    Indeed. I'm not asking for help in outdated versions, just trying to work with more than one at a time.

     

    13 hours ago, Draco18s said:

    I use different workspaces for each version of Forge.

    I do that also, but the problem is that the dependencies (LWJGL3, to be specific) of the new version of Forge overwrite the dependencies of the old one, since they're downloaded to the same workspace-external directory. The build path is also set up to expect them there, so if I were to move the files, I'd have to manually reconfigure the build path to point to the new location. That would be tedious to do for every single file, and the problem would rear up again if I ever had to re-run setup for some other reason.

    13 hours ago, Draco18s said:

    Re-running setup might not be sufficient, as the server resources have moved a couple of times, so the old setup files might not be downloading from the right URL.

    This is interesting. In truth, I haven't re-run setup for the older version, because doing so would overwrite the newer LWGJL files, and I'd rather be able to keep developing in the current version. I was mostly expecting it to work, however, when I tried it. Does this mean that it isn't possible to develop in old versions at all, or simply that the new resulting file structure wouldn't necessarily match the expected build path of my old project? If the latter, wouldn't re-running setup also reformat the build path to match? I thought that was automatic.

  6. I've long-since switched over to Forge 1.16, but recently got a feature request on an older mod, which I wanted to look into implementing. I opened up my old workspace, and discovered that the build path is no longer valid, because the new Forge dependencies overwrote the old ones.

    I suppose I could rerun the setup tasks every time I switched workspace (right?), but that seems like an impractical solution.

    Is there any way to have non-colliding build paths for the two workspaces, so that I can develop in multiple versions simultaneously?

  7. I've done some testing, and there are 3 things that cause the item to move.

    The first is when you return a success, the item will swing. Updating the returns as previously discussed achieves the desired result in this context.

    The second is when you return a consume, the item will bob if it is not in use. This means that if you try to use the pan while not able to do any panning, it will bob repeatedly (but not jarringly quickly). If you don't want this, you can return a pass, which has no visual effect.

    The third is when you set the damage value every tick. This is what causes the glitchy-looking vibration, and it would seem you can fix it by setting the damage less frequently (once every 3 ticks eliminated all unwanted movement in my experiments).

    • Like 1
  8. This is your problem.

    The boolean parameter of ActionResult<T>#sidedSuccess is whether or not the game is running on the logical client, and so returns success on true, or consume on false. Your condition will usually be true, so a success is usually returned, which causes the item to swing. I don't think it's necessary to use sidedSuccess for this, but if you do, you should pass in World.isClientSide, or an equivalent. Regardless, the condition should be updated.

  9. 22 minutes ago, Skelyvelocirap said:

    Ok, well it seems to work exactly how i want it to currently! Although, for some reason it still swings the players arms even though im returning ActionResult#consume(stack). Am i supposed to override that somewhere else as well?

    Please post your code, so that I can see what might be causing this (I won't be able to respond until tomorrow, though, since I need to sleep now).

    22 minutes ago, Skelyvelocirap said:

    Also, this isn't 100% related but what would I need to override to add an animation to the item? I don't mean how do I make an animation(don't quite know how but i should be able to find it on google), rather how do I make it play when the item is held down. I now know that for the items it would be the Item#onUseTick. Is there a similar method for the animation?

    I've never done this before, so my knowledge is limited. Here is a link to the documentation on the topic, though, which seems fairly straightforward.

    • Like 1
  10. 4 minutes ago, Skelyvelocirap said:

    Alright. So ActionResult basically just tells Minecraft whether or not to swing the hand, along with whether or not it should process the item further(so inhibiting other items from doing their thing instead).

    Yup, that's about right.

    4 minutes ago, Skelyvelocirap said:

    And so I would simply check(in Item#use) if LivingEntity#getUseItemRemainingTicks is greater than 0, if it is than return Consume, or else success?

    The exact details of when you should do what depend on how you want it to work and look. Ultimately, that's up to you, so you should try to set something up using these tools, experiment a bit, and figure out what produces the best result. It seems like you mostly understand what's going on here, so that ought to go fairly well.

  11. 30 minutes ago, Skelyvelocirap said:

    My guess is that its what is responsible for the hand movement when you right click(am I correct?). If it is, how exactly would I fix it so that it only does that once Item#onUseTick's tick parameter is 0?

    It is responsible for determining how the hand moves, but it also does a bit more.

    Each ActionResult<T> has an ActionResultType and an object T. In the case of the ActionResult<ItemStack>, the ItemStack object of the returned ActionResult<ItemStack> is set as the held item.

    Additionally, these ActionResultTypes dictate what happens after your Item's logic has been run. They are queried with the ActionResultType#shouldSwing and ActionResultType#consumesAction methods. The former is self-explanitory, while the latter dictates whether or not the click will be further processed.

    For example, ActionResultType.SUCCESS both consumes the action and swings. This means that if you held an ender pearl in your offhand, and clicked with an item that returns a successful ActionResult<ItemStack>, the main item would swing, and no ender pearl would be thrown. ActionResultType.PASS doesn't swing or consume, so returning that would result in no animation of the main item, and an unblocked, thrown ender pearl. ActionResultType.CONSUME consumes the action, but doesn't swing, so that's probably what you want here. ActionResultType.FAIL behaves as PASS, but is used more in the context of Block placement, I think, and as a message to prevent a behaviour.

    For your purposes, I would probably recommend returning CONSUME unless LIvingEntity#getUseItemRemainingTicks (this is the value passed into Item#onUseTick) fits your requirements (you could also use LivingEntity#getTicksUsingItem), in which case you would return SUCCESS.

    It might also be helpful to return true from Item#useOnRelease, so that your item is used when released, in addition to initially.

  12. 3 hours ago, Skelyvelocirap said:

    Can someone help be with this?

    Within Item#use, you should call PlayerEntity#startUsingItem. This will start using the item when the item is used.

    You can set the maximum number of ticks that the item can be used for with the return value of Item#getUseDuration.

    While the item is being used, Item#onUseTick will be called every tick, and its integer parameter is the number of ticks left in the use duration. This is probably where you want to put your logic, since you mentioned that the player should be able to keep holding the item to keep the process going.

    At some point, the player will release the item, which calls Item#releaseUsing. Its integer parameter is the number of ticks that the item was used for, so you could also put some logic there.

    • Like 1
  13. 3 hours ago, Khamai said:

    How do I go about storing custom player data such as a mana count for each individual player? I believe it has something to do with NBT however I can't find much on it for 1.16 Forge Modding.

    You should almost certainly use the Capability system for this purpose. Here is a link to its documentation.

  14. 6 hours ago, skip999 said:

    However, the log will display this (I have attached the full log for more details) for all my custom recipes:

    This is a warning that no category in the recipe book corresponds to those IRecipeTypes. The method that determines that is hardcoded for vanilla types only, so this is to be expected. It doesn't mean you've done anything wrong, or that the recipes will fail to work, and I don't think there's any way to get rid of it for custom IRecipeTypes.

     

  15. This effect is hardcoded for the Nether portal only. If you wanted to recreate the effect, I think you could perform similar operations on the projection matrix before rendering, which would be done in the EntityViewRenderEvent.CameraSetup. Unfortunately, this event is fired after the projection matrix is already loaded into RenderSystem, and with no reference to the general-purpose new MatrixStack that is passed around for rendering. In order to modify it, then, you would use RenderSystem#multMatrix() with your effect matrix. This method is marked as deprecated, which means it's not supposed to be called in general. I don't know what the consequences of doing so are.

  16. 10 hours ago, Nephty said:

    I wonder if executing the task runData will overwrite the previous file ? Or if the data is in any danger of potential erasure ?  As an example, I said previously that I use the simpleBlock() method and that I think this is what tells the game to create a full block. If I runData, will it overwrite the parent and replace it with a full block again ?

    runData has an output folder that is specified by the build.gradle file. I think the default is src/generated. It will overwrite files that it's previously put there. The idea, I think, is that you move the files you need from the generated folder into your main resources folder, but the problem I found there is that the build.gradle file by default allows assets to be kept in the src/generated folder, and will look for them there, which causes weird conflicts if you don't delete everything from the generated folder and refresh the IDE. That's not very convenient, so I changed my build.gradle to ignore the assets in src/generated.

    3 hours ago, Nephty said:

    the string referring to the texture in the json file located in generated\resources\assets\mod\blockstates

    These strings do not refer to textures, they refer to models, as I mentioned in my previous post. BlockState → Model → Shape & Texture.

    3 hours ago, Nephty said:

    1. I use a texture located in the items folder instead of the blocks folder : the rendered block becomes a flat image, as if you simply put the item from your hand on the ground. Not a cross texture, neither a full block.

    Because of the previous point, you are referencing the item model, which is a flat image that generally appears in the hand. The texture reference in the item model is defined correctly.

    3 hours ago, Nephty said:

    2. I use the correct texture in the blocks folder : the rendered block is a cross block but the texture is the "missing texture" one, purple and black squares.

    Again, this is the block model, not the texture. The model is found correctly, and the parent is defined correctly, resulting in the correct shape, but the texture is not found. There should be an error message in the console window that tells you more information about the problem. These error messages tend to be quite helpful, so do look for it. It's probably a typo in the model json, a typo in the texture file's name, or a misplaced texture file.

    3 hours ago, Nephty said:

    3. I use the name of a texture that doesn't exite : the rendered block is a full block with the missing texture.

    Since the model (again: model, not texture) doesn't exist, neither the shape nor the texture (both of these are defined by the model file) can be determined. This means that the game uses the default shape (a block) with the default texture (the "missing" texture).

  17. 8 minutes ago, Nephty said:

    What Material could I reference here ? I tried Plant, Decoration, Bamboo Sapling, Grass and Coral but the final result is always the same : the flower looks like what's shown in the picture. In the source code, a Poppy is created using Properties.of(Material.PLANT), so I guessed I'd go with that too.

    The Material specifies generic properties like whether or not the block can be collided with, how it interacts with pistons, whether it burns, etc. It won't solve your rendering problem, but will dictate some other relevant behaviors. Using the settings of PLANT is probably exactly what you want in this regard.

    7 minutes ago, Nephty said:

    How can I access this json file ? And what can I do to modify the BlockState of my flower ? I found a json file in a ressource pack that has the parent block/cross, but I don't really know how to apply this to my flower.

    In .minecraft/versions/[version_folder] there is a jar file, which you can extract somewhere convenient. In this extracted folder, there is an assets/minecraft folder, which contains the Minecraft assets which you can use as reference.

    BlockState describes a combination of IProperty<?>s. Your Block's blockstate file maps these combinations to a number of model files to use for each one. You don't need to alter the BlockState of your flower to change its default model, but if you want to add different models for different combinations of IProperty<?>s, you would do so with BlockStates. Here is a link to how one interacts with BlockStates in code. Here is a link to documentation on writing a blockstate file.

    What you're looking for to change the default model of the block is the model file, not the blockstate file. A model file defines the elements and textures of a model in the world. Alternatively, the model file can reference a different model file that is already defined (the "parent" model), and simply alter the textures of that parent model. This is what the line "parent": "block/cross" does. It defines the parent model as being the one named cross in the folder block. To make your flower render with a cross model, then, you would use its model file to define its parent to be block/cross, and then alter the textures tag to use your own flower texture.

    textures is a tag containing a number of String variables, whose names should correspond to the parent model's definitions. The cross model has only one textures variable, which is named cross.

    • Thanks 1
  18. 1 hour ago, Nephty said:

    I sought and found out about a "isOpaqueBlock" method, yet I can't find it anywhere

    These sorts of properties are now part of the AbstractBlock.Properties object that you pass to the Block constructor. The methods you're probably interested in are noOcclusion and noCollission. The Material of the Properties is also relevant here, since they have the nonSolid building method.

    The reason your flower is rendered on the outside of a cube is that its model defines that to be the case. You should look at the model file of a block with the relevant model to determine how to change this. models/block/dead_bush.json, for example, uses the parent block/cross, which I think is what you're after.

    • Thanks 1
  19.     @SubscribeEvent
        public void onWorldTick(final TickEvent.WorldTickEvent event){
            if(this.world == null){
                this.world = event.world;
            }
            if(random.nextInt(2) == 0){
                swapBlock();
            }
        }

    My guess would be that this is the problem. You only ever set the World object once, and I don't think it's the same object between loads of the world, which means that you're trying to edit the old World when it is no longer being processed. It seems likely that yours is the last reference to that World object, since it should have been unloaded, which would also be causing a memory leak.

    From the previous topic, this is a Capability, right? That means you can unload the IDecay object during the write/readNBT methods. It looks like you're applying the decay logic every tick, which means that it should be feasible to discard the IDecay objects between world-loadings.

  20. I've finally got a solution to the positional problem. It turns out DrawHighlightEvent is fired before all the relevant batches are drawn, while RenderWorldLastEvent is fired after all the buffers have been drawn. (I would consider this a bug.) That means that while your buffer's waiting patiently to be drawn, other parts of the code can change the global projection matrix. Notably, GameRenderer#renderItemInHand starts mucking about with the projection matrix naught but 4 lines later. The result is all this unpredictable failure.

    The solution is to draw your buffer at the end of writing to it, with Impl#endBatch(RenderType). Here is a working (and more thoroughly tested) example:

    @EventBusSubscriber(Dist.CLIENT)
    public class SpellRenderEventSubscriber
    {	
    	@SubscribeEvent
    	public static void worldRender(RenderWorldLastEvent event)
    	{
    		Impl buffer = Minecraft.getInstance().renderBuffers().bufferSource();
    		IVertexBuilder builder = buffer.getBuffer(SpellRender.QUADS); //SpellRender.QUADS is a personal RenderType, of VertexFormat POSITION_COLOR.
    		
    		MatrixStack stack = event.getMatrixStack();
    		
    		stack.pushPose();
    		
    		Vector3d cam = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
    		stack.translate(-cam.x, -cam.y, -cam.z);
    		
    		Matrix4f mat = stack.last().pose();
    		
    		builder.vertex(mat, 0, 57, 0).color(0, 255, 255, 150).endVertex();
    		builder.vertex(mat, 1, 57, 0).color(0, 255, 255, 150).endVertex();
    		builder.vertex(mat, 1, 58, 0).color(0, 255, 255, 150).endVertex();
    		builder.vertex(mat, 0, 58, 0).color(0, 255, 255, 150).endVertex();
    		
    		stack.popPose();
    		
    		buffer.endBatch(SpellRender.QUADS);
    	}
    }

    And the result, which stays where it's told despite all manner of character-scooching/FOV-changing:

    Success.png.1b0d048f1a3f68c5d374cacb2adecd45.png

    • Thanks 1
  21. First I need to apologize for the previous post. It looked to hold true while I was writing it, but with further testing it would seem I don't know what I'm talking about. Sorry about that mess.

    I'm working on a similar problem, and (apparently) haven't figured out how to solve it yet, but have a couple clues that might help...

    ● TileEntityRenderers render in block-space, which means that their MatrixStack has to get that way somehow. GameRenderer#renderLevel calls WorldRender#renderLevel, which activates the TileEntityRendererDispatcher, which activates the TileEntityRenderers.

    ● GameRenderer#renderLevel receives a new MatrixStack() as a parameter. It also creates a new MatrixStack(), which is multiplied by the projection matrix of the main camera and bobbing/portal effects. The RenderSystem is then reset to that projection matrix pose, and the GameRender.mainCamera is setup to include information about the view entity and camera (not including projection information). It then multiplies the parameter stack by rotations of the camera, making it a rotation matrix.

    ● I would expect the application of the projection matrix to RenderSystem to be effective globally, since it's internally a process of GlStateManager.

    ● GameRenderer#renderLevel passes both the projection Matrix4f and the rotation MatrixStack to WorldRender#renderLevel, as well as the ActiveRenderInfo. We in RenderWorldLastEvent just get the projection and rotation matrices, but the ActiveRenderInfo in question is just a reference to GameRenderer.mainCamera.

    ● From what I can tell, no change persists to either of the matrices between the calling of WorldRender#renderLevel and RenderWorldLastEvent, which means that we should be able to follow the TileEntityRendererDispatcher's transforms.

    ● Unfortunately, the only transform applied is a translation of the matrix by the position of the TileEntity in question minus the ActiveRenderInfo's position, which is the equivalent of exactly what we're doing already. This is all I would expect to be necessary, though. If the projection matrix is globally applied, and the stack already contains rotational information, then translation is all that ought to be needed.

    I don't understand why applying the same transformations as the TileEntitys receive doesn't yield a comparable result. I suppose they must not be the same transformations, but I can't figure out where they differ (and I've spent a long time looking). Hopefully this information is helpful to someone, because I'm just about out of ideas.

     

    On the same topic, the most I've been able to conjure is a location that's sort of right in first person, and entirely wrong in 3rd person if you have an item in your hotbar. That suggests to me that the item rendering interferes with RenderWorldLastEvent's matrices, which I suppose is where I'll spend my next bout of free time. Does your render have the same problem? You never specified exactly how things are moving wrong.

     

    As for the line width, it looks like that's a fixed property of the LineState set on creation of RenderType.LINES, which is loaded into the RenderSystem every time the buffer begins drawing. In order to change it, that means you would need to create your own RenderType. Botania has an example of how to do this.

     

    The color is a bit more odd. I had a similar problem when I accidentally used IVertexBuilder#color(int, int, int, int), instead of IVertexBuilder#color(float, float, float, float), but WorldRender#renderLineBox shouldn't have that issue.

     

    Sorry I'm not able to be more helpful. 😕

  22. EDIT: I'm wrong.

     

    On 5/18/2021 at 11:39 AM, Silverminer said:

    The lines are also moving while flying, sprinting and bobbing.

    These days, instead of manually interpolating between tick positions, there's a method Entity#getPosition(float), which returns an interpolated Vector3d. That is the vector which you should use to translate the MatrixStack back to world-space, from entity-space. Passing the last matrix pose in as a parameter to IVertexBuilder#vertex(Matrix4f, float, float, float) will transform from camera-space to entity-space (while using IVertexBuilder#vertex(float, float, float) operates in camera-space).

    Here is an example of rendering a translucent white quad near the world origin.

    Spoiler
    
    @EventBusSubscriber(Dist.CLIENT)
    public class SpellRenderEventSubscriber
    {
    	@SubscribeEvent
    	public static void worldRender(RenderWorldLastEvent event)
    	{
    		IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().renderBuffers().bufferSource();
    		IVertexBuilder builder = buffer.getBuffer(SpellRender.QUADS); //SpellRender.QUADS is a personal RenderType, of VertexFormat POSITION_COLOR.
    		
    		MatrixStack stack = event.getMatrixStack();
    		
    		stack.pushPose();
    		
    		Vector3d player = Minecraft.getInstance().player.getPosition(event.getPartialTicks());
    		stack.translate(-player.x, -player.y, -player.z);
    		
    		Matrix4f mat = stack.last().pose();
    		
    		builder.vertex(mat, 0, 0, -2).color(255, 255, 255, 150).endVertex();
    		builder.vertex(mat, 1, 0, -2).color(255, 255, 255, 150).endVertex();
    		builder.vertex(mat, 1, 1, -2).color(255, 255, 255, 150).endVertex();
    		builder.vertex(mat, 0, 1, -2).color(255, 255, 255, 150).endVertex();
    		
    		stack.popPose();
    	}
    }

     

     

×
×
  • Create New...

Important Information

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