diff --git a/.classpath b/.classpath
index e1cdf3c..ae2c214 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,7 @@
+
diff --git a/.gitignore b/.gitignore
index 2b29054..69f7e61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
*.orig
*.csr
+*.cer
*.jks
/build/
diff --git a/.project b/.project
index 8657623..0f0d6b7 100644
--- a/.project
+++ b/.project
@@ -14,4 +14,11 @@
org.eclipse.jdt.core.javanature
+
+
+ src/jnlp/JNLP-INF/APPLICATION.JNLP
+ 1
+ C:/CFH/eclipse/Puzzle/src/puzzle.jnlp
+
+
diff --git a/Puzzle Test ARG.launch b/Puzzle Test ARG.launch
index 0cf602a..772140b 100644
--- a/Puzzle Test ARG.launch
+++ b/Puzzle Test ARG.launch
@@ -1,16 +1,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Puzzle Test.launch b/Puzzle Test.launch
index 333c66b..fc6f936 100644
--- a/Puzzle Test.launch
+++ b/Puzzle Test.launch
@@ -1,15 +1,17 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 4e4aa33..a0ebd1e 100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,41 @@
# Puzzle
+![splash](src/pics/splash.png)
+
My jigsaw puzzle
-Just for doing some tests... work in progress.
+Work in progress.
*use at your own risk - no warranties!*
## Instructions
-Open an image file to create a new puzzle
-or
-open a previously saved puzzle to continue playing.
-
-*Note:* puzzles are **not saved** automatically!
-
-#### Moving Pieces
-
-* Use the `LEFT` button to drag and drop pieces.
- If a piece is dropped near the correct neighbour(s), the pieces will snap together.
-* Hold the `CTRL` Key and click on a connected piece to disconnect it.
-* Use the scroll wheel or double-click (`LEFT` or `RIGHT` button) to rotate the piece(s) under the cursor.
-
-#### General
+### Version
-* `RIGHT` click background to open menu.
-* Use `LEFT` button on background to drag the whole surface.
-* `CTRL`-digit or `CTRL`-letter to save current surface position under that key.
- The corresponding digit or letter, without `CTRL`, to move to the corresponding saved position.
-* `BACKSPACE` to move back to last position.
+- append to JAR file in `docs/puzzle_V.jar`
+- `dist/puzzle.jar` ?
+- adjust `jar` entry in `src/puzzle.jnlp`
+ copy to `docs/`
+- adjust `Implementation-Version` in `src/manifest.txt`
+- adjust in `docs/index.md`
-#### Marking
+### Java Web Start
-Marked (selected) pieces can be rearranged by selecting the `Arrange` menu point. If no pieces are marked, all pieces will be rearranged. Connected pieces are never rearranged. The pieces will be arranged horizontally starting at the current location, or vertically if the `CTRL` key is pressed when the menu is selected.
+- `puzzle.jnlp` is available in `src/`
+ copy to `docs/`
-* Pieces can be marked (selected) and unmarked by `SHIFT-LEFT`-clicking on them.
-* Use `SHIFT-SPACE` to unmark all pieces.
+### Pictures
-#### Selection Group
+Originals are available under `src/pics/` as Gimp files.
-Pieces can be grouped together in Selection Groups named by a digit or letter. Activating such group will mark the pieces of that group. While the group is active, marking/unmarking a piece will add/remove that piece from that group.
+- `icon.png`
+ scaled to 32x32
+ copy to `docs/` and `src/java/cfh/puzzle/resources`
+- `splash.png`
+ scaled to 640x320
+ copy to `docs/` and `src/java/cfh/puzzle/resources`
+- `social.png`
+ used as Social Preview on GitHub
-- `SHIFT`-digit or `SHIFT`-letter to activate Selection Group.
-- `SHIFT`-`SPACE` to deactivate any group and unmark all pieces.
-- `CTRL`-`SHIFT`-digit or `CTRL`-`SHIFT`-letter to save the actually marked pieces to a Selection Group.
-#### Background
-Selecting the `Background` menu option, a background image can be loaded. A color can be chosen, by entering `color` as file name.
\ No newline at end of file
diff --git a/dist/bus.bat b/dist/bus.bat
index 9c0e600..f6adad3 100644
--- a/dist/bus.bat
+++ b/dist/bus.bat
@@ -1 +1 @@
-@java -jar puzzle.jar bus.jpg 150x60
+@start javaw -jar puzzle.jar bus.jpg 150x60
diff --git a/dist/edtq.bat b/dist/edtq.bat
index 48ba447..e740c50 100644
--- a/dist/edtq.bat
+++ b/dist/edtq.bat
@@ -1 +1 @@
-@java -jar puzzle.jar edtq.jpg 150x65
+@start javaw -jar puzzle.jar edtq.jpg 150x65
diff --git a/dist/kirche.bat b/dist/kirche.bat
index cee8819..cc91770 100644
--- a/dist/kirche.bat
+++ b/dist/kirche.bat
@@ -1 +1 @@
-@java -jar puzzle.jar kirche.jpg 200x60
+@start javaw -jar puzzle.jar kirche.jpg 200x60
diff --git a/dist/prompt.bat b/dist/prompt.bat
new file mode 100644
index 0000000..86005fc
--- /dev/null
+++ b/dist/prompt.bat
@@ -0,0 +1,2 @@
+@set /p image=Image address:
+@start javaw -jar puzzle.jar %image%
diff --git a/dist/puzzle.jar b/dist/puzzle.jar
index 7d0f34f..05b2449 100644
Binary files a/dist/puzzle.jar and b/dist/puzzle.jar differ
diff --git a/docs/icon.png b/docs/icon.png
new file mode 100644
index 0000000..d3a5475
Binary files /dev/null and b/docs/icon.png differ
diff --git a/docs/index.md b/docs/index.md
index 14426ef..9c053f6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1 +1,81 @@
-coming *soon*, check main [README](https://github.com/Heuberger/Puzzle/) for now
\ No newline at end of file
+# Jigaw Puzzle Game
+
+![splash](splash.png)
+
+*use at your own risk - no warranties!* v0.07
+
+
+
+## Running
+
+There are basically two ways to execute the game:
+
+1. `Java Web Start` - a bit complicated but includes automatic updates, desktop shortcut
+2. `local` - just no updates or desktop shortcut, but easy
+
+
+
+### Java Web Start
+
+Select: [puzzle.jnlp](puzzle.jnlp)
+
+This should start the application, if Java Web Start is working correctly;
+otherwise the file is downloaded and must be started by double-click.
+
+Java security needs the installation of 2 certificates to validate the download: if needed, download [here](https://cheuberger.github.io/keys/).
+
+
+
+### Java (WIP)
+
+Download the whole content from the `dist` folder. Start any batch file (e.g. `bus.bat`) or just start (double-click) `puzzle.jar` (command line `java -jar puzzle.jar`).
+
+
+
+## Requirements
+
+Java 8 (`JRE8`) must be installed. Version `8u202` is recommended, license of newer versions have changed - please check it yourself! Old versions can be found at [Java Archive](https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html).
+
+
+
+## How to Play
+
+Open an image file to create a new puzzle
+or
+open a previously saved puzzle to continue playing.
+
+*Note:* puzzles are **not saved** automatically!
+
+#### Moving Pieces
+
+* Use the `LEFT` button to drag and drop pieces.
+ If a piece is dropped near the correct neighbour(s), the pieces will snap together.
+* Hold the `CTRL` Key and click on a connected piece to disconnect it.
+* Use the scroll wheel or double-click (`LEFT` or `RIGHT` button) to rotate the piece(s) under the cursor.
+
+#### General
+
+* `RIGHT` click background to open menu.
+* Use `LEFT` button on background to drag the whole surface.
+* `CTRL`-digit or `CTRL`-letter to save current surface position under that key.
+ The corresponding digit or letter, without `CTRL`, to move to the corresponding saved position.
+* `BACKSPACE` to move back to last position.
+
+#### Marking
+
+Marked (selected) pieces can be rearranged by selecting the `Arrange` menu point. If no pieces are marked and no selection group is active, all pieces will be rearranged. Connected pieces are never rearranged. The pieces will be arranged horizontally starting at the current location, or vertically if the `CTRL` key is pressed when the menu is selected.
+
+* Pieces can be marked (selected) and unmarked by `SHIFT-LEFT`-clicking on them.
+* Use `SHIFT-SPACE` to unmark all pieces.
+
+#### Selection Group
+
+Pieces can be grouped together in Selection Groups named by a digit or letter. Activating such group will mark the pieces of that group. While the group is active, marking/unmarking a piece will add/remove that piece from that group.
+
+- `SHIFT`-digit or `SHIFT`-letter to activate Selection Group.
+- `SHIFT`-`SPACE` to deactivate any group and unmark all pieces.
+- `CTRL`-`SHIFT`-digit or `CTRL`-`SHIFT`-letter to save the actually marked pieces to a Selection Group.
+
+#### Background
+
+A background image can be loaded selecting the `Background` menu option. A color can be chosen instead of an image by entering `color` as file name.
diff --git a/docs/puzzle.jar b/docs/puzzle.jar
new file mode 100644
index 0000000..05b2449
Binary files /dev/null and b/docs/puzzle.jar differ
diff --git a/docs/puzzle.jnlp b/docs/puzzle.jnlp
new file mode 100644
index 0000000..e93f505
--- /dev/null
+++ b/docs/puzzle.jnlp
@@ -0,0 +1,39 @@
+
+
+
+ Jigsaw Puzzle
+ Carlos F. Heuberger
+
+ Jigsaw Puzzle Game
+ An application to create and play Jigsaw puzzles.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/splash.png b/docs/splash.png
new file mode 100644
index 0000000..f7bce5a
Binary files /dev/null and b/docs/splash.png differ
diff --git a/puzzle.jardesc b/puzzle.jardesc
index c42230e..e122cf1 100644
--- a/puzzle.jardesc
+++ b/puzzle.jardesc
@@ -1,4 +1,4 @@
-
+
@@ -12,5 +12,6 @@
+
diff --git a/src/init.sh b/src/init.sh
new file mode 100644
index 0000000..38569b8
--- /dev/null
+++ b/src/init.sh
@@ -0,0 +1,10 @@
+if [ "$PASS_S" = "" ]
+then
+ echo Please set PASS_S
+ return
+fi
+
+ALIAS_S=cfhsi
+JKS_S=~/.jks/$ALIAS_S.jks
+TIMESTAMP="-tsa http://timestamp.digicert.com"
+# TIMESTAMP=
diff --git a/src/java/cfh/FileChooser.java b/src/java/cfh/FileChooser.java
index 05c73e7..2f13da7 100644
--- a/src/java/cfh/FileChooser.java
+++ b/src/java/cfh/FileChooser.java
@@ -1,5 +1,9 @@
package cfh;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+
import java.awt.Component;
import java.awt.HeadlessException;
import java.io.File;
@@ -8,29 +12,55 @@
import javax.swing.JFileChooser;
/**
- * @version 1.0, 01.12.2011
+ * @version 2.1, 2021-04-07
*/
public class FileChooser extends JFileChooser {
- private static final long serialVersionUID = 4258094342413678764L;
+ private static final long serialVersionUID = 1L;
- private final String PREF_DIR = "directory";
+ private final String PREF_FILE = "file";
private final Preferences prefs;
- public FileChooser() {
+ public FileChooser(String key) {
String classname = Thread.currentThread().getStackTrace()[2].getClassName();
- prefs = Preferences.userRoot().node("/" + classname.replace('.', '/'));
- String dir = prefs.get(PREF_DIR, ".");
- setCurrentDirectory(new File(dir));
+ prefs = Preferences.userRoot().node("/" + classname.replace('.', '/') + "/" + key);
+ File file = new File(prefs.get(PREF_FILE, "."));
+ setSelectedFile(file);
+ setMultiSelectionEnabled(false);
+ }
+
+ public File getFileToSave(Component parent) {
+ if (showSaveDialog(getParent()) != APPROVE_OPTION) {
+ return null;
+ }
+ File file = getSelectedFile();
+ Object[] msg = { "File already exists!", file.getAbsolutePath(), "Overwrite?" };
+ if (file.exists() && showConfirmDialog(getParent(), msg, "Confirm", OK_CANCEL_OPTION) != OK_OPTION)
+ return null;
+ if (file.exists()) {
+ File bak = new File(file.getParentFile(), file.getName() + ".bak");
+ if (bak.exists()) {
+ bak.delete();
+ }
+ file.renameTo(bak);
+ }
+ return file;
+ }
+
+ public File getFileToLoad(Component parent) {
+ if (showOpenDialog(parent) != APPROVE_OPTION) {
+ return null;
+ }
+ return getSelectedFile();
}
@Override
public int showOpenDialog(Component parent) throws HeadlessException {
int option = super.showOpenDialog(parent);
if (option == APPROVE_OPTION) {
- String dir = getCurrentDirectory().getAbsolutePath();
- prefs.put(PREF_DIR, dir);
+ File file = getSelectedFile();
+ prefs.put(PREF_FILE, file.getAbsolutePath());
}
return option;
}
@@ -39,8 +69,8 @@ public int showOpenDialog(Component parent) throws HeadlessException {
public int showSaveDialog(Component parent) throws HeadlessException {
int option = super.showSaveDialog(parent);
if (option == APPROVE_OPTION) {
- String dir = getCurrentDirectory().getAbsolutePath();
- prefs.put(PREF_DIR, dir);
+ File file = getSelectedFile();
+ prefs.put(PREF_FILE, file.getAbsolutePath());
}
return option;
}
@@ -49,11 +79,9 @@ public int showSaveDialog(Component parent) throws HeadlessException {
public int showDialog(Component parent, String approveButtonText) throws HeadlessException {
int option = super.showDialog(parent, approveButtonText);
if (option == APPROVE_OPTION) {
- String dir = getCurrentDirectory().getAbsolutePath();
- prefs.put(PREF_DIR, dir);
+ File file = getSelectedFile();
+ prefs.put(PREF_FILE, file.getAbsolutePath());
}
return option;
}
-
}
-
diff --git a/src/java/cfh/puzzle/GamePanel.java b/src/java/cfh/puzzle/GamePanel.java
index c362d79..5660d98 100644
--- a/src/java/cfh/puzzle/GamePanel.java
+++ b/src/java/cfh/puzzle/GamePanel.java
@@ -33,7 +33,6 @@
import javax.swing.ImageIcon;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
-import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
@@ -322,24 +321,26 @@ private void doArrange(ActionEvent ev) {
int j = 0;
int x0 = 15 - getX();
int y0 = 15 - getY();
- for (Piece piece : pieces) {
- if (!piece.getConnected().isEmpty())
- continue;
- if (!all && !piece.isSelected())
- continue;
-
- int x = x0 + i*(sizeX+20) + 5*(j%2);
- int y = y0 + j*(sizeY+20) + 5*(i%2);
- piece.setLocation(x, y);
-
- j += 1;
- if (y + sizeY + piece.getHeight() > h - getY()) {
- j = 0;
- i += 1;
- if (x + sizeX + piece.getWidth() > w - getX()) {
- x0 += 16;
- y0 += 16;
- i = 0;
+ synchronized (getTreeLock()) {
+ for (Piece piece : pieces) {
+ if (!piece.getConnected().isEmpty())
+ continue;
+ if (!all && !piece.isSelected())
+ continue;
+
+ int x = x0 + i*(sizeX+20) + 5*(j%2);
+ int y = y0 + j*(sizeY+20) + 5*(i%2);
+ piece.setLocation(x, y);
+
+ j += 1;
+ if (y + sizeY + piece.getHeight() > h - getY()) {
+ j = 0;
+ i += 1;
+ if (!isShift(ev) && (x + sizeX + piece.getWidth() > w - getX())) {
+ x0 += 16;
+ y0 += 16;
+ i = 0;
+ }
}
}
}
@@ -364,7 +365,7 @@ private void doArrange(ActionEvent ev) {
if (x + pw > w - getX()) {
x = - getX() + delta;
y += ph;
- if (y + ph > h - getY()) {
+ if (!isShift(ev) && (y + ph > h - getY())) {
delta += 16;
x += 16;
y = - getY() + delta;
@@ -412,9 +413,8 @@ public void mousePressed(MouseEvent ev) {
}
private void doBackground(ActionEvent ev) {
- FileChooser chooser = new FileChooser();
- if (chooser.showOpenDialog(getParent()) == JFileChooser.APPROVE_OPTION) {
- File file = chooser.getSelectedFile();
+ File file = new FileChooser("background").getFileToLoad(getParent());
+ if (file != null) {
if (file.isFile()) {
try {
BufferedImage img = ImageIO.read(file);
@@ -470,6 +470,10 @@ private static boolean isCtrl(ActionEvent ev) {
return (ev.getModifiers() & ev.CTRL_MASK) != 0;
}
+ private static boolean isShift(ActionEvent ev) {
+ return (ev.getModifiers() & ev.SHIFT_MASK) != 0;
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////
private class DragListener extends MouseAdapter {
diff --git a/src/java/cfh/puzzle/Test.java b/src/java/cfh/puzzle/Test.java
index 0257a22..d55ca59 100644
--- a/src/java/cfh/puzzle/Test.java
+++ b/src/java/cfh/puzzle/Test.java
@@ -5,6 +5,7 @@
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
@@ -37,7 +38,6 @@
import java.util.Map.Entry;
import java.util.Random;
import javax.imageio.ImageIO;
-import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
@@ -45,7 +45,11 @@
public class Test extends GamePanel {
- private static final String VERSION = "Puzzle by Carlos Heuberger - test v0.05";
+ private static final String VERSION;
+ static {
+ String version = Test.class.getPackage().getImplementationVersion();
+ VERSION = "Puzzle by Carlos F. Heuberger - v" + (version==null ? "?" : version);
+ }
private static final int MAXX = 5000;
private static final int MAXY = 4000;
@@ -65,7 +69,7 @@ public static void main(String[] args) {
String imageName;
BufferedImage image = null;
int index = 0;
-
+
while (index < args.length && args[index].startsWith("-")) {
String opt = args[index++].substring(1);
if (opt.length() == 0) {
@@ -131,11 +135,8 @@ public static void main(String[] args) {
}
}
} else {
- FileChooser chooser = new FileChooser();
- chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- chooser.setMultiSelectionEnabled(false);
- if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
- File file = chooser.getSelectedFile();
+ File file = new FileChooser("puzzle").getFileToLoad(null);
+ if (file != null) {
imageName = file.getAbsolutePath();
try {
image = ImageIO.read(file);
@@ -281,6 +282,17 @@ private Test(int type, BufferedImage image, Size size, long seed, String title)
frame = new JFrame(String.format("%s - %s - %d (%dx%d)", VERSION, title, size.width()*size.height(), size.width(), size.height()));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ URL url = Test.class.getResource("resources/icon.png");
+ if (url == null) {
+ System.err.println("unable to load \"resources/icon.png\"");
+ } else {
+ try {
+ Image icon = ImageIO.read(url);
+ frame.setIconImage(icon);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent ev) {
@@ -300,19 +312,8 @@ public void windowClosing(WindowEvent ev) {
}
private void doSave(ActionEvent ev) {
- FileChooser chooser = new FileChooser();
- if (chooser.showSaveDialog(getParent()) == JFileChooser.APPROVE_OPTION) {
- File file = chooser.getSelectedFile();
- Object[] msg = { "File already exists!", file.getAbsolutePath(), "Overwrite?" };
- if (file.exists() && showConfirmDialog(getParent(), msg, "Confirm", OK_CANCEL_OPTION) != OK_OPTION)
- return;
- if (file.exists()) {
- File bak = new File(file.getParentFile(), file.getName() + ".bak");
- if (bak.exists()) {
- bak.delete();
- }
- file.renameTo(bak);
- }
+ File file = new FileChooser("puzzle").getFileToSave(getParent());
+ if (file != null) {
try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(file))) {
output.writeInt(MAGIC);
output.writeInt(type);
diff --git a/src/java/cfh/puzzle/resources/icon.png b/src/java/cfh/puzzle/resources/icon.png
new file mode 100644
index 0000000..d3a5475
Binary files /dev/null and b/src/java/cfh/puzzle/resources/icon.png differ
diff --git a/src/java/cfh/puzzle/resources/splash.png b/src/java/cfh/puzzle/resources/splash.png
new file mode 100644
index 0000000..f7bce5a
Binary files /dev/null and b/src/java/cfh/puzzle/resources/splash.png differ
diff --git a/src/manifest.txt b/src/manifest.txt
index b03d663..e9b477f 100644
--- a/src/manifest.txt
+++ b/src/manifest.txt
@@ -1,3 +1,12 @@
Manifest-Version: 1.0
Main-Class: cfh.puzzle.Test
-Implementation-Vendor: Carlos Heuberger
+Implementation-Vendor: Carlos F. Heuberger
+Implementation-Version: 0.07
+SplashScreen-Image: cfh/puzzle/resources/splash.png
+Permissions: all-permissions
+Application-Name: Jigsaw Puzzle
+Codebase: heuberger.github.io
+Trusted-Only: true
+Trusted-Library: true
+Sealed: true
+
diff --git a/src/pics/icon.png b/src/pics/icon.png
new file mode 100644
index 0000000..d3a5475
Binary files /dev/null and b/src/pics/icon.png differ
diff --git a/src/pics/icon.xcf b/src/pics/icon.xcf
new file mode 100644
index 0000000..cbcc274
Binary files /dev/null and b/src/pics/icon.xcf differ
diff --git a/src/pics/icon1.png b/src/pics/icon1.png
new file mode 100644
index 0000000..273d012
Binary files /dev/null and b/src/pics/icon1.png differ
diff --git a/src/pics/icon1.xcf b/src/pics/icon1.xcf
new file mode 100644
index 0000000..39ea84c
Binary files /dev/null and b/src/pics/icon1.xcf differ
diff --git a/src/pics/social.png b/src/pics/social.png
new file mode 100644
index 0000000..d0692fa
Binary files /dev/null and b/src/pics/social.png differ
diff --git a/src/pics/social.xcf b/src/pics/social.xcf
new file mode 100644
index 0000000..138b4c5
Binary files /dev/null and b/src/pics/social.xcf differ
diff --git a/src/pics/splash.png b/src/pics/splash.png
new file mode 100644
index 0000000..f7bce5a
Binary files /dev/null and b/src/pics/splash.png differ
diff --git a/src/puzzle.jnlp b/src/puzzle.jnlp
new file mode 100644
index 0000000..e93f505
--- /dev/null
+++ b/src/puzzle.jnlp
@@ -0,0 +1,39 @@
+
+
+
+ Jigsaw Puzzle
+ Carlos F. Heuberger
+
+ Jigsaw Puzzle Game
+ An application to create and play Jigsaw puzzles.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/signjar.sh b/src/signjar.sh
new file mode 100644
index 0000000..3050f90
--- /dev/null
+++ b/src/signjar.sh
@@ -0,0 +1,6 @@
+. init.sh
+
+JS="jarsigner $TIMESTAMP -keystore $JKS_S -storepass:env PASS_S"
+
+$JS ../dist/puzzle.jar $ALIAS_S
+$JS -verify ../dist/puzzle.jar