Skip to content

Commit

Permalink
Basic implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
naomieow committed Aug 8, 2024
1 parent fad78ec commit 7b0d657
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 2 deletions.
77 changes: 77 additions & 0 deletions src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.bibireden.playerex.mixin;

import com.bibireden.playerex.util.PlayerEXUtil;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.function.Consumer;

@Mixin(ItemStack.class)
abstract class ItemStackMixin {
@Shadow
public abstract boolean damage(int amount, Random random, @Nullable ServerPlayerEntity serverPlayer);

@Inject(method = "use(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/TypedActionResult;", at = @At(value = "HEAD"), cancellable = true)
public void preventUse(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> cir) {
ItemStack stack = (ItemStack)(Object)this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(TypedActionResult.fail(stack));
}
}

@Inject(method = "useOnBlock(Lnet/minecraft/item/ItemUsageContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "HEAD"), cancellable = true)
public void preventUseOnBlock(ItemUsageContext context, CallbackInfoReturnable<ActionResult> cir) {
ItemStack stack = (ItemStack)(Object)this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(ActionResult.FAIL);
}
}

@Inject(method = "damage(ILnet/minecraft/util/math/random/Random;Lnet/minecraft/server/network/ServerPlayerEntity;)Z", at = @At(value = "HEAD"), cancellable = true)
public void preventDamage(int amount, Random random, ServerPlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
ItemStack stack = (ItemStack)(Object)this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(true);
}
}

@Inject(method = "damage(ILnet/minecraft/entity/LivingEntity;Ljava/util/function/Consumer;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;"), cancellable = true)
public <T extends LivingEntity> void preventBreak(int amount, T entity, Consumer<T> onBroken, CallbackInfo ci) {
ItemStack stack = (ItemStack)(Object)this;
// TODO: If "unbreakable" item, maybe use a tag?
if (true) {
if (!PlayerEXUtil.isBroken(stack)) {
NbtCompound tag = stack.getNbt();
tag.putBoolean("broken", true);
stack.setNbt(tag);
}
ci.cancel();
}
}

@Inject(method = "setDamage(I)V", at = @At(value = "HEAD"))
public void removeBrokenOnRepair(int damage, CallbackInfo ci) {
ItemStack stack = (ItemStack)(Object)this;
if (PlayerEXUtil.isBroken(stack) && damage < stack.getDamage()) {
NbtCompound tag = stack.getNbt();
tag.putBoolean("broken", false);
stack.setNbt(tag);
}
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.bibireden.playerex.mixin;

import com.bibireden.playerex.api.event.LivingEntityEvents;
import com.bibireden.playerex.util.PlayerEXUtil;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.util.Hand;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin {
Expand All @@ -19,6 +22,14 @@ public abstract class LivingEntityMixin {
@Unique
private int playerex_ticks;

@Inject(method = "setCurrentHand(Lnet/minecraft/util/Hand;)V", at = @At(value = "HEAD"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
public void preventAttack(Hand hand, CallbackInfo ci) {
LivingEntity entity = (LivingEntity)(Object)this;
if (PlayerEXUtil.isBroken(entity.getStackInHand(hand))) {
ci.cancel();
}
}

@ModifyVariable(method = "heal", at = @At("HEAD"), argsOnly = true)
private float playerex$heal(float original) {
return LivingEntityEvents.ON_HEAL.invoker().onHeal((LivingEntity) (Object) this, original);
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/bibireden/playerex/mixin/PlayerEntityMixin.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,48 @@
package com.bibireden.playerex.mixin;

import com.bibireden.playerex.api.event.PlayerEntityEvents;
import com.bibireden.playerex.util.PlayerEXUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameMode;
import net.minecraft.world.World;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin {
@Inject(method = "attack(Lnet/minecraft/entity/Entity;)V", at = @At(value = "HEAD"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
public void preventAttack(Entity target, CallbackInfo ci) {
PlayerEntity entity = (PlayerEntity)(Object)this;
// TODO: BetterCombat compat
if (PlayerEXUtil.isBroken(entity.getMainHandStack())) {
ci.cancel();
}
}

@Inject(method = "interact(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;", at = @At(value = "HEAD"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
public void preventInteract(Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
PlayerEntity player = (PlayerEntity)(Object)this;
if (PlayerEXUtil.isBroken(player.getStackInHand(hand))) {
cir.setReturnValue(ActionResult.FAIL);
}
}

@Inject(method = "isBlockBreakingRestricted(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/GameMode;)Z", at = @At(value = "HEAD"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
public void preventBreakBlock(World world, BlockPos pos, GameMode gameMode, CallbackInfoReturnable<Boolean> cir) {
PlayerEntity player = (PlayerEntity)(Object)this;
if (PlayerEXUtil.isBroken(player.getMainHandStack())) {
cir.setReturnValue(true);
}
}

@ModifyVariable(method = "attack", at = @At("STORE"), name = "bl3", ordinal = 2)
private boolean playerex_attack(boolean bl3, Entity target) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public abstract class PlayerInventoryMixin {

@ModifyReturnValue(method = "getBlockBreakingSpeed", at = @At("RETURN"))
private float playerex$getBlockBreakingSpeed(float original) {
Optional<Double> maybeBreakingSpeed = DataAttributesAPI.INSTANCE.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player);
Optional<Double> maybeBreakingSpeed = DataAttributesAPI.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player);
return maybeBreakingSpeed.map(v -> original + v.floatValue() - 1.0F).orElse(original);
}
}
9 changes: 9 additions & 0 deletions src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.bibireden.data_attributes.api.util.Maths
import com.bibireden.playerex.PlayerEX
import com.bibireden.playerex.ext.level
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.objecthunter.exp4j.Expression
import net.objecthunter.exp4j.ExpressionBuilder
import net.objecthunter.exp4j.function.Function
Expand Down Expand Up @@ -46,4 +47,12 @@ object PlayerEXUtil {
/** todo: document, none evident on former, resolve if orElse is needed here, and if we can do nullable or not without drastically changing things */
@JvmStatic
fun getRequiredXpForNextLevel(player: PlayerEntity): Int = getRequiredXpForLevel(player, player.level + 1)

@JvmStatic
fun isBroken(stack: ItemStack): Boolean {
if (stack.nbt != null) {
return stack.nbt!!.getBoolean("broken")
}
return false;
}
}
2 changes: 2 additions & 0 deletions src/main/resources/assets/playerex/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
"attribute.name.playerex.smithing": "Smithing",
"attribute.name.playerex.farming": "Farming",

"playerex.broken": "Broken",

"playerex.command.reset_chunk": "Reset experience negation factor for chunk at %s",
"playerex.command.refund": "Refunded %s skill points for player %s",

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/playerex.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"PlayerEntityMixin",
"PlayerInventoryMixin",
"ServerPlayerEntityMixin",
"ServerWorldMixin"
"ServerWorldMixin",
"ItemStackMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 7b0d657

Please sign in to comment.