diff --git a/gradle.properties b/gradle.properties index 14c41bd3..950040b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ org.gradle.daemon=false modmenu_version=7.0.0-beta.2 minelp_version=4.10.4+1.20.1 kirin_version=1.15.4+1.20 - reach_attributes_version=2.3.3 + reach_attributes_version=2.3.4 trinkets_version=3.7.1 terraformer_api_version=7.0.0-beta.1 diff --git a/lib/reach-entity-attributes-2.3.3.jar b/lib/reach-entity-attributes-2.3.3.jar deleted file mode 100644 index 40ddce21..00000000 Binary files a/lib/reach-entity-attributes-2.3.3.jar and /dev/null differ diff --git a/lib/reach-entity-attributes-2.3.4.jar b/lib/reach-entity-attributes-2.3.4.jar new file mode 100644 index 00000000..f8e834ae Binary files /dev/null and b/lib/reach-entity-attributes-2.3.4.jar differ diff --git a/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java b/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java index df5394d9..8f33d14a 100644 --- a/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java +++ b/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java @@ -38,6 +38,9 @@ public class UnicopiaMixinPlugin implements IMixinConfigPlugin { if (mixinClassName.indexOf("minelp") != -1) { return FabricLoader.getInstance().isModLoaded("minelp"); } + if (mixinClassName.indexOf("forgified") != -1) { + return FabricLoader.getInstance().isModLoaded("connectormod"); + } } return true; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java b/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java index 9bad7931..d2d65f3e 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java @@ -17,7 +17,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.EntityView; public class EntityCollisions { @@ -40,7 +40,7 @@ public class EntityCollisions { } } - public static List getColissonShapes(@Nullable Entity entity, WorldAccess world, Box box) { + public static List getColissonShapes(@Nullable Entity entity, EntityView world, Box box) { ShapeContext ctx = entity == null ? ShapeContext.absent() : ShapeContext.of(entity); return collectCollisionBoxes(box, collector -> { world.getOtherEntities(entity, box.expand(50), e -> { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index fab87347..181fd53d 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -28,6 +28,7 @@ import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; import com.minelittlepony.unicopia.item.FriendshipBraceletItem; import com.minelittlepony.unicopia.item.UItems; +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.util.*; import com.minelittlepony.unicopia.network.*; @@ -39,7 +40,6 @@ import com.minelittlepony.common.util.animation.Interpolator; import com.mojang.authlib.GameProfile; import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.*; import net.minecraft.entity.attribute.DefaultAttributeContainer; @@ -919,7 +919,7 @@ public class Pony extends Living implements Copyable, Update PlayerInventory inventory = oldPlayer.asEntity().getInventory(); for (int i = 0; i < inventory.size(); i++) { ItemStack stack = inventory.getStack(i); - if (EnchantmentHelper.getLevel(UEnchantments.HEART_BOUND, stack) > 0) { + if (EnchantmentUtil.consumeEnchantment(UEnchantments.HEART_BOUND, 1, stack, entity.getWorld().random, EnchantmentUtil.getLuck(3, oldPlayer.asEntity()))) { asEntity().getInventory().setStack(i, stack); } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java index 5bc6d8f2..f518d5d3 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java @@ -16,6 +16,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.random.Random; public interface EnchantmentUtil { + String HEART_BOUND_CONSUMED_FLAG = "unicopia:heart_bound_consumed"; static boolean consumeEnchantment(Enchantment enchantment, int levels, ItemStack stack) { return consumeEnchantment(enchantment, levels, stack, null, 0); @@ -33,7 +34,7 @@ public interface EnchantmentUtil { if (level == 0) { enchantments.remove(enchantment); } else { - enchantments.put(enchantment, level - 1); + enchantments.put(enchantment, level); } EnchantmentHelper.set(enchantments, stack); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/HeartboundEnchantmentUtil.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/HeartboundEnchantmentUtil.java new file mode 100644 index 00000000..b27dd3ad --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/HeartboundEnchantmentUtil.java @@ -0,0 +1,51 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import java.util.List; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.ItemStack; +import net.minecraft.util.collection.DefaultedList; + +public interface HeartboundEnchantmentUtil { + static InventorySnapshot createSnapshot(List> combinedInventory) { + List> storedCombinedInventory = combinedInventory.stream().map(l -> DefaultedList.ofSize(l.size(), ItemStack.EMPTY)).toList(); + boolean empty = true; + for (int group = 0; group < combinedInventory.size(); group++) { + var original = combinedInventory.get(group); + for (int i = 0; i < original.size(); i++) { + ItemStack stack = original.get(i); + if (EnchantmentHelper.getLevel(Enchantments.BINDING_CURSE, stack) == 0 + && EnchantmentHelper.getLevel(UEnchantments.HEART_BOUND, stack) > 0) { + original.set(i, ItemStack.EMPTY); + storedCombinedInventory.get(group).set(i, stack); + empty = false; + } + } + } + return empty ? InventorySnapshot.EMPTY : new InventorySnapshot(storedCombinedInventory); + } + + public record InventorySnapshot(List> combinedInventory) { + public static InventorySnapshot EMPTY = new InventorySnapshot(List.of()); + + public boolean empty() { + return combinedInventory.isEmpty(); + } + + public void restoreInto(List> combinedInventory) { + if (empty()) { + return; + } + for (int group = 0; group < combinedInventory.size(); group++) { + var original = combinedInventory.get(group); + for (int i = 0; i < original.size(); i++) { + ItemStack stored = this.combinedInventory.get(group).get(i); + if (!stored.isEmpty()) { + original.set(i, stored); + } + } + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java index 3414e340..559e9406 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java @@ -30,12 +30,12 @@ public interface UEnchantments { /** * Protects against wall collisions and earth pony attacks! */ - Enchantment PADDED = register("padded", new SimpleEnchantment(Options.armor().rarity(Rarity.COMMON).maxLevel(3))); + Enchantment PADDED = register("padded", new SimpleEnchantment(Options.armor().rarity(Rarity.UNCOMMON).maxLevel(3))); /** * Heavy players move more slowly but are less likely to be flung around wildly. */ - Enchantment HEAVY = register("heavy", new AttributedEnchantment(Options.armor().rarity(Rarity.COMMON).maxLevel(4))) + Enchantment HEAVY = register("heavy", new AttributedEnchantment(Options.armor().rarity(Rarity.UNCOMMON).maxLevel(4))) .addModifier(EntityAttributes.GENERIC_MOVEMENT_SPEED, (user, level) -> { return new EntityAttributeModifier(UUID.fromString("a3d5a94f-4c40-48f6-a343-558502a13e10"), "Heavyness", (1 - level/(float)10) - 1, Operation.MULTIPLY_TOTAL); }); @@ -83,7 +83,7 @@ public interface UEnchantments { * Items with loyalty are kept after death. * Only works if they don't also have curse of binding. */ - Enchantment HEART_BOUND = register("heart_bound", new SimpleEnchantment(Options.create(EnchantmentTarget.VANISHABLE, UEnchantmentValidSlots.ANY).rarity(Rarity.COMMON).maxLevel(5))); + Enchantment HEART_BOUND = register("heart_bound", new SimpleEnchantment(Options.create(EnchantmentTarget.VANISHABLE, UEnchantmentValidSlots.ANY).rarity(Rarity.UNCOMMON).maxLevel(5))); /** * Consumes drops whilst mining and produces experience instead diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java index 392cf967..76ba1b29 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java @@ -31,7 +31,12 @@ abstract class MixinBoatEntity extends Entity implements LavaAffine { "fall", "canAddPassenger" }, - at = @At(value = "FIELD", target = "net/minecraft/registry/tag/FluidTags.WATER:Lnet/minecraft/registry/tag/TagKey;", opcode = Opcodes.GETSTATIC) + at = @At( + value = "FIELD", + target = "net/minecraft/registry/tag/FluidTags.WATER:Lnet/minecraft/registry/tag/TagKey;", + opcode = Opcodes.GETSTATIC + ), + require = 0 // Forge ) private TagKey redirectFluidTag() { return isLavaAffine() ? FluidTags.LAVA : FluidTags.WATER; diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java new file mode 100644 index 00000000..c2de6378 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java @@ -0,0 +1,32 @@ +package com.minelittlepony.unicopia.mixin; + +import java.util.List; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; +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; + +import com.minelittlepony.unicopia.entity.collision.EntityCollisions; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.EntityView; + +@Mixin(EntityView.class) +interface MixinEntityView { + @Inject(method = "getEntityCollisions(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Box;)Ljava/util/List;", at = @At("RETURN"), cancellable = true) + private void onGetEntityCollisions(@Nullable Entity entity, Box box, CallbackInfoReturnable> info) { + if (box.getAverageSideLength() < 1.0E-7D) { + return; + } + + List shapes = EntityCollisions.getColissonShapes(entity, (EntityView)this, box); + if (!shapes.isEmpty()) { + info.setReturnValue(Stream.concat(shapes.stream(), info.getReturnValue().stream()).toList()); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerInventory.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerInventory.java index 5debbac8..e2311fef 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerInventory.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerInventory.java @@ -11,11 +11,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.minelittlepony.unicopia.advancement.UCriteria; -import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; -import com.minelittlepony.unicopia.item.enchantment.UEnchantments; - -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.enchantment.Enchantments; +import com.minelittlepony.unicopia.item.enchantment.HeartboundEnchantmentUtil; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -31,37 +27,21 @@ abstract class MixinPlayerInventory implements Inventory, Nameable { private @Final List> combinedInventory; @Nullable - private List> storedCombinedInventory; + private HeartboundEnchantmentUtil.InventorySnapshot inventorySnapshot; @Inject(method = "dropAll()V", at = @At("HEAD")) public void beforeDropAll(CallbackInfo info) { - storedCombinedInventory = combinedInventory.stream().map(l -> DefaultedList.ofSize(l.size(), ItemStack.EMPTY)).toList(); - for (int group = 0; group < combinedInventory.size(); group++) { - var original = combinedInventory.get(group); - for (int i = 0; i < original.size(); i++) { - ItemStack stack = original.get(i); - if (EnchantmentHelper.getLevel(Enchantments.BINDING_CURSE, stack) == 0 - && EnchantmentUtil.consumeEnchantment(UEnchantments.HEART_BOUND, 1, stack, player.getWorld().random, EnchantmentUtil.getLuck(3, player))) { - original.set(i, ItemStack.EMPTY); - UCriteria.USE_SOULMATE.trigger(player); - storedCombinedInventory.get(group).set(i, stack); - } - } + inventorySnapshot = HeartboundEnchantmentUtil.createSnapshot(combinedInventory); + if (!inventorySnapshot.empty()) { + UCriteria.USE_SOULMATE.trigger(player); } } - @Inject(method = "dropAll()V", at = @At("TAIL")) + @Inject(method = "dropAll()V", at = @At("RETURN")) public void afterDropAll(CallbackInfo info) { - if (storedCombinedInventory != null) { - for (int group = 0; group < combinedInventory.size(); group++) { - var original = combinedInventory.get(group); - for (int i = 0; i < original.size(); i++) { - ItemStack stored = storedCombinedInventory.get(group).get(i); - if (!stored.isEmpty()) { - original.set(i, stored); - } - } - } + if (inventorySnapshot != null) { + inventorySnapshot.restoreInto(combinedInventory); + inventorySnapshot = null; } } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java index d3237ca4..eda9c5b4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -1,26 +1,17 @@ package com.minelittlepony.unicopia.mixin; -import java.util.List; import java.util.Stack; import java.util.function.Supplier; -import java.util.stream.Stream; - -import org.jetbrains.annotations.Nullable; - 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.CallbackInfoReturnable; -import com.minelittlepony.unicopia.entity.collision.EntityCollisions; import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; @@ -47,18 +38,6 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source return destructions.get(); } - @Override - public List getEntityCollisions(@Nullable Entity entity, Box box) { - if (box.getAverageSideLength() >= 1.0E-7D) { - List shapes = EntityCollisions.getColissonShapes(entity, this, box); - if (!shapes.isEmpty()) { - return Stream.concat(shapes.stream(), WorldAccess.super.getEntityCollisions(entity, box).stream()).toList(); - } - } - - return WorldAccess.super.getEntityCollisions(entity, box); - } - @ModifyVariable(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("HEAD")) private BlockPos modifyBlockPos(BlockPos pos) { pos = applyRotation(pos); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java b/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java new file mode 100644 index 00000000..dd7abfe8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java @@ -0,0 +1,54 @@ +package com.minelittlepony.unicopia.mixin.forgified; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.*; +import com.minelittlepony.unicopia.entity.duck.LavaAffine; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.registry.tag.FluidTags; + +@Pseudo +@Mixin(targets = "net.minecraftforge.common.extensions.IForgeBoat") +interface MixinIForgeBoat { + @ModifyVariable( + method = "canBoatInFluid(Lnet/minecraft/fluid/FluidState;)Z", + at = @At("HEAD"), + ordinal = 0, + argsOnly = true, + require = 0 + ) + private FluidState modifyFluidState(FluidState incoming) { + if (this instanceof LavaAffine a && a.isLavaAffine()) { + if (incoming.isIn(FluidTags.WATER)) { + return Fluids.LAVA.getDefaultState(); + } + if (incoming.isIn(FluidTags.LAVA)) { + return Fluids.WATER.getDefaultState(); + } + } + + return incoming; + } + @SuppressWarnings("deprecation") + @ModifyVariable( + method = "canBoatInFluid(Lnet/minecraft/fluid/Fluid;)Z", + at = @At("HEAD"), + ordinal = 0, + argsOnly = true, + require = 0 + ) + private Fluid modifyFluid(Fluid incoming) { + if (this instanceof LavaAffine a && a.isLavaAffine()) { + if (incoming.isIn(FluidTags.WATER)) { + return Fluids.LAVA; + } + if (incoming.isIn(FluidTags.LAVA)) { + return Fluids.WATER; + } + } + + return incoming; + } +} diff --git a/src/main/resources/data/unicopia/recipes/spells/mimic.json b/src/main/resources/data/unicopia/recipes/spells/mimic.json index eca1681a..546c0908 100644 --- a/src/main/resources/data/unicopia/recipes/spells/mimic.json +++ b/src/main/resources/data/unicopia/recipes/spells/mimic.json @@ -4,7 +4,9 @@ "traits": { "knowledge": 19, "life": 10, "chaos": 4 }, - "ingredients": [], + "ingredients": [ + { "item": "unicopia:gemstone", "spell": "unicopia:transformation" } + ], "result": { "item": "unicopia:gemstone", "spell": "unicopia:mimic" diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 81c55c34..549625a7 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -20,6 +20,7 @@ "MixinEnchantmentHelper", "MixinFallLocation", "MixinEntity", + "MixinEntityView", "MixinEntityShapeContext", "MixinFallingBlock", "MixinFallingBlockEntity", @@ -57,7 +58,8 @@ "trinkets.MixinTrinketInventory", "trinkets.MixinScreenHandler", "seasons.MixinFertilizableUtil", - "ad_astra.MixinOxygenUtils" + "ad_astra.MixinOxygenUtils", + "forgified.MixinIForgeBoat" ], "client": [ "client.MixinAnimalModel",