From 854f4d49407e45d67dd5754afd21a7e59970ca5b Mon Sep 17 00:00:00 2001 From: Joseph Burton Date: Sun, 3 May 2020 21:06:38 +0100 Subject: Multiplayer support (#221) * First pass on multiplayer * Apply review suggestions * Dedicated Enigma server * Don't jump to references when other users do stuff * Better UI + translations * french translation * Apply review suggestions * Document the protocol * Fix most issues with scrolling. * Apply review suggestions * Fix zip hash issues + add a bit more logging * Optimize zip hash * Fix a couple of login bugs * Add message log and user list * Make Message an abstract class * Make status bar work, add chat box * Hide message log/users list when not connected * Fix status bar not resetting entirely * Run stop server task on server thread to prevent multithreading race conditions * Add c2s message to packet id list * Fix message scroll bar not scrolling to the end * Formatting * User list size -> ushort * Combine contains and remove check * Check removal before sending packet * Add password to login packet * Fix the GUI closing the rename text field when someone else renames something * Update fr_fr.json * oups * Make connection/server create dialogs not useless if it fails once * Refactor UI state updating * Fix imports * Fix Collab menu * Fix NPE when rename not allowed * Make the log file a configurable option * Don't use modified UTF * Update fr_fr.json * Bump version to 0.15.4 * Apparently I can't spell neither words nor semantic versions Co-authored-by: Yanis48 Co-authored-by: 2xsaiko --- src/main/java/cuchaz/enigma/utils/Utils.java | 64 ++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) (limited to 'src/main/java/cuchaz/enigma/utils/Utils.java') diff --git a/src/main/java/cuchaz/enigma/utils/Utils.java b/src/main/java/cuchaz/enigma/utils/Utils.java index b8f2ec2..b45b00d 100644 --- a/src/main/java/cuchaz/enigma/utils/Utils.java +++ b/src/main/java/cuchaz/enigma/utils/Utils.java @@ -15,6 +15,8 @@ import com.google.common.io.CharStreams; import org.objectweb.asm.Opcodes; import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.MouseEvent; import java.io.IOException; @@ -22,13 +24,16 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Comparator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; import java.util.List; -import java.util.Locale; -import java.util.StringJoiner; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; public class Utils { @@ -98,6 +103,19 @@ public class Utils { manager.setInitialDelay(oldDelay); } + public static Rectangle safeModelToView(JTextComponent component, int modelPos) { + if (modelPos < 0) { + modelPos = 0; + } else if (modelPos >= component.getText().length()) { + modelPos = component.getText().length(); + } + try { + return component.modelToView(modelPos); + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + } + public static boolean getSystemPropertyAsBoolean(String property, boolean defValue) { String value = System.getProperty(property); return value == null ? defValue : Boolean.parseBoolean(value); @@ -111,6 +129,34 @@ public class Utils { } } + public static byte[] zipSha1(Path path) throws IOException { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + // Algorithm guaranteed to be supported + throw new RuntimeException(e); + } + try (ZipFile zip = new ZipFile(path.toFile())) { + List entries = Collections.list(zip.entries()); + // only compare classes (some implementations may not generate directory entries) + entries.removeIf(entry -> !entry.getName().toLowerCase(Locale.ROOT).endsWith(".class")); + // different implementations may add zip entries in a different order + entries.sort(Comparator.comparing(ZipEntry::getName)); + byte[] buffer = new byte[8192]; + for (ZipEntry entry : entries) { + digest.update(entry.getName().getBytes(StandardCharsets.UTF_8)); + try (InputStream in = zip.getInputStream(entry)) { + int n; + while ((n = in.read(buffer)) != -1) { + digest.update(buffer, 0, n); + } + } + } + } + return digest.digest(); + } + public static String caplisiseCamelCase(String input){ StringJoiner stringJoiner = new StringJoiner(" "); for (String word : input.toLowerCase(Locale.ROOT).split("_")) { @@ -118,4 +164,16 @@ public class Utils { } return stringJoiner.toString(); } + + public static boolean isBlank(String input) { + if (input == null) { + return true; + } + for (int i = 0; i < input.length(); i++) { + if (!Character.isWhitespace(input.charAt(i))) { + return false; + } + } + return true; + } } -- cgit v1.2.3