001/* 002 * This file is part of Baritone. 003 * 004 * Baritone is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU Lesser General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * Baritone is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public License 015 * along with Baritone. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package baritone.api.command.datatypes; 019 020import baritone.api.command.argument.IArgConsumer; 021import baritone.api.command.exception.CommandException; 022 023import java.io.File; 024import java.io.IOException; 025import java.io.UncheckedIOException; 026import java.nio.file.FileSystems; 027import java.nio.file.InvalidPathException; 028import java.nio.file.Path; 029import java.util.Locale; 030import java.util.Objects; 031import java.util.stream.Stream; 032 033import static baritone.api.utils.Helper.HELPER; 034 035public enum RelativeFile implements IDatatypePost<File, File> { 036 INSTANCE; 037 038 @Override 039 public File apply(IDatatypeContext ctx, File original) throws CommandException { 040 if (original == null) { 041 original = new File("./"); 042 } 043 044 Path path; 045 try { 046 path = FileSystems.getDefault().getPath(ctx.getConsumer().getString()); 047 } catch (InvalidPathException e) { 048 throw new IllegalArgumentException("invalid path"); 049 } 050 return getCanonicalFileUnchecked(original.toPath().resolve(path).toFile()); 051 } 052 053 @Override 054 public Stream<String> tabComplete(IDatatypeContext ctx) { 055 return Stream.empty(); 056 } 057 058 /** 059 * Seriously 060 * 061 * @param file File 062 * @return Canonical file of file 063 * @author LoganDark 064 */ 065 private static File getCanonicalFileUnchecked(File file) { 066 try { 067 return file.getCanonicalFile(); 068 } catch (IOException e) { 069 throw new UncheckedIOException(e); 070 } 071 } 072 073 public static Stream<String> tabComplete(IArgConsumer consumer, File base0) throws CommandException { 074 // I will not make the caller deal with this, seriously 075 // Tab complete code is beautiful and I'm not going to bloat it with dumb ass checked exception bullshit -LoganDark 076 077 // lol owned -Brady 078 079 File base = getCanonicalFileUnchecked(base0); 080 String currentPathStringThing = consumer.getString(); 081 Path currentPath = FileSystems.getDefault().getPath(currentPathStringThing); 082 Path basePath = currentPath.isAbsolute() ? currentPath.getRoot() : base.toPath(); 083 boolean useParent = !currentPathStringThing.isEmpty() && !currentPathStringThing.endsWith(File.separator); 084 File currentFile = currentPath.isAbsolute() ? currentPath.toFile() : new File(base, currentPathStringThing); 085 return Stream.of(Objects.requireNonNull(getCanonicalFileUnchecked( 086 useParent 087 ? currentFile.getParentFile() 088 : currentFile 089 ).listFiles())) 090 .map(f -> (currentPath.isAbsolute() ? f : basePath.relativize(f.toPath()).toString()) + 091 (f.isDirectory() ? File.separator : "")) 092 .filter(s -> s.toLowerCase(Locale.US).startsWith(currentPathStringThing.toLowerCase(Locale.US))) 093 .filter(s -> !s.contains(" ")); 094 } 095 096 public static File gameDir() { 097 File gameDir = HELPER.mc.gameDir.getAbsoluteFile(); 098 if (gameDir.getName().equals(".")) { 099 return gameDir.getParentFile(); 100 } 101 return gameDir; 102 } 103}