1
0
mirror of https://github.com/chylex/Better-Controls.git synced 2025-01-30 22:46:04 +01:00

Compare commits

...

7 Commits

38 changed files with 274 additions and 223 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,3 +1 @@
github: chylex
patreon: chylex
ko_fi: chylex ko_fi: chylex

View File

@ -1,6 +1,8 @@
import net.fabricmc.loom.configuration.ide.RunConfigSettings
import org.gradle.jvm.tasks.Jar import org.gradle.jvm.tasks.Jar
val modId: String by project val modId: String by project
val modSides: String by project
val minecraftVersion: String by project val minecraftVersion: String by project
val fabricVersion: String by project val fabricVersion: String by project
@ -24,12 +26,24 @@ loom {
ideConfigGenerated(true) ideConfigGenerated(true)
} }
named("client") { fun side(name: String, configure: RunConfigSettings.() -> Unit) {
if (modSides == "both" || modSides == name) {
named(name, configure)
}
else {
findByName(name)?.let(::remove)
}
}
side("client") {
configName = "Fabric Client" configName = "Fabric Client"
client() client()
} }
findByName("server")?.let(::remove) side("server") {
configName = "Fabric Server"
server()
}
} }
mixin { mixin {

View File

@ -3,11 +3,10 @@ package chylex.bettercontrols.compatibility;
import chylex.bettercontrols.gui.BetterControlsScreen; import chylex.bettercontrols.gui.BetterControlsScreen;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi; import com.terraformersmc.modmenu.api.ModMenuApi;
import net.minecraft.client.Minecraft;
public class ModMenuSupport implements ModMenuApi { public class ModMenuSupport implements ModMenuApi {
@Override @Override
public ConfigScreenFactory<?> getModConfigScreenFactory() { public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parentScreen -> new BetterControlsScreen(Minecraft.getInstance(), parentScreen); return BetterControlsScreen::new;
} }
} }

View File

@ -1,4 +1,7 @@
import net.neoforged.moddevgradle.dsl.RunModel
val modId: String by project val modId: String by project
val modSides: String by project
val neoForgeVersion: String by project val neoForgeVersion: String by project
plugins { plugins {
@ -23,10 +26,21 @@ neoForge {
jvmArguments.addAll(runJvmArgs) jvmArguments.addAll(runJvmArgs)
} }
register("client") { fun side(name: String, configure: RunModel.() -> Unit) {
if (modSides == "both" || modSides == name) {
register(name, configure)
}
}
side("client") {
ideName.set("NeoForge Client") ideName.set("NeoForge Client")
client() client()
} }
side("server") {
ideName.set("NeoForge Server")
server()
}
} }
} }

View File

@ -2,19 +2,26 @@ package chylex.bettercontrols;
import chylex.bettercontrols.config.BetterControlsConfig; import chylex.bettercontrols.config.BetterControlsConfig;
import chylex.bettercontrols.gui.BetterControlsScreen; import chylex.bettercontrols.gui.BetterControlsScreen;
import net.minecraft.client.gui.screens.Screen;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import javax.annotation.Nullable;
@Mod("bettercontrols") @Mod("bettercontrols")
public final class BetterControlsMod { public final class BetterControlsMod {
public BetterControlsMod() { public BetterControlsMod() {
if (FMLEnvironment.dist == Dist.CLIENT) { if (FMLEnvironment.dist == Dist.CLIENT) {
BetterControlsCommon.setConfig(BetterControlsConfig.load(FMLPaths.CONFIGDIR.get().resolve("BetterControls.json"))); BetterControlsCommon.setConfig(BetterControlsConfig.load(FMLPaths.CONFIGDIR.get().resolve("BetterControls.json")));
ModLoadingContext.get().registerExtensionPoint(IConfigScreenFactory.class, () -> BetterControlsScreen::new); ModLoadingContext.get().registerExtensionPoint(IConfigScreenFactory.class, () -> BetterControlsMod::createOptionsScreen);
} }
} }
private static BetterControlsScreen createOptionsScreen(ModContainer modContainer, @Nullable Screen parentScreen) {
return new BetterControlsScreen(parentScreen);
}
} }

View File

@ -14,6 +14,7 @@ val modSides: String by project
val minecraftVersion: String by project val minecraftVersion: String by project
val mixinVersion: String by project val mixinVersion: String by project
val mixinExtrasVersion: String by project
val minimumMinecraftVersion: String by project val minimumMinecraftVersion: String by project
val minimumNeoForgeVersion: String by project val minimumNeoForgeVersion: String by project
@ -65,6 +66,8 @@ dependencies {
mappings(loom.officialMojangMappings()) mappings(loom.officialMojangMappings())
compileOnly("net.fabricmc:sponge-mixin:$mixinVersion") compileOnly("net.fabricmc:sponge-mixin:$mixinVersion")
compileOnly("io.github.llamalad7:mixinextras-common:$mixinExtrasVersion")
api("com.google.code.findbugs:jsr305:3.0.2") api("com.google.code.findbugs:jsr305:3.0.2")
} }

View File

@ -10,21 +10,23 @@ modIssuesURL=https://github.com/chylex/Better-Controls/issues
modSides=client modSides=client
# Dependencies # Dependencies
minecraftVersion=1.21 minecraftVersion=1.21.4
neoForgeVersion=21.0.0-beta neoForgeVersion=21.4.77-beta
neoModDevVersion=1.0.10 neoModDevVersion=2.0.76
fabricVersion=0.15.11 fabricVersion=0.16.10
loomVersion=1.7 loomVersion=1.9
mixinVersion=0.12.5+mixin.0.8.5 mixinVersion=0.12.5+mixin.0.8.5
mixinExtrasVersion=0.4.1
# https://projects.neoforged.net/neoforged/neoforge
# https://projects.neoforged.net/neoforged/moddevgradle # https://projects.neoforged.net/neoforged/moddevgradle
# https://fabricmc.net/develop/ # https://fabricmc.net/develop/
# https://github.com/FabricMC/fabric-loom/releases # https://github.com/FabricMC/fabric-loom/releases
# Constraints # Constraints
minimumMinecraftVersion=1.21 minimumMinecraftVersion=1.21.4
minimumNeoForgeVersion=21.0.0-beta minimumNeoForgeVersion=21.4.0-beta
minimumFabricVersion=0.12.3 minimumFabricVersion=0.15.0
# Gradle # Gradle
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

4
gradlew vendored
View File

@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum

2
gradlew.bat vendored
View File

@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################

View File

@ -9,7 +9,7 @@ public final class BetterControlsCommon {
return config; return config;
} }
static void setConfig(final BetterControlsConfig config) { static void setConfig(BetterControlsConfig config) {
BetterControlsCommon.config = config; BetterControlsCommon.config = config;
} }

View File

