Skip to content

Commit 9d9a26f

Browse files
ScribbleScribble
authored andcommitted
Fixes #106, Documentation 🚂 in VirtualInput
1 parent b96a10b commit 9d9a26f

File tree

1 file changed

+125
-59
lines changed

1 file changed

+125
-59
lines changed

src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java

Lines changed: 125 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Iterator;
55
import java.util.List;
66

7+
import de.scribble.lp.tasmod.TASmod;
78
import de.scribble.lp.tasmod.inputcontainer.InputContainer;
89
import de.scribble.lp.tasmod.inputcontainer.TickInputContainer;
910
import de.scribble.lp.tasmod.mixin.AccessorRunStuff;
@@ -14,35 +15,57 @@
1415
/**
1516
* One of the core classes of this mod <br>
1617
* <br>
17-
* This mimics peripherals used to control minecraft which are: The keyboard, the mouse and the angle of the player, which is called "Subticks" in this case
18-
* <i>(this came from a time when the camera angle was actually updated on a subtick level)</i>.<br>
18+
* This mimics peripherals used to control minecraft which are: The keyboard,
19+
* the mouse and the angle of the player, which is called "Subticks" in this
20+
* case <i>(this came from a time when the camera angle was actually updated on
21+
* a subtick level)</i>.<br>
1922
* <br>
20-
* For each peripheral there are 2 states. The "current" state <i>(e.g. {@linkplain #currentKeyboard})</i>, which is the state of what the game actually currently recognizes and the "next" state <i>(e.g. {@linkplain #nextKeyboard})</i> which either the buttons pressed on the keyboard, or the buttons pressed in the next playback tick.<br>
23+
* For each peripheral there are 2 states. The "current" state <i>(e.g.
24+
* {@linkplain #currentKeyboard})</i>, which is the state of what the game
25+
* actually currently recognizes and the "next" state <i>(e.g.
26+
* {@linkplain #nextKeyboard})</i> which either the buttons pressed on the
27+
* keyboard, or the buttons pressed in the next playback tick.<br>
2128
* <br>
22-
* Outside of this class, there is a third state, which is the Vanilla Minecraft keybindings, which, in the best case, should be a copy of the "current" state. <br>
23-
* <h2>Events</h2>
24-
* To update the vanilla keybindings you need something called key events. An event for a keyboard might look like this <br>
29+
* Outside of this class, there is a third state, which is the Vanilla Minecraft
30+
* keybindings, which, in the best case, should be a copy of the "current"
31+
* state. <br>
32+
* <h2>Events</h2> To update the vanilla keybindings you need something called
33+
* key events. An event for a keyboard might look like this <br>
2534
* <br>
2635
* <b>17,true,'w'</b><br>
2736
* <br>
28-
* Something like this is sent by the LWJGL methods to the vanilla methods to update the keybindings. <br>
29-
* In this case it is the key with the keycode 17 (The 'W' key), in the state true which means it is pressed down. And the 'w' is the character that is associated with that key <br>
37+
* Something like this is sent by the LWJGL methods to the vanilla methods to
38+
* update the keybindings. <br>
39+
* In this case it is the key with the keycode 17 (The 'W' key), in the state
40+
* true which means it is pressed down. And the 'w' is the character that is
41+
* associated with that key <br>
3042
* <br>
31-
* You can find a complete list of LWJGL keycodes in {@link VirtualKeyboard}.<br>
43+
* You can find a complete list of LWJGL keycodes in
44+
* {@link VirtualKeyboard}.<br>
3245
* <br>
33-
* If W is released, the key event for this would look something like this: <b>17, false, NULL</b>
34-
* <br>
35-
* From that, the vanilla keybindings know which key is currently pressed down. As a bonus, the character 'w' is used when typing in a textfield.<br>
36-
* <h2>Emulating events</h2>
37-
* With the key events from LWJGL, so from the "physical keyboard", we can update the nextKeyboard in the {@link #updateNextKeyboard(int, boolean, char)} method.<br>
46+
* If W is released, the key event for this would look something like this:
47+
* <b>17, false, NULL</b> <br>
48+
* From that, the vanilla keybindings know which key is currently pressed down.
49+
* As a bonus, the character 'w' is used when typing in a textfield.<br>
50+
* <h2>Emulating events</h2> With the key events from LWJGL, so from the
51+
* "physical keyboard", we can update the nextKeyboard in the
52+
* {@link #updateNextKeyboard(int, boolean, char)} method.<br>
3853
* This method is called every frame and also works in tickrate 0.<br>
3954
* <br>
40-
* And on every tick, we call {@link #updateCurrentKeyboard()}, which updates the currentKeyboard with a copy of nextKeyboard. <br>
41-
* However, we still need to update the Vanilla Minecraft keybinding by using key events.<br>
42-
* To solve this problem we can use {@link VirtualKeyboard#getDifference(VirtualKeyboard)}, which compares 2 keyboards and extracts the key events from that.<br>
55+
* And on every tick, we call {@link #updateCurrentKeyboard()}, which updates
56+
* the currentKeyboard with a copy of nextKeyboard. <br>
57+
* However, we still need to update the Vanilla Minecraft keybinding by using
58+
* key events.<br>
59+
* To solve this problem we can use
60+
* {@link VirtualKeyboard#getDifference(VirtualKeyboard)}, which compares 2
61+
* keyboards and extracts the key events from that.<br>
4362
* <br>
44-
* For instance if we have a keyboard, where nothing is pressed, then a keyboard where only "W" is pressed, we can assume that the key event responsible for that change 17,true,? is. <br>
45-
* But as indicated by the ? we actually don't know the character that is typed there. And for that we need to store the characters seperately in the keyboard ({@link VirtualKeyboard#getCharList()}).<br>
63+
* For instance if we have a keyboard, where nothing is pressed, then a keyboard
64+
* where only "W" is pressed, we can assume that the key event responsible for
65+
* that change 17,true,? is. <br>
66+
* But as indicated by the ? we actually don't know the character that is typed
67+
* there. And for that we need to store the characters seperately in the
68+
* keyboard ({@link VirtualKeyboard#getCharList()}).<br>
4669
* <br>
4770
* The advantage of this system is:
4871
* <ul>
@@ -58,20 +81,24 @@
5881
public class VirtualInput {
5982

6083
/**
61-
* The container where all inputs get stored during recording or stored and ready to be played back
84+
* The container where all inputs get stored during recording or stored and
85+
* ready to be played back
6286
*/
6387
private InputContainer container = new InputContainer();
6488

