/
UserInputRouter.java
119 lines (106 loc) · 4.74 KB
/
UserInputRouter.java
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
package mezz.jei.common.input.handlers;
import com.mojang.blaze3d.platform.InputConstants;
import mezz.jei.common.input.IInternalKeyMappings;
import mezz.jei.common.input.IUserInputHandler;
import mezz.jei.common.input.UserInput;
import mezz.jei.core.config.IClientConfig;
import net.minecraft.client.gui.screens.Screen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class UserInputRouter {
private static final Logger LOGGER = LogManager.getLogger();
private final IClientConfig config;
private final CombinedInputHandler combinedInputHandler;
private final Map<InputConstants.Key, IUserInputHandler> pending = new HashMap<>();
public UserInputRouter(IClientConfig config, IUserInputHandler... inputHandlers) {
this.config = config;
this.combinedInputHandler = new CombinedInputHandler(inputHandlers);
}
public boolean handleUserInput(Screen screen, UserInput input, IInternalKeyMappings keyBindings) {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Received user input: {}", input);
}
return switch (input.getClickState()) {
case IMMEDIATE -> handleImmediateClick(screen, input, keyBindings);
case SIMULATE -> handleSimulateClick(screen, input, keyBindings);
case EXECUTE -> handleExecuteClick(screen, input, keyBindings);
};
}
/*
* A vanilla click or key-down will be handled immediately.
* We do not track the mousedDown for it,
* the first handler to use it will be the "winner", the rest will get a clicked-out.
*/
private boolean handleImmediateClick(Screen screen, UserInput input, IInternalKeyMappings keyBindings) {
IUserInputHandler oldClick = this.pending.remove(input.getKey());
if (oldClick != null) {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Canceled previous user input: {}", oldClick);
}
}
return this.combinedInputHandler.handleUserInput(screen, input, keyBindings)
.map(callback -> {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Immediate click handled by: {}\n{}", callback, input);
}
return true;
})
.orElse(false);
}
/*
* For JEI-controlled clicks.
* JEI activates clicks when the player clicks down on it and releases the mouse on the same element.
*
* In the first click pass, it is a "simulate" to check if the handler can handle the click,
* and it will be added to mousedDown.
* In the second pass, all handlers that were in mousedDown will be sent the real click.
*/
private boolean handleSimulateClick(Screen screen, UserInput input, IInternalKeyMappings keyBindings) {
IUserInputHandler oldClick = this.pending.remove(input.getKey());
if (oldClick != null) {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Canceled pending user input: {}", oldClick);
}
}
return this.combinedInputHandler.handleUserInput(screen, input, keyBindings)
.map(callback -> {
this.pending.put(input.getKey(), callback);
if (config.isDebugModeEnabled()) {
LOGGER.debug("Click successfully simulated by: {}\n{}", callback, input);
}
return true;
})
.orElse(false);
}
private boolean handleExecuteClick(Screen screen, UserInput input, IInternalKeyMappings keyBindings) {
return Optional.ofNullable(this.pending.remove(input.getKey()))
.flatMap(inputHandler -> inputHandler.handleUserInput(screen, input, keyBindings))
.map(callback -> {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Click successfully executed by: {}\n{}", callback, input);
}
return true;
})
.orElse(false);
}
public void handleGuiChange() {
LOGGER.debug("The GUI has changed, clearing all pending clicks");
for (InputConstants.Key key : this.pending.keySet()) {
this.combinedInputHandler.handleMouseClickedOut(key);
}
this.pending.clear();
}
public boolean handleMouseScrolled(double mouseX, double mouseY, double scrollDelta) {
return this.combinedInputHandler.handleMouseScrolled(mouseX, mouseY, scrollDelta)
.map(callback -> {
if (config.isDebugModeEnabled()) {
LOGGER.debug("Scroll handled by: {}", callback);
}
return true;
})
.orElse(false);
}
}