From 1261d05c9b64f6bebc67be9801938b077f261076 Mon Sep 17 00:00:00 2001 From: lexikiq Date: Sat, 1 May 2021 15:25:18 -0400 Subject: [PATCH] Initial commit --- .github/ISSUE_TEMPLATE/bug_report.md | 23 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/workflows/pr-build.yml | 38 + .github/workflows/push-build.yml | 38 + .gitignore | 43 ++ .gitmodules | 4 + Paper | 1 + README.md | 39 + parchment | 136 ++++ patches/api/0001-Parchment-POM-Changes.patch | 35 + .../server/0001-Parchment-POM-Changes.patch | 78 ++ patches/server/0002-Disable-Metrics.patch | 19 + .../server/0003-Parchment-brand-changes.patch | 683 ++++++++++++++++++ pom.xml | 30 + scripts/apply.sh | 92 +++ scripts/generatesources.sh | 40 + scripts/importmcdev.sh | 127 ++++ scripts/init.sh | 65 ++ scripts/paperclip.sh | 25 + scripts/push.sh | 15 + scripts/rebuildpatches.sh | 43 ++ scripts/upstream.sh | 64 ++ scripts/upstreamCommit.sh | 28 + 23 files changed, 1686 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/pr-build.yml create mode 100644 .github/workflows/push-build.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 160000 Paper create mode 100644 README.md create mode 100755 parchment create mode 100644 patches/api/0001-Parchment-POM-Changes.patch create mode 100644 patches/server/0001-Parchment-POM-Changes.patch create mode 100644 patches/server/0002-Disable-Metrics.patch create mode 100644 patches/server/0003-Parchment-brand-changes.patch create mode 100644 pom.xml create mode 100755 scripts/apply.sh create mode 100755 scripts/generatesources.sh create mode 100755 scripts/importmcdev.sh create mode 100755 scripts/init.sh create mode 100755 scripts/paperclip.sh create mode 100755 scripts/push.sh create mode 100755 scripts/rebuildpatches.sh create mode 100755 scripts/upstream.sh create mode 100755 scripts/upstreamCommit.sh diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..8fa3904 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Create a report detailing a bug +title: '' +labels: bug, unconfirmed +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce. Videos are nice if applicable. + +**Plugins** +Show the output of /plugins here. + +**Version** +Show the output of /version here. + +**Misc** +Anything else helpful not belonging in the categories above. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..4fe86d5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml new file mode 100644 index 0000000..c35e05b --- /dev/null +++ b/.github/workflows/pr-build.yml @@ -0,0 +1,38 @@ +name: Build PR + +on: [pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + java: [11, 8] + + steps: + - uses: actions/checkout@v2 + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + + - uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Patch Parchment + run: | + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + git submodule update --init --recursive + ./parchment jar + + - uses: actions/upload-artifact@v2 + with: + name: Parchment-PR${{ github.event.pull_request.number }}-JDK${{ matrix.java }} + path: parchment-paperclip.jar diff --git a/.github/workflows/push-build.yml b/.github/workflows/push-build.yml new file mode 100644 index 0000000..a4e1609 --- /dev/null +++ b/.github/workflows/push-build.yml @@ -0,0 +1,38 @@ +name: Build main + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + java: [11, 8] + + steps: + - uses: actions/checkout@v2 + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + + - uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Patch Parchment + run: | + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + git submodule update --init --recursive + ./parchment jar + + - uses: actions/upload-artifact@v2 + with: + name: Parchment-JDK${{ matrix.java }} + path: parchment-paperclip.jar diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..26f5a28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Concrete +Parchment-Server +Parchment-API +mc-dev +.idea +testserver +run +current-paper + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# IntelliJ +*.iml +*.ipr +*.iws +.idea/ +out/ + +# Maven +target/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9e97d59 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "Paper"] + path = Paper + url = https://github.com/PaperMC/Paper + branch = master diff --git a/Paper b/Paper new file mode 160000 index 0000000..9958447 --- /dev/null +++ b/Paper @@ -0,0 +1 @@ +Subproject commit 9958447cbaca4c3ca9dc4c625d7e95a932c82f52 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9484487 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Parchment + +This is a fork of [Paper](https://github.com/PaperMC/Paper) for the [Project Eden](https://bnn.gg/) server. +It contains changes to the API to make development of our plugin [Nexus](https://github.com/Pugabyte/Nexus) easier. + +## Building + +Requirements: +- You need `git` installed, with a configured user name and email. + On Windows you need to run from git bash. +- You need `maven` installed. +- You need `jdk` 8+ installed to compile (and `jre` 8+ to run). +- Anything else that `paper` requires to build. + +If all you want is a paperclip server jar, just run `./parchment jar`. + +Otherwise, to setup the `Parchment-API` and `Parchment-Server` repo, just run the following command +in your project root `./parchment patch` additionally, after you run `./parchment patch` you can run `./parchment build` to build the +respective api and server jars. + +`./parchment patch` should initialize the repo such that you can now start modifying and creating +patches. The folder `Parchment-API` is the api repo and the `Parchment-Server` folder +is the server repo and will contain the source files you will modify. + +### Creating a patch + +Patches are effectively just commits in either `Parchment-API` or `Parchment-Server`. +To create one, just add a commit to either repo and run `./parchment rb`, and a +patch will be placed in the patches folder. Modifying commits will also modify its +corresponding patch file. + +## License + +See https://github.com/starlis/empirecraft, https://github.com/electronicboy/byof, and https://github.com/Spottedleaf/Tuinity +for the license of material used/modified by this project. + +### Note + +The fork is based off of [Tuinity](https://github.com/Spottedleaf/Tuinity). \ No newline at end of file diff --git a/parchment b/parchment new file mode 100755 index 0000000..a03e4fe --- /dev/null +++ b/parchment @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +# exit immediately if a command exits with a non-zero status +set -e +# get base dir regardless of execution location +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}") +basedir=$(dirname "$SOURCE") +. "$basedir"/scripts/init.sh + +paperstash() { + STASHED=$(git stash) +} + +paperunstash() { + if [[ "$STASHED" != "No local changes to save" ]] ; then + git stash pop + fi +} + +case "$1" in + "rb" | "rbp" | "rebuild") + ( + set -e + cd "$basedir" + scripts/rebuildpatches.sh "$basedir" + ) + ;; + "p" | "patch" | "apply") + ( + set -e + cd "$basedir" + if [ "$2" != "fast" ]; then + scripts/upstream.sh + fi + scripts/apply.sh "$basedir" + ) + ;; + "b" | "bu" | "build") + ( + basedir + mvn -N install + cd ${FORK_NAME}-API && mvn -e clean install + cd ../Paper/Paper-MojangAPI && mvn -e clean install + cd ../../${FORK_NAME}-Server && mvn -e clean install + ) + ;; + "jar" | "paperclip") + ( + basedir + cd "$basedir" + if [ "$2" != "fast" ]; then + scripts/upstream.sh + fi + ./scripts/apply.sh "$basedir" + cd "$basedir" + mvn -N install + cd ${FORK_NAME}-API && mvn -e clean install + cd ../Paper/Paper-MojangAPI && mvn -e clean install + cd ../../${FORK_NAME}-Server && mvn -e clean install + cd "$basedir" + ./scripts/paperclip.sh + ) + ;; + "i" | "install") + ( + basedir + mvn -N install + cd ${FORK_NAME}-API + mvn clean install && cd ../${FORK_NAME}-Server && mvn clean install + ) + ;; + "up" | "upstream") + ( + cd "$basedir" + scripts/upstream.sh "$2" + ) + ;; + "r" | "root") + cd "$basedir" + ;; + "a" | "api") + cd "$basedir/Parchment-API" + ;; + "s" | "server") + cd "$basedir/Parchment-Server" + ;; + "setup") + if [[ -f ~/.bashrc ]] ; then + NAME="ec" + if [[ ! -z "${2+x}" ]] ; then + NAME="$2" + fi + (grep "alias $NAME=" ~/.bashrc > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" ~/.bashrc) || (echo "alias $NAME='. $SOURCE'" >> ~/.bashrc) + alias "$NAME=. $SOURCE" + echo "You can now just type '$NAME' at any time to access the paper tool." + fi + ;; + *) + echo "Parchment build tool command. This provides a variety of commands to build and manage the PaperMC build" + echo "environment. For all of the functionality of this command to be available, you must first run the" + echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup." + echo "" + echo " Normal commands:" + echo " * rb, rebuild | Rebuild patches, can be called from anywhere." + echo " * p, patch | Apply all patches to top of Paper without building it. Can be run from anywhere." + echo " * up, upstream | Build Paper upstream, pass arg up to update paper. Can be run from anywhere." + echo " * b, build | Build API and Server but no deploy. Can be ran anywhere." + echo " * j, jar | Apply all patches and build the project, parchment-paperclip.jar will be output. Can be run from anywhere." + echo " * i, install | Build and install API jar and build Server. Can be ran anywhere." + echo "" + echo " These commands require the setup command before use:" + echo " * r, root | Change directory to the root of the project." + echo " * a. api | Move to the Paper-API directory." + echo " * s, server | Move to the Paper-Server directory." + echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\"" + echo " | respectively to edit the correct project. Use the argument \"continue\" after" + echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere." + echo "" + echo " * setup | Add an alias to .bashrc to allow full functionality of this script. Run as:" + echo " | . ./parchment setup" + echo " | After you run this command you'll be able to just run 'parchment' from anywhere." + echo " | The default name for the resulting alias is 'parchment', you can give an argument to override" + echo " | this default, such as:" + echo " | . ./parchment setup example" + echo " | Which will allow you to run 'example' instead." + ;; +esac + +unset -f paperstash +unset -f paperunstash diff --git a/patches/api/0001-Parchment-POM-Changes.patch b/patches/api/0001-Parchment-POM-Changes.patch new file mode 100644 index 0000000..7baddaf --- /dev/null +++ b/patches/api/0001-Parchment-POM-Changes.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 1 May 2021 14:27:26 -0400 +Subject: [PATCH] Parchment POM Changes + + +diff --git a/pom.xml b/pom.xml +index c2e9ca1cc7f14d3a696385edc3cb341f902fa2fd..e5ed07236c358e9ea544f43b41533c92769192dd 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -3,18 +3,18 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + +- com.destroystokyo.paper +- paper-parent ++ me.lexikiq ++ parchment-parent + dev-SNAPSHOT ++ ../pom.xml + + +- com.destroystokyo.paper +- paper-api ++ parchment-api + 1.16.5-R0.1-SNAPSHOT + jar + +- Paper-API +- https://github.com/PaperMC/Paper ++ Parchment-API ++ https://github.com/lexikiq/Parchment + An enhanced plugin API for Minecraft servers. + + diff --git a/patches/server/0001-Parchment-POM-Changes.patch b/patches/server/0001-Parchment-POM-Changes.patch new file mode 100644 index 0000000..64320af --- /dev/null +++ b/patches/server/0001-Parchment-POM-Changes.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 1 May 2021 14:36:37 -0400 +Subject: [PATCH] Parchment POM Changes + + +diff --git a/pom.xml b/pom.xml +index ab57297272c2d6f3d21067081bcaf8775b8fff09..85bf0a229fa8c4e42744f438b71fda4cef67b4e0 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,11 +1,11 @@ + + 4.0.0 +- paper ++ parchment + jar + 1.16.5-R0.1-SNAPSHOT +- Paper +- https://papermc.io ++ Parchment-Server ++ https://github.com/lexikiq/Parchment + + + +@@ -19,8 +19,8 @@ + + + +- com.destroystokyo.paper +- paper-parent ++ me.lexikiq ++ parchment-parent + dev-SNAPSHOT + ../pom.xml + +@@ -39,8 +39,8 @@ + + + +- com.destroystokyo.paper +- paper-api ++ me.lexikiq ++ parchment-api + ${project.version} + compile + +@@ -160,7 +160,7 @@ + + + +- paper-${minecraft.version} ++ parchment-${minecraft.version} + clean install + + +@@ -168,7 +168,7 @@ + gitdescribe-maven-plugin + 1.3 + +- git-Paper- ++ git-Parchment- + .. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 674096cab190d62622f9947853b056f57d43a2a5..fbba763d909c4636174e79c680745b83c41409bb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.lexikiq/parchment-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { diff --git a/patches/server/0002-Disable-Metrics.patch b/patches/server/0002-Disable-Metrics.patch new file mode 100644 index 0000000..2fbc2a7 --- /dev/null +++ b/patches/server/0002-Disable-Metrics.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 1 May 2021 14:44:37 -0400 +Subject: [PATCH] Disable Metrics + + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index dee00aac05f1acf050f05d4db557a08dd0f301c8..df2aefc163d9f932664e2ff0c8a8f9a5b09047e5 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -73,7 +73,7 @@ public class Metrics { + Metrics.logger = logger; + + // Start submitting the data +- startSubmitting(); ++ // startSubmitting(); + } + + /** diff --git a/patches/server/0003-Parchment-brand-changes.patch b/patches/server/0003-Parchment-brand-changes.patch new file mode 100644 index 0000000..ab4243a --- /dev/null +++ b/patches/server/0003-Parchment-brand-changes.patch @@ -0,0 +1,683 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 1 May 2021 15:08:28 -0400 +Subject: [PATCH] Parchment brand changes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 61712ae515b329a6b85dbe2e5960e4e864dc7731..051ba2c4ae14c5da58177e52f5c55241f97caab8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1579,7 +1579,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "Parchment"; //Parchment - Parchment > //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport b(CrashReport crashreport) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 03b8d67a5f0088c0254b2099f27e8dcae32a6221..d2c645f459a604dd804fcda119a282f6947a4bbf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -232,7 +232,7 @@ import javax.annotation.Nullable; // Paper + import javax.annotation.Nonnull; // Paper + + public final class CraftServer implements Server { +- private final String serverName = "Paper"; // Paper ++ private final String serverName = "Parchment"; // Paper // Parchment + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 154f3a6a3d37b94c40cb29c305e3aa5fb494850c..ae76d5878392e1226ad7d72fe536fb1796cdb500 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -253,7 +253,7 @@ public class Main { + if (buildDate.before(deadline.getTime())) { + // Paper start - This is some stupid bullshit + System.err.println("*** Warning, you've not updated in a while! ***"); +- System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper ++ System.err.println("*** Please compile a new build ***"); // Paper + //System.err.println("*** Server will start in 20 seconds ***"); + //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + // Paper End +diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png +index a7d785f60c884ee4ee487cc364402d66c3dc2ecc..0aea373d9f0b09a19a0ed781938bba9cda1a4a30 100644 +GIT binary patch +literal 18477 +zcmV)9K*hg_P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T +zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p +z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i +z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW +zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X +zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 +zfg=2N-7=cNnjjOr{yriy6mMFgG#l +znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U +zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? +z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y +zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB +zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt +z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C +z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB +zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe +zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 +z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ +z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 +z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu +zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu +z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E +ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw +zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX +z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& +z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 +z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R +z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw +zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD +zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| +zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy +zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z +zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} +z002E$Nkl)=_nw*GA8U3yB?&1Ig#A3{Id9$X +z-m})M^3t`hu +zAc`1w*G(*XE?cJiJMfq-`Q>r{S|Q`Sv=dvuEY<*LyvsfDM9qIxzn>RXb9Iobu4#Y{e7ZHGxhuyJAS+?ZyfP0 +z`P@ODQms?tt?D~JJ=?#c05A39 +zo(Dg|k;hiTfAVPVyzFG6L}PQf=x19<1UVjQvaC+8(RuJ`w1?YCb1CfH;&TMhtFWd6LzW&Ym;t~E81$ZeP +zKl^nx>mNIcdoQ1Y)-AFWvJ9MsC=w-5fQcbWL=j9Idd4Wy%ro`8noBt9gnvsV`1b&T +zi~3gMoL|o8oL@F$;m3~Ro|{f3PeI4v9ViVZ0-M3uHVh0vPg|72d%%OW9&5o`n0j8D +z9Y4{L6CQI?r3Bknd1`y~GJfMIq_1yZi7Q20++x&qC9{D^x^7-=l;NYLwVf+1FaRDpu@OkR| +z&-Z+{zvu&>YzTkPoj1f!JDT0MQl;<#1_vN+i-|YE0_^n3N|2`?`wqGf9$7wr&Hw9S +zEp$7cI2Mawb5Vvn&KBi(_fCrA|I={x(Mj{_=03YG*IwrrJ(mSL!p^T)faMhUXm9NH +z>h-zh;scv6T1#K2`4wXT7X+zbkAu?2`!`;7HDCP1tMQK=g?iPLQVH%nJK%*>+(i_L +zR;E84nk`T +zbO#`cBi85*Gq4@WR0ZN#z?`ee;=_9=Vgu)2??nmtEB43Nmha~o#4Rvdl*s1LQ)7%b +zSX&9GRB{I@10wql>k3n_zTD3A5S>> +z+>{URp}6QKQG)$N6bh}t +z=AI~$3FBOtJ6?oT9H0K$<-G5mTaa}<$_GKzu|Wji_*}y5XFZT{(M_I<|6W~4yI0W} +z@I;Bir6SY|uBuE(mU)5CUP*+3$9cIv6DypP-!lrFg3h2PX^A2jqv&+umY*g>u~?Vg +zzRW35`$qis)~XmIiXFLA +z!T}_T+s|sT%V)a0=WC-EY}|fU3!FzQp^B9mL6w!5eQm_W +ztRtAgInQpNPe*n;XSHz7lXV3Isxa2hdv+b+JGY&c;B)c)-V2?al66s4EG!ei6JjpuD1;z;>VPF4_M)b`(cOs~X;BQw)l +z5m;ozUwaEWlIv)<0~?q#q5=#(E}Igw+8B{bt1b7Ir{XH`!X@ZPTuWpm7vZdk(dAOX +z<}8><6gAJ~TC`I9=sX#yzuxD0X2FsbVQJ+WEvLB$;G_F(%LPB$XZR<2R^uOk`VL;n +z;5!G}L!>Evdb>w_b)I@$pe8#5V%ALp?OwR>3dXi5WeUe}R4cqN9t#KXiIjXYP +z?F6pgOvc%t|yA+u}ekhc?K#8#FLTFC=F>BbSCrcO9w_I3OHY)k%2D!-#hJ(0b5w`xtDM< +z0Q}N?NAO=~S}woMap}byu<0a&512$7O_rwMa=g#ku45%U~f!0KE8%@q@ +z_Lx4hJJJz1{pn30+@*_1q6ihvTQF}rN-z;n_Y`9i +zUbXY-JpRja*ajs54m+8V(GEt6x)A%_-w!7nspc$2qBnvSf69O +z6Xq@N&}y|Y?Qtkf)RSEMXyC?3CO +z6LJqK+{pg3zDSzq!tgl<&f~46o8@HAk!Lx^M6BK$lUqm2Xj-j=sr!6uI79lwh(uQr +zMV5(We9Pf7Ij%n~Dr*+vP`vWf-`b%Of_kA`KvMyd9{zsm2}H5NdtU;cT|XyE@bjZ0 +zUbB^A=T8s!UGLp*JO>}NIvR(!9Vyc?;Bt#Xw8j{Z@;TZh=p-gGk%V1FGA~9cOwt<) +zI&zXov(;;-vFk2vF8IZ|I19>XTs8nWBJJ=VoK1ymP!URNl+vIhv{oq7!Z~>4v5a@T +zcLq<~I|f~W#^0!kX_B}dhVLxm#QE|@K4a!5O1FcrDdJ+8oYR9a({smV6gOFaO0^E4%$+X*I +z%JKkkTn1jlwRbqaaprIYfBBy`K^Gv-i%GS42dx~j0iUPh4~u**mblf6j=<;$A0h^& +z99kPps|T&X+gyy0(s-?jlnA>}0HZf_}rqj!fUwaz26=- +zMmL@o(G4YRMdVUY;CU{9`n)Ubaw)*FU;q*R6JIZ{s6EDD(|}YhbW@4z(+uAFYF#?! +z*S@BQ?|pY2JWfKRfV9z?D42RLAv4-&aRoS(&rnKZB866}1b(8EnkZ5wbLViFNDFw1 +zM7g{Ntu@+cRPf)SbOaqK6bcnsJ!^%yiNf_6T_uuEUGR3U8Q8i?K4^qIp!lGmL#Gr; +zl92lhiz8AI9jj=^AzkQ1I7+l1JnZ=UW67+e`_NN7`pt7BLdamCAI7g1uFKc1DXtXa +zBYP@-b>p((fMw?a>g2c+faJrVOYEyK&P#k9j^mG8N07S@fGT9`w372F1;%I*tdsGL +z4ES7>q%~$O^3FVr)`3WIMBzM<37W4EAsf(2H-;pNz4WX`_vi@lgt|G##50Ya2D;^kk_As+rP6cmUBO +zg|~A4ZVIggqL#UP+^T`IgWlBF|Y +z_D2Ss%f*M+CPosOpd>!<2s*qT1~(*v1e8nCUnv==II5H@3g$hEr0&0PAI^mZA;yaiiIE!kVa9llfx0 +z4iR=KeEC2Abz293CR~KGUdSpBiI!T&ydyYZvkjL|e#@i)Ypv0)X=y~(l{9UZ$pxE` +zK}!cI!@W~Zo`})a;75Vg(m@FlBQsDdnYG1A9kC9HbzA>nRr#T^u;zTK94&N6uYwj#nvzc30gA7Ji1 +zhYd+Q2+!W`3Hk6~LR&qx9}1JE0Di>;&}#T+3d>*&w33J@iHRey>AVVS=~`Jp;aZTH +z--^KmHv>)-&s6X0kcW>9L`I>NX5Fpl0kGZV$!s@yGMl~XRpn!V``&g$DX(g_R_V+r +zfDolMItu)>7TP#>H7Bif^?e;;ssc-*hxv0A5@cg~1UA@EqShI#=@9TAdz1q?ZDlIJ +zYEly8niO&cot#vupO37oRacpZN{epy-#Ys)nxT!qE^%5z2yf)14>npSkSA>6B)qzOm!@?}t@z2Ktu=g>R +zEcLWo9&%6C^%(6*Q%^VbWg+Z~q5x486U9~ +zCQ6HFg83JMt|ER6Y_j7l=FP9PfAvkCV%;sLm*ePs&D{o&RE%|D3AC=#vhB72+j;Yw +ziKB&!7L|{;-fFAic{dHQDQ17oq!kv=TITi*mj1tE!y2_>wrhzuiv=dGsC3P3J&B2R +zkmfQ;I;s4RqmVItu@oTBWVTyd17%if0J{CYVcB%ad3Zta#l3sV%$hc}d{W&)cuy3N +zdJ@5;?PoOrTOF*ez2z+W2YrKMDC+y`vQr9LIM#Y+Z-sCdEEpO2hS#H@Ewj$P3{y8B +z-iwJ>ib!iB9hgY1q-Fq*3Ywi4Goqf&Qk9={#R}Ehk)=|zU~^#y2Se?Iw?&rqMN$A4 +z7F^g2qLy5YR{{b}+ysEs1g&bto+kJ(rG%A>bQQx3X%oO+Yc(PR-#cZ|sDQ0_ZQ~uE +z!KeyL=z>cKv)&kZ#*Sx;$G$`Q$c&}B*LlxX)!NUTb9rU1OI|<`=>Y1yU^rKU0Vj2$C21UTp$Tz(?w`Fvjiti47R+r@Dx)J!}!^JKX% +zKR9+wxcHW;K%Egmgb0Zws>mEYB%PsjRrsk5V5GL-%yat}dy$0_tp2KLW!PB{F|~q2 +zW`B&mW*%0~%6bB&NTL*vi|2aCXG=n-(B$$p@$p_)alQ)g`EU;Jg)PjzC&vd;P~oi; +z3or!NjcrMoXhIph!IO48k@i^s!hyim0lxCt*HvaO3TCMjvSvZh-oXx^6x(#;UpJvJ +zYQBblieyWDGL*znksl~ss=|bLex%u-Tg!9v=kwhB`FQWk_s4BKO~@h>IC=%UJoQcf +z-q~bWOFT`vZ6Ys7N7bO9fy2_t$^U7ZdjkF0tgJ* +z!d7hxkFSjLtAM*#v;~+WC|MBg-PipBAHY@8qD%;RnlyJ*J)I@)E4(@LShFcH>PxzT30nds7$ESSD?Jy>4bIHEzkSh{H3e)d+oGum0+_G +zrx9w@pGPoVxC%X{ja@WQ`8Hik16wC+8bcb_7)^}AXoYifLq;2N=ZKUpYvr_-Olrgb +z6?n@)e@DvATQT%?pf{1R9_YfK@AP#xaQ4bj04pXp=fEQ_#b|}Caok&Nq&VjrhHj_A +zL?zO%rFe_VmO7DEWai3bjV$^_xhf~1oG8G$>#n=h)h-)sumLk>%%J}t|6=SeTh~a5 +z%D-&*>+djq|6}mpFO?f8KI5~zGT#X6Pe#JJ$AbCR;LS}Jhl1W<`WxKFf3--{qoiWlvie*FH6F1xqJ${f6=r1!2@nXGGj^Pjx}NzTt@y(8aM7eiSFs +zHH|W=Qd?6~ilTmA5+^ltWbM+WuGd*>xY@5w5EmX#f9m;lFn67-Jfkba8AVG+Jo3J8 +zmP#^t^5inyeB@nU<z^p!(`raMxE}B8ktuSmt9x<8!1@0einwJqVmPuW_EC +zaBb@DUtA(n*?;fjf%2uYNM4nU>D2ce4Z!}p!6~0o^rz4_5GY_^Ox!HVWI2|LFE5kW +zs#^icc2NSsEE8)`9Piox>5}>`c>c1=)eiw0z8OI+?~3>t-#xeN6yxee9oFJQ;$_B+ +z8H=F+DpqjlwG2gEC0SHpfO+$HcHTU?-EOG__rCor)K}7Y@3GGD&wamHe((LeLH~e& +z#8%`+lFF57%jSwdwI +z3a+3q*@fG<^V&67?qevxwhpBfn_Yi;Ah0rd6v^X$BNY`e`iLwIjV9oIR5^A44985b6gI$+U&j6;9Q3OiOrqe#`T0)e4Y +zS{OkSRjXM5w%KJyQ)P?LFKSd<*J}4FX>B@5GE5IV@W80F?NA=S@%~W1Tle1qh&=o3 +zv!kAOQ5ks%Qg?-K(jyOJUHJ8*;4l99-fvYDDDc4EV*1~(ZD=o}VSc}qfn{lxB|hlq +zuwv}uO6nBaGiHnkHWZ6=yRzJ=&J7gfURqUO0AMHe`nqDriu^(GSvN$uqY8X!po@}- +z+8&ZnW;gzX_D-7*6Fk5+H~mC1cp($0ybq;;l_IRM#u_Ex +zvACnRx3}p9;J-%Nto$K!=gd409h_|xJd-JJyM=x%~j30LB1+(L|C+K2lrN#yT{m)~@ +z2+LOoZ1tmfeVd!kz~O6uwIjD9M)a>o +zcv>|hgTEgf6jz`S05~>jBz!Ji6%}A2!1}wLAzbkeyU9Y3r~-klUO4mv@{@Ds+A0sA +zHA+V)Wy)e%6Ou(cJ^n4$GK2l8Nhe%KeHr&ax36ZYgwk{5wd9aCyo-gt7;&joN-k> +z-j+A~nC2(_MUUu>DDtx7J{zUee2QUs`~dDkKO3FU`g@Ekgyd*$Y1`N@C6fA +z3*;EW^=CPZ?UC`h@j=DP*tBTnVSuDZ%EX-14cc6|mIVvtHs&v|O{}HBI*rHC6TvQz +z92M%hL*-Dtw!0ut%EC;K8|<>}&1aBVhtdig%47UUWNocr!Q&UhsMmZ{*`wH(Frh4L +zDAI8^ozB!f4k3ynvMd{h{Od|Ed-m+0PmVmVfN);hr@)6snyqBzq4kxf0G)vabURG} +zJEVNP7D+Y6`bTFj;H1-vn!c|$&Nuez|0Xd*h9P86d?^TB4yu$I)jB*hT8h_veJJdB +z?#w^3;G%2r))B9_7Tf;n*szLa$ZRhfLl}*%g@Upzi7#^sOH;V=njPcD82A8;(^RT& +zjFxQ=%u3wYXQe5?tfw9f4H`q{Psvk1DEb<$ +zsbI(JPh;vE4`uf3*{mDN*M{-{bLPwe;F9y#8Rkt26q1By6-L8A`Vv%tNAA0scCVp- +z5yXjyNTF&iW9lJ|Hn7p;X~TqHJh#^J&j%mm!M7gHwtqXV>34%E5enIdXss5f#)tq(Ywo%CUI6aj^N>;zisDXRlz9({6eb<}pG-UU9A?j+%{uF>(=h#o +z@TWhpK6&0OpYy;#C(ynYQVU~RlqvOf8&@k&H-&K_ +zQTE2&+ao6DnigI$XYO2{n?Iik6J(2>2g0nSAap{diFbZv3^!zir+xlp9^C!lQt$c;Z0;!eiDVF$Lm?$lD?^*?|)j|Aa|mCYM%Ak|J| +z;?REHL0%&&3s$sN_aCo{3NRhu`$xSAkhZHmJpy6|`Y0oUgMTD8`RAvuU0US*W*jo& +zOq?ACte8E866kTg6{lZxXz~?cE6c8nsqdWh66$R;c>fcP-&$?;)rbA&GqYzm{?DE> +zhgr`&!#eA%!`f@F4ZxkdA5667xKjAKhD`+zSZ3Wfp1J=VODnX2fAXO{nSS3y20L|Y +z1Xo-l_w|!2E2xrY(2Ah1TeV}@W6RRoq^qI=G^So>Q2ts;W%7-IdmnF-Kku9QMV>zU +zvSFv0Gk5N&KXKn{KHCVvB2`;xXhGVKJ)11gmzul*N+kf8TEi1K&vlbdDM`jURPouf4J=x?KRYBxl0>p+mNC%D +zR_?|@D@Or>9Fn+N#_Tg`ZcrTWpLuXK5=$}rhvxeqc*|kK$-H7&(hvr3`q$4~tnima +z+>B-w)?RyU#)j&jsc-xec*k{Y&&#a7hR_f=5= +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 +z;Hh#vT}1}f%>T|Wh5~#RVAhU6Vg&Myi +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 +z4w5m_p({=d`@C&JBdg72{2>JJdT~kJ8 +zX6E47-wglpc1v;gPYhbYhd-SUdw*;jj@-BA%L82-2Rb_og7mc_5M!wA1S%zQtzw;I +zP!0t=JWGwVnsWdBJMNOjU(k0CX!7($(MPe{xdCiggQD{b4~XqaPl7|Ejy+a +z6wHVf>4w}yJF0kyD3XYTkiRJV0Eec|nX5pd4mcq;@Y5@yui4e(x4;1_eIQqMhme(Y +zGW4kgj)FX-te9c +z7Dk8tdm^N}iw|}D9uaaD+>X%|D4o3kF1(>}Z#gS)r;inNtZE7{q9Po1fjs%~f5O6U +z0D!@qds{7>7#s38)`?Jh5?M_%CJ_Z1+pf@jF+nmf&8D4~?-Z-^bZ{MME|#D$?VVJF +z9!J5o1b)A$Z@%L(xcZ(K#?SvdE5L|~@TGI)$yfJ*)yLJATPq10eT|tZ1lpSfU>0Vo +z*1|Tnqsq_gP?Tb=B>Qp)Q6Qkwz)luyWNZXi6f-`^pP&2%<}7^a2>zv_03#~GNtZTb +zbRYI4^tGz;qQRnd^56O9{(FUoEXXCT#6TMaLlkxUNhnz9rh#wJVSOs1Am9DnVy~B1 +z6ksJP0>Cl9mj6HasLXI5z+ZvtU30VWvf^eiE5K64QV0WASO^L5m3?LN2zf{A(6=4K8O3kTQ;g}I +zGwNr4e8O6MbU(%M-%>A^VTpLT9mjojUDjR`X3T=)PQ9N~elVG7PeYV8+nBse4z;3N +grN45#w2uEj0IsQg7c6bg&Hw-a07*qoM6N<$f)YdpWdHyG + +literal 14310 +zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c +zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 +z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez +za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ +zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc +zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 +z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C +z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj +z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO +zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq +zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP +zJxwXvt5fFTCOVgB)Zq +z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( +z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 +zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP +zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN +zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| +z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK +z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf +zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l +z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP +zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 +z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! +zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! +zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX +z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A +z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# +zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x +zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 +zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk +z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B +zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| +zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx +z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE +zllqxy +z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t +z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W +z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); +zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} +z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX +z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx +z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% +zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v +zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< +zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A +zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h +zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- +zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< +zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS +z4&$M&7(|(9nWY%QShCnuN0 +z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm +zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ +z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 +zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; +z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; +z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC +z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> +zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg +zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> +zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k +zL^tBOHF^=)k&U-Tw{gfijqQ&^ +z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 +z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X +z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 +zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( +zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY +zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU +zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ +z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ +z1IGS^Z5t=0Zj86J2MfJc +zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 +z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 +z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf +zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) +z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd +z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= +z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 +z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 +zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA +zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH +zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ +z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< +zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ +zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf +zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- +zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= +zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G +z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp +zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x +zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 +z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN +zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl +z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh +zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; +z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ +zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK +zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! +zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ +z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X +zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* +zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 +zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH +z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw +z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G +z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv +zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L +z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H +zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% +zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz +z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| +zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP +zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 +zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty +zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n +z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 +zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo +zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF +zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V +zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% +zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W +z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 +zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy +zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 +z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 +zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd +zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m +z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I +z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe +zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA +zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` +zh~ggr^knneWU!Nn}AQt=0Id6Hk; +z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# +zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 +z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< +zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r +z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN +zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D +z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk +zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq +z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ +z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ +zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl +zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH +z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif +z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) +zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf +zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m +zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< +zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I +z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 +zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} +zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..54aeb69 --- /dev/null +++ b/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + me.lexikiq + parchment-parent + dev-SNAPSHOT + pom + Parchment (Parent) + + + + aikar + https://repo.aikar.co/content/groups/aikar/ + + + velocity-snapshots + https://nexus.velocitypowered.com/repository/velocity-artifacts-snapshots/ + + + + + install + ${project.artifactId} + + + Parchment-API + Parchment-Server + Paper${file.separator}Paper-MojangAPI + + diff --git a/scripts/apply.sh b/scripts/apply.sh new file mode 100755 index 0000000..b48a3b0 --- /dev/null +++ b/scripts/apply.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# get base dir regardless of execution location +# resolve shell-specifics +case "$(echo "$SHELL" | sed -E 's|/usr(/local)?||g')" in + "/bin/zsh") + RCPATH="$HOME/.zshrc" + SOURCE="${BASH_SOURCE[0]:-${(%):-%N}}" + ;; + *) + RCPATH="$HOME/.bashrc" + if [[ -f "$HOME/.bash_aliases" ]]; then + RCPATH="$HOME/.bash_aliases" + fi + SOURCE="${BASH_SOURCE[0]}" + ;; +esac + +# get base dir regardless of execution location + +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh +PS1="$" + +paperVer=$(cat current-paper) +gpgsign="$(git config commit.gpgsign || echo "false")" +echo "Rebuilding Forked projects.... " +function applyPatch { + what=$1 + what_name=$(basename $what) + target=$2 + branch=$3 + patch_folder=$4 + + cd "$basedir/$what" + git fetch --all + git branch -f upstream "$branch" >/dev/null + + cd "$basedir" + if [ ! -d "$basedir/$target" ]; then + mkdir "$basedir/$target" + cd "$basedir/$target" + git init + git remote add origin "$5" + cd "$basedir" + fi + cd "$basedir/$target" + + # Disable GPG signing before AM, slows things down and doesn't play nicely. + # There is also zero rational or logical reason to do so for these sub-repo AMs. + # Calm down kids, it's re-enabled (if needed) immediately after, pass or fail. + git config commit.gpgsign false + + echo "Resetting $target to $what_name..." + git remote rm upstream > /dev/null 2>&1 + git remote add upstream "$basedir/$what" >/dev/null 2>&1 + git checkout master 2>/dev/null || git checkout -b master + git fetch upstream >/dev/null 2>&1 + git reset --hard upstream/upstream + echo " Applying patches to $target..." + git am --abort >/dev/null 2>&1 + git am --3way --ignore-whitespace "$basedir/patches/$patch_folder/"*.patch + if [ "$?" != "0" ]; then + echo " Something did not apply cleanly to $target." + echo " Please review above details and finish the apply then" + echo " save the changes with rebuildPatches.sh" + exit 1 + else + echo " Patches applied cleanly to $target" + fi +} + +function enableCommitSigningIfNeeded { + if [[ "$gpgsign" == "true" ]]; then + git config commit.gpgsign true + fi +} + + echo "Importing MC-DEV" + ./scripts/importmcdev.sh "$basedir" || exit 1 +( + (applyPatch Paper/Paper-API ${FORK_NAME}-API HEAD api $API_REPO && + applyPatch Paper/Paper-Server ${FORK_NAME}-Server HEAD server $SERVER_REPO) || exit 1 + enableCommitSigningIfNeeded +) || ( + echo "Failed to apply patches" + enableCommitSigningIfNeeded + exit 1 +) || exit 1 diff --git a/scripts/generatesources.sh b/scripts/generatesources.sh new file mode 100755 index 0000000..95bfeaf --- /dev/null +++ b/scripts/generatesources.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh + + +cd $basedir +paperVer=$(cat current-paper) + +minecraftversion=$(cat $basedir/Paper/work/BuildData/info.json | grep minecraftVersion | cut -d '"' -f 4) +decompile="Paper/work/Minecraft/$minecraftversion/spigot" + +mkdir -p mc-dev/src/net/minecraft + +cd mc-dev +if [ ! -d ".git" ]; then + git init +fi + +rm src/net/minecraft/*.java +cp -r $basedir/$decompile/net/minecraft/* src/net/minecraft + +base="$basedir/Paper/Paper-Server/src/main/java/net/minecraft" +cd $basedir/mc-dev/src/net/minecraft/ +for file in $(/bin/ls $base) +do + if [ -f "$file" ]; then + rm -f "$file" + fi +done +cd $basedir/mc-dev +git add . -A +git commit . -m "mc-dev" +git tag -a "$paperVer" -m "$paperVer" 2>/dev/null +pushRepo . $MCDEV_REPO $paperVer diff --git a/scripts/importmcdev.sh b/scripts/importmcdev.sh new file mode 100755 index 0000000..7dd6e66 --- /dev/null +++ b/scripts/importmcdev.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh + +workdir="$basedir"/Paper/work +minecraftversion=$(cat "$basedir"/Paper/work/BuildData/info.json | grep minecraftVersion | cut -d '"' -f 4) +decompiledir=$workdir/Minecraft/$minecraftversion/spigot + +nms="net/minecraft" +export MODLOG="" +cd "$basedir" + +function containsElement { + local e + for e in "${@:2}"; do + [[ "$e" == "$1" ]] && return 0; + done + return 1 +} + +export importedmcdev="" +function import { + if [ -f "$basedir/Paper/Paper-Server/src/main/java/$nms/$1.java" ]; then + echo "ALREADY IMPORTED $1" + return 0 + fi + export importedmcdev="$importedmcdev $1" + file="${1}.java" + target="$basedir/Paper/Paper-Server/src/main/java/$nms/$file" + base="$decompiledir/$nms/$file" + + if [[ ! -f "$target" ]]; then + export MODLOG="$MODLOG Imported $file from mc-dev\n"; + mkdir -p "$(dirname "$target")" + echo "$(bashColor 1 32) Copying $(bashColor 1 34)$base $(bashColor 1 32)to$(bashColor 1 34) $target $(bashColorReset)" + cp "$base" "$target" + else + echo "$(bashColor 1 33) UN-NEEDED IMPORT STATEMENT:$(bashColor 1 34) $file $(bashColorReset)" + fi +} + +function importLibrary { + group=$1 + lib=$2 + prefix=$3 + shift 3 + for file in "$@"; do + file="$prefix/$file" + target="$basedir/Paper/Paper-Server/src/main/java/$file" + targetdir=$(dirname "$target") + mkdir -p "${targetdir}" + base="$workdir/Minecraft/$minecraftversion/libraries/${group}/${lib}/$file" + if [ ! -f "$base" ]; then + echo "Missing $base" + exit 1 + fi + export MODLOG="$MODLOG Imported $file from $lib\n"; + sed 's/\r$//' "$base" > "$target" || exit 1 + done +} + +( + cd Paper/Paper-Server/ + lastlog=$(git log -1 --oneline) + if [[ "$lastlog" = *"Parchment-Extra mc-dev Imports"* ]]; then + git reset --hard HEAD^ + fi +) + + +files=$(cat patches/server/* | grep "+++ b/src/main/java/net/minecraft/" | sort | uniq | sed 's/\+\+\+ b\/src\/main\/java\/net\/minecraft\///g') + +nonnms=$(grep -R "new file mode" -B 1 "$basedir/patches/server/" | grep -v "new file mode" | grep -oE --color=none "net\/minecraft\/.*.java" | sed 's/.*\/net\/minecraft\///g') + +for f in $files; do + containsElement "$f" ${nonnms[@]} + if [ "$?" == "1" ]; then + if [ ! -f "$basedir/Paper/Paper-Server/src/main/java/net/minecraft/$f" ]; then + f="$(echo "$f" | sed 's/.java//g')" + if [ ! -f "$decompiledir/$nms/$f.java" ]; then + echo "$(bashColor 1 31) ERROR!!! Missing NMS$(bashColor 1 34) $f $(bashColorReset)"; + error=true + else + import $f + fi + fi + fi +done +if [ -n "$error" ]; then + exit 1 +fi + +############################################################################################### +############################################################################################### +#################### ADD TEMPORARY ADDITIONS HERE ############################################# +############################################################################################### +############################################################################################### + +# import Foo + +######################################################## +######################################################## +######################################################## +# LIBRARY IMPORTS +# These must always be mapped manually, no automatic stuff +# +# # group # lib # prefix # many files + +#importLibrary com.mojang datafixerupper com/mojang/datafixers/util Either.java +importLibrary com.mojang brigadier com/mojang/brigadier CommandDispatcher.java +importLibrary com.mojang brigadier com/mojang/brigadier/tree LiteralCommandNode.java +importLibrary com.mojang brigadier com/mojang/brigadier/suggestion SuggestionsBuilder.java +importLibrary com.mojang brigadier com/mojang/brigadier/arguments BoolArgumentType.java +################ +( + cd Paper/Paper-Server/ + rm -rf nms-patches + git add src -A + echo -e "Parchment-Extra mc-dev Imports\n\n$MODLOG" | git commit src -F - + exit 0 +) diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100755 index 0000000..dd44a91 --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# BEGIN config +FORK_NAME="Parchment" +API_REPO="" +SERVER_REPO="" +PAPER_API_REPO="" +PAPER_SERVER_REPO="" +MCDEV_REPO="" +# END config + +sourceBase=$(dirname $SOURCE)/../ +cd "${basedir:-$sourceBase}" + +basedir=$(pwd -P) +cd - + + +function bashColor { +if [ $2 ]; then + echo -e "\e[$1;$2m" +else + echo -e "\e[$1m" +fi +} +function bashColorReset { + echo -e "\e[m" +} + +function cleanupPatches { + cd "$1" + for patch in *.patch; do + gitver=$(tail -n 2 $patch | grep -ve "^$" | tail -n 1) + diffs=$(git diff --staged $patch | grep -E "^(\+|\-)" | grep -Ev "(From [a-z0-9]{32,}|\-\-\- a|\+\+\+ b|.index|Date\: )") + + testver=$(echo "$diffs" | tail -n 2 | grep -ve "^$" | tail -n 1 | grep "$gitver") + if [ "x$testver" != "x" ]; then + diffs=$(echo "$diffs" | tail -n +3) + fi + + if [ "x$diffs" == "x" ] ; then + git reset HEAD $patch >/dev/null + git checkout -- $patch >/dev/null + fi + done +} +function pushRepo { + if [ "$(git config minecraft.push-${FORK_NAME})" == "1" ]; then + echo "Pushing - $1 ($3) to $2" + ( + cd "$1" + git remote rm emc-push > /dev/null 2>&1 + git remote add emc-push $2 >/dev/null 2>&1 + git push emc-push $3 -f + ) + fi +} +function basedir { + cd "$basedir" +} +function gethead { + ( + cd "$1" + git log -1 --oneline + ) +} diff --git a/scripts/paperclip.sh b/scripts/paperclip.sh new file mode 100755 index 0000000..060d863 --- /dev/null +++ b/scripts/paperclip.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Copied from https://github.com/PaperMC/Paper/blob/d54ce6c17fb7a35238d6b9f734d30a4289886773/scripts/paperclip.sh +# License from Paper applies to this file + +( +set -e +basedir="$(cd "$1" && pwd -P)" +workdir="$basedir/Paper/work" +mcver=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) +paperjar="$basedir/Parchment-Server/target/parchment-$mcver.jar" +vanillajar="$workdir/Minecraft/$mcver/$mcver.jar" + +( + cd "$workdir/Paperclip" + mvn clean package "-Dmcver=$mcver" "-Dpaperjar=$paperjar" "-Dvanillajar=$vanillajar" +) +cp "$workdir/Paperclip/assembly/target/paperclip-${mcver}.jar" "$basedir/parchment-paperclip.jar" + +echo "" +echo "" +echo "" +echo "Build success!" +echo "Copied final jar to $(cd "$basedir" && pwd -P)/parchment-paperclip.jar" +) || exit 1 diff --git a/scripts/push.sh b/scripts/push.sh new file mode 100755 index 0000000..ed4bf9f --- /dev/null +++ b/scripts/push.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# get base dir regardless of execution location +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh + +minecraftversion=$(cat $basedir/Paper/work/BuildData/info.json | grep minecraftVersion | cut -d '"' -f 4) + +basedir +pushRepo ${FORK_NAME}-API $API_REPO master:$minecraftversion +pushRepo ${FORK_NAME}-Server $SERVER_REPO master:$minecraftversion diff --git a/scripts/rebuildpatches.sh b/scripts/rebuildpatches.sh new file mode 100755 index 0000000..e09a74d --- /dev/null +++ b/scripts/rebuildpatches.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# get base dir regardless of execution location +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh + +PS1="$" +echo "Rebuilding patch files from current fork state..." +function savePatches { + what=$1 + cd $basedir/$what/ + + mkdir -p $basedir/patches/$2 + if [ -d ".git/rebase-apply" ]; then + # in middle of a rebase, be smarter + echo "REBASE DETECTED - PARTIAL SAVE" + last=$(cat ".git/rebase-apply/last") + next=$(cat ".git/rebase-apply/next") + declare -a files=("$basedir/patches/$2/"*.patch) + for i in $(seq -f "%04g" 1 1 $last) + do + if [ $i -lt $next ]; then + rm "${files[`expr $i - 1`]}" + fi + done + else + rm $basedir/patches/$2/*.patch + fi + + git format-patch --no-signature --zero-commit --full-index --no-stat -N -o $basedir/patches/$2 upstream/upstream + cd $basedir + git add -A $basedir/patches/$2 + echo " Patches saved for $what to patches/$2" +} + +savePatches ${FORK_NAME}-API api +savePatches ${FORK_NAME}-Server server + +$basedir/scripts/push.sh diff --git a/scripts/upstream.sh b/scripts/upstream.sh new file mode 100755 index 0000000..2f434d3 --- /dev/null +++ b/scripts/upstream.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# get base dir regardless of execution location +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +. $(dirname $SOURCE)/init.sh + +git submodule update --init --recursive + +if [[ "$1" == up* ]]; then + ( + cd "$basedir/Paper/" + git fetch && git reset --hard origin/master + cd ../ + git add Paper + ) +fi + +paperVer=$(gethead Paper) +cd "$basedir/Paper/" + +./paper patch + +cd "Paper-Server" +mcVer=$(mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=minecraft_version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }') + +basedir +. "$basedir"/scripts/importmcdev.sh + +minecraftversion=$(cat "$basedir"/Paper/work/BuildData/info.json | grep minecraftVersion | cut -d '"' -f 4) +version=$(echo -e "Paper: $paperVer\nmc-dev:$importedmcdev") +tag="${minecraftversion}-${mcVer}-$(echo -e $version | shasum | awk '{print $1}')" +echo "$tag" > "$basedir"/current-paper + +"$basedir"/scripts/generatesources.sh + +cd Paper/ + +function tag { +( + cd $1 + if [ "$2" == "1" ]; then + git tag -d "$tag" 2>/dev/null + fi + echo -e "$(date)\n\n$version" | git tag -a "$tag" -F - 2>/dev/null +) +} +echo "Tagging as $tag" +echo -e "$version" + +forcetag=0 +if [ "$(cat "$basedir"/current-paper)" != "$tag" ]; then + forcetag=1 +fi + +tag Paper-API $forcetag +tag Paper-Server $forcetag + +pushRepo Paper-API $PAPER_API_REPO $tag +pushRepo Paper-Server $PAPER_SERVER_REPO $tag + diff --git a/scripts/upstreamCommit.sh b/scripts/upstreamCommit.sh new file mode 100755 index 0000000..c68788f --- /dev/null +++ b/scripts/upstreamCommit.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +( +set -e +PS1="$" + +function changelog() { + base=$(git ls-tree HEAD $1 | cut -d' ' -f3 | cut -f1) + cd $1 && git log --oneline ${base}...HEAD +} +paper=$(changelog Paper) + +updated="" +logsuffix="" +if [ ! -z "$paper" ]; then + logsuffix="$logsuffix\n\nPaper Changes:\n$paper" + if [ -z "$updated" ]; then updated="Paper"; else updated="$updated/Paper"; fi +fi +disclaimer="Upstream has released updates that appears to apply and compile correctly" + +if [ ! -z "$1" ]; then + disclaimer="$@" +fi + +log="${UP_LOG_PREFIX}Updated Upstream ($updated)\n\n${disclaimer}${logsuffix}" + +echo -e "$log" | git commit -F - + +) || exit 1 \ No newline at end of file