Skip to content

Commit

Permalink
Merge branch 'master' of github.com:XDjackieXD/PackUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
Kilobyte22 committed Feb 28, 2020
2 parents 34a8f37 + 552ff2a commit 10b468c
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 47 deletions.
13 changes: 1 addition & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,7 @@ It was written to work directly as a pre-launch command for MultiMC and features
* No need for a huge amount of webspace or traffic!

## How?
You can find an example modpack in the folder "ExamplePack".
Basically add the Updater.jar into the instance zip in the minecraft folder
and add this line to the instance.cfg file
`PreLaunchCommand=java -jar "$INST_MC_DIR/Updater.jar" "Link to modpack.cfg file"`
The config file on your server is a csv with the following values:
Name,Version,Download-URL,Type,checksum,flags
Where Type is either "mod", "config" or "resources":
"config" and "resources" are both zip files.
and get extracted into the root folder of your Minecraft instance.
Checksum is optional and if present a sha256 sum of the file.
Flags is a semicolon(`;`) separated list of flags.
Currently supported are `server_only`, `client_only` and `force_overwrite`
For a detailed explanation on how to set up PackUpdate see the [Wiki](https://github.com/XDjackieXD/PackUpdate/wiki)

## How to build?
Install [Scala](https://scala-lang.org/) and [SBT](https://www.scala-sbt.org/), then run `sbt assembly`. This will produce a standalone jar.
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/at/chaosfield/packupdate/common/DebugFlag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package at.chaosfield.packupdate.common;

import scala.Option;
import scala.Some;

/**
* Debug flags are passed comma-separated via the org.chaosfield.packupdate.debug java property
* Example: java -D org.chaosfield.packupdate.debug=force_refresh -jar PackUpdate.jar
*/
public enum DebugFlag {
/**
* Pretend that all packages are corrupt and need to be reinstalled
*/
ForceRefresh("force_refresh")

;

public String internalName;

DebugFlag(String internalName) {
this.internalName = internalName;
}

public static Option<DebugFlag> fromString(String data) {
for (DebugFlag flag : DebugFlag.values()) {
if (flag.internalName.equals(data)) {
return new Some<>(flag);
}
}
return Option.empty();
}
}
32 changes: 28 additions & 4 deletions src/main/scala/at/chaosfield/packupdate/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ import java.io.File
import java.net.URL
import java.util.jar.Manifest

import at.chaosfield.packupdate.common.{MainConfig, MainLogic, PackSide, Util}
import at.chaosfield.packupdate.common.{DebugFlag, MainConfig, MainLogic, PackSide, Util}
import at.chaosfield.packupdate.frontend.{CliCallbacks, SwingFrontend}
import at.chaosfield.packupdate.generator.PackGenerator
import javax.swing.SwingUtilities
import net.sourceforge.argparse4j.ArgumentParsers
import net.sourceforge.argparse4j.impl.Arguments
import net.sourceforge.argparse4j.inf.{ArgumentParser, ArgumentParserException, Namespace, Subparser}

import scala.collection.JavaConverters._
import scala.collection.immutable.HashSet


object Main {

val ProjectName = "PackUpdate"
val UpdaterUpdaterReleasesURL = new URL("https://api.github.com/repos/XDjackieXD/PackUpdateUpdater/releases")
val MultiMCMetadataLWJGL = new URL("https://v1.meta.multimc.org/org.lwjgl/")
val MultiMCMetadataLWJGL = new URL("https://meta.multimc.org/v1/org.lwjgl/")
val PackUpdateReleaseUrl = new URL("https://api.github.com/repos/XDjackieXD/PackUpdate/releases")

/// Hack to get this to run on JavaFx 7
Expand Down Expand Up @@ -137,7 +139,23 @@ object Main {

val remoteUrl = options.getString("url")

MainConfig(mcDir, new URL(remoteUrl), side, options.get("accept-eula"))
val debugFlags =
System.getProperty("at.chaosfield.packupdate.debug", "") match {
case "" => HashSet.empty[DebugFlag]
case list => HashSet.apply(
list
.split(",")
.flatMap(flagName => DebugFlag.fromString(flagName) match {
case Some(entry) =>
Some(entry)
case None =>
println(s"Unknown flag $flagName")
None
}):_*
)
}

MainConfig(mcDir, new URL(remoteUrl), side, options.get("accept-eula"), debugFlags)
}

def runCli(config: MainConfig): Unit = {
Expand All @@ -147,7 +165,13 @@ object Main {
}

def runSwing(config: MainConfig): Unit = {
val logic = new MainLogic(new SwingFrontend)
val gui = Util.swingRun(new SwingFrontend)

Util.swingRunAsync {
gui.run()
}

val logic = new MainLogic(gui)

logic.runUpdate(config)
Util.exit(0) // TODO: Find a solution to this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object FileManager {
case Some(remote_version) => if (remote_version.version != component.version) {
Some(Update.UpdatedComponent(component, remote_version))
} else {
if (component.validateIntegrity(config, ui)) {
if (!config.debugFlags.contains(DebugFlag.ForceRefresh) && component.validateIntegrity(config, ui)) {
None
} else {
Some(Update.InvalidComponent(component))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package at.chaosfield.packupdate.common
import java.io.File
import java.net.URL

import scala.collection.immutable.HashSet

case class MainConfig(
minecraftDir: File,
remoteUrl: URL,
packSide: PackSide,
acceptEula: Boolean = false
acceptEula: Boolean = false,
debugFlags: HashSet[DebugFlag]
)
18 changes: 17 additions & 1 deletion src/main/scala/at/chaosfield/packupdate/common/Util.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import java.nio.file.Files

import at.chaosfield.packupdate.common.error.ChecksumException
import at.chaosfield.packupdate.json.GithubRelease
import javax.swing.SwingUtilities
import org.json4s._
import org.json4s.jackson.JsonMethods

import scala.collection.mutable.ArrayBuffer
import scala.io.Source

object Util {

/**
* Get the file where a [[Component]] should be put. This is only valid for single-file components
*
Expand Down Expand Up @@ -209,4 +209,20 @@ object Util {
def absoluteToRelativePath(path: File, to: File): String = {
to.toURI.relativize(path.toURI).getPath
}

/**
* A wrapper around [[SwingUtilities.invokeAndWait]], that fits better into the scala type system
* @param cb
* @tparam T
* @return
*/
def swingRun[T >: Null](cb: => T): T = {
var foo: T = null
SwingUtilities.invokeAndWait(() => foo = cb)
foo
}

def swingRunAsync(cb: => Unit): Unit = {
SwingUtilities.invokeLater(() => cb)
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package at.chaosfield.packupdate.frontend

import java.awt.event.{WindowEvent, WindowListener}
import java.awt.{Dimension, GridLayout, Window}
import java.awt.{Component, Dimension, Frame, Graphics, GridLayout, Window}

import at.chaosfield.packupdate.common.{ConflictResolution, LogLevel, ProgressUnit, UiCallbacks, Update, Util}
import javax.swing.{BoxLayout, JDialog, JFrame, JLabel, JOptionPane, JPanel, JProgressBar, JTextArea, SwingConstants, WindowConstants}
import javax.swing.{BoxLayout, Icon, JDialog, JFrame, JLabel, JOptionPane, JPanel, JProgressBar, JTextArea, SwingConstants, SwingUtilities, WindowConstants}

import scala.collection.mutable.ArrayBuffer

class SwingFrontend extends UiCallbacks {
val jframe = new JFrame("PackUpdate - Updating Mods")

val size = new Dimension(310, 100)
jframe.setMinimumSize(size)
jframe.setMaximumSize(size)
jframe.setPreferredSize(size)
val panel = new JPanel //("PackUpdate - Updating Mods")

val layout = new GridLayout(0, 1)
jframe.setLayout(layout)
jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS))

//val layout = new GridLayout(0, 1)
//panel.setLayout(layout)
//jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)

val status1 = new JLabel("Launching", SwingConstants.CENTER)
val status2 = new JLabel("", SwingConstants.CENTER)
Expand All @@ -28,22 +26,42 @@ class SwingFrontend extends UiCallbacks {
progress1.setVisible(false)
progress2.setVisible(false)

private val content = jframe.getContentPane
panel.add("status1", status1)
panel.add("progress1", progress1)
panel.add("status2", status2)
panel.add("progress2", progress2)

val pane = new JOptionPane(
"",
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION,
SwingFrontend.EmptyIcon,
Array.empty,
null
)

private val dialog = pane.createDialog(new Frame,"PackUpdate - Updating Mods")

dialog.add(panel)

content.add("status1", status1)
content.add("progress1", progress1)
content.add("status2", status2)
content.add("progress2", progress2)
val size = new Dimension(310, 125)
dialog.setMinimumSize(size)
dialog.setMaximumSize(size)
dialog.setPreferredSize(size)

jframe.pack()
jframe.setVisible(true)
dialog.pack()
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)

private var subStatusMessage: Option[String] = None
private var subProgressUnit = ProgressUnit.Scalar
private var subProgressValue = (0, 0)

private val errorList = ArrayBuffer.empty[String]

def run(): Unit = {
dialog.setVisible(true)
}

/**
*
* @param message the message to display
Expand Down Expand Up @@ -77,8 +95,10 @@ class SwingFrontend extends UiCallbacks {
* @param numTotal the amount of items to process in total
*/
override def progressUpdate(numProcessed: Int, numTotal: Int): Unit = {
progress1.setValue(numProcessed)
progress1.setMaximum(numTotal)
Util.swingRun {
progress1.setValue(numProcessed)
progress1.setMaximum(numTotal)
}
}

/**
Expand All @@ -99,22 +119,28 @@ class SwingFrontend extends UiCallbacks {
* Show a secondary progress indicator to the user
*/
override def subProgressBar_=(value: Boolean): Unit = {
progress2.setVisible(value)
updateSubStatus()
Util.swingRun {
progress2.setVisible(value)
updateSubStatus()
}
}

override def subProgressUpdate(numProcessed: Int, numTotal: Int): Unit = {
progress2.setMaximum(numTotal)
progress2.setValue(numProcessed)
subProgressValue = (numProcessed, numTotal)
updateSubStatus()
Util.swingRun {
progress2.setMaximum(numTotal)
progress2.setValue(numProcessed)
updateSubStatus()
}
}

override def subUnit: ProgressUnit = subProgressUnit

override def subUnit_=(unit: ProgressUnit): Unit = {
subProgressUnit = unit
updateSubStatus()
Util.swingRun {
updateSubStatus()
}
}

/**
Expand All @@ -124,7 +150,9 @@ class SwingFrontend extends UiCallbacks {
*/
override def subStatusUpdate(status: Option[String]): Unit = {
subStatusMessage = status
updateSubStatus()
Util.swingRun {
updateSubStatus()
}
}

/**
Expand All @@ -142,7 +170,7 @@ class SwingFrontend extends UiCallbacks {
*/
override def printTransactionSummary(summary: List[(String, List[Update])]): Unit = CliCallbacks.printTransactionSummary(summary)

override def log(logLevel: LogLevel, message: String): Unit = CliCallbacks.log(logLevel, message)
override def log(logLevel: LogLevel, message: String): Unit = println(format_log(logLevel, message))

def updateSubStatus(): Unit = {
val status = new StringBuilder
Expand Down Expand Up @@ -176,7 +204,17 @@ class SwingFrontend extends UiCallbacks {
errorBox.setEditable(false)
panel.add(errorBox)

JOptionPane.showMessageDialog(jframe, panel, "PackUpdate encountered errors during operation", JOptionPane.PLAIN_MESSAGE)
JOptionPane.showMessageDialog(panel, panel, "PackUpdate encountered errors during operation", JOptionPane.PLAIN_MESSAGE)
}
}
}

object SwingFrontend {
object EmptyIcon extends Icon {
override def paintIcon(c: Component, g: Graphics, x: Int, y: Int): Unit = ()

override def getIconWidth: Int = 0

override def getIconHeight: Int = 0
}
}

0 comments on commit 10b468c

Please sign in to comment.