Skip to content

Commit

Permalink
Merge pull request #24 from valoeghese/master
Browse files Browse the repository at this point in the history
fuck fuck fuck fuck fuck
  • Loading branch information
valoeghese authored Oct 11, 2020
2 parents 501960d + 518592e commit e442c00
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 76 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.10.0+build.208

# Mod Properties
mod_version = 1.2.0
mod_version = 1.3.0
maven_group = io.github.fabriccommunity
archives_base_name = too-many-events

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.github.fabriccommunity.events.impl;

import io.github.fabriccommunity.events.world.ChickenTurnLeftCallback;
import net.minecraft.entity.passive.ChickenEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.MathHelper;

/**
* @author leocth
*/
public final class ChickenTurnLeftImpl {
private ChickenTurnLeftImpl() {

}

public static float hackChangeAngle(ChickenEntity entity, float headYaw, float targetYaw, float yawSpeed, ChickenTurnLeftCallback.TurnLeftType type) {
float f = MathHelper.subtractAngles(headYaw, targetYaw);
float g = MathHelper.clamp(f, -yawSpeed, yawSpeed);
float h = headYaw + g;
if (MathHelper.wrapDegrees(g) < 0f) {
ActionResult result = ChickenTurnLeftCallback.EVENT.invoker().onTurnLeft(entity, headYaw, targetYaw, yawSpeed, type);

if (result == ActionResult.FAIL) {
// trolololololo lololooooo lo lo loo loooo lo lo
h = headYaw - g;
}
}
return MathHelper.wrapDegrees(h);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.github.fabriccommunity.events.mixin.client;

import io.github.fabriccommunity.events.play.ClientPlayerInteractionEvents;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.ActionResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

/**
* @author leocth
*/
@Mixin(TextFieldWidget.class)
public class MixinTextFieldWidget {
@Inject(at = @At("HEAD"), method = "charTyped", cancellable = true)
public void charTyped(char chr, int keyCode, CallbackInfoReturnable<Boolean> cir) {
ActionResult result = ClientPlayerInteractionEvents.TYPE_LETTER.invoker().onType(chr, keyCode);
if (result == ActionResult.FAIL) {
cir.setReturnValue(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.github.fabriccommunity.events.mixin.world;

import io.github.fabriccommunity.events.impl.ChickenTurnLeftImpl;
import io.github.fabriccommunity.events.world.ChickenTurnLeftCallback;
import net.minecraft.entity.ai.control.LookControl;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.ChickenEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

/**
* @author leocth
*/
@Mixin(LookControl.class)
public abstract class MixinLookControl {

@Shadow abstract float changeAngle(float from, float to, float max);

@Redirect(
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ai/control/LookControl;changeAngle(FFF)F", ordinal = 0),
method = "tick"
)
private float redirectHeadChangeAngle(LookControl self, float headYaw, float targetYaw, float yawSpeed) {
return (entity instanceof ChickenEntity)
? ChickenTurnLeftImpl.hackChangeAngle((ChickenEntity) entity, headYaw, targetYaw, yawSpeed, ChickenTurnLeftCallback.TurnLeftType.HEAD)
: this.changeAngle(headYaw, targetYaw, yawSpeed);
}

@Redirect(
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ai/control/LookControl;changeAngle(FFF)F", ordinal = 1),
method = "tick"
)
private float redirectBodyChangeAngle(LookControl self, float headYaw, float targetYaw, float yawSpeed) {
return (entity instanceof ChickenEntity)
? ChickenTurnLeftImpl.hackChangeAngle((ChickenEntity) entity, headYaw, targetYaw, yawSpeed, ChickenTurnLeftCallback.TurnLeftType.BODY)
: this.changeAngle(headYaw, targetYaw, yawSpeed);
}

@Shadow @Final private MobEntity entity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.github.fabriccommunity.events.mixin.world;

import io.github.fabriccommunity.events.impl.ChickenTurnLeftImpl;
import io.github.fabriccommunity.events.world.ChickenTurnLeftCallback;
import net.minecraft.entity.ai.control.MoveControl;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.ChickenEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

/**
* @author leocth
*/
@Mixin(MoveControl.class)
public abstract class MixinMoveControl {

@Shadow abstract float changeAngle(float from, float to, float max);

@Redirect(
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ai/control/MoveControl;changeAngle(FFF)F", ordinal = 0),
method = "tick"
)
private float redirectBodyChangeAngle(MoveControl self, float headYaw, float targetYaw, float yawSpeed) {
return (entity instanceof ChickenEntity)
? ChickenTurnLeftImpl.hackChangeAngle((ChickenEntity) entity, headYaw, targetYaw, yawSpeed, ChickenTurnLeftCallback.TurnLeftType.BODY)
: this.changeAngle(headYaw, targetYaw, yawSpeed);
}

@Shadow @Final private MobEntity entity;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,71 +13,102 @@
*/
@Environment(EnvType.CLIENT)
public final class ClientPlayerInteractionEvents {
public static final Event<AttackKeyPress> ATTACK_KEY_PRESS = EventFactory.createArrayBacked(AttackKeyPress.class, listeners -> (player, hitResult) -> {
for (AttackKeyPress listener : listeners) {
ActionResult result = listener.onAttackKeyPress(player, hitResult);
public static final Event<AttackKeyPress> ATTACK_KEY_PRESS = EventFactory.createArrayBacked(AttackKeyPress.class, listeners -> (player, hitResult) -> {
for (AttackKeyPress listener : listeners) {
ActionResult result = listener.onAttackKeyPress(player, hitResult);

if (result != ActionResult.PASS) {
return result;
}
}
if (result != ActionResult.PASS) {
return result;
}
}

return ActionResult.PASS;
});
return ActionResult.PASS;
});

public static final Event<AttackKeyHold> ATTACK_KEY_HOLD = EventFactory.createArrayBacked(AttackKeyHold.class, listeners -> (player, hitResult) -> {
for (AttackKeyHold listener : listeners) {
ActionResult result = listener.onAttackKeyHold(player, hitResult);
public static final Event<AttackKeyHold> ATTACK_KEY_HOLD = EventFactory.createArrayBacked(AttackKeyHold.class, listeners -> (player, hitResult) -> {
for (AttackKeyHold listener : listeners) {
ActionResult result = listener.onAttackKeyHold(player, hitResult);

if (result != ActionResult.PASS) {
return result;
}
}
if (result != ActionResult.PASS) {
return result;
}
}

return ActionResult.PASS;
});
return ActionResult.PASS;
});

/**
* An event which runs when the player presses down the attack key (left mouse button by default) in-game.
* This event does NOT run when the player has a screen of any sort opened, and is called *before* AttackBlockEvent and AttackEntityEvent.
*
* @author leocth
*/
@FunctionalInterface
public interface AttackKeyPress {
/**
* @param player the attacking player.
* @param hitResult the result of the hit (miss/block/entity), might be null.
*
* @return
* <ul>
* <li>{@code SUCCESS} or {@code CONSUME} cancels further event processing and swings the player's arms.
* <li>{@code PASS} pass event handling on to further processing. If all listeners pass, vanilla behavior is executed instead.
* <li>{@code FAIL} cancels further event processing without swinging the player's arms.
* </ul>
*/
ActionResult onAttackKeyPress(ClientPlayerEntity player, /* @Nullable */ HitResult hitResult);
}
public static final Event<TypeLetter> TYPE_LETTER = EventFactory.createArrayBacked(TypeLetter.class, listeners -> (chr, keycode) -> {
for (TypeLetter listener : listeners) {
ActionResult result = listener.onType(chr, keycode);

/**
* An event which runs when the player holds down the attack key (left mouse button by default) in-game.
* This event does NOT run when the player has a screen of any sort opened.
*
* @author leocth
*/
@FunctionalInterface
public interface AttackKeyHold {
/**
* @param player the attacking player.
* @param hitResult the result of the hit (miss/block/entity), might be null.
*
* @return
* <ul>
* <li>{@code SUCCESS} or {@code CONSUME} cancels further event processing and swings the player's arms.
* <li>{@code PASS} pass event handling on to further processing. If all listeners pass, vanilla behavior is executed instead.
* <li>{@code FAIL} cancels further event processing without swinging the player's arms.
* </ul>
*/
ActionResult onAttackKeyHold(ClientPlayerEntity player, /* @Nullable */ HitResult hitResult);
}
if (result != ActionResult.PASS) {
return result;
}
}

return ActionResult.PASS;
});

/**
* An event which runs when the player presses down the attack key (left mouse button by default) in-game.
* This event does NOT run when the player has a screen of any sort opened, and is called *before* AttackBlockEvent and AttackEntityEvent.
*
* @author leocth
*/
@FunctionalInterface
public interface AttackKeyPress {
/**
* @param player the attacking player.
* @param hitResult the result of the hit (miss/block/entity), might be null.
*
* @return
* <ul>
* <li>{@code SUCCESS} or {@code CONSUME} cancels further event processing and swings the player's arms.
* <li>{@code PASS} pass event handling on to further processing. If all listeners pass, vanilla behavior is executed instead.
* <li>{@code FAIL} cancels further event processing without swinging the player's arms.
* </ul>
*/
ActionResult onAttackKeyPress(ClientPlayerEntity player, /* @Nullable */ HitResult hitResult);
}

/**
* An event which runs when the player holds down the attack key (left mouse button by default) in-game.
* This event does NOT run when the player has a screen of any sort opened.
*
* @author leocth
*/
@FunctionalInterface
public interface AttackKeyHold {
/**
* @param player the attacking player.
* @param hitResult the result of the hit (miss/block/entity), might be null.
*
* @return
* <ul>
* <li>{@code SUCCESS} or {@code CONSUME} cancels further event processing and swings the player's arms.
* <li>{@code PASS} pass event handling on to further processing. If all listeners pass, vanilla behavior is executed instead.
* <li>{@code FAIL} cancels further event processing without swinging the player's arms.
* </ul>
*/
ActionResult onAttackKeyHold(ClientPlayerEntity player, /* @Nullable */ HitResult hitResult);
}

/**
* An event which runs when the player types a letter in the chat text field.
* @author leocth
*/
@FunctionalInterface
public interface TypeLetter {
/**
* @param chr the character being typed
* @param keyCode the keycode being pressed
* @see org.lwjgl.glfw.GLFW for more info on key codes.
*
* @return
* {@code SUCCESS} or {@code CONSUME} cancels further event processing and the character is written into the text field.
* {@code PASS} pass event handling on to further processing. If all listeners pass, functions exactly the same as {@code SUCCESS} and {@code CONSUME}.
* {@code FAIL} cancels further event processing and disallows the character to be written into the text field.
*/
ActionResult onType(char chr, int keyCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.github.fabriccommunity.events.world;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.passive.ChickenEntity;
import net.minecraft.util.ActionResult;

/**
* You deserved this.
* @author leocth
*/
@FunctionalInterface
public interface ChickenTurnLeftCallback {
Event<ChickenTurnLeftCallback> EVENT = EventFactory.createArrayBacked(ChickenTurnLeftCallback.class, listeners -> (chicken, oldYaw, targetYaw, yawSpeed, type) -> {
for (ChickenTurnLeftCallback listener : listeners) {
ActionResult result = listener.onTurnLeft(chicken, oldYaw, targetYaw, yawSpeed, type);
if (result != ActionResult.PASS)
return result;
}
return ActionResult.PASS;
});

/**
* Called when a chicken ({@code ChickenEntity}) turns left.
*
* @param chicken the chicken in question
* @param oldYaw the chicken's previous head yaw
* @param targetYaw the chicken's target yaw (new yaw)
* @param yawSpeed the speed (limiter, to be exact) of the rotation.
* @param type the type of the turn (head, body)
*
* @return
* {@code SUCCESS} and {@code CONSUME} cancels further processing and allows the chicken to turn.
* {@code PASS} pass event handling on to further processing. If all listeners pass, functions exactly the same as {@code SUCCESS} and {@code CONSUME}.
* {@code FAIL} cancels further processing and forces the chicken to turn right by {@code |oldYaw - targetYaw|} instead.
*/
ActionResult onTurnLeft(ChickenEntity chicken, float oldYaw, float targetYaw, float yawSpeed, TurnLeftType type);

enum TurnLeftType {
HEAD, BODY
}
}
5 changes: 4 additions & 1 deletion src/main/resources/toomanyevents.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
"spawn.MixinMobSpawnerLogic",
"spawn.MixinSpawnHelper",
"spawn.MixinSummonCommand",
"world.MixinChunkGenerator"
"world.MixinChunkGenerator",
"world.MixinLookControl",
"world.MixinMoveControl"
],
"client": [
"client.MixinBackgroundRenderer",
"client.MixinMinecraftClient",
"client.MixinTextFieldWidget",
"client.MixinWorldRenderer"
],
"injectors": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.fabriccommunity.events.test;

import io.github.fabriccommunity.events.world.ChickenTurnLeftCallback;
import net.fabricmc.api.ModInitializer;
import net.minecraft.util.ActionResult;

/**
* @author leocth
*/
public class ChickenTurnLeftTest implements ModInitializer {
public static final boolean ENABLED = true;

@Override
public void onInitialize() {
if (ENABLED) {
ChickenTurnLeftCallback.EVENT.register((chicken, oldYaw, targetYaw, yawSpeed, type) -> {
if (type == ChickenTurnLeftCallback.TurnLeftType.HEAD) {
// disable this if you want to
System.out.println(chicken + " turned left by " + Math.abs(oldYaw - targetYaw) + "! Adjusting...");
return ActionResult.FAIL;
}
return ActionResult.PASS;
});
}
}
}
Loading

0 comments on commit e442c00

Please sign in to comment.