From 0f47403d0220757fed189b76e2071e25b1025cb8 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Wed, 3 Jun 2020 13:39:42 -0400 Subject: Split GUI code to separate module (#242) * Split into modules * Post merge compile fixes Co-authored-by: modmuss50 --- src/main/java/cuchaz/enigma/gui/GuiController.java | 729 --------------------- 1 file changed, 729 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/gui/GuiController.java (limited to 'src/main/java/cuchaz/enigma/gui/GuiController.java') diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java deleted file mode 100644 index cccc9e8..0000000 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ /dev/null @@ -1,729 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import cuchaz.enigma.Enigma; -import cuchaz.enigma.EnigmaProfile; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.analysis.*; -import cuchaz.enigma.api.service.ObfuscationTestService; -import cuchaz.enigma.bytecode.translators.SourceFixVisitor; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.gui.dialog.ProgressDialog; -import cuchaz.enigma.gui.stats.StatsGenerator; -import cuchaz.enigma.gui.stats.StatsMember; -import cuchaz.enigma.gui.util.History; -import cuchaz.enigma.network.EnigmaClient; -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.network.IntegratedEnigmaServer; -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.network.packet.LoginC2SPacket; -import cuchaz.enigma.network.packet.Packet; -import cuchaz.enigma.source.*; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.utils.ReadableToken; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.tree.ClassNode; - -import javax.annotation.Nullable; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import java.awt.*; -import java.awt.event.ItemEvent; -import java.io.*; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class GuiController { - private static final ExecutorService DECOMPILER_SERVICE = Executors.newSingleThreadExecutor( - new ThreadFactoryBuilder() - .setDaemon(true) - .setNameFormat("decompiler-thread") - .build() - ); - - private final Gui gui; - public final Enigma enigma; - - public EnigmaProject project; - private DecompilerService decompilerService; - private Decompiler decompiler; - private IndexTreeBuilder indexTreeBuilder; - - private Path loadedMappingPath; - private MappingFormat loadedMappingFormat; - - private DecompiledClassSource currentSource; - private Source uncommentedSource; - - private EnigmaClient client; - private EnigmaServer server; - - public GuiController(Gui gui, EnigmaProfile profile) { - this.gui = gui; - this.enigma = Enigma.builder() - .setProfile(profile) - .build(); - - decompilerService = Config.getInstance().decompiler.service; - } - - public boolean isDirty() { - return project != null && project.getMapper().isDirty(); - } - - public CompletableFuture openJar(final Path jarPath) { - this.gui.onStartOpenJar(); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - project = enigma.openJar(jarPath, progress); - indexTreeBuilder = new IndexTreeBuilder(project.getJarIndex()); - decompiler = createDecompiler(); - gui.onFinishOpenJar(jarPath.getFileName().toString()); - refreshClasses(); - }); - } - - private Decompiler createDecompiler() { - return decompilerService.create(name -> { - ClassNode node = project.getClassCache().getClassNode(name); - - if (node == null) { - return null; - } - - ClassNode fixedNode = new ClassNode(); - node.accept(new SourceFixVisitor(Utils.ASM_VERSION, fixedNode, project.getJarIndex())); - return fixedNode; - }, new SourceSettings(true, true)); - } - - public void closeJar() { - this.project = null; - this.gui.onCloseJar(); - } - - public CompletableFuture openMappings(MappingFormat format, Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - gui.setMappingsFile(path); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - try { - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - EntryTree mappings = format.read(path, progress, saveParameters); - project.setMappings(mappings); - - loadedMappingFormat = format; - loadedMappingPath = path; - - refreshClasses(); - refreshCurrentClass(); - } catch (MappingParseException e) { - JOptionPane.showMessageDialog(gui.getFrame(), e.getMessage()); - } - }); - } - - public void openMappings(EntryTree mappings) { - if (project == null) return; - - project.setMappings(mappings); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture saveMappings(Path path) { - return saveMappings(path, loadedMappingFormat); - } - - public CompletableFuture saveMappings(Path path, MappingFormat format) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EntryRemapper mapper = project.getMapper(); - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - MappingDelta delta = mapper.takeMappingDelta(); - boolean saveAll = !path.equals(loadedMappingPath); - - loadedMappingFormat = format; - loadedMappingPath = path; - - if (saveAll) { - format.write(mapper.getObfToDeobf(), path, progress, saveParameters); - } else { - format.write(mapper.getObfToDeobf(), delta, path, progress, saveParameters); - } - }); - } - - public void closeMappings() { - if (project == null) return; - - project.setMappings(null); - - this.gui.setMappingsFile(null); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture dropMappings() { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> project.dropMappings(progress)); - } - - public CompletableFuture exportSource(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - EnigmaProject.SourceExport source = jar.decompile(progress, decompilerService); - - source.write(path, progress); - }); - } - - public CompletableFuture exportJar(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - jar.write(path, progress); - }); - } - - public Token getToken(int pos) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReferenceToken(pos); - } - - @Nullable - public EntryReference, Entry> getReference(Token token) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReference(token); - } - - public ReadableToken getReadableToken(Token token) { - if (this.currentSource == null) { - return null; - } - - SourceIndex index = this.currentSource.getIndex(); - return new ReadableToken( - index.getLineNumber(token.start), - index.getColumnNumber(token.start), - index.getColumnNumber(token.end) - ); - } - - /** - * Navigates to the declaration with respect to navigation history - * - * @param entry the entry whose declaration will be navigated to - */ - public void openDeclaration(Entry entry) { - if (entry == null) { - throw new IllegalArgumentException("Entry cannot be null!"); - } - openReference(new EntryReference<>(entry, entry.getName())); - } - - /** - * Navigates to the reference with respect to navigation history - * - * @param reference the reference - */ - public void openReference(EntryReference, Entry> reference) { - if (reference == null) { - throw new IllegalArgumentException("Reference cannot be null!"); - } - if (this.gui.referenceHistory == null) { - this.gui.referenceHistory = new History<>(reference); - } else { - if (!reference.equals(this.gui.referenceHistory.getCurrent())) { - this.gui.referenceHistory.push(reference); - } - } - setReference(reference); - } - - /** - * Navigates to the reference without modifying history. If the class is not currently loaded, it will be loaded. - * - * @param reference the reference - */ - private void setReference(EntryReference, Entry> reference) { - // get the reference target class - ClassEntry classEntry = reference.getLocationClassEntry(); - if (!project.isRenamable(classEntry)) { - throw new IllegalArgumentException("Obfuscated class " + classEntry + " was not found in the jar!"); - } - - if (this.currentSource == null || !this.currentSource.getEntry().equals(classEntry)) { - // deobfuscate the class, then navigate to the reference - loadClass(classEntry, () -> showReference(reference)); - } else { - showReference(reference); - } - } - - /** - * Navigates to the reference without modifying history. Assumes the class is loaded. - * - * @param reference - */ - private void showReference(EntryReference, Entry> reference) { - Collection tokens = getTokensForReference(reference); - if (tokens.isEmpty()) { - // DEBUG - System.err.println(String.format("WARNING: no tokens found for %s in %s", reference, this.currentSource.getEntry())); - } else { - this.gui.showTokens(tokens); - } - } - - public Collection getTokensForReference(EntryReference, Entry> reference) { - EntryRemapper mapper = this.project.getMapper(); - - SourceIndex index = this.currentSource.getIndex(); - return mapper.getObfResolver().resolveReference(reference, ResolutionStrategy.RESOLVE_CLOSEST) - .stream() - .flatMap(r -> index.getReferenceTokens(r).stream()) - .collect(Collectors.toList()); - } - - public void openPreviousReference() { - if (hasPreviousReference()) { - setReference(gui.referenceHistory.goBack()); - } - } - - public boolean hasPreviousReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoBack(); - } - - public void openNextReference() { - if (hasNextReference()) { - setReference(gui.referenceHistory.goForward()); - } - } - - public boolean hasNextReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoForward(); - } - - public void navigateTo(Entry entry) { - if (!project.isRenamable(entry)) { - // entry is not in the jar. Ignore it - return; - } - openDeclaration(entry); - } - - public void navigateTo(EntryReference, Entry> reference) { - if (!project.isRenamable(reference.getLocationClassEntry())) { - return; - } - openReference(reference); - } - - private void refreshClasses() { - List obfClasses = Lists.newArrayList(); - List deobfClasses = Lists.newArrayList(); - this.addSeparatedClasses(obfClasses, deobfClasses); - this.gui.setObfClasses(obfClasses); - this.gui.setDeobfClasses(deobfClasses); - } - - public void addSeparatedClasses(List obfClasses, List deobfClasses) { - EntryRemapper mapper = project.getMapper(); - - Collection classes = project.getJarIndex().getEntryIndex().getClasses(); - Stream visibleClasses = classes.stream() - .filter(entry -> !entry.isInnerClass()); - - visibleClasses.forEach(entry -> { - ClassEntry deobfEntry = mapper.deobfuscate(entry); - - List obfService = enigma.getServices().get(ObfuscationTestService.TYPE); - boolean obfuscated = deobfEntry.equals(entry); - - if (obfuscated && !obfService.isEmpty()) { - if (obfService.stream().anyMatch(service -> service.testDeobfuscated(entry))) { - obfuscated = false; - } - } - - if (obfuscated) { - obfClasses.add(entry); - } else { - deobfClasses.add(entry); - } - }); - } - - public void refreshCurrentClass() { - refreshCurrentClass(null); - } - - private void refreshCurrentClass(EntryReference, Entry> reference) { - refreshCurrentClass(reference, RefreshMode.MINIMAL); - } - - private void refreshCurrentClass(EntryReference, Entry> reference, RefreshMode mode) { - if (currentSource != null) { - if (reference == null) { - int obfSelectionStart = currentSource.getObfuscatedOffset(gui.editor.getSelectionStart()); - int obfSelectionEnd = currentSource.getObfuscatedOffset(gui.editor.getSelectionEnd()); - - Rectangle viewportBounds = gui.sourceScroller.getViewport().getViewRect(); - // Here we pick an "anchor position", which we want to stay in the same vertical location on the screen after the new text has been set - int anchorModelPos = gui.editor.getSelectionStart(); - Rectangle anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - if (anchorViewPos.y < viewportBounds.y || anchorViewPos.y >= viewportBounds.y + viewportBounds.height) { - anchorModelPos = gui.editor.viewToModel(new Point(0, viewportBounds.y)); - anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - } - int obfAnchorPos = currentSource.getObfuscatedOffset(anchorModelPos); - Rectangle anchorViewPos_f = anchorViewPos; - int scrollX = gui.sourceScroller.getHorizontalScrollBar().getValue(); - - loadClass(currentSource.getEntry(), () -> SwingUtilities.invokeLater(() -> { - int newAnchorModelPos = currentSource.getDeobfuscatedOffset(obfAnchorPos); - Rectangle newAnchorViewPos = Utils.safeModelToView(gui.editor, newAnchorModelPos); - int newScrollY = newAnchorViewPos.y - (anchorViewPos_f.y - viewportBounds.y); - - gui.editor.select(currentSource.getDeobfuscatedOffset(obfSelectionStart), currentSource.getDeobfuscatedOffset(obfSelectionEnd)); - // Changing the selection scrolls to the caret position inside a SwingUtilities.invokeLater call, so - // we need to wrap our change to the scroll position inside another invokeLater so it happens after - // the caret's own scrolling. - SwingUtilities.invokeLater(() -> { - gui.sourceScroller.getHorizontalScrollBar().setValue(Math.min(scrollX, gui.sourceScroller.getHorizontalScrollBar().getMaximum())); - gui.sourceScroller.getVerticalScrollBar().setValue(Math.min(newScrollY, gui.sourceScroller.getVerticalScrollBar().getMaximum())); - }); - }), mode); - } else { - loadClass(currentSource.getEntry(), () -> showReference(reference), mode); - } - } - } - - private void loadClass(ClassEntry classEntry, Runnable callback) { - loadClass(classEntry, callback, RefreshMode.MINIMAL); - } - - private void loadClass(ClassEntry classEntry, Runnable callback, RefreshMode mode) { - ClassEntry targetClass = classEntry.getOutermostClass(); - - boolean requiresDecompile = mode == RefreshMode.FULL || currentSource == null || !currentSource.getEntry().equals(targetClass); - if (requiresDecompile) { - currentSource = null; // Or the GUI may try to find a nonexistent token - gui.setEditorText(I18n.translate("info_panel.editor.class.decompiling")); - } - - DECOMPILER_SERVICE.submit(() -> { - try { - if (requiresDecompile || mode == RefreshMode.JAVADOCS) { - currentSource = decompileSource(targetClass, mode == RefreshMode.JAVADOCS); - } - - remapSource(project.getMapper().getDeobfuscator()); - callback.run(); - } catch (Throwable t) { - System.err.println("An exception was thrown while decompiling class " + classEntry.getFullName()); - t.printStackTrace(System.err); - } - }); - } - - private DecompiledClassSource decompileSource(ClassEntry targetClass, boolean onlyRefreshJavadocs) { - try { - if (!onlyRefreshJavadocs || currentSource == null || !currentSource.getEntry().equals(targetClass)) { - uncommentedSource = decompiler.getSource(targetClass.getFullName()); - } - - Source source = uncommentedSource.addJavadocs(project.getMapper()); - - if (source == null) { - gui.setEditorText(I18n.translate("info_panel.editor.class.not_found") + " " + targetClass); - return DecompiledClassSource.text(targetClass, "Unable to find class"); - } - - SourceIndex index = source.index(); - index.resolveReferences(project.getMapper().getObfResolver()); - - return new DecompiledClassSource(targetClass, index); - } catch (Throwable t) { - StringWriter traceWriter = new StringWriter(); - t.printStackTrace(new PrintWriter(traceWriter)); - - return DecompiledClassSource.text(targetClass, traceWriter.toString()); - } - } - - private void remapSource(Translator translator) { - if (currentSource == null) { - return; - } - - currentSource.remapSource(project, translator); - - gui.setEditorTheme(Config.getInstance().lookAndFeel); - gui.setSource(currentSource); - } - - public void modifierChange(ItemEvent event) { - if (event.getStateChange() == ItemEvent.SELECTED) { - EntryRemapper mapper = project.getMapper(); - Entry entry = gui.cursorReference.entry; - AccessModifier modifier = (AccessModifier) event.getItem(); - - EntryMapping mapping = mapper.getDeobfMapping(entry); - if (mapping != null) { - mapper.mapFromObf(entry, new EntryMapping(mapping.getTargetName(), modifier)); - } else { - mapper.mapFromObf(entry, new EntryMapping(entry.getName(), modifier)); - } - - refreshCurrentClass(); - } - } - - public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); - return ClassInheritanceTreeNode.findNode(rootNode, entry); - } - - public ClassImplementationsTreeNode getClassImplementations(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - return this.indexTreeBuilder.buildClassImplementations(translator, entry); - } - - public MethodInheritanceTreeNode getMethodInheritance(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodInheritanceTreeNode rootNode = indexTreeBuilder.buildMethodInheritance(translator, entry); - return MethodInheritanceTreeNode.findNode(rootNode, entry); - } - - public MethodImplementationsTreeNode getMethodImplementations(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - List rootNodes = indexTreeBuilder.buildMethodImplementations(translator, entry); - if (rootNodes.isEmpty()) { - return null; - } - if (rootNodes.size() > 1) { - System.err.println("WARNING: Method " + entry + " implements multiple interfaces. Only showing first one."); - } - return MethodImplementationsTreeNode.findNode(rootNodes.get(0), entry); - } - - public ClassReferenceTreeNode getClassReferences(ClassEntry entry) { - Translator deobfuscator = project.getMapper().getDeobfuscator(); - ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(deobfuscator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public FieldReferenceTreeNode getFieldReferences(FieldEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public MethodReferenceTreeNode getMethodReferences(MethodEntry entry, boolean recursive) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true, recursive); - return rootNode; - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree) { - rename(reference, newName, refreshClassTree, true); - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree, boolean jumpToReference) { - Entry entry = reference.getNameableEntry(); - project.getMapper().mapFromObf(entry, new EntryMapping(newName)); - - if (refreshClassTree && reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, newName); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void removeMapping(EntryReference, Entry> reference) { - removeMapping(reference, true); - } - - public void removeMapping(EntryReference, Entry> reference, boolean jumpToReference) { - project.getMapper().removeByObf(reference.getNameableEntry()); - - if (reference.entry instanceof ClassEntry) - this.gui.moveClassTree(reference, false, true); - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs) { - changeDocs(reference, updatedDocs, true); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs, boolean jumpToReference) { - changeDoc(reference.entry, Utils.isBlank(updatedDocs) ? null : updatedDocs); - - refreshCurrentClass(jumpToReference ? reference : null, RefreshMode.JAVADOCS); - } - - private void changeDoc(Entry obfEntry, String newDoc) { - EntryRemapper mapper = project.getMapper(); - if (mapper.getDeobfMapping(obfEntry) == null) { - markAsDeobfuscated(obfEntry, false); // NPE - } - mapper.mapFromObf(obfEntry, mapper.getDeobfMapping(obfEntry).withDocs(newDoc), false); - } - - private void markAsDeobfuscated(Entry obfEntry, boolean renaming) { - EntryRemapper mapper = project.getMapper(); - mapper.mapFromObf(obfEntry, new EntryMapping(mapper.deobfuscate(obfEntry).getName()), renaming); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference) { - markAsDeobfuscated(reference, true); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference, boolean jumpToReference) { - EntryRemapper mapper = project.getMapper(); - Entry entry = reference.getNameableEntry(); - mapper.mapFromObf(entry, new EntryMapping(mapper.deobfuscate(entry).getName())); - - if (reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, true, false); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void openStats(Set includedMembers) { - ProgressDialog.runOffThread(gui.getFrame(), progress -> { - String data = new StatsGenerator(project).generate(progress, includedMembers); - - try { - File statsFile = File.createTempFile("stats", ".html"); - - try (FileWriter w = new FileWriter(statsFile)) { - w.write( - Utils.readResourceToString("/stats.html") - .replace("/*data*/", data) - ); - } - - Desktop.getDesktop().open(statsFile); - } catch (IOException e) { - throw new Error(e); - } - }); - } - - public void setDecompiler(DecompilerService service) { - uncommentedSource = null; - decompilerService = service; - decompiler = createDecompiler(); - refreshCurrentClass(null, RefreshMode.FULL); - } - - public EnigmaClient getClient() { - return client; - } - - public EnigmaServer getServer() { - return server; - } - - public void createClient(String username, String ip, int port, char[] password) throws IOException { - client = new EnigmaClient(this, ip, port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, username)); - gui.setConnectionState(ConnectionState.CONNECTED); - } - - public void createServer(int port, char[] password) throws IOException { - server = new IntegratedEnigmaServer(project.getJarChecksum(), password, EntryRemapper.mapped(project.getJarIndex(), new HashEntryTree<>(project.getMapper().getObfToDeobf())), port); - server.start(); - client = new EnigmaClient(this, "127.0.0.1", port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, EnigmaServer.OWNER_USERNAME)); - gui.setConnectionState(ConnectionState.HOSTING); - } - - public synchronized void disconnectIfConnected(String reason) { - if (client == null && server == null) { - return; - } - - if (client != null) { - client.disconnect(); - } - if (server != null) { - server.stop(); - } - client = null; - server = null; - SwingUtilities.invokeLater(() -> { - if (reason != null) { - JOptionPane.showMessageDialog(gui.getFrame(), I18n.translate(reason), I18n.translate("disconnect.disconnected"), JOptionPane.INFORMATION_MESSAGE); - } - gui.setConnectionState(ConnectionState.NOT_CONNECTED); - }); - } - - public void sendPacket(Packet packet) { - if (client != null) { - client.sendPacket(packet); - } - } - - public void addMessage(Message message) { - gui.addMessage(message); - } - - public void updateUserList(List users) { - gui.setUserList(users); - } - -} -- cgit v1.2.3