6589
// ===========================Keyboard=================================
6690

6791
/**
68-
* The state of the keyboard recognized by the game. Updated on a tick basis <br>
92+
* The state of the keyboard recognized by the game. Updated on a tick basis
93+
* <br>
6994
* See also: {@link VirtualInput}
7095
*/
7196
private VirtualKeyboard currentKeyboard = new VirtualKeyboard();
7297

7398
/**
74-
* The state of the keyboard which will replace {@linkplain VirtualInput#currentKeyboard} in the next tick. Updated every frame<br>
99+
* The state of the keyboard which will replace
100+
* {@linkplain VirtualInput#currentKeyboard} in the next tick. Updated every
101+
* frame<br>
75102
* See also: {@link VirtualInput}
76103
*/
77104
private VirtualKeyboard nextKeyboard = new VirtualKeyboard();
@@ -362,13 +389,14 @@ public float getSubtickYaw() {
362389
}
363390

364391
// =====================================Container===========================================
365-
392+
366393
public InputContainer getContainer() {
367394
return container;
368395
}
369396

370397
/**
371-
* Updates the input container and the {@link #nextKeyboard} as well as {@link #nextMouse}<br>
398+
* Updates the input container and the {@link #nextKeyboard} as well as
399+
* {@link #nextMouse}<br>
372400
* Gets executed each game tick
373401
*/
374402
public void updateContainer() {
@@ -377,76 +405,114 @@ public void updateContainer() {
377405
}
378406

379407
/**
380-
* Replaces the {@link #container}, used in
408+
* Replaces the {@link #container}, used in
409+
*
381410
* @param container to replace the current one
382411
*/
383412
public void setContainer(InputContainer container) {
384413
this.container = container;
385414
}
386415

387416
// =====================================Savestates===========================================
388-
389-
public void loadSavestate(InputContainer container) {
417+
418+
/**
419+
* Loads and preloads the inputs from the new InputContainer to
420+
* {@link #container}
421+
*
422+
* @param savestatecontainer The container that should be loaded.
423+
*/
424+
public void loadSavestate(InputContainer savestatecontainer) {
425+
390426
if (this.container.isPlayingback()) {
391-
preloadInput(this.container, container.size() - 1);
392-
this.container.setIndex(container.size());
427+
preloadInput(this.container, savestatecontainer.size() - 1); // Preloading from the current container and from the second to last index of
428+
// the savestatecontainer. Since this is executed during playback,
429+
// we will only load the position of the savestate container and not replace the
430+
// container itself
431+
432+
this.container.setIndex(savestatecontainer.size()); // Set the "playback" index of the current container to the latest index of the
433+
// savestatecontainer. Meaning this index will be played next
393434

394435
} else if (this.container.isRecording()) {
395-
String start = container.getStartLocation();
396-
preloadInput(container, container.size() - 1);
436+
String start = savestatecontainer.getStartLocation(); // TODO Another start location thing to keep in mind
437+
preloadInput(savestatecontainer, savestatecontainer.size() - 1); // Preload the input of the savestate
397438

398-
nextKeyboard = new VirtualKeyboard();
439+
nextKeyboard = new VirtualKeyboard(); // Unpress the nextKeyboard and mouse to get rid of the preloaded inputs in the
440+
// next keyboard. Note that these inputs are still loaded in the current
441+
// keyboard
399442
nextMouse = new VirtualMouse();
400443

401-
container.setIndex(container.size());
402-
container.setTASState(TASstate.RECORDING);
403-
container.setStartLocation(start);
404-
this.container = container;
444+
savestatecontainer.setIndex(savestatecontainer.size());
445+
savestatecontainer.setTASState(TASstate.RECORDING);
446+
savestatecontainer.setStartLocation(start); //TODO Another one
447+
this.container = savestatecontainer; //Replace the current container with the savestated container
405448
}
406449
}
407450

451+
/**
452+
* Preloads the specified index from, the container to {@link #nextMouse} and {@link #nextKeyboard}
453+
* @param container The container from which the inputs should be pre loaded
454+
* @param index The index of the container from which the inputs should be loaded
455+
*/
408456
private void preloadInput(InputContainer container, int index) {
409-
TickInputContainer tickcontainer = container.get(index).clone();
410-
411-
nextKeyboard = tickcontainer.getKeyboard().clone();
412-
nextMouse = tickcontainer.getMouse().clone();
457+
TickInputContainer tickcontainer = container.get(index);
413458

414-
((AccessorRunStuff) Minecraft.getMinecraft()).runTickKeyboardAccessor();
415-
((AccessorRunStuff) Minecraft.getMinecraft()).runTickMouseAccessor();
459+
if (tickcontainer != null) {
460+
tickcontainer = tickcontainer.clone();
461+
nextKeyboard = tickcontainer.getKeyboard().clone();
462+
nextMouse = tickcontainer.getMouse().clone();
416463

464+
((AccessorRunStuff) Minecraft.getMinecraft()).runTickKeyboardAccessor(); // Letting mouse and keyboard tick once to load inputs into the "currentKeyboard"
465+
((AccessorRunStuff) Minecraft.getMinecraft()).runTickMouseAccessor();
466+
} else {
467+
TASmod.logger.warn("Can't preload inputs, specified inputs are null!");
468+
}
417469
}
418-
470+
419471
// =====================================Debug===========================================
420-
421-
public class InputEvent{
472+
473+
public class InputEvent {
422474
public int tick;
423475
public List<VirtualKeyboardEvent> keyboardevent;
424476
public List<VirtualMouseEvent> mouseEvent;
425477
public VirtualSubticks subticks;
426-
478+
427479
public InputEvent(int tick, List<VirtualKeyboardEvent> keyboardevent, List<VirtualMouseEvent> mouseEvent, VirtualSubticks subticks) {
428-
this.tick=tick;
480+
this.tick = tick;
429481
this.keyboardevent = keyboardevent;
430482
this.mouseEvent = mouseEvent;
431483
this.subticks = subticks;
432484
}
433485
}
434-
486+
487+
/**
488+
* Gets all InputEvents from the current container.<br>
489+
* <br>
490+
* Container and input events differ in that input events are the events that get accepted by Minecraft in the runTickKeyboard.<br>
491+
* The container however stores the current inputs and can calculate the corresponding input events from that, but it does it only when you are playing back or recording.<br>
492+
* <br>
493+
* This however runs through the {@link VirtualInput#container} and generates the input events on for debug purposes.
494+
* @return
495+
*/
435496
public List<InputEvent> getAllInputEvents() {
436-
List<InputEvent> main=new ArrayList<>();
497+
498+
List<InputEvent> main = new ArrayList<>();
499+
437500
for (int i = 0; i < container.size(); i++) {
438-
TickInputContainer tick=container.get(i);
439-
TickInputContainer nextTick=container.get(i+1);
440-
if(nextTick==null) {
441-
nextTick=new TickInputContainer(i+1);
442-
}
443-
VirtualKeyboard kb=tick.getKeyboard();
444-
List<VirtualKeyboardEvent> kbe=kb.getDifference(nextTick.getKeyboard());
445501

446-
VirtualMouse m=tick.getMouse();
447-
List<VirtualMouseEvent> me=m.getDifference(nextTick.getMouse());
502+
TickInputContainer tick = container.get(i);
503+
TickInputContainer nextTick = container.get(i + 1);
504+
505+
if (nextTick == null) {
506+
nextTick = new TickInputContainer(i + 1); //Fills the last tick in the container with an empty TickInputContainer
507+
}
448508

449-
main.add(new InputEvent(tick.getTick(), kbe, me, tick.getSubticks()));
509+
VirtualKeyboard keyboard = tick.getKeyboard();
510+
List<VirtualKeyboardEvent> keyboardEventsList = keyboard.getDifference(nextTick.getKeyboard());
511+
512+
VirtualMouse mouse = tick.getMouse();
513+
List<VirtualMouseEvent> mouseEventsList = mouse.getDifference(nextTick.getMouse());
514+
515+
main.add(new InputEvent(tick.getTick(), keyboardEventsList, mouseEventsList, tick.getSubticks()));
450516
}
451517
return main;
452518
}

0 commit comments

Comments
 (0)