├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── Waterfall-Proxy-Patches ├── 0001-Change-brand-to-lightfall.patch ├── 0002-Modern-forge-support.patch ├── 0003-Queue-packets-during-handshake.patch ├── 0004-Wrap-modded-command-arguments.patch ├── 0005-Accept-all-suggestion-types.patch └── 0006-Implement-ModernFMLHandshakeEvent.patch ├── lightfall ├── pom.xml └── scripts ├── applyPatches.sh ├── build.sh ├── edit.sh ├── mergeUpstream.sh ├── rebuildPatches.sh ├── upstreamCommit.sh └── wigglePatch.py /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build lightfall 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Set up JDK 1.8 19 | uses: actions/setup-java@v1 20 | with: 21 | java-version: 1.8 22 | - name: Build with Maven 23 | run: | 24 | git config --global user.name "GitHub Actions" 25 | git submodule update --recursive --init 26 | ./scripts/applyPatches.sh 27 | mvn -B clean package "-Dbuild.number=$GITHUB_RUN_NUMBER" 28 | - name: Upload Artifact 29 | uses: actions/upload-artifact@v2 30 | with: 31 | name: lightfall jars 32 | path: ./lightfall-proxy/bootstrap/target/lightfall.jar 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,linux,windows,intellij,eclipse,netbeans,maven 3 | 4 | ### macOS ### 5 | *.DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | # Thumbnails 12 | ._* 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | 28 | 29 | ### Linux ### 30 | *~ 31 | 32 | # temporary files which can be created if a process still has a handle open of a deleted file 33 | .fuse_hidden* 34 | 35 | # KDE directory preferences 36 | .directory 37 | 38 | # Linux trash folder which might appear on any partition or disk 39 | .Trash-* 40 | 41 | # .nfs files are created when an open file is removed but is still being accessed 42 | .nfs* 43 | 44 | 45 | ### Windows ### 46 | # Windows image file caches 47 | Thumbs.db 48 | ehthumbs.db 49 | 50 | # Folder config file 51 | Desktop.ini 52 | 53 | # Recycle Bin used on file shares 54 | $RECYCLE.BIN/ 55 | 56 | # Windows Installer files 57 | *.cab 58 | *.msi 59 | *.msm 60 | *.msp 61 | 62 | # Windows shortcuts 63 | *.lnk 64 | 65 | 66 | ### Intellij ### 67 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 68 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 69 | 70 | # User-specific stuff: 71 | .idea/workspace.xml 72 | .idea/tasks.xml 73 | 74 | # Sensitive or high-churn files: 75 | .idea/dataSources/ 76 | .idea/dataSources.ids 77 | .idea/dataSources.xml 78 | .idea/dataSources.local.xml 79 | .idea/sqlDataSources.xml 80 | .idea/dynamic.xml 81 | .idea/uiDesigner.xml 82 | 83 | # Gradle: 84 | .idea/gradle.xml 85 | .idea/libraries 86 | 87 | # Mongo Explorer plugin: 88 | .idea/mongoSettings.xml 89 | 90 | ## File-based project format: 91 | *.iws 92 | 93 | ## Plugin-specific files: 94 | 95 | # IntelliJ 96 | /out/ 97 | 98 | # mpeltonen/sbt-idea plugin 99 | .idea_modules/ 100 | 101 | # JIRA plugin 102 | atlassian-ide-plugin.xml 103 | 104 | # Crashlytics plugin (for Android Studio and IntelliJ) 105 | com_crashlytics_export_strings.xml 106 | crashlytics.properties 107 | crashlytics-build.properties 108 | fabric.properties 109 | 110 | ### Intellij Patch ### 111 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 112 | 113 | # *.iml 114 | # modules.xml 115 | # .idea/misc.xml 116 | # *.ipr 117 | 118 | 119 | ### Eclipse ### 120 | 121 | .metadata 122 | bin/ 123 | tmp/ 124 | *.tmp 125 | *.bak 126 | *.swp 127 | *~.nib 128 | local.properties 129 | .settings/ 130 | .loadpath 131 | .recommenders 132 | 133 | # Eclipse Core 134 | .project 135 | 136 | # External tool builders 137 | .externalToolBuilders/ 138 | 139 | # Locally stored "Eclipse launch configurations" 140 | *.launch 141 | 142 | # PyDev specific (Python IDE for Eclipse) 143 | *.pydevproject 144 | 145 | # CDT-specific (C/C++ Development Tooling) 146 | .cproject 147 | 148 | # JDT-specific (Eclipse Java Development Tools) 149 | .classpath 150 | 151 | # Java annotation processor (APT) 152 | .factorypath 153 | 154 | # PDT-specific (PHP Development Tools) 155 | .buildpath 156 | 157 | # sbteclipse plugin 158 | .target 159 | 160 | # Tern plugin 161 | .tern-project 162 | 163 | # TeXlipse plugin 164 | .texlipse 165 | 166 | # STS (Spring Tool Suite) 167 | .springBeans 168 | 169 | # Code Recommenders 170 | .recommenders/ 171 | 172 | 173 | ### NetBeans ### 174 | nbproject/private/ 175 | build/ 176 | nbbuild/ 177 | dist/ 178 | nbdist/ 179 | .nb-gradle/ 180 | 181 | 182 | ### Maven ### 183 | target/ 184 | pom.xml.tag 185 | pom.xml.releaseBackup 186 | pom.xml.versionsBackup 187 | pom.xml.next 188 | release.properties 189 | dependency-reduced-pom.xml 190 | buildNumber.properties 191 | .mvn/timing.properties 192 | 193 | # Exclude maven wrapper 194 | !/.mvn/wrapper/maven-wrapper.jar 195 | 196 | 197 | ### Waterfall Extras ### 198 | Waterfall-Proxy/ 199 | run/ 200 | 201 | # Because Github lost their minds 202 | .idea/ 203 | *.iml 204 | lightfall-proxy 205 | 206 | # intellij 207 | *.ipr 208 | out/ 209 | logs/ 210 | config.yml 211 | waterfall.yml 212 | modules 213 | plugins 214 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Waterfall"] 2 | path = Waterfall 3 | url = https://github.com/WaterfallMC/Waterfall.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 IzzelAliz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## lightfall 2 | 3 | A fork of Waterfall with modern forge support. 4 | 5 | ### Usage 6 | 7 | 1. Run lightfall as a BungeeCord server, downloads available [here](https://github.com/ArclightPowered/lightfall/releases) (lightfall is version independent, use latest) 8 | 2. Do all configuration 9 | 3. Enable `bungeecord` in `spigot.yml` in all Arclight servers 10 | 4. (Optionally) enable `ip-forward` in lightfall `config.yml` 11 | 5. (Optionally) enable `disable_entity_metadata_rewrite` in `waterfall.yml` 12 | 6. Install [lightfallclient](https://github.com/ArclightPowered/lightfall-client/releases) in client -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0001-Change-brand-to-lightfall.patch: -------------------------------------------------------------------------------- 1 | From 5b4d23ec2279ae713fc3b65898ec4fa6e4f9125f Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Sun, 7 Mar 2021 19:26:00 +0800 4 | Subject: [PATCH] Change brand to lightfall 5 | 6 | 7 | diff --git a/api/pom.xml b/api/pom.xml 8 | index 3cd57d98..23d08d27 100644 9 | --- a/api/pom.xml 10 | +++ b/api/pom.xml 11 | @@ -4,42 +4,47 @@ 12 | 4.0.0 13 | 14 | 15 | - io.github.waterfallmc 16 | - waterfall-parent 17 | - 1.20-R0.2-SNAPSHOT 18 | + io.izzel.lightfall 19 | + lightfall-parent 20 | + 1.20-R0.2-SNAPSHOT 21 | ../pom.xml 22 | 23 | 24 | - io.github.waterfallmc 25 | waterfall-api 26 | 1.20-R0.2-SNAPSHOT 27 | jar 28 | 29 | - Waterfall-API 30 | + lightfall-API 31 | API implemented by the Elastic Portal Suite 32 | 33 | + 34 | + 35 | + IzzelAliz 36 | + https://maven.izzel.io/releases 37 | + 38 | + 39 | 40 | 41 | - io.github.waterfallmc 42 | - waterfall-chat 43 | + io.izzel.lightfall 44 | + lightfall-chat 45 | ${project.version} 46 | compile 47 | 48 | 49 | - io.github.waterfallmc 50 | - waterfall-config 51 | + io.izzel.lightfall 52 | + lightfall-config 53 | ${project.version} 54 | compile 55 | 56 | 57 | - io.github.waterfallmc 58 | - waterfall-event 59 | + io.izzel.lightfall 60 | + lightfall-event 61 | ${project.version} 62 | compile 63 | 64 | 65 | - io.github.waterfallmc 66 | - waterfall-protocol 67 | + io.izzel.lightfall 68 | + lightfall-protocol 69 | ${project.version} 70 | compile 71 | 72 | @@ -75,5 +80,11 @@ 73 | 2.2 74 | compile 75 | 76 | + 77 | + 78 | + io.izzel.lightfall 79 | + lightfall-api 80 | + 1.0.0 81 | + 82 | 83 | 84 | diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml 85 | index 7fbac761..5ecb4452 100644 86 | --- a/bootstrap/pom.xml 87 | +++ b/bootstrap/pom.xml 88 | @@ -4,19 +4,18 @@ 89 | 4.0.0 90 | 91 | 92 | - io.github.waterfallmc 93 | - waterfall-parent 94 | + io.izzel.lightfall 95 | + lightfall-parent 96 | 1.20-R0.2-SNAPSHOT 97 | ../pom.xml 98 | 99 | 100 | - io.github.waterfallmc 101 | - waterfall-bootstrap 102 | + lightfall-bootstrap 103 | 1.20-R0.2-SNAPSHOT 104 | jar 105 | 106 | - Waterfall-Bootstrap 107 | - Java 1.6 loader for Waterfall 108 | + lightfall-Bootstrap 109 | + Java 1.6 loader for lightfall 110 | 111 | 112 | true 113 | @@ -29,15 +28,15 @@ 114 | 115 | 116 | 117 | - io.github.waterfallmc 118 | - waterfall-proxy 119 | + io.izzel.lightfall 120 | + lightfall-proxy 121 | ${project.version} 122 | compile 123 | 124 | 125 | 126 | 127 | - Waterfall 128 | + lightfall 129 | 130 | 131 | org.apache.maven.plugins 132 | diff --git a/bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java b/bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java 133 | index a4516ed9..1bb5dbce 100644 134 | --- a/bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java 135 | +++ b/bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java 136 | @@ -7,7 +7,7 @@ public class Bootstrap 137 | { 138 | if ( Float.parseFloat( System.getProperty( "java.class.version" ) ) < 52.0 ) 139 | { 140 | - System.err.println( "*** ERROR *** Waterfall requires Java 8 or above to function! Please download and install it!" ); 141 | + System.err.println( "*** ERROR *** lightfall requires Java 8 or above to function! Please download and install it!" ); 142 | System.out.println( "You can check your Java version with the command: java -version" ); 143 | return; 144 | } 145 | diff --git a/chat/pom.xml b/chat/pom.xml 146 | index 2aa2ad55..2ac8e2a6 100644 147 | --- a/chat/pom.xml 148 | +++ b/chat/pom.xml 149 | @@ -4,18 +4,17 @@ 150 | 4.0.0 151 | 152 | 153 | - io.github.waterfallmc 154 | - waterfall-parent 155 | + io.izzel.lightfall 156 | + lightfall-parent 157 | 1.20-R0.2-SNAPSHOT 158 | ../pom.xml 159 | 160 | 161 | - io.github.waterfallmc 162 | - waterfall-chat 163 | + lightfall-chat 164 | 1.20-R0.2-SNAPSHOT 165 | jar 166 | 167 | - Waterfall-Chat 168 | + lightfall-Chat 169 | Minecraft JSON chat API intended for use with Waterfall 170 | 171 | 172 | diff --git a/config/pom.xml b/config/pom.xml 173 | index 058e6fa8..7865bcf5 100644 174 | --- a/config/pom.xml 175 | +++ b/config/pom.xml 176 | @@ -4,18 +4,17 @@ 177 | 4.0.0 178 | 179 | 180 | - io.github.waterfallmc 181 | - waterfall-parent 182 | + io.izzel.lightfall 183 | + lightfall-parent 184 | 1.20-R0.2-SNAPSHOT 185 | ../pom.xml 186 | 187 | 188 | - io.github.waterfallmc 189 | - waterfall-config 190 | + lightfall-config 191 | 1.20-R0.2-SNAPSHOT 192 | jar 193 | 194 | - Waterfall-Config 195 | + lightfall-Config 196 | Generic java configuration API intended for use with Waterfall 197 | 198 | 199 | diff --git a/event/pom.xml b/event/pom.xml 200 | index 316f1e35..a38b6d54 100644 201 | --- a/event/pom.xml 202 | +++ b/event/pom.xml 203 | @@ -4,17 +4,16 @@ 204 | 4.0.0 205 | 206 | 207 | - io.github.waterfallmc 208 | - waterfall-parent 209 | + io.izzel.lightfall 210 | + lightfall-parent 211 | 1.20-R0.2-SNAPSHOT 212 | ../pom.xml 213 | 214 | 215 | - io.github.waterfallmc 216 | - waterfall-event 217 | + lightfall-event 218 | 1.20-R0.2-SNAPSHOT 219 | jar 220 | 221 | - Waterfall-Event 222 | - Generic java event dispatching API intended for use with Waterfall. 223 | + lightfall-Event 224 | + Generic java event dispatching API intended for use with lightfall. 225 | 226 | diff --git a/log/pom.xml b/log/pom.xml 227 | index 9ee30d66..d2da305a 100644 228 | --- a/log/pom.xml 229 | +++ b/log/pom.xml 230 | @@ -4,18 +4,17 @@ 231 | 4.0.0 232 | 233 | 234 | - io.github.waterfallmc 235 | - waterfall-parent 236 | + io.izzel.lightfall 237 | + lightfall-parent 238 | 1.20-R0.2-SNAPSHOT 239 | ../pom.xml 240 | 241 | 242 | - io.github.waterfallmc 243 | - waterfall-log 244 | + lightfall-log 245 | 1.20-R0.2-SNAPSHOT 246 | jar 247 | 248 | - Waterfall-Log 249 | + lightfall-Log 250 | Simplistic and performant java.util.Logger based logger and console API designed for use with Waterfall and Minecraft related applications. 251 | 252 | 253 | @@ -26,8 +25,8 @@ 254 | compile 255 | 256 | 257 | - io.github.waterfallmc 258 | - waterfall-chat 259 | + io.izzel.lightfall 260 | + lightfall-chat 261 | ${project.version} 262 | compile 263 | 264 | diff --git a/log4j/pom.xml b/log4j/pom.xml 265 | index 6d20191e..f75e7bf9 100644 266 | --- a/log4j/pom.xml 267 | +++ b/log4j/pom.xml 268 | @@ -3,18 +3,17 @@ 269 | 4.0.0 270 | 271 | 272 | - io.github.waterfallmc 273 | - waterfall-parent 274 | + io.izzel.lightfall 275 | + lightfall-parent 276 | 1.20-R0.2-SNAPSHOT 277 | ../pom.xml 278 | 279 | 280 | - io.github.waterfallmc 281 | - waterfall-log4j 282 | + lightfall-log4j 283 | 1.20-R0.2-SNAPSHOT 284 | jar 285 | 286 | - Waterfall-Log4J 287 | + lightfall-log4j 288 | Simplistic and performant Log4j2 based logger and console API designed for use with Waterfall and Minecraft related applications. 289 | 290 | 291 | diff --git a/module/pom.xml b/module/pom.xml 292 | index d78c9a25..0917140d 100644 293 | --- a/module/pom.xml 294 | +++ b/module/pom.xml 295 | @@ -4,8 +4,8 @@ 296 | 4.0.0 297 | 298 | 299 | - io.github.waterfallmc 300 | - waterfall-parent 301 | + io.izzel.lightfall 302 | + lightfall-parent 303 | 1.20-R0.2-SNAPSHOT 304 | ../pom.xml 305 | 306 | @@ -15,7 +15,7 @@ 307 | 1.20-R0.2-SNAPSHOT 308 | pom 309 | 310 | - Waterfall Modules 311 | + lightfall Modules 312 | Parent project for all Waterfall modules. 313 | 314 | 315 | @@ -36,7 +36,7 @@ 316 | 317 | 318 | 319 | - io.github.waterfallmc 320 | + io.izzel.lightfall 321 | waterfall-api 322 | ${project.version} 323 | compile 324 | diff --git a/native/pom.xml b/native/pom.xml 325 | index 5e9d29d7..d81d9cfa 100644 326 | --- a/native/pom.xml 327 | +++ b/native/pom.xml 328 | @@ -4,18 +4,17 @@ 329 | 4.0.0 330 | 331 | 332 | - io.github.waterfallmc 333 | - waterfall-parent 334 | + io.izzel.lightfall 335 | + lightfall-parent 336 | 1.20-R0.2-SNAPSHOT 337 | ../pom.xml 338 | 339 | 340 | - io.github.waterfallmc 341 | - waterfall-native 342 | + lightfall-native 343 | 1.20-R0.2-SNAPSHOT 344 | jar 345 | 346 | - Waterfall-Native 347 | + lightfall-Native 348 | Optional native code to speed up and enhance Waterfall functionality. 349 | 350 | 351 | diff --git a/pom.xml b/pom.xml 352 | index 0c04b87a..2117d732 100644 353 | --- a/pom.xml 354 | +++ b/pom.xml 355 | @@ -4,24 +4,23 @@ 356 | 4.0.0 357 | 358 | 359 | - io.github.waterfallmc 360 | - waterfall-super 361 | + io.izzel.lightfall 362 | + lightfall-super 363 | dev-SNAPSHOT 364 | ../pom.xml 365 | 366 | 367 | - io.github.waterfallmc 368 | - waterfall-parent 369 | + lightfall-parent 370 | 1.20-R0.2-SNAPSHOT 371 | pom 372 | 373 | - Waterfall-Parent 374 | - Parent project for all Waterfall modules. 375 | - https://github.com/WaterfallMC/Waterfall 376 | - 2015 377 | + lightfall-Parent 378 | + Parent project for all lightfall modules. 379 | + https://github.com/ArclightPowered/lightfall 380 | + 2022 381 | 382 | - WaterfallMC 383 | - https://github.com/WaterfallMC 384 | + ArclightPowered 385 | + https://github.com/ArclightPowered 386 | 387 | 388 | 389 | @@ -47,6 +46,9 @@ 390 | 391 | fuzzybot 392 | 393 | + 394 | + IzzelAliz 395 | + 396 | 397 | 398 | 399 | @@ -66,13 +68,13 @@ 400 | 401 | 402 | 403 | - scm:git:git@github.com:com:WaterfallMC/Waterfall.git 404 | - scm:git:git@github.com:WaterfallMC/Waterfall.git 405 | - git@github.com:WaterfallMC/Waterfall.git 406 | + scm:git:git@github.com:com:ArclightPowered/lightfall.git 407 | + scm:git:git@github.com:ArclightPowered/lightfall.git 408 | + git@github.com:ArclightPowered/lightfall.git 409 | 410 | 411 | GitHub 412 | - https://github.com/PaperMC/Waterfall/issues 413 | + https://github.com/ArclightPowered/lightfall/issues 414 | 415 | 416 | 417 | diff --git a/protocol/pom.xml b/protocol/pom.xml 418 | index 76a3510d..549cbf87 100644 419 | --- a/protocol/pom.xml 420 | +++ b/protocol/pom.xml 421 | @@ -4,18 +4,17 @@ 422 | 4.0.0 423 | 424 | 425 | - io.github.waterfallmc 426 | - waterfall-parent 427 | + io.izzel.lightfall 428 | + lightfall-parent 429 | 1.20-R0.2-SNAPSHOT 430 | ../pom.xml 431 | 432 | 433 | - io.github.waterfallmc 434 | - waterfall-protocol 435 | + lightfall-protocol 436 | 1.20-R0.2-SNAPSHOT 437 | jar 438 | 439 | - Waterfall-Protocol 440 | + lightfall-Protocol 441 | Minimal implementation of the Minecraft protocol for use in Waterfall 442 | 443 | 444 | @@ -35,8 +34,8 @@ 445 | compile 446 | 447 | 448 | - io.github.waterfallmc 449 | - waterfall-chat 450 | + io.izzel.lightfall 451 | + lightfall-chat 452 | ${project.version} 453 | compile 454 | 455 | diff --git a/proxy/pom.xml b/proxy/pom.xml 456 | index 9be9aa22..897a8ed9 100644 457 | --- a/proxy/pom.xml 458 | +++ b/proxy/pom.xml 459 | @@ -4,18 +4,17 @@ 460 | 4.0.0 461 | 462 | 463 | - io.github.waterfallmc 464 | - waterfall-parent 465 | + io.izzel.lightfall 466 | + lightfall-parent 467 | 1.20-R0.2-SNAPSHOT 468 | ../pom.xml 469 | 470 | 471 | - io.github.waterfallmc 472 | - waterfall-proxy 473 | + lightfall-proxy 474 | 1.20-R0.2-SNAPSHOT 475 | jar 476 | 477 | - Waterfall-Proxy 478 | + lightfall-Proxy 479 | Proxy component of the Elastic Portal Suite 480 | 481 | 482 | @@ -64,32 +63,32 @@ 483 | compile 484 | 485 | 486 | - io.github.waterfallmc 487 | + io.izzel.lightfall 488 | waterfall-api 489 | ${project.version} 490 | compile 491 | 492 | 493 | - io.github.waterfallmc 494 | - waterfall-log4j 495 | + io.izzel.lightfall 496 | + lightfall-log4j 497 | ${project.version} 498 | compile 499 | 500 | 501 | - io.github.waterfallmc 502 | - waterfall-native 503 | + io.izzel.lightfall 504 | + lightfall-native 505 | ${project.version} 506 | compile 507 | 508 | 509 | - io.github.waterfallmc 510 | - waterfall-protocol 511 | + io.izzel.lightfall 512 | + lightfall-protocol 513 | ${project.version} 514 | compile 515 | 516 | 517 | - io.github.waterfallmc 518 | - waterfall-query 519 | + io.izzel.lightfall 520 | + lightfall-query 521 | ${project.version} 522 | compile 523 | 524 | diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java 525 | index 01c8a172..f508961e 100644 526 | --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java 527 | +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java 528 | @@ -545,7 +545,7 @@ public class BungeeCord extends ProxyServer 529 | @Override 530 | public String getName() 531 | { 532 | - return "Waterfall"; 533 | + return "lightfall"; 534 | } 535 | 536 | @Override 537 | diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java 538 | index 96a9998d..9c36927b 100644 539 | --- a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java 540 | +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java 541 | @@ -63,7 +63,7 @@ public class BungeeCordLauncher 542 | 543 | BungeeCord bungee = new BungeeCord(); 544 | ProxyServer.setInstance( bungee ); 545 | - bungee.getLogger().info( "Enabled Waterfall version " + bungee.getVersion() ); 546 | + bungee.getLogger().info( "Enabled lightfall version " + bungee.getVersion() ); 547 | bungee.start(); 548 | 549 | if ( !options.has( "noconsole" ) ) 550 | diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java 551 | index b26035cf..d7d0ed58 100644 552 | --- a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java 553 | +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java 554 | @@ -16,6 +16,6 @@ public class CommandBungee extends Command 555 | @Override 556 | public void execute(CommandSender sender, String[] args) 557 | { 558 | - sender.sendMessage( ChatColor.BLUE + "This server is running Waterfall version " + ProxyServer.getInstance().getVersion() + " by md_5" ); 559 | + sender.sendMessage( ChatColor.BLUE + "This server is running lightfall version " + ProxyServer.getInstance().getVersion() + " by md_5" ); 560 | } 561 | } 562 | diff --git a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java 563 | index f6b5e8b8..98a175e6 100644 564 | --- a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java 565 | +++ b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java 566 | @@ -227,7 +227,7 @@ public class YamlConfig implements ConfigurationAdapter 567 | Map val = entry.getValue(); 568 | String name = entry.getKey(); 569 | String addr = get( "address", "localhost:25565", val ); 570 | - String motd = ChatColor.translateAlternateColorCodes( '&', get( "motd", "&1Just another Waterfall - Forced Host", val ) ); 571 | + String motd = ChatColor.translateAlternateColorCodes( '&', get( "motd", "&1This server has super lightfall power - Forced Host", val ) ); 572 | boolean restricted = get( "restricted", false, val ); 573 | SocketAddress address = Util.getAddr( addr ); 574 | ServerInfo info = ProxyServer.getInstance().constructServerInfo( name, address, motd, restricted ); 575 | diff --git a/proxy/src/main/java/net/md_5/bungee/module/JenkinsModuleSource.java b/proxy/src/main/java/net/md_5/bungee/module/JenkinsModuleSource.java 576 | index 5bb86152..ca9faa28 100644 577 | --- a/proxy/src/main/java/net/md_5/bungee/module/JenkinsModuleSource.java 578 | +++ b/proxy/src/main/java/net/md_5/bungee/module/JenkinsModuleSource.java 579 | @@ -22,7 +22,7 @@ public class JenkinsModuleSource implements ModuleSource 580 | "https://api.papermc.io/v2/projects/%1$s/versions/%2$s/builds/%3$s/downloads/%4$s-%2$s-%3$s.jar", 581 | "waterfall", 582 | net.md_5.bungee.api.ProxyServer.getInstance().getVersion().split(":")[2].split("-")[0], 583 | - version.getBuild(), 584 | + 558, 585 | module.getName() 586 | ); 587 | URL website = new URL( url ); 588 | diff --git a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java 589 | index d3abee44..f7aaf001 100644 590 | --- a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java 591 | +++ b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java 592 | @@ -124,7 +124,7 @@ public class ModuleManager 593 | { 594 | ModuleVersion moduleVersion = ( module.getFile().exists() ) ? getVersion( module.getFile() ) : null; 595 | 596 | - if ( !bungeeVersion.equals( moduleVersion ) ) 597 | + if ( moduleVersion == null && !bungeeVersion.equals( moduleVersion ) ) // lightfall 598 | { 599 | System.out.println( "Attempting to update plugin from " + moduleVersion + " to " + bungeeVersion ); 600 | module.getProvider().retrieve( module, bungeeVersion ); 601 | diff --git a/query/pom.xml b/query/pom.xml 602 | index 4e9bd6cc..fb9dc20f 100644 603 | --- a/query/pom.xml 604 | +++ b/query/pom.xml 605 | @@ -4,18 +4,17 @@ 606 | 4.0.0 607 | 608 | 609 | - io.github.waterfallmc 610 | - waterfall-parent 611 | + io.izzel.lightfall 612 | + lightfall-parent 613 | 1.20-R0.2-SNAPSHOT 614 | ../pom.xml 615 | 616 | 617 | - io.github.waterfallmc 618 | - waterfall-query 619 | + lightfall-query 620 | 1.20-R0.2-SNAPSHOT 621 | jar 622 | 623 | - Waterfall-Query 624 | + lightfall-Query 625 | Minecraft query implementation based on the Waterfall API. 626 | 627 | 628 | @@ -25,7 +24,7 @@ 629 | compile 630 | 631 | 632 | - io.github.waterfallmc 633 | + io.izzel.lightfall 634 | waterfall-api 635 | ${project.version} 636 | compile 637 | -- 638 | 2.36.1.windows.1 639 | 640 | -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0002-Modern-forge-support.patch: -------------------------------------------------------------------------------- 1 | From 1719ed1ffccc9ae562d360f90a56f9cf6097b7fd Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Sun, 7 Mar 2021 22:24:56 +0800 4 | Subject: [PATCH] Modern forge support 5 | 6 | 7 | diff --git a/api/src/main/java/net/md_5/bungee/api/ServerPing.java b/api/src/main/java/net/md_5/bungee/api/ServerPing.java 8 | index 29cd91dd..d8242958 100644 9 | --- a/api/src/main/java/net/md_5/bungee/api/ServerPing.java 10 | +++ b/api/src/main/java/net/md_5/bungee/api/ServerPing.java 11 | @@ -3,6 +3,8 @@ package net.md_5.bungee.api; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.UUID; 15 | + 16 | +import com.google.gson.JsonObject; 17 | import lombok.AllArgsConstructor; 18 | import lombok.Data; 19 | import lombok.NoArgsConstructor; 20 | @@ -101,6 +103,7 @@ public class ServerPing 21 | // Right now, we don't get the mods from the user, so we just use a stock ModInfo object to 22 | // create the server ping. Vanilla clients will ignore this. 23 | private final ModInfo modinfo = new ModInfo(); 24 | + private final JsonObject forgeData = null; // lightfall - modern forge ping data 25 | 26 | @Deprecated 27 | public ServerPing(Protocol version, Players players, String description, String favicon) 28 | diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java 29 | index 91f71c09..be62a708 100644 30 | --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java 31 | +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java 32 | @@ -45,7 +45,7 @@ public class PluginMessage extends DefinedPacket 33 | return tag; 34 | } 35 | 36 | - return "legacy:" + tag.toLowerCase( Locale.ROOT ); 37 | + return "legacy:" + tag.toLowerCase( Locale.ROOT ).replace("|", ""); // Lightfall - remove illegal characters 38 | } 39 | }; 40 | 41 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeClientHandler.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeClientHandler.java 42 | new file mode 100644 43 | index 00000000..7a4a0317 44 | --- /dev/null 45 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeClientHandler.java 46 | @@ -0,0 +1,16 @@ 47 | +package io.izzel.lightfall.forge; 48 | + 49 | +import lombok.NonNull; 50 | +import net.md_5.bungee.UserConnection; 51 | +import net.md_5.bungee.forge.ForgeClientHandler; 52 | + 53 | +public class ModernForgeClientHandler extends ForgeClientHandler { 54 | + 55 | + public ModernForgeClientHandler(@NonNull UserConnection con) { 56 | + super(con); 57 | + } 58 | + 59 | + @Override 60 | + public void resetHandshake() { 61 | + } 62 | +} 63 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 64 | new file mode 100644 65 | index 00000000..1713e7d5 66 | --- /dev/null 67 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 68 | @@ -0,0 +1,120 @@ 69 | +package io.izzel.lightfall.forge; 70 | + 71 | +import com.google.common.base.Preconditions; 72 | +import lombok.Getter; 73 | +import net.md_5.bungee.BungeeServerInfo; 74 | +import net.md_5.bungee.ServerConnector; 75 | +import net.md_5.bungee.UserConnection; 76 | +import net.md_5.bungee.api.ProxyServer; 77 | +import net.md_5.bungee.connection.UpstreamBridge; 78 | +import net.md_5.bungee.forge.ForgeConstants; 79 | +import net.md_5.bungee.netty.ChannelWrapper; 80 | +import net.md_5.bungee.netty.HandlerBoss; 81 | +import net.md_5.bungee.protocol.PacketWrapper; 82 | +import net.md_5.bungee.protocol.Protocol; 83 | +import net.md_5.bungee.protocol.packet.EncryptionResponse; 84 | +import net.md_5.bungee.protocol.packet.Kick; 85 | +import net.md_5.bungee.protocol.packet.Login; 86 | +import net.md_5.bungee.protocol.packet.LoginPayloadRequest; 87 | +import net.md_5.bungee.protocol.packet.LoginSuccess; 88 | +import net.md_5.bungee.protocol.packet.PluginMessage; 89 | +import net.md_5.bungee.protocol.packet.SetCompression; 90 | + 91 | +import java.util.Queue; 92 | +import java.util.concurrent.ConcurrentLinkedQueue; 93 | + 94 | +public class ModernForgeServerConnector extends ServerConnector { 95 | + 96 | + enum State { 97 | + PLAIN, PENDING, ACK 98 | + } 99 | + 100 | + private final Queue pendingHandshakes = new ConcurrentLinkedQueue<>(); 101 | + @Getter 102 | + private volatile State thisState = State.PLAIN; 103 | + 104 | + public ModernForgeServerConnector(ProxyServer bungee, UserConnection user, BungeeServerInfo target) { 105 | + super(bungee, user, target); 106 | + } 107 | + 108 | + @Override 109 | + public boolean shouldHandle(PacketWrapper packet) throws Exception { 110 | + return user.isConnected() && (thisState != State.PLAIN ? 111 | + (packet.packet instanceof LoginPayloadRequest 112 | + || packet.packet instanceof SetCompression 113 | + || packet.packet instanceof LoginSuccess 114 | + || packet.packet instanceof EncryptionResponse 115 | + || packet.packet instanceof PluginMessage 116 | + || packet.packet instanceof Kick 117 | + ) : super.shouldHandle(packet)); 118 | + } 119 | + 120 | + @Override 121 | + public void connected(ChannelWrapper channel) throws Exception { 122 | + super.connected(channel); 123 | + } 124 | + 125 | + @Override 126 | + public void handle(LoginSuccess loginSuccess) throws Exception { 127 | + Preconditions.checkState(thisState != State.PENDING, "Not expecting PENDING"); 128 | + if (thisState == State.ACK) { 129 | + user.unsafe().sendPacket(loginSuccess); 130 | + user.getCh().setProtocol(Protocol.GAME); 131 | + user.getCh().getHandle().pipeline().get(HandlerBoss.class).setHandler(new UpstreamBridge(bungee, user)); 132 | + thisState = State.PLAIN; 133 | + } 134 | + super.handle(loginSuccess); 135 | + } 136 | + 137 | + @Override 138 | + public void handle(Login login) throws Exception { 139 | + super.handle(login); 140 | + } 141 | + 142 | + @Override 143 | + public void handle(LoginPayloadRequest request) { 144 | + switch (thisState) { 145 | + case PLAIN: { 146 | + user.setForgeServerHandler(getHandshakeHandler()); 147 | + user.getCh().getHandle().flush(); 148 | + user.getCh().write(ForgeConstants.MODERN_FML_RESET); 149 | + user.getCh().setProtocol(Protocol.LOGIN); 150 | + user.getCh().getHandle().pipeline().get(HandlerBoss.class).setHandler(new ModernForgeUpstreamBridge(bungee, user, this)); 151 | + if (user.getServer() != null) { 152 | + user.getServer().setObsolete(true); 153 | + user.getServer().disconnect("Quiting"); 154 | + } 155 | + thisState = State.PENDING; 156 | + } 157 | + case PENDING: { 158 | + this.pendingHandshakes.add(request); 159 | + break; 160 | + } 161 | + case ACK: { 162 | + user.unsafe().sendPacket(request); 163 | + break; 164 | + } 165 | + } 166 | + } 167 | + 168 | + public void onResetAck() { 169 | + Preconditions.checkState(thisState == State.PENDING, "Not expecting PENDING"); 170 | + while (!pendingHandshakes.isEmpty()) { 171 | + user.unsafe().sendPacket(pendingHandshakes.poll()); 172 | + } 173 | + thisState = State.ACK; 174 | + } 175 | + 176 | + public ChannelWrapper getChannel() { 177 | + return this.ch; 178 | + } 179 | + 180 | + @Override 181 | + public String toString() { 182 | + if (thisState != State.PLAIN) { 183 | + return "[" + user.getName() + "|" + user.getAddress() + "] <-> Modern FML " + thisState + " [" + target.getName() + "]"; 184 | + } else { 185 | + return super.toString(); 186 | + } 187 | + } 188 | +} 189 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java 190 | new file mode 100644 191 | index 00000000..5e5432ec 192 | --- /dev/null 193 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java 194 | @@ -0,0 +1,71 @@ 195 | +package io.izzel.lightfall.forge; 196 | + 197 | +import io.netty.handler.timeout.ReadTimeoutException; 198 | +import lombok.RequiredArgsConstructor; 199 | +import net.md_5.bungee.BungeeCord; 200 | +import net.md_5.bungee.UserConnection; 201 | +import net.md_5.bungee.Util; 202 | +import net.md_5.bungee.api.ProxyServer; 203 | +import net.md_5.bungee.api.event.PlayerDisconnectEvent; 204 | +import net.md_5.bungee.netty.ChannelWrapper; 205 | +import net.md_5.bungee.netty.PacketHandler; 206 | +import net.md_5.bungee.protocol.PacketWrapper; 207 | +import net.md_5.bungee.protocol.Protocol; 208 | +import net.md_5.bungee.protocol.packet.LoginPayloadResponse; 209 | + 210 | +import java.nio.charset.StandardCharsets; 211 | +import java.util.Arrays; 212 | + 213 | +@RequiredArgsConstructor 214 | +public class ModernForgeUpstreamBridge extends PacketHandler { 215 | + 216 | + private final ProxyServer bungee; 217 | + private final UserConnection con; 218 | + private final ModernForgeServerConnector server; 219 | + 220 | + @Override 221 | + public boolean shouldHandle(PacketWrapper packet) throws Exception { 222 | + return packet.packet instanceof LoginPayloadResponse; 223 | + } 224 | + 225 | + @Override 226 | + public void handle(LoginPayloadResponse response) throws Exception { 227 | + if (isAckPacket(response)) { 228 | + server.onResetAck(); 229 | + } else { 230 | + con.getForgeServerHandler().getCh().write(response); 231 | + } 232 | + } 233 | + 234 | + @Override 235 | + public void exception(Throwable t) throws Exception { 236 | + if (server.getThisState() == ModernForgeServerConnector.State.PENDING) { 237 | + con.getCh().setProtocol(Protocol.GAME); 238 | + } 239 | + if (t instanceof ReadTimeoutException) { 240 | + con.disconnect("You need to install lightfall client mod to join this server!"); 241 | + } else { 242 | + con.disconnect(Util.exception(t)); 243 | + } 244 | + } 245 | + 246 | + @Override 247 | + public void disconnected(ChannelWrapper channel) throws Exception { 248 | + PlayerDisconnectEvent event = new PlayerDisconnectEvent(con); 249 | + bungee.getPluginManager().callEvent(event); 250 | + con.getTabListHandler().onDisconnect(); 251 | + server.getChannel().close(); 252 | + BungeeCord.getInstance().removeConnection(con); 253 | + } 254 | + 255 | + @Override 256 | + public String toString() { 257 | + return "[" + con.getAddress() + "|" + con.getName() + "] -> HS Upstream"; 258 | + } 259 | + 260 | + private static final byte[] RESET_ACK = "lightfall:ack".getBytes(StandardCharsets.UTF_8); 261 | + 262 | + private static boolean isAckPacket(LoginPayloadResponse response) { 263 | + return Arrays.equals(response.getData(), RESET_ACK); 264 | + } 265 | +} 266 | diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java 267 | index 9a22a1f7..fbfcd57e 100644 268 | --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java 269 | +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java 270 | @@ -66,10 +66,10 @@ import net.md_5.bungee.util.QuietException; 271 | public class ServerConnector extends PacketHandler 272 | { 273 | 274 | - private final ProxyServer bungee; 275 | - private ChannelWrapper ch; 276 | - private final UserConnection user; 277 | - private final BungeeServerInfo target; 278 | + protected final ProxyServer bungee; 279 | + protected ChannelWrapper ch; 280 | + protected final UserConnection user; 281 | + protected final BungeeServerInfo target; 282 | private State thisState = State.LOGIN_SUCCESS; 283 | @Getter 284 | private ForgeServerHandler handshakeHandler; 285 | diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java 286 | index 2f996a69..49a2d7bd 100644 287 | --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java 288 | +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java 289 | @@ -47,6 +47,8 @@ import net.md_5.bungee.entitymap.EntityMap; 290 | import net.md_5.bungee.forge.ForgeClientHandler; 291 | import net.md_5.bungee.forge.ForgeConstants; 292 | import net.md_5.bungee.forge.ForgeServerHandler; 293 | +import io.izzel.lightfall.forge.ModernForgeClientHandler; 294 | +import io.izzel.lightfall.forge.ModernForgeServerConnector; 295 | import net.md_5.bungee.netty.ChannelWrapper; 296 | import net.md_5.bungee.netty.HandlerBoss; 297 | import net.md_5.bungee.netty.PipelineUtils; 298 | @@ -174,6 +176,24 @@ public final class UserConnection implements ProxiedPlayer 299 | addGroups( s ); 300 | } 301 | 302 | + // lightfall start 303 | + // Forge 1.20.2+ 304 | + if ( ForgeConstants.FORGE_1_20_4_TOKEN.matcher(this.getPendingConnection().getExtraDataInHandshake()).find() ) 305 | + { 306 | + // This version of Forge uses configuration phase for registry sync, so we do not report it as modern forge but only forward tokens 307 | + forgeClientHandler = new ModernForgeClientHandler(this); 308 | + forgeClientHandler.setFmlTokenInHandshake( true ); 309 | + } 310 | + // Forge 1.13 - 1.20.1 311 | + else if (this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.MODERN_FML_HANDSHAKE_TOKEN ) 312 | + || this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.MODERN_FML_NET_3 )) 313 | + { 314 | + forgeClientHandler = new ModernForgeClientHandler(this); 315 | + forgeClientHandler.setFmlTokenInHandshake( true ); 316 | + this.modernForge = true; 317 | + } 318 | + else { 319 | + // lightfall end 320 | forgeClientHandler = new ForgeClientHandler( this ); 321 | 322 | // No-config FML handshake marker. 323 | @@ -182,6 +202,7 @@ public final class UserConnection implements ProxiedPlayer 324 | { 325 | forgeClientHandler.setFmlTokenInHandshake( true ); 326 | } 327 | + } // lightfall 328 | return BungeeCord.getInstance().addConnection( this ); 329 | } 330 | 331 | @@ -376,7 +397,13 @@ public final class UserConnection implements ProxiedPlayer 332 | PipelineUtils.BASE_SERVERSIDE.initChannel( ch ); 333 | ch.pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); 334 | ch.pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); 335 | - ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); 336 | + // lightfall start 337 | + if (isModernForge()) { 338 | + ch.pipeline().get( HandlerBoss.class ).setHandler( new ModernForgeServerConnector( bungee, UserConnection.this, target ) ); 339 | + } else { 340 | + ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); 341 | + } 342 | + // lightfall end 343 | } 344 | }; 345 | ChannelFutureListener listener = new ChannelFutureListener() 346 | @@ -400,7 +427,7 @@ public final class UserConnection implements ProxiedPlayer 347 | { 348 | if (request.isSendFeedback()) sendMessage( bungee.getTranslation( "fallback_lobby" ) ); // Waterfall 349 | connect( def, null, true, ServerConnectEvent.Reason.LOBBY_FALLBACK, request.getConnectTimeout(), request.isSendFeedback() ); // Waterfall 350 | - } else if ( dimensionChange ) 351 | + } else if ( dimensionChange || isDuringModernHandshake() ) 352 | { 353 | disconnect( bungee.getTranslation( "fallback_kick", connectionFailMessage( future.cause() ) ) ); 354 | } else 355 | @@ -802,4 +829,13 @@ public final class UserConnection implements ProxiedPlayer 356 | return entityRewrite == net.md_5.bungee.entitymap.EntityMap_Dummy.INSTANCE; 357 | } 358 | // Waterfall end 359 | + // lightfall start 360 | + @Getter 361 | + @Setter 362 | + private boolean modernForge = false; 363 | + 364 | + public boolean isDuringModernHandshake() { 365 | + return this.modernForge && getCh().getHandle().pipeline().get(MinecraftEncoder.class).getProtocol() == Protocol.LOGIN; 366 | + } 367 | + // lightfall end 368 | } 369 | diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java 370 | index bea2bbff..6fca66a8 100644 371 | --- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java 372 | +++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java 373 | @@ -21,7 +21,7 @@ public class ForgeClientHandler 374 | { 375 | 376 | @NonNull 377 | - private final UserConnection con; 378 | + protected final UserConnection con; 379 | 380 | /** 381 | * The users' mod list. 382 | diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java 383 | index f5253b89..37789125 100644 384 | --- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java 385 | +++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java 386 | @@ -22,6 +22,9 @@ public class ForgeConstants 387 | * The FML 1.8 handshake token. 388 | */ 389 | public static final String FML_HANDSHAKE_TOKEN = "\0FML\0"; 390 | + public static final String MODERN_FML_HANDSHAKE_TOKEN = "\0FML2\0", MODERN_FML_NET_3 = "\0FML3\0"; // lightfall 391 | + public static final PluginMessage MODERN_FML_RESET = new PluginMessage("lightfall:reset", new byte[]{0,0}, true); 392 | + public static final java.util.regex.Pattern FORGE_1_20_4_TOKEN = java.util.regex.Pattern.compile("\\x00FORGE\\d*(\\x00|$)"); 393 | 394 | public static final PluginMessage FML_RESET_HANDSHAKE = new PluginMessage( FML_HANDSHAKE_TAG, new byte[] 395 | { 396 | -- 397 | 2.36.1.windows.1 398 | 399 | -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0003-Queue-packets-during-handshake.patch: -------------------------------------------------------------------------------- 1 | From 95adbd39ea62388a8e168dcadb05a25f02c48be2 Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Sun, 14 Mar 2021 20:04:23 +0800 4 | Subject: [PATCH] Queue packets during handshake 5 | 6 | 7 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 8 | index 1713e7d5..0f5c1fa6 100644 9 | --- a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 10 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 11 | @@ -60,6 +60,7 @@ public class ModernForgeServerConnector extends ServerConnector { 12 | if (thisState == State.ACK) { 13 | user.unsafe().sendPacket(loginSuccess); 14 | user.getCh().setProtocol(Protocol.GAME); 15 | + user.getCh().endHandshake(); 16 | user.getCh().getHandle().pipeline().get(HandlerBoss.class).setHandler(new UpstreamBridge(bungee, user)); 17 | thisState = State.PLAIN; 18 | } 19 | @@ -79,6 +80,7 @@ public class ModernForgeServerConnector extends ServerConnector { 20 | user.getCh().getHandle().flush(); 21 | user.getCh().write(ForgeConstants.MODERN_FML_RESET); 22 | user.getCh().setProtocol(Protocol.LOGIN); 23 | + user.getCh().beginHandshake(); 24 | user.getCh().getHandle().pipeline().get(HandlerBoss.class).setHandler(new ModernForgeUpstreamBridge(bungee, user, this)); 25 | if (user.getServer() != null) { 26 | user.getServer().setObsolete(true); 27 | diff --git a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java 28 | index 00e03bae..894cbdbd 100644 29 | --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java 30 | +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java 31 | @@ -6,6 +6,9 @@ import io.netty.channel.ChannelFutureListener; 32 | import io.netty.channel.ChannelHandler; 33 | import io.netty.channel.ChannelHandlerContext; 34 | import java.net.SocketAddress; 35 | +import java.util.Objects; 36 | +import java.util.Queue; 37 | +import java.util.concurrent.ConcurrentLinkedQueue; 38 | import java.util.concurrent.TimeUnit; 39 | import lombok.Getter; 40 | import lombok.Setter; 41 | @@ -17,6 +20,8 @@ import net.md_5.bungee.protocol.MinecraftEncoder; 42 | import net.md_5.bungee.protocol.PacketWrapper; 43 | import net.md_5.bungee.protocol.Protocol; 44 | import net.md_5.bungee.protocol.packet.Kick; 45 | +import net.md_5.bungee.protocol.packet.LoginPayloadRequest; 46 | +import net.md_5.bungee.protocol.packet.LoginSuccess; 47 | 48 | public class ChannelWrapper 49 | { 50 | @@ -78,6 +83,17 @@ public class ChannelWrapper 51 | { 52 | if ( !closed ) 53 | { 54 | + // lightfall start 55 | + if (queueGamePacket) { 56 | + Object actual = packet instanceof PacketWrapper ? ((PacketWrapper) packet).packet : packet; 57 | + if (actual instanceof LoginPayloadRequest || actual instanceof Kick || actual instanceof LoginSuccess) { 58 | + ch.writeAndFlush(actual, ch.voidPromise()); 59 | + } else { 60 | + packetQueue.add(packet); 61 | + } 62 | + return; 63 | + } 64 | + // lightfall end 65 | DefinedPacket defined = null; 66 | if ( packet instanceof PacketWrapper ) 67 | { 68 | @@ -188,4 +204,19 @@ public class ChannelWrapper 69 | ch.pipeline().remove( "decompress" ); 70 | } 71 | } 72 | + // lightfall start 73 | + private volatile boolean queueGamePacket = false; 74 | + private final Queue packetQueue = new ConcurrentLinkedQueue<>(); 75 | + 76 | + public void beginHandshake() { 77 | + queueGamePacket = true; 78 | + } 79 | + 80 | + public void endHandshake() { 81 | + queueGamePacket = false; 82 | + while (!packetQueue.isEmpty()) { 83 | + write(packetQueue.poll()); 84 | + } 85 | + } 86 | + // lightfall end 87 | } 88 | -- 89 | 2.36.1.windows.1 90 | 91 | -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0004-Wrap-modded-command-arguments.patch: -------------------------------------------------------------------------------- 1 | From 1bf437aba8c0d7118a9ee42dad0c1bc5f5ca774b Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Wed, 5 May 2021 23:50:01 +0800 4 | Subject: [PATCH] Wrap modded command arguments 5 | 6 | 7 | diff --git a/protocol/src/main/java/io/izzel/lightfall/forge/WrappedArgumentType.java b/protocol/src/main/java/io/izzel/lightfall/forge/WrappedArgumentType.java 8 | new file mode 100644 9 | index 00000000..73d491fa 10 | --- /dev/null 11 | +++ b/protocol/src/main/java/io/izzel/lightfall/forge/WrappedArgumentType.java 12 | @@ -0,0 +1,21 @@ 13 | +package io.izzel.lightfall.forge; 14 | + 15 | +import com.mojang.brigadier.StringReader; 16 | +import com.mojang.brigadier.arguments.ArgumentType; 17 | +import com.mojang.brigadier.exceptions.CommandSyntaxException; 18 | +import lombok.Data; 19 | +import lombok.RequiredArgsConstructor; 20 | + 21 | +@RequiredArgsConstructor 22 | +@Data 23 | +public class WrappedArgumentType implements ArgumentType { 24 | + 25 | + public final String actualKey; 26 | + public final int actualIntKey; 27 | + public final byte[] actualPayload; 28 | + 29 | + @Override 30 | + public Object parse(StringReader stringReader) throws CommandSyntaxException { 31 | + throw new UnsupportedOperationException("Not supported."); 32 | + } 33 | +} 34 | diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 35 | index 069bb52b..64cc579b 100644 36 | --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 37 | +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 38 | @@ -21,6 +21,7 @@ import com.mojang.brigadier.tree.ArgumentCommandNode; 39 | import com.mojang.brigadier.tree.CommandNode; 40 | import com.mojang.brigadier.tree.LiteralCommandNode; 41 | import com.mojang.brigadier.tree.RootCommandNode; 42 | +import io.izzel.lightfall.forge.WrappedArgumentType; 43 | import io.netty.buffer.ByteBuf; 44 | import java.util.ArrayDeque; 45 | import java.util.Collection; 46 | @@ -535,6 +536,64 @@ public class Commands extends DefinedPacket 47 | DefinedPacket.writeString( t, buf ); 48 | } 49 | }; 50 | + // lightfall start 51 | + private static final ArgumentSerializer FORGE_ENUM = new ArgumentSerializer() { 52 | + @Override 53 | + protected String read(ByteBuf buf) { 54 | + return readString(buf); 55 | + } 56 | + 57 | + @Override 58 | + protected void write(ByteBuf buf, String enumClass) { 59 | + writeString(enumClass, buf); 60 | + } 61 | + }; 62 | + private static final int ARCLIGHT_WRAP_INDEX = -256; 63 | + private static final ProperArgumentSerializer ARCLIGHT_WRAP = new ProperArgumentSerializer() { 64 | + @Override 65 | + protected String getKey() { 66 | + throw new IllegalStateException(); 67 | + } 68 | + 69 | + @Override 70 | + protected String getKey(WrappedArgumentType t) { 71 | + return t.actualKey; 72 | + } 73 | + 74 | + @Override 75 | + protected int getIntKey() { 76 | + throw new UnsupportedOperationException("getIntKey"); 77 | + } 78 | + 79 | + @Override 80 | + protected int getIntKey(WrappedArgumentType t) { 81 | + return t.actualIntKey; 82 | + } 83 | + 84 | + @Override 85 | + protected WrappedArgumentType read(ByteBuf buf) { 86 | + throw new UnsupportedOperationException("read"); 87 | + } 88 | + 89 | + @Override 90 | + protected WrappedArgumentType read(ByteBuf buf, int protocolVersion) { 91 | + if (protocolVersion >= ProtocolConstants.MINECRAFT_1_19) { 92 | + int actualKey = readVarInt(buf); 93 | + byte[] bytes = readArray(buf); 94 | + return new WrappedArgumentType(null, actualKey, bytes); 95 | + } else { 96 | + String actualKey = readString(buf); 97 | + byte[] bytes = readArray(buf); 98 | + return new WrappedArgumentType(actualKey, -1, bytes); 99 | + } 100 | + } 101 | + 102 | + @Override 103 | + protected void write(ByteBuf buf, WrappedArgumentType t) { 104 | + buf.writeBytes(t.actualPayload); 105 | + } 106 | + }; 107 | + // lightfall end 108 | 109 | static 110 | { 111 | @@ -799,6 +858,13 @@ public class Commands extends DefinedPacket 112 | get( "minecraft:uuid", VOID ), 113 | get( "minecraft:heightmap", VOID ) 114 | }; 115 | + // lightfall start 116 | + PROVIDERS.put( "forge:enum", FORGE_ENUM ); 117 | + PROVIDERS.put( "forge:modid", VOID ); 118 | + PROVIDERS.put( "minecraft:", VOID ); 119 | + PROVIDERS.put( "arclight:wrapped", ARCLIGHT_WRAP ); 120 | + PROPER_PROVIDERS.put( WrappedArgumentType.class, ARCLIGHT_WRAP ); 121 | + // lightfall end 122 | } 123 | 124 | private static void register(String name, ArgumentSerializer serializer) 125 | @@ -819,7 +885,11 @@ public class Commands extends DefinedPacket 126 | if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) 127 | { 128 | key = readVarInt( buf ); 129 | - 130 | + // lightfall - start 131 | + if (key.equals(ARCLIGHT_WRAP_INDEX)) { 132 | + reader = ARCLIGHT_WRAP; 133 | + } else 134 | + // lightfall - end 135 | if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 ) 136 | { 137 | reader = IDS_1_20_3[(Integer) key]; 138 | @@ -841,7 +911,7 @@ public class Commands extends DefinedPacket 139 | 140 | Preconditions.checkArgument( reader != null, "No provider for argument " + key ); 141 | 142 | - Object val = reader.read( buf ); 143 | + Object val = reader.read( buf, protocolVersion ); // lightfall - use protocol version 144 | return val != null && PROPER_PROVIDERS.containsKey( val.getClass() ) ? (ArgumentType) val : new DummyType( key, reader, val ); 145 | } 146 | 147 | @@ -852,10 +922,10 @@ public class Commands extends DefinedPacket 148 | { 149 | if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) 150 | { 151 | - writeVarInt( proper.getIntKey(), buf ); 152 | + writeVarInt( proper.getIntKey(arg), buf ); // lightfall - use arg 153 | } else 154 | { 155 | - writeString( proper.getKey(), buf ); 156 | + writeString( proper.getKey(arg), buf ); // lightfall - use arg 157 | } 158 | proper.write( buf, arg ); 159 | } else 160 | @@ -894,6 +964,12 @@ public class Commands extends DefinedPacket 161 | 162 | protected abstract T read(ByteBuf buf); 163 | 164 | + // lightfall start 165 | + protected T read(ByteBuf buf, int protocolVersion) { 166 | + return read(buf); 167 | + } 168 | + // lightfall end 169 | + 170 | protected abstract void write(ByteBuf buf, T t); 171 | } 172 | 173 | @@ -903,6 +979,16 @@ public class Commands extends DefinedPacket 174 | protected abstract int getIntKey(); 175 | 176 | protected abstract String getKey(); 177 | + 178 | + // lightfall begin 179 | + protected String getKey(T t) { 180 | + return getKey(); 181 | + } 182 | + 183 | + protected int getIntKey(T t) { 184 | + return getIntKey(); 185 | + } 186 | + // lightfall end 187 | } 188 | } 189 | 190 | diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java 191 | index d0496ab4..c73e85a4 100644 192 | --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java 193 | +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java 194 | @@ -97,6 +97,7 @@ public class DownstreamBridge extends PacketHandler 195 | // do not perform any actions if the user has already moved 196 | return; 197 | } 198 | + t.printStackTrace(); 199 | 200 | // Waterfall start 201 | ServerInfo def = con.updateAndGetNextServer( server.getInfo() ); 202 | -- 203 | 2.36.1.windows.1 204 | 205 | -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0005-Accept-all-suggestion-types.patch: -------------------------------------------------------------------------------- 1 | From 53b7bbe1f81c217ae17a4257e5303c184e8879db Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Thu, 6 May 2021 21:04:52 +0800 4 | Subject: [PATCH] Accept all suggestion types 5 | 6 | 7 | diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 8 | index 64cc579b..afa2676e 100644 9 | --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 10 | +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java 11 | @@ -1015,7 +1015,7 @@ public class Commands extends DefinedPacket 12 | 13 | private static SuggestionProvider getProvider(String key) 14 | { 15 | - SuggestionProvider provider = PROVIDERS.get( key ); 16 | + SuggestionProvider provider = PROVIDERS.computeIfAbsent( key, DummyProvider::new ); // lightfall - accept any suggestion 17 | Preconditions.checkArgument( provider != null, "Unknown completion provider " + key ); 18 | 19 | return provider; 20 | -- 21 | 2.36.1.windows.1 22 | 23 | -------------------------------------------------------------------------------- /Waterfall-Proxy-Patches/0006-Implement-ModernFMLHandshakeEvent.patch: -------------------------------------------------------------------------------- 1 | From 1b21148f2b1e7006b2c1885e2955fd5e643d6191 Mon Sep 17 00:00:00 2001 2 | From: IzzelAliz 3 | Date: Fri, 9 Jul 2021 15:58:58 +0800 4 | Subject: [PATCH] Implement ModernFMLHandshakeEvent 5 | 6 | 7 | diff --git a/api/pom.xml b/api/pom.xml 8 | index 23d08d27..a7fe5292 100644 9 | --- a/api/pom.xml 10 | +++ b/api/pom.xml 11 | @@ -84,7 +84,7 @@ 12 | 13 | io.izzel.lightfall 14 | lightfall-api 15 | - 1.0.0 16 | + 1.1.1 17 | 18 | 19 | 20 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 21 | index 0f5c1fa6..55ad11e2 100644 22 | --- a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 23 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeServerConnector.java 24 | @@ -1,6 +1,7 @@ 25 | package io.izzel.lightfall.forge; 26 | 27 | import com.google.common.base.Preconditions; 28 | +import io.izzel.lightfall.api.event.ModernFMLHandshakeEvent; 29 | import lombok.Getter; 30 | import net.md_5.bungee.BungeeServerInfo; 31 | import net.md_5.bungee.ServerConnector; 32 | @@ -10,6 +11,7 @@ import net.md_5.bungee.connection.UpstreamBridge; 33 | import net.md_5.bungee.forge.ForgeConstants; 34 | import net.md_5.bungee.netty.ChannelWrapper; 35 | import net.md_5.bungee.netty.HandlerBoss; 36 | +import net.md_5.bungee.protocol.DefinedPacket; 37 | import net.md_5.bungee.protocol.PacketWrapper; 38 | import net.md_5.bungee.protocol.Protocol; 39 | import net.md_5.bungee.protocol.packet.EncryptionResponse; 40 | @@ -93,7 +95,7 @@ public class ModernForgeServerConnector extends ServerConnector { 41 | break; 42 | } 43 | case ACK: { 44 | - user.unsafe().sendPacket(request); 45 | + writePacket(request); 46 | break; 47 | } 48 | } 49 | @@ -102,11 +104,22 @@ public class ModernForgeServerConnector extends ServerConnector { 50 | public void onResetAck() { 51 | Preconditions.checkState(thisState == State.PENDING, "Not expecting PENDING"); 52 | while (!pendingHandshakes.isEmpty()) { 53 | - user.unsafe().sendPacket(pendingHandshakes.poll()); 54 | + writePacket(pendingHandshakes.poll()); 55 | } 56 | thisState = State.ACK; 57 | } 58 | 59 | + private void writePacket(LoginPayloadRequest packet) { 60 | + ModernFMLHandshakeEvent.Request event = new ModernFMLHandshakeEvent.Request(user, target, packet); 61 | + if (event.callEvent()) { 62 | + user.unsafe().sendPacket(packet); 63 | + } else { 64 | + if (event.getResponse() != null) { 65 | + user.getForgeServerHandler().getCh().write(event.getResponse()); 66 | + } 67 | + } 68 | + } 69 | + 70 | public ChannelWrapper getChannel() { 71 | return this.ch; 72 | } 73 | @@ -119,4 +132,8 @@ public class ModernForgeServerConnector extends ServerConnector { 74 | return super.toString(); 75 | } 76 | } 77 | + 78 | + public BungeeServerInfo getTarget() { 79 | + return this.target; 80 | + } 81 | } 82 | diff --git a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java 83 | index 5e5432ec..37e7a9a4 100644 84 | --- a/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java 85 | +++ b/proxy/src/main/java/io/izzel/lightfall/forge/ModernForgeUpstreamBridge.java 86 | @@ -1,5 +1,6 @@ 87 | package io.izzel.lightfall.forge; 88 | 89 | +import io.izzel.lightfall.api.event.ModernFMLHandshakeEvent; 90 | import io.netty.handler.timeout.ReadTimeoutException; 91 | import lombok.RequiredArgsConstructor; 92 | import net.md_5.bungee.BungeeCord; 93 | @@ -33,7 +34,9 @@ public class ModernForgeUpstreamBridge extends PacketHandler { 94 | if (isAckPacket(response)) { 95 | server.onResetAck(); 96 | } else { 97 | - con.getForgeServerHandler().getCh().write(response); 98 | + if (new ModernFMLHandshakeEvent.Response(con, server.getTarget(), response).callEvent()) { 99 | + con.getForgeServerHandler().getCh().write(response); 100 | + } 101 | } 102 | } 103 | 104 | -- 105 | 2.36.1.windows.1 106 | 107 | -------------------------------------------------------------------------------- /lightfall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "$1" in 4 | "rb" | "rbp" | "rebuild") 5 | scripts/rebuildPatches.sh 6 | ;; 7 | "p" | "patch") 8 | scripts/build.sh 9 | ;; 10 | "m" | "up" | "merge") 11 | scripts/mergeUpstream.sh 12 | ;; 13 | "b" | "build") 14 | scripts/build.sh --jar 15 | ;; 16 | "e" | "edit") 17 | scripts/edit.sh 18 | ;; 19 | "w" | "wiggle") 20 | scripts/wigglePatch.py 21 | ;; 22 | *) 23 | echo "lightfall build tool command. This provides a variety of commands to control the lightfall" 24 | echo "build. View below for details of the available commands." 25 | echo "" 26 | echo "Commands:" 27 | echo " * rb, rbp, rebuild | Rebuilds the patches" 28 | echo " * p, patch | Applies all the patches to BungeeCord" 29 | echo " * m, up, merge | Utility to aid in merging upstream" 30 | echo " * b, build | Builds the project" 31 | echo " | The bootstrap artifact can be found in lightfall-proxy/bootstrap/target/" 32 | echo " * e, edit | Runs git rebase -i for Waterfall, allowing patches to be easily modified" 33 | echo " * w, wiggle | Helps to apply patches that fail to using default Git." 34 | ;; 35 | esac -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.izzel.lightfall 7 | lightfall-super 8 | dev-SNAPSHOT 9 | pom 10 | 11 | lightfall-Super 12 | Super project for Waterfall. 13 | https://github.com/WaterfallMC/Waterfall 14 | 15 | 16 | lightfall-proxy 17 | 18 | 19 | 20 | clean install 21 | 22 | 23 | 24 | UTF-8 25 | 26 | 27 | -------------------------------------------------------------------------------- /scripts/applyPatches.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PS1="$" 4 | basedir="$(cd "$1" && pwd -P)" 5 | workdir="$basedir/work" 6 | gpgsign="$(git config commit.gpgsign || echo "false")" 7 | echo "Rebuilding Forked projects.... " 8 | 9 | function enableCommitSigningIfNeeded { 10 | if [[ "$gpgsign" == "true" ]]; then 11 | echo "Re-enabling GPG Signing" 12 | # Yes, this has to be global 13 | git config --global commit.gpgsign true 14 | fi 15 | } 16 | 17 | function applyPatch { 18 | what=$1 19 | what_name=$(basename "$what") 20 | target=$2 21 | branch=$3 22 | 23 | cd "$basedir/$what" 24 | git fetch 25 | git branch -f upstream "$branch" >/dev/null 26 | 27 | cd "$basedir" 28 | if [ ! -d "$basedir/$target" ]; then 29 | git clone "$what" "$target" 30 | fi 31 | cd "$basedir/$target" 32 | 33 | echo "Resetting $target to $what_name..." 34 | git remote rm upstream > /dev/null 2>&1 35 | git remote add upstream "$basedir/$what" >/dev/null 2>&1 36 | git checkout master 2>/dev/null || git checkout -b master 37 | git fetch upstream >/dev/null 2>&1 38 | git reset --hard upstream/upstream 39 | 40 | echo " Applying patches to $target..." 41 | 42 | git am --abort >/dev/null 2>&1 43 | git am --3way --ignore-whitespace "$basedir/${what_name}-Patches/"*.patch 44 | if [ "$?" != "0" ]; then 45 | echo " Something did not apply cleanly to $target." 46 | echo " Please review above details and finish the apply then" 47 | echo " save the changes with rebuildPatches.sh" 48 | enableCommitSigningIfNeeded 49 | exit 1 50 | else 51 | echo " Patches applied cleanly to $target" 52 | fi 53 | } 54 | 55 | # Disable GPG signing before AM, slows things down and doesn't play nicely. 56 | # There is also zero rational or logical reason to do so for these sub-repo AMs. 57 | # Calm down kids, it's re-enabled (if needed) immediately after, pass or fail. 58 | if [[ "$gpgsign" == "true" ]]; then 59 | echo "_Temporarily_ disabling GPG signing" 60 | git config --global commit.gpgsign false 61 | fi 62 | 63 | # Apply waterfall patches 64 | basedir=$basedir/Waterfall 65 | pushd Waterfall 66 | applyPatch BungeeCord Waterfall-Proxy HEAD 67 | popd 68 | basedir=$(dirname $basedir) 69 | 70 | # Apply lightfall patches 71 | applyPatch Waterfall/Waterfall-Proxy lightfall-proxy HEAD 72 | 73 | enableCommitSigningIfNeeded 74 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git submodule update --recursive --init && ./scripts/applyPatches.sh 4 | if [ "$1" == "--jar" ]; then 5 | pushd lightfall-proxy 6 | mvn clean package 7 | fi 8 | -------------------------------------------------------------------------------- /scripts/edit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd lightfall-proxy 4 | git rebase --interactive upstream/upstream 5 | popd 6 | -------------------------------------------------------------------------------- /scripts/mergeUpstream.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PS1="$" 4 | basedir=`pwd` 5 | 6 | function update { 7 | cd "$basedir/$1" 8 | git fetch && git reset --hard origin/master 9 | cd "$basedir/$1/.." 10 | git add $1 11 | } 12 | 13 | update Waterfall 14 | 15 | # Update submodules 16 | git submodule update --recursive 17 | -------------------------------------------------------------------------------- /scripts/rebuildPatches.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ( 4 | PS1="$" 5 | basedir="$(cd "$1" && pwd -P)" 6 | workdir="$basedir/work" 7 | echo "Rebuilding patch files from current fork state..." 8 | git config core.safecrlf false 9 | 10 | function cleanupPatches { 11 | cd "$1" 12 | for patch in *.patch; do 13 | echo "$patch" 14 | gitver=$(tail -n 2 "$patch" | grep -ve "^$" | tail -n 1) 15 | diffs=$(git diff --staged "$patch" | grep -E "^(\+|\-)" | grep -Ev "(From [a-z0-9]{32,}|\-\-\- a|\+\+\+ b|.index)") 16 | 17 | testver=$(echo "$diffs" | tail -n 2 | grep -ve "^$" | tail -n 1 | grep "$gitver") 18 | if [ "x$testver" != "x" ]; then 19 | diffs=$(echo "$diffs" | sed 'N;$!P;$!D;$d') 20 | fi 21 | 22 | if [ "x$diffs" == "x" ] ; then 23 | git reset HEAD "$patch" >/dev/null 24 | git checkout -- "$patch" >/dev/null 25 | fi 26 | done 27 | } 28 | 29 | function savePatches { 30 | what=$1 31 | what_name=$(basename "$what") 32 | target=$2 33 | echo "Formatting patches for $what..." 34 | 35 | cd "$basedir/${what_name}-Patches/" 36 | if [ -d "$basedir/$target/.git/rebase-apply" ]; then 37 | # in middle of a rebase, be smarter 38 | echo "REBASE DETECTED - PARTIAL SAVE" 39 | last=$(cat "$basedir/$target/.git/rebase-apply/last") 40 | next=$(cat "$basedir/$target/.git/rebase-apply/next") 41 | for i in $(seq -f "%04g" 1 1 $last) 42 | do 43 | if [ $i -lt $next ]; then 44 | rm ${i}-*.patch 45 | fi 46 | done 47 | else 48 | rm -rf *.patch 49 | fi 50 | 51 | cd "$basedir/$target" 52 | 53 | git format-patch --no-stat -N -o "$basedir/${what_name}-Patches/" upstream/upstream >/dev/null 54 | cd "$basedir" 55 | git add -A "$basedir/${what_name}-Patches" 56 | cleanupPatches "$basedir/${what_name}-Patches" 57 | echo " Patches saved for $what to $what_name-Patches/" 58 | } 59 | 60 | savePatches "Waterfall/Waterfall-Proxy" "lightfall-proxy" 61 | ) 62 | -------------------------------------------------------------------------------- /scripts/upstreamCommit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ( 3 | set -e 4 | PS1="$" 5 | 6 | function changelog() { 7 | base=$(git ls-tree HEAD $1 | cut -d' ' -f3 | cut -f1) 8 | cd $1 && git log --oneline ${base}...HEAD 9 | } 10 | waterfall=$(changelog Waterfall) 11 | 12 | updated="" 13 | logsuffix="" 14 | if [ ! -z "$waterfall" ]; then 15 | logsuffix="$logsuffix\n\nWaterfall Changes:\n$waterfall" 16 | if [ -z "$updated" ]; then updated="Waterfall"; else updated="$updated/Waterfall"; fi 17 | fi 18 | disclaimer="Upstream has released updates that appears to apply and compile correctly.\nThis update has not been tested by PaperMC and as with ANY update, please do your own testing" 19 | 20 | if [ ! -z "$1" ]; then 21 | disclaimer="$@" 22 | fi 23 | 24 | log="${UP_LOG_PREFIX}Updated Upstream ($updated)\n\n${disclaimer}${logsuffix}" 25 | 26 | echo -e "$log" | git commit -F - 27 | 28 | ) || exit 1 29 | -------------------------------------------------------------------------------- /scripts/wigglePatch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from subprocess import run, PIPE, CalledProcessError 3 | from argparse import ArgumentParser 4 | import os 5 | from os import path 6 | from sys import stderr, stdout 7 | import re 8 | from enum import Enum, unique 9 | 10 | @unique 11 | class FileStatus(Enum): 12 | UNTRACKED = '?' 13 | UNMODIFIED = ' ' 14 | MODIFIED = 'M' 15 | ADDED = 'A' 16 | DELETED = 'D' 17 | RENAMED = 'R' 18 | COPIED = 'C' 19 | UNMERGED = 'U' 20 | IGNORED = '!' 21 | 22 | class GitRepository: 23 | def __init__(self, directory): 24 | if not path.isdir(directory): 25 | if not path.exists(directory): 26 | raise ValueError("Repository doesn't exist:", directory) 27 | else: 28 | raise ValueError("Repository isn't a valid directory:", directory) 29 | elif not path.isdir(path.join(directory, ".git")): 30 | raise ValueError("Directory isn't a git repository:", directory) 31 | self.directory = directory 32 | 33 | def status(self): 34 | status_lines = run( 35 | ["git", "status", "--porcelain"], 36 | check=True, stdout=PIPE, universal_newlines=True, 37 | cwd=self.directory 38 | ).stdout 39 | status = dict() 40 | for line in status_lines.splitlines(): 41 | old_status = FileStatus(line[0]) 42 | new_status = FileStatus(line[1]) 43 | file_name = line[3:] 44 | status[file_name] = (old_status, new_status) 45 | return status 46 | 47 | def is_clean(self): 48 | try: 49 | return len(self.status()) == 0 50 | except CalledProcessError: 51 | return False 52 | 53 | def is_automatically_merging(self): 54 | return path.exists(path.join(self.directory, ".git", "rebase-apply", "applying")) 55 | 56 | def wiggle_patch(self, patch): 57 | assert self.is_clean() 58 | # By default, wiggle won't create files the patch needs, and just fails 59 | for created_file in patch.created_files: 60 | # mkdir -p $(dirname created_file) 61 | os.makedirs(path.join(self.directory, path.dirname(created_file)), exist_ok=True) 62 | # touch created_file 63 | with open(path.join(self.directory, created_file), 'a'): 64 | pass 65 | result = run(["wiggle", "-rp", path.relpath(patch.file, start=self.directory)], 66 | stderr=stderr, cwd=self.directory) 67 | for file_name, (old_status, new_status) in self.status().items(): 68 | if new_status == FileStatus.UNTRACKED and old_status == FileStatus.UNTRACKED \ 69 | and file_name.endswith(".porig"): 70 | # Remove wiggle's automatically created backup files 71 | # They're completely unessicary since the entire repo is version-controlled 72 | os.remove(path.join(self.directory, file_name)) 73 | if result.returncode == 1: 74 | return False # There were unresolved conflicts 75 | else: 76 | # Check for an unexpected error 77 | # Since conflicts were already checked for, this will only raise for unexpected errors 78 | result.check_returncode() 79 | return True # Successfully wiggled 80 | 81 | def __str__(self): 82 | return path.basename(self.directory) 83 | 84 | class PatchFile: 85 | def __init__(self, file): 86 | if not path.isfile(file): 87 | if not path.exists(file): 88 | raise ValueError("Patch file doesn't exist:", file) 89 | else: 90 | raise ValueError("Patch isn't a file:", file) 91 | self.file = file 92 | try: 93 | summary = run(["git", "apply", "--summary", file], 94 | check=True, stdout=PIPE, universal_newlines=True).stdout 95 | except CalledProcessError: 96 | raise ValueError("Invalid patch file:", file) 97 | summary_pattern = re.compile(r"\s*(create) mode \d+ (\S+)") 98 | created_files = list() 99 | for line in summary.splitlines(): 100 | match = summary_pattern.match(line) 101 | if not match: 102 | raise NotImplementedError("Don't know how to parse summary line: {}".format(line)) 103 | (action, target_file) = match.groups() 104 | if action == "create": 105 | created_files.append(target_file) 106 | self.created_files = tuple(created_files) # Immutable copy 107 | 108 | def __str__(self): 109 | return path.basename(self.file) 110 | 111 | parser = ArgumentParser(description="Wiggle the patch into the specified git repository") 112 | parser.add_argument("repo", help="The git repository to apply the patch to", type=GitRepository) 113 | parser.add_argument("patch", help="The patch to apply to the repository", type=PatchFile) 114 | parser.add_argument("--git-am", "--am", "-a", action="store_true", 115 | help="If an automatic merge is in progress, continue it after wiggling") 116 | 117 | args = parser.parse_args() 118 | 119 | repository, patch = args.repo, args.patch 120 | 121 | if not repository.is_clean(): 122 | print(repository, "isn't a clean repo!") 123 | exit(1) 124 | 125 | 126 | was_automatically_merging = False 127 | if args.git_am and repository.is_automatically_merging(): 128 | print("Automatic merge in progress, will continue applying if successful") 129 | was_automatically_merging = True 130 | 131 | if not repository.wiggle_patch(patch): 132 | print("Unresolved conflicts found while wiggling!", file=stderr) 133 | print("Manual intervention is required to fix the conflicts!", file=stderr) 134 | exit(2) 135 | 136 | if args.git_am and was_automatically_merging: 137 | assert repository.is_automatically_merging() 138 | try: 139 | print("Adding changed files to index") 140 | run(["git", "add", "."], stdout=stdout, stderr=stderr, check=True, 141 | cwd=repository.directory) 142 | print("Continuing automatic merge after successful wiggle") 143 | run(["git", "am", "--continue"], stdout=stdout, stderr=stderr, check=True, 144 | cwd=repository.directory) 145 | except CalledProcessError as e: 146 | print("Failed to continue automatic merge!", file=stderr) 147 | exit(3) 148 | else: 149 | print("Successfully Wiggled", patch, "into", repository) 150 | --------------------------------------------------------------------------------