From 3e67c318fafcf2ca1bfae5842c0c105434724fe1 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 9 Jul 2023 20:39:16 -0400 Subject: [PATCH 1/3] Initial start on preferences --- .../api/preference/BooleanPreference.java | 39 ++++++++ .../api/preference/FloatPreference.java | 39 ++++++++ .../api/preference/IntegerPreference.java | 39 ++++++++ .../geyser/api/preference/Preference.java | 44 ++++++++++ .../api/preference/StringPreference.java | 39 ++++++++ .../geyser/preference/CooldownPreference.java | 75 ++++++++++++++++ .../preference/CustomSkullsPreference.java | 59 +++++++++++++ .../geyser/preference/PreferenceHolder.java | 65 ++++++++++++++ .../preference/ShowCoordinatesPreference.java | 68 ++++++++++++++ .../session/cache/PreferencesCache.java | 88 ++++++++++++------- .../JavaLevelChunkWithLightTranslator.java | 3 +- .../geysermc/geyser/util/CooldownUtils.java | 11 ++- .../geysermc/geyser/util/SettingsUtils.java | 44 +++------- 13 files changed, 543 insertions(+), 70 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/preference/Preference.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java create mode 100644 core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java create mode 100644 core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java create mode 100644 core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java create mode 100644 core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java new file mode 100644 index 00000000000..faeabdbd7a9 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public abstract class BooleanPreference implements Preference { + + @Override + public Boolean deserialize(@NonNull Object response) { + if (response instanceof Boolean booleanValue) { + return booleanValue; + } + throw new IllegalArgumentException(response + " is not a boolean"); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java new file mode 100644 index 00000000000..42e44b70107 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public abstract class FloatPreference implements Preference { + + @Override + public Float deserialize(@NonNull Object response) throws IllegalArgumentException { + if (response instanceof Float floatValue) { + return floatValue; + } + throw new IllegalArgumentException(response + " is not a float"); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java new file mode 100644 index 00000000000..79814f33f6b --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public abstract class IntegerPreference implements Preference { + + @Override + public Integer deserialize(@NonNull Object response) throws IllegalArgumentException { + if (response instanceof Integer integerValue) { + return integerValue; + } + throw new IllegalArgumentException(response + " is not an integer"); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java b/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java new file mode 100644 index 00000000000..b90395a0e7d --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.cumulus.component.Component; +import org.geysermc.geyser.api.connection.GeyserConnection; + +public interface Preference { + + @NonNull + T defaultValue(GeyserConnection connection); + + boolean isModifiable(GeyserConnection connection); + + Component component(@NonNull T currentValue, GeyserConnection connection); + + T deserialize(@NonNull Object response) throws IllegalArgumentException; + + void onUpdate(@NonNull T value, GeyserConnection connection); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java new file mode 100644 index 00000000000..9696359b6c0 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public abstract class StringPreference implements Preference { + + @Override + public String deserialize(@NonNull Object response) throws IllegalArgumentException { + if (response instanceof String stringValue) { + return stringValue; + } + throw new IllegalArgumentException(response + " is not a string"); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java new file mode 100644 index 00000000000..342772be389 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.cumulus.component.Component; +import org.geysermc.cumulus.component.DropdownComponent; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.preference.Preference; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.Arrays; +import java.util.List; + +import static org.geysermc.geyser.util.CooldownUtils.CooldownType; + +public class CooldownPreference implements Preference { + + public static final String KEY = "geyser:cooldown_type"; + + private static final List OPTIONS = Arrays.stream(CooldownType.VALUES) + .map(CooldownType::getTranslation) + .toList(); + + @NonNull + @Override + public CooldownType defaultValue(GeyserConnection connection) { + GeyserSession session = (GeyserSession) connection; + String type = session.getGeyser().getConfig().getShowCooldown(); + return CooldownType.getByName(type); + } + + @Override + public boolean isModifiable(GeyserConnection connection) { + return defaultValue(connection) != CooldownType.DISABLED; + } + + @Override + public Component component(@NonNull CooldownType currentValue, GeyserConnection connection) { + return DropdownComponent.of(CooldownType.OPTION_DESCRIPTION, OPTIONS, currentValue.ordinal()); + } + + @Override + public CooldownType deserialize(@NonNull Object response) throws IllegalArgumentException { + return CooldownType.VALUES[(int) response]; + } + + @Override + public void onUpdate(@NonNull CooldownType value, GeyserConnection connection) { + //no-op + } +} diff --git a/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java b/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java new file mode 100644 index 00000000000..40efb4f3196 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.cumulus.component.Component; +import org.geysermc.cumulus.component.ToggleComponent; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.preference.BooleanPreference; +import org.geysermc.geyser.session.GeyserSession; + +public class CustomSkullsPreference extends BooleanPreference { + + public static final String KEY = "geyser:show_custom_skulls"; + + @Override + public @NonNull Boolean defaultValue(GeyserConnection connection) { + return isModifiable(connection); + } + + @Override + public boolean isModifiable(GeyserConnection connection) { + GeyserSession session = (GeyserSession) connection; + return session.getGeyser().getConfig().isAllowCustomSkulls(); + } + + @Override + public Component component(@NonNull Boolean currentValue, GeyserConnection connection) { + return ToggleComponent.of("geyser.settings.option.customSkulls", currentValue); + } + + @Override + public void onUpdate(@NonNull Boolean value, GeyserConnection connection) { + //no-op + } +} diff --git a/core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java b/core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java new file mode 100644 index 00000000000..aad4845dbcb --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.preference; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.cumulus.component.Component; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.preference.Preference; + +@Getter +@Accessors(fluent = true) +public class PreferenceHolder { + + @Setter + @NonNull + private T value; + + @NonNull + private final Preference preference; + + public PreferenceHolder(Preference preference, GeyserConnection connection) { + this.value = preference.defaultValue(connection); + this.preference = preference; + } + + public Component component(GeyserConnection connection) { + return preference.component(value, connection); + } + + public void onFormUpdate(Object formResponse, GeyserConnection connection) { + // parsed the cumulus form response value into the preference value + T newValue = preference.deserialize(formResponse); + + if (value != newValue) { + value = newValue; + preference.onUpdate(value, connection); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java b/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java new file mode 100644 index 00000000000..c6eafbef3ea --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.preference; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.cumulus.component.Component; +import org.geysermc.cumulus.component.ToggleComponent; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.preference.BooleanPreference; +import org.geysermc.geyser.session.GeyserSession; + +public class ShowCoordinatesPreference extends BooleanPreference { + + public static final String KEY = "geyser:show_coordinates"; + + @NonNull + @Override + public Boolean defaultValue(GeyserConnection connection) { + return isModifiable(connection); + } + + @Override + public boolean isModifiable(GeyserConnection connection) { + GeyserSession session = (GeyserSession) connection; + return !session.isReducedDebugInfo() && session.getGeyser().getConfig().isShowCoordinates(); + } + + @Override + public Component component(@NonNull Boolean currentValue, GeyserConnection connection) { + return ToggleComponent.of("%createWorldScreen.showCoordinates", currentValue); + } + + @Override + public void onUpdate(@NonNull Boolean value, GeyserConnection connection) { + boolean showCoordinates; + if (isModifiable(connection)) { + showCoordinates = value; + } else { + showCoordinates = false; + } + + GeyserSession session = (GeyserSession) connection; + session.sendGameRule("showcoordinates", showCoordinates); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java index 9e8597b0f54..6aee6b860a2 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java @@ -25,63 +25,83 @@ package org.geysermc.geyser.session.cache; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; -import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.configuration.GeyserConfiguration; +import org.geysermc.geyser.preference.CooldownPreference; +import org.geysermc.geyser.preference.CustomSkullsPreference; +import org.geysermc.geyser.preference.PreferenceHolder; +import org.geysermc.geyser.preference.ShowCoordinatesPreference; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.CooldownUtils; -@Getter +import java.util.Map; + public class PreferencesCache { private final GeyserSession session; - /** - * True if the client prefers being shown their coordinates, regardless if they're being shown or not. - * This will be true everytime the client joins the server because neither the client nor server store the preference permanently. - */ - @Setter - private boolean prefersShowCoordinates = true; + @Getter + private final Map> preferences = new Object2ObjectOpenHashMap<>(); - /** - * If the client's preference will be ignored, this will return false. - */ - private boolean allowShowCoordinates; + public PreferencesCache(GeyserSession session) { + this.session = session; - /** - * If the session wants custom skulls to be shown. - */ - @Setter - private boolean prefersCustomSkulls; + preferences.put(CooldownPreference.KEY, new PreferenceHolder<>(new CooldownPreference(), session)); + preferences.put(CustomSkullsPreference.KEY, new PreferenceHolder<>(new CustomSkullsPreference(), session)); + preferences.put(ShowCoordinatesPreference.KEY, new PreferenceHolder<>(new ShowCoordinatesPreference(), session)); + } - /** - * Which CooldownType the client prefers. Initially set to {@link CooldownUtils#getDefaultShowCooldown()}. - */ - @Setter - private CooldownUtils.CooldownType cooldownPreference = CooldownUtils.getDefaultShowCooldown(); + @Nullable + public T getPreference(String key) { + PreferenceHolder holder = get(key); + if (holder == null) { + return null; + } + return holder.value(); + } - public PreferencesCache(GeyserSession session) { - this.session = session; + public T getPreference(String key, T defaultValue) { + T value = getPreference(key); + if (value == null) { + return defaultValue; + } + return value; + } - prefersCustomSkulls = session.getGeyser().getConfig().isAllowCustomSkulls(); + @SuppressWarnings("unchecked") + private PreferenceHolder get(String key) { + return (PreferenceHolder) preferences.get(key); } /** - * Tell the client to hide or show the coordinates. - * - * If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply:
- *
- * {@link GeyserSession#reducedDebugInfo} is enabled - * {@link GeyserConfiguration#isShowCoordinates()} is disabled + * Tell the client to hide or show the coordinates. The client's preference will be overridden if either of the + * following are true: + *

+ * {@link GeyserSession#isReducedDebugInfo} is enabled.
+ * {@link GeyserConfiguration#isShowCoordinates()} is disabled. */ public void updateShowCoordinates() { - allowShowCoordinates = !session.isReducedDebugInfo() && session.getGeyser().getConfig().isShowCoordinates(); - session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates); + PreferenceHolder holder = get(ShowCoordinatesPreference.KEY); + // preference itself won't be any different, but trigger an update anyway in case + // reduced-debug-info has changed or the config has changed + holder.preference().onUpdate(holder.value(), session); } /** * @return true if the session prefers custom skulls, and the config allows them. */ public boolean showCustomSkulls() { - return prefersCustomSkulls && session.getGeyser().getConfig().isAllowCustomSkulls(); + if (session.getGeyser().getConfig().isAllowCustomSkulls()) { + return false; + } + return getPreference(CustomSkullsPreference.KEY, true); + } + + /** + * @return the session's cooldown preference. does not take the config setting into account. + */ + public CooldownUtils.CooldownType getCooldownPreference() { + return getPreference(CooldownPreference.KEY, CooldownUtils.getDefaultShowCooldown()); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java index a6d5fe09c9a..abcb59a3c0b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -90,6 +90,7 @@ public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacke int yOffset = session.getChunkCache().getChunkMinY(); int chunkSize = session.getChunkCache().getChunkHeightY(); int biomeGlobalPalette = session.getBiomeGlobalPalette(); + boolean customSkulls = session.getPreferencesCache().showCustomSkulls(); DataPalette[] javaChunks = new DataPalette[chunkSize]; DataPalette[] javaBiomes = new DataPalette[chunkSize]; @@ -283,7 +284,7 @@ public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacke bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState)); // Check for custom skulls - if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) { + if (customSkulls && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) { SkullBlockEntityTranslator.translateSkull(session, tag, x + chunkBlockX, y, z + chunkBlockZ, blockState); } } diff --git a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java index c00e389fd21..fbce146b9fd 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.util; +import lombok.AllArgsConstructor; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import lombok.Getter; import org.geysermc.geyser.session.GeyserSession; @@ -146,13 +147,17 @@ private static String getTitle(GeyserSession session) { } @Getter + @AllArgsConstructor public enum CooldownType { - TITLE, - ACTIONBAR, - DISABLED; + TITLE("options.attack.crosshair"), + ACTIONBAR("options.attack.hotbar"), + DISABLED("options.off"); + public static final String OPTION_DESCRIPTION = "options.attackIndicator"; public static final CooldownType[] VALUES = values(); + private final String translation; + /** * Convert the CooldownType string (from config) to the enum, DISABLED on fail * diff --git a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java index 5957fb9d98f..33222922d06 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -32,6 +32,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.WorldManager; +import org.geysermc.geyser.preference.PreferenceHolder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; @@ -51,29 +52,19 @@ public static CustomForm buildForm(GeyserSession session) { .title("geyser.settings.title.main") .iconPath("textures/ui/settings_glyph_color_2x.png"); - // Only show the client title if any of the client settings are available - boolean showClientSettings = session.getPreferencesCache().isAllowShowCoordinates() - || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED - || session.getGeyser().getConfig().isAllowCustomSkulls(); + var preferences = session.getPreferencesCache().getPreferences().values() + .stream() + .filter(s -> s.preference().isModifiable(session)) // only show modifiable preferences + .toList(); + + // Only show the client title if any of the client settings are available + boolean showClientSettings = !preferences.isEmpty(); if (showClientSettings) { builder.label("geyser.settings.title.client"); - // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (session.getPreferencesCache().isAllowShowCoordinates()) { - builder.toggle("%createWorldScreen.showCoordinates", session.getPreferencesCache().isPrefersShowCoordinates()); - } - - if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { - DropdownComponent.Builder cooldownDropdown = DropdownComponent.builder("options.attackIndicator"); - cooldownDropdown.option("options.attack.crosshair", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.TITLE); - cooldownDropdown.option("options.attack.hotbar", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.ACTIONBAR); - cooldownDropdown.option("options.off", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.DISABLED); - builder.dropdown(cooldownDropdown); - } - - if (session.getGeyser().getConfig().isAllowCustomSkulls()) { - builder.toggle("geyser.settings.option.customSkulls", session.getPreferencesCache().isPrefersCustomSkulls()); + for (PreferenceHolder preference : preferences) { + builder.component(preference.component(session)); } } @@ -112,19 +103,8 @@ public static CustomForm buildForm(GeyserSession session) { builder.validResultHandler((response) -> { if (showClientSettings) { - // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (session.getPreferencesCache().isAllowShowCoordinates()) { - session.getPreferencesCache().setPrefersShowCoordinates(response.next()); - session.getPreferencesCache().updateShowCoordinates(); - } - - if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { - CooldownUtils.CooldownType cooldownType = CooldownUtils.CooldownType.VALUES[(int) response.next()]; - session.getPreferencesCache().setCooldownPreference(cooldownType); - } - - if (session.getGeyser().getConfig().isAllowCustomSkulls()) { - session.getPreferencesCache().setPrefersCustomSkulls(response.next()); + for (PreferenceHolder preference : preferences) { + preference.onFormUpdate(response.next(), session); } } From 507912bd4eefb52581764c4f9364f6fd36d86b63 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 12 Jul 2023 04:32:21 -0400 Subject: [PATCH 2/3] Use abstract Preference, add api to GeyserConnection --- .../api/connection/GeyserConnection.java | 11 ++++ .../api/preference/BooleanPreference.java | 10 ++- .../api/preference/FloatPreference.java | 10 ++- .../api/preference/IntegerPreference.java | 10 ++- .../geyser/api/preference/Preference.java | 29 +++++++-- .../geyser/api/preference/PreferenceKey.java | 40 +----------- .../api/preference/StringPreference.java | 10 ++- .../configuration/GeyserConfiguration.java | 3 +- .../GeyserJacksonConfiguration.java | 4 +- .../geyser/preference/CooldownPreference.java | 28 ++++---- .../preference/CustomSkullsPreference.java | 21 +++--- .../preference/ShowCoordinatesPreference.java | 25 +++---- .../geyser/session/GeyserSession.java | 17 +++++ .../session/cache/PreferencesCache.java | 65 ++++++++++--------- .../level/JavaBlockEntityDataTranslator.java | 2 +- .../JavaLevelChunkWithLightTranslator.java | 2 +- .../geysermc/geyser/util/CooldownUtils.java | 18 ++++- .../geysermc/geyser/util/SettingsUtils.java | 18 +++-- 18 files changed, 182 insertions(+), 141 deletions(-) rename core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java => api/src/main/java/org/geysermc/geyser/api/preference/PreferenceKey.java (50%) diff --git a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java index 7094812a0f9..db37c921d51 100644 --- a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java +++ b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java @@ -33,7 +33,10 @@ import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; +import org.geysermc.geyser.api.preference.Preference; +import org.geysermc.geyser.api.preference.PreferenceKey; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -95,4 +98,12 @@ public interface GeyserConnection extends Connection, CommandSource { */ @NonNull Set fogEffects(); + + void storePreference(@NonNull PreferenceKey key, @NonNull Preference preference); + + @NonNull + Preference requirePreference(@NonNull PreferenceKey key) throws IllegalArgumentException; + + @NonNull + Optional> getPreference(@NonNull PreferenceKey key); } diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java index faeabdbd7a9..2e575fa271b 100644 --- a/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/BooleanPreference.java @@ -27,12 +27,16 @@ import org.checkerframework.checker.nullness.qual.NonNull; -public abstract class BooleanPreference implements Preference { +public abstract class BooleanPreference extends Preference { + + public BooleanPreference(@NonNull Boolean initialValue) { + super(initialValue); + } @Override - public Boolean deserialize(@NonNull Object response) { + public void onFormResponse(@NonNull Object response) { if (response instanceof Boolean booleanValue) { - return booleanValue; + update(booleanValue); } throw new IllegalArgumentException(response + " is not a boolean"); } diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java index 42e44b70107..64bf22306a2 100644 --- a/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/FloatPreference.java @@ -27,12 +27,16 @@ import org.checkerframework.checker.nullness.qual.NonNull; -public abstract class FloatPreference implements Preference { +public abstract class FloatPreference extends Preference { + + public FloatPreference(@NonNull Float initialValue) { + super(initialValue); + } @Override - public Float deserialize(@NonNull Object response) throws IllegalArgumentException { + public void onFormResponse(@NonNull Object response) throws IllegalArgumentException { if (response instanceof Float floatValue) { - return floatValue; + update(floatValue); } throw new IllegalArgumentException(response + " is not a float"); } diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java index 79814f33f6b..409b6e60316 100644 --- a/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/IntegerPreference.java @@ -27,12 +27,16 @@ import org.checkerframework.checker.nullness.qual.NonNull; -public abstract class IntegerPreference implements Preference { +public abstract class IntegerPreference extends Preference { + + public IntegerPreference(@NonNull Integer initialValue) { + super(initialValue); + } @Override - public Integer deserialize(@NonNull Object response) throws IllegalArgumentException { + public void onFormResponse(@NonNull Object response) throws IllegalArgumentException { if (response instanceof Integer integerValue) { - return integerValue; + update(integerValue); } throw new IllegalArgumentException(response + " is not an integer"); } diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java b/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java index b90395a0e7d..10bb33d927d 100644 --- a/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/Preference.java @@ -29,16 +29,33 @@ import org.geysermc.cumulus.component.Component; import org.geysermc.geyser.api.connection.GeyserConnection; -public interface Preference { +import java.util.Objects; + +public abstract class Preference { @NonNull - T defaultValue(GeyserConnection connection); + private T value; + + public Preference(@NonNull T initialValue) { + this.value = Objects.requireNonNull(initialValue, "initialValue"); + } + + @NonNull + public final T value() { + return value; + } + + public final void update(@NonNull T newValue) { + this.value = Objects.requireNonNull(newValue, "newValue"); + } - boolean isModifiable(GeyserConnection connection); + public abstract boolean isModifiable(GeyserConnection connection); - Component component(@NonNull T currentValue, GeyserConnection connection); + public abstract Component component(GeyserConnection connection); - T deserialize(@NonNull Object response) throws IllegalArgumentException; + public abstract void onFormResponse(@NonNull Object response) throws IllegalArgumentException; - void onUpdate(@NonNull T value, GeyserConnection connection); + public void onUpdate(GeyserConnection connection) { + // no-op by default + } } diff --git a/core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java b/api/src/main/java/org/geysermc/geyser/api/preference/PreferenceKey.java similarity index 50% rename from core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java rename to api/src/main/java/org/geysermc/geyser/api/preference/PreferenceKey.java index aad4845dbcb..a0063c7f6ee 100644 --- a/core/src/main/java/org/geysermc/geyser/preference/PreferenceHolder.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/PreferenceKey.java @@ -23,43 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.preference; +package org.geysermc.geyser.api.preference; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.cumulus.component.Component; -import org.geysermc.geyser.api.connection.GeyserConnection; -import org.geysermc.geyser.api.preference.Preference; - -@Getter -@Accessors(fluent = true) -public class PreferenceHolder { - - @Setter - @NonNull - private T value; - - @NonNull - private final Preference preference; - - public PreferenceHolder(Preference preference, GeyserConnection connection) { - this.value = preference.defaultValue(connection); - this.preference = preference; - } - - public Component component(GeyserConnection connection) { - return preference.component(value, connection); - } - - public void onFormUpdate(Object formResponse, GeyserConnection connection) { - // parsed the cumulus form response value into the preference value - T newValue = preference.deserialize(formResponse); - - if (value != newValue) { - value = newValue; - preference.onUpdate(value, connection); - } - } +public record PreferenceKey(String key) { } diff --git a/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java b/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java index 9696359b6c0..24f1d8e3eab 100644 --- a/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java +++ b/api/src/main/java/org/geysermc/geyser/api/preference/StringPreference.java @@ -27,12 +27,16 @@ import org.checkerframework.checker.nullness.qual.NonNull; -public abstract class StringPreference implements Preference { +public abstract class StringPreference extends Preference { + + public StringPreference(@NonNull String initialValue) { + super(initialValue); + } @Override - public String deserialize(@NonNull Object response) throws IllegalArgumentException { + public void onFormResponse(@NonNull Object response) throws IllegalArgumentException { if (response instanceof String stringValue) { - return stringValue; + update(stringValue); } throw new IllegalArgumentException(response + " is not a string"); } diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index 222af341b35..f7f45f63539 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -33,6 +33,7 @@ import org.geysermc.geyser.network.CIDRMatcher; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.CooldownUtils; import java.nio.file.Path; import java.util.List; @@ -82,7 +83,7 @@ public interface GeyserConfiguration { boolean isAllowThirdPartyEars(); - String getShowCooldown(); + CooldownUtils.CooldownType getShowCooldown(); boolean isShowCoordinates(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index e096d58fa68..c6badde952a 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -39,6 +39,7 @@ import org.geysermc.geyser.network.CIDRMatcher; import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.CooldownUtils; import java.io.IOException; import java.nio.file.Path; @@ -99,8 +100,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("allow-third-party-capes") private boolean allowThirdPartyCapes = true; + @JsonDeserialize(using = CooldownUtils.CooldownType.Deserializer.class) @JsonProperty("show-cooldown") - private String showCooldown = "title"; + private CooldownUtils.CooldownType showCooldown = CooldownUtils.CooldownType.TITLE; @JsonProperty("show-coordinates") private boolean showCoordinates = true; diff --git a/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java index 342772be389..50c193c99a1 100644 --- a/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java +++ b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java @@ -30,6 +30,7 @@ import org.geysermc.cumulus.component.DropdownComponent; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.preference.Preference; +import org.geysermc.geyser.api.preference.PreferenceKey; import org.geysermc.geyser.session.GeyserSession; import java.util.Arrays; @@ -37,39 +38,34 @@ import static org.geysermc.geyser.util.CooldownUtils.CooldownType; -public class CooldownPreference implements Preference { +public class CooldownPreference extends Preference { - public static final String KEY = "geyser:cooldown_type"; + public static final PreferenceKey KEY = new PreferenceKey<>("geyser:cooldown_type"); private static final List OPTIONS = Arrays.stream(CooldownType.VALUES) .map(CooldownType::getTranslation) .toList(); - @NonNull - @Override - public CooldownType defaultValue(GeyserConnection connection) { - GeyserSession session = (GeyserSession) connection; - String type = session.getGeyser().getConfig().getShowCooldown(); - return CooldownType.getByName(type); + public CooldownPreference(GeyserSession session) { + super(configSetting(session)); } @Override public boolean isModifiable(GeyserConnection connection) { - return defaultValue(connection) != CooldownType.DISABLED; + return configSetting((GeyserSession) connection) != CooldownType.DISABLED; } @Override - public Component component(@NonNull CooldownType currentValue, GeyserConnection connection) { - return DropdownComponent.of(CooldownType.OPTION_DESCRIPTION, OPTIONS, currentValue.ordinal()); + public Component component(GeyserConnection connection) { + return DropdownComponent.of(CooldownType.OPTION_DESCRIPTION, OPTIONS, value().ordinal()); } @Override - public CooldownType deserialize(@NonNull Object response) throws IllegalArgumentException { - return CooldownType.VALUES[(int) response]; + public void onFormResponse(@NonNull Object response) throws IllegalArgumentException { + update(CooldownType.VALUES[(int) response]); } - @Override - public void onUpdate(@NonNull CooldownType value, GeyserConnection connection) { - //no-op + private static CooldownType configSetting(GeyserSession session) { + return session.getGeyser().getConfig().getShowCooldown(); } } diff --git a/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java b/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java index 40efb4f3196..fdca24fd087 100644 --- a/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java +++ b/core/src/main/java/org/geysermc/geyser/preference/CustomSkullsPreference.java @@ -25,35 +25,32 @@ package org.geysermc.geyser.preference; -import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.cumulus.component.Component; import org.geysermc.cumulus.component.ToggleComponent; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.preference.BooleanPreference; +import org.geysermc.geyser.api.preference.PreferenceKey; import org.geysermc.geyser.session.GeyserSession; public class CustomSkullsPreference extends BooleanPreference { - public static final String KEY = "geyser:show_custom_skulls"; + public static final PreferenceKey KEY = new PreferenceKey<>("geyser:show_custom_skulls"); - @Override - public @NonNull Boolean defaultValue(GeyserConnection connection) { - return isModifiable(connection); + public CustomSkullsPreference(GeyserSession session) { + super(configSetting(session)); } @Override public boolean isModifiable(GeyserConnection connection) { - GeyserSession session = (GeyserSession) connection; - return session.getGeyser().getConfig().isAllowCustomSkulls(); + return configSetting((GeyserSession) connection); } @Override - public Component component(@NonNull Boolean currentValue, GeyserConnection connection) { - return ToggleComponent.of("geyser.settings.option.customSkulls", currentValue); + public Component component(GeyserConnection connection) { + return ToggleComponent.of("geyser.settings.option.customSkulls", value()); } - @Override - public void onUpdate(@NonNull Boolean value, GeyserConnection connection) { - //no-op + private static boolean configSetting(GeyserSession session) { + return session.getGeyser().getConfig().isAllowCustomSkulls(); } } diff --git a/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java b/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java index c6eafbef3ea..f760436db78 100644 --- a/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java +++ b/core/src/main/java/org/geysermc/geyser/preference/ShowCoordinatesPreference.java @@ -25,39 +25,36 @@ package org.geysermc.geyser.preference; -import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.cumulus.component.Component; import org.geysermc.cumulus.component.ToggleComponent; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.preference.BooleanPreference; +import org.geysermc.geyser.api.preference.PreferenceKey; import org.geysermc.geyser.session.GeyserSession; public class ShowCoordinatesPreference extends BooleanPreference { - public static final String KEY = "geyser:show_coordinates"; + public static final PreferenceKey KEY = new PreferenceKey<>("geyser:show_coordinates"); - @NonNull - @Override - public Boolean defaultValue(GeyserConnection connection) { - return isModifiable(connection); + public ShowCoordinatesPreference(GeyserSession session) { + super(isAllowed(session)); } @Override public boolean isModifiable(GeyserConnection connection) { - GeyserSession session = (GeyserSession) connection; - return !session.isReducedDebugInfo() && session.getGeyser().getConfig().isShowCoordinates(); + return isAllowed((GeyserSession) connection); } @Override - public Component component(@NonNull Boolean currentValue, GeyserConnection connection) { - return ToggleComponent.of("%createWorldScreen.showCoordinates", currentValue); + public Component component(GeyserConnection connection) { + return ToggleComponent.of("%createWorldScreen.showCoordinates", value()); } @Override - public void onUpdate(@NonNull Boolean value, GeyserConnection connection) { + public void onUpdate(GeyserConnection connection) { boolean showCoordinates; if (isModifiable(connection)) { - showCoordinates = value; + showCoordinates = value(); } else { showCoordinates = false; } @@ -65,4 +62,8 @@ public void onUpdate(@NonNull Boolean value, GeyserConnection connection) { GeyserSession session = (GeyserSession) connection; session.sendGameRule("showcoordinates", showCoordinates); } + + private static boolean isAllowed(GeyserSession session) { + return !session.isReducedDebugInfo() && session.getGeyser().getConfig().isShowCoordinates(); + } } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index dba4bd112e3..3ec677eaff9 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -99,6 +99,8 @@ import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; import org.geysermc.geyser.api.bedrock.camera.CameraShake; +import org.geysermc.geyser.api.preference.Preference; +import org.geysermc.geyser.api.preference.PreferenceKey; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; @@ -1991,6 +1993,21 @@ public void removeFog(String... fogNameSpaces) { return Set.copyOf(this.appliedFog); } + @Override + public void storePreference(@NonNull PreferenceKey key, @NonNull Preference preference) { + this.preferencesCache.register(key, preference); + } + + @Override + public @NonNull Preference requirePreference(@NonNull PreferenceKey key) throws IllegalArgumentException { + return this.preferencesCache.require(key); + } + + @Override + public @NonNull Optional> getPreference(@NonNull PreferenceKey key) { + return this.preferencesCache.get(key); + } + public void addCommandEnum(String name, String enums) { softEnumPacket(name, SoftEnumUpdateType.ADD, enums); } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java index 6aee6b860a2..3864e2523ef 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java @@ -27,51 +27,54 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.preference.Preference; +import org.geysermc.geyser.api.preference.PreferenceKey; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.preference.CooldownPreference; import org.geysermc.geyser.preference.CustomSkullsPreference; -import org.geysermc.geyser.preference.PreferenceHolder; import org.geysermc.geyser.preference.ShowCoordinatesPreference; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.CooldownUtils; import java.util.Map; +import java.util.Optional; public class PreferencesCache { private final GeyserSession session; @Getter - private final Map> preferences = new Object2ObjectOpenHashMap<>(); + private final Map, Preference> preferences = new Object2ObjectOpenHashMap<>(); public PreferencesCache(GeyserSession session) { this.session = session; - preferences.put(CooldownPreference.KEY, new PreferenceHolder<>(new CooldownPreference(), session)); - preferences.put(CustomSkullsPreference.KEY, new PreferenceHolder<>(new CustomSkullsPreference(), session)); - preferences.put(ShowCoordinatesPreference.KEY, new PreferenceHolder<>(new ShowCoordinatesPreference(), session)); + register(CooldownPreference.KEY, new CooldownPreference(session)); + register(CustomSkullsPreference.KEY, new CustomSkullsPreference(session)); + register(ShowCoordinatesPreference.KEY, new ShowCoordinatesPreference(session)); } - @Nullable - public T getPreference(String key) { - PreferenceHolder holder = get(key); - if (holder == null) { - return null; + public void register(PreferenceKey key, Preference preference) { + if (preference == null) { + throw new IllegalArgumentException("preference cannot be null"); } - return holder.value(); + preferences.put(key, preference); } - public T getPreference(String key, T defaultValue) { - T value = getPreference(key); - if (value == null) { - return defaultValue; + @SuppressWarnings("unchecked") + @NonNull + public Preference require(PreferenceKey key) throws IllegalArgumentException { + Preference preference = (Preference) preferences.get(key); + if (preference == null) { + throw new IllegalArgumentException("preference with key " + key + " is not stored for session " + session.javaUuid()); } - return value; + return preference; } @SuppressWarnings("unchecked") - private PreferenceHolder get(String key) { - return (PreferenceHolder) preferences.get(key); + @NonNull + public Optional> get(PreferenceKey key) { + return Optional.ofNullable((Preference) preferences.get(key)); } /** @@ -82,26 +85,24 @@ private PreferenceHolder get(String key) { * {@link GeyserConfiguration#isShowCoordinates()} is disabled. */ public void updateShowCoordinates() { - PreferenceHolder holder = get(ShowCoordinatesPreference.KEY); + Preference preference = require(ShowCoordinatesPreference.KEY); // preference itself won't be any different, but trigger an update anyway in case // reduced-debug-info has changed or the config has changed - holder.preference().onUpdate(holder.value(), session); + preference.onUpdate(session); } - /** - * @return true if the session prefers custom skulls, and the config allows them. - */ - public boolean showCustomSkulls() { - if (session.getGeyser().getConfig().isAllowCustomSkulls()) { + public boolean getEffectiveShowSkulls() { + if (!session.getGeyser().getConfig().isAllowCustomSkulls()) { return false; } - return getPreference(CustomSkullsPreference.KEY, true); + return require(CustomSkullsPreference.KEY).value(); } - /** - * @return the session's cooldown preference. does not take the config setting into account. - */ - public CooldownUtils.CooldownType getCooldownPreference() { - return getPreference(CooldownPreference.KEY, CooldownUtils.getDefaultShowCooldown()); + + public CooldownUtils.CooldownType getEffectiveCooldown() { + if (session.getGeyser().getConfig().getShowCooldown() == CooldownUtils.CooldownType.DISABLED) { + return CooldownUtils.CooldownType.DISABLED; + } + return require(CooldownPreference.KEY).value(); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index e1a94f02caa..ac735ee07da 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -63,7 +63,7 @@ public void translate(GeyserSession session, ClientboundBlockEntityDataPacket pa BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(), packet.getNbt(), blockState), packet.getPosition()); // Check for custom skulls. - if (session.getPreferencesCache().showCustomSkulls() && packet.getNbt() != null && packet.getNbt().contains("SkullOwner")) { + if (session.getPreferencesCache().getEffectiveShowSkulls() && packet.getNbt() != null && packet.getNbt().contains("SkullOwner")) { SkullBlockEntityTranslator.translateSkull(session, packet.getNbt(), position.getX(), position.getY(), position.getZ(), blockState); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java index abcb59a3c0b..e1b44c9a83d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -90,7 +90,7 @@ public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacke int yOffset = session.getChunkCache().getChunkMinY(); int chunkSize = session.getChunkCache().getChunkHeightY(); int biomeGlobalPalette = session.getBiomeGlobalPalette(); - boolean customSkulls = session.getPreferencesCache().showCustomSkulls(); + boolean customSkulls = session.getPreferencesCache().getEffectiveShowSkulls(); DataPalette[] javaChunks = new DataPalette[chunkSize]; DataPalette[] javaBiomes = new DataPalette[chunkSize]; diff --git a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java index fbce146b9fd..443ccb2693f 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java @@ -25,6 +25,10 @@ package org.geysermc.geyser.util; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; import lombok.AllArgsConstructor; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import lombok.Getter; @@ -32,6 +36,7 @@ import org.geysermc.geyser.session.cache.PreferencesCache; import org.geysermc.geyser.text.ChatColor; +import java.io.IOException; import java.util.concurrent.TimeUnit; /** @@ -41,8 +46,8 @@ public class CooldownUtils { private static CooldownType DEFAULT_SHOW_COOLDOWN; - public static void setDefaultShowCooldown(String showCooldown) { - DEFAULT_SHOW_COOLDOWN = CooldownType.getByName(showCooldown); + public static void setDefaultShowCooldown(CooldownType showCooldown) { + DEFAULT_SHOW_COOLDOWN = showCooldown; } public static CooldownType getDefaultShowCooldown() { @@ -55,7 +60,7 @@ public static CooldownType getDefaultShowCooldown() { */ public static void sendCooldown(GeyserSession session) { if (DEFAULT_SHOW_COOLDOWN == CooldownType.DISABLED) return; - CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference(); + CooldownType sessionPreference = session.getPreferencesCache().getEffectiveCooldown(); if (sessionPreference == CooldownType.DISABLED) return; if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used @@ -177,5 +182,12 @@ public static CooldownType getByName(String name) { } return DISABLED; } + + public static class Deserializer extends JsonDeserializer { + @Override + public CooldownType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + return CooldownType.getByName(p.getValueAsString()); + } + } } } diff --git a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java index 33222922d06..1b810da83cc 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -27,16 +27,19 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; +import it.unimi.dsi.fastutil.Pair; import org.geysermc.cumulus.component.DropdownComponent; +import org.geysermc.cumulus.component.LabelComponent; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.WorldManager; -import org.geysermc.geyser.preference.PreferenceHolder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; +import java.util.Objects; + public class SettingsUtils { /** * Build a settings form for the given session and store it for later @@ -55,7 +58,9 @@ public static CustomForm buildForm(GeyserSession session) { var preferences = session.getPreferencesCache().getPreferences().values() .stream() - .filter(s -> s.preference().isModifiable(session)) // only show modifiable preferences + .filter(pref -> pref.isModifiable(session)) // only show modifiable preferences + .map(pref -> Pair.of(pref, pref.component(session))) // compute components + .filter(p -> !(p.value() instanceof LabelComponent)) // skip any that gave us a label .toList(); // Only show the client title if any of the client settings are available @@ -63,8 +68,8 @@ public static CustomForm buildForm(GeyserSession session) { if (showClientSettings) { builder.label("geyser.settings.title.client"); - for (PreferenceHolder preference : preferences) { - builder.component(preference.component(session)); + for (var preferenceData : preferences) { + builder.component(preferenceData.value()); } } @@ -103,8 +108,9 @@ public static CustomForm buildForm(GeyserSession session) { builder.validResultHandler((response) -> { if (showClientSettings) { - for (PreferenceHolder preference : preferences) { - preference.onFormUpdate(response.next(), session); + for (var preferenceData : preferences) { + Object value = Objects.requireNonNull(response.next(), "response for preference " + preferenceData.key()); + preferenceData.key().onFormResponse(value); } } From 0b36ff1736b838a97ab1d40242c6dc1dc63eed21 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 12 Jul 2023 04:38:09 -0400 Subject: [PATCH 3/3] Move CooldownType to its own class like EmoteOffhandWorkaroundOption --- .../geyser/configuration/CooldownType.java | 74 +++++++++++++++++++ .../configuration/GeyserConfiguration.java | 3 +- .../GeyserJacksonConfiguration.java | 5 +- .../geyser/preference/CooldownPreference.java | 3 +- .../session/cache/PreferencesCache.java | 8 +- .../geysermc/geyser/util/CooldownUtils.java | 47 +----------- 6 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/configuration/CooldownType.java diff --git a/core/src/main/java/org/geysermc/geyser/configuration/CooldownType.java b/core/src/main/java/org/geysermc/geyser/configuration/CooldownType.java new file mode 100644 index 00000000000..123de4c1aed --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/configuration/CooldownType.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.configuration; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.IOException; + +@Getter +@AllArgsConstructor +public enum CooldownType { + TITLE("options.attack.crosshair"), + ACTIONBAR("options.attack.hotbar"), + DISABLED("options.off"); + + public static final String OPTION_DESCRIPTION = "options.attackIndicator"; + public static final CooldownType[] VALUES = values(); + + private final String translation; + + /** + * Convert the CooldownType string (from config) to the enum, DISABLED on fail + * + * @param name CooldownType string + * @return The converted CooldownType + */ + public static CooldownType getByName(String name) { + if (name.equalsIgnoreCase("true")) { // Backwards config compatibility + return CooldownType.TITLE; + } + + for (CooldownType type : VALUES) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return DISABLED; + } + + public static class Deserializer extends JsonDeserializer { + @Override + public CooldownType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + return CooldownType.getByName(p.getValueAsString()); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index f7f45f63539..133fb870175 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -33,7 +33,6 @@ import org.geysermc.geyser.network.CIDRMatcher; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.util.CooldownUtils; import java.nio.file.Path; import java.util.List; @@ -83,7 +82,7 @@ public interface GeyserConfiguration { boolean isAllowThirdPartyEars(); - CooldownUtils.CooldownType getShowCooldown(); + CooldownType getShowCooldown(); boolean isShowCoordinates(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index c6badde952a..8c0eb692db9 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -39,7 +39,6 @@ import org.geysermc.geyser.network.CIDRMatcher; import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.util.CooldownUtils; import java.io.IOException; import java.nio.file.Path; @@ -100,9 +99,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("allow-third-party-capes") private boolean allowThirdPartyCapes = true; - @JsonDeserialize(using = CooldownUtils.CooldownType.Deserializer.class) + @JsonDeserialize(using = CooldownType.Deserializer.class) @JsonProperty("show-cooldown") - private CooldownUtils.CooldownType showCooldown = CooldownUtils.CooldownType.TITLE; + private CooldownType showCooldown = CooldownType.TITLE; @JsonProperty("show-coordinates") private boolean showCoordinates = true; diff --git a/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java index 50c193c99a1..4087f15b36e 100644 --- a/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java +++ b/core/src/main/java/org/geysermc/geyser/preference/CooldownPreference.java @@ -31,13 +31,12 @@ import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.preference.Preference; import org.geysermc.geyser.api.preference.PreferenceKey; +import org.geysermc.geyser.configuration.CooldownType; import org.geysermc.geyser.session.GeyserSession; import java.util.Arrays; import java.util.List; -import static org.geysermc.geyser.util.CooldownUtils.CooldownType; - public class CooldownPreference extends Preference { public static final PreferenceKey KEY = new PreferenceKey<>("geyser:cooldown_type"); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java index 3864e2523ef..d009a5d47f8 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java @@ -30,12 +30,12 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.preference.Preference; import org.geysermc.geyser.api.preference.PreferenceKey; +import org.geysermc.geyser.configuration.CooldownType; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.preference.CooldownPreference; import org.geysermc.geyser.preference.CustomSkullsPreference; import org.geysermc.geyser.preference.ShowCoordinatesPreference; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.CooldownUtils; import java.util.Map; import java.util.Optional; @@ -99,9 +99,9 @@ public boolean getEffectiveShowSkulls() { } - public CooldownUtils.CooldownType getEffectiveCooldown() { - if (session.getGeyser().getConfig().getShowCooldown() == CooldownUtils.CooldownType.DISABLED) { - return CooldownUtils.CooldownType.DISABLED; + public CooldownType getEffectiveCooldown() { + if (session.getGeyser().getConfig().getShowCooldown() == CooldownType.DISABLED) { + return CooldownType.DISABLED; } return require(CooldownPreference.KEY).value(); } diff --git a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java index 443ccb2693f..b7346382b7c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java @@ -25,18 +25,12 @@ package org.geysermc.geyser.util; -import com.fasterxml.jackson.core.JacksonException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import lombok.AllArgsConstructor; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; -import lombok.Getter; +import org.geysermc.geyser.configuration.CooldownType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PreferencesCache; import org.geysermc.geyser.text.ChatColor; -import java.io.IOException; import java.util.concurrent.TimeUnit; /** @@ -151,43 +145,4 @@ private static String getTitle(GeyserSession session) { return builder.toString(); } - @Getter - @AllArgsConstructor - public enum CooldownType { - TITLE("options.attack.crosshair"), - ACTIONBAR("options.attack.hotbar"), - DISABLED("options.off"); - - public static final String OPTION_DESCRIPTION = "options.attackIndicator"; - public static final CooldownType[] VALUES = values(); - - private final String translation; - - /** - * Convert the CooldownType string (from config) to the enum, DISABLED on fail - * - * @param name CooldownType string - * - * @return The converted CooldownType - */ - public static CooldownType getByName(String name) { - if (name.equalsIgnoreCase("true")) { // Backwards config compatibility - return CooldownType.TITLE; - } - - for (CooldownType type : VALUES) { - if (type.name().equalsIgnoreCase(name)) { - return type; - } - } - return DISABLED; - } - - public static class Deserializer extends JsonDeserializer { - @Override - public CooldownType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { - return CooldownType.getByName(p.getValueAsString()); - } - } - } }