Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import de.hysky.skyblocker.skyblock.fancybars.StatusBarsConfigScreen;
import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager;
import de.hysky.skyblocker.skyblock.item.slottext.SlotTextMode;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenu;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenuManager;
import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen;
import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder;
import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager;
Expand Down Expand Up @@ -37,6 +39,10 @@
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

public class UIAndVisualsCategory {
public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
Expand Down Expand Up @@ -214,6 +220,27 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig
.options(createSlotTextToggles(config))
.build()
)
.group(OptionGroup.createBuilder()
.name(Text.translatable("skyblocker.config.uiAndVisuals.radialMenu"))
.collapsed(true)
.option(Option.<Boolean>createBuilder()
.name(Text.translatable("skyblocker.config.uiAndVisuals.radialMenu.enabled"))
.description(Text.translatable("skyblocker.config.uiAndVisuals.radialMenu.enabled.@Tooltip"))
.binding(defaults.uiAndVisuals.radialMenu.enabled,
() -> config.uiAndVisuals.radialMenu.enabled,
newValue -> config.uiAndVisuals.radialMenu.enabled = newValue)
.controller(ConfigUtils.createBooleanController())
.build())
.option(Option.<Boolean>createBuilder()
.name(Text.translatable("skyblocker.config.uiAndVisuals.radialMenu.tooltipsWithoutShift"))
.binding(defaults.uiAndVisuals.radialMenu.tooltipsWithoutShift,
() -> config.uiAndVisuals.radialMenu.tooltipsWithoutShift,
newValue -> config.uiAndVisuals.radialMenu.tooltipsWithoutShift = newValue)
.controller(ConfigUtils.createBooleanController())
.build())
.options(createRadialToggles(config))
.build()
)

