1
0
forked from Clones/Controlify

refactor binding api (sorry enjarai)

This commit is contained in:
isXander
2023-04-14 20:11:57 +01:00
parent 07b57d5637
commit abe6b27cef
16 changed files with 183 additions and 109 deletions

View File

@ -0,0 +1,272 @@
package dev.isxander.controlify.bindings;
import com.google.gson.JsonObject;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.api.bind.BindRenderer;
import dev.isxander.controlify.api.bind.ControllerBinding;
import dev.isxander.controlify.api.bind.ControllerBindingBuilder;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.gamepad.GamepadController;
import dev.isxander.controlify.gui.DrawSize;
import net.minecraft.client.KeyMapping;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.ApiStatus;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BooleanSupplier;
public class ControllerBindingImpl<T extends ControllerState> implements ControllerBinding {
private final Controller<T, ?> controller;
private IBind<T> bind;
private final IBind<T> defaultBind;
private BindRenderer renderer;
private final ResourceLocation id;
private final Component name, description, category;
private final KeyMappingOverride override;
private static final Map<Controller<?, ?>, Set<IBind<?>>> pressedBinds = new HashMap<>();
private ControllerBindingImpl(Controller<T, ?> controller, IBind<T> defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category) {
this.controller = controller;
this.bind = this.defaultBind = defaultBind;
this.renderer = new BindRendererImpl(bind);
this.id = id;
this.override = vanillaOverride;
this.name = name;
this.description = description;
this.category = category;
}
@Override
public float state() {
return bind.state(controller.state());
}
@Override
public float prevState() {
return bind.state(controller.prevState());
}
@Override
public boolean held() {
return bind.held(controller.state());
}
@Override
public boolean prevHeld() {
return bind.held(controller.prevState());
}
@Override
public boolean justPressed() {
if (hasBindPressed(this)) return false;
if (held() && !prevHeld()) {
addPressedBind(this);
return true;
} else {
return false;
}
}
@Override
public boolean justReleased() {
if (hasBindPressed(this)) return false;
if (!held() && prevHeld()) {
addPressedBind(this);
return true;
} else {
return false;
}
}
public IBind<T> currentBind() {
return bind;
}
public void setCurrentBind(IBind<T> bind) {
this.bind = bind;
this.renderer = new BindRendererImpl(bind);
Controlify.instance().config().setDirty();
}
public IBind<T> defaultBind() {
return defaultBind;
}
@Override
public void resetBind() {
setCurrentBind(defaultBind());
}
public ResourceLocation id() {
return id;
}
@Override
public Component name() {
return name;
}
@Override
public Component description() {
return description;
}
@Override
public Component category() {
return category;
}
@Override
public boolean isUnbound() {
return bind instanceof EmptyBind;
}
@Override
public KeyMappingOverride override() {
return override;
}
@Override
public JsonObject toJson() {
return currentBind().toJson();
}
@Override
public BindRenderer renderer() {
return renderer;
}
// FIXME: very hack solution please remove me
public static void clearPressedBinds(Controller<?, ?> controller) {
if (pressedBinds.containsKey(controller)) {
pressedBinds.get(controller).clear();
}
}
private static boolean hasBindPressed(ControllerBindingImpl<?> binding) {
var pressed = pressedBinds.getOrDefault(binding.controller, Set.of());
return pressed.containsAll(getBinds(binding.bind));
}
private static void addPressedBind(ControllerBindingImpl<?> binding) {
pressedBinds.computeIfAbsent(binding.controller, c -> new HashSet<>()).addAll(getBinds(binding.bind));
}
private static Set<IBind<?>> getBinds(IBind<?> bind) {
return Set.of(bind);
}
@ApiStatus.Internal
public static final class ControllerBindingBuilderImpl<T extends ControllerState> implements ControllerBindingBuilder<T> {
private final Controller<T, ?> controller;
private IBind<T> bind;
private ResourceLocation id;
private Component name = null, description = null, category = null;
private KeyMappingOverride override = null;
public ControllerBindingBuilderImpl(Controller<T, ?> controller) {
this.controller = controller;
}
@Override
public ControllerBindingBuilder<T> identifier(ResourceLocation id) {
this.id = id;
return this;
}
@Override
public ControllerBindingBuilder<T> identifier(String namespace, String path) {
return identifier(new ResourceLocation(namespace, path));
}
@Override
public ControllerBindingBuilder<T> defaultBind(IBind<T> bind) {
this.bind = bind;
return this;
}
@Override
@SuppressWarnings("unchecked")
public ControllerBindingBuilder<T> defaultBind(GamepadBinds gamepadBind) {
if (controller instanceof GamepadController gamepad) {
this.bind = (IBind<T>) gamepadBind.forGamepad(gamepad);
} else {
this.bind = new EmptyBind<>();
}
return this;
}
@Override
public ControllerBindingBuilder<T> name(Component name) {
this.name = name;
return this;
}
@Override
public ControllerBindingBuilder<T> description(Component description) {
this.description = description;
return this;
}
@Override
public ControllerBindingBuilder<T> category(Component category) {
this.category = category;
return this;
}
@Override
public ControllerBindingBuilder<T> vanillaOverride(KeyMapping keyMapping, BooleanSupplier toggleable) {
this.override = new KeyMappingOverride(keyMapping, toggleable);
return this;
}
@Override
public ControllerBindingBuilder<T> vanillaOverride(KeyMapping keyMapping) {
return vanillaOverride(keyMapping, () -> false);
}
@Override
public ControllerBinding build() {
Validate.notNull(id, "Identifier must be set");
Validate.notNull(bind, "Default bind must be set");
Validate.notNull(category, "Category must be set");
if (name == null)
name = Component.translatable("controlify.binding." + id.getNamespace() + "." + id.getPath());
if (description == null) {
var descKey = "controlify.binding." + id.getNamespace() + "." + id.getPath() + ".desc";
if (Language.getInstance().has(descKey)) {
description = Component.translatable(descKey);
} else {
description = Component.empty();
}
}
return new ControllerBindingImpl<>(controller, bind, id, override, name, description, category);
}
}
private record BindRendererImpl(IBind<?> bind) implements BindRenderer {
@Override
public void render(PoseStack poseStack, int x, int centerY) {
bind.draw(poseStack, x, centerY);
}
@Override
public DrawSize size() {
return bind.drawSize();
}
}
}