Skip to content

Commit

Permalink
Merge branch 'develop' into j_develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Jmr3366 authored Jan 21, 2025
2 parents 7dd0e7b + b02a6a5 commit 2047ccc
Show file tree
Hide file tree
Showing 85 changed files with 1,201 additions and 67,300 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ out/
# Automatically Generated
################################################################################
package/windows/MapTool.iss
package/linux/MapTool*.desktop


# IDEs
Expand Down
22 changes: 21 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,26 @@ classes.configure {
dependsOn instrumentForms
}


if (osdetector.os.is('linux')) {
def generateDesktop = tasks.register('generateDesktop', Copy) {
from 'package/linux/launcher.desktop'
into 'package/linux/'
expand(
description: project.description,
projectName: project.name,
developerRelease: developerRelease
)
filteringCharset = 'UTF-8'
rename { fileName ->
project.name + developerRelease + '.desktop'
}
}

tasks.jpackageImage.dependsOn generateDesktop
tasks.spotlessMisc.dependsOn generateDesktop
}

// Workaround the runtime plugin's hardcoded dependencies on the shadow plugin. It sneakily
// (dynamically) adds dependencies when shadow is detected, but we don't want it to do that since we
// only use shadow for a completely separate build artifact.
Expand Down Expand Up @@ -383,7 +403,7 @@ dependencies {

//maybe replace with jupnp
implementation 'commons-jxpath:commons-jxpath:1.3'
implementation 'net.sbbi.upnp:upnplib:1.0.9-nodebug'
implementation 'com.github.fishface60:upnplib:0351d7502a57f6c5dc8653220bc03ad99af58b21'

// custom binding stuff, should probably be replace with Beans Binding (JSR 295)
implementation 'yasb:yasb:0.2-21012007'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public abstract class AbstractServer implements Server {
public abstract class AbstractServer {

private static final Logger log = LogManager.getLogger(AbstractServer.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
package net.rptools.clientserver.simple.server;

/** A server implementation that never receives connections */
public class NilServer extends AbstractServer {
public final class NilServer extends AbstractServer implements Server {
@Override
public void start() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import java.io.IOException;

public interface Server extends AutoCloseable {
public sealed interface Server extends AutoCloseable permits NilServer, SocketServer, WebRTCServer {
void start() throws IOException;

void close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/**
* @author drice
*/
public class SocketServer extends AbstractServer {
public final class SocketServer extends AbstractServer implements Server {

private static final Logger log = LogManager.getLogger(SocketServer.class);
private final int port;
Expand All @@ -39,6 +39,9 @@ public SocketServer(int port) {
@Override
public void start() throws IOException {
var serverSocket = new ServerSocket(port);
if (serverSocket.getLocalPort() == -1) {
throw new AssertionError("Socket not bound yet");
}
// If the above throws, it will be as though we never started.

socket = serverSocket;
Expand Down Expand Up @@ -70,6 +73,16 @@ public String getError() {
return null;
}

/** Get the port of the socket the server is running on or -1. */
public int getPort() {
// NOTE: We do not use this.port because the socket's bound port can be different
if (socket == null || socket.isClosed()) {
return -1;
}

return socket.getLocalPort();
}

////
// Threads
private static class ListeningThread extends Thread {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

public class WebRTCServer extends AbstractServer {
public final class WebRTCServer extends AbstractServer implements Server {
private static final Logger log = LogManager.getLogger(WebRTCServer.class);

public interface Listener {
Expand Down
13 changes: 2 additions & 11 deletions doc/How_To_Setup_UI_Tools.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
How To Setup User Interface (UI) Tools for MapTool
==================================================

You thought you were done? Sorry, there are two extra things you may wish to consider and both are related to managing UI elements within Maptool. The current edition of the tool uses **Abeille** to manage **Swing** elements within the design. Abeille is a WYSIWYG form designer for Swing objects and if you plan on modifying any of the UI elements you should definitely install the Abeille Designer.
You thought you were done? Sorry, there are two extra things you may wish to consider and both are related to managing UI elements within Maptool. The current edition of the tool uses **IntelliJ** to manage **Swing** elements within the design. Just open the `.form` files and install the plugin when prompted.

As Swing is now deprecated within Java the plan is to move those elements over to **JavaFX**, although this work is further down the line at the moment. If you want to get to grips with JavaFX, you should probably install the Eclipse Plugin **e(fx)clipse** and the **JavaFX Scene Builder**. Scene Builder is also a WYSIWYG form designer, but this time for JavaFX Objects.

Install Abeille
----------------

1. Go to the [Abeille Downloads page](https://java.net/projects/abeille/downloads/directory/Abeille%20Form%20Designer%202.1.0%20M3) and download the latest binaries. This is a closed project so they are quite old. The binaries are jar files so you can simply unzip the folder to anywhere on your PC, such as `C:\Program Files (x86)\abeille-2.1.0_M3`
* As the Abeille downloads are now offline the last version has been attached here: [abeille-2.1.0_M3.zip](https://github.com/RPTools/maptool/files/6554805/abeille-2.1.0_M3.zip)
2. Launch the Designer by running the `designer.jar` file in the `abeille-2.1.0_M3` directory. If you have installed Java as described elsewhere, you can just right click the file and select **Open**
3. Once the Designer is running, you need to create a new project for the MapTool forms. Call this file `maptool.jfpr` and save it anywhere you like, BUT NOT in the Eclipse MapTool project directory, as you do not want this file to become part of the MapTool project and is only used by you locally.
4. Add the MapTool resource directory as a Source path for your Abeille Project. On the Abeille Project Settings screen you should see a button in the Source Tab to **Add Path**. Click this and navigate to the resource directory. For example, if your Eclipse workspace directory was `C:\Workspace` and your top level MapTool project was called `C:\Workspace\maptool` you should add the path `C:\Workspace\maptool\maptool\src\main\resources`. This is very important, otherwise the Albeille Designer will save the local path names into the designer files rather than the relative paths that are needed for proper distribution.

Install e(fx)clipse Plugin
--------------------------

Expand All @@ -29,4 +20,4 @@ Install JavaFX Scene Builder

The JavaFX Scene Builder application has been handed over to the open source community and as a consequence it can be hard to find the Scene Builder install. The latest version as of this writing is SceneBuilder 10.0.0 and is available from [GluonHQ.com](https://gluonhq.com/products/scene-builder/)

Download and install SceneBuilder. It can now be used to open **.fxml** files which are the JavaFX equivalent to Abeille files (above).
Download and install SceneBuilder. It can now be used to open **.fxml** files which are the JavaFX equivalent to `.form` files (above).
9 changes: 9 additions & 0 deletions package/linux/launcher.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Desktop Entry]
Name=${projectName}
Comment=${description}
Exec=/opt/maptool/bin/${projectName}${developerRelease} %u
Icon=/opt/maptool/lib/${projectName}${developerRelease}.png
Terminal=false
Type=Application
Categories=Game
MimeType=application/maptool;x-scheme-handler/rptools-maptool+registry;x-scheme-handler/rptools-maptool+lan;x-scheme-handler/rptools-maptool+tcp
33 changes: 19 additions & 14 deletions src/main/java/net/rptools/clientserver/ConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package net.rptools.clientserver;

import java.awt.EventQueue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.rptools.clientserver.simple.connection.Connection;
import net.rptools.clientserver.simple.connection.SocketConnection;
Expand All @@ -24,6 +25,7 @@
import net.rptools.clientserver.simple.server.SocketServer;
import net.rptools.clientserver.simple.server.WebRTCServer;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.RemoteServerConfig;
import net.rptools.maptool.server.ServerConfig;

public class ConnectionFactory {
Expand All @@ -33,22 +35,25 @@ public static ConnectionFactory getInstance() {
return instance;
}

public Connection createConnection(String id, ServerConfig config) {
if (!config.getUseWebRTC()) {
return new SocketConnection(id, config.getHostName(), config.getPort());
}

return new WebRTCConnection(
id,
config.getServerName(),
new WebRTCConnection.Listener() {
@Override
public void onLoginError() {
MapTool.showError("Handshake.msg.playerAlreadyConnected");
}
});
@Nonnull
public Connection createConnection(@Nonnull String id, @Nonnull RemoteServerConfig config) {
return switch (config) {
case RemoteServerConfig.Socket(String hostName, int port) ->
new SocketConnection(id, hostName, port);
case RemoteServerConfig.WebRTC(String serverName) ->
new WebRTCConnection(
id,
serverName,
new WebRTCConnection.Listener() {
@Override
public void onLoginError() {
MapTool.showError("Handshake.msg.playerAlreadyConnected");
}
});
};
}

@Nonnull
public Server createServer(@Nullable ServerConfig config) {
if (config == null) {
return new NilServer();
Expand Down
149 changes: 69 additions & 80 deletions src/main/java/net/rptools/maptool/client/AppActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.annotation.Nonnull;
import javax.crypto.NoSuchPaddingException;
import javax.swing.*;
import javax.swing.text.BadLocationException;
Expand Down Expand Up @@ -2209,7 +2210,7 @@ protected void executeAction() {
StartServerDialogPreferences serverProps =
new StartServerDialogPreferences(); // data retrieved from
// Preferences.userRoot()
if (serverProps.getPort() == 0 || serverProps.getPort() > 65535) {
if (serverProps.getPort() > 65535) {
MapTool.showError("ServerDialog.error.port.outOfRange");
return;
}
Expand Down Expand Up @@ -2349,6 +2350,66 @@ protected void executeAction() {
}
};

public static void connectToServer(
@Nonnull String username, @Nonnull String password, @Nonnull RemoteServerConfig config) {
LOAD_MAP.setSeenWarning(false);

MapTool.disconnect();
MapTool.stopServer();

// Install a temporary gimped campaign until we get the one from the server
final Campaign oldCampaign = MapTool.getCampaign();
MapTool.setCampaign(new Campaign(), null);

// connecting
MapTool.getFrame().getConnectionStatusPanel().setStatus(ConnectionStatusPanel.Status.connected);

// Show the user something interesting while we're connecting. Look below for the corresponding
// hideGlassPane
StaticMessageDialog progressDialog =
new StaticMessageDialog(I18N.getText("msg.info.connecting"));
MapTool.getFrame().showFilledGlassPane(progressDialog);

boolean failed = false;
try {
MapTool.connectToRemoteServer(
config,
new LocalPlayer(username, password),
(success) -> {
EventQueue.invokeLater(
() -> {
MapTool.getFrame().hideGlassPane();
if (success) {
// Show the user something interesting until we've got the campaign
// Look in ClientMethodHandler.setCampaign() for the corresponding
// hideGlassPane
MapTool.getFrame()
.showFilledGlassPane(
new StaticMessageDialog(I18N.getText("msg.info.campaignLoading")));
}
});
});

} catch (UnknownHostException e1) {
MapTool.showError("msg.error.unknownHost", e1);
failed = true;
} catch (IOException e1) {
MapTool.showError("msg.error.failedLoadCampaign", e1);
failed = true;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e1) {
MapTool.showError("msg.error.initializeCrypto", e1);
failed = true;
}
if (failed) {
MapTool.getFrame().hideGlassPane();
try {
MapTool.startPersonalServer(oldCampaign);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
MapTool.showError("msg.error.failedStartPersonalServer", e);
}
}
}

public static final Action CONNECT_TO_SERVER =
new ClientAction() {
{
Expand All @@ -2366,89 +2427,17 @@ protected void executeAction() {

final ConnectToServerDialog dialog = new ConnectToServerDialog();
dialog.showDialog();
if (!dialog.accepted()) {
var config = dialog.getResult();
if (config == null) {
return;
}
ConnectToServerDialogPreferences prefs = new ConnectToServerDialogPreferences();

LOAD_MAP.setSeenWarning(false);

MapTool.disconnect();
MapTool.stopServer();

// Install a temporary gimped campaign until we get the one from the
// server
final Campaign oldCampaign = MapTool.getCampaign();
MapTool.setCampaign(new Campaign(), null);
var username = prefs.getUsername();
var password =
prefs.getUsePublicKey() ? new PasswordGenerator().getPassword() : prefs.getPassword();

// connecting
MapTool.getFrame()
.getConnectionStatusPanel()
.setStatus(ConnectionStatusPanel.Status.connected);

// Show the user something interesting while we're connecting. Look below for the
// corresponding hideGlassPane
StaticMessageDialog progressDialog =
new StaticMessageDialog(I18N.getText("msg.info.connecting"));
MapTool.getFrame().showFilledGlassPane(progressDialog);

runBackground(
() -> {
boolean failed = false;
try {
ConnectToServerDialogPreferences prefs = new ConnectToServerDialogPreferences();
ServerConfig config =
new ServerConfig(
prefs.getUsername(),
"",
"",
dialog.getPort(),
prefs.getServerName(),
dialog.getServer(),
false,
dialog.getUseWebRTC());

String password =
prefs.getUsePublicKey()
? new PasswordGenerator().getPassword()
: prefs.getPassword();
MapTool.connectToRemoteServer(
config,
new LocalPlayer(prefs.getUsername(), prefs.getRole(), password),
(success) -> {
EventQueue.invokeLater(
() -> {
MapTool.getFrame().hideGlassPane();
if (success) {
// Show the user something interesting until we've got the campaign
// Look in ClientMethodHandler.setCampaign() for the corresponding
// hideGlassPane
MapTool.getFrame()
.showFilledGlassPane(
new StaticMessageDialog(
I18N.getText("msg.info.campaignLoading")));
}
});
});

} catch (UnknownHostException e1) {
MapTool.showError("msg.error.unknownHost", e1);
failed = true;
} catch (IOException e1) {
MapTool.showError("msg.error.failedLoadCampaign", e1);
failed = true;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e1) {
MapTool.showError("msg.error.initializeCrypto", e1);
failed = true;
}
if (failed) {
MapTool.getFrame().hideGlassPane();
try {
MapTool.startPersonalServer(oldCampaign);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
MapTool.showError("msg.error.failedStartPersonalServer", e);
}
}
});
runBackground(() -> connectToServer(username, password, config));
}
};

Expand Down
Loading

0 comments on commit 2047ccc

Please sign in to comment.