// Inventory Search
.group(OptionGroup.createBuilder()
Expand Down Expand Up @@ -922,4 +949,15 @@ private static List<Option<Boolean>> createSlotTextToggles(SkyblockerConfig conf
.map(configInfo -> configInfo.getOption(config))
.sorted(Comparator.comparing(option -> option.name().getString())).toList();
}

private static List<Option<Boolean>> createRadialToggles(SkyblockerConfig config) {
return RadialMenuManager.getMenuStream().filter(distinctByKey(RadialMenu::getConfigId))
.map(configInfo -> configInfo.getOption(config))
.sorted(Comparator.comparing(option -> option.name().getString())).toList();
}
//
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public class UIAndVisualsConfig {

public SlotText slotText = new SlotText();

public RadialMenu radialMenu = new RadialMenu();

public InventorySearchConfig inventorySearch = new InventorySearchConfig();

public TitleContainer titleContainer = new TitleContainer();
Expand Down Expand Up @@ -106,6 +108,16 @@ public static class SlotText {

}

public static class RadialMenu {
public boolean enabled = false;

public boolean tooltipsWithoutShift = false;

public Object2BooleanOpenHashMap<String> enabledMenus = new Object2BooleanOpenHashMap<>();


}

public static class InventorySearchConfig {
public EnableState enabled = EnableState.SKYBLOCK;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import de.hysky.skyblocker.skyblock.auction.AuctionViewScreen;
import de.hysky.skyblocker.skyblock.dungeon.LeapOverlay;
import de.hysky.skyblocker.skyblock.dungeon.partyfinder.PartyFinderScreen;
import de.hysky.skyblocker.skyblock.item.SkyblockCraftingTableScreenHandler;
import de.hysky.skyblocker.skyblock.item.SkyblockCraftingTableScreen;
import de.hysky.skyblocker.skyblock.item.SkyblockCraftingTableScreenHandler;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenu;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenuManager;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenuScreen;
import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen;
import de.hysky.skyblocker.utils.Utils;
import net.minecraft.client.MinecraftClient;
Expand All @@ -26,6 +29,7 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;


@Mixin(HandledScreens.Provider.class)
public interface HandledScreenProviderMixin<T extends ScreenHandler> {

Expand Down Expand Up @@ -117,6 +121,15 @@ public interface HandledScreenProviderMixin<T extends ScreenHandler> {
ci.cancel();
}

// radial menus
case GenericContainerScreenHandler containerScreenHandler when RadialMenuManager.isMenuExistsFromTitle(nameLowercase) -> {
client.player.currentScreenHandler = containerScreenHandler;
RadialMenu menuType = RadialMenuManager.getMenuFromTitle(nameLowercase);
client.setScreen(new RadialMenuScreen(containerScreenHandler, menuType, name));

ci.cancel();
}

case null, default -> {}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import de.hysky.skyblocker.skyblock.hunting.AttributeLevelHelper;
import de.hysky.skyblocker.skyblock.item.slottext.adders.*;
import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerScreen;
import de.hysky.skyblocker.skyblock.radialMenu.RadialMenuScreen;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.container.SlotTextAdder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
Expand Down Expand Up @@ -78,7 +79,7 @@ private SlotTextManager() {
@Init
public static void init() {
ScreenEvents.AFTER_INIT.register((client, screen, width, height) -> {
if ((screen instanceof HandledScreen<?> && Utils.isOnSkyblock()) || screen instanceof ProfileViewerScreen) {
if ((screen instanceof HandledScreen<?> && Utils.isOnSkyblock()) || screen instanceof ProfileViewerScreen || screen instanceof RadialMenuScreen) {
onScreenChange(screen);
ScreenEvents.remove(screen).register(ignored -> currentScreenAdders.clear());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package de.hysky.skyblocker.skyblock.radialMenu;

import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager;
import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview;
import de.hysky.skyblocker.utils.render.HudHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.gui.screen.narration.NarrationPart;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import org.joml.Vector2f;
import org.joml.Vector2i;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;

public class RadialButton implements Drawable, Element, Widget, Selectable {
private static final MinecraftClient CLIENT = MinecraftClient.getInstance();

private final float startAngle;
private final float arcLength;
private final float internalRadius;
private final float externalRadius;
private final ItemStack icon;
private final BooleanSupplier getHovered;
private final int linkedSlot;

public RadialButton(float startAngle, float arcLength, float internalRadius, float externalRadius, ItemStack icon, BooleanSupplier getHovered, int linkedSlot) {
super();
this.startAngle = (float) (startAngle - (Math.PI / 2)); //start at the top
this.arcLength = arcLength;
this.internalRadius = internalRadius;
this.externalRadius = externalRadius;
this.icon = icon;
this.getHovered = getHovered;
this.linkedSlot = linkedSlot;
}

public String getName() {
Text customName = icon.getCustomName();
if (customName == null) return "null";
return icon.getCustomName().getString();
}

protected int getLinkedSlot() {
return linkedSlot;
}

@Override
public ScreenRect getNavigationFocus() {
return Element.super.getNavigationFocus();
}

@Override
public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
//change color and radius when hovered
boolean hovered = getHovered.getAsBoolean();
int color = hovered ? 0xFE000000 : 0x77000000; //darker when hovered
float internal = internalRadius;
float external = hovered ? externalRadius + 5 : externalRadius;

//get bounding box
Vector2i center = new Vector2i(context.getScaledWindowWidth() / 2, context.getScaledWindowHeight() / 2);
List<Vector2f> vertices = new ArrayList<>();
//first background rectangle
vertices.add(getPos(center, startAngle, internal));
vertices.add(getPos(center, startAngle + arcLength / 2, internal));
vertices.add(getPos(center, startAngle + arcLength / 2, external));
vertices.add(getPos(center, startAngle, external));
//second background rectangle
vertices.add(getPos(center, startAngle + arcLength / 2, internal));
vertices.add(getPos(center, startAngle + arcLength, internal));
vertices.add(getPos(center, startAngle + arcLength, external));
vertices.add(getPos(center, startAngle + arcLength / 2, external));

//draw background
HudHelper.drawCustomShape(context, vertices, color);

//render icon
float iconAngle = startAngle + (arcLength / 2);
Vector2f iconPos = getPos(center, iconAngle, (internal + external) / 2);
iconPos.sub(8, 8);
context.drawItem(icon, (int) iconPos.x, (int) iconPos.y);
context.drawStackOverlay(CLIENT.textRenderer, icon, (int) iconPos.x, (int) iconPos.y);
SlotTextManager.renderSlotText(context, CLIENT.textRenderer, null, icon, linkedSlot, (int) iconPos.x, (int) iconPos.y);

//render tooltip
if (hovered && (Screen.hasShiftDown() || SkyblockerConfigManager.get().uiAndVisuals.radialMenu.tooltipsWithoutShift)) {
// Backpack Preview
if (CLIENT.currentScreen != null && CLIENT.currentScreen.getTitle().getString().equals("Storage")) {
BackpackPreview.renderPreview(context, CLIENT.currentScreen, linkedSlot, mouseX, mouseY);
} else {
//normal tooltips
context.drawItemTooltip(CLIENT.textRenderer, icon, mouseX, mouseY);
}
}
}

/**
* Get Screen position for a given angle and radius around the center
*
* @param center center of screen
* @param angle angle around center clockwise from top
* @param radius radius
* @return the screen position
*/
private static Vector2f getPos(Vector2i center, float angle, float radius) {
return new Vector2f((float) (center.x + (radius * Math.cos(angle))), (float) (center.y + (radius * Math.sin(angle))));
}

@Override
public SelectionType getType() {
if (this.isFocused()) {
return Selectable.SelectionType.FOCUSED;
} else {
return this.getHovered.getAsBoolean() ? Selectable.SelectionType.HOVERED : Selectable.SelectionType.NONE;
}
}

@Override
public boolean isNarratable() {
return Selectable.super.isNarratable();
}

@Override
public Collection<? extends Selectable> getNarratedParts() {
return Selectable.super.getNarratedParts();
}

@Override
public void appendNarrations(NarrationMessageBuilder builder) {
builder.put(NarrationPart.TITLE, getName());
}

@Override
public void setX(int x) {}

@Override
public void setY(int y) {}

@Override
public int getX() {
return 0;
}

@Override
public int getY() {
return 0;
}

@Override
public int getWidth() {
return 0;
}

@Override
public int getHeight() {
return 0;
}

@Override
public void forEachChild(Consumer<ClickableWidget> consumer) {}

@Override
public void setFocused(boolean focused) {

}

@Override
public boolean isFocused() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package de.hysky.skyblocker.skyblock.radialMenu;

import de.hysky.skyblocker.config.ConfigUtils;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import net.azureaaron.dandelion.systems.Option;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;

public abstract class RadialMenu {

/**
* @param title the original window title
* @return the title to show in the radial menu
*/
protected abstract Text getTitle(Text title);

/**
* Works out if this radial menu should be shown for a given screen title
*
* @param title screen title to compare
* @return the menu should be shown
*/
protected abstract boolean titleMatches(String title);

/**
* Works out if an item should be added to the menu
*
* @param slotId the slot the items in
* @param stack the item
* @return if it should be added
*/
protected abstract boolean itemMatches(int slotId, ItemStack stack);

public abstract String getConfigId();

/**
* Lets a Menu remap button clicked to suit it.
*
* @param originalButton original button clicked by user
* @param slotId the slot to be clicked
*/
public abstract int remapClickSlotButton(int originalButton, int slotId);

/**
* Lets a menu offset the clicked slot compared to the one shown in the menu
*
* @return offset to add to menu
*/
public abstract int clickSlotOffset(int slotId);

/**
* @return an array of names of items that are used to navigate the menu. These will be placed at the bottom
*/
public abstract String[] getNavigationItemNames();

protected boolean getEnabled() {
return SkyblockerConfigManager.get().uiAndVisuals.radialMenu.enabled && SkyblockerConfigManager.get().uiAndVisuals.radialMenu.enabledMenus.getOrDefault(getConfigId(), false);
}

public Option<Boolean> getOption(SkyblockerConfig config) {
return Option.<Boolean>createBuilder()
.name(Text.translatable("skyblocker.config.uiAndVisuals.radialMenu." + getConfigId()))
.binding(false,
() -> config.uiAndVisuals.radialMenu.enabledMenus.getOrDefault(getConfigId(), false),
newValue -> config.uiAndVisuals.radialMenu.enabledMenus.put(getConfigId(), newValue.booleanValue()))
.controller(ConfigUtils.createBooleanController())
.build();
}
}
Loading
Loading