Item Throwing
hammy275 opened this issue ยท 11 comments
See this thread on the ImmersiveMC Discord: https://discord.com/channels/1061675558347489343/1065409551324684288
For where I'm currently stuck, here are some ideas:
- Test for the existence of one of the Data Holder classes to see if we're using Mixin Vivecraft or Optifine Vivecraft.
- In Mixin Vivecraft land, we'll have two options to work with:
- Before ModifyVariable PR: We can detect the old Mixin using a Mixin config plugin. If we find it, we WON'T inject it, and instead inject our own copy with our modifications on top.
- After ModifyVariable PR: We can modify the variables later in the
shootFromRotation
, or do something similar to the Before PR and replace theModifyVariable
s with our own. Ideally if it exists, we can put ourModifyVariable
after Vivecraft's
- For Optifine Vivecraft, we'll need to figure out where to Mixin
ModifyVariable
calls, and modify from there
Entire pivot:
Instead of trying to override shootFromRotation
as a whole (since MIxin config plugins can't affect other mods, it seems), instead, we can take advantage of @Redirect
. For each individual item, whenever it calls shootFromRotation
from its use
method (or the other for Tridents), we call our own entire shoot method instead. If we personally don't run, pass control over to the normal shootFromRotation
instead.
Part 1 of this is at 9df5660 .
Things left to do:
- Fine tune throwing velocities, especially for trident.
- Use very hack-y mixins to render the Trident properly (see https://github.com/ferriarnus/VivecraftMod/blob/Multiloader-1.18/common/src/main/java/org/vivecraft/mixin/client/renderer/ItemInHandRendererVRMixin.java and https://github.com/ferriarnus/VivecraftMod/blob/d09c2512b91bc0eb747d25a22dbc402c41e0f7e3/common/src/main/java/org/vivecraft/render/VivecraftItemRendering.java#L151 ). We'll probably need to mixin just before Vivecraft kicks in item in hand rendering, set some boolean, then for item using check that boolean, and if it's true, return some value to pretend we're using the item. After that rendering pass, set the boolean back to false to get normal values.
- Add fishing rod. Vivecraft already does some correction on it, so we'll probably just want to add the velocity and let Vivecraft itself handle the rod movement. Looks like at the very end we can just multiply the
deltaMovement
of it by our velocity factor. - Fix left click blocking. It seems the current implementation of it doesn't actually work. That said, we shouldn't block it for the first tick, since we need to be able to hit things with the Trident.
- Config entry. Should be something both the server and client are on-board with. No need to send the client's preference to the server though, the client can simply not pass a packet along if they don't want to throw
- Safeguarding and warning for those in Optifine Vivecraft (or a solution for those using it)
- Dedicated server testing
- Testing outside of VR, without Vivecraft, and without the API
- Port to other branches
Velocity tuning is done! Next is a config entry, then we can port to other versions!
Will only support primary hand throwing.
Looks like the way to do this is a mixin into Projectile#shootFromRotation
.
We'll want to average the velocity of the hand every tick for the past 3 ticks and use that as our throwing velocity. Might move this to server-side at some future point, but for now, I'll run this client side. On release, we send a packet to the server containing the velocity we should throw at.
From there, the server will call use
or releaseUsing
(depending on the item) after adding the player to a global HashMap
. Call it vrNextThrowData
or something, with keys being player names or UUIDs, and values being the velocity from the packet.
In our Mixin, we check if the player is part of the aforementioned HashMap
. If so, we use their hand's rotation. Additionally, at the end of shootFromRotation
, we check again if they're in the HashMap
. If so, we remove them from the map, and use the provided velocity to augment the delta movement of the projectile. This augmentation I'll have to experiment with until I find something that "feels right".
Based on https://minecraft-archive.fandom.com/wiki/Category:Projectiles , we'll support the following items:
- Bottle o' Enchanting
- Egg
- Ender Pearl
- Potions (Splash/Lingering)
- Snowballs
- Tridents
Notable exceptions:
- Eyes of Ender don't use
shootFromRotation
, and would just generally feel "weird" to throw due to how they travel in-game.
Also, since people may throw things in a variety of different ways, to determine the direction, we'll do the difference between the current controller pos and the last, then normalize it. To get it to a x and y rotation, we should be able to reverse the calculation done in Entity#calculateViewVector
. Note that the constant being multiplied there is pi/180.
EDIT: Also, for throwable items, we always cancel their left click action with the exception of the Trident, which we only cancel if we're not hovering over an Entity at melee range.
I don't even need to worry about not blocking it for the first tick; we run at the end of the game tick! :)