-
Posts
160 -
Joined
-
Last visited
-
Days Won
4
Everything posted by SerpentDagger
-
[1.16.5] Rotation angles/axis not consistent when rotated
SerpentDagger replied to That_Martin_Guy's topic in Modder Support
Matrix transformations actually take effect in the opposite order from that of multiplication, which means that it is indeed how I described. 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. -
[1.16.5] Rotation angles/axis not consistent when rotated
SerpentDagger replied to That_Martin_Guy's topic in Modder Support
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. -
[1.16.5] Rotation angles/axis not consistent when rotated
SerpentDagger replied to That_Martin_Guy's topic in Modder Support
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. -
Developing in multiple different versions of Forge [Solved]
SerpentDagger replied to SerpentDagger's topic in Modder Support
I was going to make a tweak in a 1.12.2 mod. (The graphing calculator linked to in my signature.) 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! -
Developing in multiple different versions of Forge [Solved]
SerpentDagger replied to SerpentDagger's topic in Modder Support
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). Indeed. I'm not asking for help in outdated versions, just trying to work with more than one at a time. 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. 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. -
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?
-
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
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). -
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
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. -
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
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). 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. -
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
Yup, that's about right. 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. -
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
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. -
[1.16.5] Changing the use duration of an item
SerpentDagger replied to Skelyvelocirap's topic in Modder Support
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. -
You should almost certainly use the Capability system for this purpose. Here is a link to its documentation.
-
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.
-
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.
-
Texture file not found (but no compile exception)
SerpentDagger replied to Nephty's topic in Modder Support
-
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. These strings do not refer to textures, they refer to models, as I mentioned in my previous post. BlockState → Model → Shape & Texture. 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. 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. 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).
-
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. 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. A 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.
-
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.
-
@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.
-
You're welcome! 🙂 I think that may also be fixable with a custom RenderType. They can specify layering, blending, masking, etc.
-
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:
-
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. 😕
-
EDIT: I'm wrong. 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.
-
That's a pretty nice way of doing it, thanks!