diff --git a/forge116/src/main/java/me/neovitalism/neomixins/NeoMixins.java b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java similarity index 66% rename from forge116/src/main/java/me/neovitalism/neomixins/NeoMixins.java rename to forge116/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java index c538654..44662fd 100644 --- a/forge116/src/main/java/me/neovitalism/neomixins/NeoMixins.java +++ b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java @@ -1,15 +1,15 @@ -package me.neovitalism.neomixins; +package me.neovitalism.pokeballdatastorage; import net.minecraftforge.fml.common.Mod; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@Mod("neomixins") -public class NeoMixins { +@Mod("pokeballdatastorage") +public class PokeballDataStorage { private static final Logger LOGGER = LogManager.getLogger(); - public NeoMixins() { + public PokeballDataStorage() { LOGGER.log(Level.INFO, "Loaded!"); } } diff --git a/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java new file mode 100644 index 0000000..55d9142 --- /dev/null +++ b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java @@ -0,0 +1,71 @@ +package me.neovitalism.pokeballdatastorage.mixins; + +import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBall; +import com.pixelmonmod.pixelmon.entities.pokeballs.EmptyPokeBallEntity; +import com.pixelmonmod.pixelmon.entities.pokeballs.PokeBallEntity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.UUID; + +@SuppressWarnings("UnusedMixin") +@Mixin(value = EmptyPokeBallEntity.class, remap = false) +public abstract class EmptyPokeBallEntityMixin extends PokeBallEntity { + public EmptyPokeBallEntityMixin(EntityType type, World world) { + super(type, world); + } + + @Redirect(method = "onHit", at = @At(value = "INVOKE", + target = "Lcom/pixelmonmod/pixelmon/api/pokemon/item/pokeball/PokeBall;getBallItem()Lnet/minecraft/item/ItemStack;"), + remap = true) + public ItemStack neoMixins$redirectBallItemOnHit(PokeBall instance) { + ItemStack item = this.getItemFromNBT(); + if(!item.isEmpty()) return item; + return instance.getBallItem(); + } + + @Inject(method = "onHit", at = @At(value = "INVOKE", + target = "Lcom/pixelmonmod/pixelmon/entities/pokeballs/EmptyPokeBallEntity;setPairedEntity(Lnet/minecraft/entity/Entity;)V"), + remap = true) + public void neoMixins$resetDropItem(RayTraceResult movingObjectPosition, CallbackInfo ci) { + if (this.getOwner() instanceof PlayerEntity) { + this.dropItem = !((PlayerEntity)this.getOwner()).isCreative(); + } else this.dropItem = true; + } + + @Redirect(method = "catchPokemon", at = @At(value = "INVOKE", + target = "Lcom/pixelmonmod/pixelmon/api/pokemon/item/pokeball/PokeBall;getBallItem()Lnet/minecraft/item/ItemStack;")) + public ItemStack neoMixins$redirectBallItemOnCatch(PokeBall instance) { + ItemStack item = this.getItemFromNBT(); + if(!item.isEmpty()) return item; + return instance.getBallItem(); + } + + @Override + public ItemStack[] getComponentItems() { + CompoundNBT itemNBT = this.getPersistentData().getCompound("item"); + if (itemNBT.getCompound("tag").getBoolean("Unbreakable")) return new ItemStack[]{ItemStack.of(itemNBT)}; + return super.getComponentItems(); + } + + @Override + public UUID getOwnerId() { + return this.thrower.getUUID(); + } + + @Unique + public ItemStack getItemFromNBT() { + CompoundNBT itemNBT = this.getPersistentData().getCompound("item"); + return ItemStack.of(itemNBT); + } +} diff --git a/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java new file mode 100644 index 0000000..93b39b5 --- /dev/null +++ b/forge116/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java @@ -0,0 +1,63 @@ +package me.neovitalism.pokeballdatastorage.mixins; + +import com.pixelmonmod.pixelmon.api.events.ThrowPokeballEvent; +import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBall; +import com.pixelmonmod.pixelmon.battles.controller.participants.PixelmonWrapper; +import com.pixelmonmod.pixelmon.entities.pokeballs.EmptyPokeBallEntity; +import com.pixelmonmod.pixelmon.entities.pokeballs.PokeBallEntity; +import com.pixelmonmod.pixelmon.items.PixelmonItem; +import com.pixelmonmod.pixelmon.items.PokeBallItem; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.world.World; +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.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.Optional; + +@SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "UnusedMixin", "OptionalGetWithoutIsPresent"}) +@Mixin(value = PokeBallItem.class, remap = false) +public abstract class PokeBallItemMixin extends PixelmonItem { + public PokeBallItemMixin(Properties properties) { + super(properties); + } + + @Inject(method = "use", at = @At(value = "INVOKE", target = + "Lnet/minecraft/world/World;addFreshEntity(Lnet/minecraft/entity/Entity;)Z"), + locals = LocalCapture.CAPTURE_FAILSOFT, remap = true, cancellable = true) + public void neoMixins$use(World world, PlayerEntity entityPlayer, Hand handIn, + CallbackInfoReturnable> cir, ItemStack itemStack, + Optional pokeBall) { + EmptyPokeBallEntity entity = new EmptyPokeBallEntity(world, entityPlayer, pokeBall.get(), !entityPlayer.isCreative()); + this.setBallInNBT(entity, itemStack); + world.addFreshEntity(entity); + if (!entityPlayer.isCreative()) { + itemStack.shrink(1); + entityPlayer.inventory.setChanged(); + } + cir.setReturnValue(new ActionResult<>(ActionResultType.SUCCESS, itemStack)); + } + + @Inject(method = "useFromBag", at = @At(value = "INVOKE", target = + "Lnet/minecraft/world/World;addFreshEntity(Lnet/minecraft/entity/Entity;)Z"), + locals = LocalCapture.CAPTURE_FAILSOFT) + public void neoMixins$useFromBag(PixelmonWrapper userWrapper, PixelmonWrapper targetWrapper, ItemStack stack, + CallbackInfoReturnable cir, PlayerEntity thrower, Optional pokeBall, + ThrowPokeballEvent throwPokeballEvent, World world, PokeBallEntity p) { + this.setBallInNBT((EmptyPokeBallEntity) p, stack); + } + + @Unique + private void setBallInNBT(EmptyPokeBallEntity entity, ItemStack ballItem) { + ItemStack clonedItem = ballItem.copy(); + clonedItem.setCount(1); + entity.getPersistentData().put("item", clonedItem.serializeNBT()); + } +} diff --git a/forge116/src/main/resources/mixins.neomixins.json b/forge116/src/main/resources/mixins.pokeballdatastorage.json similarity index 82% rename from forge116/src/main/resources/mixins.neomixins.json rename to forge116/src/main/resources/mixins.pokeballdatastorage.json index 09daee9..35b4071 100644 --- a/forge116/src/main/resources/mixins.neomixins.json +++ b/forge116/src/main/resources/mixins.pokeballdatastorage.json @@ -5,7 +5,8 @@ "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_8", "mixins": [ - + "EmptyPokeBallEntityMixin", + "PokeBallItemMixin" ], "injectors": { "defaultRequire": 1 diff --git a/forge120/build.gradle b/forge120/build.gradle index 9dea8b2..1c10b34 100644 --- a/forge120/build.gradle +++ b/forge120/build.gradle @@ -50,7 +50,7 @@ dependencies { implementation 'org.jetbrains:annotations:24.0.1' minecraft "net.minecraftforge:forge:1.20.2-48.0.30" - implementation fg.deobf('pixelmon:Pixelmon-1.20.2-9.2.8-server:9.2.8') + implementation fg.deobf('pixelmon:Pixelmon-1.20.2-9.2.9-server:9.2.9') annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' } diff --git a/forge120/src/main/java/me/neovitalism/neomixins/NeoMixins.java b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java similarity index 66% rename from forge120/src/main/java/me/neovitalism/neomixins/NeoMixins.java rename to forge120/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java index c538654..44662fd 100644 --- a/forge120/src/main/java/me/neovitalism/neomixins/NeoMixins.java +++ b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/PokeballDataStorage.java @@ -1,15 +1,15 @@ -package me.neovitalism.neomixins; +package me.neovitalism.pokeballdatastorage; import net.minecraftforge.fml.common.Mod; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@Mod("neomixins") -public class NeoMixins { +@Mod("pokeballdatastorage") +public class PokeballDataStorage { private static final Logger LOGGER = LogManager.getLogger(); - public NeoMixins() { + public PokeballDataStorage() { LOGGER.log(Level.INFO, "Loaded!"); } } diff --git a/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java new file mode 100644 index 0000000..4323cd1 --- /dev/null +++ b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/EmptyPokeBallEntityMixin.java @@ -0,0 +1,58 @@ +package me.neovitalism.pokeballdatastorage.mixins; + +import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBall; +import com.pixelmonmod.pixelmon.entities.pokeballs.EmptyPokeBallEntity; +import com.pixelmonmod.pixelmon.entities.pokeballs.PokeBallEntity; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +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.Redirect; + +import java.util.UUID; + +@SuppressWarnings("UnusedMixin") +@Mixin(value = EmptyPokeBallEntity.class, remap = false) +public abstract class EmptyPokeBallEntityMixin extends PokeBallEntity { + public EmptyPokeBallEntityMixin(EntityType type, Level world) { + super(type, world); + } + + @Redirect(method = "onHit", at = @At(value = "INVOKE", + target = "Lcom/pixelmonmod/pixelmon/api/pokemon/item/pokeball/PokeBall;getBallItem()Lnet/minecraft/world/item/ItemStack;"), + remap = true) + public ItemStack neoMixins$redirectBallItemOnHit(PokeBall instance) { + ItemStack item = this.getItemFromNBT(); + if(!item.isEmpty()) return item; + return instance.getBallItem(); + } + + @Redirect(method = "catchPokemon", at = @At(value = "INVOKE", + target = "Lcom/pixelmonmod/pixelmon/api/pokemon/item/pokeball/PokeBall;getBallItem()Lnet/minecraft/world/item/ItemStack;")) + public ItemStack neoMixins$redirectBallItemOnCatch(PokeBall instance) { + ItemStack item = this.getItemFromNBT(); + if(!item.isEmpty()) return item; + return instance.getBallItem(); + } + + @Override + public ItemStack[] getComponentItems() { + CompoundTag itemNBT = this.getPersistentData().getCompound("item"); + if (itemNBT.getCompound("tag").getBoolean("Unbreakable")) return new ItemStack[]{ItemStack.of(itemNBT)}; + return super.getComponentItems(); + } + + @Override + public UUID getOwnerId() { + return this.thrower.getUUID(); + } + + @Unique + public ItemStack getItemFromNBT() { + CompoundTag itemNBT = this.getPersistentData().getCompound("item"); + return ItemStack.of(itemNBT); + } +} diff --git a/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java new file mode 100644 index 0000000..102d9a1 --- /dev/null +++ b/forge120/src/main/java/me/neovitalism/pokeballdatastorage/mixins/PokeBallItemMixin.java @@ -0,0 +1,63 @@ +package me.neovitalism.pokeballdatastorage.mixins; + +import com.pixelmonmod.pixelmon.api.events.ThrowPokeballEvent; +import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBall; +import com.pixelmonmod.pixelmon.battles.controller.participants.PixelmonWrapper; +import com.pixelmonmod.pixelmon.entities.pokeballs.EmptyPokeBallEntity; +import com.pixelmonmod.pixelmon.entities.pokeballs.PokeBallEntity; +import com.pixelmonmod.pixelmon.items.PixelmonItem; +import com.pixelmonmod.pixelmon.items.PokeBallItem; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +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.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.Optional; + +@SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "UnusedMixin", "OptionalGetWithoutIsPresent"}) +@Mixin(value = PokeBallItem.class, remap = false) +public abstract class PokeBallItemMixin extends PixelmonItem { + public PokeBallItemMixin(Properties properties) { + super(properties); + } + + @Inject(method = "use", at = @At(value = "INVOKE", target = + "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + locals = LocalCapture.CAPTURE_FAILSOFT, remap = true, cancellable = true) + public void neoMixins$use(Level world, Player entityPlayer, InteractionHand handIn, + CallbackInfoReturnable> cir, ItemStack itemStack, + Optional pokeBall) { + EmptyPokeBallEntity entity = new EmptyPokeBallEntity(world, entityPlayer, pokeBall.get(), !entityPlayer.isCreative()); + this.setBallInNBT(entity, itemStack); + world.addFreshEntity(entity); + if (!entityPlayer.isCreative()) { + itemStack.shrink(1); + entityPlayer.getInventory().setChanged(); + } + cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, itemStack)); + } + + @Inject(method = "useFromBag", at = @At(value = "INVOKE", target = + "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + locals = LocalCapture.CAPTURE_FAILSOFT) + public void neoMixins$useFromBag(PixelmonWrapper userWrapper, PixelmonWrapper targetWrapper, ItemStack stack, + CallbackInfoReturnable cir, Player thrower, Optional pokeBall, + ThrowPokeballEvent throwPokeballEvent, Level world, PokeBallEntity p) { + this.setBallInNBT((EmptyPokeBallEntity) p, stack); + } + + @Unique + private void setBallInNBT(EmptyPokeBallEntity entity, ItemStack ballItem) { + ItemStack clonedItem = ballItem.copy(); + clonedItem.setCount(1); + entity.getPersistentData().put("item", clonedItem.serializeNBT()); + } +} diff --git a/forge120/src/main/resources/mixins.neomixins.json b/forge120/src/main/resources/mixins.pokeballdatastorage.json similarity index 82% rename from forge120/src/main/resources/mixins.neomixins.json rename to forge120/src/main/resources/mixins.pokeballdatastorage.json index 0af23d8..ab598ef 100644 --- a/forge120/src/main/resources/mixins.neomixins.json +++ b/forge120/src/main/resources/mixins.pokeballdatastorage.json @@ -5,7 +5,8 @@ "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_17", "mixins": [ - + "EmptyPokeBallEntityMixin", + "PokeBallItemMixin" ], "injectors": { "defaultRequire": 1 diff --git a/gradle.properties b/gradle.properties index 707b506..444329d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ mod_version = 1.0.0 -mod_id = neomixins -mod_name = NeoMixins -mod_description = Mixins for use with Pixelmon -github_page = https://github.com/Neovitalism/NeoMixins \ No newline at end of file +mod_id = pokeballdatastorage +mod_name = PokeballDataStorage +mod_description = Caches the pokeball thrown onto the EmptyPokeballEntity. +github_page = https://github.com/Neovitalism/NeoMixins/tree/pokeball-data-storage \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 8a8e3e2..0214bb1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -rootProject.name = 'NeoMixins' +rootProject.name = 'PokeballDataStorage' include 'forge116' include 'forge120'