-
-
Notifications
You must be signed in to change notification settings - Fork 86
Expand file tree
/
Copy pathInputComponent.java
More file actions
199 lines (167 loc) · 6.67 KB
/
Copy pathInputComponent.java
File metadata and controls
199 lines (167 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package dev.isxander.controlify.controller.input;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.bindings.ControlifyBindApiImpl;
import dev.isxander.controlify.api.bind.InputBinding;
import dev.isxander.controlify.bindings.input.InputType;
import dev.isxander.controlify.config.settings.device.DeviceSettings;
import dev.isxander.controlify.config.settings.profile.InputSettings;
import dev.isxander.controlify.controller.*;
import dev.isxander.controlify.controller.impl.ECSComponentImpl;
import dev.isxander.controlify.controller.input.mapping.ControllerMapping;
import dev.isxander.controlify.utils.CUtil;
import net.minecraft.resources.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class InputComponent extends ECSComponentImpl {
public static final Identifier ID = CUtil.rl("input");
private final ControllerEntity controller;
private DeviceSettings deviceSettings; // Cached reference
private ControllerState
stateNow = ControllerState.EMPTY,
stateThen = ControllerState.EMPTY;
private DeadzoneControllerStateView
deadzoneStateNow,
deadzoneStateThen;
private final int buttonCount, axisCount, hatCount;
private final Map<Identifier, DeadzoneGroup> deadzoneAxes;
private final boolean definitelyGamepad;
private final Map<Identifier, InputBinding> inputBindings;
public InputComponent(
ControllerEntity controller,
int buttonCount, int axisCount, int hatCount,
boolean definitelyGamepad,
Set<DeadzoneGroup> deadzoneAxes,
String mappingId
) {
this.controller = controller;
this.buttonCount = buttonCount;
this.axisCount = axisCount;
this.hatCount = hatCount;
this.definitelyGamepad = definitelyGamepad;
this.deadzoneAxes = deadzoneAxes.stream()
.collect(Collectors.toMap(
DeadzoneGroup::name,
Function.identity(),
(x, y) -> y,
LinkedHashMap::new
));
this.inputBindings = new LinkedHashMap<>();
this.updateDeadzoneView();
}
public ControllerStateView stateNow() {
return this.deadzoneStateNow;
}
public ControllerStateView stateThen() {
return this.deadzoneStateThen;
}
public ControllerState rawStateNow() {
return this.stateNow;
}
public ControllerState rawStateThen() {
return this.stateThen;
}
public void pushState(ControllerState state) {
ControllerMapping mapping = getDeviceMapping();
if (mapping != null) {
state = mapping.mapState(state);
}
this.stateThen = this.stateNow;
this.stateNow = state;
this.updateDeadzoneView();
// Get all the CompoundInputs from the current inputs.
List<InputBinding> sortedBindings = this.inputBindings.values().stream()
.filter(object -> object.boundInput().type() == InputType.COMPOUND)
.toList();
List<Identifier> boundIdentifiers = new ArrayList<>();
// For all the active CompoundInputs, get a list of the underlying active inputs.
sortedBindings.forEach(inputBinding -> {
if (inputBinding.boundInput().state(this.deadzoneStateNow) == 1)
boundIdentifiers.addAll(inputBinding.boundInput().getRelevantInputs());
});
Set<Identifier> boundIdentifierSet = new HashSet<>(boundIdentifiers);
// Prevent those active inputs from being used in a non-compound bind.
for (InputBinding binding : this.inputBindings.values()) {
if (binding.boundInput().type() != InputType.COMPOUND) {
if (boundIdentifierSet.containsAll(binding.boundInput().getRelevantInputs())) {
binding.limitActivity();
}
}
binding.pushState(this.deadzoneStateNow);
}
}
public @Nullable InputBinding getBinding(Identifier id) {
return this.inputBindings.get(id);
}
public Collection<InputBinding> getAllBindings() {
return this.inputBindings.values();
}
public void notifyGuiPressOutputsOfNavigate() {
for (InputBinding binding : this.inputBindings.values()) {
binding.guiPressed().onNavigate();
}
}
@Override
public void attach(ControllerEntity controller) {
super.attach(controller);
// Cache device settings reference
this.deviceSettings = Controlify.instance().config().getSettings()
.getOrCreateDeviceSettings(controller.uid());
// Populate bindings
for (InputBinding binding : ControlifyBindApiImpl.INSTANCE.provideBindsForController(controller)) {
this.inputBindings.put(binding.id(), binding);
}
// Note: No need to copy bound inputs from config here since InputBindingImpl.boundInput()
// now reads directly from the config (via inputComponent.settings().bindings.bindings)
}
public int buttonCount() {
return this.buttonCount;
}
public int axisCount() {
return this.axisCount;
}
public int hatCount() {
return this.hatCount;
}
public boolean isDefinitelyGamepad() {
return this.definitelyGamepad;
}
public Map<Identifier, DeadzoneGroup> getDeadzoneGroups() {
ControllerMapping mapping = getDeviceMapping();
if (mapping != null) {
return mapping.deadzones();
} else {
return this.deadzoneAxes;
}
}
private @Nullable ControllerMapping getDeviceMapping() {
// Use cached device settings to avoid repeated lookups
return deviceSettings.mapping;
}
public ControllerEntity getController() {
return controller();
}
public InputSettings settings() {
return this.controller().settings().input;
}
public InputSettings defaultSettings() {
return this.controller().defaultSettings().input;
}
@Override
public Identifier id() {
return ID;
}
private void updateDeadzoneView() {
this.deadzoneStateNow = new DeadzoneControllerStateView(this.stateNow, this);
this.deadzoneStateThen = new DeadzoneControllerStateView(this.stateThen, this);
}
Optional<Identifier> getDeadzoneForAxis(Identifier axis) {
for (DeadzoneGroup group : this.getDeadzoneGroups().values()) {
if (group.axes().contains(axis)) {
return Optional.of(group.name());
}
}
return Optional.empty();
}
}