Initial commit

This commit is contained in:
Max Weber
2019-12-12 13:21:58 -07:00
commit f5db90a810
23 changed files with 1095 additions and 0 deletions

10
.travis.yml Normal file
View File

@@ -0,0 +1,10 @@
language: java
sudo: false
dist: xenial
cache:
directories:
- $HOME/.m2
jdk:
- openjdk8
install: true
script: ./travis.sh

25
LICENSE Normal file
View File

@@ -0,0 +1,25 @@
BSD 2-Clause License
Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2
LICENSE.templateplugin Normal file
View File

@@ -0,0 +1,2 @@
The contents of the template plugin and the output of the `create_net_plugin.py`
script are, released into the public domain unless otherwise noted.

18
README.md Normal file
View File

@@ -0,0 +1,18 @@
![](https://runelite.net/img/logo.png)
# plugin-hub [![Discord](https://img.shields.io/discord/301497432909414422.svg)](https://discord.gg/mePCs8U)
This repository contains markers for [RuneLite](https://github.com/runelite/runelite)
plugins that are not supported by the RuneLite Developers. The plugins are
provided "as is"; we make no guarantees about any plugin in this repo.
## Creating new plugins
Clone this repository and run the `create_new_plugin.py` script. It will ask
some questions then generate a plugin skeleton. When your plugin is ready to
release, create a new GitHub repository with it, then put the url and commit
hash you want to release in this repository's `plugins` directory and create
a PR. We will then review your plugin to ensure it isn't malicious or [breaking
jagex's rules](https://secure.runescape.com/m=news/another-message-about-unofficial-clients?oldschool=1).
__If it is difficult for us to ensure the plugin isn't against the rules we
will not merge it__.

77
build_manifest.sh Executable file
View File

@@ -0,0 +1,77 @@
#!/bin/bash
# Copyright (c) 2019 Abex
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
source repo_config.sh
set -e -x
[[ "${TRAVIS_PULL_REQUEST:-false}" == "false" ]] || exit 0
RUNELITE_VERSION="$(cat "runelite.version")"
MANIFEST="$(mktemp /tmp/manifest.XXXXXXXX)"
trap "rm -f ""$MANIFEST*""" EXIT
echo "[" > "$MANIFEST"
IS_FIRST=true
for PLUGINFILE in plugins/*; do
# read in the plugin descriptor
disabled=
# shellcheck disable=SC2162
while read LINE || [[ -n "$LINE" ]]; do
[[ $LINE =~ ^(repository|commit|disabled)=(.*)$ ]]
eval "${BASH_REMATCH[1]}=\"${BASH_REMATCH[2]}\""
done < "$PLUGINFILE"
[ -z "$disabled" ] || continue
PLUGIN_ID=$(basename "$PLUGINFILE")
LOCATION="$REPO_ROOT/$RUNELITE_VERSION/$PLUGIN_ID/$commit"
RET=0
curl --fail "$LOCATION.manifest" > "$MANIFEST.sub" || RET=$?
[ $RET -ne 0 ] && continue
if [[ "$IS_FIRST" != true ]]; then
echo "," >> "$MANIFEST"
fi
IS_FIRST=
cat "$MANIFEST.sub" >> "$MANIFEST"
done
echo "]" >> "$MANIFEST"
# shellcheck disable=SC2059
openssl dgst -sha256 -sign <(set +x; printf -- "$SIGNING_KEY") -out "$MANIFEST.sig" "$MANIFEST"
perl -e "print pack('N', -s \"$MANIFEST.sig\")" > "$MANIFEST.out"
cat "$MANIFEST.sig" >> "$MANIFEST.out"
cat "$MANIFEST" >> "$MANIFEST.out"
curl --fail \
--user "$REPO_CREDS" \
--upload-file "$MANIFEST.out" "$REPO_ROOT/$RUNELITE_VERSION/manifest.js"
echo "Build Success"

95
build_plugin.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/bash
# Copyright (c) 2019 Abex
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
source repo_config.sh
set -e -x
PLUGINFILE="$1"
[ -s "$PLUGINFILE" ]
PLUGIN_ID=$(basename "$PLUGINFILE")
# check valid plugin id
[[ $PLUGIN_ID =~ ^[a-z0-9-]+$ ]]
SCRIPT_HOME="$(cd "$(dirname "$0")" ; pwd -P)"
RUNELITE_VERSION="$(cat "$SCRIPT_HOME/runelite.version")"
# read in the plugin descriptor
disabled=
# shellcheck disable=SC2162
while read LINE || [[ -n "$LINE" ]]; do
[[ $LINE =~ ^(repository|commit|disabled)=(.*)$ ]]
eval "${BASH_REMATCH[1]}=\"${BASH_REMATCH[2]}\""
done < "$PLUGINFILE"
[ -z "$disabled" ] || exit 0
# must be a https github repo
[[ $repository =~ ^https://github.com/.*\.git$ ]]
# we must have a full 40 char sha1sum
[[ $commit =~ ^[a-fA-F0-9]{40}+$ ]]
BUILDDIR="$(mktemp -d /tmp/external-plugin.XXXXXXXX)"
trap "rm -rf ""$BUILDDIR""" EXIT
pushd "$BUILDDIR"
git clone "$repository" "repo"
pushd "repo"
git checkout "$commit"
SIGNING_KEY="" REPO_CREDS="" gradle \
--no-build-cache \
--parallel \
--console=plain \
--init-script="$SCRIPT_HOME/package.gradle" \
-DrlpluginRuneLiteVersion="$RUNELITE_VERSION" \
-DrlpluginOutputDirectory="$BUILDDIR" \
-DrlpluginPluginID="$PLUGIN_ID" \
-DrlpluginCommit="$commit" \
rlpluginPackageJar rlpluginEmitManifest
[ -s "$BUILDDIR/plugin.jar" ]
[ -s "$BUILDDIR/plugin.manifest" ]
cat "$BUILDDIR/plugin.manifest"
[[ "${TRAVIS_PULL_REQUEST:-false}" == "false" ]] || exit 0
LOCATION="$REPO_ROOT/$RUNELITE_VERSION/$PLUGIN_ID/$commit"
ICON_UPLOAD=()
if [ -e "icon.png" ]; then
ICON_UPLOAD=("--upload-file" "icon.png" "$LOCATION.png")
fi
curl --fail \
--user "$REPO_CREDS" \
--upload-file "$BUILDDIR/plugin.manifest" "$LOCATION.manifest" \
--upload-file "$BUILDDIR/plugin.jar" "$LOCATION.jar" \
"${ICON_UPLOAD[@]}"
echo "Build Success"

198
create_new_plugin.py Executable file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env python3
"""
Copyright (c) 2019 Abex
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import os
import sys
from collections import OrderedDict
import argparse
import re
from string import Template
templatedir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templateplugin")
def strip_plugin(str):
return re.sub(r"(?i)[ _-]*plugin$", "", str)
def reformat(str, replacer):
if replacer != to_spaces:
str=re.sub(r"[^a-zA-Z0-9_ -]", "", str)
if re.match(r".*[ _-]", str):
return re.sub(r"(?:^|[ _.-]+)([^ _.-]+)", lambda m:replacer(m.group(1)), str).strip(" -_")
return re.sub(r"((?:^.|[A-Z0-9]+)(?:[a-z0-9]+|$))", lambda m:replacer(m.group(1)), str).strip(" -_")
def to_spaces(seg):
return " " + seg.capitalize()
def to_camelcase(seg):
return seg.capitalize()
def to_dashes(seg):
return "-" + seg.lower()
def to_lowercase(seg):
return seg.lower()
def strfun(strfun):
if isinstance(strfun, str):
return strfun
return strfun()
subs = OrderedDict([
("name", {
"ask": True,
"desc": "The name your plugin will be shown by in menus",
"value": "Foo Bazzer",
"strip_plugin": True,
}),
("package", {
"ask": True,
"desc": "The java package your plugin will be in. Typically a reversed domain name",
"value": "com.examaple.foobazzer",
"strip_plugin": True,
}),
("author", {
"ask": True,
"desc": "Who wrote/maintains this plugin",
"value": "John Doe",
}),
("description", {
"ask": True,
"desc": "A short string describing the plugin",
"value": "Adds a bazzer to the foo",
}),
("version", {
"desc": "The initial version number of the plugin",
"value": "1.0-SNAPSHOT",
}),
("plugin_prefix", {
"desc": "The name of the your plugin's main class, without the 'Plugin' suffix",
"value": lambda: reformat(subs["name"]["value"], to_camelcase),
"strip_plugin": True
}),
("artifact_id", {
"desc": "The name of the maven artifact",
"value": lambda: reformat(subs["name"]["value"], to_dashes),
}),
("group_id", {
"desc": "The group of the maven artifact",
"value": lambda: subs["package"]["value"],
}),
("plugin_config_group", {
"desc": "The prefix used to store config keys",
"value": lambda: reformat(subs["name"]["value"], to_lowercase),
"strip_plugin": True
})
])
pwd = os.getcwd()
pwdIsEmpty = len(os.listdir(pwd)) == 0
if pwdIsEmpty:
subs["name"]["value"] = strip_plugin(reformat(os.path.basename(pwd), to_spaces))
parser = argparse.ArgumentParser()
parser.add_argument("--noninteractive", dest = "noninteractive", action='store_true')
parser.add_argument("--output_directory", dest = "output_directory")
for key, var in subs.items():
parser.add_argument("--" + key, dest = key, help = var["desc"])
args = vars(parser.parse_args())
noninteractive = args["noninteractive"]
if noninteractive and pwdIsEmpty:
subs["name"]["ask"] = False
for key, var in subs.items():
if args[key] != None:
val = args[key]
if "strip_plugin" in var and var["strip_plugin"]:
val = strip_plugin(val)
var["value"] = val
var["ask"] = False
askAll = False
while True:
for key, var in subs.items():
if askAll or ("ask" in var and var["ask"]):
if noninteractive:
print("\"{}\" was not specified in noninteractive mode".format(key))
sys.exit(1)
print(var["desc"])
print("[" + strfun(var["value"]) + "]")
val = input(key + ": ")
if val:
if "strip_plugin" in var and var["strip_plugin"]:
val = strip_plugin(val)
var["value"] = val
askAll = True
print("")
for key, var in subs.items():
print("{} = \"{}\"".format(key, strfun(var["value"])))
def input_yes():
while True:
inp = input("Is this ok? [Yn]").lower()
if inp == "" or inp == "y":
return True
if inp == "n":
return False
if noninteractive or input_yes():
break
outdir = args["output_directory"]
if outdir == None:
if pwdIsEmpty:
outdir = pwd
else:
outdir = os.path.join(pwd, strfun(subs["artifact_id"]["value"]))
mappings = {}
for key, var in subs.items():
mappings[key] = strfun(var["value"])
mappings["package_path"] = mappings["package"].replace(".", os.path.sep)
with open(os.path.join(templatedir, "../runelite.version"), "rt") as fi:
mappings["runelite_version"] = fi.read().strip()
for root, dir, files in os.walk(templatedir):
for file in files:
try:
infi = os.path.join(root, file)
outfi = os.path.join(os.path.relpath(root, templatedir), file)
outfi = outfi.replace("_(", "${").replace(")_", "}")
outfi = Template(outfi).substitute(mappings)
outfi = os.path.join(outdir, outfi)
os.makedirs(os.path.dirname(outfi), exist_ok=True)
with open(infi, "rb") as ifd: # we need binary mode to not do that stupid crlf bullshit on windows
if file.endswith(".jar") or file.startswith("gradlew"):
with open(outfi, "wb") as ofd:
ofd.write(ifd.read())
else:
contents = Template(ifd.read().decode("utf-8")).substitute(mappings)
with open(outfi, "wb") as ofd:
ofd.write(contents.encode("utf-8"))
except ValueError as ex:
raise ValueError(infi) from ex

137
package.gradle Normal file
View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2019 Abex
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.google.common.hash.Hashing
import com.google.common.io.Files
import com.google.gson.Gson
initscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0"
classpath "com.google.code.gson:gson:2.8.5"
classpath "com.google.guava:guava:23.2-jre"
}
}
allprojects {
apply plugin: "java";
apply plugin: com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
tasks.withType(AbstractArchiveTask) {
preserveFileTimestamps = false
reproducibleFileOrder = true
}
task rlpluginPackageJar(type: ShadowJar) {
destinationDir = new File(System.properties["rlpluginOutputDirectory"])
archiveName = "plugin.jar"
configurations = [project.configurations.runtimeClasspath]
from sourceSets.main.output
}
task rlpluginEmitManifest {
// this doesn't have up-to-date stuff because we always do --no-build-cache
doLast {
def manifest = new ExternalPluginManifest()
manifest.internalName = System.properties["rlpluginPluginID"]
manifest.commit = System.properties["rlpluginCommit"]
def pluginJar = new File(System.properties["rlpluginOutputDirectory"], "plugin.jar");
manifest.hash = Files.asByteSource(pluginJar)
.hash(Hashing.sha256())
.toString()
manifest.size = pluginJar.length()
def props = new Properties()
new FileInputStream(file("runelite-plugin.properties")).withCloseable { is ->
props.load(is)
}
manifest.plugins = props["plugins"].split(/[,:;]/)*.trim()
manifest.displayName = props["displayName"]
if (!manifest.displayName) {
throw new RuntimeException("Plugin must have a display name")
}
manifest.author = props["author"]
if (!manifest.author) {
throw new RuntimeException("Plugin must have an author")
}
if (props["support"]) {
manifest.support = new URL(props["support"])
}
manifest.description = props["description"] ?: null
manifest.tags = props["tags"]?.split() ?: null
manifest.version = project.version
if (!(manifest.version ==~ /^[a-zA-Z0-9.-]+$/)) {
throw new RuntimeException("Plugin version \"${manifest.version}\" is invalid");
}
manifest.hasIcon = file("icon.png").exists();
new File(System.properties["rlpluginOutputDirectory"], "plugin.manifest")
.text = new Gson().toJson(manifest);
}
}
rlpluginEmitManifest.dependsOn rlpluginPackageJar
task configured {
def runeLiteDeps = [
"runelite-client",
"runelite-api",
"http-api",
]
def version = System.properties["rlpluginRuneLiteVersion"]
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "net.runelite" && details.requested.name in runeLiteDeps) {
details.useVersion version
}
}
}
}
}
class ExternalPluginManifest {
String internalName;
String commit;
String hash;
int size;
String[] plugins;
String displayName;
String version;
String author;
String description;
String[] tags;
URL support;
boolean hasIcon;
}

41
rebuild_all.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
# Copyright (c) 2019 Abex
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[[ "${TRAVIS_PULL_REQUEST:-false}" == "false" ]] || exit 0
SECONDS=0
for PLUGIN in plugins/* ; do
if [ $SECONDS -gt 60 ]; then
./build_manifest.sh
SECONDS=0
fi
PLUGIN_ID=$(basename "$PLUGINFILE")
echo "travis_fold:start:$PLUGIN_ID]"
./build_plugin.sh "$PLUGIN"
echo "travis_font:end:[$PLUGIN_ID]"
done
./build_manifest.sh

9
repo_config.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
# export REPO_CREDS="user:password"
# export REPO_ROOT="https://your/webdav/server"
# export SIGNING_KEY="
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# "

1
runelite.version Normal file
View File

@@ -0,0 +1 @@
1.5.43-SNAPSHOT

9
templateplugin/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.gradle
build
.idea/
.project
.settings/
.classpath
nbactions.xml
nb-configuration.xml
nbproject/

View File

@@ -0,0 +1,31 @@
plugins {
id 'java'
}
repositories {
mavenLocal()
maven {
url = 'http://repo.runelite.net'
}
mavenCentral()
}
dependencies {
compileOnly 'net.runelite:client:${runelite_version}'
compileOnly 'org.slf4j:slf4j-api:1.7.25'
compileOnly 'org.projectlombok:lombok:1.18.4'
annotationProcessor 'org.projectlombok:lombok:1.18.4'
testImplementation 'junit:junit:4.12'
testImplementation 'org.slf4j:slf4j-simple:1.7.12'
testImplementation 'net.runelite:client:${runelite_version}'
}
group = '${group_id}'
version = '${version}'
sourceCompatibility = '1.8'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

View File

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Thu Dec 12 13:37:44 MST 2019
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

188
templateplugin/gradlew vendored Executable file
View File

@@ -0,0 +1,188 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="/usr/lib/jvm/java-11-openjdk/bin/java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

100
templateplugin/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,6 @@
displayName=${name}
author=${author}
support=
description=${description}
tags=
plugins=${package}.${plugin_prefix}Plugin

View File

@@ -0,0 +1 @@
rootProject.name = '${artifact_id}'

View File

@@ -0,0 +1,20 @@
package ${package};
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("${plugin_config_group}")
public interface ${plugin_prefix}Config extends Config
{
@ConfigItem(
keyName = "greeting",
name = "Welcome Greeting",
description = "The message to show to the user when they login"
)
default String greeting()
{
return "Hello";
}
}

View File

@@ -0,0 +1,53 @@
package ${package};
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@PluginDescriptor(
name = "${name}"
)
public class ${plugin_prefix}Plugin extends Plugin
{
@Inject
private Client client;
@Inject
private ${plugin_prefix}Config config;
@Override
protected void startUp() throws Exception
{
log.info("${name} started!");
}
@Override
protected void shutDown() throws Exception
{
log.info("${name} stopped!");
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
if (gameStateChanged.getGameState() == GameState.LOGGED_IN)
{
client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "${name} says " + config.greeting(), null);
}
}
@Provides
${plugin_prefix}Config provideConfig(ConfigManager configManager)
{
return configManager.getConfig(${plugin_prefix}Config.class);
}
}

View File

@@ -0,0 +1,13 @@
package ${package};
import net.runelite.client.RuneLite;
import net.runelite.client.externalplugins.ExternalPluginManager;
public class ${plugin_prefix}PluginTest
{
public static void main(String[] args) throws Exception
{
ExternalPluginManager.loadBuiltin(${plugin_prefix}Plugin.class);
RuneLite.main(args);
}
}

55
travis.sh Executable file
View File

@@ -0,0 +1,55 @@
#!/bin/bash
# Copyright (c) 2019 Abex
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e -x
: '
env:
-FORCE_BUILD: example-external-plugin
'
if [[ "$FORCE_BUILD" == "ALL" ]]; then
./rebuild_all
exit
elif [[ -n "${FORCE_BUILD+x}" ]]; then
for FI in "${FORCE_BUILD[@]}"; do
./build_plugin.sh "plugins/$FORCE_BUILD"
done
exit
fi
PLUGIN_CHANGE=
while read -r FI ; do
if [[ $FI =~ ^plugins/.*$ ]]; then
./build_plugin.sh "$FI"
PLUGIN_CHANGE=true
elif [[ "$FI" == "runelite.version" ]]; then
./rebuild_all.sh
fi
done < <(git diff --name-only "$TRAVIS_COMMIT_RANGE")
if [[ "$PLUGIN_CHANGE" == true ]]; then
./build_manifest.sh
fi