@ -5,8 +5,8 @@ import chylex.bettercontrols.input.SprintMode;
import java.nio.file.Path; import java.nio.file.Path;
public final class BetterControlsConfig { public final class BetterControlsConfig {
public static BetterControlsConfig load(final Path path) { public static BetterControlsConfig load(Path path) {
final BetterControlsConfig cfg = ConfigSerializer.read(path); BetterControlsConfig cfg = ConfigSerializer.read(path);
cfg.path = path; cfg.path = path;
if (cfg.wasMigrated) { if (cfg.wasMigrated) {

View File

@ -30,8 +30,8 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
private ConfigSerializer() {} private ConfigSerializer() {}
@Override @Override
public JsonElement serialize(final BetterControlsConfig cfg, final Type typeOfSrc, final JsonSerializationContext context) { public JsonElement serialize(BetterControlsConfig cfg, Type typeOfSrc, JsonSerializationContext context) {
final JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
Json.writeKeyBinding(obj, "Sprint.KeyToggle", cfg.keyToggleSprint); Json.writeKeyBinding(obj, "Sprint.KeyToggle", cfg.keyToggleSprint);
Json.setEnum(obj, "Sprint.Mode", cfg.sprintMode); Json.setEnum(obj, "Sprint.Mode", cfg.sprintMode);
@ -64,9 +64,9 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
} }
@Override @Override
public BetterControlsConfig deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { public BetterControlsConfig deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final BetterControlsConfig cfg = new BetterControlsConfig(); BetterControlsConfig cfg = new BetterControlsConfig();
final JsonObject obj = json.getAsJsonObject(); JsonObject obj = json.getAsJsonObject();
if (obj.has("Sprint.TapToStop") && obj.get("Sprint.TapToStop").getAsBoolean()) { if (obj.has("Sprint.TapToStop") && obj.get("Sprint.TapToStop").getAsBoolean()) {
cfg.sprintMode = SprintMode.TAP_TO_TOGGLE; cfg.sprintMode = SprintMode.TAP_TO_TOGGLE;
@ -102,18 +102,18 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
return cfg; return cfg;
} }
private static float readHorizontalSpeedMultiplier(final JsonObject obj, final String key, final float defaultValue) { private static float readHorizontalSpeedMultiplier(JsonObject obj, String key, float defaultValue) {
return Json.getFloat(obj, key, defaultValue, 0.25F, 8F); return Json.getFloat(obj, key, defaultValue, 0.25F, 8F);
} }
private static float readVerticalSpeedMultiplier(final JsonObject obj, final BetterControlsConfig cfg, final String newKey, final String legacyBoostKey, final float defaultValue) { private static float readVerticalSpeedMultiplier(JsonObject obj, BetterControlsConfig cfg, String newKey, String legacyBoostKey, float defaultValue) {
if (obj.has(newKey)) { if (obj.has(newKey)) {
return Json.getFloat(obj, newKey, defaultValue, 0.25F, 8F); return Json.getFloat(obj, newKey, defaultValue, 0.25F, 8F);
} }
else if (obj.has(legacyBoostKey)) { else if (obj.has(legacyBoostKey)) {
cfg.wasMigrated = true; cfg.wasMigrated = true;
final float value = 1F + Json.getFloat(obj, legacyBoostKey, 0F, 0F, 3F); float value = 1F + Json.getFloat(obj, legacyBoostKey, 0F, 0F, 3F);
// 1.25x, 1.75x, 2.5x, and 3.5x are not supported // 1.25x, 1.75x, 2.5x, and 3.5x are not supported
if (Mth.equal(value, 1.25F) || Mth.equal(value, 1.75F)) { if (Mth.equal(value, 1.25F) || Mth.equal(value, 1.75F)) {
return 1.5F; return 1.5F;
@ -133,19 +133,19 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
} }
} }
static void write(final Path path, final BetterControlsConfig config) { static void write(Path path, BetterControlsConfig config) {
try (final JsonWriter writer = gson.newJsonWriter(Files.newBufferedWriter(path, StandardCharsets.UTF_8))) { try (JsonWriter writer = gson.newJsonWriter(Files.newBufferedWriter(path, StandardCharsets.UTF_8))) {
gson.getAdapter(BetterControlsConfig.class).write(writer, config); gson.getAdapter(BetterControlsConfig.class).write(writer, config);
} catch (final IOException e) { } catch (IOException e) {
logger.error("Error saving BetterControls configuration file!", e); logger.error("Error saving BetterControls configuration file!", e);
} }
} }
static BetterControlsConfig read(final Path path) { static BetterControlsConfig read(Path path) {
try (final JsonReader jsonReader = new JsonReader(Files.newBufferedReader(path, StandardCharsets.UTF_8))) { try (JsonReader jsonReader = new JsonReader(Files.newBufferedReader(path, StandardCharsets.UTF_8))) {
return gson.getAdapter(BetterControlsConfig.class).read(jsonReader); return gson.getAdapter(BetterControlsConfig.class).read(jsonReader);
} catch (final FileNotFoundException | NoSuchFileException ignored) { } catch (FileNotFoundException | NoSuchFileException ignored) {
} catch (final IOException e) { } catch (IOException e) {
logger.error("Error reading BetterControls configuration file!", e); logger.error("Error reading BetterControls configuration file!", e);
} }

View File

@ -8,40 +8,40 @@ import com.mojang.blaze3d.platform.InputConstants;
final class Json { final class Json {
private Json() {} private Json() {}
static void setFloat(final JsonObject obj, final String key, final float value) { static void setFloat(JsonObject obj, String key, float value) {
obj.addProperty(key, Float.valueOf(value)); obj.addProperty(key, Float.valueOf(value));
} }
static float getFloat(final JsonObject obj, final String key, final float defaultValue, final float minValue, final float maxValue) { static float getFloat(JsonObject obj, String key, float defaultValue, float minValue, float maxValue) {
final float value = obj.has(key) ? obj.get(key).getAsFloat() : defaultValue; float value = obj.has(key) ? obj.get(key).getAsFloat() : defaultValue;
return Math.max(minValue, Math.min(maxValue, value)); return Math.max(minValue, Math.min(maxValue, value));
} }
static void setBool(final JsonObject obj, final String key, final boolean value) { static void setBool(JsonObject obj, String key, boolean value) {
obj.addProperty(key, Boolean.valueOf(value)); obj.addProperty(key, Boolean.valueOf(value));
} }
static boolean getBool(final JsonObject obj, final String key, final boolean defaultValue) { static boolean getBool(JsonObject obj, String key, boolean defaultValue) {
return obj.has(key) ? obj.get(key).getAsBoolean() : defaultValue; return obj.has(key) ? obj.get(key).getAsBoolean() : defaultValue;
} }
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
static <T extends Enum<T>> void setEnum(final JsonObject obj, final String key, final T value) { static <T extends Enum<T>> void setEnum(JsonObject obj, String key, T value) {
obj.addProperty(key, value.name()); obj.addProperty(key, value.name());
} }
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
static <T extends Enum<T>> T getEnum(final JsonObject obj, final String key, final T defaultValue, final Class<T> enumClass) { static <T extends Enum<T>> T getEnum(JsonObject obj, String key, T defaultValue, Class<T> enumClass) {
if (!obj.has(key)) { if (!obj.has(key)) {
return defaultValue; return defaultValue;
} }
final T[] constants = enumClass.getEnumConstants(); T[] constants = enumClass.getEnumConstants();
if (constants != null) { if (constants != null) {
final String value = obj.get(key).getAsString(); String value = obj.get(key).getAsString();
for (final T constant : constants) { for (T constant : constants) {
if (constant.name().equalsIgnoreCase(value)) { if (constant.name().equalsIgnoreCase(value)) {
return constant; return constant;
} }
@ -54,7 +54,7 @@ final class Json {
private static final String KEY_SUFFIX = ".Key"; private static final String KEY_SUFFIX = ".Key";
private static final String MOD_SUFFIX = ".Mod"; private static final String MOD_SUFFIX = ".Mod";
static void writeKeyBinding(final JsonObject obj, final String key, final KeyBindingWithModifier keyBinding) { static void writeKeyBinding(JsonObject obj, String key, KeyBindingWithModifier keyBinding) {
obj.addProperty(key + KEY_SUFFIX, keyBinding.saveString()); obj.addProperty(key + KEY_SUFFIX, keyBinding.saveString());
if (keyBinding.getModifier() != null) { if (keyBinding.getModifier() != null) {
@ -62,11 +62,11 @@ final class Json {
} }
} }
static void readKeyBinding(final JsonObject obj, final String key, final KeyBindingWithModifier keyBinding) { static void readKeyBinding(JsonObject obj, String key, KeyBindingWithModifier keyBinding) {
if (obj.has(key + KEY_SUFFIX)) { if (obj.has(key + KEY_SUFFIX)) {
try { try {
keyBinding.setKey(InputConstants.getKey(obj.get(key + KEY_SUFFIX).getAsString())); keyBinding.setKey(InputConstants.getKey(obj.get(key + KEY_SUFFIX).getAsString()));
} catch (final IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); // let's not crash if the config file has garbage, okay? e.printStackTrace(); // let's not crash if the config file has garbage, okay?
} }
} }

View File

@ -34,7 +34,7 @@ import static chylex.bettercontrols.gui.elements.TextWidget.CENTER;
import static net.minecraft.network.chat.Component.literal; import static net.minecraft.network.chat.Component.literal;
public class BetterControlsScreen extends OptionsSubScreen { public class BetterControlsScreen extends OptionsSubScreen {
private static Component text(final String text) { private static Component text(String text) {
return literal(text); return literal(text);
} }
@ -53,8 +53,8 @@ public class BetterControlsScreen extends OptionsSubScreen {
// Options // Options
private int generateSprintingOptions(int y, final List<GuiEventListener> elements) { private int generateSprintingOptions(int y, List<GuiEventListener> elements) {
final BetterControlsConfig cfg = BetterControlsCommon.getConfig(); BetterControlsConfig cfg = BetterControlsCommon.getConfig();
generateKeyBindingWithModifierRow(y, elements, text("Toggle Sprint"), cfg.keyToggleSprint); generateKeyBindingWithModifierRow(y, elements, text("Toggle Sprint"), cfg.keyToggleSprint);
y += ROW_HEIGHT; y += ROW_HEIGHT;
@ -71,8 +71,8 @@ public class BetterControlsScreen extends OptionsSubScreen {
return y; return y;
} }
private int generateSneakingOptions(int y, final List<GuiEventListener> elements) { private int generateSneakingOptions(int y, List<GuiEventListener> elements) {
final BetterControlsConfig cfg = BetterControlsCommon.getConfig(); BetterControlsConfig cfg = BetterControlsCommon.getConfig();
generateKeyBindingWithModifierRow(y, elements, text("Toggle Sneak"), cfg.keyToggleSneak); generateKeyBindingWithModifierRow(y, elements, text("Toggle Sneak"), cfg.keyToggleSneak);
y += ROW_HEIGHT; y += ROW_HEIGHT;
@ -83,10 +83,10 @@ public class BetterControlsScreen extends OptionsSubScreen {
return y; return y;
} }
private int generateFlightOptions(int y, final List<GuiEventListener> elements) { private int generateFlightOptions(int y, List<GuiEventListener> elements) {
final BetterControlsConfig cfg = BetterControlsCommon.getConfig(); BetterControlsConfig cfg = BetterControlsCommon.getConfig();
final ImmutableList<Option<Float>> flightSpeedOptions = ImmutableList.of( ImmutableList<Option<Float>> flightSpeedOptions = ImmutableList.of(
new Option<>(Float.valueOf(0.25F), text("0.25x")), new Option<>(Float.valueOf(0.25F), text("0.25x")),
new Option<>(Float.valueOf(0.50F), text("0.5x")), new Option<>(Float.valueOf(0.50F), text("0.5x")),
new Option<>(Float.valueOf(0.75F), text("0.75x")), new Option<>(Float.valueOf(0.75F), text("0.75x")),
@ -144,8 +144,8 @@ public class BetterControlsScreen extends OptionsSubScreen {
return y; return y;
} }
private int generateMiscellaneousOptions(int y, final List<GuiEventListener> elements) { private int generateMiscellaneousOptions(int y, List<GuiEventListener> elements) {
final BetterControlsConfig cfg = BetterControlsCommon.getConfig(); BetterControlsConfig cfg = BetterControlsCommon.getConfig();
generateKeyBindingWithModifierRow(y, elements, text("Toggle Walk Forwards"), cfg.keyToggleWalkForward); generateKeyBindingWithModifierRow(y, elements, text("Toggle Walk Forwards"), cfg.keyToggleWalkForward);
y += ROW_HEIGHT; y += ROW_HEIGHT;
@ -171,9 +171,9 @@ public class BetterControlsScreen extends OptionsSubScreen {
new Option<>(ModifierKey.ALT, text("Alt")) new Option<>(ModifierKey.ALT, text("Alt"))
); );
private void generateKeyBindingWithModifierRow(final int y, final List<GuiEventListener> elements, final Component text, final KeyBindingWithModifier binding) { private void generateKeyBindingWithModifierRow(int y, List<GuiEventListener> elements, Component text, KeyBindingWithModifier binding) {
final var modifierButton = Option.button(col4(2), y, COL4_W, text.plainCopy().append(" Modifier"), MODIFIER_OPTIONS, binding.getModifier(), binding::setModifier); var modifierButton = Option.button(col4(2), y, COL4_W, text.plainCopy().append(" Modifier"), MODIFIER_OPTIONS, binding.getModifier(), binding::setModifier);
final var bindingButton = new KeyBindingWidget(col4(3), y, COL4_W, text, binding, this::startEditingKeyBinding); var bindingButton = new KeyBindingWidget(col4(3), y, COL4_W, text, binding, this::startEditingKeyBinding);
bindingButton.linkButtonToBoundState(modifierButton); bindingButton.linkButtonToBoundState(modifierButton);
generateLeftSideText(y, elements, text); generateLeftSideText(y, elements, text);
@ -182,12 +182,12 @@ public class BetterControlsScreen extends OptionsSubScreen {
allKeyBindings.add(bindingButton); allKeyBindings.add(bindingButton);
} }
private static <T> void generateCycleOptionRow(final int y, final List<GuiEventListener> elements, final Component text, final List<Option<T>> options, final T initialValue, final Consumer<T> onValueChanged) { private static <T> void generateCycleOptionRow(int y, List<GuiEventListener> elements, Component text, List<Option<T>> options, T initialValue, Consumer<T> onValueChanged) {
generateLeftSideText(y, elements, text); generateLeftSideText(y, elements, text);
elements.add(Option.button(col2(1), y, COL2_W, text, options, initialValue, onValueChanged)); elements.add(Option.button(col2(1), y, COL2_W, text, options, initialValue, onValueChanged));
} }
private static void generateBooleanOptionRow(final int y, final List<GuiEventListener> elements, final Component text, final boolean initialValue, final BooleanConsumer onValueChanged) { private static void generateBooleanOptionRow(int y, List<GuiEventListener> elements, Component text, boolean initialValue, BooleanConsumer onValueChanged) {
generateLeftSideText(y, elements, text); generateLeftSideText(y, elements, text);
elements.add(CycleButton.onOffBuilder() elements.add(CycleButton.onOffBuilder()
.displayOnlyValue() .displayOnlyValue()
@ -195,7 +195,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
.create(col2(1), y, COL2_W, 20, text, (btn, newValue) -> onValueChanged.accept(newValue.booleanValue()))); .create(col2(1), y, COL2_W, 20, text, (btn, newValue) -> onValueChanged.accept(newValue.booleanValue())));
} }
private static void generateLeftSideText(final int y, final List<GuiEventListener> elements, final Component text) { private static void generateLeftSideText(int y, List<GuiEventListener> elements, Component text) {
elements.add(new TextWidget(col2(0), y, COL2_W - TEXT_PADDING_RIGHT, text)); elements.add(new TextWidget(col2(0), y, COL2_W - TEXT_PADDING_RIGHT, text));
} }
@ -206,15 +206,15 @@ public class BetterControlsScreen extends OptionsSubScreen {
private final List<KeyBindingWidget> allKeyBindings = new ArrayList<>(); private final List<KeyBindingWidget> allKeyBindings = new ArrayList<>();
@SuppressWarnings("DataFlowIssue") @SuppressWarnings("DataFlowIssue")
public BetterControlsScreen(final Minecraft mc, @Nullable final Screen parentScreen) { public BetterControlsScreen(@Nullable Screen parentScreen) {
super(parentScreen, mc.options, TITLE); super(parentScreen, Minecraft.getInstance().options, TITLE);
} }
@Override @Override
protected void addContents() { protected void addContents() {
allKeyBindings.clear(); allKeyBindings.clear();
final List<GuiEventListener> elements = new ArrayList<>(); List<GuiEventListener> elements = new ArrayList<>();
int y = 0; int y = 0;
elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Sprinting"), CENTER)); elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Sprinting"), CENTER));
@ -249,7 +249,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
BetterControlsCommon.getConfig().save(); BetterControlsCommon.getConfig().save();
} }
private void startEditingKeyBinding(final KeyBindingWidget widget) { private void startEditingKeyBinding(KeyBindingWidget widget) {
if (editingKeyBinding != null) { if (editingKeyBinding != null) {
editingKeyBinding.stopEditing(); editingKeyBinding.stopEditing();
} }
@ -258,7 +258,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
} }
@Override @Override
public boolean mouseClicked(final double mouseX, final double mouseY, final int button) { public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (editingKeyBinding != null) { if (editingKeyBinding != null) {
editingKeyBinding.bindAndStopEditing(InputConstants.Type.MOUSE.getOrCreate(button)); editingKeyBinding.bindAndStopEditing(InputConstants.Type.MOUSE.getOrCreate(button));
onKeyBindingEditingFinished(); onKeyBindingEditingFinished();
@ -270,7 +270,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
} }
@Override @Override
public boolean keyPressed(final int keyCode, final int scanCode, final int modifiers) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (editingKeyBinding != null) { if (editingKeyBinding != null) {
if (keyCode == GLFW.GLFW_KEY_ESCAPE) { if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
editingKeyBinding.bindAndStopEditing(InputConstants.UNKNOWN); editingKeyBinding.bindAndStopEditing(InputConstants.UNKNOWN);
@ -291,7 +291,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
editingKeyBinding = null; editingKeyBinding = null;
KeyMapping.resetMapping(); KeyMapping.resetMapping();
for (final KeyBindingWidget widget : allKeyBindings) { for (KeyBindingWidget widget : allKeyBindings) {
widget.updateKeyBindingText(); widget.updateKeyBindingText();
} }
} }

View File

@ -25,19 +25,19 @@ public final class OptionListWidget extends ContainerObjectSelectionList<Entry>
public static final int COL2_W = (ROW_WIDTH / 2) - ROW_HORIZONTAL_PADDING; public static final int COL2_W = (ROW_WIDTH / 2) - ROW_HORIZONTAL_PADDING;
public static final int COL4_W = (ROW_WIDTH / 4) - ROW_HORIZONTAL_PADDING; public static final int COL4_W = (ROW_WIDTH / 4) - ROW_HORIZONTAL_PADDING;
public static int col2(final int column) { public static int col2(int column) {
return (column * ROW_WIDTH) / 2; return (column * ROW_WIDTH) / 2;
} }
public static int col4(final int column) { public static int col4(int column) {
return (column * ROW_WIDTH) / 4; return (column * ROW_WIDTH) / 4;
} }
private static Offset getElementOffset(final GuiEventListener element) { private static Offset getElementOffset(GuiEventListener element) {
if (element instanceof final OptionWidget widget) { if (element instanceof OptionWidget widget) {
return new Offset(widget.getX(), widget.getY()); return new Offset(widget.getX(), widget.getY());
} }
else if (element instanceof final AbstractWidget widget) { else if (element instanceof AbstractWidget widget) {
return new Offset(widget.getX(), widget.getY()); return new Offset(widget.getX(), widget.getY());
} }
else { else {
@ -54,7 +54,7 @@ public final class OptionListWidget extends ContainerObjectSelectionList<Entry>
private record Offset(int x, int y) {} private record Offset(int x, int y) {}
public OptionListWidget(final int width, final int height, final int top, final int innerHeight, final List<GuiEventListener> widgets) { public OptionListWidget(int width, int height, int top, int innerHeight, List<GuiEventListener> widgets) {
super(Minecraft.getInstance(), width, height, top, innerHeight); super(Minecraft.getInstance(), width, height, top, innerHeight);
addEntry(new Entry(widgets)); addEntry(new Entry(widgets));
} }
@ -70,13 +70,13 @@ public final class OptionListWidget extends ContainerObjectSelectionList<Entry>
} }
@Override @Override
protected int getScrollbarPosition() { protected int scrollBarX() {
return (width + ROW_WIDTH) / 2 + 4; return (width + ROW_WIDTH) / 2 + 4;
} }
@Override @Override
public boolean mouseScrolled(final double x, final double y, final double xAmount, final double yAmount) { public boolean mouseScrolled(double x, double y, double xAmount, double yAmount) {
setScrollAmount(getScrollAmount() - yAmount * SCROLL_MULTIPLIER); setScrollAmount(scrollAmount() - yAmount * SCROLL_MULTIPLIER);
return true; return true;
} }
@ -85,7 +85,7 @@ public final class OptionListWidget extends ContainerObjectSelectionList<Entry>
private final List<NarratableEntry> narratables; private final List<NarratableEntry> narratables;
private final Map<GuiEventListener, Offset> offsets; private final Map<GuiEventListener, Offset> offsets;
public Entry(final List<GuiEventListener> elements) { public Entry(List<GuiEventListener> elements) {
this.elements = new ArrayList<>(elements); this.elements = new ArrayList<>(elements);
this.narratables = elements.stream().filter(e -> e instanceof NarratableEntry).map(e -> (NarratableEntry)e).collect(Collectors.toList()); this.narratables = elements.stream().filter(e -> e instanceof NarratableEntry).map(e -> (NarratableEntry)e).collect(Collectors.toList());
this.offsets = elements.stream().collect(Collectors.toMap(Function.identity(), OptionListWidget::getElementOffset)); this.offsets = elements.stream().collect(Collectors.toMap(Function.identity(), OptionListWidget::getElementOffset));
@ -104,20 +104,20 @@ public final class OptionListWidget extends ContainerObjectSelectionList<Entry>
} }
@Override @Override
public void render(final @NotNull GuiGraphics graphics, final int index, final int y, final int x, final int entryWidth, final int entryHeight, final int mouseX, final int mouseY, final boolean hovered, final float tickDelta) { public void render(@NotNull GuiGraphics graphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
for (final GuiEventListener element : elements) { for (GuiEventListener element : elements) {
final Offset offset = offsets.get(element); Offset offset = offsets.get(element);
if (element instanceof final AbstractWidget widget) { if (element instanceof AbstractWidget widget) {
widget.setX(x + offset.x); widget.setX(x + offset.x);
widget.setY(y + offset.y); widget.setY(y + offset.y);
} }
else if (element instanceof final OptionWidget widget) { else if (element instanceof OptionWidget widget) {
widget.setX(x + offset.x); widget.setX(x + offset.x);
widget.setY(y + offset.y); widget.setY(y + offset.y);
} }
if (element instanceof final Renderable renderable) { if (element instanceof Renderable renderable) {
renderable.render(graphics, mouseX, mouseY, tickDelta); renderable.render(graphics, mouseX, mouseY, tickDelta);
} }
} }

View File

@ -14,7 +14,7 @@ public final class DiscreteValueSliderWidget<T> extends AbstractSliderButton {
private final Consumer<T> onChanged; private final Consumer<T> onChanged;
private T selectedValue; private T selectedValue;
public DiscreteValueSliderWidget(final int x, final int y, final int width, final int height, final Component narration, final ImmutableList<Option<T>> options, final T selectedValue, final Consumer<T> onChanged) { public DiscreteValueSliderWidget(int x, int y, int width, int height, Component narration, ImmutableList<Option<T>> options, T selectedValue, Consumer<T> onChanged) {
super(x, y, width, height, Option.find(options, selectedValue).text(), options.indexOf(Option.find(options, selectedValue)) / (options.size() - 1.0)); super(x, y, width, height, Option.find(options, selectedValue).text(), options.indexOf(Option.find(options, selectedValue)) / (options.size() - 1.0));
this.narration = narration; this.narration = narration;
this.options = options; this.options = options;
@ -22,7 +22,7 @@ public final class DiscreteValueSliderWidget<T> extends AbstractSliderButton {
this.onChanged = onChanged; this.onChanged = onChanged;
} }
public DiscreteValueSliderWidget(final int x, final int y, final int width, final Component narration, final ImmutableList<Option<T>> options, final T selectedValue, final Consumer<T> onChanged) { public DiscreteValueSliderWidget(int x, int y, int width, Component narration, ImmutableList<Option<T>> options, T selectedValue, Consumer<T> onChanged) {
this(x, y, width, 20, narration, options, selectedValue, onChanged); this(x, y, width, 20, narration, options, selectedValue, onChanged);
} }
@ -37,7 +37,7 @@ public final class DiscreteValueSliderWidget<T> extends AbstractSliderButton {
@Override @Override
protected void applyValue() { protected void applyValue() {
final T newSelectedValue = getSelectedOption().value(); T newSelectedValue = getSelectedOption().value();
if (selectedValue != newSelectedValue) { if (selectedValue != newSelectedValue) {
selectedValue = newSelectedValue; selectedValue = newSelectedValue;

View File

@ -22,7 +22,7 @@ public final class KeyBindingWidget extends Button {
private final Consumer<KeyBindingWidget> onEditingStarted; private final Consumer<KeyBindingWidget> onEditingStarted;
private boolean isEditing; private boolean isEditing;
public KeyBindingWidget(final int x, final int y, final int width, final int height, final Component bindingName, final KeyMapping binding, final Consumer<KeyBindingWidget> onEditingStarted) { public KeyBindingWidget(int x, int y, int width, int height, Component bindingName, KeyMapping binding, Consumer<KeyBindingWidget> onEditingStarted) {
super(x, y, width, height, Component.empty(), btn -> {}, DEFAULT_NARRATION); super(x, y, width, height, Component.empty(), btn -> {}, DEFAULT_NARRATION);
this.binding = binding; this.binding = binding;
this.bindingName = bindingName; this.bindingName = bindingName;
@ -30,11 +30,11 @@ public final class KeyBindingWidget extends Button {
updateKeyBindingText(); updateKeyBindingText();
} }
public KeyBindingWidget(final int x, final int y, final int width, final Component bindingName, final KeyMapping binding, final Consumer<KeyBindingWidget> onEditingStarted) { public KeyBindingWidget(int x, int y, int width, Component bindingName, KeyMapping binding, Consumer<KeyBindingWidget> onEditingStarted) {
this(x, y, width, 20, bindingName, binding, onEditingStarted); this(x, y, width, 20, bindingName, binding, onEditingStarted);
} }
public void linkButtonToBoundState(final AbstractButton button) { public void linkButtonToBoundState(AbstractButton button) {
linkedButtons.add(button); linkedButtons.add(button);
button.active = !binding.isUnbound(); button.active = !binding.isUnbound();
} }
@ -52,11 +52,11 @@ public final class KeyBindingWidget extends Button {
updateKeyBindingText(); updateKeyBindingText();
} }
public void bindAndStopEditing(final InputConstants.Key key) { public void bindAndStopEditing(InputConstants.Key key) {
binding.setKey(key); binding.setKey(key);
stopEditing(); stopEditing();
for (final AbstractButton button : linkedButtons) { for (AbstractButton button : linkedButtons) {
button.active = !binding.isUnbound(); button.active = !binding.isUnbound();
} }
} }
@ -70,7 +70,7 @@ public final class KeyBindingWidget extends Button {
boolean hasConflict = false; boolean hasConflict = false;
if (!binding.isUnbound()) { if (!binding.isUnbound()) {
for (final KeyMapping other : Minecraft.getInstance().options.keyMappings) { for (KeyMapping other : Minecraft.getInstance().options.keyMappings) {
if (binding != other && binding.same(other)) { if (binding != other && binding.same(other)) {
hasConflict = true; hasConflict = true;
break; break;

View File

@ -7,11 +7,11 @@ import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
public record Option<T>(T value, Component text) { public record Option<T>(T value, Component text) {
public static <T> Option<T> find(final List<Option<T>> options, final T value) { public static <T> Option<T> find(List<Option<T>> options, T value) {
return options.stream().filter(it -> Objects.equals(it.value, value)).findFirst().orElseGet(() -> options.get(0)); return options.stream().filter(it -> Objects.equals(it.value, value)).findFirst().orElseGet(() -> options.get(0));
} }
public static <T> CycleButton<Option<T>> button(final int x, final int y, final int width, final Component text, final List<Option<T>> options, final T initialValue, final Consumer<T> onValueChanged) { public static <T> CycleButton<Option<T>> button(int x, int y, int width, Component text, List<Option<T>> options, T initialValue, Consumer<T> onValueChanged) {
return CycleButton.<Option<T>>builder(Option::text) return CycleButton.<Option<T>>builder(Option::text)
.displayOnlyValue() .displayOnlyValue()
.withValues(options) .withValues(options)

View File

@ -22,7 +22,7 @@ public final class TextWidget implements OptionWidget {
private final int height; private final int height;
private final int align; private final int align;
public TextWidget(final int x, final int y, final int width, final int height, final Component text, final int align) { public TextWidget(int x, int y, int width, int height, Component text, int align) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.width = width; this.width = width;
@ -31,11 +31,11 @@ public final class TextWidget implements OptionWidget {
this.align = align; this.align = align;
} }
public TextWidget(final int x, final int y, final int width, final Component text, final int align) { public TextWidget(int x, int y, int width, Component text, int align) {
this(x, y, width, 20, text, align); this(x, y, width, 20, text, align);
} }
public TextWidget(final int x, final int y, final int width, final Component text) { public TextWidget(int x, int y, int width, Component text) {
this(x, y, width, 20, text, LEFT); this(x, y, width, 20, text, LEFT);
} }
@ -50,17 +50,17 @@ public final class TextWidget implements OptionWidget {
} }
@Override @Override
public void setX(final int x) { public void setX(int x) {
this.x = x; this.x = x;
} }
@Override @Override
public void setY(final int y) { public void setY(int y) {
this.y = y; this.y = y;
} }
@Override @Override
public void setFocused(final boolean focused) {} public void setFocused(boolean focused) {}
@Override @Override
public boolean isFocused() { public boolean isFocused() {
@ -68,13 +68,13 @@ public final class TextWidget implements OptionWidget {
} }
@Override @Override
public void render(final @NotNull GuiGraphics graphics, final int mouseX, final int mouseY, final float delta) { public void render(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float delta) {
final Font textRenderer = Minecraft.getInstance().font; Font textRenderer = Minecraft.getInstance().font;
final List<FormattedCharSequence> lines = textRenderer.split(text, width); List<FormattedCharSequence> lines = textRenderer.split(text, width);
final int lineHeight = textRenderer.lineHeight + 1; final int lineHeight = textRenderer.lineHeight + 1;
final int finalX = align == CENTER ? x + (width / 2) - (lines.stream().mapToInt(textRenderer::width).max().orElse(0) / 2) : x; int finalX = align == CENTER ? x + (width / 2) - (lines.stream().mapToInt(textRenderer::width).max().orElse(0) / 2) : x;
final int finalY = y + (height / 2) - (lineHeight * lines.size() / 2) + 1; int finalY = y + (height / 2) - (lineHeight * lines.size() / 2) + 1;
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
graphics.drawString(textRenderer, lines.get(i), finalX, finalY + (i * lineHeight), WHITE); graphics.drawString(textRenderer, lines.get(i), finalX, finalY + (i * lineHeight), WHITE);

View File

@ -10,11 +10,11 @@ public class KeyBindingWithModifier extends KeyMapping {
@Nullable @Nullable
private ModifierKey modifier = null; private ModifierKey modifier = null;
public KeyBindingWithModifier(final String translationKey) { public KeyBindingWithModifier(String translationKey) {
super(translationKey, Type.KEYSYM, -1, CATEGORY); super(translationKey, Type.KEYSYM, -1, CATEGORY);
} }
public void setModifier(@Nullable final ModifierKey modifier) { public void setModifier(@Nullable ModifierKey modifier) {
this.modifier = modifier; this.modifier = modifier;
} }

View File

@ -26,13 +26,13 @@ public enum ModifierKey {
public final int id; public final int id;
ModifierKey(final int id) { ModifierKey(int id) {
this.id = id; this.id = id;
} }
public abstract boolean isPressed(); public abstract boolean isPressed();
public static ModifierKey getById(final int id) { public static ModifierKey getById(int id) {
return switch (id) { return switch (id) {
case 0 -> CONTROL; case 0 -> CONTROL;
case 1 -> SHIFT; case 1 -> SHIFT;

View File

@ -12,7 +12,7 @@ public class ToggleTracker {
private boolean hasToggledWhileHoldingReset; private boolean hasToggledWhileHoldingReset;
private boolean skipNextToggle; private boolean skipNextToggle;
public ToggleTracker(final KeyMapping bindingToggle, final KeyMapping bindingReset) { public ToggleTracker(KeyMapping bindingToggle, KeyMapping bindingReset) {
this.bindingToggle = bindingToggle; this.bindingToggle = bindingToggle;
this.bindingReset = bindingReset; this.bindingReset = bindingReset;
} }
@ -42,7 +42,7 @@ public class ToggleTracker {
*/ */
public boolean tick() { public boolean tick() {
final boolean isHoldingReset = isResetKeyPressed(); boolean isHoldingReset = isResetKeyPressed();
if (bindingToggle.isDown()) { if (bindingToggle.isDown()) {
if (!waitForRelease) { if (!waitForRelease) {

View File

@ -9,13 +9,13 @@ import java.util.Set;
public final class ToggleTrackerForStickyKey extends ToggleTracker { public final class ToggleTrackerForStickyKey extends ToggleTracker {
private static final Set<KeyMapping> enabledOverrides = new HashSet<>(); private static final Set<KeyMapping> enabledOverrides = new HashSet<>();
public static boolean isOverrideEnabled(final KeyMapping binding) { public static boolean isOverrideEnabled(KeyMapping binding) {
return enabledOverrides.contains(binding); return enabledOverrides.contains(binding);
} }
private final BooleanConsumer setToggleState; private final BooleanConsumer setToggleState;
public ToggleTrackerForStickyKey(final KeyMapping bindingToggle, final KeyMapping bindingStickyReset, final BooleanConsumer setToggleState) { public ToggleTrackerForStickyKey(KeyMapping bindingToggle, KeyMapping bindingStickyReset, BooleanConsumer setToggleState) {
super(bindingToggle, bindingStickyReset); super(bindingToggle, bindingStickyReset);
this.setToggleState = setToggleState; this.setToggleState = setToggleState;
this.setToggleState.accept(false); this.setToggleState.accept(false);
@ -24,7 +24,7 @@ public final class ToggleTrackerForStickyKey extends ToggleTracker {
@Override @Override
public boolean tick() { public boolean tick() {
final boolean isToggled = super.tick(); boolean isToggled = super.tick();
setToggleState.accept(isToggled); setToggleState.accept(isToggled);
return isToggled; return isToggled;
} }

View File

@ -13,5 +13,5 @@ public interface AccessStickyKeyBindingStateGetter {
@Accessor @Accessor
@Mutable @Mutable
void setNeedsToggle(final BooleanSupplier toggleGetter); void setNeedsToggle(BooleanSupplier toggleGetter);
} }

View File

@ -1,26 +1,26 @@
package chylex.bettercontrols.mixin; package chylex.bettercontrols.mixin;
import chylex.bettercontrols.player.PlayerTicker; import chylex.bettercontrols.player.PlayerTicker;
import net.minecraft.client.Minecraft; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
@Mixin(AbstractClientPlayer.class) @Mixin(AbstractClientPlayer.class)
public abstract class HookClientPlayerFOV { public abstract class HookClientPlayerFOV {
@Redirect( @ModifyExpressionValue(
method = "getFieldOfViewModifier", method = "getFieldOfViewModifier",
at = @At(value = "INVOKE", target = "Ljava/lang/Float;isNaN(F)Z"), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getWalkingSpeed()F")
slice = @Slice(
from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getWalkingSpeed()F"),
to = @At(value = "INVOKE", target = "Ljava/lang/Float;isInfinite(F)Z")
)
) )
private boolean resetFOV(final float movementSpeed) { private float overrideWalkingSpeed(float walkingSpeed) {
final LocalPlayer player = Minecraft.getInstance().player; AbstractClientPlayer me = (AbstractClientPlayer)(Object)this;
return (player != null && PlayerTicker.get(player).shouldResetFOV(player)) || Float.isNaN(movementSpeed);
if (me instanceof LocalPlayer localPlayer && PlayerTicker.get(localPlayer).shouldResetFOV(localPlayer)) {
return 0F;
}
else {
return walkingSpeed;
}
} }
} }

View File

@ -2,7 +2,6 @@ package chylex.bettercontrols.mixin;
import chylex.bettercontrols.player.PlayerTicker; import chylex.bettercontrols.player.PlayerTicker;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.player.Input;
import net.minecraft.client.player.KeyboardInput; import net.minecraft.client.player.KeyboardInput;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -12,16 +11,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER;
@Mixin(KeyboardInput.class) @Mixin(KeyboardInput.class)
@SuppressWarnings("UnreachableCode") @SuppressWarnings({ "MethodMayBeStatic", "UnreachableCode" })
public abstract class HookClientPlayerInputTick { public abstract class HookClientPlayerInputTick {
@Inject(method = "tick(ZF)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/KeyboardInput;up:Z", ordinal = 0, shift = AFTER)) @Inject(
private void afterInputTick(final CallbackInfo info) { method = "tick",
@SuppressWarnings("ConstantConditions") at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/KeyboardInput;keyPresses:Lnet/minecraft/world/entity/player/Input;", ordinal = 0, shift = AFTER)
final Input input = (Input)(Object)this; )
final LocalPlayer player = Minecraft.getInstance().player; private void afterInputTick(CallbackInfo info) {
LocalPlayer player = Minecraft.getInstance().player;
if (player != null) { if (player != null) {
PlayerTicker.get(player).afterInputAssignsPressingForward(input); PlayerTicker.get(player).afterKeyboardInputAssigned(player);
} }
} }
} }

View File

@ -14,28 +14,28 @@ import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER;
@Mixin(LocalPlayer.class) @Mixin(LocalPlayer.class)
@SuppressWarnings("UnreachableCode") @SuppressWarnings("UnreachableCode")
public abstract class HookClientPlayerTick extends AbstractClientPlayer { public abstract class HookClientPlayerTick extends AbstractClientPlayer {
protected HookClientPlayerTick(final ClientLevel world, final GameProfile profile) { protected HookClientPlayerTick(ClientLevel world, GameProfile profile) {
super(world, profile); super(world, profile);
} }
@Inject(method = "aiStep()V", at = @At("HEAD")) @Inject(method = "aiStep()V", at = @At("HEAD"))
private void atHead(final CallbackInfo info) { private void atHead(CallbackInfo info) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final LocalPlayer player = (LocalPlayer)(Object)this; LocalPlayer player = (LocalPlayer)(Object)this;
PlayerTicker.get(player).atHead(player); PlayerTicker.get(player).atHead(player);
} }
@Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/Input;tick(ZF)V", ordinal = 0, shift = AFTER)) @Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/ClientInput;tick()V", ordinal = 0, shift = AFTER))
private void afterInputTick(final CallbackInfo info) { private void afterInputTick(CallbackInfo info) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final LocalPlayer player = (LocalPlayer)(Object)this; LocalPlayer player = (LocalPlayer)(Object)this;
PlayerTicker.get(player).afterInputTick(player); PlayerTicker.get(player).afterInputTick(player);
} }
@Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;aiStep()V", ordinal = 0, shift = AFTER)) @Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;aiStep()V", ordinal = 0, shift = AFTER))
private void afterSuperCall(final CallbackInfo info) { private void afterSuperCall(CallbackInfo info) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final LocalPlayer player = (LocalPlayer)(Object)this; LocalPlayer player = (LocalPlayer)(Object)this;
PlayerTicker.get(player).afterSuperCall(player); PlayerTicker.get(player).afterSuperCall(player);
} }
} }

View File

@ -1,24 +1,23 @@
package chylex.bettercontrols.mixin; package chylex.bettercontrols.mixin;
import chylex.bettercontrols.player.FlightHelper; import chylex.bettercontrols.player.FlightHelper;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Abilities;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.Slice;
@Mixin(LocalPlayer.class) @Mixin(LocalPlayer.class)
@SuppressWarnings({ "SameReturnValue", "UnreachableCode" }) @SuppressWarnings({ "SameReturnValue", "UnreachableCode" })
public abstract class HookClientPlayerVerticalFlightSpeed extends LivingEntity { public abstract class HookClientPlayerVerticalFlightSpeed extends LivingEntity {
protected HookClientPlayerVerticalFlightSpeed(final EntityType<? extends LivingEntity> type, final Level world) { protected HookClientPlayerVerticalFlightSpeed(EntityType<? extends LivingEntity> type, Level world) {
super(type, world); super(type, world);
} }
@Redirect( @ModifyExpressionValue(
method = "aiStep", method = "aiStep",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getFlyingSpeed()F"), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getFlyingSpeed()F"),
slice = @Slice( slice = @Slice(
@ -26,9 +25,9 @@ public abstract class HookClientPlayerVerticalFlightSpeed extends LivingEntity {
to = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V") to = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")
) )
) )
private float modifyVerticalFlightSpeed(final Abilities abilities) { private float modifyVerticalFlightSpeed(float flyingSpeed) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final LocalPlayer me = (LocalPlayer)(Object)this; LocalPlayer me = (LocalPlayer)(Object)this;
return abilities.getFlyingSpeed() * FlightHelper.getVerticalSpeedMultiplier(me); return flyingSpeed * FlightHelper.getVerticalSpeedMultiplier(me);
} }
} }

View File

@ -1,6 +1,8 @@
package chylex.bettercontrols.mixin; package chylex.bettercontrols.mixin;
import chylex.bettercontrols.BetterControlsCommon; import chylex.bettercontrols.BetterControlsCommon;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.Options; import net.minecraft.client.Options;
@ -10,16 +12,16 @@ import net.minecraft.client.gui.screens.options.controls.KeyBindsList.Entry;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(KeyBindsList.class) @Mixin(KeyBindsList.class)
@SuppressWarnings("MethodMayBeStatic")
public abstract class HookControlsListWidget extends ContainerObjectSelectionList<Entry> { public abstract class HookControlsListWidget extends ContainerObjectSelectionList<Entry> {
public HookControlsListWidget(final Minecraft client, final int width, final int height, final int top, final int itemHeight) { public HookControlsListWidget(Minecraft client, int width, int height, int top, int itemHeight) {
super(client, width, height, top, itemHeight); super(client, width, height, top, itemHeight);
} }
@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Options;keyMappings:[Lnet/minecraft/client/KeyMapping;")) @WrapOperation(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Options;keyMappings:[Lnet/minecraft/client/KeyMapping;"))
private KeyMapping[] excludeOwnKeyBindings(final Options options) { private KeyMapping[] excludeOwnKeyBindings(Options options, Operation<KeyMapping[]> operation) {
return ArrayUtils.removeElements(options.keyMappings, BetterControlsCommon.getConfig().getAllKeyBindings()); return ArrayUtils.removeElements(operation.call(options), BetterControlsCommon.getConfig().getAllKeyBindings());
} }
} }

View File

@ -19,24 +19,22 @@ import java.util.List;
@Mixin(ControlsScreen.class) @Mixin(ControlsScreen.class)
@SuppressWarnings("UnreachableCode") @SuppressWarnings("UnreachableCode")
public abstract class HookControlsScreen extends OptionsSubScreen { public abstract class HookControlsScreen extends OptionsSubScreen {
public HookControlsScreen(final Screen parentScreen, final Options options, final Component title) { public HookControlsScreen(Screen parentScreen, Options options, Component title) {
super(parentScreen, options, title); super(parentScreen, options, title);
} }
@Inject(method = "addOptions", at = @At("RETURN")) @Inject(method = "addOptions", at = @At("RETURN"))
public void afterAddOptions(final CallbackInfo ci) { public void afterAddOptions(CallbackInfo ci) {
@SuppressWarnings("ConstantConditions")
final ControlsScreen screen = (ControlsScreen)(Object)this;
if (list != null) { if (list != null) {
final MutableComponent buttonTitle = BetterControlsScreen.TITLE.plainCopy().append("..."); @SuppressWarnings("ConstantConditions")
ControlsScreen screen = (ControlsScreen)(Object)this;
MutableComponent buttonTitle = BetterControlsScreen.TITLE.plainCopy().append("...");
list.addSmall(List.of(Button.builder(buttonTitle, btn -> showOptionsScreen(screen)).build())); list.addSmall(List.of(Button.builder(buttonTitle, btn -> showOptionsScreen(screen)).build()));
} }
} }
@Unique @Unique
private static void showOptionsScreen(final ControlsScreen screen) { private static void showOptionsScreen(ControlsScreen screen) {
final Minecraft mc = Minecraft.getInstance(); Minecraft.getInstance().setScreen(new BetterControlsScreen(screen));
mc.setScreen(new BetterControlsScreen(mc, screen));
} }
} }

View File

@ -26,12 +26,12 @@ public abstract class HookLoadGameOptions {
public KeyMapping[] keyMappings; public KeyMapping[] keyMappings;
@Inject(method = "load()V", at = @At("HEAD")) @Inject(method = "load()V", at = @At("HEAD"))
private void load(final CallbackInfo info) { private void load(CallbackInfo info) {
if (hasLoaded) { if (hasLoaded) {
return; return;
} }
final BetterControlsConfig config = BetterControlsCommon.getConfig(); BetterControlsConfig config = BetterControlsCommon.getConfig();
if (config == null) { if (config == null) {
return; return;
} }

View File

@ -1,6 +1,8 @@
package chylex.bettercontrols.mixin; package chylex.bettercontrols.mixin;
import chylex.bettercontrols.player.FlightHelper; import chylex.bettercontrols.player.FlightHelper;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@ -8,20 +10,17 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Player.class) @Mixin(Player.class)
@SuppressWarnings({ "SameReturnValue", "UnreachableCode" }) @SuppressWarnings({ "SameReturnValue", "UnreachableCode" })
public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity { public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity {
protected HookPlayerHorizontalFlightSpeed(final EntityType<? extends LivingEntity> type, final Level world) { protected HookPlayerHorizontalFlightSpeed(EntityType<? extends LivingEntity> type, Level world) {
super(type, world); super(type, world);
} }
@SuppressWarnings("SimplifiableIfStatement") @SuppressWarnings("SimplifiableIfStatement")
@Redirect( @ModifyExpressionValue(
method = "getFlyingSpeed", method = "getFlyingSpeed",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z"), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z"),
slice = @Slice( slice = @Slice(
@ -29,23 +28,28 @@ public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity {
to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getFlyingSpeed()F") to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getFlyingSpeed()F")
) )
) )
private boolean disableVanillaSprintBoost(final Player player) { private boolean disableVanillaSprintBoost(boolean isSprinting) {
if (player instanceof LocalPlayer) { @SuppressWarnings("ConstantConditions")
Player me = (Player)(Object)this;
if (me instanceof LocalPlayer localPlayer && FlightHelper.isFlyingCreativeOrSpectator(localPlayer)) {
return false; return false;
} }
else { else {
return player.isSprinting(); return isSprinting;
} }
} }
@Inject(method = "getFlyingSpeed", at = @At("RETURN"), cancellable = true) @ModifyReturnValue(method = "getFlyingSpeed", at = @At("RETURN"))
private void modifyHorizontalFlyingSpeed(final CallbackInfoReturnable<Float> cir) { private float modifyHorizontalFlyingSpeed(float flyingSpeed) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final Player me = (Player)(Object)this; Player me = (Player)(Object)this;
if (me instanceof final LocalPlayer localPlayer && localPlayer.getAbilities().flying) { if (me instanceof LocalPlayer localPlayer && localPlayer.getAbilities().flying) {
final float multiplier = FlightHelper.getHorizontalSpeedMultiplier(localPlayer); return flyingSpeed * FlightHelper.getHorizontalSpeedMultiplier(localPlayer);
cir.setReturnValue(Float.valueOf(cir.getReturnValueF() * multiplier)); }
else {
return flyingSpeed;
} }
} }
} }

View File

@ -17,12 +17,12 @@ public abstract class HookStickyKeyBindingState extends KeyMapping {
@Final @Final
private BooleanSupplier needsToggle; private BooleanSupplier needsToggle;
public HookStickyKeyBindingState(final String translationKey, final int code, final String category) { public HookStickyKeyBindingState(String translationKey, int code, String category) {
super(translationKey, code, category); super(translationKey, code, category);
} }
@Inject(method = "setDown", at = @At("HEAD"), cancellable = true) @Inject(method = "setDown", at = @At("HEAD"), cancellable = true)
public void setPressed(final boolean pressed, final CallbackInfo info) { public void setPressed(boolean pressed, CallbackInfo info) {
if (ToggleTrackerForStickyKey.isOverrideEnabled(this)) { if (ToggleTrackerForStickyKey.isOverrideEnabled(this)) {
((AccessKeyBindingFields)this).setPressedField(pressed); ((AccessKeyBindingFields)this).setPressedField(pressed);
info.cancel(); info.cancel();

View File

@ -13,9 +13,9 @@ import java.util.function.Consumer;
@SuppressWarnings("UnreachableCode") @SuppressWarnings("UnreachableCode")
public abstract class HookToggleOptionButtons { public abstract class HookToggleOptionButtons {
@Inject(method = "createButton(Lnet/minecraft/client/Options;IIILjava/util/function/Consumer;)Lnet/minecraft/client/gui/components/AbstractWidget;", at = @At("RETURN")) @Inject(method = "createButton(Lnet/minecraft/client/Options;IIILjava/util/function/Consumer;)Lnet/minecraft/client/gui/components/AbstractWidget;", at = @At("RETURN"))
private <T> void disableToggleOptions(final Options options, final int x, final int y, final int width, final Consumer<T> callback, final CallbackInfoReturnable<AbstractWidget> cir) { private <T> void disableToggleOptions(Options options, int x, int y, int width, Consumer<T> callback, CallbackInfoReturnable<AbstractWidget> cir) {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
final OptionInstance<?> me = (OptionInstance<?>)(Object)this; OptionInstance<?> me = (OptionInstance<?>)(Object)this;
if (me == options.toggleCrouch() || me == options.toggleSprint()) { if (me == options.toggleCrouch() || me == options.toggleSprint()) {
cir.getReturnValue().active = false; cir.getReturnValue().active = false;

View File

@ -19,15 +19,15 @@ public final class FlightHelper {
return BetterControlsCommon.getConfig(); return BetterControlsCommon.getConfig();
} }
static boolean isFlyingCreativeOrSpectator(final LocalPlayer player) { public static boolean isFlyingCreativeOrSpectator(LocalPlayer player) {
return player.getAbilities().flying && (player.isCreative() || player.isSpectator()); return player.getAbilities().flying && (player.isCreative() || player.isSpectator());
} }
static boolean shouldFlyOnGround(final LocalPlayer player) { static boolean shouldFlyOnGround(LocalPlayer player) {
return cfg().flyOnGroundInCreative && player.isCreative() && player.getAbilities().flying; return cfg().flyOnGroundInCreative && player.isCreative() && player.getAbilities().flying;
} }
public static float getHorizontalSpeedMultiplier(final LocalPlayer player) { public static float getHorizontalSpeedMultiplier(LocalPlayer player) {
if (player.isCreative()) { if (player.isCreative()) {
return isSprinting() ? cfg().flightHorizontalSpeedMpCreativeSprinting : cfg().flightHorizontalSpeedMpCreativeDefault; return isSprinting() ? cfg().flightHorizontalSpeedMpCreativeSprinting : cfg().flightHorizontalSpeedMpCreativeDefault;
} }
@ -39,7 +39,7 @@ public final class FlightHelper {
} }
} }
public static float getVerticalSpeedMultiplier(final LocalPlayer player) { public static float getVerticalSpeedMultiplier(LocalPlayer player) {
if (player.isCreative()) { if (player.isCreative()) {
return isSprinting() ? cfg().flightVerticalSpeedMpCreativeSprinting : cfg().flightVerticalSpeedMpCreativeDefault; return isSprinting() ? cfg().flightVerticalSpeedMpCreativeSprinting : cfg().flightVerticalSpeedMpCreativeDefault;
} }

View File

@ -14,8 +14,9 @@ import net.minecraft.client.Camera;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.Options; import net.minecraft.client.Options;
import net.minecraft.client.player.Input; import net.minecraft.client.player.ClientInput;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.player.Input;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
@ -30,7 +31,7 @@ public final class PlayerTicker {
private static PlayerTicker ticker = new PlayerTicker(null); private static PlayerTicker ticker = new PlayerTicker(null);
public static PlayerTicker get(final LocalPlayer player) { public static PlayerTicker get(LocalPlayer player) {
if (ticker.ref.get() != player) { if (ticker.ref.get() != player) {
ticker = new PlayerTicker(player); ticker = new PlayerTicker(player);
} }
@ -44,7 +45,7 @@ public final class PlayerTicker {
private final WeakReference<LocalPlayer> ref; private final WeakReference<LocalPlayer> ref;
private PlayerTicker(final LocalPlayer player) { private PlayerTicker(LocalPlayer player) {
this.ref = new WeakReference<>(player); this.ref = new WeakReference<>(player);
setup(); setup();
} }
@ -68,17 +69,17 @@ public final class PlayerTicker {
private int temporaryFlyOnGroundTimer = 0; private int temporaryFlyOnGroundTimer = 0;
private void setup() { private void setup() {
final AccessStickyKeyBindingStateGetter sprint = (AccessStickyKeyBindingStateGetter)KEY_SPRINT; AccessStickyKeyBindingStateGetter sprint = (AccessStickyKeyBindingStateGetter)KEY_SPRINT;
BooleanSupplier getter = sprint.getNeedsToggle(); BooleanSupplier getter = sprint.getNeedsToggle();
if (getter instanceof final SprintPressGetter g) { if (getter instanceof SprintPressGetter g) {
getter = g.wrapped(); getter = g.wrapped();
} }
sprint.setNeedsToggle(new SprintPressGetter(getter, () -> temporarySprintTimer > 0)); sprint.setNeedsToggle(new SprintPressGetter(getter, () -> temporarySprintTimer > 0));
} }
public void atHead(final LocalPlayer player) { public void atHead(LocalPlayer player) {
if (FlightHelper.shouldFlyOnGround(player)) { if (FlightHelper.shouldFlyOnGround(player)) {
player.setOnGround(false); player.setOnGround(false);
} }
@ -91,15 +92,15 @@ public final class PlayerTicker {
((AccessPlayerFields)player).setJumpTriggerTime(0); ((AccessPlayerFields)player).setJumpTriggerTime(0);
} }
final SprintMode sprintMode = cfg().sprintMode; SprintMode sprintMode = cfg().sprintMode;
final boolean wasSprintToggled = Boolean.TRUE.equals(OPTIONS.toggleSprint().get()); boolean wasSprintToggled = Boolean.TRUE.equals(OPTIONS.toggleSprint().get());
final boolean isSprintToggled = toggleSprint.tick(); boolean isSprintToggled = toggleSprint.tick();
if (temporarySprintTimer > 0) { if (temporarySprintTimer > 0) {
stopSprintingAfterReleasingSprintKey = false; stopSprintingAfterReleasingSprintKey = false;
waitingForSprintKeyRelease = false; waitingForSprintKeyRelease = false;
final int nextTemporarySprintTimer = temporarySprintTimer - 1; int nextTemporarySprintTimer = temporarySprintTimer - 1;
temporarySprintTimer = 0; temporarySprintTimer = 0;
if (!KEY_SPRINT.isDown() && KEY_FORWARD.isDown()) { if (!KEY_SPRINT.isDown() && KEY_FORWARD.isDown()) {
@ -148,19 +149,25 @@ public final class PlayerTicker {
toggleSneak.tick(); toggleSneak.tick();
} }
public void afterInputAssignsPressingForward(final Input input) { public void afterKeyboardInputAssigned(LocalPlayer player) {
if (MINECRAFT.screen == null) { if (MINECRAFT.screen == null && toggleWalkForward.tick()) {
//noinspection NonShortCircuitBooleanExpression ClientInput input = player.input;
input.up |= toggleWalkForward.tick();
input.keyPresses = new Input(
true,
input.keyPresses.backward(),
input.keyPresses.left(),
input.keyPresses.right(),
input.keyPresses.jump(),
input.keyPresses.shift(),
input.keyPresses.sprint()
);
} }
} }
public void afterInputTick(final LocalPlayer player) { public void afterInputTick(LocalPlayer player) {
final Input input = player.input; if (MINECRAFT.screen == null && !player.getAbilities().flying && toggleJump.tick()) {
player.input.makeJump();
if (MINECRAFT.screen == null && !player.getAbilities().flying) {
//noinspection NonShortCircuitBooleanExpression
input.jumping |= toggleJump.tick();
} }
if (cfg().resumeSprintingAfterHittingObstacle) { if (cfg().resumeSprintingAfterHittingObstacle) {
@ -183,10 +190,10 @@ public final class PlayerTicker {
} }
} }
public void afterSuperCall(final LocalPlayer player) { public void afterSuperCall(LocalPlayer player) {
if (FlightHelper.shouldFlyOnGround(player)) { if (FlightHelper.shouldFlyOnGround(player)) {
final boolean isSneaking = player.isShiftKeyDown(); boolean isSneaking = player.isShiftKeyDown();
final boolean isOnGround = player.onGround(); boolean isOnGround = player.onGround();
if (!isSneaking) { if (!isSneaking) {
wasSneakingBeforeTouchingGround = false; wasSneakingBeforeTouchingGround = false;
@ -223,20 +230,20 @@ public final class PlayerTicker {
} }
if (FlightHelper.isFlyingCreativeOrSpectator(player) && cfg().disableFlightInertia) { if (FlightHelper.isFlyingCreativeOrSpectator(player) && cfg().disableFlightInertia) {
final Input input = player.input; ClientInput input = player.input;
if (input.forwardImpulse == 0F && input.leftImpulse == 0F) { if (input.forwardImpulse == 0F && input.leftImpulse == 0F) {
player.setDeltaMovement(player.getDeltaMovement().multiply(0.0, 1.0, 0.0)); player.setDeltaMovement(player.getDeltaMovement().multiply(0.0, 1.0, 0.0));
} }
if (!input.jumping && !input.shiftKeyDown) { if (!input.keyPresses.jump() && !input.keyPresses.shift()) {
player.setDeltaMovement(player.getDeltaMovement().multiply(1.0, 0.0, 1.0)); player.setDeltaMovement(player.getDeltaMovement().multiply(1.0, 0.0, 1.0));
} }
} }
if (player.isCreative()) { if (player.isCreative()) {
if (cfg().keyToggleFlight.consumeClick()) { if (cfg().keyToggleFlight.consumeClick()) {
final boolean isFlying = !player.getAbilities().flying; boolean isFlying = !player.getAbilities().flying;
player.getAbilities().flying = isFlying; player.getAbilities().flying = isFlying;
player.onUpdateAbilities(); player.onUpdateAbilities();
@ -261,7 +268,7 @@ public final class PlayerTicker {
} }
if (!cfg().sneakingMovesCameraSmoothly) { if (!cfg().sneakingMovesCameraSmoothly) {
final Camera camera = MINECRAFT.gameRenderer.getMainCamera(); Camera camera = MINECRAFT.gameRenderer.getMainCamera();
if (camera.getEntity() == player) { if (camera.getEntity() == player) {
((AccessCameraFields)camera).setEyeHeight(player.getEyeHeight()); ((AccessCameraFields)camera).setEyeHeight(player.getEyeHeight());
@ -276,11 +283,11 @@ public final class PlayerTicker {
} }
if (cfg().keyOpenMenu.isDown()) { if (cfg().keyOpenMenu.isDown()) {
MINECRAFT.setScreen(new BetterControlsScreen(MINECRAFT, null)); MINECRAFT.setScreen(new BetterControlsScreen(null));
} }
} }
public boolean shouldResetFOV(final LocalPlayer player) { public boolean shouldResetFOV(LocalPlayer player) {
return cfg().disableChangingFovWhileFlying && FlightHelper.isFlyingCreativeOrSpectator(player); return cfg().disableChangingFovWhileFlying && FlightHelper.isFlyingCreativeOrSpectator(player);
} }
} }