Skip to content

Commit

Permalink
[PlaybackSerialiser] Improved error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
ScribbleTAS committed Jul 24, 2024
1 parent f297b3f commit c5faf56
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class PlaybackMetadata {

private String extensionName;
private LinkedHashMap<String, String> data;

private static String SEPERATOR = ":";

public PlaybackMetadata(PlaybackMetadataExtension extension) {
Expand Down Expand Up @@ -81,7 +81,7 @@ public boolean equals(Object obj) {
public static PlaybackMetadata fromStringList(String extensionName, List<String> list) {
PlaybackMetadata out = new PlaybackMetadata(extensionName);

final Pattern pattern = Pattern.compile("(\\w+)\\"+SEPERATOR+"(.+)");
final Pattern pattern = Pattern.compile("(\\w+)\\" + SEPERATOR + "(.+)");

for (String data : list) {
Matcher matcher = pattern.matcher(data);
Expand All @@ -94,19 +94,20 @@ public static PlaybackMetadata fromStringList(String extensionName, List<String>

return out;
}

public static PlaybackMetadata fromHashMap(String extensionName, LinkedHashMap<String, String> data) {
return new PlaybackMetadata(extensionName, new LinkedHashMap<>(data));
}

public static abstract class PlaybackMetadataExtension implements Registerable {

/**
* Currently unused.<br>
* Maybe in the future, TASes have to be created with /create, then you can interactively set the values...<br>
*/
public void onCreate() {};

public void onCreate() {
};

/**
* Runs, when the TASfile is being stored to a file.<br>
* Create a new {@link PlaybackMetadata} with <code>PlaybackMetadata metadata = new PlaybackMetadata(this);</code>.<br>
Expand All @@ -115,14 +116,14 @@ public static abstract class PlaybackMetadataExtension implements Registerable {
* @return The {@link PlaybackMetadata} to be saved in the TASfile
*/
public abstract PlaybackMetadata onStore();

/**
* Runs when the TASfile is being loaded from a file<br>
*
* @param metadata The metadata for this extension to read from
*/
public abstract void onLoad(PlaybackMetadata metadata);

/**
* Runs when the PlaybackController is cleared
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,9 @@ public BigArrayList<TickContainer> deserialise(BigArrayList<String> lines, long
// Extract the tick and set the index
i = extractContainer(container, lines, i);
currentLine = i;
currentTick++;
// Extract container
deserialiseContainer(out, container);
currentTick++;
}
previousTickContainer = null;
return out;
Expand Down Expand Up @@ -711,8 +711,10 @@ protected VirtualKeyboard deserialiseKeyboard(List<String> keyboardStrings) {
String[] keys = matcher.group(1).split(",");
char[] chars = matcher.group(2).toCharArray();

int[] keycodes = deserialiseVirtualKey(keys, VirtualKey.ZERO);
int[] keycodes = deserialiseVirtualKeyboardKey(keys);
out.updateFromState(keycodes, chars);
} else {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Keyboard could not be read. Probably a missing semicolon: %s", line);
}
currentSubtick++;
}
Expand All @@ -732,7 +734,7 @@ protected VirtualMouse deserialiseMouse(List<String> mouseStrings) {
String[] buttons = matcher.group(1).split(",");
String[] functions = matcher.group(2).split(",");

int[] keycodes = deserialiseVirtualKey(buttons, VirtualKey.MOUSEMOVED);
int[] keycodes = deserialiseVirtualMouseKey(buttons);
int scrollwheel;
Integer cursorX;
Integer cursorY;
Expand All @@ -742,13 +744,15 @@ protected VirtualMouse deserialiseMouse(List<String> mouseStrings) {
cursorX = deserialiseRelativeInt("cursorX", functions[1], previousCursorX);
cursorY = deserialiseRelativeInt("cursorY", functions[2], previousCursorY);
} else {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Mouse functions do not have the correct length");
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Mouse can't be read. Probably a missing comma: %s", line);
}

out.updateFromState(keycodes, scrollwheel, cursorX, cursorY);

previousCursorX = cursorX;
previousCursorY = cursorY;
} else {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Mouse is missing a semicolon");
}
currentSubtick++;
}
Expand All @@ -766,57 +770,92 @@ protected VirtualCameraAngle deserialiseCameraAngle(List<String> cameraAngleStri
Matcher matcher = extract("(.+?);(.+)", line);

if (matcher.find()) {
String cameraPitchString = matcher.group(1);
String cameraYawString = matcher.group(2);
String cameraYawString = matcher.group(1);
String cameraPitchString = matcher.group(2);

Float cameraPitch = null;
Float cameraYaw = null;

if (!"null".equals(cameraPitchString))
cameraPitch = deserialiseRelativeFloat("camera pitch", cameraPitchString, previousPitch);
Float cameraPitch = null;

if (!"null".equals(cameraYawString))
cameraYaw = deserialiseRelativeFloat("camera yaw", cameraYawString, previousYaw);

if (!"null".equals(cameraPitchString))
cameraPitch = deserialiseRelativeFloat("camera pitch", cameraPitchString, previousPitch);

out.updateFromState(cameraPitch, cameraYaw);
} else {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Camera is missing a semicolon");
}
currentSubtick++;
}
return out;
}

protected int[] deserialiseVirtualKey(String[] keyString, VirtualKey defaultKey) {
protected int[] deserialiseVirtualKeyboardKey(String[] keyString) {
int[] out = new int[keyString.length];

for (int i = 0; i < keyString.length; i++) {
String key = keyString[i];
out[i] = deserialiseVirtualKey(key, VirtualKey.ZERO, (vkey) -> {
if (vkey < 0) {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Keyboard section contains a mouse key: %s", VirtualKey.get(vkey));
}
});
}
return out;
}

/* If no key is pressed, then a zero key will be used for the state.
* This zero key is either VirtualKey.ZERO on a keyboard or VirtualKey.MOUSEMOVED on a mouse,
* hence the parameter */
if (key.isEmpty()) {
out[i] = defaultKey.getKeycode();
continue;
}

/* Instead of keynames such as W, A, S, KEY_1, NUMPAD3 you can also write the numerical keycodes
* into the tasfile, e.g. 17, 30, 31, 2, 81. This enables TASmod to support every current and future
* keycodes, even if no name was given to the key in VirtualKey.*/
if (isNumeric(key)) {
out[i] = Integer.parseInt(key);
continue;
}
protected int[] deserialiseVirtualMouseKey(String[] keyString) {
int[] out = new int[keyString.length];

out[i] = VirtualKey.getKeycode(key);
for (int i = 0; i < keyString.length; i++) {
String key = keyString[i];
out[i] = deserialiseVirtualKey(key, VirtualKey.MOUSEMOVED, (vkey) -> {
if (vkey >= 0) {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "Mouse section contains a keyboard key: %s", VirtualKey.get(vkey));
}
});
}
return out;
}

protected int deserialiseVirtualKey(String key, VirtualKey defaultKey, WrongKeyCheck keyValidator) {

Integer vkey = null;
/* If no key is pressed, then a zero key will be used for the state.
* This zero key is either VirtualKey.ZERO on a keyboard or VirtualKey.MOUSEMOVED on a mouse,
* hence the parameter */
if (key.isEmpty()) {
vkey = defaultKey.getKeycode();
}
/* Instead of keynames such as W, A, S, KEY_1, NUMPAD3 you can also write the numerical keycodes
* into the tasfile, e.g. 17, 30, 31, 2, 81. This enables TASmod to support every current and future
* keycodes, even if no name was given to the key in VirtualKey.*/
else if (isNumeric(key)) {
vkey = Integer.parseInt(key);
} else {
vkey = VirtualKey.getKeycode(key);
}

if (vkey == null) {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, "The keycode %s does not exist", key);
}

keyValidator.checkKey(vkey);

return vkey;
}

@FunctionalInterface
protected interface WrongKeyCheck {
public void checkKey(int key) throws PlaybackLoadException;
}

protected int parseInt(String name, String intstring) {
try {
return Integer.parseInt(intstring);
} catch (NumberFormatException e) {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, e, "Can't parse integer in %s", name);
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, e, "The %s could not be processed. This should be a number: %s", name, intstring);
}
}

Expand All @@ -840,7 +879,7 @@ protected float parseFloat(String name, String floatstring) {
try {
return Float.parseFloat(floatstring);
} catch (NumberFormatException e) {
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, e, "Can't parse float in %s", name);
throw new PlaybackLoadException(currentLine, currentTick, currentSubtick, e, "The %s could not be processed. This should be a decimal number: %s", name, floatstring);
}
}

Expand Down
24 changes: 12 additions & 12 deletions src/test/java/tasmod/playback/tasfile/SerialiserFlavorBaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -858,30 +858,30 @@ void testDeserialiseMouse() {
expected.updateFromEvent(VirtualKey.MC, true, 15, 25, 34);

assertEquals(expected, actual);
currentTick=29;

currentTick = 29;
List<String> tick2 = new ArrayList<>();
tick2.add(";0,0,0");
tick2.add("LC;0,12,35");
tick2.add("LC,MC;15,25");
Throwable t = assertThrows(PlaybackLoadException.class, ()->{

Throwable t = assertThrows(PlaybackLoadException.class, () -> {
deserialiseMouse(tick2);
});
assertEquals("Line 1, Tick 29, Subtick 2: Mouse functions do not have the correct length", t.getMessage());
currentTick=30;

assertEquals("Line 1, Tick 29, Subtick 2: Mouse can't be read. Probably a missing comma: LC,MC;15,25", t.getMessage());

currentTick = 30;
List<String> tick3 = new ArrayList<>();
tick3.add(";0,0,0");
tick3.add("LC;0,12,35,12");
tick3.add("LC,MC;15,25,15");
Throwable t1 = assertThrows(PlaybackLoadException.class, ()->{

Throwable t1 = assertThrows(PlaybackLoadException.class, () -> {
deserialiseMouse(tick3);
});
assertEquals("Line 1, Tick 30, Subtick 1: Mouse functions do not have the correct length", t1.getMessage());

assertEquals("Line 1, Tick 30, Subtick 1: Mouse can't be read. Probably a missing comma: LC;0,12,35,12", t1.getMessage());
}

/**
Expand Down

0 comments on commit c5faf56

Please sign in to comment.