diff --git a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockEntityAbstractImpetus.java b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockEntityAbstractImpetus.java index 6b4b792b..56015bdd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockEntityAbstractImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockEntityAbstractImpetus.java @@ -116,7 +116,7 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen public void applyScryingLensOverlay(List> lines, BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, - Direction hitFace, InteractionHand lensHand) { + Direction hitFace) { if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { if (beai.getMana() < 0) { lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), ItemCreativeUnlocker.infiniteMedia(world))); @@ -533,6 +533,11 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen return false; } + @Override + public void clearContent() { + // NO-OP + } + @Override public boolean canPlaceItem(int index, ItemStack stack) { var manamount = extractManaFromItem(stack, true); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java b/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java index d5d95f20..6c111641 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java @@ -10,7 +10,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -18,7 +17,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; @@ -116,16 +114,16 @@ public final class ScryingLensOverlayRegistry { */ public static @NotNull List> getLines(BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, - Direction hitFace, @Nullable InteractionHand lensHand) { + Direction hitFace) { List> lines = Lists.newArrayList(); var idLookedup = ID_LOOKUP.get(IXplatAbstractions.INSTANCE.getID(state.getBlock())); if (idLookedup != null) { - idLookedup.addLines(lines, state, pos, observer, world, hitFace, lensHand); + idLookedup.addLines(lines, state, pos, observer, world, hitFace); } for (var pair : PREDICATE_LOOKUP) { - if (pair.getFirst().test(state, pos, observer, world, hitFace, lensHand)) { - pair.getSecond().addLines(lines, state, pos, observer, world, hitFace, lensHand); + if (pair.getFirst().test(state, pos, observer, world, hitFace)) { + pair.getSecond().addLines(lines, state, pos, observer, world, hitFace); } } @@ -142,7 +140,7 @@ public final class ScryingLensOverlayRegistry { void addLines(List> lines, BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, - Direction hitFace, @Nullable InteractionHand lensHand); + Direction hitFace); } /** @@ -152,6 +150,6 @@ public final class ScryingLensOverlayRegistry { public interface OverlayPredicate { boolean test(BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, - Direction hitFace, @Nullable InteractionHand lensHand); + Direction hitFace); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java b/Common/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java index f8aa0d5e..c7c70932 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java @@ -2,7 +2,7 @@ package at.petrak.hexcasting.client; import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry; import at.petrak.hexcasting.api.player.Sentinel; -import at.petrak.hexcasting.common.lib.HexItems; +import at.petrak.hexcasting.common.items.ItemLens; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.common.collect.Lists; import com.mojang.blaze3d.platform.GlStateManager; @@ -22,8 +22,6 @@ import net.minecraft.locale.Language; import net.minecraft.network.chat.FormattedText; import net.minecraft.network.chat.Style; import net.minecraft.util.Mth; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; @@ -157,22 +155,8 @@ public class HexAdditionalRenderers { return; } - boolean foundLens = false; - InteractionHand lensHand = null; - for (var hand : InteractionHand.values()) { - if (player.getItemInHand(hand).is(HexItems.SCRYING_LENS)) { - lensHand = hand; - foundLens = true; - break; - } - } - if (!foundLens && player.getItemBySlot(EquipmentSlot.HEAD).is(HexItems.SCRYING_LENS)) { - foundLens = true; - } - - if (!foundLens) { + if (!ItemLens.hasLensHUD(player)) return; - } var hitRes = mc.hitResult; if (hitRes != null && hitRes.getType() == HitResult.Type.BLOCK) { @@ -180,7 +164,7 @@ public class HexAdditionalRenderers { var pos = bhr.getBlockPos(); var bs = level.getBlockState(pos); - var lines = ScryingLensOverlayRegistry.getLines(bs, pos, player, level, bhr.getDirection(), lensHand); + var lines = ScryingLensOverlayRegistry.getLines(bs, pos, player, level, bhr.getDirection()); int totalHeight = 8; List>> actualLines = Lists.newArrayList(); diff --git a/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java b/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java index 0faac5ba..77f0ce01 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java @@ -109,15 +109,15 @@ public class RegisterClientStuff { private static void addScryingLensStuff() { ScryingLensOverlayRegistry.addPredicateDisplayer( - (state, pos, observer, world, direction, lensHand) -> state.getBlock() instanceof BlockAbstractImpetus, - (lines, state, pos, observer, world, direction, lensHand) -> { + (state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus, + (lines, state, pos, observer, world, direction) -> { if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { - beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction, lensHand); + beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction); } }); ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK, - (lines, state, pos, observer, world, direction, lensHand) -> { + (lines, state, pos, observer, world, direction) -> { int note = state.getValue(NoteBlock.NOTE); float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F); @@ -139,7 +139,7 @@ public class RegisterClientStuff { }); ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF, - (lines, state, pos, observer, world, direction, lensHand) -> { + (lines, state, pos, observer, world, direction) -> { if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) { var recordPos = tile.getRecordPos(); var pattern = tile.getPattern(); @@ -156,7 +156,7 @@ public class RegisterClientStuff { }); ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_RECORD, - (lines, state, pos, observer, world, direction, lensHand) -> { + (lines, state, pos, observer, world, direction) -> { if (world.getBlockEntity(pos) instanceof BlockEntityAkashicRecord tile) { int count = tile.getCount(); @@ -168,7 +168,7 @@ public class RegisterClientStuff { }); ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR, - (lines, state, pos, observer, world, direction, lensHand) -> { + (lines, state, pos, observer, world, direction) -> { int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true); lines.add(new Pair<>( new ItemStack(Items.REDSTONE), @@ -185,15 +185,15 @@ public class RegisterClientStuff { }); ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER, - (lines, state, pos, observer, world, direction, lensHand) -> lines.add(new Pair<>( + (lines, state, pos, observer, world, direction) -> lines.add(new Pair<>( new ItemStack(Items.CLOCK), new TextComponent(String.valueOf(state.getValue(RepeaterBlock.DELAY))) .withStyle(ChatFormatting.YELLOW)))); ScryingLensOverlayRegistry.addPredicateDisplayer( - (state, pos, observer, world, direction, lensHand) -> state.isSignalSource() && !state.is( + (state, pos, observer, world, direction) -> state.isSignalSource() && !state.is( Blocks.COMPARATOR), - (lines, state, pos, observer, world, direction, lensHand) -> { + (lines, state, pos, observer, world, direction) -> { int signalStrength = 0; if (state.getBlock() instanceof RedStoneWireBlock) { signalStrength = state.getValue(RedStoneWireBlock.POWER); @@ -210,8 +210,8 @@ public class RegisterClientStuff { }); ScryingLensOverlayRegistry.addPredicateDisplayer( - (state, pos, observer, world, direction, lensHand) -> state.hasAnalogOutputSignal(), - (lines, state, pos, observer, world, direction, lensHand) -> { + (state, pos, observer, world, direction) -> state.hasAnalogOutputSignal(), + (lines, state, pos, observer, world, direction) -> { int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false); lines.add( new Pair<>( diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityStoredPlayerImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityStoredPlayerImpetus.java index aef5bf48..44f05a1a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityStoredPlayerImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityStoredPlayerImpetus.java @@ -14,7 +14,6 @@ import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -82,8 +81,8 @@ public class BlockEntityStoredPlayerImpetus extends BlockEntityAbstractImpetus { public void applyScryingLensOverlay(List> lines, BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, - Direction hitFace, InteractionHand lensHand) { - super.applyScryingLensOverlay(lines, state, pos, observer, world, hitFace, lensHand); + Direction hitFace) { + super.applyScryingLensOverlay(lines, state, pos, observer, world, hitFace); var name = this.getPlayerName(); if (name != null) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java index 29aa56fe..3869e489 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java @@ -1,27 +1,24 @@ package at.petrak.hexcasting.common.items; import at.petrak.hexcasting.annotations.SoftImplement; +import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.network.MsgUpdateComparatorVisualsAck; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.mojang.datafixers.util.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockSource; import net.minecraft.core.dispenser.OptionalDispenseItemBehavior; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Wearable; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -30,11 +27,34 @@ import net.minecraft.world.phys.HitResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; +import java.util.function.Predicate; public class ItemLens extends Item implements Wearable { + private static final List> HAS_HUD_PREDICATE = new ArrayList<>(); + static { + addLensHUDPredicate(player -> player.getItemBySlot(EquipmentSlot.MAINHAND).is(HexItems.SCRYING_LENS)); + addLensHUDPredicate(player -> player.getItemBySlot(EquipmentSlot.OFFHAND).is(HexItems.SCRYING_LENS)); + addLensHUDPredicate(player -> player.getItemBySlot(EquipmentSlot.HEAD).is(HexItems.SCRYING_LENS)); + } + + public static boolean hasLensHUD(Player player) { + for (Predicate predicate : HAS_HUD_PREDICATE) { + if (predicate.test(player)) { + return true; + } + } + return false; + } + + public static void addLensHUDPredicate(Predicate predicate) { + HAS_HUD_PREDICATE.add(predicate); + } + public ItemLens(Properties pProperties) { super(pProperties); DispenserBlock.registerBehavior(this, new OptionalDispenseItemBehavior() { @@ -53,38 +73,21 @@ public class ItemLens extends Item implements Wearable { return EquipmentSlot.HEAD; } - @Override - public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { - ItemStack itemstack = player.getItemInHand(hand); - EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); - ItemStack stack = player.getItemBySlot(equipmentslot); - if (stack.isEmpty()) { - player.setItemSlot(equipmentslot, itemstack.copy()); - if (!world.isClientSide()) { - player.awardStat(Stats.ITEM_USED.get(this)); - } - - itemstack.setCount(0); - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } else { - return InteractionResultHolder.fail(itemstack); + public static void tickAllPlayers(ServerLevel world) { + for (ServerPlayer player : world.players()) { + tickLens(player); } } - @Override - public void inventoryTick(ItemStack pStack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) { - if (!pLevel.isClientSide() && pEntity instanceof ServerPlayer player) { - if (pStack == player.getItemBySlot(EquipmentSlot.HEAD) || - pStack == player.getItemBySlot(EquipmentSlot.MAINHAND) || - pStack == player.getItemBySlot(EquipmentSlot.OFFHAND)) { - sendComparatorDataToClient(player); - } + public static void tickLens(Entity pEntity) { + if (!pEntity.getLevel().isClientSide() && pEntity instanceof ServerPlayer player && hasLensHUD(player)) { + sendComparatorDataToClient(player); } } private static final Map> comparatorDataMap = new WeakHashMap<>(); - private void sendComparatorDataToClient(ServerPlayer player) { + private static void sendComparatorDataToClient(ServerPlayer player) { double reachAttribute = IXplatAbstractions.INSTANCE.getReachDistance(player); double distance = player.isCreative() ? reachAttribute : reachAttribute - 0.5; var hitResult = player.pick(distance, 0, false); @@ -104,7 +107,7 @@ public class ItemLens extends Item implements Wearable { } } - private void syncComparatorValue(ServerPlayer player, BlockPos pos, int value) { + private static void syncComparatorValue(ServerPlayer player, BlockPos pos, int value) { var previous = comparatorDataMap.get(player); if (value == -1) { if (previous != null) { diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java b/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java index 4377a363..53cd3094 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.interop; import at.petrak.hexcasting.interop.pehkui.PehkuiInterop; +import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.Platform; import vazkii.patchouli.api.PatchouliAPI; @@ -13,10 +14,12 @@ public class HexInterop { public static final String PEHKUI_ID = "pehkui"; public static final class Forge { + public static final String CURIOS_API_ID = "curios"; } public static final class Fabric { public static final String GRAVITY_CHANGER_API_ID = "gravitychanger"; + public static final String TRINKETS_API_ID = "trinkets"; } public static void init() { @@ -30,6 +33,10 @@ public class HexInterop { xplat.initPlatformSpecific(); } + public static void clientInit() { + IClientXplatAbstractions.INSTANCE.initPlatformSpecific(); + } + private static void initPatchouli() { var integrations = List.of(PEHKUI_ID); diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java b/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java index b849e5b8..7b9b1326 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java @@ -27,6 +27,8 @@ public interface IClientXplatAbstractions { void setRenderLayer(Block block, RenderType type); + void initPlatformSpecific(); + void registerEntityRenderer(EntityType type, EntityRendererProvider renderer); void registerParticleType(ParticleType type, diff --git a/Fabric/build.gradle b/Fabric/build.gradle index 0dbdf09c..0f60e4e1 100644 --- a/Fabric/build.gradle +++ b/Fabric/build.gradle @@ -85,6 +85,7 @@ dependencies { exclude(group: "net.fabricmc.fabric-api") } + modImplementation "dev.emi:trinkets:$trinketsVersion" modImplementation "dev.emi:emi:${emiVersion}" modImplementation "maven.modrinth:gravity-api:$gravityApiVersion" diff --git a/Fabric/gradle.properties b/Fabric/gradle.properties index 8912af00..82438c20 100644 --- a/Fabric/gradle.properties +++ b/Fabric/gradle.properties @@ -10,3 +10,4 @@ reiVersion=8.0.442 emiVersion=0.1.0+1.18.2 gravityApiVersion=0.7.7+fabric clothConfigVersion=6.1.48 +trinketsVersion=3.3.1 diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt index ac58d762..8a3859b6 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt @@ -6,6 +6,7 @@ import at.petrak.hexcasting.client.RegisterClientStuff import at.petrak.hexcasting.client.ShiftScrollListener import at.petrak.hexcasting.fabric.event.MouseScrollCallback import at.petrak.hexcasting.fabric.network.FabricPacketHandler +import at.petrak.hexcasting.interop.HexInterop import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry @@ -50,5 +51,7 @@ object FabricHexClientInitializer : ClientModInitializer { BlockEntityRendererRegistry.register(type, berp) } }) + + HexInterop.clientInit() } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt index 479fb8b8..bdf941af 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt @@ -9,6 +9,7 @@ import at.petrak.hexcasting.common.casting.RegisterPatterns import at.petrak.hexcasting.common.command.PatternResLocArgument import at.petrak.hexcasting.common.entities.HexEntities import at.petrak.hexcasting.common.items.ItemJewelerHammer +import at.petrak.hexcasting.common.items.ItemLens import at.petrak.hexcasting.common.lib.* import at.petrak.hexcasting.common.loot.HexLootHandler import at.petrak.hexcasting.common.misc.Brainsweeping @@ -72,6 +73,7 @@ object FabricHexInitializer : ModInitializer { } ServerTickEvents.END_WORLD_TICK.register(PlayerPositionRecorder::updateAllPlayers) + ServerTickEvents.END_WORLD_TICK.register(ItemLens::tickAllPlayers) CommandRegistrationCallback.EVENT.register { dp, _ -> HexCommands.register(dp) } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java new file mode 100644 index 00000000..30b8a208 --- /dev/null +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java @@ -0,0 +1,51 @@ +package at.petrak.hexcasting.fabric.interop.trinkets; + +import at.petrak.hexcasting.common.lib.HexItems; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Vector3f; +import dev.emi.trinkets.api.SlotReference; +import dev.emi.trinkets.api.client.TrinketRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; + +/** + * @author WireSegal + * Created at 9:50 AM on 7/25/22. + */ +public class LensTrinketRenderer implements TrinketRenderer { + @Override + public void render(ItemStack stack, SlotReference slotReference, EntityModel model, + PoseStack matrices, MultiBufferSource multiBufferSource, int light, LivingEntity entity, + float limbAngle, float limbDistance, float tickDelta, float animationProgress, + float headYaw, float headPitch) { + if (stack.is(HexItems.SCRYING_LENS) && + model instanceof PlayerModel playerModel && + entity instanceof AbstractClientPlayer player) { + + // from https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java + + // Translate and rotate with our head + matrices.pushPose(); + TrinketRenderer.followBodyRotations(entity, playerModel); + TrinketRenderer.translateToFace(matrices, playerModel, player, headYaw, headPitch); + + // Translate and scale to our head + matrices.translate(0, 0, 0.3); + matrices.mulPose(Vector3f.ZP.rotationDegrees(180.0f)); + matrices.scale(0.625f, 0.625f, 0.625f); + + // Render + Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.HEAD, + light, OverlayTexture.NO_OVERLAY, matrices, multiBufferSource, 0); + matrices.popPose(); + } + } + +} diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java new file mode 100644 index 00000000..a6187d08 --- /dev/null +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java @@ -0,0 +1,29 @@ +package at.petrak.hexcasting.fabric.interop.trinkets; + +import at.petrak.hexcasting.common.items.ItemLens; +import at.petrak.hexcasting.common.lib.HexItems; +import dev.emi.trinkets.api.TrinketComponent; +import dev.emi.trinkets.api.TrinketsApi; +import dev.emi.trinkets.api.client.TrinketRendererRegistry; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import java.util.Optional; + +public class TrinketsApiInterop { + public static void init() { + ItemLens.addLensHUDPredicate(player -> { + Optional optional = TrinketsApi.getTrinketComponent(player); + if (optional.isPresent()) { + TrinketComponent component = optional.get(); + return component.isEquipped(HexItems.SCRYING_LENS); + } + return false; + }); + } + + @Environment(EnvType.CLIENT) + public static void clientInit() { + TrinketRendererRegistry.registerRenderer(HexItems.SCRYING_LENS, new LensTrinketRenderer()); + } +} diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java index 76899f3f..4c60abb3 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java @@ -2,7 +2,10 @@ package at.petrak.hexcasting.fabric.xplat; import at.petrak.hexcasting.common.network.IMessage; import at.petrak.hexcasting.fabric.client.ExtendedTexture; +import at.petrak.hexcasting.fabric.interop.trinkets.TrinketsApiInterop; +import at.petrak.hexcasting.interop.HexInterop; import at.petrak.hexcasting.xplat.IClientXplatAbstractions; +import at.petrak.hexcasting.xplat.IXplatAbstractions; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; @@ -43,6 +46,13 @@ public class FabricClientXplatImpl implements IClientXplatAbstractions { BlockRenderLayerMap.INSTANCE.putBlock(block, type); } + @Override + public void initPlatformSpecific() { + if (IXplatAbstractions.INSTANCE.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { + TrinketsApiInterop.clientInit(); + } + } + @Override public void registerEntityRenderer(EntityType type, EntityRendererProvider renderer) { diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java index af8f3e6b..c57f7100 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java @@ -14,6 +14,7 @@ import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.network.IMessage; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import at.petrak.hexcasting.fabric.interop.gravity.GravityApiInterop; +import at.petrak.hexcasting.fabric.interop.trinkets.TrinketsApiInterop; import at.petrak.hexcasting.fabric.recipe.FabricUnsealedIngredient; import at.petrak.hexcasting.interop.HexInterop; import at.petrak.hexcasting.interop.pehkui.PehkuiInterop; @@ -98,6 +99,9 @@ public class FabricXplatImpl implements IXplatAbstractions { if (this.isModPresent(HexInterop.Fabric.GRAVITY_CHANGER_API_ID)) { GravityApiInterop.init(); } + if (this.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { + TrinketsApiInterop.init(); + } } @Override diff --git a/Fabric/src/main/resources/data/trinkets/entities/hex.json b/Fabric/src/main/resources/data/trinkets/entities/hex.json new file mode 100644 index 00000000..6f53a620 --- /dev/null +++ b/Fabric/src/main/resources/data/trinkets/entities/hex.json @@ -0,0 +1,8 @@ +{ + "entities": [ + "player" + ], + "slots": [ + "head/face" + ] +} diff --git a/Fabric/src/main/resources/data/trinkets/tags/items/head/face.json b/Fabric/src/main/resources/data/trinkets/tags/items/head/face.json new file mode 100644 index 00000000..9fae8ae7 --- /dev/null +++ b/Fabric/src/main/resources/data/trinkets/tags/items/head/face.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "hexcasting:lens" + ] +} diff --git a/Fabric/src/main/resources/fabric.mod.json b/Fabric/src/main/resources/fabric.mod.json index 3482c873..9c5f83d6 100644 --- a/Fabric/src/main/resources/fabric.mod.json +++ b/Fabric/src/main/resources/fabric.mod.json @@ -55,7 +55,8 @@ }, "suggests": { "gravitychanger": "0.7.7+fabric", - "pehkui": "3.3.2+1.14.4-1.19" + "pehkui": "3.3.2+1.14.4-1.19", + "trinkets": "3.3.1" }, "custom": { diff --git a/Forge/build.gradle b/Forge/build.gradle index ed6a3cea..3150cb41 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -119,6 +119,10 @@ repositories { name = "ModMaven" url = "https://modmaven.dev" } + maven { + //location of the maven for curios api + url = "https://maven.theillusivec4.top/" + } } dependencies { @@ -138,6 +142,9 @@ dependencies { compileOnly fg.deobf("mezz.jei:jei-$minecraftVersion:$jeiVersion:api") runtimeOnly fg.deobf("mezz.jei:jei-$minecraftVersion:$jeiVersion") + compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:$minecraftVersion-$curiosVersion:api") + runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:$minecraftVersion-$curiosVersion") + // aughh testCompileOnly fg.deobf("at.petra-k.paucal:paucal-forge-$minecraftVersion:$paucalVersion") testCompileOnly fg.deobf("vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion") diff --git a/Forge/gradle.properties b/Forge/gradle.properties index ad1f412f..9a6739a9 100644 --- a/Forge/gradle.properties +++ b/Forge/gradle.properties @@ -1 +1,3 @@ forgeVersion=40.1.0 + +curiosVersion=5.0.7.0 diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java index dbe92623..8b3f2b21 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java @@ -5,6 +5,7 @@ import at.petrak.hexcasting.client.HexAdditionalRenderers; import at.petrak.hexcasting.client.RegisterClientStuff; import at.petrak.hexcasting.client.ShiftScrollListener; import at.petrak.hexcasting.client.shader.HexShaders; +import at.petrak.hexcasting.interop.HexInterop; import net.minecraftforge.client.event.*; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; @@ -47,6 +48,8 @@ public class ForgeHexClientInitializer { var cancel = ShiftScrollListener.onScrollInGameplay(e.getScrollDelta()); e.setCanceled(cancel); }); + + HexInterop.clientInit(); } @SubscribeEvent diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java index e1a281ca..ef1fc043 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java @@ -12,6 +12,7 @@ import at.petrak.hexcasting.common.casting.operators.spells.great.OpFlight; import at.petrak.hexcasting.common.command.PatternResLocArgument; import at.petrak.hexcasting.common.entities.HexEntities; import at.petrak.hexcasting.common.items.ItemJewelerHammer; +import at.petrak.hexcasting.common.items.ItemLens; import at.petrak.hexcasting.common.lib.*; import at.petrak.hexcasting.common.loot.HexLootHandler; import at.petrak.hexcasting.common.misc.Brainsweeping; @@ -20,6 +21,8 @@ import at.petrak.hexcasting.common.recipe.HexRecipeSerializers; import at.petrak.hexcasting.forge.cap.CapSyncers; import at.petrak.hexcasting.forge.cap.ForgeCapabilityHandler; import at.petrak.hexcasting.forge.datagen.HexForgeDataGenerators; +import at.petrak.hexcasting.forge.interop.curios.CuriosApiInterop; +import at.petrak.hexcasting.forge.interop.curios.CuriosRenderers; import at.petrak.hexcasting.forge.network.ForgePacketHandler; import at.petrak.hexcasting.forge.network.MsgBrainsweepAck; import at.petrak.hexcasting.forge.recipe.ForgeUnsealedIngredient; @@ -37,6 +40,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.ToolActions; @@ -51,6 +55,8 @@ import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; @@ -160,6 +166,7 @@ public class ForgeHexInitializer { evBus.addListener((LivingEvent.LivingUpdateEvent evt) -> { OpFlight.INSTANCE.tickDownFlight(evt.getEntityLiving()); + ItemLens.tickLens(evt.getEntityLiving()); }); evBus.addListener((TickEvent.WorldTickEvent evt) -> { @@ -208,6 +215,12 @@ public class ForgeHexInitializer { modBus.register(HexForgeDataGenerators.class); modBus.register(ForgeCapabilityHandler.class); evBus.register(CapSyncers.class); + + if (ModList.get().isLoaded(HexInterop.Forge.CURIOS_API_ID)) { + modBus.addListener(CuriosApiInterop::onInterModEnqueue); + modBus.addListener(CuriosApiInterop::onClientSetup); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> modBus.addListener(CuriosRenderers::onLayerRegister)); + } } // aaaauughhg diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java new file mode 100644 index 00000000..2f3ebcd7 --- /dev/null +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java @@ -0,0 +1,36 @@ +package at.petrak.hexcasting.forge.interop.curios; + +import at.petrak.hexcasting.common.items.ItemLens; +import at.petrak.hexcasting.common.lib.HexItems; +import at.petrak.hexcasting.interop.HexInterop; +import net.minecraftforge.fml.InterModComms; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; +import top.theillusivec4.curios.api.CuriosCapability; +import top.theillusivec4.curios.api.SlotTypeMessage; +import top.theillusivec4.curios.api.SlotTypePreset; +import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class CuriosApiInterop { + + public static void init() { + ItemLens.addLensHUDPredicate(player -> { + AtomicBoolean hasLens = new AtomicBoolean(false); + player.getCapability(CuriosCapability.INVENTORY).ifPresent(handler -> { + ICurioStacksHandler stacksHandler = handler.getCurios().get("head"); + if(stacksHandler != null) hasLens.set(stacksHandler.getStacks().getStackInSlot(0).is(HexItems.SCRYING_LENS)); + }); + return hasLens.get(); + }); + } + + public static void onInterModEnqueue(final InterModEnqueueEvent event) { + InterModComms.sendTo(HexInterop.Forge.CURIOS_API_ID, SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.HEAD.getMessageBuilder().build()); + } + + public static void onClientSetup(final FMLClientSetupEvent event) { + CuriosRenderers.register(); + } +} diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java new file mode 100644 index 00000000..f0552fc1 --- /dev/null +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java @@ -0,0 +1,30 @@ +package at.petrak.hexcasting.forge.interop.curios; + +import at.petrak.hexcasting.common.lib.HexItems; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.EntityRenderersEvent; +import top.theillusivec4.curios.api.client.CuriosRendererRegistry; + +@OnlyIn(Dist.CLIENT) +public class CuriosRenderers { + public static void register() { + CuriosRendererRegistry.register(HexItems.SCRYING_LENS, () -> new LensCurioRenderer(Minecraft.getInstance().getEntityModels().bakeLayer(LensCurioRenderer.LAYER))); + } + + public static void onLayerRegister(final EntityRenderersEvent.RegisterLayerDefinitions event) { + event.registerLayerDefinition(LensCurioRenderer.LAYER, () -> { + CubeListBuilder builder = new CubeListBuilder(); + MeshDefinition mesh = HumanoidModel.createMesh(CubeDeformation.NONE, 0); + mesh.getRoot().addOrReplaceChild("head", builder, PartPose.ZERO); + return LayerDefinition.create(mesh, 1, 1); + }); + } +} diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java new file mode 100644 index 00000000..376731df --- /dev/null +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java @@ -0,0 +1,54 @@ +package at.petrak.hexcasting.forge.interop.curios; + +import at.petrak.hexcasting.api.HexAPI; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Vector3f; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import top.theillusivec4.curios.api.SlotContext; +import top.theillusivec4.curios.api.client.ICurioRenderer; + +public class LensCurioRenderer implements ICurioRenderer { + public static final ModelLayerLocation LAYER = new ModelLayerLocation(new ResourceLocation(HexAPI.MOD_ID, "lens"), "lens"); + + private final HumanoidModel model; + + public LensCurioRenderer(ModelPart part) { + this.model = new HumanoidModel<>(part); + } + + @Override + public > void render(ItemStack stack, SlotContext slotContext, PoseStack matrixStack, RenderLayerParent renderLayerParent, MultiBufferSource renderTypeBuffer, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + // https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java + + // Prepare values for transformation + model.setupAnim(slotContext.entity(), limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + model.prepareMobModel(slotContext.entity(), limbSwing, limbSwingAmount, partialTicks); + ICurioRenderer.followHeadRotations(slotContext.entity(), model.head); + + // Translate and rotate with our head + matrixStack.pushPose(); + matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0); + matrixStack.mulPose(Vector3f.YP.rotation(model.head.yRot)); + matrixStack.mulPose(Vector3f.XP.rotation(model.head.xRot)); + + // Translate and scale to our head + matrixStack.translate(0, -0.25, 0); + matrixStack.mulPose(Vector3f.ZP.rotationDegrees(180.0f)); + matrixStack.scale(0.625f, 0.625f, 0.625f); + + // Render + Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.HEAD, light, OverlayTexture.NO_OVERLAY, matrixStack, renderTypeBuffer, 0); + matrixStack.popPose(); + } +} diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java index a3013b1c..9107e1c7 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java @@ -37,6 +37,11 @@ public class ForgeClientXplatImpl implements IClientXplatAbstractions { ItemBlockRenderTypes.setRenderLayer(block, type); } + @Override + public void initPlatformSpecific() { + // NO-OP + } + @Override public void registerEntityRenderer(EntityType type, EntityRendererProvider renderer) { diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java index f1a24096..8e7e9a26 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java @@ -17,6 +17,7 @@ import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.network.IMessage; import at.petrak.hexcasting.forge.cap.CapSyncers; import at.petrak.hexcasting.forge.cap.HexCapabilities; +import at.petrak.hexcasting.forge.interop.curios.CuriosApiInterop; import at.petrak.hexcasting.forge.network.ForgePacketHandler; import at.petrak.hexcasting.forge.network.MsgBrainsweepAck; import at.petrak.hexcasting.forge.recipe.ForgeUnsealedIngredient; @@ -99,7 +100,9 @@ public class ForgeXplatImpl implements IXplatAbstractions { @Override public void initPlatformSpecific() { - // NO-OP + if (this.isModPresent(HexInterop.Forge.CURIOS_API_ID)) { + CuriosApiInterop.init(); + } } @Override diff --git a/Forge/src/main/resources/data/curios/tags/items/head.json b/Forge/src/main/resources/data/curios/tags/items/head.json new file mode 100644 index 00000000..9fae8ae7 --- /dev/null +++ b/Forge/src/main/resources/data/curios/tags/items/head.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "hexcasting:lens" + ] +}