diff --git a/src/main/java/com/minecrafttas/tasmod/TASmodClient.java b/src/main/java/com/minecrafttas/tasmod/TASmodClient.java index 885d4b50..fca5e374 100644 --- a/src/main/java/com/minecrafttas/tasmod/TASmodClient.java +++ b/src/main/java/com/minecrafttas/tasmod/TASmodClient.java @@ -36,6 +36,7 @@ import com.minecrafttas.tasmod.playback.metadata.builtin.StartpositionMetadataExtension; import com.minecrafttas.tasmod.playback.tasfile.flavor.builtin.AlphaFlavor; import com.minecrafttas.tasmod.playback.tasfile.flavor.builtin.Beta1Flavor; +import com.minecrafttas.tasmod.playback.tasfile.flavor.builtin.ParkourCalculatorFlavor; import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; import com.minecrafttas.tasmod.registries.TASmodKeybinds; import com.minecrafttas.tasmod.registries.TASmodPackets; @@ -330,10 +331,12 @@ private void registerPlaybackMetadata(Minecraft mc) { public static Beta1Flavor betaFlavor = new Beta1Flavor(); public static AlphaFlavor alphaFlavor = new AlphaFlavor(); + public static ParkourCalculatorFlavor parkourFlavor = new ParkourCalculatorFlavor(); private void registerSerialiserFlavors(Minecraft mc) { TASmodAPIRegistry.SERIALISER_FLAVOR.register(betaFlavor); TASmodAPIRegistry.SERIALISER_FLAVOR.register(alphaFlavor); + TASmodAPIRegistry.SERIALISER_FLAVOR.register(parkourFlavor); } public static DesyncMonitorFileCommandExtension desyncMonitorFileCommandExtension; diff --git a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java index b28b0416..bbc531a9 100644 --- a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java +++ b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java @@ -20,6 +20,7 @@ import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; +import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.Logger; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; @@ -276,7 +277,6 @@ public String setTASStateClient(TASstate stateIn, boolean verbose) { return verbose ? TextFormatting.GREEN + "Pausing a playback" : ""; case NONE: stopPlayback(true); - state = TASstate.NONE; return verbose ? TextFormatting.GREEN + "Stopping the playback" : ""; } } else if (state == TASstate.PAUSED) { @@ -321,6 +321,9 @@ private void stopRecording() { private void startPlayback() { logger.debug(LoggerMarkers.Playback, "Starting playback"); + if (inputs.isEmpty()) + return; + state = TASstate.PLAYBACK; InputContainer initialContainer = inputs.get(0); @@ -936,18 +939,18 @@ public PacketID[] getAcceptedPacketIDs() { @Override public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws PacketNotImplementedException, WrongSideException, Exception { TASmodPackets packet = (TASmodPackets) id; - String name = null; + String filename = null; String flavor = null; Minecraft mc = Minecraft.getMinecraft(); switch (packet) { case PLAYBACK_SAVE: - name = TASmodBufferBuilder.readString(buf); + filename = TASmodBufferBuilder.readString(buf); flavor = TASmodBufferBuilder.readString(buf); try { - PlaybackSerialiser.saveToFile(tasFileDirectory.resolve(name + fileEnding), this, flavor); + PlaybackSerialiser.saveToFile(tasFileDirectory.resolve(filename), this, flavor); } catch (PlaybackSaveException e) { if (mc.world != null) mc.ingameGUI.getChatGUI().printChatMessage(new TextComponentString(TextFormatting.RED + e.getMessage())); @@ -961,19 +964,23 @@ public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws } if (mc.world != null) { - TextComponentString confirm = new TextComponentString(TextFormatting.GREEN + "Saved inputs to " + name + ".mctas" + TextFormatting.RESET + " [" + TextFormatting.YELLOW + "Open folder" + TextFormatting.RESET + "]"); + TextComponentString confirm = new TextComponentString(TextFormatting.GREEN + "Saved inputs to " + filename + TextFormatting.RESET + " [" + TextFormatting.YELLOW + "Open folder" + TextFormatting.RESET + "]"); confirm.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/folder tasfiles")); mc.ingameGUI.getChatGUI().printChatMessage(confirm); } else - logger.debug(LoggerMarkers.Playback, "Saved inputs to " + name + ".mctas"); + logger.debug(LoggerMarkers.Playback, "Saved inputs to " + filename); break; case PLAYBACK_LOAD: - name = TASmodBufferBuilder.readString(buf); + filename = TASmodBufferBuilder.readString(buf); flavor = TASmodBufferBuilder.readString(buf); + String name = FilenameUtils.getBaseName(filename); + String extension = FilenameUtils.getExtension(filename); + if (extension.isEmpty()) + extension += fileEnding; try { - TASmodClient.controller.setInputs(PlaybackSerialiser.loadFromFile(tasFileDirectory.resolve(name + fileEnding), flavor)); + TASmodClient.controller.setInputs(PlaybackSerialiser.loadFromFile(tasFileDirectory.resolve(String.format("%s.%s", name, extension)), flavor)); } catch (PlaybackLoadException e) { if (mc.world != null) { TextComponentString textComponent = new TextComponentString(e.getMessage()); @@ -989,9 +996,9 @@ public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws } if (mc.world != null) - mc.ingameGUI.getChatGUI().printChatMessage(new TextComponentString(TextFormatting.GREEN + "Loaded inputs from " + name + ".mctas")); + mc.ingameGUI.getChatGUI().printChatMessage(new TextComponentString(TextFormatting.GREEN + "Loaded inputs from " + filename)); else - logger.debug(LoggerMarkers.Playback, "Loaded inputs from " + name + ".mctas"); + logger.debug(LoggerMarkers.Playback, "Loaded inputs from " + filename + ".mctas"); break; case PLAYBACK_FULLPLAY: diff --git a/src/main/java/com/minecrafttas/tasmod/playback/filecommands/builtin/DesyncMonitorFileCommandExtension.java b/src/main/java/com/minecrafttas/tasmod/playback/filecommands/builtin/DesyncMonitorFileCommandExtension.java index c4bd6559..42044103 100644 --- a/src/main/java/com/minecrafttas/tasmod/playback/filecommands/builtin/DesyncMonitorFileCommandExtension.java +++ b/src/main/java/com/minecrafttas/tasmod/playback/filecommands/builtin/DesyncMonitorFileCommandExtension.java @@ -99,6 +99,8 @@ public void onDisable() { @Override public SortedFileCommandContainer onSerialiseEndlineComment(long currentTick, InputContainer inputContainer) { SortedFileCommandContainer out = new SortedFileCommandContainer(); + if (monitorContainer.size() <= currentTick) + return out; MonitorContainer monitoredValues = monitorContainer.get(currentTick); PlaybackFileCommand command = new PlaybackFileCommand("desyncMonitor", monitoredValues.toStringArray()); diff --git a/src/main/java/com/minecrafttas/tasmod/playback/tasfile/PlaybackSerialiser.java b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/PlaybackSerialiser.java index 876be822..8c2119f6 100644 --- a/src/main/java/com/minecrafttas/tasmod/playback/tasfile/PlaybackSerialiser.java +++ b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/PlaybackSerialiser.java @@ -9,6 +9,8 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.io.FilenameUtils; + import com.dselent.bigarraylist.BigArrayList; import com.minecrafttas.tasmod.playback.PlaybackControllerClient; import com.minecrafttas.tasmod.playback.PlaybackControllerClient.InputContainer; @@ -95,6 +97,10 @@ public static void saveToFile(Path path, BigArrayList container, flavorName = defaultFlavor; } + SerialiserFlavorBase flavor = TASmodAPIRegistry.SERIALISER_FLAVOR.getFlavor(flavorName); + + path = addDefaultExtension(path, flavor); + FileThread writerThread; try { writerThread = new FileThread(path, false); @@ -103,17 +109,17 @@ public static void saveToFile(Path path, BigArrayList container, } writerThread.start(); - SerialiserFlavorBase flavor = TASmodAPIRegistry.SERIALISER_FLAVOR.getFlavor(flavorName); - if (flavor == null) { throw new PlaybackSaveException("Flavor %s doesn't exist", flavorName); } defaultFlavor = flavorName; - List header = flavor.serialiseHeader(); - for (String line : header) { - writerThread.addLine(line); + if (flavor.hasHeader()) { + List header = flavor.serialiseHeader(); + for (String line : header) { + writerThread.addLine(line); + } } BigArrayList tickLines = flavor.serialise(container, stopIndex); @@ -124,6 +130,16 @@ public static void saveToFile(Path path, BigArrayList container, writerThread.close(); } + private static Path addDefaultExtension(Path path, SerialiserFlavorBase flavor) { + String extension = FilenameUtils.getExtension(path.getFileName().toString()); + if (extension.isEmpty()) { + extension = flavor.getFileExtension(); + String name = FilenameUtils.getBaseName(path.getFileName().toString()); + path = path.resolveSibling(name + extension); + } + return path; + } + /** * Loads a BigArrayList of {@link InputContainer InputContainers} from a file.
* Tries to determine the {@link SerialiserFlavorBase flavor} by reading the header of the TASfile @@ -247,11 +263,15 @@ public static BigArrayList loadFromFile(Path file, SerialiserFla reader.close(); // Deserialise Header - List headerLines = flavor.extractHeader(lines); - flavor.deserialiseHeader(headerLines); + int startPos = 0; + if (flavor.hasHeader()) { + List headerLines = flavor.extractHeader(lines); + flavor.deserialiseHeader(headerLines); + startPos = headerLines.size(); + } // Deserialise main data - BigArrayList deserialisedContainers = flavor.deserialise(lines, headerLines.size()); + BigArrayList deserialisedContainers = flavor.deserialise(lines, startPos); return deserialisedContainers; } diff --git a/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/SerialiserFlavorBase.java b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/SerialiserFlavorBase.java index 97253cdb..687c7695 100644 --- a/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/SerialiserFlavorBase.java +++ b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/SerialiserFlavorBase.java @@ -2067,6 +2067,17 @@ public Integer getCurrentSubtick() { return currentSubtick; } + /** + * @return The file extension this file is usually associated with. Is used if no file ending is present + */ + public String getFileExtension() { + return ".mctas"; + } + + public boolean hasHeader() { + return true; + } + @Override public String toString() { return getExtensionName(); diff --git a/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/builtin/ParkourCalculatorFlavor.java b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/builtin/ParkourCalculatorFlavor.java new file mode 100644 index 00000000..67a0bec8 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/playback/tasfile/flavor/builtin/ParkourCalculatorFlavor.java @@ -0,0 +1,321 @@ +package com.minecrafttas.tasmod.playback.tasfile.flavor.builtin; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import com.dselent.bigarraylist.BigArrayList; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.minecrafttas.tasmod.playback.PlaybackControllerClient.CommentContainer; +import com.minecrafttas.tasmod.playback.PlaybackControllerClient.InputContainer; +import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommand; +import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommand.FileCommandsInCommentList; +import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommand.UnsortedFileCommandContainer; +import com.minecrafttas.tasmod.playback.metadata.PlaybackMetadata; +import com.minecrafttas.tasmod.playback.tasfile.exception.PlaybackLoadException; +import com.minecrafttas.tasmod.playback.tasfile.flavor.SerialiserFlavorBase; +import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; +import com.minecrafttas.tasmod.virtual.VirtualCameraAngle; +import com.minecrafttas.tasmod.virtual.VirtualKey; +import com.minecrafttas.tasmod.virtual.VirtualKeyboard; +import com.minecrafttas.tasmod.virtual.VirtualMouse; + +/** + * Flavor for importing/exporting files from ParkourCalculatorMod + * + * @author Scribble + */ +public class ParkourCalculatorFlavor extends SerialiserFlavorBase { + + private final Gson gson; + + public ParkourCalculatorFlavor() { + gson = new GsonBuilder().setPrettyPrinting().create(); + } + + @Override + public boolean checkFlavorName(List headerLines) { + boolean version = false, createdAt = false, modVersion = false, mcVersion = false; + for (int i = 0; i < 5; i++) { + String line = headerLines.get(i); + if (line.contains("\"version\"")) + version = true; + if (line.contains("\"createdAt\"")) + createdAt = true; + if (line.contains("\"modVersion\"")) + modVersion = true; + if (line.contains("\"mcVersion\"")) + mcVersion = true; + } + return version && createdAt && modVersion && mcVersion; + } + + @Override + public String getExtensionName() { + return "parkourcalculator"; + } + + @Override + public SerialiserFlavorBase clone() { + return new ParkourCalculatorFlavor(); + } + + @Override + public String getFileExtension() { + return ".json"; + } + + @Override + public boolean hasHeader() { + return false; + } + + @Override + public BigArrayList deserialise(BigArrayList lines, long startPos) { + BigArrayList out = new BigArrayList<>(); + TASmodAPIRegistry.PLAYBACK_FILE_COMMAND.setEnabled("tasmod_desyncMonitor@v1"); + String fullJson = String.join("\n", lines); + JsonObject main = gson.fromJson(fullJson, JsonObject.class); + deserialiseMetadata(main); + JsonObject start = main.get("start").getAsJsonObject(); + previousInputContainer = new InputContainer(new VirtualKeyboard(), new VirtualMouse(), new VirtualCameraAngle(0f, start.get("yaw").getAsFloat(), false)); + + JsonArray rows = main.get("rows").getAsJsonArray(); + JsonArray debug = null; + if (main.has("debug")) + debug = main.get("debug").getAsJsonArray(); + + for (int i = 0; i < rows.size(); i++) { + currentTick = i; + JsonElement row = rows.get(i); + JsonElement debugElement = null; + if (debug != null) { + debugElement = debug.get(i + 1); + } + + deserialiseContainer(out, row, debugElement); + } + previousInputContainer = null; + return out; + } + + protected void deserialiseContainer(BigArrayList out, JsonElement row, JsonElement debugElement) { + JsonObject rowObject = row.getAsJsonObject(); + VirtualKeyboard keyboard = deserialiseKeyboard(rowObject.get("keys")); + VirtualCameraAngle cameraAngle = deserialiseCameraAngle(rowObject.get("yaw")); + InputContainer deserialisedContainer = new InputContainer(keyboard, new VirtualMouse(), cameraAngle, new CommentContainer()); + + UnsortedFileCommandContainer fileCommands = deserialiseDebug((JsonObject) debugElement); + + if (!fileCommands.isEmpty()) + TASmodAPIRegistry.PLAYBACK_FILE_COMMAND.handleOnDeserialiseEndline(currentTick, deserialisedContainer, fileCommands); + + previousInputContainer = deserialisedContainer; + out.add(deserialisedContainer); + } + + protected UnsortedFileCommandContainer deserialiseDebug(JsonObject debugElement) { + UnsortedFileCommandContainer container = new UnsortedFileCommandContainer(); + if (debugElement == null) { + return container; + } + FileCommandsInCommentList commentList = new FileCommandsInCommentList(); + JsonArray pos = debugElement.get("pos").getAsJsonArray(); + String x = pos.get(0).getAsString(); + String y = pos.get(1).getAsString(); + String z = pos.get(2).getAsString(); + JsonArray vel = debugElement.get("vel").getAsJsonArray(); + String mx = vel.get(0).getAsString(); + String my = vel.get(1).getAsString(); + String mz = vel.get(2).getAsString(); + commentList.add(new PlaybackFileCommand("desyncMonitor", x, y, z, mx, my, mz)); + container.add(commentList); + return container; + } + + protected VirtualKeyboard deserialiseKeyboard(JsonElement jsonElement) { + if (jsonElement == null) + return new VirtualKeyboard(); + + JsonArray keyList = jsonElement.getAsJsonArray(); + Set keySet = new HashSet<>(); + keyList.forEach(key -> { + String keyString = key.getAsString(); + keySet.add(deserialiseVirtualKey(keyString, null)); + }); + return new VirtualKeyboard(keySet, new ArrayList<>(), new ArrayList<>(), false); + } + + @Override + protected Integer deserialiseVirtualKey(String key, WrongKeyCheck keyValidator) { + switch (key) { + case "W": + return VirtualKey.W.getKeycode(); + case "S": + return VirtualKey.S.getKeycode(); + case "A": + return VirtualKey.A.getKeycode(); + case "D": + return VirtualKey.D.getKeycode(); + case "JUMP": + return VirtualKey.SPACE.getKeycode(); + case "SPRINT": + return VirtualKey.LCONTROL.getKeycode(); + case "SNEAK": + return VirtualKey.LSHIFT.getKeycode(); + default: + throw new PlaybackLoadException("Key %s is not supported", key); + } + } + + private VirtualCameraAngle deserialiseCameraAngle(JsonElement jsonElement) { + if (jsonElement == null) + return previousInputContainer.getCameraAngle(); + float yaw = jsonElement.getAsFloat() + previousInputContainer.getCameraAngle().getYaw(); + return new VirtualCameraAngle(0f, yaw, false); + } + + protected void deserialiseMetadata(JsonObject main) { + JsonObject start = main.get("start").getAsJsonObject(); + JsonArray pos = start.get("pos").getAsJsonArray(); + LinkedHashMap startPosValues = new LinkedHashMap<>(); + startPosValues.put("x", pos.get(0).getAsString()); + startPosValues.put("y", pos.get(1).getAsString()); + startPosValues.put("z", pos.get(2).getAsString()); + startPosValues.put("pitch", "0"); + startPosValues.put("yaw", start.get("yaw").getAsString()); + + PlaybackMetadata startPosMetadata = PlaybackMetadata.fromHashMap("Start Position", startPosValues); + List out = new ArrayList<>(); + out.add(startPosMetadata); + TASmodAPIRegistry.PLAYBACK_METADATA.handleOnLoad(out); + } + + @Override + public BigArrayList serialise(BigArrayList inputs, long toTick) { + BigArrayList out = new BigArrayList<>(); + JsonObject main = new JsonObject(); + serialiseMetadata(main); + + JsonArray rows = new JsonArray(); + for (int i = 0; i < inputs.size(); i++) { + if (toTick == i) { + break; + } + currentTick = i; + InputContainer container = inputs.get(i).clone(); + serialiseContainer(rows, container); + previousInputContainer = container; + } + + main.add("rows", rows); + + String serialised = gson.toJson(main); + out.addAll(Arrays.asList(serialised.split("\n"))); + return out; + } + + protected void serialiseContainer(JsonArray rows, InputContainer container) { + JsonObject row = new JsonObject(); + serialiseKeyboard(row, container.getKeyboard()); + serialiseCameraAngle(row, container.getCameraAngle()); + row.addProperty("yawLocked", false); + row.addProperty("speedAmplifier", 0); + row.addProperty("jumpBoostAmplifier", 0); + rows.add(row); + } + + protected void serialiseKeyboard(JsonObject row, VirtualKeyboard keyboard) { + JsonArray keys = new JsonArray(); + Set pressedKeys = keyboard.getPressedKeys(); + for (Integer keyCode : pressedKeys) { + VirtualKey key = VirtualKey.get(keyCode); + switch (key) { + case W: + keys.add("W"); + break; + case A: + keys.add("A"); + break; + case S: + keys.add("S"); + break; + case D: + keys.add("D"); + break; + case SPACE: + keys.add("JUMP"); + break; + case LCONTROL: + keys.add("SPRINT"); + break; + case LSHIFT: + keys.add("SNEAK"); + break; + default: + break; + } + } + row.add("keys", keys); + } + + protected void serialiseCameraAngle(JsonObject row, VirtualCameraAngle cameraAngle) { + if (previousInputContainer == null) + return; + VirtualCameraAngle previousCameraAngle = previousInputContainer.getCameraAngle(); + if (cameraAngle.equals(previousCameraAngle)) + return; + + float yawdiff = cameraAngle.getYaw() - previousCameraAngle.getYaw(); + row.addProperty("yaw", yawdiff); + } + + protected void serialiseMetadata(JsonObject main) { + List metadataList = TASmodAPIRegistry.PLAYBACK_METADATA.handleOnStore(); + main.addProperty("version", 1); + main.addProperty("createdAt", nowIso8601()); + main.addProperty("modVersion", "1.5.1"); + main.addProperty("mcVersion", "1.12.2"); + JsonObject start = new JsonObject(); + for (PlaybackMetadata metadata : metadataList) { + switch (metadata.getExtensionName()) { + case "Start Position": + JsonArray pos = new JsonArray(); + Map map = metadata.getData(); + pos.add(Double.parseDouble(map.get("x"))); + pos.add(Double.parseDouble(map.get("y"))); + pos.add(Double.parseDouble(map.get("z"))); + start.add("pos", pos); + + JsonArray vel = new JsonArray(); + vel.add(0.0); + vel.add(0.0); + vel.add(0.0); + start.add("vel", vel); + start.addProperty("yaw", Float.parseFloat(map.get("yaw"))); + break; + + default: + break; + } + } + main.add("start", start); + } + + private static String nowIso8601() { + SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + fmt.setTimeZone(TimeZone.getTimeZone("UTC")); + return fmt.format(new Date()); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/util/TabCompletionUtils.java b/src/main/java/com/minecrafttas/tasmod/util/TabCompletionUtils.java index e4238cd4..2e178b4f 100644 --- a/src/main/java/com/minecrafttas/tasmod/util/TabCompletionUtils.java +++ b/src/main/java/com/minecrafttas/tasmod/util/TabCompletionUtils.java @@ -3,16 +3,17 @@ import static com.minecrafttas.tasmod.registries.TASmodPackets.COMMAND_FLAVORLIST; import static com.minecrafttas.tasmod.registries.TASmodPackets.COMMAND_TASFILELIST; -import java.io.File; -import java.io.FileFilter; +import java.io.IOException; import java.nio.ByteBuffer; -import java.util.ArrayList; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; import com.minecrafttas.mctcommon.networking.exception.PacketNotImplementedException; import com.minecrafttas.mctcommon.networking.exception.WrongSideException; @@ -25,8 +26,6 @@ import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; import com.minecrafttas.tasmod.registries.TASmodPackets; -import net.minecraft.client.Minecraft; - public class TabCompletionUtils implements ServerPacketHandler, ClientPacketHandler { private volatile CompletableFuture> fileList = null; @@ -97,19 +96,7 @@ public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws } } - private List getFilenames() { - List tab = new ArrayList(); - File folder = new File(Minecraft.getMinecraft().gameDir, "saves" + File.separator + "tasfiles"); - - File[] listOfFiles = folder.listFiles(new FileFilter() { - @Override - public boolean accept(File pathname) { - return pathname.getName().endsWith(".mctas"); - } - }); - for (int i = 0; i < listOfFiles.length; i++) { - tab.add(listOfFiles[i].getName().replaceFirst("\\.mctas$", "")); - } - return tab; + private List getFilenames() throws IOException { + return Files.list(TASmodClient.tasfiledirectory).map(Path::getFileName).map(Path::toString).collect(Collectors.toList()); } }