Install STKO in docker and add to supervisord
This commit is contained in:
parent
67121f5fd6
commit
669d0df55b
39
Dockerfile
39
Dockerfile
|
|
@ -105,17 +105,42 @@ FROM system
|
|||
|
||||
COPY --from=builder /src/web/dist/ /usr/local/lib/web/frontend/
|
||||
|
||||
# Install QGIS
|
||||
# Install STKO
|
||||
|
||||
|
||||
RUN apt update \
|
||||
&& apt upgrade -y \
|
||||
&& apt install build-essential -y
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -y \
|
||||
xterm \
|
||||
&& apt autoclean \
|
||||
&& apt autoremove \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
python3-dev \
|
||||
tcl8.6-dev \
|
||||
tk8.6-dev \
|
||||
libtogl-dev \
|
||||
libglu1-mesa-dev \
|
||||
freeglut3-dev \
|
||||
mesa-common-dev \
|
||||
mesa-utils \
|
||||
libxi-dev \
|
||||
libxmu-dev \
|
||||
xterm
|
||||
|
||||
# Add our STKO (currently using glxgears as example)
|
||||
RUN apt update && apt-get install -y mesa-utils
|
||||
RUN apt update \
|
||||
&& apt install -y \
|
||||
libxkbcommon-x11-0
|
||||
|
||||
# Add stko executable
|
||||
ADD STKO-Install /STKO-Install
|
||||
# Use/overwrite script so that it uses qt libs that will be installed by online installer
|
||||
COPY STKO.sh /STKO-Install/STKO.sh
|
||||
|
||||
# Install qt 5.12.4 using online installer
|
||||
COPY qt_install_utils/ /qt_temp
|
||||
ADD http://download.qt.io/official_releases/qt/5.12/5.12.4/qt-opensource-linux-x64-5.12.4.run /qt_temp/qt-opensource-linux-x64-5.12.4.run
|
||||
RUN chmod +x /qt_temp/qt-opensource-linux-x64-5.12.4.run
|
||||
RUN /qt_temp/qt-opensource-linux-x64-5.12.4.run --script /qt_temp/qt-installer.qs -platform minimal
|
||||
RUN rm -rf /qt_temp
|
||||
|
||||
COPY image /
|
||||
EXPOSE 6080
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
STKO app
|
||||
--------
|
||||
Here are some notes on this app's image.
|
||||
|
||||
|
||||
Building Docker image
|
||||
================
|
||||
Get STKO-Install.zip from developers and unzip into this diretory
|
||||
```
|
||||
docker build -t tagname .
|
||||
```
|
||||
|
||||
Other files of interest used in image
|
||||
=========================
|
||||
STKO.sh is an edited version of STKO-Install/STKO.sh (provided by STKO devs) which uses a system-installed qt version instead of the libs they provided
|
||||
`qt_install_utils/qt-installer.qs` is an input script to online qt installer (see Dockerfile for more details on how its used)
|
||||
`qt_install_utils/extract-qt-installer` can be used to see a list of modules which might be helpful when editing qt-installer.qs (`./extract-qt-installer --list qt-opensource-linux-x64-5.12.4.run`)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
appname=`basename $0 | sed s,\.sh$,,`
|
||||
|
||||
dirname=`dirname $0`
|
||||
tmp="${dirname#?}"
|
||||
|
||||
if [ "${dirname%$tmp}" != "/" ]; then
|
||||
dirname=$PWD/$dirname
|
||||
fi
|
||||
|
||||
core=$dirname/lib/core
|
||||
coredep=$dirname/lib/coredep
|
||||
export QTTOOLDIR=/opt/Qt5.12.4/5.12.4/gcc_64/bin
|
||||
export QTLIBDIR=/opt/Qt5.12.4/5.12.4/gcc_64/lib
|
||||
LD_LIBRARY_PATH=$dirname:$core:$coredep:$QTLIBDIR:$LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH
|
||||
#export QT_DEBUG_PLUGINS=1
|
||||
#echo "$0 = "$0
|
||||
#echo "appname = "$appname
|
||||
#echo "dirname = "$dirname
|
||||
#echo "tmp = "$tmp
|
||||
echo "LD_LIBRARY_PATH = "$LD_LIBRARY_PATH
|
||||
|
||||
$dirname/$appname "$@"
|
||||
|
|
@ -63,7 +63,7 @@ stdout_logfile=/var/log/novnc.log
|
|||
[program:stko]
|
||||
priority=35
|
||||
directory=/home/ubuntu/mydata
|
||||
command=xterm -r -ls -geometry 80x24+10+10 -title '*** Exit this window to kill your QGIS session ***' -e 'xterm'
|
||||
command=xterm -r -ls -geometry 80x24+10+10 -title '*** Exit this window to kill your STKO session ***' -e '/STKO-Install/STKO.sh'
|
||||
user=ubuntu
|
||||
autostart=true
|
||||
autorestart=false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,340 @@
|
|||
#!/bin/bash
|
||||
# QT-CI Project
|
||||
# License: Apache-2.0
|
||||
# https://github.com/benlau/qtci
|
||||
|
||||
function usage() {
|
||||
echo "Usage:"
|
||||
echo "extract-qt-installer qt-installer output_path"
|
||||
echo "extract-qt-installer --list-packages qt-installer"
|
||||
exit -1
|
||||
}
|
||||
|
||||
LIST_PACKAGES=0
|
||||
|
||||
getopt --test > /dev/null 2>&1
|
||||
GETOPT_RET_CODE=$?
|
||||
|
||||
set -e #quit on error
|
||||
|
||||
if [ "$GETOPT_RET_CODE" != "4" ]
|
||||
then
|
||||
echo "Warning: gnu-getopt is not installed. Long parameter like '--list-package' will not be working. Please install gnu-getopt by 'brew install gnu-getopt'"
|
||||
else
|
||||
|
||||
OPTS=`getopt -o l --long list-packages --long disable-progress-report -n "extract-qt-installer" -- "$@"`
|
||||
|
||||
eval set -- "$OPTS"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
--list-packages)
|
||||
LIST_PACKAGES=1
|
||||
shift;;
|
||||
--disable-progress-report)
|
||||
DISABLE_PROGRESS_REPORT=1
|
||||
shift;;
|
||||
--) shift;break;;
|
||||
*) shift;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
export PATH=$PATH:$PWD
|
||||
export WORKDIR=$PWD
|
||||
INSTALLER=$1
|
||||
OUTPUT=$2
|
||||
SCRIPT="$(mktemp /tmp/tmp.XXXXXXXXX)"
|
||||
PACKAGES=$QT_CI_PACKAGES
|
||||
|
||||
if [ $LIST_PACKAGES -gt 0 ]
|
||||
then
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
OUTPUT="/tmp/Qt"
|
||||
|
||||
else
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [[ ! "${OUTPUT:0:1}" = "/" ]]
|
||||
then
|
||||
echo output path must be an absolute path
|
||||
exit -1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cat <<EOF > $SCRIPT
|
||||
|
||||
function abortInstaller()
|
||||
{
|
||||
installer.setDefaultPageVisible(QInstaller.Introduction, false);
|
||||
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
|
||||
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
|
||||
installer.setDefaultPageVisible(QInstaller.ReadyForInstallation, false);
|
||||
installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false);
|
||||
installer.setDefaultPageVisible(QInstaller.PerformInstallation, false);
|
||||
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
|
||||
|
||||
var abortText = "<font color='red' size=3>" + qsTr("Installation failed:") + "</font>";
|
||||
|
||||
var error_list = installer.value("component_errors").split(";;;");
|
||||
abortText += "<ul>";
|
||||
// ignore the first empty one
|
||||
for (var i = 0; i < error_list.length; ++i) {
|
||||
if (error_list[i] !== "") {
|
||||
log(error_list[i]);
|
||||
abortText += "<li>" + error_list[i] + "</li>"
|
||||
}
|
||||
}
|
||||
abortText += "</ul>";
|
||||
installer.setValue("FinishedText", abortText);
|
||||
}
|
||||
|
||||
function log() {
|
||||
var msg = ["QTCI: "].concat([].slice.call(arguments));
|
||||
console.log(msg.join(" "));
|
||||
}
|
||||
|
||||
function printObject(object) {
|
||||
var lines = [];
|
||||
for (var i in object) {
|
||||
lines.push([i, object[i]].join(" "));
|
||||
}
|
||||
log(lines.join(","));
|
||||
}
|
||||
|
||||
var status = {
|
||||
widget: null,
|
||||
finishedPageVisible: false,
|
||||
installationFinished: false
|
||||
}
|
||||
|
||||
function tryFinish() {
|
||||
if (status.finishedPageVisible && status.installationFinished) {
|
||||
if (status.widget.LaunchQtCreatorCheckBoxForm) {
|
||||
// Disable this checkbox for minimal platform
|
||||
status.widget.LaunchQtCreatorCheckBoxForm.launchQtCreatorCheckBox.setChecked(false);
|
||||
}
|
||||
if (status.widget.RunItCheckBox) {
|
||||
// LaunchQtCreatorCheckBoxForm may not work for newer versions.
|
||||
status.widget.RunItCheckBox.setChecked(false);
|
||||
}
|
||||
log("Press Finish Button");
|
||||
gui.clickButton(buttons.FinishButton);
|
||||
}
|
||||
}
|
||||
|
||||
function Controller() {
|
||||
installer.installationFinished.connect(function() {
|
||||
status.installationFinished = true;
|
||||
gui.clickButton(buttons.NextButton);
|
||||
tryFinish();
|
||||
});
|
||||
installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
|
||||
installer.setMessageBoxAutomaticAnswer("installationErrorWithRetry", QMessageBox.Ignore);
|
||||
installer.setMessageBoxAutomaticAnswer("XcodeError", QMessageBox.Ok);
|
||||
|
||||
// Allow to cancel installation for arguments --list-packages
|
||||
installer.setMessageBoxAutomaticAnswer("cancelInstallation", QMessageBox.Yes);
|
||||
}
|
||||
|
||||
Controller.prototype.WelcomePageCallback = function() {
|
||||
log("Welcome Page");
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
/*
|
||||
Online installer 3.0.6
|
||||
- It must disconnect the completeChanged callback after used, otherwise it will click the 'next' button on another pages
|
||||
*/
|
||||
var callback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
widget.completeChanged.disconnect(callback);
|
||||
}
|
||||
|
||||
widget.completeChanged.connect(callback);
|
||||
}
|
||||
|
||||
Controller.prototype.CredentialsPageCallback = function() {
|
||||
|
||||
var login = installer.environmentVariable("QT_CI_LOGIN");
|
||||
var password = installer.environmentVariable("QT_CI_PASSWORD");
|
||||
|
||||
if (login === "" || password === "") {
|
||||
gui.clickButton(buttons.CommitButton);
|
||||
}
|
||||
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
widget.loginWidget.EmailLineEdit.setText(login);
|
||||
|
||||
widget.loginWidget.PasswordLineEdit.setText(password);
|
||||
|
||||
gui.clickButton(buttons.CommitButton);
|
||||
}
|
||||
|
||||
Controller.prototype.ComponentSelectionPageCallback = function() {
|
||||
log("ComponentSelectionPageCallback");
|
||||
|
||||
function list_packages() {
|
||||
var components = installer.components();
|
||||
log("Available components: " + components.length);
|
||||
var packages = ["Packages: "];
|
||||
|
||||
for (var i = 0 ; i < components.length ;i++) {
|
||||
packages.push(components[i].name);
|
||||
}
|
||||
log(packages.join(" "));
|
||||
}
|
||||
|
||||
if ($LIST_PACKAGES) {
|
||||
list_packages();
|
||||
gui.clickButton(buttons.CancelButton);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Select components");
|
||||
|
||||
function trim(str) {
|
||||
return str.replace(/^ +/,"").replace(/ *$/,"");
|
||||
}
|
||||
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
var packages = trim("$PACKAGES").split(",");
|
||||
if (packages.length > 0 && packages[0] !== "") {
|
||||
widget.deselectAll();
|
||||
var components = installer.components();
|
||||
var allfound = true;
|
||||
for (var i in packages) {
|
||||
var pkg = trim(packages[i]);
|
||||
var found = false;
|
||||
for (var j in components) {
|
||||
if (components[j].name === pkg) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
allfound = false;
|
||||
log("ERROR: Package " + pkg + " not found.");
|
||||
} else {
|
||||
log("Select " + pkg);
|
||||
widget.selectComponent(pkg);
|
||||
}
|
||||
}
|
||||
if (!allfound) {
|
||||
list_packages();
|
||||
// TODO: figure out how to set non-zero exit status.
|
||||
gui.clickButton(buttons.CancelButton);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log("Use default component list");
|
||||
}
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.IntroductionPageCallback = function() {
|
||||
log("Introduction Page");
|
||||
log("Retrieving meta information from remote repository");
|
||||
|
||||
/*
|
||||
Online installer 3.0.6
|
||||
- Don't click buttons.NextButton directly. It will skip the componenet selection.
|
||||
*/
|
||||
|
||||
if (installer.isOfflineOnly()) {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.prototype.TargetDirectoryPageCallback = function() {
|
||||
log("Set target installation page: $OUTPUT");
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
if (widget != null) {
|
||||
widget.TargetDirectoryLineEdit.setText("$OUTPUT");
|
||||
}
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.LicenseAgreementPageCallback = function() {
|
||||
log("Accept license agreement");
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
if (widget != null) {
|
||||
widget.AcceptLicenseRadioButton.setChecked(true);
|
||||
}
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.ReadyForInstallationPageCallback = function() {
|
||||
log("Ready to install");
|
||||
|
||||
// Bug? If commit button pressed too quickly finished callback might not show the checkbox to disable running qt creator
|
||||
// Behaviour started around 5.10. You don't actually have to press this button at all with those versions, even though gui.isButtonEnabled() returns true.
|
||||
|
||||
gui.clickButton(buttons.CommitButton, 200);
|
||||
}
|
||||
|
||||
Controller.prototype.PerformInstallationPageCallback = function() {
|
||||
log("PerformInstallationPageCallback");
|
||||
gui.clickButton(buttons.CommitButton);
|
||||
}
|
||||
|
||||
Controller.prototype.FinishedPageCallback = function() {
|
||||
log("FinishedPageCallback");
|
||||
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
// Bug? Qt 5.9.5 and Qt 5.9.6 installer show finished page before the installation completed
|
||||
// Don't press "finishButton" immediately
|
||||
|
||||
status.finishedPageVisible = true;
|
||||
status.widget = widget;
|
||||
tryFinish();
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
chmod u+x $1
|
||||
if [ -n "$QT_CI_DEBUG" ]
|
||||
then
|
||||
$INSTALLER -v --script $SCRIPT | grep "\(QTCI\|operation\)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
unset DISPLAY
|
||||
|
||||
if [ -n "$DISABLE_PROGRESS_REPORT" ]
|
||||
then
|
||||
QT_QPA_PLATFORM=minimal $INSTALLER --script $SCRIPT
|
||||
else
|
||||
ARGS="-v"
|
||||
|
||||
if [ -n "$VERBOSE" ]
|
||||
then
|
||||
QT_QPA_PLATFORM=minimal $INSTALLER $ARGS --script $SCRIPT
|
||||
else
|
||||
QT_QPA_PLATFORM=minimal $INSTALLER $ARGS --script $SCRIPT | grep "\(QTCI\|operation\)"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// installer script for the Qt installer. Launch with (-platform is for headless)
|
||||
// ./installer -platform minimal --script path/to/qt-installer.qs
|
||||
|
||||
function Controller() {
|
||||
installer.autoRejectMessageBoxes();
|
||||
installer.installationFinished.connect(function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
})
|
||||
}
|
||||
|
||||
Controller.prototype.WelcomePageCallback = function() {
|
||||
// click delay here because the next button is initially disabled for ~1 second
|
||||
gui.clickButton(buttons.NextButton, 3000);
|
||||
}
|
||||
|
||||
Controller.prototype.CredentialsPageCallback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.IntroductionPageCallback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.TargetDirectoryPageCallback = function() {
|
||||
gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/Qt5.12.4");
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.ComponentSelectionPageCallback = function() {
|
||||
var widget = gui.currentPageWidget();
|
||||
widget.deselectAll();
|
||||
// Package names are a mystery but can be extracted using the following script with a --list-packages flag:
|
||||
// https://raw.githubusercontent.com/benlau/qtci/master/bin/extract-qt-installer
|
||||
// Here is the full list for 5.12:
|
||||
// qt qt.qt5.5124 qt.tools qt.installer.changelog qt.license.gplv3except qt.license.python qt.license.thirdparty qt.license.lgpl qt.qt5.5124.gcc_64 qt.qt5.5124.android_x86 qt.qt5.5124.android_arm64_v8a qt.qt5.5124.android_armv7 qt.qt5.5124.src qt.qt5.5124.qtcharts qt.qt5.5124.qtdatavis3d qt.qt5.5124.qtpurchasing qt.qt5.5124.qtvirtualkeyboard qt.qt5.5124.qtwebengine qt.qt5.5124.qtnetworkauth qt.qt5.5124.qtwebglplugin qt.qt5.5124.qtscript qt.qt5.5124.examples qt.qt5.5124.doc qt.qt5.5124.qtcharts.android_x86 qt.qt5.5124.qtcharts.android_arm64_v8a qt.qt5.5124.qtcharts.android_armv7 qt.qt5.5124.qtcharts.gcc_64 qt.qt5.5124.qtdatavis3d.android_x86 qt.qt5.5124.qtdatavis3d.android_arm64_v8a qt.qt5.5124.qtdatavis3d.android_armv7 qt.qt5.5124.qtdatavis3d.gcc_64 qt.qt5.5124.qtpurchasing.android_arm64_v8a qt.qt5.5124.qtpurchasing.android_x86 qt.qt5.5124.qtpurchasing.gcc_64 qt.qt5.5124.qtpurchasing.android_armv7 qt.qt5.5124.qtvirtualkeyboard.gcc_64 qt.qt5.5124.qtwebengine.gcc_64 qt.qt5.5124.qtnetworkauth.android_x86 qt.qt5.5124.qtnetworkauth.gcc_64 qt.qt5.5124.qtnetworkauth.android_armv7 qt.qt5.5124.qtnetworkauth.android_arm64_v8a qt.qt5.5124.qtwebglplugin.gcc_64 qt.qt5.5124.qtscript.android_armv7 qt.qt5.5124.qtscript.android_arm64_v8a qt.qt5.5124.qtscript.android_x86 qt.qt5.5124.qtscript.gcc_64 qt.qt5.5124.examples.qtdatavis3d qt.qt5.5124.examples.qtpurchasing qt.qt5.5124.examples.qtcharts qt.qt5.5124.examples.qtwebengine qt.qt5.5124.examples.qtscript qt.qt5.5124.examples.qtnetworkauth qt.qt5.5124.examples.qtvirtualkeyboard qt.qt5.5124.doc.qtwebengine qt.qt5.5124.doc.qtpurchasing qt.qt5.5124.doc.qtdatavis3d qt.qt5.5124.doc.qtcharts qt.qt5.5124.doc.qtvirtualkeyboard qt.qt5.5124.doc.qtnetworkauth qt.qt5.5124.doc.qtscript qt.tools.qtcreator
|
||||
// qt qt.qt5.5124 qt.tools qt.installer.changelog qt.license.gplv3except qt.license.python qt.license.thirdparty qt.license.lgpl qt.qt5.5124.gcc_64 qt.qt5.5124.android_x86 qt.qt5.5124.android_arm64_v8a qt.qt5.5124.android_armv7 qt.qt5.5124.src qt.qt5.5124.qtcharts qt.qt5.5124.qtdatavis3d qt.qt5.5124.qtpurchasing qt.qt5.5124.qtvirtualkeyboard qt.qt5.5124.qtwebengine qt.qt5.5124.qtnetworkauth qt.qt5.5124.qtwebglplugin qt.qt5.5124.qtscript ...
|
||||
widget.selectComponent("qt.qt5.5124.gcc_64");
|
||||
//widget.selectComponent("qt.qt5.5124.qtcharts");
|
||||
//widget.selectComponent("qt.qt5.5124.qtdatavis3d");
|
||||
//widget.selectComponent("qt.qt5.5124.qtvirtualkeyboard");
|
||||
//widget.selectComponent("qt.qt5.5124.qtwebengine");
|
||||
//widget.selectComponent("qt.qt5.5124.qtnetworkauth");
|
||||
//widget.selectComponent("qt.qt5.5124.qtwebglplugin");
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.LicenseAgreementPageCallback = function() {
|
||||
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.StartMenuDirectoryPageCallback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.ReadyForInstallationPageCallback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.FinishedPageCallback = function() {
|
||||
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
|
||||
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
|
||||
checkBoxForm.launchQtCreatorCheckBox.checked = false;
|
||||
}
|
||||
gui.clickButton(buttons.FinishButton);
|
||||
}
|
||||
Loading…
Reference in New Issue