From b89e1d1e7615826e1e62fa2f20b22766fdde2b74 Mon Sep 17 00:00:00 2001 From: MehVahdJukaar Date: Sat, 1 Jun 2024 12:18:45 +0200 Subject: [PATCH] Variant selector cleanups. Added alternative smaller arrow for variant HUD --- .../oddities/module/TotemOfHoldingModule.java | 3 - .../client/screen/VariantSelectorScreen.java | 364 +++++++++--------- .../experimental/config/VariantsConfig.java | 42 +- .../content/experimental/item/HammerItem.java | 2 +- .../module/VariantSelectorModule.java | 227 ++++++----- .../resources/assets/quark/lang/en_us.json | 1 - .../quark/textures/gui/general_icons.png | Bin 8175 -> 8168 bytes 7 files changed, 334 insertions(+), 305 deletions(-) diff --git a/src/main/java/org/violetmoon/quark/addons/oddities/module/TotemOfHoldingModule.java b/src/main/java/org/violetmoon/quark/addons/oddities/module/TotemOfHoldingModule.java index 7302aa605a..20b5ef38d6 100644 --- a/src/main/java/org/violetmoon/quark/addons/oddities/module/TotemOfHoldingModule.java +++ b/src/main/java/org/violetmoon/quark/addons/oddities/module/TotemOfHoldingModule.java @@ -54,9 +54,6 @@ public class TotemOfHoldingModule extends ZetaModule { @Config(description = "Set this to false to only allow the owner of a totem to collect its items rather than any player") public static boolean allowAnyoneToCollect = true; - @Config(flag = "soul_compass") - public static boolean enableSoulCompass = true; - @LoadEvent public final void register(ZRegister event) { totemType = EntityType.Builder.of(TotemOfHoldingEntity::new, MobCategory.MISC) diff --git a/src/main/java/org/violetmoon/quark/content/experimental/client/screen/VariantSelectorScreen.java b/src/main/java/org/violetmoon/quark/content/experimental/client/screen/VariantSelectorScreen.java index 296a6aadf1..38149bdf98 100644 --- a/src/main/java/org/violetmoon/quark/content/experimental/client/screen/VariantSelectorScreen.java +++ b/src/main/java/org/violetmoon/quark/content/experimental/client/screen/VariantSelectorScreen.java @@ -8,9 +8,9 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.datafixers.util.Pair; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.GameRenderer; @@ -18,198 +18,204 @@ import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import org.violetmoon.quark.content.experimental.item.HammerItem; import org.violetmoon.quark.content.experimental.module.VariantSelectorModule; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class VariantSelectorScreen extends Screen { - private float timeIn = 0; - private int slotSelected = -1; + private float timeIn = 0; + private int slotSelected = -1; - private final Minecraft mc; - private final ItemStack stack; - private final KeyMapping key; - private final String currentVariant; - private final List variants; + private final Minecraft mc; + private final KeyMapping key; + private final String currentVariant; + private final List> variants; + + private final List drawStacks = new ArrayList<>(); - private final List drawStacks = new ArrayList<>(); - - public VariantSelectorScreen(ItemStack stack, KeyMapping key, String currentVariant, List variants) { - super(Component.empty()); - mc = Minecraft.getInstance(); - this.stack = stack; - this.key = key; - this.currentVariant = currentVariant; - this.variants = variants; - } - - @Override - public void render(@NotNull GuiGraphics guiGraphics, int mx, int my, float delta) { - super.render(guiGraphics, mx, my, delta); - - timeIn += delta; - - int x = width / 2; - int y = height / 2; - int maxRadius = 50; - - int segments = variants.size() + 1; - float degPer = (float) Math.PI * 2 / segments; - - // ensure the boring one is always at the bottom - float pad = -((float) Math.PI / segments) + ((float) Math.PI / 2); - double angle = mouseAngle(x, y, mx, my); - double dist = (x - mx) * (x - mx) + (y - my) * (y - my); - - // loop angle around to ensure the last bit is accessible - if(angle < pad) - angle = Math.PI * 2 + pad; - - slotSelected = -1; - - Block block = Blocks.COBBLESTONE; - if(stack.getItem() instanceof BlockItem bi) - block = bi.getBlock(); - - Tesselator tess = Tesselator.getInstance(); - BufferBuilder buf = tess.getBuilder(); - - RenderSystem.disableCull(); - RenderSystem.enableBlend(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); - - drawStacks.clear(); - buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); - - for(int seg = 0; seg < segments; seg++) { - String variant = seg == 0 ? "" : variants.get(seg - 1); - boolean rightVariant = variant.equals(currentVariant); - - Block variantBlock = VariantSelectorModule.getVariantForBlock(block, variant); - boolean variantExists = seg == 0 || (variantBlock != block); - - float start = seg * degPer + pad; - float end = (seg + 1) * degPer + pad; - - boolean mouseInSector = variantExists && start < angle && angle < end && dist > 64; - float radius = Math.max(0F, Math.min((timeIn - ((float) seg * 6F / (float) segments)) * 40F, (float) maxRadius)); - - if(mouseInSector || rightVariant) - radius *= 1.1f; - - if(!variantExists) - radius *= 0.9f; - - int gs = 0x39; - if(seg % 2 == 0) - gs += 0x29; - - int r = gs; - int g = gs; - int b = gs; - int a = 0x44; - - if(variantExists) { - g += 0x22; - a = 0x99; - } else { - r /= 4; - g /= 4; - b /= 4; - } - - if(seg == 0) - buf.vertex(x, y, 0).color(r, g, b, a).endVertex(); - - if(mouseInSector) { - slotSelected = seg; - r = 0x00; - g = b = 0xAA; - } else if(rightVariant) { - r = b = 0x00; - g = 0xAA; - } - - float sxp = x + Mth.cos(start) * radius; - float syp = y + Mth.sin(start) * radius; - float exp = x + Mth.cos(end) * radius; - float eyp = y + Mth.sin(end) * radius; - - buf.vertex(sxp, syp, 0).color(r, g, b, a).endVertex(); - buf.vertex(exp, eyp, 0).color(r, g, b, a).endVertex(); - - float center = (seg + 0.5f) * degPer + pad; - float cxp = x + Mth.cos(center) * radius; - float cyp = y + Mth.sin(center) * radius; - - ItemStack variantStack = variantExists ? new ItemStack(variantBlock) : ItemStack.EMPTY; - double mod = 0.6; - int xdp = (int) ((cxp - x) * mod + x); - int ydp = (int) ((cyp - y) * mod + y); - drawStacks.add(new DrawStack(variantStack, xdp - 8, ydp - 8)); - } - tess.end(); - - RenderSystem.enableBlend(); - RenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); - - for(DrawStack ds : drawStacks) { - if(!ds.stack().isEmpty()) - guiGraphics.renderItem(ds.stack(), ds.x(), ds.y()); - } - RenderSystem.disableBlend(); - } - - @Override - public void tick() { - super.tick(); - if(!isKeyDown(key)) { - mc.setScreen(null); - - if(slotSelected == -1 && timeIn < 10) - slotSelected = 0; - - if(slotSelected != -1) { - String variant = slotSelected == 0 ? "" : variants.get(slotSelected - 1); - VariantSelectorModule.Client.setClientVariant(variant, true); - mc.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - } - } - - ImmutableSet set = ImmutableSet.of(mc.options.keyUp, mc.options.keyLeft, mc.options.keyDown, mc.options.keyRight, mc.options.keyShift, mc.options.keySprint, mc.options.keyJump); - for(KeyMapping k : set) { - KeyMapping.set(k.getKey(), isKeyDown(k)); - } - } - - public boolean isKeyDown(KeyMapping keybind) { - InputConstants.Key key = keybind.getKey(); - if(key.getType() == InputConstants.Type.MOUSE) { - return keybind.isDown(); - } - return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), key.getValue()); - } - - @Override - public boolean isPauseScreen() { - return false; - } - - private static double mouseAngle(int x, int y, int mx, int my) { - return (Mth.atan2(my - y, mx - x) + Math.PI * 2) % (Math.PI * 2); - } - - private record DrawStack(ItemStack stack, int x, int y) { - }; + public VariantSelectorScreen(Block originalBlock, KeyMapping key, String currentVariant, List visibleVariants) { + super(Component.empty()); + this.mc = Minecraft.getInstance(); + this.key = key; + this.currentVariant = currentVariant; + + this.variants = new ArrayList<>(); + this.variants.add(Pair.of("", originalBlock)); + for(String v : visibleVariants){ + Block variantBlock = VariantSelectorModule.getVariantBlockFromOriginal(originalBlock, v); + variants.add(Pair.of(v, variantBlock)); + } + } + + @Override + public void render(@NotNull GuiGraphics guiGraphics, int mx, int my, float delta) { + super.render(guiGraphics, mx, my, delta); + + timeIn += delta; + + int x = width / 2; + int y = height / 2; + int maxRadius = 50; + + int segments = variants.size() ; + float degPer = (float) Math.PI * 2 / segments; + + // ensure the boring one is always at the bottom + float pad = -((float) Math.PI / segments) + ((float) Math.PI / 2); + double angle = mouseAngle(x, y, mx, my); + double dist = (x - mx) * (x - mx) + (y - my) * (y - my); + + // loop angle around to ensure the last bit is accessible + if (angle < pad) + angle = Math.PI * 2 + pad; + + slotSelected = -1; + + Tesselator tess = Tesselator.getInstance(); + BufferBuilder buf = tess.getBuilder(); + + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + + drawStacks.clear(); + buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); + + for (int seg = 0; seg < segments; seg++) { + //we need 1 extra + var pair = variants.get(seg); + String variant = pair.getFirst(); + Block variantBlock = pair.getSecond(); + boolean variantExists = variantBlock != null; + + boolean rightVariant = variant.equals(currentVariant); + + float start = seg * degPer + pad; + float end = (seg + 1) * degPer + pad; + + boolean mouseInSector = variantExists && start < angle && angle < end && dist > 64; + float radius = Math.max(0F, Math.min((timeIn - ((float) seg * 6F / (float) segments)) * 40F, (float) maxRadius)); + + if (mouseInSector || rightVariant) + radius *= 1.1f; + + if (!variantExists) + radius *= 0.9f; + + int gs = 0x39; + if (seg % 2 == 0) + gs += 0x29; + + int r = gs; + int g = gs; + int b = gs; + int a = 0x44; + + if (variantExists) { + g += 0x22; + a = 0x99; + } else { + r /= 4; + g /= 4; + b /= 4; + } + + if (seg == 0) + buf.vertex(x, y, 0).color(r, g, b, a).endVertex(); + + if (mouseInSector) { + slotSelected = seg; + r = 0x00; + g = b = 0xAA; + } else if (rightVariant) { + r = b = 0x00; + g = 0xAA; + } + + float sxp = x + Mth.cos(start) * radius; + float syp = y + Mth.sin(start) * radius; + float exp = x + Mth.cos(end) * radius; + float eyp = y + Mth.sin(end) * radius; + + buf.vertex(sxp, syp, 0).color(r, g, b, a).endVertex(); + buf.vertex(exp, eyp, 0).color(r, g, b, a).endVertex(); + + float center = (seg + 0.5f) * degPer + pad; + float cxp = x + Mth.cos(center) * radius; + float cyp = y + Mth.sin(center) * radius; + + ItemStack variantStack = variantExists ? new ItemStack(variantBlock) : ItemStack.EMPTY; + double mod = 0.6; + int xdp = (int) ((cxp - x) * mod + x); + int ydp = (int) ((cyp - y) * mod + y); + drawStacks.add(new DrawStack(variantStack, xdp - 8, ydp - 8)); + } + tess.end(); + + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + + for (DrawStack ds : drawStacks) { + if (!ds.stack().isEmpty()) + guiGraphics.renderItem(ds.stack(), ds.x(), ds.y()); + } + RenderSystem.disableBlend(); + } + + @Override + public void tick() { + super.tick(); + if (!isKeyDown(key)) { + mc.setScreen(null); + + if (slotSelected == -1 && timeIn < 10) + slotSelected = 0; + + if (slotSelected != -1) { + String variant = variants.get(slotSelected).getFirst(); + VariantSelectorModule.Client.setClientVariant(variant, true); + mc.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + } + } + + ImmutableSet set = ImmutableSet.of(mc.options.keyUp, mc.options.keyLeft, mc.options.keyDown, mc.options.keyRight, mc.options.keyShift, mc.options.keySprint, mc.options.keyJump); + for (KeyMapping k : set) { + KeyMapping.set(k.getKey(), isKeyDown(k)); + } + } + + public boolean isKeyDown(KeyMapping keybind) { + InputConstants.Key key = keybind.getKey(); + if (key.getType() == InputConstants.Type.MOUSE) { + return keybind.isDown(); + } + return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), key.getValue()); + } + + @Override + public boolean isPauseScreen() { + return false; + } + + private static double mouseAngle(int x, int y, int mx, int my) { + return (Mth.atan2(my - y, mx - x) + Math.PI * 2) % (Math.PI * 2); + } + + private record DrawStack(ItemStack stack, int x, int y) { + } + + ; } diff --git a/src/main/java/org/violetmoon/quark/content/experimental/config/VariantsConfig.java b/src/main/java/org/violetmoon/quark/content/experimental/config/VariantsConfig.java index 58e67a86d7..71408df2a1 100644 --- a/src/main/java/org/violetmoon/quark/content/experimental/config/VariantsConfig.java +++ b/src/main/java/org/violetmoon/quark/content/experimental/config/VariantsConfig.java @@ -8,6 +8,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.violetmoon.quark.base.Quark; import org.violetmoon.zeta.config.Config; @@ -106,18 +107,6 @@ public void onReload(ZetaModule module, ConfigFlagManager flagManager) { logVariantMap(); } - // gets variant key for a block given its base block - @Nullable - public String getVariantForBlock(Block baseBlock, Block possibleVariant) { - VariantMap map = getVariants(baseBlock); - if(map != null){ - for(Entry entry : map.variants.entrySet()) - if(entry.getValue().equals(possibleVariant)) - return entry.getKey(); - } - return null; - } - @Nullable public String findVariantForBlock(Block variantBlock) { String name = BuiltInRegistries.BLOCK.getKey(variantBlock).getPath(); @@ -135,19 +124,30 @@ public String findVariantForBlock(Block variantBlock) { return null; } - public Block getBlockForVariant(Block block, String variant) { - blockVariants.clear(); - if(variant == null || !sortedSuffixes.contains(variant)) - return block; + // Null if not valid string, Not an original block or block wasn't changed (variant wasnt found) + @Nullable + public Block getBlockOfVariant(Block baseBlock, @NotNull String variant) { + //not a valid string + if(!sortedSuffixes.contains(variant)) + return null; - VariantMap map = getVariants(block); - Block ret = map.variants.get(variant); - if(ret != null) - return ret; + VariantMap map = getVariants(baseBlock); + return map.variants.get(variant); + } - return block; + // gets variant key for a block given its base block. Inverse of above + @Nullable + public String getVariantOfBlock(Block baseBlock, Block possibleVariant) { + VariantMap map = getVariants(baseBlock); + if(map != null){ + for(Entry entry : map.variants.entrySet()) + if(entry.getValue().equals(possibleVariant)) + return entry.getKey(); + } + return null; } + public Collection getAllVariants(Block block) { Map map = getVariants(block).variants; List blocks = new ArrayList<>(); diff --git a/src/main/java/org/violetmoon/quark/content/experimental/item/HammerItem.java b/src/main/java/org/violetmoon/quark/content/experimental/item/HammerItem.java index 9e5f5b46ef..b43b7d710b 100644 --- a/src/main/java/org/violetmoon/quark/content/experimental/item/HammerItem.java +++ b/src/main/java/org/violetmoon/quark/content/experimental/item/HammerItem.java @@ -39,7 +39,7 @@ public InteractionResult useOn(UseOnContext context) { if(player != null) { String variant = VariantSelectorModule.getSavedVariant(player); - Block variantBlock = VariantSelectorModule.getVariantOrOriginal(block, variant); + Block variantBlock = VariantSelectorModule.getVariantBlockFromAny(block, variant); if(variantBlock != null) { level.removeBlock(pos, false); diff --git a/src/main/java/org/violetmoon/quark/content/experimental/module/VariantSelectorModule.java b/src/main/java/org/violetmoon/quark/content/experimental/module/VariantSelectorModule.java index 07aaeaf7a9..219ebaf3ae 100644 --- a/src/main/java/org/violetmoon/quark/content/experimental/module/VariantSelectorModule.java +++ b/src/main/java/org/violetmoon/quark/content/experimental/module/VariantSelectorModule.java @@ -4,8 +4,8 @@ import java.util.Objects; import com.mojang.blaze3d.platform.GlStateManager; -import net.minecraft.client.gui.Gui; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import org.lwjgl.opengl.GL11; import org.violetmoon.quark.base.Quark; @@ -42,7 +42,6 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; @@ -57,12 +56,10 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; -import org.violetmoon.zetaimplforge.event.play.entity.player.ForgeZPlayer; @ZetaLoadModule( category = "experimental", enabledByDefault = false, @@ -102,6 +99,9 @@ public class VariantSelectorModule extends ZetaModule { @Config(description = "When true, selector arrow will render in same style as crosshair") public static boolean renderLikeCrossHair = true; + @Config(description = "Uses smaller arrow icon for variant selector overlay") + public static boolean smallerArrow = false; + @Config public static VariantsConfig variants = new VariantsConfig(); @@ -118,6 +118,7 @@ public final void configChanged(ZConfigChanged event) { staticEnabled = enabled; } + @NotNull public static String getSavedVariant(Player player) { if(player.level().isClientSide) return clientVariant; @@ -130,30 +131,31 @@ public static void setSavedVariant(ServerPlayer player, @NotNull String variant) player.getPersistentData().putString(TAG_CURRENT_VARIANT, variant); } + @Nullable private static Block getMainHandVariantBlock(Player player, String variant) { ItemStack mainHand = player.getMainHandItem(); if(mainHand.getItem() instanceof BlockItem blockItem) { Block block = blockItem.getBlock(); - return getVariantForBlock(block, variant); + return getVariantBlockFromOriginal(block, variant); } return null; } - public static Block getVariantForBlock(Block block, String variant) { - return variants.getBlockForVariant(block, variant); + // returns null if block was not changed! + // Like below but just accepts original block + @Nullable + public static Block getVariantBlockFromOriginal(Block original, @NotNull String variant) { + return variants.getBlockOfVariant(original, variant); } - public static Block getVariantOrOriginal(Block block, String variant) { - if(!variants.isVariant(block) && !variants.isOriginal(block)) - return null; - - block = variants.getOriginalBlock(block); - - if(variant == null || variant.isEmpty()) - return variants.getOriginalBlock(block); - - return getVariantForBlock(block, variant); + // returns null if block was not changed! + @Nullable + public static Block getVariantBlockFromAny(Block block, @NotNull String variant) { + Block originalBlock = variants.getOriginalBlock(block); + Block variantBlock = getVariantBlockFromOriginal(originalBlock, variant); + if(variantBlock != block)return variantBlock; + return null; } // Restore saved variant on join @@ -192,9 +194,11 @@ public static BlockState modifyBlockPlacementState(BlockState state, BlockPlaceC Player player = ctx.getPlayer(); if(player != null) { String variant = getSavedVariant(player); - if(variant != null && !variant.isEmpty()) { - Block target = getVariantForBlock(state.getBlock(), variant); - return target.getStateForPlacement(ctx); + if(!variant.isEmpty()) { + Block target = getVariantBlockFromOriginal(state.getBlock(), variant); + if (target != null) { + return target.getStateForPlacement(ctx); + } } } @@ -213,7 +217,7 @@ public static ItemStack modifyHeldItemStack(AbstractClientPlayer player, ItemSta if(player == mc.player && stack.getItem() instanceof BlockItem bi) { Block block = bi.getBlock(); if(!clientVariant.isEmpty()) { - Block variant = variants.getBlockForVariant(block, clientVariant); + Block variant = variants.getBlockOfVariant(block, clientVariant); if(variant != null && variant != block) return new ItemStack(variant); } @@ -235,13 +239,22 @@ public static void setClientVariant(String variant, boolean sync) { clientVariant = variant; } - public static boolean onPickBlock(Player player, ItemStack stack) { - ItemStack mainHand = player.getMainHandItem(); - if(mainHand.getItem() instanceof BlockItem handItem && stack.getItem() instanceof BlockItem variant) { - String variantKey = variants.getVariantForBlock(handItem.getBlock(), variant.getBlock()); - if(variantKey != null) { - setClientVariant(variantKey, true); - return true; + public static boolean onPickBlock(Player player, ItemStack pickResult) { + if(pickResult.getItem() instanceof BlockItem pickedVariant){ + Block pickedBlock = pickedVariant.getBlock(); + Block original = null; + ItemStack mainHand = player.getMainHandItem(); + if(mainHand.getItem() instanceof BlockItem handItem) { + original = handItem.getBlock(); + }else if(mainHand.is(hammer)){ + original = variants.getOriginalBlock(pickedBlock); + } + if(original!= null) { + String variantKey = variants.getVariantOfBlock(original, pickedBlock); + if (variantKey != null) { + setClientVariant(variantKey, true); + return true; + } } } return false; @@ -254,23 +267,31 @@ public void keystroke(ZInput.Key event) { if(variantSelectorKey.isDown()) { ItemStack stack = mc.player.getMainHandItem(); + Block originalBlock = null; if(stack.is(hammer)) { - HitResult result = mc.hitResult; - if(result instanceof BlockHitResult bhr) { - BlockPos pos = bhr.getBlockPos(); - Block block = mc.player.level().getBlockState(pos).getBlock(); - stack = new ItemStack(variants.getOriginalBlock(block)); - } + originalBlock = variants.getOriginalBlock(getLookedAtBlock()); + }else if(!stack.isEmpty() && stack.getItem() instanceof BlockItem bi){ + originalBlock = bi.getBlock(); + } + if(originalBlock != null){ + mc.setScreen(new VariantSelectorScreen(originalBlock, variantSelectorKey, + clientVariant, variants.getVisibleVariants())); } - - if(!stack.isEmpty() && stack.getItem() instanceof BlockItem) - mc.setScreen(new VariantSelectorScreen(stack, variantSelectorKey, clientVariant, variants.getVisibleVariants())); - - return; } } } + private Block getLookedAtBlock() { + Minecraft mc = Minecraft.getInstance(); + HitResult result = mc.hitResult; + if(result instanceof BlockHitResult bhr) { + BlockPos pos = bhr.getBlockPos(); + Block block = mc.player.level().getBlockState(pos).getBlock(); + return block; + } + return null; + } + @LoadEvent public void registerClientTooltipComponentFactories(ZTooltipComponents event) { event.register(VariantsComponent.class); @@ -310,84 +331,90 @@ public void onRender(ZRenderGuiOverlay.Crosshair.Pre event) { Player player = mc.player; String savedVariant = getSavedVariant(player); - if(savedVariant != null) { - ItemStack mainHand = player.getMainHandItem(); - ItemStack displayLeft = mainHand.copy(); + ItemStack mainHand = player.getMainHandItem(); + ItemStack displayLeft = mainHand.copy(); - Block variantBlock = null; + Block variantBlock = null; - if(displayLeft.is(hammer)) { - HitResult result = mc.hitResult; - if(result instanceof BlockHitResult bhr) { - BlockPos pos = bhr.getBlockPos(); - Block testBlock = player.level().getBlockState(pos).getBlock(); + if(displayLeft.is(hammer)) { + HitResult result = mc.hitResult; + if(result instanceof BlockHitResult bhr) { + BlockPos pos = bhr.getBlockPos(); + Block testBlock = player.level().getBlockState(pos).getBlock(); - displayLeft = new ItemStack(testBlock); - variantBlock = getVariantOrOriginal(testBlock, savedVariant); - } - } else - variantBlock = getMainHandVariantBlock(player, savedVariant); + displayLeft = new ItemStack(testBlock); + variantBlock = getVariantBlockFromAny(testBlock, savedVariant); + } + } else + variantBlock = getMainHandVariantBlock(player, savedVariant); - if(variantBlock != null) { - ItemStack displayRight = new ItemStack(variantBlock); + if(variantBlock != null) { + ItemStack displayRight = new ItemStack(variantBlock); - if(displayLeft.getItem() == displayRight.getItem()) - return; + if(displayLeft.getItem() == displayRight.getItem()) + return; - Window window = event.getWindow(); - int x = window.getGuiScaledWidth() / 2; - int y = window.getGuiScaledHeight() / 2 + 12; + Window window = event.getWindow(); + int x = window.getGuiScaledWidth() / 2; + int y = window.getGuiScaledHeight() / 2 + 12; - if(alignHudToHotbar) { - HumanoidArm arm = mc.options.mainHand().get(); - if(arm == HumanoidArm.RIGHT) - x += 125; - else - x -= 93; + if(alignHudToHotbar) { + HumanoidArm arm = mc.options.mainHand().get(); + if(arm == HumanoidArm.RIGHT) + x += 125; + else + x -= 93; - y = window.getGuiScaledHeight() - 19; - } + y = window.getGuiScaledHeight() - 19; + } - int offset = 8; - int width = 16; + int offset = 8; + int width = smallerArrow ? 13 : 16; - displayLeft.setCount(1); + displayLeft.setCount(1); - int posX = x - offset - width + hudOffsetX; - int posY = y + hudOffsetY; + int posX = x - offset - width + hudOffsetX; + int posY = y + hudOffsetY; - if( !showSimpleHud) { - guiGraphics.renderFakeItem(displayLeft, posX, posY); + if( !showSimpleHud) { + guiGraphics.renderFakeItem(displayLeft, posX, posY); - RenderSystem.enableBlend(); - if(renderLikeCrossHair) { - RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1); - }else{ - RenderSystem.defaultBlendFunc(); - RenderSystem.setShaderColor(0.8f, 0.8f, 0.8f, 0.7f); - } - guiGraphics.blit(ClientUtil.GENERAL_ICONS, posX + 8, posY, 0, 141, 22, 15, 256, 256); + RenderSystem.enableBlend(); + if(renderLikeCrossHair) { + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1); + }else{ RenderSystem.defaultBlendFunc(); - - posX += width * 2; - } else { - final ResourceLocation WIDGETS_LOCATION = new ResourceLocation("textures/gui/widget.png"); - - if(alignHudToHotbar) { - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - if(enableGreenTint) - RenderSystem.setShaderColor(0.5F, 1.0F, 0.5F, 1.0F); - else - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - guiGraphics.blit(WIDGETS_LOCATION, posX - 3, posY - 3, 24, 23, 22, 22, 256, 256); - } else - posX += width; + RenderSystem.setShaderColor(0.8f, 0.8f, 0.8f, 0.7f); } + //alternative smaller arrow + if(smallerArrow){ + guiGraphics.blit(ClientUtil.GENERAL_ICONS, posX + 8, posY+5, 0, + 141+17, 22, 15, 256, 256); + }else { + guiGraphics.blit(ClientUtil.GENERAL_ICONS, posX + 8, posY, 0, + 141, 22, 15, 256, 256); + } + + RenderSystem.defaultBlendFunc(); - guiGraphics.renderFakeItem(displayRight, posX, posY); + posX += width * 2; + } else { + final ResourceLocation WIDGETS_LOCATION = new ResourceLocation("textures/gui/widget.png"); + + if(alignHudToHotbar) { + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + if(enableGreenTint) + RenderSystem.setShaderColor(0.5F, 1.0F, 0.5F, 1.0F); + else + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + guiGraphics.blit(WIDGETS_LOCATION, posX - 3, posY - 3, 24, 23, 22, 22, 256, 256); + } else + posX += width; } + + guiGraphics.renderFakeItem(displayRight, posX, posY); } } } diff --git a/src/main/resources/assets/quark/lang/en_us.json b/src/main/resources/assets/quark/lang/en_us.json index 211ff28fa7..8fd939c480 100644 --- a/src/main/resources/assets/quark/lang/en_us.json +++ b/src/main/resources/assets/quark/lang/en_us.json @@ -518,7 +518,6 @@ "item.quark.moss_paste": "Moss Paste", "item.quark.backpack": "Backpack", "item.quark.ravager_hide": "Ravager Hide", - "item.quark.soul_compass": "Soul Compass", "item.quark.bottled_cloud": "Cloud in a Bottle", "item.quark.flamerang": "Flamarang", "item.quark.seed_pouch": "Seed Pouch", diff --git a/src/main/resources/assets/quark/textures/gui/general_icons.png b/src/main/resources/assets/quark/textures/gui/general_icons.png index 65cee3d330d661abc36c29147ca6419e76086430..875bcc5e1fbf8d890cd0735455e2a894d3017a64 100644 GIT binary patch delta 6126 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 delta 6125 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 C3Gguh