mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-13 07:15:10 +01:00
Fix issues, improve REI compat and horizontal reach-around, WIP on ring.
This commit is contained in:
@@ -7,7 +7,7 @@ archivesBaseName = project.archives_base_name + "-core"
|
||||
|
||||
dependencies {
|
||||
api "org.jetbrains:annotations:17.0.0"
|
||||
api "org.aperlambda:lambdajcommon:1.8.0"
|
||||
api "org.aperlambda:lambdajcommon:1.8.1"
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@@ -21,15 +21,15 @@ import java.util.Optional;
|
||||
* Represents a feature.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.3.2
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class LambdaControlsFeature implements Nameable
|
||||
{
|
||||
private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>();
|
||||
public static final LambdaControlsFeature FAST_BLOCK_PLACING = new LambdaControlsFeature("fast_block_placing", true, true);
|
||||
public static final LambdaControlsFeature FRONT_BLOCK_PLACING = new LambdaControlsFeature("front_block_placing", true, false);
|
||||
public static final LambdaControlsFeature VERTICAL_REACHAROUND = new LambdaControlsFeature("vertical_reacharound", true, false);
|
||||
private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>();
|
||||
public static final LambdaControlsFeature FAST_BLOCK_PLACING = new LambdaControlsFeature("fast_block_placing", true, true);
|
||||
public static final LambdaControlsFeature HORIZONTAL_REACHAROUND = new LambdaControlsFeature("horizontal_reacharound", true, false);
|
||||
public static final LambdaControlsFeature VERTICAL_REACHAROUND = new LambdaControlsFeature("vertical_reacharound", true, false);
|
||||
|
||||
private final String key;
|
||||
private final boolean defaultAllowed;
|
||||
@@ -157,7 +157,7 @@ public class LambdaControlsFeature implements Nameable
|
||||
|
||||
static {
|
||||
FEATURES.add(FAST_BLOCK_PLACING);
|
||||
FEATURES.add(FRONT_BLOCK_PLACING);
|
||||
FEATURES.add(HORIZONTAL_REACHAROUND);
|
||||
FEATURES.add(VERTICAL_REACHAROUND);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.Optional;
|
||||
* Represents the LambdaControls mod.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.3.0
|
||||
* @version 1.5.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LambdaControls implements ModInitializer
|
||||
@@ -56,7 +56,7 @@ public class LambdaControls implements ModInitializer
|
||||
.ifPresent(controlsMode -> context.getTaskQueue()
|
||||
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode)));
|
||||
context.getTaskQueue().execute(() ->
|
||||
ServerSidePacketRegistry.INSTANCE.sendToPlayer(context.getPlayer(), FEATURE_CHANNEL, this.makeFeatureBuffer(LambdaControlsFeature.FRONT_BLOCK_PLACING)));
|
||||
ServerSidePacketRegistry.INSTANCE.sendToPlayer(context.getPlayer(), FEATURE_CHANNEL, this.makeFeatureBuffer(LambdaControlsFeature.HORIZONTAL_REACHAROUND)));
|
||||
});
|
||||
ServerSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL,
|
||||
(context, attachedData) -> ControlsMode.byId(attachedData.readString(32))
|
||||
|
||||
@@ -20,6 +20,7 @@ import me.lambdaurora.lambdacontrols.client.controller.InputManager;
|
||||
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud;
|
||||
import me.lambdaurora.lambdacontrols.client.gui.RingScreen;
|
||||
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
|
||||
import me.lambdaurora.lambdacontrols.client.ring.KeyBindingRingAction;
|
||||
import me.lambdaurora.lambdacontrols.client.ring.LambdaRing;
|
||||
import me.lambdaurora.spruceui.event.OpenScreenCallback;
|
||||
import me.lambdaurora.spruceui.hud.HudManager;
|
||||
@@ -43,7 +44,7 @@ import java.io.File;
|
||||
* Represents the LambdaControls client mod.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class LambdaControlsClient extends LambdaControls implements ClientModInitializer
|
||||
@@ -65,7 +66,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
|
||||
public final static File MAPPINGS_FILE = new File("config/gamecontrollerdb.txt");
|
||||
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
|
||||
public final LambdaInput input = new LambdaInput(this);
|
||||
public final LambdaRing ring = new LambdaRing();
|
||||
public final LambdaRing ring = new LambdaRing(this);
|
||||
public final LambdaReacharound reacharound = new LambdaReacharound();
|
||||
private LambdaControlsHud hud;
|
||||
private ControlsMode previousControlsMode;
|
||||
@@ -78,7 +79,9 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
||||
//KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||
|
||||
this.ring.registerAction("keybinding", KeyBindingRingAction.FACTORY);
|
||||
|
||||
ClientSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL, (context, attachedData) -> context.getTaskQueue()
|
||||
.execute(() -> ClientSidePacketRegistry.INSTANCE.sendToServer(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()))));
|
||||
|
||||
@@ -44,7 +44,7 @@ public class LambdaControlsConfig
|
||||
private static final boolean DEFAULT_FAST_BLOCK_INTERACTION = true;
|
||||
private static final boolean DEFAULT_FLY_DRIFTING = false;
|
||||
private static final boolean DEFAULT_FLY_VERTICAL_DRIFTING = true;
|
||||
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = false;
|
||||
private static final boolean DEFAULT_HORIZONTAL_REACHAROUND = false;
|
||||
private static final boolean DEFAULT_VERTICAL_REACHAROUND = false;
|
||||
private static final boolean DEFAULT_REACHAROUND_OUTLINE = true;
|
||||
private static final int[] DEFAULT_REACHAROUND_OUTLINE_COLOR = new int[]{255, 255, 255, 102};
|
||||
@@ -96,7 +96,7 @@ public class LambdaControlsConfig
|
||||
this.hudSide = HudSide.byId(this.config.getOrElse("hud.side", DEFAULT_HUD_SIDE.getName())).orElse(DEFAULT_HUD_SIDE);
|
||||
// Gameplay
|
||||
LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.fast_block_placing", DEFAULT_FAST_BLOCK_INTERACTION));
|
||||
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.reacharound.horizontal", DEFAULT_FRONT_BLOCK_PLACING));
|
||||
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(this.config.getOrElse("gameplay.reacharound.horizontal", DEFAULT_HORIZONTAL_REACHAROUND));
|
||||
LambdaControlsFeature.VERTICAL_REACHAROUND.setEnabled(this.config.getOrElse("gameplay.reacharound.vertical", DEFAULT_VERTICAL_REACHAROUND));
|
||||
this.shouldRenderReacharoundOutline = this.config.getOrElse("gameplay.reacharound.outline", DEFAULT_REACHAROUND_OUTLINE);
|
||||
this.reacharoundOutlineColor = this.config.getOptional("gameplay.reacharound.outline_color").map(hex -> parseColor((String) hex)).orElse(DEFAULT_REACHAROUND_OUTLINE_COLOR);
|
||||
@@ -110,6 +110,8 @@ public class LambdaControlsConfig
|
||||
this.virtualMouseSkin = VirtualMouseSkin.byId(this.config.getOrElse("controller.virtual_mouse_skin", DEFAULT_VIRTUAL_MOUSE_SKIN.getName())).orElse(DEFAULT_VIRTUAL_MOUSE_SKIN);
|
||||
// Controller controls.
|
||||
InputManager.loadButtonBindings(this);
|
||||
|
||||
this.mod.ring.load(this.config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +140,7 @@ public class LambdaControlsConfig
|
||||
});
|
||||
|
||||
if (this.config.contains("gameplay.front_block_placing.enabled")) {
|
||||
this.setFrontBlockPlacing(this.config.getOrElse("gameplay.front_block_placing.enabled", DEFAULT_FRONT_BLOCK_PLACING));
|
||||
this.setFrontBlockPlacing(this.config.getOrElse("gameplay.front_block_placing.enabled", DEFAULT_HORIZONTAL_REACHAROUND));
|
||||
this.config.remove("gameplay.front_block_placing.enabled");
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ public class LambdaControlsConfig
|
||||
this.setFastBlockPlacing(DEFAULT_FAST_BLOCK_INTERACTION);
|
||||
this.setFlyDrifting(DEFAULT_FLY_DRIFTING);
|
||||
this.setFlyVerticalDrifting(DEFAULT_FLY_VERTICAL_DRIFTING);
|
||||
this.setFrontBlockPlacing(DEFAULT_FRONT_BLOCK_PLACING);
|
||||
this.setFrontBlockPlacing(DEFAULT_HORIZONTAL_REACHAROUND);
|
||||
this.setVerticalReacharound(DEFAULT_VERTICAL_REACHAROUND);
|
||||
this.setRenderReacharoundOutline(DEFAULT_REACHAROUND_OUTLINE);
|
||||
// Controller
|
||||
@@ -376,7 +378,7 @@ public class LambdaControlsConfig
|
||||
*/
|
||||
public boolean hasFrontBlockPlacing()
|
||||
{
|
||||
return LambdaControlsFeature.FRONT_BLOCK_PLACING.isEnabled();
|
||||
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +388,7 @@ public class LambdaControlsConfig
|
||||
*/
|
||||
public void setFrontBlockPlacing(boolean enable)
|
||||
{
|
||||
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(enable);
|
||||
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(enable);
|
||||
this.config.set("gameplay.reacharound.horizontal", enable);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,26 +23,27 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.RayTraceContext;
|
||||
import net.minecraft.world.RaycastContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents the reacharound API of LambdaControls.
|
||||
* Represents the reach-around API of LambdaControls.
|
||||
*
|
||||
* @version 1.3.2
|
||||
* @version 1.5.0
|
||||
* @since 1.3.2
|
||||
*/
|
||||
public class LambdaReacharound
|
||||
{
|
||||
private BlockHitResult lastReacharoundResult = null;
|
||||
private boolean onSlab = false;
|
||||
private boolean lastReacharoundVertical = false;
|
||||
|
||||
public void tick(@NotNull MinecraftClient client)
|
||||
{
|
||||
this.lastReacharoundResult = this.tryVerticalReachAround(client);
|
||||
if (this.lastReacharoundResult == null) {
|
||||
this.lastReacharoundResult = this.tryFrontPlace(client);
|
||||
this.lastReacharoundResult = this.tryHorizontalReachAround(client);
|
||||
this.lastReacharoundVertical = false;
|
||||
} else this.lastReacharoundVertical = true;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ public class LambdaReacharound
|
||||
*/
|
||||
public boolean isReacharoundAvailable()
|
||||
{
|
||||
return LambdaControlsFeature.FRONT_BLOCK_PLACING.isAvailable() || LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
||||
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
||||
}
|
||||
|
||||
private float getPlayerRange(@NotNull MinecraftClient client)
|
||||
@@ -83,10 +84,10 @@ public class LambdaReacharound
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nullable block hit result if vertical reacharound is possible.
|
||||
* Returns a nullable block hit result if vertical reach-around is possible.
|
||||
*
|
||||
* @param client The client instance.
|
||||
* @return A block hit result if vertical reacharound is possible, else null.
|
||||
* @return A block hit result if vertical reach-around is possible, else null.
|
||||
*/
|
||||
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client)
|
||||
{
|
||||
@@ -101,7 +102,7 @@ public class LambdaReacharound
|
||||
Vec3d rotationVec = client.player.getRotationVec(1.0F);
|
||||
float range = getPlayerRange(client);
|
||||
Vec3d rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
|
||||
BlockHitResult result = client.world.rayTrace(new RayTraceContext(pos, rayVec, RayTraceContext.ShapeType.OUTLINE, RayTraceContext.FluidHandling.NONE, client.player));
|
||||
BlockHitResult result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
|
||||
|
||||
if (result.getType() == HitResult.Type.BLOCK) {
|
||||
BlockPos blockPos = result.getBlockPos().down();
|
||||
@@ -116,19 +117,26 @@ public class LambdaReacharound
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nullable block hit result if front placing is possible.
|
||||
* Returns a nullable block hit result if horizontal reach-around is possible.
|
||||
*
|
||||
* @param client The client instance.
|
||||
* @return A block hit result if front placing is possible.
|
||||
* @return A block hit result if horizontal reach-around is possible.
|
||||
*/
|
||||
public @Nullable BlockHitResult tryFrontPlace(@NotNull MinecraftClient client)
|
||||
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client)
|
||||
{
|
||||
if (!LambdaControlsFeature.FRONT_BLOCK_PLACING.isAvailable())
|
||||
if (!LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
||||
return null;
|
||||
|
||||
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS && client.player.isOnGround() && client.player.pitch > 35.0F) {
|
||||
if (client.player.isRiding())
|
||||
return null;
|
||||
BlockPos playerPos = client.player.getBlockPos().down();
|
||||
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
||||
playerPos = playerPos.up();
|
||||
this.onSlab = true;
|
||||
} else {
|
||||
this.onSlab = false;
|
||||
}
|
||||
BlockPos targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
||||
BlockPos vector = new BlockPos(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
||||
BlockPos blockPos = playerPos.add(vector);
|
||||
@@ -148,17 +156,19 @@ public class LambdaReacharound
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @Nullable ItemStack stack)
|
||||
public @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @Nullable ItemStack stack)
|
||||
{
|
||||
if (stack == null || stack.isEmpty() || !(stack.getItem() instanceof BlockItem))
|
||||
return result;
|
||||
return withSideForReacharound(result, Block.getBlockFromItem(stack.getItem()));
|
||||
}
|
||||
|
||||
public static @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @NotNull Block block)
|
||||
public @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @NotNull Block block)
|
||||
{
|
||||
if (block instanceof SlabBlock)
|
||||
result = result.withSide(Direction.DOWN);
|
||||
if (block instanceof SlabBlock) {
|
||||
if (this.onSlab) result = result.withSide(Direction.UP);
|
||||
else result = result.withSide(Direction.DOWN);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -22,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Represents a compatibility handler for a mod.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.3.2
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface CompatHandler
|
||||
@@ -45,6 +46,20 @@ public interface CompatHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a slot at the specified location if possible.
|
||||
*
|
||||
* @param screen The screen.
|
||||
* @param mouseX The mouse X-coordinate.
|
||||
* @param mouseY The mouse Y-coordinate.
|
||||
* @return A slot if present, else null.
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current slot is a creative slot or not.
|
||||
*
|
||||
|
||||
@@ -14,8 +14,10 @@ import me.lambdaurora.lambdacontrols.client.controller.InputManager;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,7 +29,7 @@ import java.util.stream.Stream;
|
||||
* Represents a compatibility handler.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.3.2
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class LambdaControlsCompat
|
||||
@@ -88,6 +90,24 @@ public class LambdaControlsCompat
|
||||
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a slot at the specified location if possible.
|
||||
*
|
||||
* @param screen The screen.
|
||||
* @param mouseX The mouse X-coordinate.
|
||||
* @param mouseY The mouse Y-coordinate.
|
||||
* @return A slot if present, else null.
|
||||
*/
|
||||
public static @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY)
|
||||
{
|
||||
for (CompatHandler handler : HANDLERS) {
|
||||
Pair<Integer, Integer> slot = handler.getSlotAt(screen, mouseX, mouseY);
|
||||
if (slot != null)
|
||||
return slot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a custom translation key to make custom attack action strings on the HUD.
|
||||
*
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.compat;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
@@ -21,7 +22,7 @@ import java.util.Set;
|
||||
* This plugin is only present for the conditional mixins.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.2.0
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class LambdaControlsMixinPlugin implements IMixinConfigPlugin
|
||||
@@ -30,8 +31,15 @@ public class LambdaControlsMixinPlugin implements IMixinConfigPlugin
|
||||
|
||||
public LambdaControlsMixinPlugin()
|
||||
{
|
||||
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
||||
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("EntryListWidgetAccessor", LambdaControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("EntryWidgetAccessor", LambdaControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("RecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("VillagerRecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
||||
}
|
||||
|
||||
private void putConditionalMixin(@NotNull String path, boolean condition)
|
||||
{
|
||||
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin." + path, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,24 +11,32 @@ package me.lambdaurora.lambdacontrols.client.compat;
|
||||
|
||||
import me.lambdaurora.lambdacontrols.client.ButtonState;
|
||||
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
||||
import me.lambdaurora.lambdacontrols.client.compat.mixin.EntryListWidgetAccessor;
|
||||
import me.lambdaurora.lambdacontrols.client.compat.mixin.EntryWidgetAccessor;
|
||||
import me.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor;
|
||||
import me.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor;
|
||||
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
||||
import me.lambdaurora.lambdacontrols.client.controller.InputHandlers;
|
||||
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
|
||||
import me.lambdaurora.lambdacontrols.client.controller.PressAction;
|
||||
import me.shedaniel.rei.api.REIHelper;
|
||||
import me.shedaniel.rei.api.RecipeCategory;
|
||||
import me.shedaniel.rei.api.*;
|
||||
import me.shedaniel.rei.gui.ContainerScreenOverlay;
|
||||
import me.shedaniel.rei.gui.PreRecipeViewingScreen;
|
||||
import me.shedaniel.rei.gui.RecipeViewingScreen;
|
||||
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
|
||||
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
|
||||
import me.shedaniel.rei.gui.widget.EntryListWidget;
|
||||
import me.shedaniel.rei.gui.widget.EntryWidget;
|
||||
import me.shedaniel.rei.gui.widget.WidgetWithBounds;
|
||||
import me.shedaniel.rei.impl.ScreenHelper;
|
||||
import me.shedaniel.rei.impl.widgets.ButtonWidget;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -39,67 +47,124 @@ import static org.lwjgl.glfw.GLFW.*;
|
||||
* Represents a compatibility handler for REI.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.0
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ReiCompat implements CompatHandler
|
||||
{
|
||||
private static EntryListWidget ENTRY_LIST_WIDGET;
|
||||
private static final Pair<Integer, Integer> INVALID_SLOT = new Pair<>(-1, -1);
|
||||
private static EntryListWidget ENTRY_LIST_WIDGET;
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull LambdaControlsClient mod)
|
||||
{
|
||||
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "category_back"))
|
||||
ButtonBinding.builder(new Identifier("rei", "category_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(false))
|
||||
.cooldown(true)
|
||||
.build());
|
||||
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "category_next"))
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "category_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(true))
|
||||
.cooldown(true)
|
||||
.build());
|
||||
.register();
|
||||
|
||||
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "page_back"))
|
||||
ButtonBinding.builder(new Identifier("rei", "page_back"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, false))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(false))
|
||||
.cooldown(true)
|
||||
.build());
|
||||
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "page_next"))
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "page_next"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, true))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(true))
|
||||
.cooldown(true)
|
||||
.build());
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
// For some reasons this is broken.
|
||||
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "show_usage"))
|
||||
ButtonBinding.builder(new Identifier("rei", "show_usage"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action((client, button, value, action) -> {
|
||||
if (action != ButtonState.RELEASE)
|
||||
return false;
|
||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (!overlay.isPresent())
|
||||
return false;
|
||||
double mouseX = client.mouse.getX();
|
||||
double mouseY = client.mouse.getY();
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return false;
|
||||
return widget.mouseClicked(mouseX, mouseY, GLFW_MOUSE_BUTTON_2);
|
||||
})
|
||||
.action(handleShowRecipeUsage(true))
|
||||
.cooldown(true)
|
||||
.build());
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "show_recipe"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handleShowRecipeUsage(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireMouseOnScreen(Screen screen)
|
||||
{
|
||||
return isViewingScreen(screen);
|
||||
return isViewingScreen(screen) || screen instanceof PreRecipeViewingScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY)
|
||||
{
|
||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (overlay.isPresent() && overlay.get().isInside(mouseX, mouseY)) {
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return null;
|
||||
|
||||
Pair<Integer, Integer> slot = this.getSlotAt(widget, mouseX, mouseY, false);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
} else if (isViewingScreen(screen)) {
|
||||
for (Element element : screen.children()) {
|
||||
Pair<Integer, Integer> slot = this.getSlotAt(element, mouseX, mouseY, true);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty)
|
||||
{
|
||||
if (element instanceof EntryWidget) {
|
||||
EntryWidget entry = (EntryWidget) element;
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
if (!allowEmpty && entry.entries().isEmpty())
|
||||
return INVALID_SLOT;
|
||||
return Pair.of(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
|
||||
}
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
Pair<Integer, Integer> slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
|
||||
for (Element child : ((WidgetWithBounds) element).children()) {
|
||||
Pair<Integer, Integer> slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isViewingScreen(Screen screen)
|
||||
@@ -128,6 +193,76 @@ public class ReiCompat implements CompatHandler
|
||||
return ENTRY_LIST_WIDGET;
|
||||
}
|
||||
|
||||
private static @Nullable EntryStack getCurrentStack(@NotNull MinecraftClient client)
|
||||
{
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
if (isViewingScreen(client.currentScreen)) {
|
||||
for (Element element : client.currentScreen.children()) {
|
||||
EntryStack stack = getCurrentStack(element, x, y);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (!overlay.isPresent())
|
||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
|
||||
return getCurrentStack(widget, x, y);
|
||||
}
|
||||
|
||||
private static @Nullable EntryStack getCurrentStack(@NotNull Element element, double mouseX, double mouseY)
|
||||
{
|
||||
if (element instanceof EntryWidget) {
|
||||
EntryWidget entry = (EntryWidget) element;
|
||||
if (entry.containsMouse(mouseX, mouseY))
|
||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
||||
}
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
|
||||
for (Element child : ((WidgetWithBounds) element).children()) {
|
||||
EntryStack stack = getCurrentStack(child, mouseX, mouseY);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PressAction handleShowRecipeUsage(boolean usage)
|
||||
{
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
if (stack == null) {
|
||||
stack = getCurrentStack(client);
|
||||
}
|
||||
|
||||
if (stack != null && !stack.isEmpty()) {
|
||||
stack = stack.copy();
|
||||
if (usage) {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addUsagesFor(stack).setInputNotice(stack).fillPreferredOpenedCategory());
|
||||
} else {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handlePage(boolean next)
|
||||
{
|
||||
return (client, button, value, action) -> {
|
||||
@@ -175,16 +310,66 @@ public class ReiCompat implements CompatHandler
|
||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
int nextTab = currentTab + (next ? 1 : -1);
|
||||
if (nextTab < 0)
|
||||
nextTab = categories.size() - 1;
|
||||
else if (nextTab >= categories.size())
|
||||
nextTab = 0;
|
||||
screen.setSelectedCategoryIndex(nextTab);
|
||||
screen.setSelectedCategoryIndex(getNextIndex(currentTab, categories.size(), next));
|
||||
screen.setSelectedRecipeIndex(0);
|
||||
screen.lambdacontrols_init();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handleRecipe(boolean next)
|
||||
{
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
if (client.currentScreen instanceof RecipeViewingScreen) {
|
||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
||||
if (next)
|
||||
screen.getRecipeNext().onClick();
|
||||
else
|
||||
screen.getRecipeBack().onClick();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
|
||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
List<RecipeDisplay> recipes = screen.getCategoryMap().get(categories.get(currentTab));
|
||||
|
||||
if (recipes.size() == 0)
|
||||
return true;
|
||||
|
||||
int currentRecipe = screen.getSelectedRecipeIndex();
|
||||
int nextRecipe = getNextIndex(currentRecipe, recipes.size(), next);
|
||||
|
||||
if (nextRecipe == 0) {
|
||||
screen.getScrolling().scrollTo(0.0, true);
|
||||
} else if (nextRecipe == recipes.size() - 1) {
|
||||
screen.getScrolling().scrollTo(screen.getScrolling().getMaxScroll(), true);
|
||||
} else {
|
||||
double scrollAmount = screen.getScrolling().getMaxScroll() / (float) recipes.size();
|
||||
screen.getScrolling().offset(next ? scrollAmount : -scrollAmount, true);
|
||||
}
|
||||
|
||||
screen.setSelectedRecipeIndex(nextRecipe);
|
||||
screen.lambdacontrols_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static int getNextIndex(int currentIndex, int size, boolean next)
|
||||
{
|
||||
int nextIndex = currentIndex + (next ? 1 : -1);
|
||||
if (nextIndex < 0)
|
||||
nextIndex = size - 1;
|
||||
else if (nextIndex >= size)
|
||||
nextIndex = 0;
|
||||
return nextIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of LambdaControls.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.compat.mixin;
|
||||
|
||||
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
|
||||
import me.shedaniel.rei.gui.widget.EntryListWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryListWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Mixin(value = EntryListWidget.class, remap = false)
|
||||
public interface EntryListWidgetAccessor
|
||||
{
|
||||
@Accessor(value = "entries")
|
||||
List<EntryListEntryWidget> getEntries();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of LambdaControls.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.compat.mixin;
|
||||
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.gui.widget.EntryWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Mixin(value = EntryWidget.class, remap = false)
|
||||
public interface EntryWidgetAccessor
|
||||
{
|
||||
@Invoker("getCurrentEntry")
|
||||
EntryStack lambdacontrols_getCurrentEntry();
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
* Represents an accessor to REI's RecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.0
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Mixin(value = RecipeViewingScreen.class, remap = false)
|
||||
@@ -29,4 +29,10 @@ public interface RecipeViewingScreenAccessor
|
||||
|
||||
@Accessor("categoryNext")
|
||||
Button getCategoryNext();
|
||||
|
||||
@Accessor("recipeBack")
|
||||
Button getRecipeBack();
|
||||
|
||||
@Accessor("recipeNext")
|
||||
Button getRecipeNext();
|
||||
}
|
||||
|
||||
@@ -9,24 +9,30 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.compat.mixin;
|
||||
|
||||
import me.shedaniel.clothconfig2.api.ScrollingContainer;
|
||||
import me.shedaniel.rei.api.RecipeCategory;
|
||||
import me.shedaniel.rei.api.RecipeDisplay;
|
||||
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's VillagerRecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.1
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Mixin(VillagerRecipeViewingScreen.class)
|
||||
public interface VillagerRecipeViewingScreenAccessor
|
||||
{
|
||||
@Accessor(value = "categoryMap", remap = false)
|
||||
Map<RecipeCategory<?>, List<RecipeDisplay>> getCategoryMap();
|
||||
|
||||
@Accessor(value = "categories", remap = false)
|
||||
List<RecipeCategory<?>> getCategories();
|
||||
|
||||
@@ -36,6 +42,15 @@ public interface VillagerRecipeViewingScreenAccessor
|
||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
||||
void setSelectedCategoryIndex(int selectedCategoryIndex);
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
int getSelectedRecipeIndex();
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
void setSelectedRecipeIndex(int selectedRecipeIndex);
|
||||
|
||||
@Accessor(value = "scrolling", remap = false)
|
||||
ScrollingContainer getScrolling();
|
||||
|
||||
@Invoker("init")
|
||||
void lambdacontrols_init();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import static org.lwjgl.glfw.GLFW.*;
|
||||
* Represents a button binding.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @version 1.5.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ButtonBinding implements Nameable
|
||||
@@ -46,43 +46,43 @@ public class ButtonBinding implements Nameable
|
||||
public static final ButtonBinding ATTACK = new Builder("attack").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true)).onlyInGame().register();
|
||||
public static final ButtonBinding BACK = new Builder("back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding CHAT = new Builder("chat").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT).onlyInGame().cooldown(true).register();
|
||||
public static final ButtonBinding DROP_ITEM = new Builder("drop_item").buttons(GLFW_GAMEPAD_BUTTON_B).onlyInGame().cooldown(true).register();
|
||||
public static final ButtonBinding CHAT = new Builder("chat").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding DROP_ITEM = new Builder("drop_item").buttons(GLFW_GAMEPAD_BUTTON_B).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding FORWARD = new Builder("forward").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding HOTBAR_LEFT = new Builder("hotbar_left").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(false)).onlyInGame().cooldown(true).register();
|
||||
.action(InputHandlers.handleHotbar(false)).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown(true).register();
|
||||
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown(true).register();
|
||||
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
|
||||
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding PAUSE_GAME = new Builder("pause_game").buttons(GLFW_GAMEPAD_BUTTON_START).action(InputHandlers::handlePauseGame).cooldown(true).register();
|
||||
public static final ButtonBinding PICK_BLOCK = new Builder("pick_block").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT).onlyInGame().cooldown(true).register();
|
||||
public static final ButtonBinding PAUSE_GAME = new Builder("pause_game").buttons(GLFW_GAMEPAD_BUTTON_START).action(InputHandlers::handlePauseGame).cooldown().register();
|
||||
public static final ButtonBinding PICK_BLOCK = new Builder("pick_block").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding PLAYER_LIST = new Builder("player_list").buttons(GLFW_GAMEPAD_BUTTON_BACK).onlyInGame().register();
|
||||
public static final ButtonBinding RIGHT = new Builder("right").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true))
|
||||
.action(MovementHandler.HANDLER).register();
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
||||
.action(InputHandlers::handleScreenshot).cooldown(true).register();
|
||||
.action(InputHandlers::handleScreenshot).cooldown().register();
|
||||
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown(true).register();
|
||||
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
||||
.action(InputHandlers.handleInventorySlotPad(3)).onlyInInventory().cooldown(true).register();
|
||||
.action(InputHandlers.handleInventorySlotPad(3)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SLOT_RIGHT = new Builder("slot_right").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)
|
||||
.action(InputHandlers.handleInventorySlotPad(2)).onlyInInventory().cooldown(true).register();
|
||||
.action(InputHandlers.handleInventorySlotPad(2)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SLOT_UP = new Builder("slot_up").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
||||
.action(InputHandlers.handleInventorySlotPad(0)).onlyInInventory().cooldown(true).register();
|
||||
public static final ButtonBinding SMOOTH_CAMERA = new Builder("toggle_smooth_camera").cooldown(true).register();
|
||||
.action(InputHandlers.handleInventorySlotPad(0)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SMOOTH_CAMERA = new Builder("toggle_smooth_camera").onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown(true).register();
|
||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).register();
|
||||
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).cooldown(true).register();
|
||||
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).onlyInGame().register();
|
||||
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register();
|
||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
||||
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register();
|
||||
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown(true).register();
|
||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
||||
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
|
||||
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
|
||||
|
||||
private int[] button;
|
||||
@@ -267,12 +267,19 @@ public class ButtonBinding implements Nameable
|
||||
*
|
||||
* @return The key binding equivalent.
|
||||
*/
|
||||
public @NotNull
|
||||
Optional<KeyBinding> asKeyBinding()
|
||||
public @NotNull Optional<KeyBinding> asKeyBinding()
|
||||
{
|
||||
return Optional.ofNullable(this.mcKeyBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ButtonBinding{id=\"" + this.key + "\","
|
||||
+ "hasCooldown=" + this.hasCooldown
|
||||
+ "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified axis as a button.
|
||||
*
|
||||
@@ -426,11 +433,36 @@ public class ButtonBinding implements Nameable
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a builder instance.
|
||||
*
|
||||
* @param identifier The identifier of the button binding.
|
||||
* @return The builder instance
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static Builder builder(@NotNull Identifier identifier)
|
||||
{
|
||||
return new Builder(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a builder instance.
|
||||
*
|
||||
* @param identifier The identifier of the button binding.
|
||||
* @return The builder instance.
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static Builder builder(@NotNull net.minecraft.util.Identifier identifier)
|
||||
{
|
||||
return new Builder(identifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a quick {@link ButtonBinding} builder.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.1.0
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public static class Builder
|
||||
@@ -558,6 +590,17 @@ public class ButtonBinding implements Nameable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a cooldown on the {@link ButtonBinding}.
|
||||
*
|
||||
* @return The builder instance.
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public Builder cooldown()
|
||||
{
|
||||
return this.cooldown(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the category of the {@link ButtonBinding}.
|
||||
*
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.List;
|
||||
*/
|
||||
public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Entry>
|
||||
{
|
||||
private static final int[] UNBOUND = new int[0];
|
||||
private static final int[] UNBOUND = new int[]{-1};
|
||||
private final ControllerControlsScreen gui;
|
||||
private int field_2733;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ package me.lambdaurora.lambdacontrols.client.gui;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
||||
import me.lambdaurora.lambdacontrols.client.LambdaInput;
|
||||
import me.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
||||
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
||||
import me.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
@@ -29,7 +30,7 @@ import org.lwjgl.glfw.GLFW;
|
||||
* Represents the LambdaControls renderer.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.3.2
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class LambdaControlsRenderer
|
||||
@@ -251,6 +252,16 @@ public class LambdaControlsRenderer
|
||||
}
|
||||
}
|
||||
|
||||
if (!hoverSlot) {
|
||||
Pair<Integer, Integer> slot = LambdaControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
|
||||
|
||||
if (slot != null) {
|
||||
mouseX = slot.getFirst();
|
||||
mouseY = slot.getSecond();
|
||||
hoverSlot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hoverSlot) {
|
||||
mouseX -= 8;
|
||||
mouseY -= 8;
|
||||
|
||||
@@ -106,7 +106,7 @@ public abstract class MinecraftClientMixin
|
||||
}
|
||||
// Removed front placing sprinting as way too cheaty.
|
||||
/* else if (this.player.isSprinting()) {
|
||||
hitResult = this.lambdacontrols_frontBlockPlaceResult;
|
||||
hitResult = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
|
||||
if (hitResult != null) {
|
||||
if (cooldown > 0)
|
||||
this.itemUseCooldown = 0;
|
||||
@@ -136,15 +136,16 @@ public abstract class MinecraftClientMixin
|
||||
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand)
|
||||
{
|
||||
if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && LambdaControlsClient.get().reacharound.isReacharoundAvailable()) {
|
||||
LambdaControlsClient mod = LambdaControlsClient.get();
|
||||
if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && mod.reacharound.isReacharoundAvailable()) {
|
||||
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
|
||||
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
|
||||
BlockHitResult hitResult = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
|
||||
BlockHitResult hitResult = mod.reacharound.getLastReacharoundResult();
|
||||
|
||||
if (hitResult == null)
|
||||
return;
|
||||
|
||||
hitResult = LambdaReacharound.withSideForReacharound(hitResult, stackInHand);
|
||||
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
||||
|
||||
int previousStackCount = stackInHand.getCount();
|
||||
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
/**
|
||||
* Represents a mixin to WorldRenderer.
|
||||
* <p>
|
||||
* Handles the rendering of the block outline of the front block placing.
|
||||
* Handles the rendering of the block outline of the reach-around features.
|
||||
*/
|
||||
@Mixin(WorldRenderer.class)
|
||||
public abstract class WorldRendererMixin
|
||||
@@ -84,8 +84,10 @@ public abstract class WorldRendererMixin
|
||||
if (stack == null || !(stack.getItem() instanceof BlockItem))
|
||||
return;
|
||||
|
||||
LambdaControlsClient mod = LambdaControlsClient.get();
|
||||
|
||||
Block block = ((BlockItem) stack.getItem()).getBlock();
|
||||
result = LambdaReacharound.withSideForReacharound(result, block);
|
||||
result = mod.reacharound.withSideForReacharound(result, block);
|
||||
ItemPlacementContext context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
|
||||
|
||||
BlockState placementState = block.getPlacementState(context);
|
||||
@@ -94,7 +96,7 @@ public abstract class WorldRendererMixin
|
||||
Vec3d pos = camera.getPos();
|
||||
|
||||
VoxelShape outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||
int[] color = LambdaControlsClient.get().config.getReacharoundOutlineColor();
|
||||
int[] color = mod.config.getReacharoundOutlineColor();
|
||||
|
||||
VertexConsumer vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
||||
drawShapeOutline(matrices, vertexConsumer, outlineShape,
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DummyRingAction extends RingAction
|
||||
{
|
||||
public DummyRingAction(@NotNull Config config)
|
||||
{
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName()
|
||||
{
|
||||
|
||||
@@ -9,19 +9,26 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.options.KeyBinding;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class KeyBindingRingAction extends RingAction
|
||||
{
|
||||
public final KeyBinding binding;
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final KeyBinding binding;
|
||||
|
||||
public KeyBindingRingAction(@NotNull KeyBinding binding)
|
||||
public KeyBindingRingAction(@NotNull Config config, @NotNull KeyBinding binding)
|
||||
{
|
||||
super(config);
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
@@ -52,4 +59,19 @@ public class KeyBindingRingAction extends RingAction
|
||||
{
|
||||
drawCenteredText(matrices, textRenderer, new TranslatableText(this.getName()), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
|
||||
}
|
||||
|
||||
protected static class Factory implements RingAction.Factory
|
||||
{
|
||||
@Override
|
||||
public @NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen)
|
||||
{
|
||||
return () -> null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable RingAction parse(@NotNull Config config)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,27 +9,65 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Represents a key binding ring.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @version 1.5.0
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class LambdaRing
|
||||
public final class LambdaRing
|
||||
{
|
||||
public static final int ELEMENT_SIZE = 50;
|
||||
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(new RingPage()));
|
||||
private int currentPage = 0;
|
||||
public static final int ELEMENT_SIZE = 50;
|
||||
|
||||
public LambdaRing()
|
||||
private final Object2ObjectMap<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
|
||||
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT));
|
||||
private final LambdaControlsClient mod;
|
||||
private int currentPage = 0;
|
||||
|
||||
public LambdaRing(@NotNull LambdaControlsClient mod)
|
||||
{
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
public void registerAction(@NotNull String name, @NotNull RingAction.Factory factory)
|
||||
{
|
||||
if (this.actionFactories.containsKey(name)) {
|
||||
this.mod.warn("Tried to register twice a ring action: \"" + name + "\".");
|
||||
return;
|
||||
}
|
||||
this.actionFactories.put(name, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the ring from configuration.
|
||||
*
|
||||
* @param config The configuration.
|
||||
*/
|
||||
public void load(@NotNull Config config)
|
||||
{
|
||||
List<Config> configPages = config.get("ring.pages");
|
||||
if (configPages != null) {
|
||||
this.pages.clear();
|
||||
for (Config configPage : configPages) {
|
||||
RingPage.parseRingPage(configPage).ifPresent(this.pages::add);
|
||||
}
|
||||
}
|
||||
if (this.pages.isEmpty()) {
|
||||
this.pages.add(RingPage.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull RingPage getCurrentPage()
|
||||
|
||||
@@ -9,25 +9,36 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a ring action.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @version 1.5.0
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract class RingAction extends DrawableHelper implements Nameable
|
||||
{
|
||||
protected Config config;
|
||||
protected boolean activated = false;
|
||||
|
||||
public RingAction(@NotNull Config config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text name of the ring action.
|
||||
*
|
||||
@@ -64,4 +75,17 @@ public abstract class RingAction extends DrawableHelper implements Nameable
|
||||
}
|
||||
|
||||
public abstract void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered);
|
||||
|
||||
/**
|
||||
* Represents a factory for {@link RingAction}.
|
||||
*
|
||||
* @version 1.4.3
|
||||
* @since 1.4.3
|
||||
*/
|
||||
public interface Factory
|
||||
{
|
||||
@NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen);
|
||||
|
||||
@Nullable RingAction parse(@NotNull Config config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,32 +9,35 @@
|
||||
|
||||
package me.lambdaurora.lambdacontrols.client.ring;
|
||||
|
||||
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents a ring page.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @version 1.5.0
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class RingPage extends DrawableHelper
|
||||
{
|
||||
private RingAction[] actions = new RingAction[8];
|
||||
public static final RingPage DEFAULT = new RingPage("Default");
|
||||
|
||||
public RingPage()
|
||||
public final String name;
|
||||
private RingAction[] actions = new RingAction[8];
|
||||
|
||||
public RingPage(@NotNull String name)
|
||||
{
|
||||
this.name = name;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
this.actions[i] = new DummyRingAction();
|
||||
this.actions[i] = null;
|
||||
}
|
||||
this.actions[1] = new KeyBindingRingAction(LambdaControlsClient.BINDING_LOOK_UP);
|
||||
this.actions[3] = new KeyBindingRingAction(LambdaControlsClient.BINDING_LOOK_LEFT);
|
||||
this.actions[4] = new KeyBindingRingAction(LambdaControlsClient.BINDING_LOOK_RIGHT);
|
||||
this.actions[6] = new KeyBindingRingAction(LambdaControlsClient.BINDING_LOOK_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,4 +87,24 @@ public class RingPage extends DrawableHelper
|
||||
{
|
||||
return mouseX >= x && mouseY >= y && mouseX <= x + LambdaRing.ELEMENT_SIZE && mouseY <= y + LambdaRing.ELEMENT_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to parse a ring page configuration.
|
||||
*
|
||||
* @param config The configuration.
|
||||
* @return An optional ring page.
|
||||
*/
|
||||
public static @NotNull Optional<RingPage> parseRingPage(@NotNull Config config)
|
||||
{
|
||||
String name = config.get("name");
|
||||
if (name == null)
|
||||
return Optional.empty();
|
||||
|
||||
RingPage page = new RingPage(name);
|
||||
|
||||
List<Config> actionConfigs = config.get("actions");
|
||||
|
||||
|
||||
return Optional.of(page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
"plugin": "me.lambdaurora.lambdacontrols.client.compat.LambdaControlsMixinPlugin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"client": [
|
||||
"EntryListWidgetAccessor",
|
||||
"EntryWidgetAccessor",
|
||||
"RecipeViewingScreenAccessor",
|
||||
"VillagerRecipeViewingScreenAccessor"
|
||||
],
|
||||
|
||||
@@ -4,11 +4,11 @@ org.gradle.jvmargs=-Xmx1G
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/use
|
||||
minecraft_version=1.16.2
|
||||
yarn_mappings=1.16.2+build.6
|
||||
yarn_mappings=1.16.2+build.25
|
||||
loader_version=0.9.1+build.205
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.4.3
|
||||
mod_version = 1.5.0-dev2
|
||||
maven_group = me.lambdaurora.lambdacontrols
|
||||
archives_base_name = lambdacontrols
|
||||
|
||||
|
||||
@@ -36,6 +36,6 @@ public class LambdaControlsConfig
|
||||
configDir.mkdirs();
|
||||
this.config.load();
|
||||
this.plugin.log("Configuration loaded.");
|
||||
LambdaControlsFeature.FRONT_BLOCK_PLACING.setAllowed(this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING));
|
||||
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setAllowed(this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LambdaControlsSpigot extends JavaPlugin implements PluginMessageLis
|
||||
PLAYERS_CONTROLS_MODE.put(player, ControlsMode.DEFAULT);
|
||||
|
||||
this.requestPlayerControlsMode(player);
|
||||
this.updatePlayerFeature(player, LambdaControlsFeature.FRONT_BLOCK_PLACING);
|
||||
this.updatePlayerFeature(player, LambdaControlsFeature.HORIZONTAL_REACHAROUND);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public class LambdaControlsSpigot extends JavaPlugin implements PluginMessageLis
|
||||
PlayerChangeControlsModeEvent event = new PlayerChangeControlsModeEvent(player, controlsMode);
|
||||
this.getServer().getPluginManager().callEvent(event);
|
||||
});
|
||||
this.updatePlayerFeature(player, LambdaControlsFeature.FRONT_BLOCK_PLACING);
|
||||
this.updatePlayerFeature(player, LambdaControlsFeature.HORIZONTAL_REACHAROUND);
|
||||
} else if (channel.equals(CONTROLS_MODE_CHANNEL.toString())) {
|
||||
NettyPacketBuffer buffer = new NettyPacketBuffer(Unpooled.copiedBuffer(message));
|
||||
ControlsMode.byId(buffer.readString(32)).ifPresent(controlsMode -> {
|
||||
|
||||
Reference in New Issue
Block a user