Merge branch 'master' of https://github.com/open-osrs/runelite into spawn

# Conflicts:
#	runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java
#	runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java
This commit is contained in:
f0rmatme
2019-11-14 16:20:49 -08:00
908 changed files with 54678 additions and 53781 deletions

View File

@@ -54,7 +54,7 @@ Before you submit your pull request consider the following guidelines:
* After cloning, set a new remote [upstream](https://help.github.com/articles/configuring-a-remote-for-a-fork/) (this helps to keep your fork up to date)
```shell
git remote add upstream https://github.com/runelite-extended/runelite.git
git remote add upstream https://github.com/open-osrs/runelite.git
```
* Make your changes in a new git branch:

View File

@@ -4,7 +4,7 @@ about: Create a report to help us improve
---
Please check if your issue is not a duplicate by [searching existing issues](https://github.com/runelite/runelite/search?type=Issues)
Please check if your issue is not a duplicate by [searching existing issues](https://github.com/open-osrs/runelite/search?type=Issues)
**Describe the bug**
A clear and concise description of what the bug is.

25
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
version-template: '$MAJOR.$MINOR.$PATCH.0'
name-template: 'v$NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
exclude-labels:
- 'skip-changelog'
- 'automated-pull-request'
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
label: 'chore'
change-template: '* $TITLE (#$NUMBER) @$AUTHOR'
template: |
Thanks to: $CONTRIBUTORS
## Changes
$CHANGES

View File

@@ -1,72 +0,0 @@
name: OpenOSRS - CI
on: [pull_request, push]
jobs:
pr-lint:
name: PR title
runs-on: ubuntu-latest
steps:
- name: PR title lint
if: github.event_name == 'pull_request'
uses: seferov/pr-lint-action@master
with:
title-regex: '^([\w-/]+): \w+'
build:
runs-on: windows-latest
name: Build
steps:
- uses: actions/checkout@master
- name: Set up JDK 11
uses: actions/setup-java@master
with:
java-version: 11
- name: Assembling
run: gradlew assemble --console=plain
- name: Building
run: gradlew build --stacktrace -x test -x checkstyleMain --console=plain
test:
runs-on: windows-latest
name: Test
steps:
- uses: actions/checkout@master
- name: Set up JDK 11
uses: actions/setup-java@master
with:
java-version: 11
- name: Assembling
run: gradlew assemble --console=plain
- name: Testing
run: gradlew test --stacktrace --console=plain
checkstyle:
name: Checkstyle
runs-on: windows-latest
steps:
- uses: actions/checkout@master
- name: Set up JDK 11
uses: actions/setup-java@master
with:
java-version: 11
- name: Assembling
run: gradlew assemble --console=plain
- name: Checking code conventions
run: gradlew checkstyleMain --console=plain
approve:
name: Approve
needs: [build, test, checkstyle]
runs-on: ubuntu-latest
steps:
- name: Approve pull request
if: github.event_name == 'pull_request' && github.actor == 'OpenOSRS'
uses: hmarr/auto-approve-action@master
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -9,7 +9,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Update Gradle Wrapper
@@ -22,23 +28,4 @@ jobs:
PULL_REQUEST_TITLE: 'project: Update gradle wrapper'
PULL_REQUEST_BODY: This is an auto-generated PR with an updated gradle version
COMMIT_MESSAGE: 'project: Update gradle wrapper'
PULL_REQUEST_LABELS: automated pull request, gradle
update-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Update Gradle dependencies
run: ./gradlew useLatestVersions --console=plain
- name: Create Gradle dependencies update Pull Request
uses: Owain94/create-pull-request@master
env:
GITHUB_TOKEN: ${{ secrets.OpenOSRS }}
PULL_REQUEST_BRANCH: GRADLE-DEPENDENCY-UPDATE
PULL_REQUEST_TITLE: 'project: Update gradle dependencies'
PULL_REQUEST_BODY: This is an auto-generated PR with an updated gradle dependencies versions
COMMIT_MESSAGE: 'project: Update gradle dependencies'
PULL_REQUEST_LABELS: automated pull request, gradle
PULL_REQUEST_LABELS: automated-pull-request, gradle

15
.github/workflows/greetings.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: OpenOSRS - First interaction
on:
issues:
types: [opened]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for opening your first issue! Please make sure to join our [Discord](https://discord.gg/openosrs).'

37
.github/workflows/merge.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: OpenOSRS - Auto merge
on:
pull_request_review:
types:
- submitted
jobs:
automerge:
name: Auto merge
runs-on: ubuntu-latest
steps:
- name: automerge
uses: pascalgn/automerge-action@f84dd310ea4a19890c70a4ff11ab282a872fb94b
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MERGE_FORKS: false
LABELS: automated-pull-request
AUTOMERGE: automated-pull-request
cleanup:
name: Cleanup
needs: automerge
runs-on: ubuntu-latest
steps:
- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo $(jq --raw-output .pull_request.head.ref "$GITHUB_EVENT_PATH"))"
id: extract_branch
- name: Delete PR head branch
uses: dawidd6/action-delete-branch@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ steps.extract_branch.outputs.branch }}
be_kind: true

119
.github/workflows/pr.yml vendored Normal file
View File

@@ -0,0 +1,119 @@
name: OpenOSRS - CI (PR)
on: pull_request
jobs:
pr-lint:
name: PR title
runs-on: ubuntu-latest
steps:
- name: PR title lint
if: github.event_name == 'pull_request'
uses: seferov/pr-lint-action@master
with:
title-regex: '^([\w-/]+): \w+'
build:
runs-on: ubuntu-latest
name: Build
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Building
run: ./gradlew build --stacktrace -x test -x checkstyleMain --console=plain
test:
runs-on: ubuntu-latest
name: Test
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Testing
run: ./gradlew test --stacktrace --console=plain
checkstyleMain:
name: Checkstyle main
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Checking code conventions
run: ./gradlew checkstyleMain --console=plain
checkstyleTest:
name: Checkstyle test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Checking code conventions
run: ./gradlew checkstyleTest --console=plain
approve:
name: Approve
needs: [build, test, checkstyleMain, checkstyleTest]
runs-on: ubuntu-latest
steps:
- name: Approve pull request
if: github.event_name == 'pull_request' && github.actor == 'OpenOSRS'
uses: hmarr/auto-approve-action@v2.0.0
with:
github-token: ${{ secrets.Owain }}

108
.github/workflows/push.yml vendored Normal file
View File

@@ -0,0 +1,108 @@
name: OpenOSRS - CI (push)
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
name: Build
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Building
run: ./gradlew build --stacktrace -x test -x checkstyleMain --console=plain
test:
runs-on: ubuntu-latest
name: Test
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Testing
run: ./gradlew test --stacktrace --console=plain
checkstyleMain:
name: Checkstyle main
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Checking code conventions
run: ./gradlew checkstyleMain --console=plain
checkstyleTest:
name: Checkstyle test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Assembling
run: ./gradlew assemble --console=plain
- name: Checking code conventions
run: ./gradlew checkstyleTest --console=plain
update_draft_release:
name: Draft release
runs-on: ubuntu-latest
steps:
- uses: toolmantim/release-drafter@v5.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,9 +9,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Set up JDK 11
uses: actions/setup-java@master
uses: actions/setup-java@v1
with:
java-version: 11
- name: Make gradlew executable
@@ -25,7 +31,7 @@ jobs:
- name: Building scraper
run: ./gradlew :wiki-scraper:build --console=plain
- name: Downloading jagex cache
run: ./gradlew :cache-client:update --console=plain
run: ./gradlew :cache-client:download --console=plain
- name: Scraping NPC stats
run: ./gradlew :wiki-scraper:npcStatsScrape --console=plain
- name: Create NPC stats Pull Request
@@ -36,4 +42,4 @@ jobs:
PULL_REQUEST_TITLE: 'Client: Update NPC stats'
PULL_REQUEST_BODY: This is an auto-generated PR with changes from the OSRS wiki
COMMIT_MESSAGE: 'Client: Update NPC stats'
PULL_REQUEST_LABELS: automated pull request, NPC stats
PULL_REQUEST_LABELS: automated-pull-request, NPC stats

View File

@@ -19,4 +19,4 @@ jobs:
exempt-issue-label: 'awaiting-approval'
exempt-pr-label: 'awaiting-approval'
days-before-stale: 60
days-before-close: 30
days-before-close: 30

View File

@@ -3,7 +3,7 @@
# OpenOSRS
[![Build Status](https://github.com/open-osrs/runelite/workflows/OpenOSRS%20-%20CI/badge.svg)](https://github.com/open-osrs/runelite/actions)
[![Build Status](https://github.com/open-osrs/runelite/workflows/OpenOSRS%20-%20CI%20(push)/badge.svg)](https://github.com/open-osrs/runelite/actions?query=workflow%3A%22OpenOSRS+-+CI+%28push%29%22)
[![HitCount](http://hits.dwyl.io/open-osrs/runelite.svg)](http://hits.dwyl.io/open-osrs/runelite)
[OpenOSRS](https://openosrs.com) is an extended version of [RuneLite](https://github.com/runelite/runelite) that provides more functionality and less restrictions while staying more open-source. We are not affiliated with RuneLite.
@@ -54,3 +54,7 @@ OpenOSRS is licensed under the BSD 2-clause license. See the license header in t
## Contribute and Develop
We've set up a separate document for our [contribution guidelines](https://github.com/open-osrs/runelite/blob/master/.github/CONTRIBUTING.md).
## Supported By
OpenOSRS uses profiling tools provided by [![YourKit](https://www.yourkit.com/images/yklogo.png)](https://www.yourkit.com/java/profiler/)

View File

@@ -1,207 +0,0 @@
import org.ajoberstar.grgit.Grgit
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "org.ajoberstar.grgit:grgit-gradle:3.1.1"
}
}
plugins {
id 'com.adarshr.test-logger' version '1.7.0' apply false
id "com.github.ben-manes.versions" version "0.22.0"
id "com.gradle.build-scan" version "2.4"
id 'se.patrikerdes.use-latest-versions' version '0.2.8'
}
apply plugin: 'application'
ext {
grgit = Grgit.open(dir: "${rootProject.projectDir}")
localGitCommit = grgit.head().id
localGitCommitShort = grgit.head().getAbbreviatedId(7)
localGitDirty = !grgit.status().clean
// sets the minimum launcher version that is output for the bootstrapper
launcherVersion = '2.0.3'
// Dependencies versions
annotations = '17.0.0'
antlr = '4.7.2'
apacheCommonsCompress = '1.19'
apacheCommonsCsv = '1.7'
apacheCommonsText = '1.8'
asm = '7.2'
commonsCli = '1.4'
discord = '1.1'
fernflower = '07082019'
findbugs = '3.0.2'
gson = '2.8.6'
guava = '28.1-jre'
guice = '4.2.2'
h2 = '1.4.200'
hamcrest = '2.2'
httpcore = '4.4.12'
httpmime = '4.5.10'
javassist = '3.26.0-GA'
javax = '1.3.2'
javaxInject = '1'
jbsdiff = '1.0'
jclCore = '2.8'
jedis = '3.1.0'
jfoenix = '9.0.9'
jna = '5.4.0'
jogamp = '2.3.2'
jopt = '5.0.4'
jooq = '3.12.1'
junit = '4.12'
jupiter = '5.5.2'
logback = '1.2.3'
lombok = '1.18.10'
mapstruct = '1.3.1.Final'
mariadbJdbc = '2.5.1'
mavenPluginAnnotations = '3.6.0'
mavenPluginApi = '3.6.2'
minio = '6.0.11'
mockito = '3.1.0'
mongodbDriverSync = '3.11.1'
mysqlConnectorJava = '8.0.18'
netty = '4.1.42.Final'
okhttp3 = '4.2.2'
orangeExtensions = '1.0'
petitparser = '2.2.0'
plexus = '3.3.0'
rxjava = '2.2.13'
rxrelay = '2.1.1'
scribejava = '6.9.0'
sisu = '0.3.3'
slf4j = '1.7.28'
springJdbc = '5.2.0.RELEASE'
springboot = '2.2.0.RELEASE'
sql2o = '1.6.0'
substance = '8.0.02'
trident = '1.5.00'
}
allprojects {
apply plugin: 'maven'
if (this.name != 'rs-client') apply plugin: 'checkstyle'
group = 'com.openosrs'
version = '1.5.37-SNAPSHOT'
ext {
rsversion = 184
cacheversion = 165
plusVersion = '2.1.8.0'
gitCommit = localGitCommit
gitCommitShort = localGitCommitShort
gitDirty = localGitDirty
rootPath = rootDir.toString().replace('\\', '/')
injectedClassesPath = rootPath + "/injector-plugin/out/injected-client/"
}
}
subprojects {
apply plugin: 'com.adarshr.test-logger'
apply plugin: 'java-library'
apply plugin: 'maven'
apply plugin: 'fernflower'
apply plugin: 'maven-publish'
sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
tasks.withType(GroovyCompile).configureEach {
options.incremental = true
}
publishing {
repositories {
maven {
name = "runelite"
url = uri("https://maven.pkg.github.com/open-osrs/runelite")
credentials {
username = System.getProperty("gpr_user")
password = System.getProperty("gpr_key")
}
}
}
publications {
gpr(MavenPublication) {
from(components.java)
}
}
}
repositories {
mavenLocal()
maven { url "http://repo1.maven.org/maven2" }
maven { url "http://repo.runelite.net" }
maven { url "http://repo.maven.apache.org/maven2" }
maven { url "https://raw.githubusercontent.com/open-osrs/hosting/master" }
if (System.getenv("NEXUS-URL") != null) {
maven { url System.getenv("NEXUS-URL") }
}
}
checkstyle {
toolVersion = '6.4.1'
sourceSets = [sourceSets.main]
configFile = file("${rootDir}/checkstyle/checkstyle.xml")
configProperties = [ "suppressionFile" : file("${rootDir}/checkstyle/suppressions.xml")]
showViolations = true
ignoreFailures = false
maxWarnings = 0
}
}
wrapper {
gradleVersion = '5.6.2'
doLast {
def optsEnvVar = "DEFAULT_JVM_OPTS"
scriptFile.write scriptFile.text.replace("$optsEnvVar='\"-Xmx64m\" \"-Xms64m\"'", "$optsEnvVar='\"-Xmx4g\" \"-Xms2g\" \"-Dfile.encoding=UTF-8\"'")
batchScript.write batchScript.text.replace("set $optsEnvVar=\"-Xmx64m\" \"-Xms64m\"", "set $optsEnvVar=\"-Xmx4g\" \"-Xms2g\" \"-Dfile.encoding=UTF-8\"")
}
}
run {
classpath = childProjects.client.sourceSets.main.runtimeClasspath
mainClassName = "net.runelite.client.RuneLite"
}
def isNonStable = { String version ->
def unstableKeyword = ['ALPHA', 'BETA', 'RC'].any { it -> version.toUpperCase().contains(it) }
return unstableKeyword
}
dependencyUpdates {
checkForGradleUpdate = false
resolutionStrategy {
componentSelection {
all {
if (isNonStable(candidate.version)) {
reject()
}
}
}
}
}

166
build.gradle.kts Normal file
View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.benmanes.gradle.versions.updates.DependencyUpdatesTask
import org.ajoberstar.grgit.Grgit
buildscript {
repositories {
gradlePluginPortal()
maven(url = "https://raw.githubusercontent.com/open-osrs/hosting/master")
}
dependencies {
classpath(Plugins.grgitPlugin)
classpath(Plugins.versionsPlugin)
classpath(Plugins.injectorPlugin)
}
}
plugins {
id(Plugins.testLogger.first) version Plugins.testLogger.second apply false
id(Plugins.versions.first) version Plugins.versions.second
id(Plugins.latestVersion.first) version Plugins.latestVersion.second
id(Plugins.grgit.first) version Plugins.grgit.second
checkstyle
application
}
val grgit = Grgit.open(mapOf("dir" to rootProject.projectDir.absolutePath))
val localGitCommit = grgit.head().id
val localGitCommitShort = grgit.head().getAbbreviatedId(7)
fun isNonStable(version: String): Boolean {
return listOf("ALPHA", "BETA", "RC").any {
version.toUpperCase().contains(it)
}
}
allprojects {
group = "com.openosrs"
version = ProjectVersions.rlVersion
}
subprojects {
repositories {
//mavenLocal()
jcenter()
maven(url = "https://mvnrepository.com/artifact")
maven(url = "https://repo.runelite.net")
maven(url = "https://raw.githubusercontent.com/open-osrs/hosting/master")
maven(url = "https://jitpack.io")
}
apply<JavaLibraryPlugin>()
apply<MavenPublishPlugin>()
apply(plugin = Plugins.testLogger.first)
project.extra["gitCommit"] = localGitCommit
project.extra["gitCommitShort"] = localGitCommitShort
project.extra["rootPath"] = rootDir.toString().replace("\\", "/")
if (this.name != "runescape-client") {
apply(plugin = "checkstyle")
checkstyle {
maxWarnings = 0
toolVersion = "8.25"
isShowViolations = true
isIgnoreFailures = false
}
}
configure<PublishingExtension> {
repositories {
maven {
name = "runelite"
url = uri("https://maven.pkg.github.com/open-osrs/runelite")
credentials {
username = System.getProperty("gpr_user")
password = System.getProperty("gpr_key")
}
}
}
publications {
register("gpr", MavenPublication::class) {
from(components["java"])
}
}
}
tasks {
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
withType<JavaCompile> {
options.encoding = "UTF-8"
}
withType<AbstractArchiveTask> {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
dirMode = 493
fileMode = 420
}
withType<Checkstyle> {
group = "verification"
exclude("**/ScriptVarType.java")
exclude("**/LayoutSolver.java")
exclude("**/RoomType.java")
}
}
}
application {
mainClassName = "net.runelite.client.RuneLite"
}
tasks {
named<JavaExec>("run") {
group = "openosrs"
classpath = project(":runelite-client").sourceSets.main.get().runtimeClasspath
}
named<DependencyUpdatesTask>("dependencyUpdates") {
checkForGradleUpdate = false
resolutionStrategy {
componentSelection {
all {
if (candidate.displayName.contains("fernflower") || isNonStable(candidate.version)) {
reject("Non stable")
}
}
}
}
}
}

View File

@@ -1,7 +0,0 @@
repositories {
maven { url "https://raw.githubusercontent.com/open-osrs/hosting/master" }
}
dependencies {
compile localGroovy()
implementation group: 'net.runelite', name: 'fernflower', version: '07082019'
}

43
buildSrc/build.gradle.kts Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
maven(url = "https://raw.githubusercontent.com/open-osrs/hosting/master")
}
dependencies {
implementation(gradleApi())
implementation(group = "net.runelite", name = "fernflower", version = "07082019")
implementation(group = "org.json", name = "json", version = "20190722")
}
kotlinDslPluginOptions {
experimentalWarning.set(false)
}

View File

@@ -1,16 +0,0 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.StopExecutionException
class FernflowerPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('decompile', type: FernflowerTask) {
it.dependsOn(project.tasks.jar)
it.doFirst {
if (!project.tasks.jar.didWork) {
throw new StopExecutionException()
}
}
}
}
}

View File

@@ -1,32 +0,0 @@
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler
class FernflowerTask extends DefaultTask {
List<String> extraArgs
String inputJar
String outputDir
@InputFile
File getInputJar() {
project.file(inputJar ?: project.buildDir.toString() + '/libs/' + project.getName() + '-' + project.version + '.jar')
}
@OutputDirectory
File getOutputDir() {
project.file(outputDir ?: project.buildDir.toString() + '/decompiled-sources')
}
@TaskAction
void decompile() {
getOutputDir().mkdirs()
def args = [getInputJar().toString(), getOutputDir().toString()]
if (extraArgs) {
args.addAll(extraArgs)
}
ConsoleDecompiler.main(args as String[])
}
}

View File

@@ -0,0 +1,87 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.register
import java.io.File
class BootstrapPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register<BootstrapTask>("bootstrapStaging") {
dependsOn("jar")
dependsOn("shadowJar")
type = "staging"
clientJar = project.tasks["jar"].outputs.files.singleFile
dependsOn(project.parent!!.project(":runelite-api").tasks["jar"])
dependsOn(project.parent!!.project(":runescape-api").tasks["jar"])
dependsOn(project.parent!!.project(":http-api").tasks["jar"])
dependsOn(project.parent!!.project(":injected-client").tasks["jar"])
doLast {
project.copy {
from(project.tasks["jar"])
from(project.parent!!.project(":runelite-api").tasks["jar"])
from(project.parent!!.project(":runescape-api").tasks["jar"])
from(project.parent!!.project(":http-api").tasks["jar"])
from(project.parent!!.project(":injected-client").tasks["jar"])
into("${project.buildDir}/bootstrap/${type}/")
}
}
}
project.tasks.register<BootstrapTask>("bootstrapStable") {
dependsOn("jar")
dependsOn("shadowJar")
type = "stable"
clientJar = project.tasks["jar"].outputs.files.singleFile
dependsOn(project.parent!!.project(":runelite-api").tasks["jar"])
dependsOn(project.parent!!.project(":runescape-api").tasks["jar"])
dependsOn(project.parent!!.project(":http-api").tasks["jar"])
dependsOn(project.parent!!.project(":injected-client").tasks["jar"])
doLast {
project.copy {
from(project.tasks["jar"])
from(project.parent!!.project(":runelite-api").tasks["jar"])
from(project.parent!!.project(":runescape-api").tasks["jar"])
from(project.parent!!.project(":http-api").tasks["jar"])
from(project.parent!!.project(":injected-client").tasks["jar"])
into("${project.buildDir}/bootstrap/${type}/")
}
}
}
project.tasks.register<BootstrapTask>("bootstrapNightly") {
dependsOn("jar")
dependsOn("shadowJar")
type = "nightly"
clientJar = project.tasks["jar"].outputs.files.singleFile
dependsOn(project.parent!!.project(":runelite-api").tasks["jar"])
dependsOn(project.parent!!.project(":runescape-api").tasks["jar"])
dependsOn(project.parent!!.project(":http-api").tasks["jar"])
dependsOn(project.parent!!.project(":injected-client").tasks["jar"])
doLast {
project.copy {
from(project.tasks["jar"])
from(project.parent!!.project(":runelite-api").tasks["jar"])
from(project.parent!!.project(":runescape-api").tasks["jar"])
from(project.parent!!.project(":http-api").tasks["jar"])
from(project.parent!!.project(":injected-client").tasks["jar"])
into("${project.buildDir}/bootstrap/${type}/")
}
}
}
}
}

View File

@@ -0,0 +1,106 @@
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.get
import java.io.File
import java.security.MessageDigest
open class BootstrapTask : DefaultTask() {
@Input
@Optional
var type: String? = "stable"
@InputFile
@PathSensitive(PathSensitivity.ABSOLUTE)
var clientJar: File? = null
@Input
val launcherJvm11Arguments = arrayOf("-XX:+DisableAttachMechanism", "-Drunelite.launcher.nojvm=true", "-Xmx512m", "-Xss2m", "-XX:CompileThreshold=1500", "-Djna.nosys=true")
@Input
val launcherArguments = arrayOf("-XX:+DisableAttachMechanism", "-Drunelite.launcher.nojvm=true", "-Xmx512m", "-Xss2m", "-XX:CompileThreshold=1500", "-Xincgc", "-XX:+UseConcMarkSweepGC", "-XX:+UseParNewGC", "-Djna.nosys=true")
@Input
val clientJvmArguments = arrayOf("-XX:+DisableAttachMechanism", "-Xmx512m", "-Xss2m", "-XX:CompileThreshold=1500", "-Xincgc", "-XX:+UseConcMarkSweepGC", "-XX:+UseParNewGC", "-Djna.nosys=true")
@Input
val clientJvm9Arguments = arrayOf("-XX:+DisableAttachMechanism", "-Xmx512m", "-Xss2m", "-XX:CompileThreshold=1500", "-Djna.nosys=true")
private fun hash(file: ByteArray): String {
return MessageDigest.getInstance("SHA-256").digest(file).fold("", { str, it -> str + "%02x".format(it) })
}
private fun getArtifacts(): Array<JsonBuilder> {
val artifacts = ArrayList<JsonBuilder>()
project.configurations["runtimeClasspath"].resolvedConfiguration.resolvedArtifacts.forEach {
val module = it.moduleVersion.id.toString()
val name = module.split(":")[1]
val group = module.split(":")[0]
val version = module.split(":")[2]
var path = ""
if (it.file.name.contains(ProjectVersions.rlVersion)) {
path = "https://github.com/open-osrs/hosting/raw/master/${type}/${it.file.name}"
} else if (!group.contains("runelite")) {
path = "https://repo.maven.apache.org/maven2/" + group.replace(".", "/") + "/${name}/$version/${name}-$version"
if (it.classifier != null && it.classifier != "no_aop") {
path += "-${it.classifier}"
}
path += ".jar"
} else if (it.file.name.contains("trident") || it.file.name.contains("discord") || it.file.name.contains("substance")) {
path = "https://repo.runelite.net/net/runelite/"
if (!it.file.name.contains("discord")) {
path += "pushingpixels/"
}
path += "${name}/$version/${name}-$version.jar"
}
val artifactFile = File(it.file.absolutePath)
artifacts.add(JsonBuilder(
"name" to it.file.name,
"path" to path,
"size" to artifactFile.length(),
"hash" to hash(artifactFile.readBytes())
))
}
artifacts.add(JsonBuilder(
"name" to clientJar!!.name,
"path" to "https://github.com/open-osrs/hosting/raw/master/${type}/${clientJar!!.name}",
"size" to clientJar!!.length(),
"hash" to hash(clientJar!!.readBytes())
))
return artifacts.toTypedArray()
}
@TaskAction
fun boostrap() {
val json = JsonBuilder(
"projectVersion" to ProjectVersions.openosrsVersion,
"minimumLauncherVersion" to ProjectVersions.launcherVersion,
"launcherJvm11Arguments" to launcherJvm11Arguments,
"launcherArguments" to launcherArguments,
"clientJvmArguments" to clientJvmArguments,
"clientJvm9Arguments" to clientJvm9Arguments,
"buildCommit" to project.extra["gitCommit"],
"artifacts" to getArtifacts()
).toString()
val bootstrapDir = File("${project.buildDir}/bootstrap")
bootstrapDir.mkdirs()
File(bootstrapDir, "bootstrap-${type}.json").printWriter().use { out ->
out.println(json)
}
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
const val kotlinVersion = "1.3.50"
object ProjectVersions {
const val launcherVersion = "2.0.4"
const val rlVersion = "1.5.41-SNAPSHOT"
const val openosrsVersion = "2.1.13.0-SNAPSHOT"
const val rsversion = 185
const val cacheversion = 165
}
object Plugins {
val grgitPlugin = "org.ajoberstar:grgit:2.3.0"
val versionsPlugin = "com.github.ben-manes:gradle-versions-plugin:0.27.0"
val injectorPlugin = "com.openosrs:injector-plugin:1.0.2"
val testLogger = Pair("com.adarshr.test-logger", "2.0.0")
val versions = Pair("com.github.ben-manes.versions", "0.27.0")
val latestVersion = Pair("se.patrikerdes.use-latest-versions", "0.2.13")
val grgit = Pair("org.ajoberstar.grgit", "4.0.0-rc.1")
val jarTest = Pair("com.github.hauner.jarTest", "1.0.1")
val shadow = Pair("com.github.johnrengelman.shadow", "5.2.0")
}
object Libraries {
private object Versions {
const val annotations = "18.0.0"
const val antlr = "4.7.2"
const val apacheCommonsCompress = "1.19"
const val apacheCommonsCsv = "1.7"
const val apacheCommonsText = "1.8"
const val asm = "7.2"
const val commonsCli = "1.4"
const val discord = "1.1"
const val fernflower = "07082019"
const val findbugs = "3.0.2"
const val gson = "2.8.6"
const val guava = "28.1-jre"
const val guice = "4.2.2"
const val h2 = "1.4.200"
const val hamcrest = "2.2"
const val httpcore = "4.4.12"
const val httpmime = "4.5.10"
const val javassist = "3.26.0-GA"
const val javax = "1.3.2"
const val javaxInject = "1"
const val jbsdiff = "1.0"
const val jclCore = "2.8"
const val jedis = "3.1.0"
const val jna = "5.5.0"
const val jogamp = "2.3.2"
const val jopt = "5.0.4"
const val jooq = "3.12.3"
const val junit = "4.12"
const val jupiter = "5.6.0-M1"
const val logback = "1.2.3"
const val lombok = "1.18.10"
const val mapstruct = "1.3.1.Final"
const val mariadbJdbc = "2.5.1"
const val mavenPluginAnnotations = "3.6.0"
const val mavenPluginApi = "3.6.2"
const val minio = "6.0.11"
const val mockito = "3.1.0"
const val mongodbDriverSync = "3.11.2"
const val mysqlConnectorJava = "8.0.18"
const val naturalMouse = "2.0.2"
const val netty = "4.1.43.Final"
const val okhttp3 = "4.2.2"
const val orangeExtensions = "1.0"
const val petitparser = "2.2.0"
const val plexus = "3.3.0"
const val rxjava = "2.2.14"
const val rxrelay = "2.1.1"
const val scribejava = "6.9.0"
const val sisu = "0.3.4"
const val sentry = "1.7.28"
const val slf4j = "1.7.29"
const val springJdbc = "5.2.1.RELEASE"
const val springboot = "2.2.1.RELEASE"
const val sql2o = "1.6.0"
const val substance = "8.0.02"
const val trident = "1.5.00"
}
const val annotations = "org.jetbrains:annotations:${Versions.annotations}"
const val antlr = "org.antlr:antlr4-runtime:${Versions.antlr}"
const val apacheCommonsCompress = "org.apache.commons:commons-compress:${Versions.apacheCommonsCompress}"
const val apacheCommonsCsv = "org.apache.commons:commons-csv:${Versions.apacheCommonsCsv}"
const val apacheCommonsText = "org.apache.commons:commons-text:${Versions.apacheCommonsText}"
const val asmAll = "org.ow2.asm:asm:${Versions.asm}"
const val asmUtil = "org.ow2.asm:asm-util:${Versions.asm}"
const val asmTree = "org.ow2.asm:asm-tree:${Versions.asm}"
const val commonsCli = "commons-cli:commons-cli:${Versions.commonsCli}"
const val discord = "net.runelite:discord:${Versions.discord}"
const val fernflower = "net.runelite:fernflower:${Versions.fernflower}"
const val findbugs = "com.google.code.findbugs:jsr305:${Versions.findbugs}"
const val gson = "com.google.code.gson:gson:${Versions.gson}"
const val guava = "com.google.guava:guava:${Versions.guava}"
const val guice = "com.google.inject:guice:${Versions.guice}:no_aop"
const val guiceGrapher = "com.google.inject.extensions:guice-grapher:${Versions.guice}"
const val guiceTestlib = "com.google.inject.extensions:guice-testlib:${Versions.guice}"
const val h2 = "com.h2database:h2:${Versions.h2}"
const val hamcrest = "org.hamcrest:hamcrest-library:${Versions.hamcrest}"
const val httpcore = "org.apache.httpcomponents:httpcore:${Versions.httpcore}"
const val httpmime = "org.apache.httpcomponents:httpmime:${Versions.httpmime}"
const val javassist = "org.javassist:javassist:${Versions.javassist}"
const val javax = "javax.annotation:javax.annotation-api:${Versions.javax}"
const val javaxInject = "javax.inject:javax.inject:${Versions.javaxInject}"
const val jbsdiff = "io.sigpipe:jbsdiff:${Versions.jbsdiff}"
const val jclCore = "org.xeustechnologies:jcl-core:${Versions.jclCore}"
const val jedis = "redis.clients:jedis:${Versions.jedis}"
const val jna = "net.java.dev.jna:jna:${Versions.jna}"
const val jnaPlatform = "net.java.dev.jna:jna-platform:${Versions.jna}"
const val jogampJogl = "org.jogamp.jogl:jogl-all:${Versions.jogamp}"
const val jogampGluegen = "org.jogamp.gluegen:gluegen-rt:${Versions.jogamp}"
const val jogampGluegenLinuxAmd64 = "org.jogamp.gluegen:gluegen-rt:${Versions.jogamp}:natives-linux-amd64"
const val jogampGluegenLinuxI586 = "org.jogamp.gluegen:gluegen-rt:${Versions.jogamp}:natives-linux-i586"
const val jogampGluegenWindowsAmd64 = "org.jogamp.gluegen:gluegen-rt:${Versions.jogamp}:natives-windows-amd64"
const val jogampGluegenWindowsI586 = "org.jogamp.gluegen:gluegen-rt:${Versions.jogamp}:natives-windows-i586"
const val jogampJoglLinuxAmd64 = "org.jogamp.jogl:jogl-all:${Versions.jogamp}:natives-linux-amd64"
const val jogampJoglLinuxI586 = "org.jogamp.jogl:jogl-all:${Versions.jogamp}:natives-linux-i586"
const val jogampJoglWindowsAmd64 = "org.jogamp.jogl:jogl-all:${Versions.jogamp}:natives-windows-amd64"
const val jogampJoglWindowsI586 = "org.jogamp.jogl:jogl-all:${Versions.jogamp}:natives-windows-i586"
const val jopt = "net.sf.jopt-simple:jopt-simple:${Versions.jopt}"
const val jooq = "org.jooq:jooq:${Versions.jooq}"
const val jooqCodegen = "org.jooq:jooq-codegen:${Versions.jooq}"
const val jooqMeta = "org.jooq:jooq-meta:${Versions.jooq}"
const val junit = "junit:junit:${Versions.junit}"
const val jupiter = "org.junit.jupiter:junit-jupiter-api:${Versions.jupiter}"
const val logback = "ch.qos.logback:logback-classic:${Versions.logback}"
const val lombok = "org.projectlombok:lombok:${Versions.lombok}"
const val mapstruct = "org.mapstruct:mapstruct-jdk8:${Versions.mapstruct}"
const val mapstructProcessor = "org.mapstruct:mapstruct-processor:${Versions.mapstruct}"
const val mariadbJdbc = "org.mariadb.jdbc:mariadb-java-client:${Versions.mariadbJdbc}"
const val mavenPluginAnnotations = "org.apache.maven.plugin-tools:maven-plugin-annotations:${Versions.mavenPluginAnnotations}"
const val mavenPluginApi = "org.apache.maven:maven-plugin-api:${Versions.mavenPluginApi}"
const val minio = "io.minio:minio:${Versions.minio}"
const val mockitoCore = "org.mockito:mockito-core:${Versions.mockito}"
const val mockitoInline = "org.mockito:mockito-inline:${Versions.mockito}"
const val mongodbDriverSync = "org.mongodb:mongodb-driver-sync:${Versions.mongodbDriverSync}"
const val mysqlConnectorJava = "mysql:mysql-connector-java:${Versions.mysqlConnectorJava}"
const val naturalMouse = "com.github.joonasvali.naturalmouse:naturalmouse:${Versions.naturalMouse}"
const val nettyAll = "io.netty:netty-all:${Versions.netty}"
const val nettyBuffer = "io.netty:netty-buffer:${Versions.netty}"
const val okhttp3 = "com.squareup.okhttp3:okhttp:${Versions.okhttp3}"
const val okhttp3Webserver = "com.squareup.okhttp3:mockwebserver:${Versions.okhttp3}"
const val orangeExtensions = "net.runelite:orange-extensions:${Versions.orangeExtensions}"
const val petitparser = "com.github.petitparser:java-petitparser:${Versions.petitparser}"
const val plexus = "org.codehaus.plexus:plexus-utils:${Versions.plexus}"
const val rxjava = "io.reactivex.rxjava2:rxjava:${Versions.rxjava}"
const val rxrelay = "com.jakewharton.rxrelay2:rxrelay:${Versions.rxrelay}"
const val scribejava = "com.github.scribejava:scribejava-apis:${Versions.scribejava}"
const val sisu = "org.eclipse.sisu:org.eclipse.sisu.inject:${Versions.sisu}"
const val slf4jApi = "org.slf4j:slf4j-api:${Versions.slf4j}"
const val slf4jNop = "org.slf4j:slf4j-nop:${Versions.slf4j}"
const val slf4jSimple = "org.slf4j:slf4j-simple:${Versions.slf4j}"
const val sentry = "io.sentry:sentry:${Versions.sentry}"
const val springbootDevtools = "org.springframework.boot:spring-boot-devtools:${Versions.springboot}"
const val springbootStarter = "org.springframework.boot:spring-boot-starter:${Versions.springboot}"
const val springbootStarterWeb = "org.springframework.boot:spring-boot-starter-web:${Versions.springboot}"
const val springbootStarterJdbc = "org.springframework.boot:spring-boot-starter-jdbc:${Versions.springboot}"
const val springbootStarterTest = "org.springframework.boot:spring-boot-starter-test:${Versions.springboot}"
const val springbootStarterTomcat = "org.springframework.boot:spring-boot-starter-tomcat:${Versions.springboot}"
const val springbootJdbc = "org.springframework:spring-jdbc:${Versions.springJdbc}"
const val sql2o = "org.sql2o:sql2o:${Versions.sql2o}"
const val substance = "net.runelite.pushingpixels:substance:${Versions.substance}"
const val trident = "net.runelite.pushingpixels:trident:${Versions.trident}"
const val vanilla = "net.runelite.rs:vanilla:${ProjectVersions.rsversion}"
}

View File

@@ -0,0 +1,19 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.StopExecutionException
import org.gradle.api.tasks.diagnostics.DependencyReportTask
import org.gradle.kotlin.dsl.register
class FernflowerPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register<FernflowerTask>("decompile") {
dependsOn(project.tasks.getByName("jar"))
doFirst {
if (!project.tasks.getByName("jar").didWork) {
throw StopExecutionException()
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler
@CacheableTask
open class FernflowerTask: DefaultTask() {
@Input
@Optional
var extraArgs: List<String>? = null
@Input
@Optional
var inputJar: String? = null
@Input
@Optional
var outputDir: String? = null
@InputFile
@PathSensitive(PathSensitivity.ABSOLUTE)
var getInputJar = project.file(inputJar ?: "${project.buildDir}/libs/${project.name}-${project.version}.jar")
@OutputDirectory
var getOutputDir = project.file(outputDir ?: "${project.buildDir}/decompiled-sources")
@TaskAction
fun decompile() {
getOutputDir.mkdirs()
val args = mutableListOf(getInputJar.toString(), getOutputDir.toString())
if (extraArgs != null) {
args.addAll(extraArgs!!)
}
ConsoleDecompiler.main(args.toTypedArray())
}
}

View File

@@ -0,0 +1,55 @@
import org.json.JSONArray
import org.json.JSONObject
class JsonBuilder() {
private var json = JSONObject()
constructor(vararg pairs: Pair<String, *>) : this() {
add(*pairs)
}
fun add(vararg pairs: Pair<String, *>) {
for ((key, value) in pairs) {
when (value) {
is Boolean -> json.put(key, value)
is Number -> add(key, value)
is String -> json.put(key, value)
is JsonBuilder -> json.put(key, value.json)
is Array<*> -> add(key, value)
is JSONObject -> json.put(key, value)
is JSONArray -> json.put(key, value)
}
}
}
fun add(key: String, value: Number): JsonBuilder {
when (value) {
is Int -> json.put(key, value)
is Long -> json.put(key, value)
is Float -> json.put(key, value)
is Double -> json.put(key, value)
else -> {}
}
return this
}
fun <T> add(key: String, items: Array<T>): JsonBuilder {
val jsonArray = JSONArray()
items.forEach {
when (it) {
is String,is Long,is Int, is Boolean -> jsonArray.put(it)
is JsonBuilder -> jsonArray.put(it.json)
else -> try {jsonArray.put(it)} catch (ignored:Exception) {
}
}
}
json.put(key, jsonArray)
return this
}
override fun toString() = json.toString()
}

View File

@@ -1 +0,0 @@
implementation-class=FernflowerPlugin

View File

@@ -1,28 +0,0 @@
description = 'Cache Client'
dependencies {
api project(':cache')
api project(':protocol')
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'io.netty', name: 'netty-all', version: netty
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4j
testImplementation group: 'junit', name: 'junit', version: junit
testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4j
testImplementation project(path: ':cache', configuration: 'testArchives')
}
task update {
dependsOn ":cache-client:build"
doLast {
def path = sourceSets.main.runtimeClasspath
def loader = new URLClassLoader(path.collect { f -> f.toURI().toURL() } as URL[])
def cacheClient = loader.loadClass('net.runelite.cache.client.CacheClient')
cacheClient.getCache(rsversion);
loader.close()
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 ThatGamerBlue
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,28 +22,28 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
description = 'Injected Client'
compileJava {
dependsOn ':injector-plugin:assemble'
description = "Cache Client"
dependencies {
api(project(":cache"))
api(project(":protocol"))
implementation(Libraries.guava)
implementation(Libraries.nettyAll)
implementation(Libraries.slf4jApi)
testImplementation(Libraries.junit)
testImplementation(Libraries.slf4jSimple)
testImplementation(project(path = ":cache", configuration = "testArchives"))
}
compileJava.outputs.upToDateWhen { false }
tasks {
register<JavaExec>("download") {
dependsOn(":cache-client:build")
compileJava.doLast() {
copy {
File f = file("build/classes/java/main")
f.deleteDir()
f.mkdirs()
from ("${injectedClassesPath}")
into ("build/classes/java/main")
classpath = project.sourceSets.main.get().runtimeClasspath
main = "net.runelite.cache.client.CacheClient"
args(listOf(ProjectVersions.rsversion))
}
}
classes.doLast() {
File f = file("build/classes/java/main/Placeholder.class")
f.delete()
}
// tasks.build.dependsOn(tasks.decompile)
// this is just here to show how this could be used

View File

@@ -85,7 +85,7 @@ public class CacheClient implements AutoCloseable
private CompletableFuture<HandshakeResponseType> handshakeFuture;
private final Queue<PendingFileRequest> requests = new ArrayDeque<>();
public static void getCache(int clientRevision)
public static void main(String[] args)
{
Path path = Paths.get(System.getProperty("user.home"), "jagexcache" + File.separator + "oldschool" + File.separator + "LIVE");
final File jagexcache = new File(String.valueOf(path));
@@ -95,7 +95,7 @@ public class CacheClient implements AutoCloseable
try (Store store = new Store(jagexcache))
{
store.load();
CacheClient c = new CacheClient(store, clientRevision);
CacheClient c = new CacheClient(store, Integer.parseInt(args[0]));
c.connect();
CompletableFuture<HandshakeResponseType> handshake = c.handshake();
handshake.get();

View File

@@ -1,15 +0,0 @@
description = 'Cache Updater'
dependencies {
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok
compileOnly group: 'org.projectlombok', name: 'lombok', version: lombok
implementation group: 'io.minio', name: 'minio', version: minio
implementation group: 'mysql', name: 'mysql-connector-java', version: mysqlConnectorJava
implementation group: 'org.springframework.boot', name: 'spring-boot-devtools', version: springboot
implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: springboot
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc', version: springboot
implementation group: 'org.sql2o', name: 'sql2o', version: sql2o
implementation project(':cache-client')
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
description = "Cache Updater"
dependencies {
annotationProcessor(Libraries.lombok)
compileOnly(Libraries.lombok)
implementation(Libraries.minio)
implementation(Libraries.mysqlConnectorJava)
implementation(Libraries.springbootDevtools)
implementation(Libraries.springbootStarter)
implementation(Libraries.springbootStarterJdbc)
implementation(Libraries.sql2o)
implementation(project(":cache-client"))
}

36
cache/build.gradle vendored
View File

@@ -1,36 +0,0 @@
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id "com.github.hauner.jarTest" version "1.0.1"
}
description = 'Cache'
dependencies {
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok
api project(':http-api')
compileOnly group: 'org.projectlombok', name: 'lombok', version: lombok
implementation group: 'com.google.code.gson', name: 'gson', version: gson
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'commons-cli', name: 'commons-cli', version: commonsCli
implementation group: 'io.netty', name: 'netty-buffer', version: netty
implementation group: 'org.antlr', name: 'antlr4-runtime', version: antlr
implementation group: 'org.apache.commons', name: 'commons-compress', version: apacheCommonsCompress
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4j
testImplementation group: 'junit', name: 'junit', version: junit
testImplementation group: 'net.runelite.rs', name: 'cache', version: cacheversion
testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4j
}
processTestResources {
from file("src/test/resources/cache.properties"), {
filter(ReplaceTokens, tokens: [
"rs.version": rsversion.toString(),
"cache.version": cacheversion.toString()
])
}
}

75
cache/cache.gradle.kts vendored Normal file
View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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 org.apache.tools.ant.filters.ReplaceTokens
plugins {
id(Plugins.jarTest.first) version Plugins.jarTest.second
}
description = "Cache"
dependencies {
annotationProcessor(Libraries.lombok)
api(project(":http-api"))
compileOnly(Libraries.lombok)
implementation(Libraries.gson)
implementation(Libraries.guava)
implementation(Libraries.commonsCli)
implementation(Libraries.nettyBuffer)
implementation(Libraries.antlr)
implementation(Libraries.apacheCommonsCompress)
implementation(Libraries.slf4jApi)
testImplementation(Libraries.junit)
testImplementation(group = "net.runelite.rs", name = "cache", version = "${ProjectVersions.cacheversion}")
testImplementation(Libraries.slf4jSimple)
}
tasks {
processTestResources {
finalizedBy("filterTestResources")
}
register<Copy>("filterTestResources") {
val tokens = mapOf(
"rs.version" to ProjectVersions.rsversion.toString(),
"cache.version" to ProjectVersions.cacheversion.toString()
)
inputs.properties(tokens)
from("src/test/resources") {
include("cache.properties")
}
into("${buildDir}/resources/test")
filter(ReplaceTokens::class, "tokens" to tokens)
filteringCharset = "UTF-8"
}
}

View File

@@ -31,38 +31,37 @@ import lombok.Data;
@Data
public class NpcDefinition
{
public final int id;
public short[] recolorToFind;
public int rotation = 32;
public String name = "null";
public short[] recolorToReplace;
public int size = 1;
public int[] models;
public int[] models_2;
public int stanceAnimation = -1;
public int anInt2165 = -1;
public int tileSpacesOccupied = 1;
public int walkAnimation = -1;
public short[] retextureToReplace;
public int rotate90RightAnimation = -1;
public boolean aBool2170 = true;
public int resizeX = 128;
public int contrast = 0;
public int[] chatheadModels;
public int standingAnimation = -1;
public int rotateLeftAnimation = -1;
public int rotateRightAnimation = -1;
public int walkingAnimation = -1;
public int rotate180Animation = -1;
public int varbitIndex = -1;
public String[] options = new String[5];
public boolean renderOnMinimap = true;
public int combatLevel = -1;
public int rotate90RightAnimation = -1;
public int rotate90LeftAnimation = -1;
public int resizeY = 128;
public boolean hasRenderPriority = false;
public int ambient = 0;
public int headIcon = -1;
public int[] configs;
public short[] recolorToFind;
public short[] recolorToReplace;
public short[] retextureToFind;
public short[] retextureToReplace;
public String[] actions = new String[5];
public boolean isMinimapVisible = true;
public int combatLevel = -1;
public int widthScale = 128;
public int heightScale = 128;
public boolean hasRenderPriority;
public int ambient;
public int contrast;
public int headIcon = -1;
public int rotationSpeed = 32;
public int[] configs;
public int varbitId = -1;
public int varpIndex = -1;
public boolean isClickable = true;
public int anInt2189 = -1;
public boolean aBool2190 = false;
public Map<Integer, Object> params = null;
public boolean isInteractable = true;
public boolean rotationFlag = true;
public boolean isPet;
public Map<Integer, Object> params;
}

View File

@@ -24,13 +24,12 @@
*/
package net.runelite.cache.definitions.loaders;
import java.util.HashMap;
import net.runelite.cache.definitions.NpcDefinition;
import net.runelite.cache.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
public class NpcLoader
{
private static final Logger logger = LoggerFactory.getLogger(NpcLoader.class);
@@ -67,7 +66,6 @@ public class NpcLoader
{
def.models[index] = stream.readUnsignedShort();
}
}
else if (opcode == 2)
{
@@ -75,37 +73,37 @@ public class NpcLoader
}
else if (opcode == 12)
{
def.tileSpacesOccupied = stream.readUnsignedByte();
def.size = stream.readUnsignedByte();
}
else if (opcode == 13)
{
def.stanceAnimation = stream.readUnsignedShort();
def.standingAnimation = stream.readUnsignedShort();
}
else if (opcode == 14)
{
def.walkAnimation = stream.readUnsignedShort();
def.walkingAnimation = stream.readUnsignedShort();
}
else if (opcode == 15)
{
def.anInt2165 = stream.readUnsignedShort();
def.rotateLeftAnimation = stream.readUnsignedShort();
}
else if (opcode == 16)
{
def.anInt2189 = stream.readUnsignedShort();
def.rotateRightAnimation = stream.readUnsignedShort();
}
else if (opcode == 17)
{
def.walkAnimation = stream.readUnsignedShort();
def.walkingAnimation = stream.readUnsignedShort();
def.rotate180Animation = stream.readUnsignedShort();
def.rotate90RightAnimation = stream.readUnsignedShort();
def.rotate90LeftAnimation = stream.readUnsignedShort();
}
else if (opcode >= 30 && opcode < 35)
{
def.options[opcode - 30] = stream.readString();
if (def.options[opcode - 30].equalsIgnoreCase("Hidden"))
def.actions[opcode - 30] = stream.readString();
if (def.actions[opcode - 30].equalsIgnoreCase("Hidden"))
{
def.options[opcode - 30] = null;
def.actions[opcode - 30] = null;
}
}
else if (opcode == 40)
@@ -137,17 +135,17 @@ public class NpcLoader
else if (opcode == 60)
{
length = stream.readUnsignedByte();
def.models_2 = new int[length];
def.chatheadModels = new int[length];
for (index = 0; index < length; ++index)
{
def.models_2[index] = stream.readUnsignedShort();
def.chatheadModels[index] = stream.readUnsignedShort();
}
}
else if (opcode == 93)
{
def.renderOnMinimap = false;
def.isMinimapVisible = false;
}
else if (opcode == 95)
{
@@ -155,11 +153,11 @@ public class NpcLoader
}
else if (opcode == 97)
{
def.resizeX = stream.readUnsignedShort();
def.widthScale = stream.readUnsignedShort();
}
else if (opcode == 98)
{
def.resizeY = stream.readUnsignedShort();
def.heightScale = stream.readUnsignedShort();
}
else if (opcode == 99)
{
@@ -179,18 +177,18 @@ public class NpcLoader
}
else if (opcode == 103)
{
def.rotation = stream.readUnsignedShort();
def.rotationSpeed = stream.readUnsignedShort();
}
else if (opcode == 106)
{
def.varbitIndex = stream.readUnsignedShort();
if ('\uffff' == def.varbitIndex)
def.varbitId = stream.readUnsignedShort();
if (def.varbitId == 65535)
{
def.varbitIndex = -1;
def.varbitId = -1;
}
def.varpIndex = stream.readUnsignedShort();
if ('\uffff' == def.varpIndex)
if (def.varpIndex == 65535)
{
def.varpIndex = -1;
}
@@ -212,26 +210,26 @@ public class NpcLoader
}
else if (opcode == 107)
{
def.isClickable = false;
def.isInteractable = false;
}
else if (opcode == 109)
{
def.aBool2170 = false;
def.rotationFlag = false;
}
else if (opcode == 111)
{
def.aBool2190 = true;
def.isPet = true;
}
else if (opcode == 118)
{
def.varbitIndex = stream.readUnsignedShort();
if ('\uffff' == def.varbitIndex)
def.varbitId = stream.readUnsignedShort();
if (def.varbitId == 65535)
{
def.varbitIndex = -1;
def.varbitId = -1;
}
def.varpIndex = stream.readUnsignedShort();
if ('\uffff' == def.varpIndex)
if (def.varpIndex == 65535)
{
def.varpIndex = -1;
}

View File

@@ -47,45 +47,45 @@ public class NpcSaver
out.writeByte(2);
out.writeString(npc.name);
}
if (npc.tileSpacesOccupied != 1)
if (npc.size != 1)
{
out.writeByte(12);
out.writeByte(npc.tileSpacesOccupied);
out.writeByte(npc.size);
}
if (npc.stanceAnimation != -1)
if (npc.standingAnimation != -1)
{
out.writeByte(13);
out.writeShort(npc.stanceAnimation);
out.writeShort(npc.standingAnimation);
}
if (npc.walkAnimation != -1)
if (npc.walkingAnimation != -1)
{
out.writeByte(14);
out.writeShort(npc.walkAnimation);
out.writeShort(npc.walkingAnimation);
}
if (npc.anInt2165 != -1)
if (npc.rotateLeftAnimation != -1)
{
out.writeByte(15);
out.writeShort(npc.anInt2165);
out.writeShort(npc.rotateLeftAnimation);
}
if (npc.anInt2189 != -1)
if (npc.rotateRightAnimation != -1)
{
out.writeByte(16);
out.writeShort(npc.anInt2189);
out.writeShort(npc.rotateRightAnimation);
}
if (npc.rotate180Animation != -1 || npc.rotate90LeftAnimation != -1 || npc.rotate90RightAnimation != -1)
{
out.writeByte(17);
out.writeShort(npc.walkAnimation);
out.writeShort(npc.walkingAnimation);
out.writeShort(npc.rotate180Animation);
out.writeShort(npc.rotate90RightAnimation);
out.writeShort(npc.rotate90LeftAnimation);
}
for (int i = 0; i < 5; ++i)
{
if (npc.options[i] != null)
if (npc.actions[i] != null)
{
out.writeByte(30 + i);
out.writeString(npc.options[i]);
out.writeString(npc.actions[i]);
}
}
if (npc.recolorToFind != null && npc.recolorToReplace != null)
@@ -108,16 +108,16 @@ public class NpcSaver
out.writeShort(npc.retextureToReplace[i]);
}
}
if (npc.models_2 != null)
if (npc.chatheadModels != null)
{
out.writeByte(60);
out.writeByte(npc.models_2.length);
for (int modelId : npc.models_2)
out.writeByte(npc.chatheadModels.length);
for (int modelId : npc.chatheadModels)
{
out.writeShort(modelId);
}
}
if (!npc.renderOnMinimap)
if (!npc.isMinimapVisible)
{
out.writeByte(93);
}
@@ -127,9 +127,9 @@ public class NpcSaver
out.writeShort(npc.combatLevel);
}
out.writeByte(97);
out.writeShort(npc.resizeX);
out.writeShort(npc.widthScale);
out.writeByte(98);
out.writeShort(npc.resizeY);
out.writeShort(npc.heightScale);
if (npc.hasRenderPriority)
{
out.writeByte(99);
@@ -144,23 +144,23 @@ public class NpcSaver
out.writeShort(npc.headIcon);
}
out.writeByte(103);
out.writeShort(npc.rotation);
if (!npc.isClickable)
out.writeShort(npc.rotationSpeed);
if (!npc.isInteractable)
{
out.writeByte(107);
}
if (!npc.aBool2170)
if (!npc.rotationFlag)
{
out.writeByte(109);
}
if (npc.aBool2190)
if (npc.isPet)
{
out.writeByte(111);
}
if (npc.configs != null)
{
out.writeByte(118);
out.writeShort(npc.varbitIndex);
out.writeShort(npc.varbitId);
out.writeShort(npc.varpIndex);
int[] c = npc.configs;

View File

@@ -24,18 +24,19 @@
*/
package net.runelite.cache;
import com.google.common.io.FileWriteMode;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import net.runelite.cache.definitions.loaders.sound.SoundEffectTrackLoader;
import net.runelite.cache.definitions.sound.SoundEffectTrackDefinition;
import net.runelite.cache.fs.Archive;
@@ -48,11 +49,6 @@ import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public class SoundEffectsDumperTest
{
private static final Logger logger = LoggerFactory.getLogger(SoundEffectsDumperTest.class);

View File

@@ -28,8 +28,8 @@
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="SuppressionCommentFilter"/>
<module name="TreeWalker">
<module name="SuppressionCommentFilter"/>
<module name="LeftCurly">
<property name="option" value="nl"/>
</module>
@@ -58,6 +58,6 @@
<property name="message" value="Newline should not be between else and if"/>
</module>
<module name="SuppressionFilter">
<property name="file" value="${suppressionFile}"/>
<property name="file" value="${config_loc}/suppressions.xml"/>
</module>
</module>

View File

@@ -24,11 +24,11 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.1//EN"
"https://checkstyle.org/dtds/suppressions_1_1.dtd">
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files="RuntimeTypeAdapterFactory\.java" checks="[a-zA-Z0-9]*"/>
<suppress files="[\\/]runescape-client[\\/]" checks="[a-zA-Z0-9]*"/>
<suppress files="[\\/]ScriptVarType[\./]" checks="[a-zA-Z0-9]*"/>
<suppress files="[\\/]RoomType[\./]" checks="[a-zA-Z0-9]*"/>
<suppress files="[\\/]LayoutSolver[\./]" checks="[a-zA-Z0-9]*"/>
</suppressions>

View File

@@ -1,117 +0,0 @@
import org.apache.tools.ant.filters.ReplaceTokens
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler
import java.nio.file.Files
import java.nio.file.Paths
import java.util.zip.ZipFile
plugins {
id "com.github.hauner.jarTest" version "1.0.1"
}
description = 'Deobfuscator'
def deobfuscatedJar = "${rootPath}/runescape-client/build/libs/rs-client-${project.version}.jar"
def unzipFile(String file, String dest)
{
def zipFile = new ZipFile(file)
zipFile.entries().each { it ->
def path = Paths.get(dest + File.separator + it.name)
if (it.directory)
{
Files.createDirectories(path)
}
else
{
def parentDir = path.getParent()
if (!Files.exists(parentDir))
{
Files.createDirectories(parentDir)
}
Files.copy(zipFile.getInputStream(it), path)
}
}
}
configurations {
deobjars
}
dependencies {
deobjars group: 'net.runelite.rs', name: 'vanilla', version: rsversion
deobjars project(':rs-client')
implementation group: 'com.google.code.gson', name: 'gson', version: gson
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'net.runelite', name: 'fernflower', version: fernflower
implementation group: 'org.ow2.asm', name: 'asm', version: asm
implementation group: 'org.ow2.asm', name: 'asm-util', version: asm
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4j
implementation project(':runelite-api')
implementation project(':runescape-api')
runtime group: 'org.slf4j', name: 'slf4j-simple', version: slf4j
testImplementation configurations.deobjars.dependencies
testImplementation group: 'junit', name: 'junit', version: junit
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockito
}
processResources {
from file("src/main/resources/deob.properties"), {
filter(ReplaceTokens, tokens: [
"rs.version": rsversion.toString(),
"vanilla.jar": configurations.deobjars.find {it.name.startsWith("vanilla")}.toString().replace('\\', "/"),
"rs.client": configurations.deobjars.find {it.name.startsWith("rs-client")}.toString().replace('\\', "/")
])
}
}
processTestResources {
from file("src/test/resources/deob-test.properties"), {
filter(ReplaceTokens, tokens: [
"rs.client": configurations.deobjars.find {it.name.startsWith("rs-client")}.toString().replace('\\', "/"),
"rs.version": rsversion.toString(),
"vanilla.jar": configurations.deobjars.find {it.name.startsWith("vanilla")}.toString().replace('\\', "/")
])
}
}
task gamepackUpdate {
dependsOn ":deobfuscator:build"
dependsOn ":rs-client:build"
doLast {
def path = sourceSets.main.runtimeClasspath
def loader = new URLClassLoader(path.collect { f -> f.toURI().toURL() } as URL[])
def downloader = loader.loadClass('net.runelite.gamepack.Downloader')
def clientVersion = loader.loadClass('net.runelite.deob.clientver.ClientVersionMain')
def deob = loader.loadClass('net.runelite.deob.Deob')
def mappings = loader.loadClass('net.runelite.deob.updater.UpdateMappings')
String gamepack = downloader.gamepack()
int version = clientVersion.version(gamepack)
String gamepackVersion = gamepack.replace("gamepack.jar", "gamepack-" + version + ".jar")
String gamepackDeob = gamepack.replace("gamepack.jar", "gamepack-" + version + "-deob.jar")
String gamepackMappings = gamepack.replace("gamepack.jar", "gamepack-" + version + "-updated-mappings.jar")
String gamepackMappingsDecomp = gamepackMappings.replace(".jar", "-decomp")
String gamepackMappingsFern = gamepackMappingsDecomp + File.separator + gamepackMappings.split("/gamepack/")[1]
if (version == -1 || version == rsversion)
{
return
}
deob.main(gamepackVersion, gamepackDeob)
mappings.main(deobfuscatedJar, gamepackDeob, gamepackMappings)
new File(gamepackMappingsDecomp).mkdirs()
ConsoleDecompiler.main(gamepackMappings, gamepackMappingsDecomp)
unzipFile(gamepackMappingsFern, gamepackMappingsDecomp)
new File(gamepackMappingsFern).delete()
loader.close()
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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 org.apache.tools.ant.filters.ReplaceTokens
plugins {
id(Plugins.jarTest.first) version Plugins.jarTest.second
}
val deobjars = configurations.create("deobjars")
dependencies {
deobjars(group = "net.runelite.rs", name = "vanilla", version = ProjectVersions.rsversion.toString())
deobjars(project(":runescape-client"))
implementation(Libraries.annotations)
implementation(Libraries.asmAll)
implementation(Libraries.asmUtil)
implementation(Libraries.fernflower)
implementation(Libraries.gson)
implementation(Libraries.guava)
implementation(Libraries.slf4jApi)
implementation(project(":runelite-api"))
implementation(project(":runescape-api"))
runtimeOnly(Libraries.slf4jSimple)
testImplementation(deobjars)
testImplementation(Libraries.junit)
testImplementation(Libraries.mockitoCore)
}
tasks {
val tokens = mapOf(
"rs.version" to ProjectVersions.rsversion.toString(),
"vanilla.jar" to deobjars.find { it.name.startsWith("vanilla") }.toString().replace("\\", "/"),
"rs.client" to deobjars.find { it.name.startsWith("runescape-client") }.toString().replace("\\", "/")
)
processResources {
finalizedBy("filterResources")
}
register<Copy>("filterResources") {
inputs.properties(tokens)
from("src/main/resources") {
include("deob.properties")
}
into("${buildDir}/resources/main")
filter(ReplaceTokens::class, "tokens" to tokens)
filteringCharset = "UTF-8"
}
processTestResources {
finalizedBy("filterTestResources")
}
register<Copy>("filterTestResources") {
inputs.properties(tokens)
from("src/test/resources") {
include("deob-test.properties")
}
into("${buildDir}/resources/test")
filter(ReplaceTokens::class, "tokens" to tokens)
filteringCharset = "UTF-8"
}
}

View File

@@ -0,0 +1,17 @@
package net.runelite.asm;
import java.util.Iterator;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import org.jetbrains.annotations.NotNull;
public interface Annotated extends Iterable<Annotation>
{
Annotations getAnnotations();
@NotNull
default Iterator<Annotation> iterator()
{
return getAnnotations().iterator();
}
}

View File

@@ -31,13 +31,12 @@ import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature;
import static net.runelite.deob.DeobAnnotations.*;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class ClassFile
public class ClassFile implements Annotated, Named
{
private ClassGroup group;
@@ -100,10 +99,9 @@ public class ClassFile
visitor.visit(version, access, name.getName(), null, super_class.getName(), ints);
visitor.visitSource(source, null);
for (Annotation annotation : annotations.getAnnotations())
for (Annotation annotation : annotations)
{
AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true);
annotation.accept(av);
annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true));
}
for (Field field : fields)

View File

@@ -27,13 +27,16 @@ package net.runelite.asm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.signature.Signature;
import static net.runelite.deob.DeobAnnotations.*;
import org.jetbrains.annotations.NotNull;
public class ClassGroup
public class ClassGroup implements Iterable<ClassFile>
{
private final List<ClassFile> classes = new ArrayList<>(); // to keep order
private final Map<String, ClassFile> classMap = new HashMap<>();
@@ -156,4 +159,17 @@ public class ClassGroup
return findClass(name);
}
@NotNull
@Override
public Iterator<ClassFile> iterator()
{
return this.classes.iterator();
}
@Override
public void forEach(Consumer<? super ClassFile> action)
{
this.classes.forEach(action);
}
}

View File

@@ -27,15 +27,13 @@ package net.runelite.asm;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.deob.DeobAnnotations;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
public class Field
public class Field implements Annotated, Named
{
public static final int ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
@@ -53,15 +51,14 @@ public class Field
this.name = name;
this.type = type;
annotations = new Annotations();
this.annotations = new Annotations();
}
public void accept(FieldVisitor visitor)
{
for (Annotation annotation : annotations.getAnnotations())
{
AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true);
annotation.accept(av);
annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true));
}
visitor.visitEnd();

View File

@@ -25,12 +25,14 @@
package net.runelite.asm;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import net.runelite.asm.pool.Class;
import net.runelite.deob.DeobAnnotations;
import org.jetbrains.annotations.NotNull;
public class Interfaces
public class Interfaces implements Iterable<Class>
{
private final ClassFile classFile;
@@ -107,4 +109,10 @@ public class Interfaces
return names;
}
@NotNull
public Iterator<Class> iterator()
{
return this.interfaces.iterator();
}
}

View File

@@ -36,7 +36,6 @@ import net.runelite.asm.attributes.code.Parameter;
import net.runelite.asm.attributes.code.instruction.types.LVTInstruction;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
@@ -47,7 +46,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED;
public class Method
public class Method implements Annotated, Named
{
public static final int ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
@@ -92,8 +91,7 @@ public class Method
for (Annotation annotation : annotations.getAnnotations())
{
AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true);
annotation.accept(av);
annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true));
}
if (code != null)

View File

@@ -0,0 +1,6 @@
package net.runelite.asm;
public interface Named
{
String getName();
}

View File

@@ -26,13 +26,16 @@
package net.runelite.asm.attributes;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import org.jetbrains.annotations.NotNull;
public class Annotations
public class Annotations implements Iterable<Annotation>
{
private final List<Annotation> annotations = new ArrayList<>();
@@ -40,7 +43,7 @@ public class Annotations
{
return annotations;
}
public void addAnnotation(Annotation annotation)
{
annotations.add(annotation);
@@ -55,7 +58,7 @@ public class Annotations
{
annotations.clear();
}
public Annotation find(Type type)
{
for (Annotation a : annotations)
@@ -68,18 +71,22 @@ public class Annotations
{
return annotations.size();
}
public Annotation addAnnotation(Type type, String name, Object value)
{
Annotation annotation = new Annotation(this);
annotation.setType(type);
Annotation annotation = new Annotation(type);
addAnnotation(annotation);
Element element = new Element(annotation);
element.setName(name);
element.setValue(value);
Element element = new SimpleElement(name, value);
annotation.addElement(element);
return annotation;
}
@NotNull
@Override
public Iterator<Annotation> iterator()
{
return this.annotations.iterator();
}
}

View File

@@ -41,11 +41,11 @@ public class Code
private int maxStack;
private Instructions instructions;
private final Exceptions exceptions;
public Code(Method method)
{
this.method = method;
exceptions = new Exceptions(this);
instructions = new Instructions(this);
}
@@ -59,12 +59,12 @@ public class Code
{
return maxStack;
}
public void setMaxStack(int maxStack)
{
this.maxStack = maxStack;
}
private int getMaxLocalsFromSig()
{
Method m = getMethod();
@@ -77,12 +77,11 @@ public class Code
/**
* calculates the size of the lvt required for this method
* @return
*/
public int getMaxLocals()
{
int max = -1;
for (Instruction ins : instructions.getInstructions())
{
if (ins instanceof LVTInstruction)
@@ -96,19 +95,19 @@ public class Code
}
}
}
int fromSig = getMaxLocalsFromSig();
if (fromSig > max)
max = fromSig;
return max;
}
public Exceptions getExceptions()
{
return exceptions;
}
public Instructions getInstructions()
{
return instructions;

View File

@@ -26,30 +26,26 @@
package net.runelite.asm.attributes.annotation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.AnnotationVisitor;
public class Annotation
public class Annotation extends Element<List<Element>> implements Iterable<Element>
{
private final Annotations annotations;
private Type type;
private final List<Element> elements = new ArrayList<>();
private final Type type;
public Annotation(Annotations annotations)
public Annotation(Type type)
{
this.annotations = annotations;
this.value = new ArrayList<>();
this.type = type;
}
public Annotations getAnnotations()
{
return annotations;
}
public void setType(Type type)
public Annotation(String name, Type type)
{
this.value = new ArrayList<>();
this.name = name;
this.type = type;
}
@@ -60,23 +56,44 @@ public class Annotation
public List<Element> getElements()
{
return elements;
return value;
}
public Element getElement()
{
return elements.get(0);
return value.get(0);
}
public void addElement(Element element)
{
elements.add(element);
value.add(element);
}
@Override
public final void setValue(List<Element> value)
{
throw new UnsupportedOperationException();
}
public void accept(AnnotationVisitor visitor)
{
for (Element element : elements)
visitor.visit(element.getName(), element.getValue());
if (visitor == null)
{
return;
}
for (Element element : this)
{
accept(visitor, element.name, element.value);
}
visitor.visitEnd();
}
@NotNull
@Override
public Iterator<Element> iterator()
{
return this.value.iterator();
}
}

View File

@@ -0,0 +1,42 @@
package net.runelite.asm.attributes.annotation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.jetbrains.annotations.NotNull;
public class ArrayElement extends Element<List> implements Iterable<Object>
{
public ArrayElement(String name)
{
this.name = name;
this.value = new ArrayList<>();
}
@SuppressWarnings("unchecked")
public void addValue(Object value)
{
this.value.add(value);
}
@Override
public final void setValue(List value)
{
throw new UnsupportedOperationException();
}
@NotNull
@Override
@SuppressWarnings("unchecked")
public Iterator<Object> iterator()
{
return this.value.iterator();
}
@SuppressWarnings("unchecked")
public Stream<Object> stream()
{
return this.value.stream();
}
}

View File

@@ -25,21 +25,14 @@
package net.runelite.asm.attributes.annotation;
public class Element
{
private final Annotation annotation;
private String name;
private Object value;
public Element(Annotation annotation)
{
this.annotation = annotation;
}
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
public Annotation getAnnotation()
{
return annotation;
}
public abstract class Element<T>
{
String name = "value";
T value;
public String getName()
{
@@ -51,18 +44,48 @@ public class Element
this.name = name;
}
public Object getValue()
public T getValue()
{
return value;
}
public void setValue(Object value)
public void setValue(T value)
{
this.value = value;
}
public String getString()
{
return value.toString();
}
public static void accept(AnnotationVisitor visitor, final String name, final Object value)
{
if (visitor == null)
{
return;
}
if (value instanceof Annotation)
{
Annotation annotation = (Annotation) value;
annotation.accept(visitor.visitAnnotation(name, annotation.getType().toString()));
}
else if (value instanceof List)
{
AnnotationVisitor arr = visitor.visitArray(name);
List<?> arrayValue = (List<?>) value;
for (Object o : arrayValue)
{
accept(arr, null, o);
}
arr.visitEnd();
}
else
{
visitor.visit(name, value);
}
}
}

View File

@@ -0,0 +1,15 @@
package net.runelite.asm.attributes.annotation;
public class SimpleElement extends Element<Object>
{
public SimpleElement(Object value)
{
this.value = value;
}
public SimpleElement(String name, Object value)
{
this.name = name;
this.value = value;
}
}

View File

@@ -26,11 +26,14 @@ package net.runelite.asm.attributes.code;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import net.runelite.asm.attributes.Code;
import org.jetbrains.annotations.NotNull;
public class Instructions
public class Instructions implements Iterable<Instruction>
{
private final Code code;
private final List<Instruction> instructions = new ArrayList<>();
@@ -186,4 +189,25 @@ public class Instructions
return i;
}
public int size()
{
return this.instructions.size();
}
@NotNull
public Iterator<Instruction> iterator()
{
return this.instructions.iterator();
}
public ListIterator<Instruction> listIterator()
{
return this.instructions.listIterator();
}
public ListIterator<Instruction> listIterator(int i)
{
return this.instructions.listIterator(i);
}
}

View File

@@ -52,8 +52,7 @@ public abstract class ArrayStore extends Instruction implements ArrayStoreInstru
if (r.getInstruction() instanceof GetFieldInstruction)
{
GetFieldInstruction gf = (GetFieldInstruction) r.getInstruction();
Field f = gf.getMyField();
return f;
return gf.getMyField();
}
return null;
@@ -89,7 +88,7 @@ public abstract class ArrayStore extends Instruction implements ArrayStoreInstru
Field f1 = gf1.getMyField(),
f2 = gf2.getMyField();
assert MappingExecutorUtil.isMaybeEqual(f1, f2);
if (f1 != null && f2 != null)

View File

@@ -24,7 +24,6 @@
*/
package net.runelite.asm.attributes.code.instructions;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.runelite.asm.ClassFile;
@@ -86,7 +85,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
@SuppressWarnings("unchecked")
public List<net.runelite.asm.Method> getMethods()
{
return myMethod != null ? Arrays.asList(myMethod) : Collections.EMPTY_LIST;
return myMethod != null ? Collections.singletonList(myMethod) : Collections.EMPTY_LIST;
}
@Override

View File

@@ -70,10 +70,9 @@ public class MethodContext
return contexts.get(i);
}
@SuppressWarnings("unchecked")
public Collection<InstructionContext> getInstructionContexts()
{
return (Collection) contexts.values();
return contexts.values();
}
public void reset()

View File

@@ -43,8 +43,21 @@ public class NonloadingClassWriter extends ClassWriter
@Override
protected String getCommonSuperClass(String type1, String type2)
{
ClassFile cf1 = group.findClass(type1),
cf2 = group.findClass(type2);
// Checking more than this wouldn't make any sense
// Object has no super class, and RS api is guaranteed to be interfaces, which always extend from Object
// some rl api classes however ARE actual classes, so we can't just assume interface, for the slim chance
// we've got rl api on classpath. We could check all implemented interfaces in group, but that means you end up
// with Object as super class anyway, just like if you just let the Class.forName call throw.
// (maybe we could if we had a better package structure...)
if (type1.equals("java/lang/Object")
|| type2.equals("java/lang/Object")
|| type1.startsWith("net/runelite/rs/api/RS")
|| type2.startsWith("net/runelite/rs/api/RS")
)
return "java/lang/Object";
ClassFile cf1 = group.findClass(type1);
ClassFile cf2 = group.findClass(type2);
if (cf1 == null && cf2 == null)
{
@@ -62,10 +75,11 @@ public class NonloadingClassWriter extends ClassWriter
if (cf1 != null && cf2 != null)
{
for (ClassFile c = cf1; c != null; c = c.getParent())
for (ClassFile c2 = cf2; c2 != null; c2 = c2.getParent())
if (c == c2)
return c.getName();
if (!(cf1.isInterface() || cf2.isInterface()))
for (ClassFile c = cf1; c != null; c = c.getParent())
for (ClassFile c2 = cf2; c2 != null; c2 = c2.getParent())
if (c == c2)
return c.getName();
return "java/lang/Object";
}
@@ -80,7 +94,6 @@ public class NonloadingClassWriter extends ClassWriter
}
else
{
assert cf2 == null;
found = cf1;
other = type2;
}
@@ -88,13 +101,10 @@ public class NonloadingClassWriter extends ClassWriter
ClassFile prev = null;
for (ClassFile c = found; c != null; c = c.getParent())
{
prev = c;
if (c.getName().equals(other))
if ((prev = c).getSuperName().equals(other))
return other;
}
// This should pretty much never be hit, right?
return super.getCommonSuperClass(prev.getSuperName(), other);
}
}

View File

@@ -25,44 +25,59 @@
package net.runelite.asm.visitors;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.ArrayElement;
import net.runelite.asm.attributes.annotation.SimpleElement;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
public class MethodAnnotationVisitor extends AnnotationVisitor
public class AnnotationElementVisitor extends AnnotationVisitor
{
private final Method method;
private final Type type;
private final Annotation annotation;
public MethodAnnotationVisitor(Method method, Type type)
AnnotationElementVisitor(Annotation annotation)
{
super(Opcodes.ASM5);
this.method = method;
this.type = type;
annotation = new Annotation(method.getAnnotations());
annotation.setType(type);
this.annotation = annotation;
}
@Override
public void visit(String name, Object value)
{
Element element = new Element(annotation);
element.setName(name);
element.setValue(value);
SimpleElement element = new SimpleElement(name, value);
annotation.addElement(element);
}
@Override
public void visitEnd()
public AnnotationVisitor visitArray(String name)
{
method.getAnnotations().addAnnotation(annotation);
ArrayElement element = new ArrayElement(name);
this.annotation.addElement(element);
return new AnnotationVisitor(Opcodes.ASM5)
{
@Override
public void visit(String name, Object value)
{
element.addValue(value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor)
{
Annotation annotation = new Annotation(name, new Type(descriptor));
element.addValue(annotation);
return new AnnotationElementVisitor(annotation);
}
};
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor)
{
Annotation annotation = new Annotation(name, new Type(descriptor));
this.annotation.addElement(annotation);
return new AnnotationElementVisitor(annotation);
}
}

View File

@@ -22,12 +22,12 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.visitors;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Field;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.FieldVisitor;
@@ -35,25 +35,25 @@ import org.objectweb.asm.Opcodes;
public class ClassFieldVisitor extends FieldVisitor
{
private final ClassFile classFile;
private final Field field;
public ClassFieldVisitor(ClassFile cf, int access, String name, Type desc, Object value)
ClassFieldVisitor(ClassFile cf, int access, String name, Type desc, Object value)
{
super(Opcodes.ASM5);
this.classFile = cf;
this.field = new Field(cf, name, desc);
this.field.setAccessFlags(access);
this.field.setValue(value);
field = new Field(cf, name, desc);
field.setAccessFlags(access);
field.setValue(value);
cf.addField(field);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
Type type = new Type(desc);
return new FieldAnnotationVisitor(field, type);
Annotation element = new Annotation(new Type(desc));
this.field.getAnnotations().addAnnotation(element);
return new AnnotationElementVisitor(element);
}
@Override
@@ -61,10 +61,4 @@ public class ClassFieldVisitor extends FieldVisitor
{
System.out.println(attr);
}
@Override
public void visitEnd()
{
classFile.addField(field);
}
}

View File

@@ -27,6 +27,7 @@ package net.runelite.asm.visitors;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.signature.Signature;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
@@ -55,7 +56,7 @@ public class ClassFileVisitor extends ClassVisitor
classFile.setSuperName(superName);
classFile.setVersion(version);
classFile.setAccess(access);
for (String inter : interfaces)
classFile.getInterfaces().addInterface(new net.runelite.asm.pool.Class(inter));
}
@@ -69,8 +70,10 @@ public class ClassFileVisitor extends ClassVisitor
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
Type type = new Type(desc);
return new ClassAnnotationVisitor(classFile, type);
Annotation annotation = new Annotation(new Type(desc));
classFile.getAnnotations().addAnnotation(annotation);
return new AnnotationElementVisitor(annotation);
}
@Override

View File

@@ -32,6 +32,7 @@ import net.runelite.asm.ClassFile;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.code.Exceptions;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.InstructionType;
@@ -72,18 +73,14 @@ import static org.objectweb.asm.Opcodes.ICONST_5;
import static org.objectweb.asm.Opcodes.ICONST_M1;
import static org.objectweb.asm.Opcodes.LCONST_0;
import static org.objectweb.asm.Opcodes.LCONST_1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CodeVisitor extends MethodVisitor
{
private static final Logger logger = LoggerFactory.getLogger(CodeVisitor.class);
private final ClassFile classFile;
private final Method method;
private Code code;
public CodeVisitor(ClassFile classFile, int access, String name, Signature signature, String[] sexceptions)
CodeVisitor(ClassFile classFile, int access, String name, Signature signature, String[] sexceptions)
{
super(Opcodes.ASM5);
@@ -111,8 +108,9 @@ public class CodeVisitor extends MethodVisitor
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
Type type = new Type(desc);
return new MethodAnnotationVisitor(method, type);
Annotation element = new Annotation(new Type(desc));
this.method.getAnnotations().addAnnotation(element);
return new AnnotationElementVisitor(element);
}
@Override
@@ -333,7 +331,7 @@ public class CodeVisitor extends MethodVisitor
if (cst instanceof org.objectweb.asm.Type)
{
org.objectweb.asm.Type t = (org.objectweb.asm.Type) cst;
entry = new net.runelite.asm.pool.Class((String) t.getClassName());
entry = new net.runelite.asm.pool.Class(t.getClassName());
}
LDC ldc = new LDC(code.getInstructions(), entry);

View File

@@ -1,68 +0,0 @@
/*
* 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:
*
* 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.
*/
package net.runelite.asm.visitors;
import net.runelite.asm.Field;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
public class FieldAnnotationVisitor extends AnnotationVisitor
{
private final Field field;
private final Type type;
private final Annotation annotation;
public FieldAnnotationVisitor(Field field, Type type)
{
super(Opcodes.ASM5);
this.field = field;
this.type = type;
annotation = new Annotation(field.getAnnotations());
annotation.setType(type);
}
@Override
public void visit(String name, Object value)
{
Element element = new Element(annotation);
element.setName(name);
element.setValue(value);
annotation.addElement(element);
}
@Override
public void visitEnd()
{
field.getAnnotations().addAnnotation(annotation);
}
}

View File

@@ -95,7 +95,7 @@ public class DeobAnnotations
{
return null;
}
return (Number) an.getElement().getValue();
}

View File

@@ -193,6 +193,7 @@ public class Renamer implements Deobfuscator
}
@Override
@SuppressWarnings("unchecked")
public void run(ClassGroup group)
{
group.buildClassGraph();

View File

@@ -37,6 +37,7 @@ import net.runelite.asm.Method;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
@@ -113,7 +114,6 @@ public class ConstantParameter implements Deobfuscator
List<StackContext> pops = invokeCtx.getPops();
outer:
// object is popped first, then param 1, 2, 3, etc. double and long take two slots.
for (int lvtOffset = offset, parameterIndex = 0;
parameterIndex < method.getDescriptor().size();
@@ -451,9 +451,7 @@ public class ConstantParameter implements Deobfuscator
}
// Add garbage value
Element element = new Element(obfuscatedSignature);
element.setName("garbageValue");
element.setValue(value.toString());
Element element = new SimpleElement("garbageValue", value.toString());
obfuscatedSignature.addElement(element);
}
}
@@ -464,12 +462,12 @@ public class ConstantParameter implements Deobfuscator
public void run(ClassGroup group)
{
Execution execution = new Execution(group);
execution.addExecutionVisitor(i -> findParameters(i));
execution.addExecutionVisitor(this::findParameters);
execution.populateInitialMethods();
execution.run();
execution = new Execution(group);
execution.addMethodContextVisitor(mc -> findDeadParameters(mc));
execution.addMethodContextVisitor(this::findDeadParameters);
execution.populateInitialMethods();
execution.run();

View File

@@ -32,6 +32,7 @@ import net.runelite.asm.Method;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import net.runelite.deob.DeobAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +40,7 @@ import org.slf4j.LoggerFactory;
public class AnnotationMapper
{
private static final Logger logger = LoggerFactory.getLogger(AnnotationMapper.class);
private final ClassGroup source, target;
private final ParallelExecutorMapping mapping;
@@ -119,20 +120,17 @@ public class AnnotationMapper
if (from.getAnnotations() == null)
return count;
for (Annotation a : from.getAnnotations())
{
if (isCopyable(a))
{
Annotation annotation = new Annotation(to);
annotation.setType(a.getType());
Annotation annotation = new Annotation(a.getType());
to.addAnnotation(annotation);
for (Element e : a.getElements())
{
Element element = new Element(annotation);
element.setName(e.getName());
element.setValue(e.getValue());
Element element = new SimpleElement(e.getName(), e.getValue());
annotation.addElement(element);
}
@@ -155,7 +153,6 @@ public class AnnotationMapper
private boolean isCopyable(Annotation a)
{
return a.getType().equals(DeobAnnotations.EXPORT)
|| a.getType().equals(DeobAnnotations.IMPLEMENTS)
|| a.getType().equals(DeobAnnotations.HOOK);
|| a.getType().equals(DeobAnnotations.IMPLEMENTS);
}
}

View File

@@ -8,6 +8,7 @@ import net.runelite.asm.Method;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import net.runelite.deob.Deob;
import net.runelite.deob.DeobAnnotations;
import org.slf4j.Logger;
@@ -23,6 +24,7 @@ public class AnnotationAdder
private final ClassGroup group;
private final Logger log = LoggerFactory.getLogger(AnnotationAdder.class);
@SuppressWarnings("unchecked")
public void run()
{
int impl = 0;
@@ -50,12 +52,9 @@ public class AnnotationAdder
{
Annotations an = c.getAnnotations();
Annotation implAn = new Annotation(an);
implAn.setType(DeobAnnotations.IMPLEMENTS);
Annotation implAn = new Annotation(DeobAnnotations.IMPLEMENTS);
Element value = new Element(implAn);
value.setValue(c.getClassName());
value.setName("value");
Element value = new SimpleElement(c.getClassName());
implAn.addElement(value);
an.addAnnotation(implAn);
@@ -81,12 +80,9 @@ public class AnnotationAdder
Annotation a = an.find(DeobAnnotations.EXPORT);
if (a == null)
{
a = new Annotation(an);
a.setType(DeobAnnotations.EXPORT);
a = new Annotation(DeobAnnotations.EXPORT);
Element value = new Element(a);
value.setValue(fieldName);
value.setName("value");
Element value = new SimpleElement(fieldName);
a.addElement(value);
an.addAnnotation(a);
@@ -114,12 +110,9 @@ public class AnnotationAdder
Annotation a = an.find(DeobAnnotations.EXPORT);
if (a == null)
{
a = new Annotation(an);
a.setType(DeobAnnotations.EXPORT);
a = new Annotation(DeobAnnotations.EXPORT);
Element value = new Element(a);
value.setValue(methodName);
value.setName("value");
Element value = new SimpleElement(methodName);
a.addElement(value);
an.addAnnotation(a);

View File

@@ -34,6 +34,7 @@ import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
public class AnnotationCopier
{
@@ -97,15 +98,12 @@ public class AnnotationCopier
{
if (!isType(a.getType()))
continue;
Annotation a2 = new Annotation(an2);
a2.setType(a.getType());
Annotation a2 = new Annotation(a.getType());
for (Element element : a.getElements())
{
Element element2 = new Element(a2);
element2.setName(element.getName());
element2.setValue(element.getValue());
Element element2 = new SimpleElement(element.getName(), element.getValue());
a2.addElement(element2);
}

View File

@@ -34,13 +34,9 @@ import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.deob.DeobAnnotations;
import net.runelite.deob.deobfuscators.Renamer;
import net.runelite.deob.util.NameMappings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AnnotationRenamer
{
private static final Logger logger = LoggerFactory.getLogger(AnnotationRenamer.class);
private ClassGroup group;
public AnnotationRenamer(ClassGroup group)

View File

@@ -25,9 +25,11 @@
package net.runelite.deob.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -79,6 +81,41 @@ public class JarUtil
return group;
}
public static ClassFile loadClass(byte[] bytes)
{
ClassReader reader = new ClassReader(bytes);
ClassFileVisitor cv = new ClassFileVisitor();
reader.accept(cv, ClassReader.SKIP_FRAMES);
return cv.getClassFile();
}
public static ClassGroup loadClasses(Collection<File> files) throws IOException
{
final ClassGroup group = new ClassGroup();
for (File file : files)
{
if (!file.getName().endsWith(".class"))
{
continue;
}
try (InputStream is = new FileInputStream(file))
{
ClassReader reader = new ClassReader(is);
ClassFileVisitor cv = new ClassFileVisitor();
reader.accept(cv, ClassReader.SKIP_FRAMES);
group.addClass(cv.getClassFile());
}
}
group.initialize();
return group;
}
public static void saveJar(ClassGroup group, File jarfile) throws IOException
{
try (JarOutputStream jout = new JarOutputStream(new FileOutputStream(jarfile), new Manifest()))

View File

@@ -276,8 +276,7 @@ public class HookImporter
{
for (Element e : a.getElements())
{
String str = (String) e.getValue();
return str;
return (String) e.getValue();
}
}
}
@@ -288,7 +287,7 @@ public class HookImporter
private Signature getObfuscatedMethodSignature(Method method)
{
String sig = getAnnotation(method.getAnnotations(), OBFUSCATED_SIGNATURE);
if (sig.isEmpty() == false)
if (!sig.isEmpty())
{
return toObSignature(new Signature(sig)); // if it is annoted, use that
}

View File

@@ -1,165 +0,0 @@
/*
* 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:
*
* 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.
*/
package net.runelite.runeloader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import net.runelite.mapping.Export;
import net.runelite.mapping.ObfuscatedGetter;
import net.runelite.mapping.ObfuscatedName;
import net.runelite.runeloader.inject.GetterInjectInstruction;
import net.runelite.runeloader.inject.Injection;
import net.runelite.runeloader.inject.InjectionModscript;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class CheckMappings
{
private static final File CLIENT = new File("d:/rs/07/adamout.jar");
private final List<Class> classes = new ArrayList<>();
@Before
public void before() throws MalformedURLException, ClassNotFoundException
{
ClassLoader loader = new URLClassLoader(new URL[]{CLIENT.toURI().toURL()});
Class c = loader.loadClass("client");
classes.add(c);
for (int i = 0; i < 230; ++i)
{
try
{
c = loader.loadClass("class" + i);
classes.add(c);
}
catch (ClassNotFoundException ex)
{
}
}
}
@SuppressWarnings("unchecked")
private Class<?> findClassWithObfuscatedName(String name)
{
for (Class c : classes)
{
if (c.getName().equals("net.runelite.rs.client.client") && name.equals("client"))
{
return c;
}
ObfuscatedName oc = (ObfuscatedName) c.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
{
continue;
}
if (oc.value().equals(name))
{
return c;
}
}
return null;
}
private Field findFieldWithObfuscatedName(Class c, String name)
{
for (Field f : c.getDeclaredFields())
{
ObfuscatedName oc = f.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
{
continue;
}
if (oc.value().equals(name))
{
return f;
}
}
return null;
}
private Integer getIntegerMultiplier(Field f)
{
ObfuscatedGetter getter = f.getDeclaredAnnotation(ObfuscatedGetter.class);
if (getter == null)
{
return null;
}
return getter.intValue() == 0 ? null : getter.intValue();
}
private String getExportedName(Field f)
{
Export e = f.getDeclaredAnnotation(Export.class);
if (e == null)
{
return null;
}
return e.value();
}
@Test
@Ignore
public void checkMappings() throws IOException
{
InjectionModscript mod = Injection.load(MappingImporter.class.getResourceAsStream(MappingImporter.RL_INJECTION));
for (int i = 0; i < mod.getGetterInjects().size(); ++i)
{
GetterInjectInstruction gii = mod.getGetterInjects().get(i);
Class c = this.findClassWithObfuscatedName(gii.getGetterClassName());
Assert.assertNotNull(c);
Field f = this.findFieldWithObfuscatedName(c, gii.getGetterFieldName());
Assert.assertNotNull(f);
String exportedName = this.getExportedName(f);
String attrName = gii.getGetterName();
attrName = Utils.toExportedName(attrName);
Integer mul = gii.getMultiplier(),
myMul = this.getIntegerMultiplier(f);
// XXX Check @Export etc names
//Assert.assertEquals(exportedName, attrName);
Assert.assertEquals(myMul, mul);
}
}
}

View File

@@ -3,4 +3,4 @@ org.gradle.warning.mode=all
org.gradle.parallel=true
org.gradle.console=rich
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.jvmargs=-XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

31
gradlew vendored
View File

@@ -44,7 +44,7 @@ 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='"-Xmx4g" "-Xms2g" "-Dfile.encoding=UTF-8"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $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" ;;
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
@@ -175,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
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" "$@"

2
gradlew.bat vendored
View File

@@ -30,7 +30,7 @@ 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="-Xmx4g" "-Xms2g" "-Dfile.encoding=UTF-8"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

View File

@@ -1,33 +0,0 @@
import org.apache.tools.ant.filters.ReplaceTokens
description = 'Web API'
dependencies {
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok
compileOnly group: 'javax.inject', name: 'javax.inject', version: javaxInject
compileOnly group: 'org.projectlombok', name: 'lombok', version: lombok
implementation group: 'com.google.code.gson', name: 'gson', version: gson
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: okhttp3
implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: rxjava
implementation group: 'org.apache.commons', name: 'commons-csv', version: apacheCommonsCsv
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4j
implementation project(':runelite-api')
testImplementation group: 'com.squareup.okhttp3', name: 'mockwebserver', version: okhttp3
testImplementation group: 'junit', name: 'junit', version: junit
testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4j
}
processResources {
from file("src/main/resources/runelite.properties"), {
filter(ReplaceTokens, tokens: [
"projectver": project.version,
"rsver": rsversion.toString(),
"gitcommit": gitCommitShort,
"gitdirty": gitDirty.toString()
])
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,53 +22,50 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.injector;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.apache.tools.ant.filters.ReplaceTokens
public class InjectTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
description = "Web API"
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
dependencies {
annotationProcessor(Libraries.lombok)
private ClassGroup deob, vanilla;
compileOnly(Libraries.javaxInject)
compileOnly(Libraries.lombok)
@Before
public void before() throws IOException
{
deob = JarUtil.loadJar(new File(properties.getRsClient()));
vanilla = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(vanilla, folder.newFile());
}
@Test
@Ignore
public void testRun() throws InjectionException
{
Inject instance = new Inject(deob, vanilla);
instance.run();
InjectorValidator iv = new InjectorValidator(vanilla);
iv.validate();
}
implementation(Libraries.gson)
implementation(Libraries.guava)
implementation(Libraries.okhttp3)
implementation(Libraries.rxjava)
implementation(Libraries.apacheCommonsCsv)
implementation(Libraries.slf4jApi)
implementation(project(":runelite-api"))
testImplementation(Libraries.okhttp3Webserver)
testImplementation(Libraries.junit)
testImplementation(Libraries.slf4jSimple)
}
tasks {
processResources {
finalizedBy("filterResources")
}
register<Copy>("filterResources") {
val tokens = mapOf(
"projectver" to ProjectVersions.rlVersion,
"rsver" to ProjectVersions.rsversion.toString(),
"gitcommit" to project.extra["gitCommit"]
)
inputs.properties(tokens)
from("src/main/resources") {
include("runelite.properties")
}
into("${buildDir}/resources/main")
filter(ReplaceTokens::class, "tokens" to tokens)
filteringCharset = "UTF-8"
}
}

View File

@@ -25,13 +25,9 @@
package net.runelite.http.api;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.runelite.http.api.item.ItemEquipmentStats;
import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.item.ItemStats;
import net.runelite.http.api.util.TypeAdapters;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@@ -60,12 +56,9 @@ public class RuneLiteAPI
public static final String RUNELITE_AUTH = "RUNELITE-AUTH";
public static final OkHttpClient CLIENT;
public static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(ItemStats.class, TypeAdapters.ITEMSTATS)
.registerTypeAdapter(ItemEquipmentStats.class, TypeAdapters.EQUIPMENTSTATS)
.registerTypeAdapter(ItemPrice.class, TypeAdapters.ITEMPRICE)
.create();
public static final Gson GSON = new Gson();
public static final MediaType JSON = MediaType.parse("application/json");
public static String userAgent;
private static final String BASE = "https://api.runelite.net";
private static final String WSBASE = "https://api.runelite.net/ws";
@@ -76,8 +69,6 @@ public class RuneLiteAPI
private static final String MAVEN_METADATA = "http://repo.runelite.net/net/runelite/runelite-parent/maven-metadata.xml";
private static final Properties properties = new Properties();
private static String userAgent;
private static String version;
private static String upstreamVersion;
private static int rsVersion;

View File

@@ -316,36 +316,6 @@ public class ChatClient
}
}
public String getLayout(String username) throws IOException
{
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("layout")
.addQueryParameter("name", username)
.build();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
if (!response.isSuccessful())
{
throw new IOException("Unable to look up layout!");
}
final String layout = response.body().string();
if (!testLayout(layout))
{
throw new IOException("Layout " + layout + " is not valid!");
}
return layout;
}
}
public boolean testLayout(String layout)
{
return LAYOUT_VALIDATOR.test(layout);
@@ -465,4 +435,51 @@ public class ChatClient
return response.isSuccessful();
}
}
public boolean submitLayout(String username, LayoutRoom[] rooms) throws IOException
{
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("layout")
.addQueryParameter("name", username)
.build();
Request request = new Request.Builder()
.post(RequestBody.create(RuneLiteAPI.JSON, RuneLiteAPI.GSON.toJson(rooms)))
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
return response.isSuccessful();
}
}
public LayoutRoom[] getLayout(String username) throws IOException
{
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("layout")
.addQueryParameter("name", username)
.build();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
if (!response.isSuccessful())
{
throw new IOException("Unable to look up layout!");
}
InputStream in = response.body().byteStream();
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), LayoutRoom[].class);
}
catch (JsonParseException ex)
{
throw new IOException(ex);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,23 +22,29 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.injector;
package net.runelite.http.api.chat;
public class InjectionException extends Exception
public enum LayoutRoom
{
public InjectionException(String message)
{
super(message);
}
START,
END,
SCAVENGERS,
FARMING,
EMPTY,
public InjectionException(Throwable cause)
{
super(cause);
}
public InjectionException(String message, Throwable cause)
{
super(message, cause);
}
TEKTON,
MUTTADILES,
GUARDIANS,
VESPULA,
SHAMANS,
VASA,
VANGUARDS,
MYSTICS,
UNKNOWN_COMBAT,
CRABS,
ICE_DEMON,
TIGHTROPE,
THIEVING,
UNKNOWN_PUZZLE;
}

View File

@@ -30,10 +30,10 @@ import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import static net.runelite.http.api.RuneLiteAPI.JSON;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@@ -42,7 +42,6 @@ import okhttp3.Response;
@AllArgsConstructor
public class GrandExchangeClient
{
private static final MediaType JSON = MediaType.parse("application/json");
private static final Gson GSON = RuneLiteAPI.GSON;
private final UUID uuid;

View File

@@ -36,10 +36,10 @@ import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import static net.runelite.http.api.RuneLiteAPI.JSON;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@@ -48,7 +48,6 @@ import okhttp3.Response;
@AllArgsConstructor
public class LootTrackerClient
{
private static final MediaType JSON = MediaType.parse("application/json");
private static final Gson GSON = RuneLiteAPI.GSON;
private final UUID uuid;

View File

@@ -31,10 +31,10 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import net.runelite.http.api.RuneLiteAPI;
import static net.runelite.http.api.RuneLiteAPI.JSON;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@@ -43,8 +43,6 @@ import org.slf4j.LoggerFactory;
public class XteaClient
{
private static final MediaType JSON = MediaType.parse("application/json");
private static final Logger logger = LoggerFactory.getLogger(XteaClient.class);
public void submit(XteaRequest xteaRequest)

View File

@@ -1,4 +1,3 @@
runelite.version=@projectver@
rs.version=@rsver@
runelite.commit=@gitcommit@
runelite.dirty=@gitdirty@
runelite.commit=@gitcommit@

View File

@@ -1,26 +0,0 @@
apply plugin: 'war'
description = 'Web Service OpenOSRS'
dependencies {
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok
api project(':cache')
api project(':http-api')
api project(':http-service')
implementation group: 'com.google.code.gson', name: 'gson', version: gson
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: okhttp3
implementation group: 'org.springframework', name: 'spring-jdbc', version: springJdbc
implementation group: 'org.springframework.boot', name: 'spring-boot-devtools', version: springboot
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springboot
implementation group: 'org.sql2o', name: 'sql2o', version: sql2o
implementation(group: 'redis.clients', name: 'jedis', version: jedis) {
exclude(module: 'commons-pool2')
}
providedCompile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: mariadbJdbc
providedCompile group: 'org.projectlombok', name: 'lombok', version: lombok
providedCompile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: springboot
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
plugins {
war
}
description = "Web Service OpenOSRS"
dependencies {
annotationProcessor(Libraries.lombok)
api(project(":cache"))
api(project(":http-api"))
api(project(":http-service"))
implementation(Libraries.gson)
implementation(Libraries.guava)
implementation(Libraries.okhttp3)
implementation(Libraries.springbootJdbc)
implementation(Libraries.springbootDevtools)
implementation(Libraries.springbootStarterWeb)
implementation(Libraries.sql2o)
implementation(Libraries.jedis) {
exclude(module = "commons-pool2")
}
providedCompile(Libraries.mariadbJdbc)
providedCompile(Libraries.lombok)
providedCompile(Libraries.springbootStarterTomcat)
}

View File

@@ -1,37 +0,0 @@
apply plugin: 'war'
description = 'Web Service'
dependencies {
annotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: mapstruct
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok
api project(':cache')
api project(':http-api')
api project(':runelite-api')
implementation group: 'com.github.scribejava', name: 'scribejava-apis', version: scribejava
implementation group: 'com.google.code.gson', name: 'gson', version: gson
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'io.minio', name: 'minio', version: minio
implementation group: 'org.mapstruct', name: 'mapstruct-jdk8', version: mapstruct
implementation group: 'org.mongodb', name: 'mongodb-driver-sync', version: mongodbDriverSync
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4j
implementation group: 'org.springframework', name: 'spring-jdbc', version: springJdbc
implementation group: 'org.springframework.boot', name: 'spring-boot-devtools', version: springboot
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springboot
implementation group: 'org.sql2o', name: 'sql2o', version: sql2o
implementation(group: 'redis.clients', name: 'jedis', version: jedis) {
exclude(module: 'commons-pool2')
}
providedCompile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: mariadbJdbc
providedCompile group: 'org.projectlombok', name: 'lombok', version: lombok
providedCompile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: springboot
testImplementation group: 'com.h2database', name: 'h2', version: '1.4.200'
testImplementation group: 'com.squareup.okhttp3', name: 'mockwebserver', version: okhttp3
testImplementation(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springboot) {
exclude(module: 'commons-logging')
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,42 +22,43 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.injector;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Method;
import net.runelite.asm.signature.Signature;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.mockito.Matchers;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class InjectConstructTest
{
@Test
public void testInjectConstruct() throws Exception
{
ClassFile targetClass = new ClassFile();
targetClass.setName("test");
ClassFile vanillaClass = new ClassFile();
vanillaClass.setName("ab");
Method constructor = new Method(vanillaClass, "<init>", new Signature("()V"));
vanillaClass.addMethod(constructor);
Inject inject = mock(Inject.class);
when(inject.findVanillaForInterface(Matchers.any(Class.class)))
.thenReturn(vanillaClass);
InjectConstruct injectConstruct = new InjectConstruct(inject);
injectConstruct.injectConstruct(targetClass, APIClass.class.getDeclaredMethod("create"));
assertNotNull(targetClass.findMethod("create"));
}
interface APIClass
{
APIClass create();
}
plugins {
war
}
description = "Web Service"
dependencies {
annotationProcessor(Libraries.mapstructProcessor)
annotationProcessor(Libraries.lombok)
api(project(":cache"))
api(project(":http-api"))
api(project(":runelite-api"))
implementation(Libraries.scribejava)
implementation(Libraries.gson)
implementation(Libraries.guava)
implementation(Libraries.minio)
implementation(Libraries.mapstruct)
implementation(Libraries.mongodbDriverSync)
implementation(Libraries.slf4jApi)
implementation(Libraries.springbootJdbc)
implementation(Libraries.springbootDevtools)
implementation(Libraries.springbootStarterWeb)
implementation(Libraries.sql2o)
implementation(Libraries.jedis) {
exclude(module = "commons-pool2")
}
providedCompile(Libraries.mariadbJdbc)
providedCompile(Libraries.lombok)
providedCompile(Libraries.springbootStarterTomcat)
testImplementation(Libraries.h2)
testImplementation(Libraries.okhttp3Webserver)
testImplementation(Libraries.springbootStarterTest) {
exclude(module = "commons-logging")
}
}

View File

@@ -30,11 +30,13 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.runelite.http.api.chat.Duels;
import net.runelite.http.api.chat.LayoutRoom;
import net.runelite.http.api.chat.Task;
import net.runelite.http.service.util.exception.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -208,4 +210,23 @@ public class ChatController
}
return duels;
}
@PostMapping("/layout")
public void submitLayout(@RequestParam String name, @RequestBody LayoutRoom[] rooms)
{
chatService.setLayout(name, rooms);
}
@GetMapping("/layout")
public LayoutRoom[] getLayout(@RequestParam String name)
{
LayoutRoom[] layout = chatService.getLayout(name);
if (layout == null)
{
throw new NotFoundException();
}
return layout;
}
}

View File

@@ -24,9 +24,13 @@
*/
package net.runelite.http.service.chat;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import net.runelite.http.api.chat.LayoutRoom;
import net.runelite.http.api.chat.Task;
import net.runelite.http.api.chat.Duels;
import net.runelite.http.service.util.redis.RedisPool;
@@ -198,4 +202,31 @@ public class ChatService
jedis.expire(key, (int) EXPIRE.getSeconds());
}
}
public LayoutRoom[] getLayout(String name)
{
String layout;
try (Jedis jedis = jedisPool.getResource())
{
layout = jedis.get("layout." + name);
}
if (layout == null)
{
return null;
}
List<String> roomList = Splitter.on(' ').splitToList(layout);
return roomList.stream()
.map(LayoutRoom::valueOf)
.toArray(LayoutRoom[]::new);
}
public void setLayout(String name, LayoutRoom[] rooms)
{
try (Jedis jedis = jedisPool.getResource())
{
jedis.setex("layout." + name, (int) EXPIRE.getSeconds(), Joiner.on(' ').join(rooms));
}
}
}

View File

@@ -51,6 +51,7 @@ import net.runelite.http.api.config.ConfigEntry;
import net.runelite.http.api.config.Configuration;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
@@ -66,11 +67,12 @@ public class ConfigService
@Autowired
public ConfigService(
MongoClient mongoClient
MongoClient mongoClient,
@Value("${mongo.database}") String databaseName
)
{
MongoDatabase database = mongoClient.getDatabase("config");
MongoDatabase database = mongoClient.getDatabase(databaseName);
MongoCollection<Document> collection = database.getCollection("config");
this.mongoCollection = collection;

View File

@@ -98,6 +98,11 @@ public class OSBGrandExchangeService
Integer itemId = entry.getKey();
OsbuddySummaryItem item = entry.getValue();
if (item.getBuy_average() <= 0 || item.getSell_average() <= 0 || item.getOverall_average() <= 0)
{
continue;
}
query
.addParameter("itemId", itemId)
.addParameter("buyAverage", item.getBuy_average())

View File

@@ -32,10 +32,11 @@ redis:
mongo:
jndiName: java:comp/env/mongodb/runelite
database: runelite
# Twitter client for feed
runelite:
twitter:
consumerkey:
secretkey:
listid: 968949795153948673
listid: 1185897074786742273

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2019 ThatGamerBlue
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
apply<FernflowerPlugin>()
description = "Injected Client"
plugins {
id("com.openosrs.injector")
}
val vanillaDep by configurations.creating
val rsapiDep by configurations.creating
val rsclientDep by configurations.creating
val mixinsDep by configurations.creating
val combined by configurations.creating {
extendsFrom(rsapiDep, rsclientDep, mixinsDep, vanillaDep)
isCanBeResolved = true
isCanBeConsumed = false
}
configurations {
all {
isTransitive = false
}
}
dependencies {
vanillaDep(Libraries.vanilla)
rsapiDep(project(":runescape-api"))
rsclientDep(project(":runescape-client"))
mixinsDep(project(":runelite-mixins"))
}
injector {
mixins.set(mixinsDep.singleFile)
rsapi.set(rsapiDep.singleFile)
rsclient.set(rsclientDep.singleFile)
vanilla.set(vanillaDep.singleFile)
}
sourceSets {
main {
output.dir(tasks.inject.get().output.get().asFile.parentFile, "builtBy" to tasks.inject)
}
}
// keep the sourcesets etc but remove useless tasks
tasks {
inject {
dependsOn(configurations["combined"])
}
classes {
enabled = false
}
compileJava {
enabled = false
}
jar {
enabled = false
}
processResources {
enabled = false
}
}

View File

@@ -1,63 +0,0 @@
group = 'us.runelitepl.rs'
description = 'Injector'
def buildPath = buildDir.toString().replace('\\', '/') // this doesnt work in an ext block for some reason
def deobfuscatedJar = "${rootPath}/runescape-client/build/libs/rs-client-${project.version}.jar"
def vanillaJar = "${buildPath}/vanilla-${rsversion}.jar"
configurations {
vanilla
}
dependencies {
annotationProcessor group: 'org.eclipse.sisu', name: 'org.eclipse.sisu.inject', version: sisu
compileOnly group: 'org.apache.maven.plugin-tools', name: 'maven-plugin-annotations', version: mavenPluginAnnotations
implementation group: 'com.google.guava', name: 'guava', version: guava
implementation group: 'org.apache.maven', name: 'maven-plugin-api', version: mavenPluginApi
implementation group: 'org.ow2.asm', name: 'asm', version: asm
implementation group: 'org.ow2.asm', name: 'asm-util', version: asm
implementation project(':deobfuscator')
implementation project(':mixins')
implementation project(':runelite-api')
implementation project(':runescape-api')
testImplementation group: 'junit', name: 'junit', version: junit
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockito
testImplementation project(':deobfuscator')
testImplementation project(path: ':deobfuscator', configuration: 'testArchives')
vanilla "net.runelite.rs:vanilla:${rsversion}"
}
compileJava {
dependsOn ":rs-client:build"
inputs.dir("${project.rootDir}/runescape-client/")
inputs.dir("${project.rootDir}/runescape-api/")
inputs.dir("${project.rootDir}/runelite-mixins/")
}
compileJava.doLast() {
copy {
from configurations.vanilla
into "$buildDir"
}
def path = sourceSets.main.runtimeClasspath
def loader
try {
loader = new URLClassLoader(path.collect { f -> f.toURI().toURL() } as URL[])
def inject = loader.loadClass('net.runelite.injector.Injector')
String[] jarPaths = [
deobfuscatedJar.toString(),
vanillaJar.toString(),
injectedClassesPath.toString()
]
inject.main(jarPaths)
} finally {
if (loader) {
loader.close()
}
}
}

View File

@@ -1,582 +0,0 @@
/*
* 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:
*
* 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.
*/
package net.runelite.injector;
import java.util.HashMap;
import java.util.Map;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Interfaces;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.DLoad;
import net.runelite.asm.attributes.code.instructions.FLoad;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.LLoad;
import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.deob.deobfuscators.arithmetic.DMath;
import static net.runelite.injector.InjectUtil.getFieldType;
import net.runelite.injector.raw.ClearColorBuffer;
import net.runelite.injector.raw.DrawAfterWidgets;
import net.runelite.injector.raw.Occluder;
import net.runelite.injector.raw.RasterizerHook;
import net.runelite.injector.raw.RenderDraw;
import net.runelite.injector.raw.ScriptVM;
import net.runelite.mapping.Import;
import net.runelite.rs.api.RSClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.runelite.injector.raw.HidePlayerAttacks;
// import net.runelite.injector.raw.DrawMenu;
public class Inject
{
public static final java.lang.Class<?> CLIENT_CLASS = RSClient.class;
public static final String API_PACKAGE_BASE = "net.runelite.rs.api.RS";
public static final String RL_API_PACKAGE_BASE = "net.runelite.api.";
private static final Logger logger = LoggerFactory.getLogger(Inject.class);
private final InjectHookMethod hookMethod = new InjectHookMethod(this);
private final InjectGetter getters = new InjectGetter(this);
private final InjectSetter setters = new InjectSetter(this);
private final InjectInvoker invokes = new InjectInvoker(this);
private final InjectConstruct construct = new InjectConstruct(this);
private final MixinInjector mixinInjector = new MixinInjector(this);
// deobfuscated contains exports etc to apply to vanilla
private final ClassGroup deobfuscated, vanilla;
public Inject(ClassGroup deobfuscated, ClassGroup vanilla)
{
this.deobfuscated = deobfuscated;
this.vanilla = vanilla;
}
/**
* Convert a java.lang.Class to a Type
*
* @param c
* @return
*/
public static Type classToType(java.lang.Class<?> c)
{
int dimms = 0;
while (c.isArray())
{
c = c.getComponentType();
++dimms;
}
if (c.isPrimitive())
{
String s;
switch (c.getName())
{
case "int":
s = "I";
break;
case "long":
s = "J";
break;
case "boolean":
s = "Z";
break;
case "char":
s = "C";
break;
case "short":
s = "S";
break;
case "float":
s = "F";
break;
case "double":
s = "D";
break;
case "byte":
s = "B";
break;
case "void":
s = "V";
break;
default:
throw new RuntimeException("unknown primitive type " + c.getName());
}
return Type.getType(s, dimms);
}
return Type.getType("L" + c.getName().replace('.', '/') + ";", dimms);
}
public Signature getMethodSignature(Method m)
{
Signature signature = m.getDescriptor();
Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE);
if (obfSignature != null)
{
//Annotation exists. Signature was updated by us during deobfuscation
signature = DeobAnnotations.getObfuscatedSignature(m);
}
return signature;
}
/**
* Build a Signature from a java method
*
* @param method
* @return
*/
public Signature javaMethodToSignature(java.lang.reflect.Method method)
{
Signature.Builder builder = new Signature.Builder()
.setReturnType(classToType(method.getReturnType()));
for (java.lang.Class<?> clazz : method.getParameterTypes())
{
builder.addArgument(classToType(clazz));
}
return builder.build();
}
public void run() throws InjectionException
{
Map<ClassFile, java.lang.Class> implemented = new HashMap<>();
// inject interfaces first, so the validateTypeIsConvertibleTo
// check below works
for (ClassFile cf : deobfuscated.getClasses())
{
Annotations an = cf.getAnnotations();
if (an == null || an.size() == 0)
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(an);
if (obfuscatedName == null)
{
obfuscatedName = cf.getName();
}
ClassFile other = vanilla.findClass(obfuscatedName);
assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName;
java.lang.Class implementingClass = injectInterface(cf, other);
// it can not implement an interface but still have exported static fields, which are
// moved to client
implemented.put(cf, implementingClass);
}
// Has to be done before mixins
// well, can be done after really
// but why do that when you can do it before
new RasterizerHook(this).inject();
// requires interfaces to be injected
mixinInjector.inject();
construct.inject(implemented);
for (ClassFile cf : deobfuscated.getClasses())
{
java.lang.Class implementingClass = implemented.get(cf);
Annotations an = cf.getAnnotations();
if (an == null || an.size() == 0)
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(an);
if (obfuscatedName == null)
{
obfuscatedName = cf.getName();
}
ClassFile other = vanilla.findClass(obfuscatedName);
assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName;
for (Field f : cf.getFields())
{
an = f.getAnnotations();
if (an == null || an.find(DeobAnnotations.EXPORT) == null)
{
continue; // not an exported field
}
Annotation exportAnnotation = an.find(DeobAnnotations.EXPORT);
String exportedName = exportAnnotation.getElement().getString();
obfuscatedName = DeobAnnotations.getObfuscatedName(an);
Annotation getterAnnotation = an.find(DeobAnnotations.OBFUSCATED_GETTER);
Number getter = null;
if (getterAnnotation != null)
{
getter = (Number) getterAnnotation.getElement().getValue();
}
// the ob jar is the same as the vanilla so this field must exist in this class.
Type obType = getFieldType(f);
Field otherf = other.findField(obfuscatedName, obType);
assert otherf != null;
assert f.isStatic() == otherf.isStatic();
ClassFile targetClass = f.isStatic() ? vanilla.findClass("client") : other; // target class for getter
java.lang.Class targetApiClass = f.isStatic() ? CLIENT_CLASS : implementingClass; // target api class for getter
if (targetApiClass == null)
{
assert !f.isStatic();
// non static field exported on non exported interface
// logger.debug("Non static exported field {} on non exported interface", exportedName);
continue;
}
java.lang.reflect.Method apiMethod = findImportMethodOnApi(targetApiClass, exportedName, true);
if (apiMethod != null)
{
Number setter = null;
if (getter != null)
{
setter = DMath.modInverse(getter); // inverse getter to get the setter
}
setters.injectSetter(targetClass, targetApiClass, otherf, exportedName, setter);
}
apiMethod = findImportMethodOnApi(targetApiClass, exportedName, false);
if (apiMethod == null)
{
//logger.debug("Unable to find import method on api class {} with imported name {}, not injecting getter", targetApiClass, exportedName);
continue;
}
// check that otherf is converable to apiMethod's
// return type
Type fieldType = otherf.getType();
Type returnType = classToType(apiMethod.getReturnType());
if (!validateTypeIsConvertibleTo(fieldType, returnType))
{
throw new InjectionException("Type " + fieldType + " is not convertable to " + returnType + " for getter " + apiMethod);
}
getters.injectGetter(targetClass, apiMethod, otherf, getter);
}
for (Method m : cf.getMethods())
{
hookMethod.process(m);
invokes.process(m, other, implementingClass);
}
}
logger.info("Injected {} getters, {} setters, {} invokers",
getters.getInjectedGetters(),
setters.getInjectedSetters(), invokes.getInjectedInvokers());
new DrawAfterWidgets(this).inject();
new ScriptVM(this).inject();
new ClearColorBuffer(this).inject();
new RenderDraw(this).inject();
// new DrawMenu(this).inject();
new Occluder(this).inject();
new HidePlayerAttacks(this).inject();
}
private java.lang.Class injectInterface(ClassFile cf, ClassFile other)
{
Annotations an = cf.getAnnotations();
if (an == null)
{
return null;
}
Annotation a = an.find(DeobAnnotations.IMPLEMENTS);
if (a == null)
{
return null;
}
String ifaceName = API_PACKAGE_BASE + a.getElement().getString();
java.lang.Class<?> apiClass;
try
{
apiClass = java.lang.Class.forName(ifaceName);
}
catch (ClassNotFoundException ex)
{
logger.trace("Class {} implements nonexistent interface {}, skipping interface injection",
cf.getName(),
ifaceName);
return null;
}
String ifaceNameInternal = ifaceName.replace('.', '/'); // to internal name
Class clazz = new Class(ifaceNameInternal);
Interfaces interfaces = other.getInterfaces();
interfaces.addInterface(clazz);
return apiClass;
}
public java.lang.reflect.Method findImportMethodOnApi(java.lang.Class<?> clazz, String name, Boolean setter)
{
for (java.lang.reflect.Method method : clazz.getDeclaredMethods())
{
if (method.isSynthetic())
{
/*
* If you override an interface method in another interface
* with a return type that is a child of the overriden methods
* return type, both methods end up in the interface, and both
* are *annotated*. But the base one is synthetic.
*/
continue;
}
Import i = method.getAnnotation(Import.class);
if (i == null || !name.equals(i.value()) || (setter != null && (method.getParameterCount() > 0) != setter))
{
continue;
}
return method;
}
return null;
}
/**
* create a load instruction for a variable of type from a given index
*
* @param instructions
* @param type
* @param index
* @return
*/
public Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index)
{
if (type.getDimensions() > 0 || !type.isPrimitive())
{
return new ALoad(instructions, index);
}
switch (type.toString())
{
case "B":
case "C":
case "I":
case "S":
case "Z":
return new ILoad(instructions, index);
case "D":
return new DLoad(instructions, index);
case "F":
return new FLoad(instructions, index);
case "J":
return new LLoad(instructions, index);
default:
throw new RuntimeException("Unknown type");
}
}
ClassFile toDeobClass(ClassFile obClass)
{
for (ClassFile cf : deobfuscated.getClasses())
{
String obfuscatedName = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
if (obClass.getName().equalsIgnoreCase(obfuscatedName))
{
return cf;
}
}
return null;
}
Type deobfuscatedTypeToApiType(Type type) throws InjectionException
{
if (type.isPrimitive())
{
return type;
}
ClassFile cf = deobfuscated.findClass(type.getInternalName());
if (cf == null)
{
return type; // not my type
}
java.lang.Class<?> rsApiType;
try
{
rsApiType = java.lang.Class.forName(API_PACKAGE_BASE + cf.getName().replace("/", "."));
}
catch (ClassNotFoundException ex)
{
throw new InjectionException("Deobfuscated type " + type.getInternalName() + " has no API type", ex);
}
java.lang.Class<?> rlApiType = null;
for (java.lang.Class<?> inter : rsApiType.getInterfaces())
{
if (inter.getName().startsWith(RL_API_PACKAGE_BASE))
{
rlApiType = inter;
}
}
// if (rlApiType == null)
// {
// throw new InjectionException("RS API type " + rsApiType + " does not extend RL API interface");
// }
final java.lang.Class<?> finalType = rlApiType == null ? rsApiType : rlApiType;
return Type.getType("L" + finalType.getName().replace('.', '/') + ";", type.getDimensions());
}
Type apiTypeToDeobfuscatedType(Type type)
{
if (type.isPrimitive())
{
return type;
}
String internalName = type.getInternalName().replace('/', '.');
if (!internalName.startsWith(API_PACKAGE_BASE))
{
return type; // not an rs api type
}
return Type.getType("L" + type.getInternalName().substring(API_PACKAGE_BASE.length()) + ";", type.getDimensions());
}
ClassFile findVanillaForInterface(java.lang.Class<?> clazz)
{
String className = clazz.getName().replace('.', '/');
for (ClassFile cf : getVanilla().getClasses())
{
for (net.runelite.asm.pool.Class cl : cf.getInterfaces().getInterfaces())
{
if (cl.getName().equals(className))
{
return cf;
}
}
}
return null;
}
private boolean validateTypeIsConvertibleTo(Type from, Type to) throws InjectionException
{
if (from.getDimensions() != to.getDimensions())
{
throw new InjectionException("Array dimension mismatch");
}
if (from.isPrimitive())
{
return true;
}
ClassFile vanillaClass = vanilla.findClass(from.getInternalName());
if (vanillaClass == null)
{
return true;
}
boolean okay = false;
for (Class inter : vanillaClass.getInterfaces().getInterfaces())
{
java.lang.Class c;
try
{
c = java.lang.Class.forName(inter.getName().replace('/', '.'));
}
catch (ClassNotFoundException ex)
{
continue;
}
okay |= check(c, to);
}
return okay;
}
private boolean check(java.lang.Class c, Type type)
{
String s = type.getInternalName()
.replace('/', '.');
if (c.getName().equals(s))
{
return true;
}
for (java.lang.Class c2 : c.getInterfaces())
{
if (check(c2, type))
{
return true;
}
}
return false;
}
public final ClassGroup getDeobfuscated()
{
return deobfuscated;
}
public final ClassGroup getVanilla()
{
return vanilla;
}
}

View File

@@ -1,171 +0,0 @@
/*
* 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:
*
* 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.
*/
package net.runelite.injector;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
import net.runelite.asm.attributes.code.instructions.New;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.mapping.Construct;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InjectConstruct
{
private static final Logger logger = LoggerFactory.getLogger(InjectConstruct.class);
private final Inject inject;
InjectConstruct(Inject inject)
{
this.inject = inject;
}
public void inject(Map<ClassFile, java.lang.Class> implemented) throws InjectionException
{
for (Entry<ClassFile, java.lang.Class> entry : implemented.entrySet())
{
Class<?> clazz = entry.getValue();
ClassFile cf = entry.getKey();
if (clazz == null)
{
continue;
}
for (java.lang.reflect.Method method : clazz.getDeclaredMethods())
{
if (method.isSynthetic())
{
continue;
}
Construct construct = method.getAnnotation(Construct.class);
if (construct == null)
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
if (obfuscatedName == null)
{
obfuscatedName = cf.getName();
}
ClassGroup vanilla = inject.getVanilla();
ClassFile other = vanilla.findClass(obfuscatedName);
assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName;
injectConstruct(other, method);
}
}
}
void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException
{
logger.info("Injecting construct for {}", apiMethod);
assert targetClass.findMethod(apiMethod.getName()) == null;
Class<?> typeToConstruct = apiMethod.getReturnType();
ClassFile vanillaClass = inject.findVanillaForInterface(typeToConstruct);
if (vanillaClass == null)
{
throw new InjectionException("Unable to find vanilla class which implements interface " + typeToConstruct);
}
Signature sig = inject.javaMethodToSignature(apiMethod);
Signature constructorSig = new Signature.Builder()
.addArguments(Stream.of(apiMethod.getParameterTypes())
.map(arg ->
{
ClassFile vanilla = inject.findVanillaForInterface(arg);
if (vanilla != null)
{
return new Type("L" + vanilla.getName() + ";");
}
return Inject.classToType(arg);
})
.collect(Collectors.toList()))
.setReturnType(Type.VOID)
.build();
Method vanillaConstructor = vanillaClass.findMethod("<init>", constructorSig);
if (vanillaConstructor == null)
{
throw new InjectionException("Unable to find constructor for " + vanillaClass.getName() + ".<init>" + constructorSig);
}
Method setterMethod = new Method(targetClass, apiMethod.getName(), sig);
setterMethod.setAccessFlags(ACC_PUBLIC);
targetClass.addMethod(setterMethod);
Code code = new Code(setterMethod);
setterMethod.setCode(code);
Instructions instructions = code.getInstructions();
List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, vanillaClass.getPoolClass()));
ins.add(new Dup(instructions));
int idx = 1;
int parameter = 0;
for (Type type : vanillaConstructor.getDescriptor().getArguments())
{
Instruction load = inject.createLoadForTypeIndex(instructions, type, idx);
idx += type.getSize();
ins.add(load);
Type paramType = sig.getTypeOfArg(parameter);
if (!type.equals(paramType))
{
CheckCast checkCast = new CheckCast(instructions);
checkCast.setType(type);
ins.add(checkCast);
}
++parameter;
}
ins.add(new InvokeSpecial(instructions, vanillaConstructor.getPoolMethod()));
ins.add(new Return(instructions));
}
}

Some files were not shown because too many files have changed in this diff Show More