- 1,870
- 52
- 357
И получить огромную просадку производительностиИзThread.currentThread().getStackTrace()
определить
И получить огромную просадку производительностиИзThread.currentThread().getStackTrace()
определить
Есть одна чутка более интересная штукаМожно сделать следующий дикий костыль:
ИзThread.currentThread().getStackTrace()
определить, кто вызываетtargetMethod
И возвращать свое значение только если вызывающийsomeMethod
Курс Java Syntax - Лекция: StackTrace
«Первый зашел, последний вышел» — так организован стек. Правило StackTrace в Java гласит: функция, вызванная последней, должна завершиться самой первой. То есть, если функция А вызвала функцию Б, а та вызвала функцию В, а та, в свою очередь, функцию Г, тогда чтобы выйти из функции Б, нужно...javarush.ru
jdk.internal.reflect.Reflection#getCallerClass()
Но, как я понял, реализовать это сложнее, чем в итоге сделал я. В моем варианте мы просто вставляем новое присваивание с хуком сразу после целевого, т.е.:Ааа, это цель для якоря.
Типо есть
player.inventory.currentItem = x;
А применение хука делает
player.inventory.currentItem = hook(other, arguments... , x);
public int targetVar() default -1;
public Type getHookMethodReturnType() {
return hookMethodReturnType;
}
public int getAnchorTargetVar() {
return (int) anchor.get("targetVar");
}
private Type varType;
varType = hook.getHookMethodReturnType();
@Override
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var);
if(hook.getAnchorPoint() == VAR_ASSIGNMENT && opcode == varType.getOpcode(54) && var == hook.getAnchorTargetVar()) {
if(visitOrderedHook()) {
super.visitVarInsn(opcode, var);
}
}
}
public void fall(float distance, float damageMultiplier)
{
float[] ret = net.minecraftforge.common.ForgeHooks.onLivingFall(this, distance, damageMultiplier);
if (ret == null) return;
distance = ret[0]; damageMultiplier = ret[1];
super.fall(distance, damageMultiplier);
PotionEffect potioneffect = this.getActivePotionEffect(MobEffects.JUMP_BOOST);
float f = potioneffect == null ? 0.0F : (float)(potioneffect.getAmplifier() + 1);
int i = MathHelper.ceil((distance - 3.0F - f) * damageMultiplier);
if (i > 0)
{
this.playSound(this.getFallSound(i), 1.0F, 1.0F);
this.attackEntityFrom(DamageSource.FALL, (float)i);
int j = MathHelper.floor(this.posX);
int k = MathHelper.floor(this.posY - 0.20000000298023224D);
int l = MathHelper.floor(this.posZ);
IBlockState iblockstate = this.world.getBlockState(new BlockPos(j, k, l));
if (iblockstate.getMaterial() != Material.AIR)
{
SoundType soundtype = iblockstate.getBlock().getSoundType(iblockstate, world, new BlockPos(j, k, l), this);
this.playSound(soundtype.getFallSound(), soundtype.getVolume() * 0.5F, soundtype.getPitch() * 0.75F);
}
}
}
int i = MathHelper.ceil((distance - 3.0F - f) * damageMultiplier);
@Hook(at = @At(point = InjectionPoint.VAR_ASSIGNMENT, targetVar = 6, ordinal = 0))
public static int fall(EntityLivingBase entity, float distance, float damageMultiplier, @Hook.LocalVariable(6) int var) {
System.out.println("previous value = " + var);
return MathHelper.ceil(var / 2) + 1;
}
Кроме аннотации @ReturnValue есть аналогичная @LocalVariable(номер_переменной). Названия переменных в коде могут не сохраняться, так что вот так вот. Чтобы узнать номер, рекомендую использовать методы в классе VariableIdHelper.