Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a event for modify player's movement during using item #4112

Open
wants to merge 14 commits into
base: 1.21.1
Choose a base branch
from

Conversation

fishshi
Copy link
Contributor

@fishshi fishshi commented Sep 22, 2024

Fixes #4103

Add a event for modify player's movement during using item.

The event ADJUST_USING_ITEM_SPEED is used to adjust a player's movement speed while using an item. It allows mods to modify the player's movement speed based on specific conditions when they are using a item.

When a player is moving while using an item, the movement speed can be modified based on various conditions. The return value is a float representing the speed adjustment percentage (e.g., 0.8 for 80% of the original speed). If it returns null, it means there is no speed adjustment. Among multiple speeds, the maximum value is taken.

The most common usecase is to modify using item speed based on main hand item, most for custom items. Another possible usecase is to modify using item speed when certain conditions (e.g. equipped items) are met.


public final class ClientPlayerEvents {
/**
* An event that is called when a player is moving during using an item.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Whats an example usecase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, a mod may wish to adjust or disable the slowdown when a player is using the mod's custom bow.

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

public final class ClientPlayerEvents {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Does this also need to be handled on the server somewhere? E.g if I wanted to increase the players speed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to make any changes on the server, as all information related to movement speed is processed on the client and sent to the server. We only need to modify the movement speed on the client. In the test mod, if you want to increase the player's speed, you only need to modify the multiplier coefficient. If you have any thoughts or additional comments, please let me know with more detailed information.

if (player.getMainHandStack().isOf(Items.BOW) && player.getEquippedStack(EquipmentSlot.FEET).isOf(Items.DIAMOND_BOOTS)) {
LOGGER.info("Player {} can move without slowdown becase of diamond boots on feet.", player);
player.input.movementForward *= 5F;
player.input.movementSideways *= 5F;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this PR, if you want to prevent slowdown, you multiply the move speed by 5? Uhhhhhhhhh

Have you considered what happens if two mods’s condition passes for trying to turn off the move speed? The two multiplying will end up causing the player to move 5 times as fast.

This PR is not suitable for multiple mods trying to turn off item use slowdown. It will need a rethinking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I will try as soon as possible. Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the event to DISABLE_USINGITEM_SLOWDOWN. When the return value is true, the player can move without being slowed down, which will also resolve the issue of multiple mods affecting this simultaneously.

@fishshi fishshi changed the title add MODIFY_PLAYER_MOVEMENT_DURING_USINGITEM MODIFY_PLAYER_MOVEMENT_DURING_USINGITEM Oct 19, 2024
@fishshi fishshi changed the title MODIFY_PLAYER_MOVEMENT_DURING_USINGITEM modify player movement during using item Oct 20, 2024
@fishshi
Copy link
Contributor Author

fishshi commented Oct 22, 2024

Description:
In event ADJUST_USING_ITEM_SPEED, I am using a float in the range [0, 1] as the percentage of movement speed, where 0 means movement is prohibited and 1 means normal speed with no slowdown. Any return values outside this range are considered invalid. When multiple mods are in effect, the maximum speed will be taken.
Additionally, I have defined a USE_DEFAULT_SLOWDOWN_SPEED flag for mods, indicating that no modifications are needed. This return value will not be compared with the return values of other mods, which helps mitigate conflicts. Mods only need to return their desired slowdown percentage in special cases; otherwise, they can return USE_DEFAULT_SLOWDOWN_SPEED.

for (AdjustUsingItemSpeed callback : callbacks) {
float currentSpeed = callback.adjustUsingItemSpeed(player);

if (currentSpeed >= 0.0F && currentSpeed <= 1.0F) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the speed capped at 1.0?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a similar note, why doesn't it accept speeds below zero? Is it just because of the -1.0F fallback or do negative values crash the game? If it's the former, consider allowing negative values after changing the fallback to @Nullable Float. If it's the latter, consider adding a comment to document why negative values would break stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this event is used to adjust the player's movement speed while using items, a value of 0 means the player's speed is already 0. A value of 1 means the player will maintain their original movement speed without any slowdown.
When the value is negative, it implies that the player will actually move backward when trying to move forward, which is counterintuitive. Therefore, negative values are not needed.
When the value is greater than 1, it can be understood as the player moving faster while using an item. I'm currently questioning whether this is even necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I find it perfectly intuitive that negative speed would move you backwards. Do we really ever know that this functionality will not be necessary for any current or future mod? It just seems like an artificial limit to me.

If it requires extra effort to make these values work, that would be a different story. But given that it seems to just work without the limit, I think we might as well remove the limit and give modders the flexibility to use crazy values if they want to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I understand, and I will remove this limit.

/*
* Flag for using default slowdown during using an item.
*/
public static final float USE_DEFAULT_SLOWDOWN_SPEED = -1.0F;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the return type of the interface to @Nullable Float instead of using this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed a good idea. Thank you!

float currentSpeed = callback.adjustUsingItemSpeed(player);

if (currentSpeed >= 0.0F && currentSpeed <= 1.0F) {
maxSpeed = currentSpeed > maxSpeed ? currentSpeed : maxSpeed;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use Math.max

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I’ve made the changes.

@Mixin(ClientPlayerEntity.class)
abstract class ClientPlayerMixin {
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z"))
private void beforeTickMovement(CallbackInfo ci) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private void beforeTickMovement(CallbackInfo ci) {
private void invokeAdjustUsingItemSpeedEvent(CallbackInfo ci) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I’ve made the changes.

@Alexander01998
Copy link
Contributor

What do you think about naming it ITEM_USE instead of USING_ITEM? It's a few characters shorter and (to me) it seems a bit easier to read.

@fishshi
Copy link
Contributor Author

fishshi commented Oct 22, 2024

What do you think about naming it ITEM_USE instead of USING_ITEM? It's a few characters shorter and (to me) it seems a bit easier to read.

Sorry, my English level is not very high, so I can't be sure which name is better. Can anyone else provide a bit more advice?

@fishshi fishshi changed the title modify player movement during using item Add a event for modify player's movement during using item Oct 27, 2024
@Earthcomputer
Copy link
Contributor

I'm reading MODIFY_USING_ITEM_SPEED as "modify using-item speed" where "using-item" is a modifier to "speed". When using verbs to modify nouns like this, normally what you're actually using is the gerund, i.e. "using" here is a noun, not a verb. The "item" here is the object of the action of "using", but (experts correct me if I'm wrong) gerunds cannot directly have objects in the same way as verbs. Instead we often use the possessive ("a using of an item" or "an item's using"), or use the object as a noun modifier like an adjective ("an item using"). Hence what I think is more grammatical here is "modify item-using speed". However as a native speaker this still feels weird to me, and I think it's because for the specific case of the verb "use", we have a better-suited noun "use" than the gerund "using". Which takes us to "modify item-use speed" ("use" here is a noun).

@fishshi
Copy link
Contributor Author

fishshi commented Nov 8, 2024

Thank you all! I have already renamed the event to MODIFY_ITEM_USE_SPEED.


public final class ClientPlayerEvents {
/**
* An event that is called when a player is moving during using an item.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* An event that is called when a player is moving during using an item.
* An event that is called when a player is moving while using an item.

@Earthcomputer
Copy link
Contributor

From the discussion on Discord. My last message in favour of MODIFY_ITEM_USE_SPEED was based on the mistaken assumption that this event was about how fast you can use an item, rather than modifying the entity's movement who is using the item. In that case, I'd recommend MODIFY_ITEM_USE_MOVEMENT_SPEED, which is consistent with the vanilla movement_speed attribute. It's not perfect because it doesn't directly refer to the entity in question but I can't think of a way to do that without making it something like MODIFY_ITEM_USE_ENTITY_MOVEMENT_SPEED which IMO is just too long. At least "movement" distinguishes it from the speed of an item use.

fishshi and others added 2 commits November 9, 2024 11:59
Co-authored-by: Alexander01998 <contact.wurstimperium@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants