Merge branch 'ver/1.16.5' into patch-mappalette

This commit is contained in:
epserv 2021-02-16 00:15:35 +05:00
commit f58ea4a9da
366 changed files with 6071 additions and 1978 deletions

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
custom: ["https://www.buymeacoffee.com/MrIvanPlays", "https://paypal.me/IvanMrIvanPlays"]

View File

@ -17,15 +17,7 @@ on:
paths-ignore:
- '*.md'
- 'Jenkinsfile'
branches:
- ver/1.16.5
- ver/1.16.4
- ver/1.16.3
- ver/1.16.1
- ver/1.16.2
- leaflight/ver/1.16.4
- leaflight/ver/1.16.5
jobs:
build:
@ -37,11 +29,6 @@ jobs:
fail-fast: false
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.4.1
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v1
@ -88,12 +75,12 @@ jobs:
- name: Build Yatopia
run: |
./gradlew paperclip
./gradlew clean build yatoclip
- name: Upload Artifact
if: github.ref != 'refs/heads/ver/1.16.4'
uses: actions/upload-artifact@v2
with:
name: Yatopia-${{ matrix.java }}
path: yatopia-1.16.5-paperclip.jar
path: yatopia-1.16.5-yatoclip.jar

1
.gitignore vendored
View File

@ -60,3 +60,4 @@ yatopia-launcher.jar
last-paper
!upstreamConfig/*
!upstreamCommits/*
testserver/

6
.gitmodules vendored
View File

@ -12,9 +12,9 @@
url = https://github.com/pl3xgaming/Purpur.git
branch = ver/1.16.5
[submodule "upstream/AirplaneLite"]
path = upstream/AirplaneLite
url = https://github.com/Technove/AirplaneLite.git
[submodule "upstream/Airplane"]
path = upstream/Airplane
url = https://github.com/Technove/Airplane.git
branch = master
[submodule "upstream/Akarin"]

154
Jenkinsfile vendored
View File

@ -1,80 +1,74 @@
pipeline {
agent { label 'slave' }
options { timestamps() }
stages {
stage('Cleanup') {
steps {
scmSkip(deleteBuild: true, skipPattern:'.*\\[CI-SKIP\\].*')
sh 'rm -rf ./target'
sh 'rm -rf ./Paper/Paper-API ./Paper/Paper-Server ./Paper/work/Spigot/Spigot-API ./Paper/work/Spigot/Spigot-Server'
sh 'rm -rf ./Yatopia-API ./Yatopia-Server'
sh 'chmod +x ./gradlew'
}
}
stage('Init project & submodules') {
steps {
sh './gradlew initGitSubmodules'
}
}
stage('Decompile & apply patches') {
tools {
jdk "OpenJDK 8"
}
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT',
) {
sh '''
./gradlew setupUpstream
./gradlew applyPatches
'''
}
}
}
stage('Build') {
tools {
jdk "OpenJDK 8"
}
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT'
) {
sh '''
./gradlew build
./gradlew publish
'''
}
}
}
stage('Build Launcher') {
tools {
jdk "OpenJDK 8"
}
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT'
) {
sh '''
mkdir -p "./target"
./gradlew paperclip
cp "yatopia-$mcver-paperclip.jar" "./target/yatopia-$mcver-paperclip-b$BUILD_NUMBER.jar"
'''
}
}
post {
success {
archiveArtifacts "target/*.jar"
}
failure {
cleanWs()
}
}
}
}
}
pipeline {
agent { label 'slave' }
options { timestamps() }
stages {
stage('Cleanup') {
steps {
scmSkip(deleteBuild: true, skipPattern:'.*\\[CI-SKIP\\].*')
sh 'rm -rf ./target'
sh 'rm -rf ./Paper/Paper-API ./Paper/Paper-Server ./Paper/work/Spigot/Spigot-API ./Paper/work/Spigot/Spigot-Server'
sh 'rm -rf ./Yatopia-API ./Yatopia-Server'
sh 'chmod +x ./gradlew'
}
}
stage('Init project & submodules') {
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT',
) {
sh './gradlew initGitSubmodules'
}
}
}
stage('Decompile & apply patches') {
tools {
jdk "OpenJDK 8"
}
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT',
) {
sh '''
./gradlew setupUpstream
./gradlew applyPatches
'''
}
}
}
stage('Build') {
tools {
jdk "OpenJDK 8"
}
steps {
withMaven(
maven: '3',
mavenLocalRepo: '.repository',
publisherStrategy: 'EXPLICIT'
) {
withCredentials([usernamePassword(credentialsId: 'jenkins-deploy', usernameVariable: 'ORG_GRADLE_PROJECT_mavenUsername', passwordVariable: 'ORG_GRADLE_PROJECT_mavenPassword')]) {
sh '''
./gradlew clean build yatoclip publish
mkdir -p "./target"
basedir=$(pwd)
paperworkdir="$basedir/Paper/work"
mcver=$(cat "$paperworkdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4)
cp "yatopia-$mcver-yatoclip.jar" "./target/yatopia-$mcver-yatoclip-b$BUILD_NUMBER.jar"
'''
}
}
}
post {
success {
archiveArtifacts "target/*.jar"
}
failure {
cleanWs()
}
}
}
}
}

View File

@ -1,5 +1,7 @@
The project without the build tools (Everything that is not a .patch file or in the buildSrc folder) are licensed under the MIT license found [here](MIT.md).<br>
All files in the buildSrc folder are licensed under MIT found [here](../buildSrc/license.txt)<br>
All patches (.patch files) marked with "lithium" are licensed under LGPL3 found [here](https://github.com/jellysquid3/lithium-fabric/blob/1.16.x/dev/LICENSE.txt).<br>
All files in the buildSrc folder are licensed under MIT found [here](../buildSrc/license.txt).<br>
All patches (.patch files) marked with "lithium" are licensed under LGPL3 found [here](https://github.com/CaffeineMC/lithium-fabric/blob/1.16.x/dev/LICENSE.txt).<br>
All patches (.patch files) marked with "hydrogen" are licensed under LGPL3 found [here](https://github.com/CaffeineMC/hydrogen-fabric/blob/1.16.x/LICENSE.txt).<br>
All patches (.patch files) marked with "krypton" are licensed under MIT found [here](https://github.com/astei/krypton/blob/master/LICENSE).<br>
All other patches (.patch files) included in this repo are licensed under the MIT license found [here](MIT.md).<br>
See [EMC](https://github.com/starlis/empirecraft/blob/master/README.md), [Akarin](https://github.com/Akarin-project/Akarin/blob/1.16.3/LICENSE.md), [Purpur](https://github.com/pl3xgaming/Purpur/blob/ver/1.16.5/LICENSE), [AirplaneLite](https://github.com/Technove/AirplaneLite/blob/master/PATCHES-LICENSE), [Origami](https://github.com/Minebench/Origami/blob/1.16/PATCHES-LICENSE), and [Tuinity](https://github.com/Spottedleaf/Tuinity/blob/master/PATCHES-LICENSE) for the license of patches automatically pulled during upstream updates.
See [EMC](https://github.com/starlis/empirecraft/blob/master/README.md), [Akarin](https://github.com/Akarin-project/Akarin/blob/1.16.3/LICENSE.md), [Purpur](https://github.com/pl3xgaming/Purpur/blob/ver/1.16.5/LICENSE), [Airplane](https://github.com/Technove/Airplane/blob/master/PATCHES-LICENSE), [Origami](https://github.com/Minebench/Origami/blob/1.16/PATCHES-LICENSE), and [Tuinity](https://github.com/Spottedleaf/Tuinity/blob/master/PATCHES-LICENSE) for the license of patches automatically pulled during upstream updates.

View File

@ -8,25 +8,24 @@ # Patches
| Side | Patch | Author | CoAuthors |
| ----- | ------------- |:-------------:| -----:|
| api | AFK API | William Blake Galbreath | |
| server | AFK API | William Blake Galbreath | |
| api | AFK API | William Blake Galbreath | |
| server | Ability to re-add farmland mechanics from Alpha | Yive | |
| server | Actually unload POI data | Spottedleaf | |
| server | Add /ping command | William Blake Galbreath | |
| server | Add 5 second tps average in /tps | William Blake Galbreath | |
| api | Add ChatColor.getById | Aikar | |
| api | Add EntityTeleportHinderedEvent | Mariell Hoversholm | |
| server | Add EntityTeleportHinderedEvent | Mariell Hoversholm | |
| api | Add GameProfileLookupEvent | tr7zw | |
| api | Add EntityTeleportHinderedEvent | Mariell Hoversholm | |
| server | Add GameProfileLookupEvent | tr7zw | |
| api | Add GameProfileLookupEvent | tr7zw | |
| server | Add IntelliJ IDEA runnable | Zoe | |
| server | Add JsonList save timings | Ivan Pekov | |
| api | Add NBT API as a first-class lib | tr7zw | |
| server | Add NBT API as a first-class lib | tr7zw | |
| api | Add StructureGenerateEvent | Nahuel | Mariell Hoversholm |
| api | Add NBT API as a first-class lib | tr7zw | |
| server | Add StructureGenerateEvent | Nahuel | Mariell Hoversholm |
| api | Add StructureGenerateEvent | Nahuel | Mariell Hoversholm |
| server | Add Velocity natives for encryption and compression | Andrew Steinborn | |
| server | Add a special case for floodgate and offline uuids | Ivan Pekov | |
| server | Add adjustable breeding cooldown to config | montlikadani | |
| server | Add allow water in end world option | William Blake Galbreath | |
| server | Add boat fall damage config | BillyGalbreath | |
@ -34,12 +33,13 @@ # Patches
| server | Add component util | William Blake Galbreath | |
| server | Add config for allowing Endermen to despawn even while | jmp | |
| server | Add configurable snowball damage | BillyGalbreath | |
| api | Add critical hit check to EntityDamagedByEntityEvent | BillyGalbreath | |
| server | Add critical hit check to EntityDamagedByEntityEvent | BillyGalbreath | |
| api | Add critical hit check to EntityDamagedByEntityEvent | BillyGalbreath | |
| server | Add demo command | BillyGalbreath | |
| server | Add enderman and creeper griefing controls | William Blake Galbreath | |
| api | Add last tick time API | Ivan Pekov | tr7zw |
| server | Add ghast allow-griefing option | BillyGalbreath | |
| server | Add last tick time API | Ivan Pekov | tr7zw |
| api | Add last tick time API | Ivan Pekov | tr7zw |
| server | Add mobGriefing bypass to everything affected | Encode42 | |
| server | Add no-tick block list | William Blake Galbreath | |
| server | Add nspt command | Ivan Pekov | |
@ -49,26 +49,29 @@ # Patches
| server | Add option to disable dolphin treasure searching | William Blake Galbreath | |
| server | Add option to disable mushroom block updates | William Blake Galbreath | |
| server | Add option to disable observer clocks | Phoenix616 | |
| api | Add option to disable zombie aggressiveness towards villagers | nitricspace | |
| server | Add option to disable zombie aggressiveness towards villagers | nitricspace | |
| api | Add option to disable zombie aggressiveness towards villagers | nitricspace | |
| server | Add option to set armorstand step height | William Blake Galbreath | |
| server | Add option to teleport to spawn if outside world border | William Blake Galbreath | |
| server | Add packet limiter config | Spottedleaf | |
| server | Add permission for F3+N debug | William Blake Galbreath | |
| server | Add phantom spawning options | William Blake Galbreath | |
| server | Add player death exp control options | William Blake Galbreath | |
| api | Add predicate to recipe&#39;s ExactChoice ingredient | William Blake Galbreath | |
| server | Add predicate to recipe&#39;s ExactChoice ingredient | William Blake Galbreath | |
| api | Add predicate to recipe&#39;s ExactChoice ingredient | William Blake Galbreath | |
| server | Add soft async catcher | Spottedleaf | |
| server | Add tablist suffix option for afk | montlikadani | |
| server | Add timings for Behavior | Phoenix616 | |
| server | Add timings for Pathfinder | MrIvanPlays | |
| server | Add twisting and weeping vines growth rates | BillyGalbreath | |
| server | Add unsafe Entity serialization API | Mariell Hoversholm | |
| api | Add unsafe Entity serialization API | Mariell Hoversholm | |
| server | Add vindicator johnny spawn chance | William Blake Galbreath | |
| server | Add wither skeleton takes wither damage option | William Blake Galbreath | |
| api | Advancement API | William Blake Galbreath | |
| server | Advancement API | William Blake Galbreath | |
| server | AirplaneLite MC Dev Fixes | Paul Sauve | |
| api | Advancement API | William Blake Galbreath | |
| server | Airplane Configuration | Paul Sauve | |
| server | Airplane MC Dev Fixes | Paul Sauve | |
| server | Allow Entities to be removed from a world while ticking | Spottedleaf | |
| server | Allow anvil colors | William Blake Galbreath | |
| server | Allow color codes in books | William Blake Galbreath | |
@ -81,8 +84,8 @@ # Patches
| server | Allow toggling special MobSpawners per world | jmp | |
| api | Alphabetize in-game /plugins list | BillyGalbreath | |
| server | Alternative Keepalive Handling | William Blake Galbreath | |
| api | Anvil API | William Blake Galbreath | |
| server | Anvil API | William Blake Galbreath | |
| api | Anvil API | William Blake Galbreath | |
| server | Apply display names from item forms of entities to entities | jmp | |
| server | Arrows should not reset despawn counter | William Blake Galbreath | |
| server | Attempt to recalculate regionfile header if it is corrupt | Spottedleaf | |
@ -91,8 +94,9 @@ # Patches
| server | Brand changes | Spottedleaf | |
| server | Brandings | YatopiaMC | |
| server | Breedable Polar Bears | William Blake Galbreath | |
| api | Bring back server name | William Blake Galbreath | |
| server | Bring back server name | William Blake Galbreath | |
| api | Bring back server name | William Blake Galbreath | |
| server | Cache palette array | Paul Sauve | |
| server | Cat spawning options | William Blake Galbreath | |
| server | Change writes to use NORMAL priority rather than LOW | Spottedleaf | |
| server | Changeable Mob Left Handed Chance | Ben Kerllenevich | |
@ -102,6 +106,8 @@ # Patches
| server | Config migration: climbing should not bypass cramming | jmp | |
| server | Config migration: disable saving projectiles to disk -&gt; | jmp | |
| server | Config to allow Note Block sounds when blocked | Encode42 | |
| server | Config to always tame in Creative | Encode42 | |
| server | Config to use infinity bows without arrows | Encode42 | |
| server | Configurable BlockPhysicsEvent | Mykyta Komarnytskyy | |
| server | Configurable TPS Catchup | William Blake Galbreath | |
| server | Configurable chance for wolves to spawn rabid | Encode42 | |
@ -141,7 +147,6 @@ # Patches
| server | Do not allow ticket level changes while unloading | Spottedleaf | |
| server | Do not load chunks during a crash report | Spottedleaf | |
| server | Do not retain playerchunkmap instance in light thread factory | Spottedleaf | |
| server | Do not update distance map when animal and mob spawning is | Beech Horn | |
| server | Don&#39;t allow StructureLocateEvent to change worlds | Spottedleaf | |
| server | Don&#39;t get entity equipment if not needed | Paul Sauve | |
| server | Don&#39;t load chunk with seed based feature search | Phoenix616 | |
@ -149,21 +154,18 @@ # Patches
| server | Don&#39;t trigger Lootable Refresh for non player interaction | Aikar | |
| server | Don&#39;t wake up entities when damage event is cancelled | Phoenix616 | |
| server | Dont send useless entity packets | William Blake Galbreath | |
| api | DragonEggPlaceEvent | William Blake Galbreath | |
| server | DragonEggPlaceEvent | William Blake Galbreath | |
| server | Duplicate paper&#39;s vanilla scoreboard colors patch to sync | William Blake Galbreath | |
| server | Dynamic activation range | Paul Sauve | |
| server | EMC - Configurable disable give dropping | Aikar | |
| api | EMC - MonsterEggSpawnEvent | Aikar | |
| server | EMC - MonsterEggSpawnEvent | Aikar | |
| api | EMC - MonsterEggSpawnEvent | Aikar | |
| server | End crystal explosion options | Ben Kerllenevich | |
| server | End gateway should check if entity can use portal | William Blake Galbreath | |
| server | Ender dragon always drop egg | William Blake Galbreath | |
| server | Ender dragon always drop full exp | William Blake Galbreath | |
| server | Ensure pools create daemon threads | Ivan Pekov | |
| server | Entities can use portals configuration | William Blake Galbreath | |
| server | Entities pick up loot bypass mob-griefing gamerule | William Blake Galbreath | |
| server | Entity lifespan | William Blake Galbreath | |
| api | EntityMoveEvent | William Blake Galbreath | |
| server | EntityMoveEvent | William Blake Galbreath | |
| server | Execute chunk tasks mid-tick | Spottedleaf | |
| api | ExecuteCommandEvent | William Blake Galbreath | |
| server | Farmland trampling changes | Mariell Hoversholm | |
@ -171,6 +173,7 @@ # Patches
| server | Fix Bukkit.createInventory() with type LECTERN | willies952002 | |
| server | Fix IndexOutOfBoundsException when sending too many changes | Ivan Pekov | |
| server | Fix LightEngineThreaded memory leak | Ivan Pekov | |
| server | Fix PlayerEditBookEvent not saving new book | BillyGalbreath | |
| server | Fix cow rotation when shearing mooshroom | William Blake Galbreath | |
| server | Fix death message colors | William Blake Galbreath | |
| server | Fix exp drop of zombie pigmen (MC-56653) | Phoenix616 | |
@ -181,12 +184,13 @@ # Patches
| server | Fix swamp hut cat generation deadlock | Spottedleaf | |
| server | Fix the dead lagging the server | William Blake Galbreath | |
| server | Fix vanilla command permission handler | William Blake Galbreath | |
| api | Full netherite armor grants fire resistance | BillyGalbreath | |
| server | Flying squids! Oh my! | William Blake Galbreath | |
| server | Full netherite armor grants fire resistance | BillyGalbreath | |
| api | Full netherite armor grants fire resistance | BillyGalbreath | |
| server | Giants AI settings | William Blake Galbreath | |
| server | Global Eula file | tr7zw | |
| server | Heavily optimize furnance fuel and recipe lookups | tr7zw | Mykyta Komarn |
| server | Heavily optimize recipe lookups in CraftingManager | Mykyta Komarn | Ivan Pekov |
| server | Heavily optimize recipe lookups in CraftingManager | Mykyta Komarn | Ivan Pekov, ishland |
| server | Highly optimise single and multi-AABB VoxelShapes and | Spottedleaf | |
| server | Highly optimize VillagePlace filtering | Ivan Pekov | |
| server | Hopper Optimizations | Phoenix616 | |
@ -200,29 +204,27 @@ # Patches
| server | Improve abnormal server shutdown process | Spottedleaf | |
| server | Improve async tp to not load chunks when crossing worlds | Spottedleaf | |
| server | Improve paper prevent moving into unloaded chunk check | Spottedleaf | |
| server | Improve task performance | ishland | Mykyta Komarn |
| server | Improved oversized chunk data packet handling | Spottedleaf | |
| server | Infinite fuel furnace | William Blake Galbreath | |
| server | Infinity No Arrows | Zoe | |
| server | Infinity bow settings | William Blake Galbreath | |
| api | Item entity immunities | William Blake Galbreath | |
| server | Item entity immunities | William Blake Galbreath | |
| api | Item entity immunities | William Blake Galbreath | |
| server | Item stuck sleep config | tr7zw | |
| api | ItemFactory#getMonsterEgg | William Blake Galbreath | |
| server | ItemFactory#getMonsterEgg | William Blake Galbreath | |
| api | ItemFactory#getMonsterEgg | William Blake Galbreath | |
| api | ItemStack convenience methods | William Blake Galbreath | |
| server | Kelp weeping and twisting vines configurable max growth age | BillyGalbreath | |
| server | Lag compensate block breaking | Spottedleaf | |
| api | Lagging threshold | William Blake Galbreath | |
| server | Lagging threshold | William Blake Galbreath | |
| api | Left handed API | BillyGalbreath | |
| api | Lagging threshold | William Blake Galbreath | |
| server | Left handed API | BillyGalbreath | |
| api | LivingEntity safeFallDistance | William Blake Galbreath | |
| api | Left handed API | BillyGalbreath | |
| server | LivingEntity safeFallDistance | William Blake Galbreath | |
| api | LivingEntity#broadcastItemBreak | William Blake Galbreath | |
| api | LivingEntity safeFallDistance | William Blake Galbreath | |
| server | LivingEntity#broadcastItemBreak | William Blake Galbreath | |
| api | Llama API | William Blake Galbreath | |
| api | LivingEntity#broadcastItemBreak | William Blake Galbreath | |
| server | Llama API | William Blake Galbreath | |
| api | Llama API | William Blake Galbreath | |
| server | Lobotomize stuck villagers | BillyGalbreath | |
| server | Logger settings (suppressing pointless logs) | William Blake Galbreath | |
| server | MC-147659 - Fix non black cats spawning in swamp huts | William Blake Galbreath | |
@ -235,13 +237,14 @@ # Patches
| server | Make sure inlined getChunkAt has inlined logic for loaded | Spottedleaf | |
| server | Manually inline methods in BlockPosition | Spottedleaf | |
| server | Mending mends most damages equipment first | William Blake Galbreath | |
| api | Modify POM | YatopiaMC | |
| server | Modify POM | YatopiaMC | |
| api | Modify POM | YatopiaMC | |
| server | Modify default configs | tr7zw | |
| server | Movement options for armour stands | Mariell Hoversholm | |
| server | Multi-Threaded Server Ticking Vanilla | Spottedleaf | |
| server | Multi-Threaded ticking CraftBukkit | Spottedleaf | |
| server | Name craft scheduler threads according to the plugin using | Spottedleaf | |
| server | New nbt cache | Hugo Planque | ishland |
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| api | Optimise Bukkit&#39;s MapPalette | epserv | |
@ -277,28 +280,28 @@ # Patches
| server | Per entity (type) collision settings | MrIvanPlays | tr7zw |
| server | Persistent TileEntity Lore and DisplayName | jmp | |
| server | Phantom flames on swoop | BillyGalbreath | |
| api | Phantoms attracted to crystals and crystals shoot phantoms | William Blake Galbreath | |
| server | Phantoms attracted to crystals and crystals shoot phantoms | William Blake Galbreath | |
| api | Phantoms attracted to crystals and crystals shoot phantoms | William Blake Galbreath | |
| server | Phantoms burn in light | draycia | |
| server | Pigs give saddle back | William Blake Galbreath | |
| api | Player invulnerabilities | William Blake Galbreath | |
| server | Player invulnerabilities | William Blake Galbreath | |
| api | PlayerAttackEntityEvent | Ivan Pekov | |
| api | Player invulnerabilities | William Blake Galbreath | |
| server | PlayerAttackEntityEvent | Ivan Pekov | |
| api | PlayerBookTooLargeEvent | BillyGalbreath | |
| api | PlayerAttackEntityEvent | Ivan Pekov | |
| server | PlayerBookTooLargeEvent | BillyGalbreath | |
| api | PlayerSetSpawnerTypeWithEggEvent | William Blake Galbreath | |
| api | PlayerBookTooLargeEvent | BillyGalbreath | |
| server | PlayerSetSpawnerTypeWithEggEvent | William Blake Galbreath | |
| api | PlayerSetSpawnerTypeWithEggEvent | William Blake Galbreath | |
| server | Players should not cram to death | William Blake Galbreath | |
| server | Populator seed controls | Spottedleaf | |
| server | Port hydrogen | JellySquid | |
| server | Preload ProtocolLib EnumWrappers | ishland | |
| server | Prevent light queue overfill when no players are online | Spottedleaf | |
| server | Prevent long map entry creation in light engine | Spottedleaf | |
| server | Prevent unload() calls removing tickets for sync loads | Spottedleaf | |
| server | Properly handle cancellation of projectile hit event | Spottedleaf | |
| api | ProxyForwardDataEvent | Ivan Pekov | |
| server | ProxyForwardDataEvent | Ivan Pekov | |
| api | Purpur config files | William Blake Galbreath | |
| server | Purpur config files | William Blake Galbreath | |
| api | Purpur config files | William Blake Galbreath | |
| server | Queue lighting update only once | Paul Sauve | |
| server | Rabbit naturally spawn toast and killer | William Blake Galbreath | |
| api | Rabid Wolf API | Encode42 | |
@ -308,18 +311,22 @@ # Patches
| server | Redirect Configs | tr7zw | |
| server | Redstone deactivates spawners | draycia | |
| server | Reduce allocation rate from crammed entities | Spottedleaf | |
| server | Reduce allocs &amp; improve perf of StructureManager | Paul Sauve | |
| server | Reduce chunk loading &amp; lookups | Paul Sauve | |
| server | Reduce iterator allocation from chunk gen | Spottedleaf | |
| server | Reduce memory allocations | Paul Sauve | |
| server | Reduce pathfinder branches | Spottedleaf | |
| server | Reduce projectile chunk loading | Paul Sauve | |
| server | Remove some streams and object allocations | Phoenix616 | |
| server | Remove streams | Paul Sauve | |
| server | Remove streams for villager AI | Spottedleaf | |
| server | Respect PlayerKickEvent leaveMessage | Ivan Pekov | |
| server | Revert MC-4 fix | Spottedleaf | |
| server | Revert getChunkAt(Async) retaining chunks for long periods of | Spottedleaf | |
| server | Rework PlayerChunk main thread checks | Spottedleaf | |
| server | Rewrite the light engine | Spottedleaf | |
| api | Ridables | William Blake Galbreath | |
| server | Ridables | William Blake Galbreath | |
| api | Ridables | William Blake Galbreath | |
| server | Separate lookup locking from state access in UserCache | Spottedleaf | |
| server | Set name visible when using a Name Tag on an Armor Stand | jmp | |
| server | Short enderman height | William Blake Galbreath | |
@ -341,20 +348,22 @@ # Patches
| server | Stop wasting resources on JsonList#get | Ivan Pekov | |
| server | Striders give saddle back | Ben Kerllenevich | |
| server | Strip raytracing for EntityLiving#hasLineOfSight | Paul Sauve | |
| server | Suspected plugins report | ishland | |
| api | Suspected plugins report | ishland | |
| server | Swap priority of checks in chunk ticking | Paul Sauve | |
| server | Time scoreboard search | Spottedleaf | |
| server | Timings stuff | William Blake Galbreath | |
| server | Toggle for Zombified Piglin death always counting as player | jmp | |
| server | Toggle for water sensitive mob damage | YouHaveTrouble | |
| server | Totems work in inventory | draycia | |
| api | Tuinity POM Changes | Spottedleaf | |
| server | Tuinity POM Changes | Spottedleaf | |
| api | Tuinity POM Changes | Spottedleaf | |
| server | Tuinity Server Config | Spottedleaf | |
| api | Tuinity config | Spottedleaf | |
| server | Tulips change fox type | William Blake Galbreath | |
| server | Update version fetcher repo | JRoy | |
| server | Use configured height for nether surface builders | William Blake Galbreath | |
| server | Use entity ticking chunk map for entity tracker | Spottedleaf | |
| server | Use offline uuids if we need to | Ivan Pekov | |
| server | Use unmodifiableMap instead of making copy | Paul Sauve | |
| server | Util patch | Spottedleaf | |
| server | Utilities | YatopiaMC | Mykyta Komarnytskyy, Ivan Pekov |
@ -377,3 +386,4 @@ # Patches
| server | lithium VoronoiBiomeAccessTypeMixin | JellySquid | |
| server | lithium enum_values | JellySquid | |
| server | lithium reduce allocations | JellySquid | Mykyta Komarnytskyy |
| server | lithium: cache chunk gen sea level | SuperCoder7979 | |

2
Paper

@ -1 +1 @@
Subproject commit 8fa15382bd7229e2688bb4b65c3f5fd823d4e23a
Subproject commit 088fa6f28b029e58cfe286608fff9803f932a512

View File

@ -6,7 +6,7 @@
[![CodeMC](https://ci.codemc.io/buildStatus/icon?job=YatopiaMC%2FYatopia%2Fver%252F1.16.5)](https://ci.codemc.io/job/YatopiaMC/job/Yatopia/job/ver%252F1.16.5/)
[![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discord.io/YatopiaMC)
[![API](https://img.shields.io/website?down_color=lightgrey&down_message=offline&label=API&up_color=green&up_message=online&url=http%3A%2F%2Fapi.yatopiamc.org%2F)](https://api.yatopiamc.org/v2/latestBuild?branch=ver/1.16.5)
<h3>Blazing fast <a href="https://github.com/Spottedleaf/Tuinity">Tuinity</a> fork with no-compromises performance.</h3>
<h3>Blazing fast <a href="https://github.com/Spottedleaf/Tuinity">Tuinity</a> fork with best in class performance.</h3>
</div>
## So what is Yatopia?
@ -17,7 +17,9 @@ ## So what is Yatopia?
* [Lithium](https://github.com/jellysquid3/lithium-fabric)
* [Origami](https://github.com/Minebench/Origami)
* [Purpur](https://github.com/pl3xgaming/Purpur)
* [AirplaneLite](https://github.com/Technove/AirplaneLite)
* [Airplane](https://github.com/Technove/Airplane)
* [Hydrogen](https://github.com/jellysquid3/hydrogen-fabric)
* [Krypton](https://github.com/astei/krypton)
## Try it out

11
Yatoclip/build.gradle.kts Normal file
View File

@ -0,0 +1,11 @@
repositories {
mavenCentral()
maven("https://jitpack.io/")
}
dependencies {
implementation("com.github.ishlandbukkit:jbsdiff:deff66b794")
implementation("com.google.code.gson:gson:2.8.6")
implementation("commons-io:commons-io:2.8.0")
}

View File

@ -0,0 +1,28 @@
package org.yatopiamc.yatoclip;
import java.lang.instrument.Instrumentation;
import java.nio.file.Path;
import java.util.jar.JarFile;
public class YatoclipLaunch {
private static Instrumentation inst = null;
public static void premain(String args, Instrumentation inst) {
YatoclipLaunch.inst = inst;
}
public static void agentmain(final String agentArgs, final Instrumentation inst) {
YatoclipLaunch.inst = inst;
}
@SuppressWarnings("unused")
static void injectClasspath(Path setup) throws Throwable {
if(inst == null) {
throw new RuntimeException("Instrumentation API handle not found");
}
inst.appendToSystemClassLoaderSearch(new JarFile(setup.toFile()));
inst = null;
}
}

View File

@ -0,0 +1,51 @@
package org.yatopiamc.yatoclip;
import java.io.Serializable;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
public class PatchesMetadata {
public final Set<PatchMetadata> patches;
public final Set<Relocation> relocations;
public final Set<String> copyExcludes;
public PatchesMetadata(Set<PatchMetadata> patches, Set<Relocation> relocations, Set<String> copyExcludes) {
Objects.requireNonNull(copyExcludes);
this.copyExcludes = Collections.unmodifiableSet(copyExcludes);
Objects.requireNonNull(relocations);
this.relocations = Collections.unmodifiableSet(relocations);
Objects.requireNonNull(patches);
this.patches = Collections.unmodifiableSet(patches);
}
public static class PatchMetadata {
public final String name;
public final String originalHash;
public final String targetHash;
public final String patchHash;
public PatchMetadata(String name, String originalHash, String targetHash, String patchHash) {
this.name = name;
this.originalHash = originalHash;
this.targetHash = targetHash;
this.patchHash = patchHash;
}
}
public static class Relocation implements Serializable {
public final String from;
public final String to;
public final boolean includeSubPackages;
public Relocation(String from, String to, boolean includeSubPackages) {
Objects.requireNonNull(from);
Objects.requireNonNull(to);
this.from = from.replaceAll("\\.", "/");
this.to = to.replaceAll("\\.", "/");
this.includeSubPackages = includeSubPackages;
}
}
}

View File

@ -0,0 +1,360 @@
package org.yatopiamc.yatoclip;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;
public class ServerSetup {
private static final String minecraftVersion;
private static final Path cacheDirectory;
private static final Gson gson = new Gson();
private static VersionInfo versionInfo = null;
private static BuildDataInfo buildDataInfo = null;
static {
Properties prop = new Properties();
try (InputStream inputStream = ServerSetup.class.getClassLoader().getResourceAsStream("yatoclip-launch.properties")) {
prop.load(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
minecraftVersion = prop.getProperty("minecraftVersion");
cacheDirectory = Paths.get("cache", minecraftVersion);
cacheDirectory.toFile().mkdirs();
}
public static Path setup() throws IOException {
long startTime = System.nanoTime();
checkBuildData();
applyMappingsAndPatches();
System.err.println(String.format("Yatoclip server setup completed in %.2fms", (System.nanoTime() - startTime) / 1_000_000.0));
return cacheDirectory.resolve("Minecraft").resolve(minecraftVersion + "-patched.jar");
}
private static void applyMappingsAndPatches() throws IOException {
final Path minecraftDir = cacheDirectory.resolve("Minecraft");
minecraftDir.toFile().mkdirs();
final Path vanillaJar = minecraftDir.resolve(minecraftVersion + ".jar");
if (!isValidZip(vanillaJar)) {
System.err.println("Downloading vanilla jar...");
download(new URL(buildDataInfo.serverUrl), vanillaJar);
if (!isValidZip(vanillaJar)) throw new RuntimeException("Invalid vanilla jar");
}
final Path classMappedJar = minecraftDir.resolve(minecraftVersion + "-cl.jar");
final Path memberMappedJar = minecraftDir.resolve(minecraftVersion + "-m.jar");
final Path patchedJar = minecraftDir.resolve(minecraftVersion + "-patched.jar");
if (!isValidZip(classMappedJar) || !isValidZip(memberMappedJar)) {
SpecialSourceLauncher.resetSpecialSourceClassloader();
final Path buildData = cacheDirectory.resolve("BuildData");
SpecialSourceLauncher.setSpecialSourceJar(buildData.resolve("bin").resolve("SpecialSource-2.jar").toFile());
System.err.println("Applying class mapping...");
SpecialSourceLauncher.runProcess(
"map", "--only", ".", "--only", "net/minecraft", "--auto-lvt", "BASIC", "--auto-member", "SYNTHETIC",
"-i", vanillaJar.toAbsolutePath().toString(),
"-m", buildData.resolve("mappings").resolve(buildDataInfo.classMappings).toAbsolutePath().toString(),
"-o", classMappedJar.toAbsolutePath().toString()
);
System.err.println("Applying member mapping...");
SpecialSourceLauncher.runProcess(
"map", "--only", ".", "--only", "net/minecraft", "--auto-member", "LOGGER", "--auto-member", "TOKENS",
"-i", classMappedJar.toAbsolutePath().toString(),
"-m", buildData.resolve("mappings").resolve(buildDataInfo.memberMappings).toAbsolutePath().toString(),
"-o", memberMappedJar.toAbsolutePath().toString()
);
SpecialSourceLauncher.resetSpecialSourceClassloader();
if (!isValidZip(classMappedJar) || !isValidZip(memberMappedJar))
throw new RuntimeException("Unable to apply mappings");
}
if (!YatoclipPatcher.isJarUpToDate(patchedJar)){
System.err.println("Applying patches...");
YatoclipPatcher.patchJar(memberMappedJar, patchedJar);
if(!YatoclipPatcher.isJarUpToDate(patchedJar))
throw new RuntimeException("Unable to apply patches");
}
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private static boolean isValidZip(Path zipPath) {
try {
ZipFile zipFile = new ZipFile(zipPath.toFile());
zipFile.close();
} catch (Throwable t) {
return false;
}
return true;
}
private static void checkBuildData() throws IOException {
final Path buildDataDir = cacheDirectory.resolve("BuildData");
buildDataDir.toFile().mkdirs();
final Path versionInfoFile = buildDataDir.resolve("version.json");
if (!tryParseVersionInfo(versionInfoFile)) {
System.err.println("Downloading version.json...");
final URL versionInfoURI = new URL("https://hub.spigotmc.org/versions/" + minecraftVersion + ".json");
download(versionInfoURI, versionInfoFile);
if (!tryParseVersionInfo(versionInfoFile)) throw new RuntimeException("Unable to parse versionInfo");
}
final Path buildDataArchive = buildDataDir.resolve("BuildData.zip");
if (!tryParseBuildData(buildDataArchive)) {
System.err.println("Downloading BuildData...");
final URL buildDataURL = new URL("https://hub.spigotmc.org/stash/rest/api/latest/projects/SPIGOT/repos/builddata/archive?at=" + ServerSetup.versionInfo.refs.buildData + "&format=zip");
download(buildDataURL, buildDataArchive);
if (!tryParseBuildData(buildDataArchive)) throw new RuntimeException("Unable to parse BuildData");
}
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private static boolean tryParseBuildData(Path buildData) {
try {
ZipFile zipFile = new ZipFile(buildData.toFile());
((Iterator<ZipEntry>) zipFile.entries()).forEachRemaining(zipEntry -> {
if (zipEntry.isDirectory()) return;
buildData.getParent().resolve(zipEntry.getName()).getParent().toFile().mkdirs();
try (
final ReadableByteChannel source = Channels.newChannel(zipFile.getInputStream(zipEntry));
final FileChannel fileChannel = FileChannel.open(buildData.getParent().resolve(zipEntry.getName()), CREATE, WRITE, TRUNCATE_EXISTING)
) {
fileChannel.transferFrom(source, 0, Long.MAX_VALUE);
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
zipFile.close();
try (Reader reader = Files.newBufferedReader(buildData.getParent().resolve("info.json"))){
ServerSetup.buildDataInfo = gson.fromJson(reader, BuildDataInfo.class);
}
} catch (Throwable t) {
return false;
}
return true;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private static boolean tryParseVersionInfo(Path versionInfo) {
try (Reader reader = Files.newBufferedReader(versionInfo)) {
ServerSetup.versionInfo = gson.fromJson(reader, VersionInfo.class);
} catch (Throwable t) {
return false;
}
return true;
}
private static void download(URL url, Path downloadTo) throws IOException {
try (
final ReadableByteChannel source = Channels.newChannel(url.openStream());
final FileChannel fileChannel = FileChannel.open(downloadTo, CREATE, WRITE, TRUNCATE_EXISTING)
) {
downloadTo.getParent().toFile().mkdirs();
fileChannel.transferFrom(source, 0, Long.MAX_VALUE);
}
}
static String toHex(final byte[] hash) {
final StringBuilder sb = new StringBuilder(hash.length * 2);
for (byte aHash : hash) {
sb.append(String.format("%02X", aHash & 0xFF));
}
return sb.toString();
}
public static class VersionInfo {
@SerializedName("refs")
private Refs refs;
@SerializedName("name")
private String name;
@SerializedName("description")
private String description;
@SerializedName("toolsVersion")
private int toolsVersion;
@SerializedName("javaVersions")
private List<Integer> javaVersions;
public Refs getRefs() {
return refs;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public int getToolsVersion() {
return toolsVersion;
}
public List<Integer> getJavaVersions() {
return javaVersions;
}
@Override
public String toString() {
return
"VersionInfo{" +
"refs = '" + refs + '\'' +
",name = '" + name + '\'' +
",description = '" + description + '\'' +
",toolsVersion = '" + toolsVersion + '\'' +
",javaVersions = '" + javaVersions + '\'' +
"}";
}
public static class Refs {
@SerializedName("BuildData")
private String buildData;
@SerializedName("CraftBukkit")
private String craftBukkit;
@SerializedName("Bukkit")
private String bukkit;
@SerializedName("Spigot")
private String spigot;
public String getBuildData() {
return buildData;
}
public String getCraftBukkit() {
return craftBukkit;
}
public String getBukkit() {
return bukkit;
}
public String getSpigot() {
return spigot;
}
@Override
public String toString() {
return
"Refs{" +
"buildData = '" + buildData + '\'' +
",craftBukkit = '" + craftBukkit + '\'' +
",bukkit = '" + bukkit + '\'' +
",spigot = '" + spigot + '\'' +
"}";
}
}
}
public static class BuildDataInfo {
@SerializedName("memberMapCommand")
private String memberMapCommand;
@SerializedName("packageMappings")
private String packageMappings;
@SerializedName("classMapCommand")
private String classMapCommand;
@SerializedName("finalMapCommand")
private String finalMapCommand;
@SerializedName("serverUrl")
private String serverUrl;
@SerializedName("toolsVersion")
private int toolsVersion;
@SerializedName("minecraftHash")
private String minecraftHash;
@SerializedName("minecraftVersion")
private String minecraftVersion;
@SerializedName("accessTransforms")
private String accessTransforms;
@SerializedName("memberMappings")
private String memberMappings;
@SerializedName("decompileCommand")
private String decompileCommand;
@SerializedName("classMappings")
private String classMappings;
public String getMemberMapCommand() {
return memberMapCommand;
}
public String getPackageMappings() {
return packageMappings;
}
public String getClassMapCommand() {
return classMapCommand;
}
public String getFinalMapCommand() {
return finalMapCommand;
}
public String getServerUrl() {
return serverUrl;
}
public int getToolsVersion() {
return toolsVersion;
}
public String getMinecraftHash() {
return minecraftHash;
}
public String getMinecraftVersion() {
return minecraftVersion;
}
public String getAccessTransforms() {
return accessTransforms;
}
public String getMemberMappings() {
return memberMappings;
}
public String getDecompileCommand() {
return decompileCommand;
}
public String getClassMappings() {
return classMappings;
}
}
}

View File

@ -0,0 +1,89 @@
package org.yatopiamc.yatoclip;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
public class SpecialSourceLauncher {
private static final AtomicReference<SpecialSourceClassLoader> classLoader = new AtomicReference<>(new SpecialSourceClassLoader(new URL[0], SpecialSourceLauncher.class.getClassLoader().getParent()));
private static final AtomicReference<String> mainClass = new AtomicReference<>("");
static void setSpecialSourceJar(File specialSourceJar) {
synchronized (classLoader) {
System.err.println("Setting up SpecialSource: " + specialSourceJar);
try {
classLoader.get().addURL(specialSourceJar.toURI().toURL());
mainClass.set(Yatoclip.getMainClass(specialSourceJar.toPath()));
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
}
static void resetSpecialSourceClassloader() {
synchronized (classLoader) {
if(!classLoader.get().isLoaded) return;
System.err.println("Releasing SpecialSource");
try {
classLoader.get().close();
classLoader.set(new SpecialSourceClassLoader(new URL[0], SpecialSourceLauncher.class.getClassLoader().getParent()));
mainClass.set("");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void runProcess(String... command) throws IOException {
if (!(command != null && command.length > 0)) throw new IllegalArgumentException();
System.err.println("Invoking SpecialSource with arguments: " + Arrays.toString(command));
AtomicReference<Throwable> thrown = new AtomicReference<>(null);
final Thread thread = new Thread(() -> {
try {
final Class<?> mainClass = Class.forName(SpecialSourceLauncher.mainClass.get(), true, classLoader.get());
final Method mainMethod = mainClass.getMethod("main", String[].class);
if (!Modifier.isStatic(mainMethod.getModifiers()) || !Modifier.isPublic(mainMethod.getModifiers()))
throw new IllegalArgumentException();
mainMethod.invoke(null, new Object[]{command});
} catch (Throwable t) {
thrown.set(t);
}
});
thread.setName("SpecialSource Thread");
thread.setContextClassLoader(classLoader.get());
thread.start();
while (thread.isAlive())
try {
thread.join();
} catch (InterruptedException ignored) {
}
if (thrown.get() != null)
throw new RuntimeException(thrown.get());
}
private static class SpecialSourceClassLoader extends URLClassLoader {
private volatile boolean isLoaded = false;
public SpecialSourceClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@Override
protected synchronized void addURL(URL url) {
if (isLoaded) throw new IllegalStateException();
this.isLoaded = true;
super.addURL(url);
}
}
}

View File

@ -0,0 +1,41 @@
package org.yatopiamc.yatoclip;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.jar.JarInputStream;
public class Yatoclip {
public static void main(String... args) throws Throwable {
final Path setup = ServerSetup.setup();
launch(setup, args);
}
private static void launch(Path setup, String[] args) throws Throwable {
YatoclipLaunch.injectClasspath(setup);
final Class<?> mainClassInstance = Class.forName("org.bukkit.craftbukkit.Main", true, ClassLoader.getSystemClassLoader());
final Method mainMethod = mainClassInstance.getMethod("main", String[].class);
if(!Modifier.isPublic(mainMethod.getModifiers()) || !Modifier.isStatic(mainMethod.getModifiers())) throw new IllegalArgumentException();
mainMethod.invoke(null, new Object[]{args});
}
static String getMainClass(Path jarPath) throws IOException {
final String mainClass;
try (
InputStream inputStream = Files.newInputStream(jarPath);
JarInputStream jar = new JarInputStream(inputStream)
) {
mainClass = jar.getManifest().getMainAttributes().getValue("Main-Class");
}
return mainClass;
}
}

View File

@ -0,0 +1,24 @@
package org.yatopiamc.yatoclip;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
public class YatoclipLaunch {
public static void premain(String args, Instrumentation inst) {
}
static void injectClasspath(Path setup) throws Throwable {
final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if(!(systemClassLoader instanceof URLClassLoader))
throw new ClassCastException("SystemClassLoader is not an instance of URLClassLoader");
final URLClassLoader classLoader = (URLClassLoader) systemClassLoader;
final Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addURL.setAccessible(true);
addURL.invoke(classLoader, setup.toUri().toURL());
}
}

View File

@ -0,0 +1,236 @@
package org.yatopiamc.yatoclip;
import com.google.gson.Gson;
import io.sigpipe.jbsdiff.InvalidHeaderException;
import io.sigpipe.jbsdiff.Patch;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.io.IOUtils;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import static java.util.Objects.requireNonNull;
public class YatoclipPatcher {
private static final PatchesMetadata patchesMetadata;
static {
try (
final InputStream in = YatoclipPatcher.class.getClassLoader().getResourceAsStream("patches/metadata.json");
final InputStreamReader reader = new InputStreamReader(in);
) {
patchesMetadata = new Gson().fromJson(reader, PatchesMetadata.class);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
static boolean isJarUpToDate(Path patchedJar) {
requireNonNull(patchedJar);
if (!patchedJar.toFile().isFile()) return false;
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
try (ZipFile patchedZip = new ZipFile(patchedJar.toFile())) {
for (PatchesMetadata.PatchMetadata patchMetadata : patchesMetadata.patches) {
ZipEntry zipEntry = patchedZip.getEntry(patchMetadata.name);
if (zipEntry == null || !patchMetadata.targetHash.equals(ServerSetup.toHex(digest.digest(IOUtils.toByteArray(patchedZip.getInputStream(zipEntry))))))
return false;
}
}
return true;
} catch (Throwable t) {
System.out.println(t.toString());
return false;
}
}
static void patchJar(Path memberMappedJar, Path patchedJar) {
requireNonNull(memberMappedJar);
requireNonNull(patchedJar);
if(!memberMappedJar.toFile().isFile()) throw new IllegalArgumentException(new FileNotFoundException());
try {
patchedJar.toFile().getParentFile().mkdirs();
final ThreadLocal<ZipFile> classMappedZip = ThreadLocal.withInitial(() -> {
try {
return new ZipFile(memberMappedJar.toFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
});
final ThreadLocal<MessageDigest> digest = ThreadLocal.withInitial(() -> {
try {
return MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
});
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
private AtomicInteger serial = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(() -> {
try {
r.run();
} finally {
try {
classMappedZip.get().close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.setName("YatoClip Worker #" + serial.incrementAndGet());
thread.setDaemon(true);
return thread;
}
});
try {
final Set<PatchData> patchDataSet = patchesMetadata.patches.stream().map((PatchesMetadata.PatchMetadata metadata) -> new PatchData(CompletableFuture.supplyAsync(() -> {
try {
return getPatchedBytes(classMappedZip.get(), digest.get(), metadata);
} catch (IOException | CompressorException | InvalidHeaderException e) {
throw new RuntimeException(e);
}
}, executorService), metadata)).collect(Collectors.toSet());
try (ZipOutputStream patchedZip = new ZipOutputStream(new FileOutputStream(patchedJar.toFile()))) {
patchedZip.setMethod(ZipOutputStream.DEFLATED);
patchedZip.setLevel(Deflater.BEST_SPEED);
Set<String> processed = new HashSet<>();
for (PatchData patchData : patchDataSet) {
putNextEntrySafe(patchedZip, patchData.metadata.name);
final byte[] patchedBytes = patchData.patchedBytesFuture.join();
patchedZip.write(patchedBytes);
patchedZip.closeEntry();
processed.add(patchData.metadata.name);
}
((Iterator<ZipEntry>) classMappedZip.get().entries()).forEachRemaining(zipEntry -> {
if (zipEntry.isDirectory() || processed.contains(applyRelocations(zipEntry.getName())) || patchesMetadata.copyExcludes.contains(zipEntry.getName()))
return;
try {
InputStream in = classMappedZip.get().getInputStream(zipEntry);
putNextEntrySafe(patchedZip, zipEntry.getName());
patchedZip.write(IOUtils.toByteArray(in));
patchedZip.closeEntry();
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
}
} catch (IOException e) {
throw new RuntimeException(e);
}
executorService.shutdown();
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
private static byte[] getPatchedBytes(ZipFile classMappedZip, MessageDigest digest, PatchesMetadata.PatchMetadata patchMetadata) throws IOException, CompressorException, InvalidHeaderException {
final byte[] originalBytes;
final ZipEntry originalEntry = classMappedZip.getEntry(applyRelocationsReverse(patchMetadata.name));
if (originalEntry != null)
try (final InputStream in = classMappedZip.getInputStream(originalEntry)) {
originalBytes = IOUtils.toByteArray(in);
}
else originalBytes = new byte[0];
final byte[] patchBytes;
try (final InputStream in = YatoclipPatcher.class.getClassLoader().getResourceAsStream("patches/" + patchMetadata.name + ".patch")) {
if (in == null)
throw new FileNotFoundException();
patchBytes = IOUtils.toByteArray(in);
}
if (!patchMetadata.originalHash.equals(ServerSetup.toHex(digest.digest(originalBytes))) || !patchMetadata.patchHash.equals(ServerSetup.toHex(digest.digest(patchBytes))))
throw new FileNotFoundException("Hash do not match");
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
Patch.patch(originalBytes, patchBytes, byteOut);
final byte[] patchedBytes = byteOut.toByteArray();
if (!patchMetadata.targetHash.equals(ServerSetup.toHex(digest.digest(patchedBytes))))
throw new FileNotFoundException("Hash do not match");
return patchedBytes;
}
private static void putNextEntrySafe(ZipOutputStream patchedZip, String name) throws IOException {
String[] split = name.split("/");
split = Arrays.copyOfRange(split, 0, split.length - 1);
StringBuilder sb = new StringBuilder();
for (String s : split) {
sb.append(s).append("/");
try {
patchedZip.putNextEntry(new ZipEntry(sb.toString()));
} catch (ZipException e) {
if (e.getMessage().startsWith("duplicate entry"))
continue;
throw e;
}
}
final ZipEntry entry = new ZipEntry(name);
patchedZip.putNextEntry(entry);
}
private static String applyRelocations(String name) {
if (!name.endsWith(".class")) return name;
if (name.indexOf('/') == -1)
name = "/" + name;
for (PatchesMetadata.Relocation relocation : patchesMetadata.relocations) {
if (name.startsWith(relocation.from) && (relocation.includeSubPackages || name.split("/").length == name.split("/").length - 1)) {
return relocation.to + name.substring(relocation.from.length());
}
}
return name;
}
private static String applyRelocationsReverse(String name) {
if (!name.endsWith(".class")) return name;
if (name.indexOf('/') == -1)
name = "/" + name;
for (PatchesMetadata.Relocation relocation : patchesMetadata.relocations) {
if (name.startsWith(relocation.to) && (relocation.includeSubPackages || name.split("/").length == name.split("/").length - 1)) {
return relocation.from + name.substring(relocation.to.length());
}
}
return name;
}
private static class PatchData {
public final CompletableFuture<byte[]> patchedBytesFuture;
public final PatchesMetadata.PatchMetadata metadata;
private PatchData(CompletableFuture<byte[]> patchedBytesFuture, PatchesMetadata.PatchMetadata metadata) {
Objects.requireNonNull(patchedBytesFuture);
Objects.requireNonNull(metadata);
this.patchedBytesFuture = patchedBytesFuture.thenApply(Objects::requireNonNull);
this.metadata = metadata;
}
}
}

View File

@ -9,7 +9,17 @@ toothpick {
groupId = "org.yatopiamc"
val versionTag = System.getenv("BUILD_NUMBER")
?: "\"${gitCmd("rev-parse", "--short", "HEAD").output}\""
forkVersion = "git-$forkName-$versionTag"
if(!System.getenv("BRANCH_NAME").isNullOrEmpty()) {
currentBranch = System.getenv("BRANCH_NAME")
} else if (!System.getenv("GITHUB_HEAD_REF").isNullOrEmpty()) {
currentBranch = System.getenv("GITHUB_HEAD_REF")
} else if (!System.getenv("GITHUB_REF").isNullOrEmpty()) {
currentBranch = System.getenv("GITHUB_REF").substring("refs/heads/".length)
} else {
currentBranch = gitCmd("rev-parse", "--abbrev-ref", "HEAD").output.toString().trim()
if(currentBranch == "HEAD") logger.warn("You are currently in \'detached HEAD\' state, branch information isn\'t available")
}
forkVersion = "git-$forkName-$currentBranch-$versionTag"
forkUrl = "https://github.com/YatopiaMC/Yatopia"
minecraftVersion = "1.16.5"
@ -32,6 +42,8 @@ toothpick {
project = project(":$forkNameLowercase-api")
patchesDir = rootProject.projectDir.resolve("patches/api")
}
logger.lifecycle("Configured version string: $calcVersionString")
}
subprojects {
@ -42,6 +54,7 @@ subprojects {
maven("https://libraries.minecraft.net")
maven("https://repo.codemc.io/repository/maven-public/")
mavenLocal()
maven("${rootProjectDir}/.repository")
}
java {
@ -52,9 +65,4 @@ subprojects {
targetCompatibility = JavaVersion.current()
withSourcesJar()
}
publishing.repositories.maven {
url = uri("https://repo.codemc.io/repository/maven-snapshots/")
credentials(PasswordCredentials::class)
}
}

View File

@ -11,6 +11,7 @@ repositories {
mavenCentral()
jcenter()
maven("https://plugins.gradle.org/m2/")
maven("https://jitpack.io/")
}
dependencies {
@ -18,6 +19,15 @@ dependencies {
implementation("com.github.jengelman.gradle.plugins:shadow:$shadowVersion")
implementation("com.github.spullara.mustache.java:compiler:$mustacheVersion")
implementation("javax.mail:mail:$javaxMailVersion")
implementation("com.github.ishlandbukkit:jbsdiff:deff66b794")
implementation("com.google.code.gson:gson:2.8.6")
implementation("com.google.guava:guava:30.0-jre")
implementation("commons-io:commons-io:2.8.0")
}
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
sourceCompatibility = "1.8"
}
gradlePlugin {

View File

@ -0,0 +1,269 @@
package org.yatopiamc.yatoclip.gradle;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gson.Gson;
import io.sigpipe.jbsdiff.Diff;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.logging.progress.ProgressLogger;
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.work.Incremental;
import org.gradle.workers.WorkerExecutor;
import javax.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class MakePatchesTask extends DefaultTask {
@OutputDirectory
private final File outputDir = ((Copy) getProject().getTasks().getByPath("processResources")).getDestinationDir().toPath().resolve("patches").toFile();
@InputFile
@Incremental
public File originalJar = null;
@InputFile
@Incremental
public File targetJar = null;
public Set<PatchesMetadata.Relocation> getRelocations() {
return relocations;
}
public void setRelocations(Set<PatchesMetadata.Relocation> relocations) {
this.relocations = relocations;
}
@Input
public Set<PatchesMetadata.Relocation> relocations;
public File getOriginalJar() {
return originalJar;
}
public void setOriginalJar(File originalJar) {
this.originalJar = originalJar;
}
public File getTargetJar() {
return targetJar;
}
public void setTargetJar(File targetJar) {
this.targetJar = targetJar;
}
public File getOutputDir() {
return outputDir;
}
private ProgressLoggerFactory getProgressLoggerFactory() {
return ((ProjectInternal) getProject()).getServices().get(ProgressLoggerFactory.class);
}
@Inject
public WorkerExecutor getWorkerExecutor() {
throw new UnsupportedOperationException();
}
@TaskAction
public void genPatches() throws IOException, InterruptedException {
Preconditions.checkNotNull(originalJar);
Preconditions.checkNotNull(targetJar);
getLogger().lifecycle("Generating patches for " + originalJar + " -> " + targetJar);
final ProgressLogger genPatches = getProgressLoggerFactory().newOperation(getClass()).setDescription("Generate patches");
genPatches.started();
genPatches.progress("Cleanup");
outputDir.mkdirs();
FileUtils.cleanDirectory(outputDir);
genPatches.progress("Reading files");
ThreadLocal<ZipFile> originalZip = ThreadLocal.withInitial(() -> {
try {
return new ZipFile(originalJar);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
ThreadLocal<ZipFile> targetZip = ThreadLocal.withInitial(() -> {
try {
return new ZipFile(targetJar);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
Set<PatchesMetadata.PatchMetadata> patchMetadata = Sets.newConcurrentHashSet();
ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
try {
return MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
});
ThreadLocal<ProgressLogger> progressLoggerThreadLocal = ThreadLocal.withInitial(() -> {
final ProgressLogger progressLogger = getProgressLoggerFactory().newOperation(this.getClass());
progressLogger.setDescription("Patch worker");
progressLogger.started("Idle");
return progressLogger;
});
final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
new ThreadFactoryBuilder().setNameFormat("MakePatches-%d").setThreadFactory(r -> new Thread(() -> {
boolean isExceptionOccurred = false;
try {
r.run();
} catch (Throwable t) {
isExceptionOccurred = true;
progressLoggerThreadLocal.get().completed(t.toString(), true);
throw t;
} finally {
digestThreadLocal.remove();
if (!isExceptionOccurred)
progressLoggerThreadLocal.get().completed();
progressLoggerThreadLocal.remove();
try {
originalZip.get().close();
targetZip.get().close();
} catch (IOException e) {
e.printStackTrace();
}
}
})).build());
AtomicInteger current = new AtomicInteger(0);
final int size = targetZip.get().size();
((Iterator<ZipEntry>) targetZip.get().entries()).forEachRemaining(zipEntryT -> {
genPatches.progress("Submitting tasks (" + current.incrementAndGet() + "/" + size + ")");
if (zipEntryT.isDirectory()) return;
executorService.execute(() -> {
ZipEntry zipEntry = targetZip.get().getEntry(zipEntryT.getName());
final String child = zipEntry.getName();
progressLoggerThreadLocal.get().progress("Reading " + zipEntry.getName());
File outputFile = new File(outputDir, child + ".patch");
outputFile.getParentFile().mkdirs();
final byte[] originalBytes;
final byte[] targetBytes;
final ZipEntry oEntry = originalZip.get().getEntry(applyRelocationsReverse(child));
try (
final InputStream oin = oEntry != null ? originalZip.get().getInputStream(oEntry) : null;
final InputStream tin = targetZip.get().getInputStream(zipEntry);
) {
originalBytes = oin != null ? IOUtils.toByteArray(oin) : new byte[0];
targetBytes = IOUtils.toByteArray(tin);
} catch (Throwable e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
if (Arrays.equals(originalBytes, targetBytes)) return;
progressLoggerThreadLocal.get().progress("GenPatch " + zipEntry.getName());
try (final OutputStream out = new FileOutputStream(outputFile)) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Diff.diff(originalBytes, targetBytes, byteArrayOutputStream);
patchMetadata.add(new PatchesMetadata.PatchMetadata(child, toHex(digestThreadLocal.get().digest(originalBytes)), toHex(digestThreadLocal.get().digest(targetBytes)), toHex(digestThreadLocal.get().digest(byteArrayOutputStream.toByteArray()))));
out.write(byteArrayOutputStream.toByteArray());
} catch (Throwable t) {
Throwables.throwIfUnchecked(t);
throw new RuntimeException(t);
}
progressLoggerThreadLocal.get().progress("Idle");
});
});
genPatches.progress("Calculating exclusions");
Set<String> copyExcludes = new HashSet<>();
((Iterator<ZipEntry>) originalZip.get().entries()).forEachRemaining(zipEntry -> {
if(targetZip.get().getEntry(applyRelocations(zipEntry.getName())) == null)
copyExcludes.add(zipEntry.getName());
});
originalZip.get().close();
targetZip.get().close();
genPatches.progress("Waiting for patching to finish");
executorService.shutdown();
while (!executorService.awaitTermination(1, TimeUnit.SECONDS)) ;
digestThreadLocal.remove();
genPatches.progress("Writing patches metadata");
try (final OutputStream out = new FileOutputStream(new File(outputDir, "metadata.json"));
final Writer writer = new OutputStreamWriter(out)) {
new Gson().toJson(new PatchesMetadata(patchMetadata, relocations, copyExcludes), writer);
}
/*
genPatches.progress("Reading jar files into memory");
byte[] origin = Files.readAllBytes(originalJar.toPath());
byte[] target = Files.readAllBytes(targetJar.toPath());
genPatches.progress("Generating patch");
try(final OutputStream out = new BufferedOutputStream(new FileOutputStream(output))){
Diff.diff(origin, target, out);
}
*/
genPatches.completed();
}
private String applyRelocations(String name) {
if(!name.endsWith(".class")) return name;
if (name.indexOf('/') == -1)
name = "/" + name;
for (PatchesMetadata.Relocation relocation : relocations) {
if (name.startsWith(relocation.from) && (relocation.includeSubPackages || name.split("/").length == name.split("/").length - 1)) {
return relocation.to + name.substring(relocation.from.length());
}
}
return name;
}
private String applyRelocationsReverse(String name) {
if(!name.endsWith(".class")) return name;
if (name.indexOf('/') == -1)
name = "/" + name;
for (PatchesMetadata.Relocation relocation : relocations) {
if (name.startsWith(relocation.to) && (relocation.includeSubPackages || name.split("/").length == name.split("/").length - 1)) {
return relocation.from + name.substring(relocation.to.length());
}
}
return name;
}
public static String toHex(final byte[] hash) {
final StringBuilder sb = new StringBuilder(hash.length * 2);
for (byte aHash : hash) {
sb.append(String.format("%02X", aHash & 0xFF));
}
return sb.toString();
}
}

View File

@ -0,0 +1,51 @@
package org.yatopiamc.yatoclip.gradle;
import java.io.Serializable;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
public class PatchesMetadata {
public final Set<PatchMetadata> patches;
public final Set<Relocation> relocations;
public final Set<String> copyExcludes;
public PatchesMetadata(Set<PatchMetadata> patches, Set<Relocation> relocations, Set<String> copyExcludes) {
Objects.requireNonNull(copyExcludes);
this.copyExcludes = Collections.unmodifiableSet(copyExcludes);
Objects.requireNonNull(relocations);
this.relocations = Collections.unmodifiableSet(relocations);
Objects.requireNonNull(patches);
this.patches = Collections.unmodifiableSet(patches);
}
public static class PatchMetadata {
public final String name;
public final String originalHash;
public final String targetHash;
public final String patchHash;
public PatchMetadata(String name, String originalHash, String targetHash, String patchHash) {
this.name = name;
this.originalHash = originalHash;
this.targetHash = targetHash;
this.patchHash = patchHash;
}
}
public static class Relocation implements Serializable {
public final String from;
public final String to;
public final boolean includeSubPackages;
public Relocation(String from, String to, boolean includeSubPackages) {
Objects.requireNonNull(from);
Objects.requireNonNull(to);
this.from = from.replaceAll("\\.", "/");
this.to = to.replaceAll("\\.", "/");
this.includeSubPackages = includeSubPackages;
}
}
}

View File

@ -0,0 +1,22 @@
package org.yatopiamc.yatoclip.gradle;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Properties;
public class PropertiesUtils {
public static void saveProperties(Properties prop, Path file, String comments){
System.out.println("Saving properties file to " + file);
file.toFile().getParentFile().mkdirs();
file.toFile().delete();
try(final OutputStream out = new FileOutputStream(file.toFile())) {
prop.store(out, comments);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -5,19 +5,27 @@ import kotlinx.dom.elements
import kotlinx.dom.parseXml
import kotlinx.dom.search
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.plugins.JavaLibraryPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.*
import org.yatopiamc.yatoclip.gradle.MakePatchesTask
import org.yatopiamc.yatoclip.gradle.PatchesMetadata
import org.yatopiamc.yatoclip.gradle.PropertiesUtils
import java.nio.charset.StandardCharsets.UTF_8
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.HashSet
internal fun Project.configureSubprojects() {
subprojects {
@ -49,6 +57,87 @@ internal fun Project.configureSubprojects() {
project.name.endsWith("api") -> configureApiProject()
}
}
rootProject.project("Yatoclip") {
configureYatoclipProject()
}
}
private fun Project.configureYatoclipProject() {
try {
rootProject.toothpick.serverProject.project.extensions.getByName("relocations")
} catch (e: UnknownDomainObjectException) {
return
}
apply<JavaLibraryPlugin>()
apply<ShadowPlugin>()
tasks.register<MakePatchesTask>("genPatches") {
originalJar = rootProject.toothpick.paperDir.resolve("work").resolve("Minecraft")
.resolve(rootProject.toothpick.minecraftVersion).resolve("${rootProject.toothpick.minecraftVersion}-m.jar")
targetJar = rootProject.toothpick.serverProject.project.tasks.getByName("shadowJar").outputs.files.singleFile
setRelocations(rootProject.toothpick.serverProject.project.extensions.getByName("relocations") as HashSet<PatchesMetadata.Relocation>)
dependsOn(rootProject.toothpick.serverProject.project.tasks.getByName("shadowJar"))
doLast {
val prop = Properties()
prop.setProperty("minecraftVersion", rootProject.toothpick.minecraftVersion)
PropertiesUtils.saveProperties(
prop,
outputDir.toPath().parent.resolve("yatoclip-launch.properties"),
"Yatoclip launch values"
)
}
}
val sourceSets = extensions.getByName("sourceSets") as org.gradle.api.tasks.SourceSetContainer
sourceSets.create("java9") {
java {
srcDir("src/java9")
}
}
val shadowJar by tasks.getting(ShadowJar::class) {
manifest {
attributes(
"Main-Class" to "org.yatopiamc.yatoclip.Yatoclip",
"Launcher-Agent-Class" to "org.yatopiamc.yatoclip.YatoclipLaunch",
"Premain-Class" to "org.yatopiamc.yatoclip.YatoclipLaunch",
"Multi-Release" to "true"
)
}
into("META-INF/versions/9") {
from(sourceSets.getByName("java9").output)
}
}
tasks.register<Copy>("copyJar") {
val targetName = "yatopia-${rootProject.toothpick.minecraftVersion}-yatoclip.jar"
from(shadowJar.outputs.files.singleFile) {
rename { targetName }
}
into(rootProject.projectDir)
doLast {
logger.lifecycle(">>> $targetName saved to root project directory")
}
dependsOn(shadowJar)
}
tasks.getByName("processResources").dependsOn(tasks.getByName("genPatches"))
tasks.getByName("assemble").dependsOn(tasks.getByName("copyJar"))
tasks.getByName("jar").enabled = false
val buildTask = tasks.getByName("build")
val buildTaskDependencies = HashSet(buildTask.dependsOn)
buildTask.setDependsOn(HashSet<Task>())
buildTask.onlyIf { false }
tasks.register("yatoclip") {
buildTaskDependencies.forEach {
dependsOn(it)
}
}
}
private fun Project.configureServerProject() {
@ -76,7 +165,7 @@ private fun Project.configureServerProject() {
"Implementation-Version" to toothpick.forkVersion,
"Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()),
"Specification-Title" to "Bukkit",
"Specification-Version" to "${project.version}",
"Specification-Version" to "${project.rootProject.toothpick.minecraftVersion}-${project.rootProject.toothpick.nmsRevision}",
"Specification-Vendor" to "Bukkit Team"
)
}
@ -85,11 +174,14 @@ private fun Project.configureServerProject() {
into("META-INF/maven/io.papermc.paper/paper")
}
val relocationSet = HashSet<PatchesMetadata.Relocation>()
// Don't like to do this but sadly have to do this for compatibility reasons
relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v${toothpick.nmsPackage}") {
exclude("org.bukkit.craftbukkit.Main*")
}
relocate("net.minecraft.server", "net.minecraft.server.v${toothpick.nmsPackage}")
relocationSet.add(PatchesMetadata.Relocation("", "net.minecraft.server.v${toothpick.nmsPackage}", false))
// Make sure we relocate deps the same as Paper et al.
val pomFile = project.projectDir.resolve("pom.xml")
@ -111,9 +203,11 @@ private fun Project.configureServerProject() {
if (pattern != "org.bukkit.craftbukkit" && pattern != "net.minecraft.server") { // We handle these ourselves above
logger.debug("Imported relocation to server project shadowJar from ${pomFile.absolutePath}: $pattern to $shadedPattern")
relocate(pattern, shadedPattern)
relocationSet.add(PatchesMetadata.Relocation(pattern, shadedPattern, true))
}
}
}
project.extensions.add("relocations", relocationSet)
}
tasks.getByName("build") {
dependsOn(shadowJar)
@ -121,9 +215,8 @@ private fun Project.configureServerProject() {
extensions.configure<PublishingExtension> {
publications {
getByName<MavenPublication>("mavenJava") {
artifactId = rootProject.name
artifact(tasks["shadowJar"])
create<MavenPublication>("shadow") {
artifact(project.tasks.named("shadowJar"))
}
}
}
@ -134,7 +227,7 @@ private fun Project.configureApiProject() {
val jar by this.tasks.getting(Jar::class) {
doFirst {
buildDir.resolve("tmp/pom.properties")
.writeText("version=${project.version}")
.writeText("version=${project.rootProject.toothpick.minecraftVersion}-${project.rootProject.toothpick.nmsRevision}")
}
from(buildDir.resolve("tmp/pom.properties")) {
into("META-INF/maven/${project.group}/${project.name}")

View File

@ -32,7 +32,7 @@ fun DependencyHandlerScope.loadDependencies(project: Project) {
val groupId = dependencyElem.search("groupId").first().textContent
val artifactId = dependencyElem.search("artifactId").first().textContent
val version = dependencyElem.search("version").first().textContent.applyReplacements(
"project.version" to project.version.toString(),
"project.version" to "${project.rootProject.toothpick.minecraftVersion}-${project.rootProject.toothpick.nmsRevision}",
"minecraft.version" to project.toothpick.minecraftVersion
)
val scope = dependencyElem.search("scope").firstOrNull()?.textContent

View File

@ -1,15 +1,18 @@
import org.gradle.api.Project
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.withType
import task.*
@Suppress("UNUSED_VARIABLE")
internal fun Project.initToothpickTasks() {
if (project.hasProperty("fast")) {
gradle.taskGraph.whenReady {
gradle.taskGraph.allTasks.filter {
it.name.contains("test", ignoreCase = true) || it.name.contains("javadoc", ignoreCase = true)
}.forEach {
it.onlyIf { false }
}
gradle.taskGraph.whenReady {
val fast = project.hasProperty("fast")
tasks.withType<Test> {
onlyIf { !fast }
}
tasks.withType<Javadoc> {
onlyIf { !fast || gradle.taskGraph.allTasks.any { it.name.contains("publish", ignoreCase = true) } }
}
}

View File

@ -1,7 +1,7 @@
/**
* This is the set of extra NMS files which will be imported as part of the patch process
*
* See `./Paper/work/Minecraft/$MCVER/net/minecraft/server` for a list of possible files
* See `./Paper/work/Minecraft/$MCVER/spigot/net/minecraft/server` for a list of possible files
*
* The `.java` extension is always assumed and should be excluded
*

View File

@ -33,6 +33,12 @@ open class ToothpickExtension(objects: ObjectFactory) {
lateinit var patchCreditsOutput: String
lateinit var patchCreditsTemplate: String
lateinit var currentBranch : String
val currentBranchDisplayName
get() = currentBranch.replace("/${minecraftVersion}", "")
val calcVersionString
get() = if(!currentBranch.startsWith("ver/")) { "${minecraftVersion}-${nmsRevision}-${currentBranchDisplayName.replace('/', '_')}" } else "${minecraftVersion}-${nmsRevision}"
fun server(receiver: ToothpickSubproject.() -> Unit) {
serverProject = ToothpickSubproject()
receiver(serverProject)

View File

@ -10,7 +10,7 @@ fun Project.toothpick(receiver: ToothpickExtension.() -> Unit) {
receiver(toothpick)
allprojects {
group = toothpick.groupId
version = "${toothpick.minecraftVersion}-${toothpick.nmsRevision}"
version = toothpick.calcVersionString
}
configureSubprojects()
initToothpickTasks()

View File

@ -27,6 +27,7 @@ internal fun Project.createPaperclipTask(
"-Dpaperjar=$patchedJarPath",
"-Dvanillajar=$vanillaJarPath"
)
if (System.getProperty("os.name").startsWith("Windows")) paperclipCmd[0] = "mvn.cmd"
if (jenkins) paperclipCmd.add("-Dstyle.color=never")
ensureSuccess(cmd(*paperclipCmd.toTypedArray(), dir = paperclipDir, printOut = true))
val paperClip = paperclipDir.resolve("assembly/target/paperclip-${toothpick.minecraftVersion}.jar")

View File

@ -70,7 +70,12 @@ private fun Project.updatePatches(
"--no-stat", "--zero-commit", "--full-index", "--no-signature", "-N",
"-o", patchPath.absolutePath, previousUpstreamName,
dir = projectDir,
printOut = true
printOut = false
)
)
gitCmd(
"add", patchPath.canonicalPath,
dir = patchPath,
printOut = true
)
}

View File

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

View File

@ -1,9 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 19:21:42 -0500
Subject: [PATCH] AirplaneLite MC Dev Fixes
Subject: [PATCH] Airplane MC Dev Fixes
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/LootTableInfo.java b/src/main/java/net/minecraft/server/LootTableInfo.java
index addeb268d4d487e18ddaadebf96f078fd079246f..268147484805e9fff298d2f5006f1c594c485342 100644
index addeb268d4d487e18ddaadebf96f078fd079246f..cbd034127de8a30b82b27c367bdd9270b43b98b0 100644
--- a/src/main/java/net/minecraft/server/LootTableInfo.java
+++ b/src/main/java/net/minecraft/server/LootTableInfo.java
@@ -53,7 +53,7 @@ public class LootTableInfo {
@ -28,7 +28,7 @@ index addeb268d4d487e18ddaadebf96f078fd079246f..268147484805e9fff298d2f5006f1c59
@Nullable
public <T> T getContextParameter(LootContextParameter<T> lootcontextparameter) {
- return this.h.get(lootcontextparameter);
+ return (T) this.h.get(lootcontextparameter); // AirplaneL - compile error
+ return (T) this.h.get(lootcontextparameter); // Airplane - compile error
}
public boolean a(LootTable loottable) {
@ -37,7 +37,7 @@ index addeb268d4d487e18ddaadebf96f078fd079246f..268147484805e9fff298d2f5006f1c59
public <T> T a(LootContextParameter<T> lootcontextparameter) {
- T t0 = this.b.get(lootcontextparameter);
+ T t0 = (T) this.b.get(lootcontextparameter); // AirplaneL - compile error
+ T t0 = (T) this.b.get(lootcontextparameter); // Airplane - compile error
if (t0 == null) {
throw new IllegalArgumentException("No parameter " + lootcontextparameter);
@ -46,7 +46,7 @@ index addeb268d4d487e18ddaadebf96f078fd079246f..268147484805e9fff298d2f5006f1c59
@Nullable
public <T> T b(LootContextParameter<T> lootcontextparameter) {
- return this.b.get(lootcontextparameter);
+ return (T) this.b.get(lootcontextparameter); // AirplaneL - compile error
+ return (T) this.b.get(lootcontextparameter); // Airplane - compile error
}
public LootTableInfo build(LootContextParameterSet lootcontextparameterset) {

View File

@ -0,0 +1,301 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Wed, 20 Jan 2021 13:08:53 -0600
Subject: [PATCH] Airplane Configuration
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..4feb9686f45ce4ae9f474447496b8e0f6fcb7e31
--- /dev/null
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -0,0 +1,46 @@
+package gg.airplane;
+
+import gg.airplane.manual.ManualParser;
+import net.minecraft.server.MinecraftServer;
+import org.apache.logging.log4j.Level;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class AirplaneConfig {
+
+ private static ManualParser manual;
+
+ public static void load() {
+ try {
+ manual = new ManualParser(new File("airplane.air"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ manual.get("info.version", "1.0");
+ manual.setComment("info",
+ " Airplane Configuration",
+ " Please see https://airplane.gg/config for help.");
+
+ for (Method method : AirplaneConfig.class.getDeclaredMethods()) {
+ if (Modifier.isStatic(method.getModifiers()) && Modifier.isPrivate(method.getModifiers())) {
+ method.setAccessible(true);
+ try {
+ method.invoke(null);
+ } catch (Throwable t) {
+ MinecraftServer.LOGGER.log(Level.WARN, "Failed to load configuration option from " + method.getName(), t);
+ }
+ }
+ }
+
+ try {
+ manual.save();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/gg/airplane/manual/ManualParser.java b/src/main/java/gg/airplane/manual/ManualParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..ace29adb0f140d99a8d85ac824654beded4bf5b8
--- /dev/null
+++ b/src/main/java/gg/airplane/manual/ManualParser.java
@@ -0,0 +1,210 @@
+package gg.airplane.manual;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+// todo make this cleaner and more ergonomic to use
+// also probably needs lists eventually
+public class ManualParser {
+
+ private final File file;
+ private final Map<String, Section> sections = new LinkedHashMap<>();
+
+ private static class ManualObject {
+ public final String key;
+ public final List<String> comments;
+
+ private ManualObject(String key, List<String> comments) {
+ this.key = key;
+ this.comments = comments == null ? new ArrayList<>() : comments;
+ }
+ }
+
+ private static class Section extends ManualObject {
+ public final Map<String, Value> values;
+
+ private Section(String key, List<String> comments) {
+ super(key, comments);
+ this.values = new LinkedHashMap<>();
+ }
+
+ public void add(String key, Value value) {
+ this.values.put(key, value);
+ value.parent = this;
+ }
+
+ public Value get(String key) {
+ return this.values.computeIfAbsent(key, k -> {
+ Value value = new Value(k, null, null);
+ value.parent = this;
+ return value;
+ });
+ }
+ }
+
+ private static class Value extends ManualObject {
+ public Object value;
+ public Section parent;
+
+ private Value(String key, Object value, List<String> comments) {
+ super(key, comments);
+ this.value = value;
+ }
+ }
+
+ public ManualParser(File file) throws IOException {
+ this.file = file;
+
+ if (!file.exists()) {
+ return;
+ }
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ Section currentSection = null;
+ List<String> currentComment = new ArrayList<>();
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+
+ if (line.length() == 0) {
+ continue; // empty line
+ }
+
+ if (line.startsWith("#")) {
+ currentComment.add(line.substring(1).trim());
+ } else if (line.startsWith("[")) {
+ if (!line.endsWith("]")) {
+ throw new IllegalArgumentException("Invalid configuration, section '" + line + "' does not end with ]");
+ }
+ if (line.length() < 3) {
+ throw new IllegalArgumentException("Invalid configuration, section '" + line + "' does not have a name");
+ }
+ String sectionName = line.substring(1, line.length() - 1);
+ Section newSection = new Section(sectionName, currentComment);
+ currentComment = new ArrayList<>();
+ currentSection = newSection;
+ this.sections.put(sectionName, newSection);
+ } else {
+ if (currentSection == null) {
+ throw new IllegalArgumentException("Invalid configuration, found value outside of section " + line);
+ }
+ int equals = line.indexOf("=");
+ if (equals <= 1 || equals == line.length() - 1) {
+ throw new IllegalArgumentException("Invalid configuration, assignment invalid " + line);
+ }
+
+ String key = line.substring(0, equals).trim();
+
+ String value = line.substring(equals + 1).trim();
+ if (value.length() == 0) {
+ throw new IllegalArgumentException("Invalid configuration, value does not exist " + line);
+ }
+ if (value.startsWith("\"")) {
+ if (!value.endsWith("\"")) {
+ throw new IllegalArgumentException("Invalid configuration, value has no ending quote " + line);
+ }
+ String stringValue = value.substring(1, value.length() - 1);
+ currentSection.add(key, new Value(key, stringValue, currentComment));
+ } else if (Character.isDigit(value.charAt(0))) {
+ if (value.contains(".")) {
+ double doubleValue = Double.parseDouble(value);
+ currentSection.add(key, new Value(key, doubleValue, currentComment));
+ } else {
+ int intValue = Integer.parseInt(value);
+ currentSection.add(key, new Value(key, intValue, currentComment));
+ }
+ } else if (value.equals("true") || value.equals("false")) {
+ boolean boolValue = Boolean.parseBoolean(value);
+ currentSection.add(key, new Value(key, boolValue, currentComment));
+ } else {
+ throw new IllegalArgumentException("Invalid configuration, unknown type for " + line);
+ }
+ currentComment = new ArrayList<>();
+ }
+ }
+ }
+ }
+
+ public void save() throws IOException {
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(this.file))) {
+ for (Map.Entry<String, Section> entry : this.sections.entrySet()) {
+ Section section = entry.getValue();
+ if (section.comments != null) {
+ for (String comment : section.comments) {
+ writer.write("# " + comment + "\n");
+ }
+ }
+ writer.write("[" + section.key + "]" + "\n");
+ for (Value value : section.values.values()) {
+ if (value.comments != null) {
+ for (String comment : value.comments) {
+ writer.write(" # " + comment + "\n");
+ }
+ }
+ writer.write(" " + value.key + " = " + serialize(value.value) + "\n");
+ }
+ writer.write("\n");
+ }
+ }
+ }
+
+ private ManualObject getObject(String key) {
+ String[] split = key.split("\\.", 2);
+ if (split.length == 1) {
+ return this.sections.computeIfAbsent(key, k -> new Section(k, null));
+ }
+ return this.sections.computeIfAbsent(split[0], k -> new Section(k, null)).get(split[1]);
+ }
+
+ public void setComment(String key, String... comment) {
+ ManualObject object = this.getObject(key);
+ object.comments.clear();
+ object.comments.addAll(Arrays.asList(comment));
+ }
+
+ public <T> T get(String key, T defaultValue, String... comment) {
+ String[] split = key.split("\\.", 2);
+ if (split.length == 1) {
+ throw new IllegalArgumentException("Key " + key + " does not include section");
+ }
+ Section section = this.sections.computeIfAbsent(split[0], k -> new Section(k, null));
+ if (!section.values.containsKey(split[1])) {
+ Value value = section.get(split[1]);
+ value.value = defaultValue;
+ value.comments.addAll(Arrays.asList(comment));
+ return defaultValue;
+ }
+ Value value = section.get(split[1]);
+ if (value.comments.isEmpty()) {
+ value.comments.addAll(Arrays.asList(comment));
+ }
+ return (T) value.value;
+ }
+
+ public void set(String key, Object value) {
+ ManualObject object = getObject(key);
+ if (!(object instanceof Value)) {
+ throw new IllegalArgumentException("Invalid key for value " + key);
+ }
+ ((Value) object).value = value;
+ }
+
+ private String serialize(Object object) {
+ if (object instanceof String) {
+ return "\"" + object + "\"";
+ }
+ return String.valueOf(object);
+ }
+
+}
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
index 3ee8d31c453105eca7b96bede39a9ebbf40e1c2c..ca3d9dbcbeeb5059a942cae1a5020f0bcc59ac9c 100644
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
@@ -179,6 +179,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
// Paper end
com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config
+ gg.airplane.AirplaneConfig.load(); // Airplane - config
this.setPVP(dedicatedserverproperties.pvp);
this.setAllowFlight(dedicatedserverproperties.allowFlight);

View File

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 23 Jan 2021 16:42:24 -0600
Subject: [PATCH] Remove streams
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/BehaviorBetterJob.java b/src/main/java/net/minecraft/server/BehaviorBetterJob.java
index 19f8cf4384ff7a1515ad33a5f573ea0061bab93d..e6507a9bef705e1496497ad6b58a546348a0779e 100644
--- a/src/main/java/net/minecraft/server/BehaviorBetterJob.java
+++ b/src/main/java/net/minecraft/server/BehaviorBetterJob.java
@@ -14,11 +14,31 @@ public class BehaviorBetterJob extends Behavior<EntityVillager> {
protected void a(WorldServer worldserver, EntityVillager entityvillager, long i) {
GlobalPos globalpos = (GlobalPos) entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE).get();
+ // Airplane start - remove stream
+ /*
worldserver.y().c(globalpos.getBlockPosition()).ifPresent((villageplacetype) -> {
BehaviorUtil.a(entityvillager, (entityvillager1) -> {
return this.a(globalpos, villageplacetype, entityvillager1);
}).reduce(entityvillager, BehaviorBetterJob::a);
});
+ */
+ java.util.Optional<VillagePlaceType> optVillagePlaceType = worldserver.y().c(globalpos.getBlockPosition());
+ if (optVillagePlaceType.isPresent()) {
+ VillagePlaceType villageplacetype = optVillagePlaceType.get();
+ java.util.Optional<java.util.List<EntityLiving>> optList = entityvillager.getBehaviorController().getMemory(MemoryModuleType.MOBS);
+ if (optList.isPresent()) {
+ EntityVillager previous = entityvillager;
+ for (EntityLiving entityliving : optList.get()) {
+ if (entityliving instanceof EntityVillager && entityliving != entityvillager && entityliving.isAlive()) {
+ EntityVillager entityvillager1 = (EntityVillager) entityliving;
+ if (this.a(globalpos, villageplacetype, entityvillager1)) {
+ previous = a(previous, entityvillager1);
+ }
+ }
+ }
+ }
+ }
+ // Airplane end
}
private static EntityVillager a(EntityVillager entityvillager, EntityVillager entityvillager1) {

View File

@ -10,7 +10,7 @@ a lot of dynamic checks for both of these, which result in extra work.
As well, since the fluid collision option is set to NONE, the entire
fluid collision system is completely unneeded, yet used anyways.
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -27,47 +27,47 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 8bceb152d9c7a3227c4bd3bb47964cf69abea0b4..c86f947a4c9843beec08f2b2ac52c0021063c285 100644
index 5f9d8999ae7a1d742918e58c0f1bb36fc74d45fe..15d74cb75725b4c53747848ca9b034c95a372a2f 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -3046,7 +3046,7 @@ public abstract class EntityLiving extends Entity {
@@ -3054,7 +3054,7 @@ public abstract class EntityLiving extends Entity {
Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ());
Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ());
- return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS;
+ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS; // AirplaneL - use direct method
+ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS; // Airplane - use direct method
}
@Override
diff --git a/src/main/java/net/minecraft/server/IBlockAccess.java b/src/main/java/net/minecraft/server/IBlockAccess.java
index 5c3eb4fc7e5aec2ad8d0050673fc8f4d2bff6a71..376ff36062d85b8ea8b004d9266ee9ee382b2942 100644
index 5c3eb4fc7e5aec2ad8d0050673fc8f4d2bff6a71..15f20132d5777c5e0162aa91e6e968e1e8b1cc2d 100644
--- a/src/main/java/net/minecraft/server/IBlockAccess.java
+++ b/src/main/java/net/minecraft/server/IBlockAccess.java
@@ -44,6 +44,15 @@ public interface IBlockAccess {
return BlockPosition.a(axisalignedbb).map(this::getType);
}
+ // AirplaneL start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect
+ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect
+ default MovingObjectPosition.EnumMovingObjectType rayTraceBlockDirect(Vec3D vec3d, Vec3D vec3d1, BlockPosition blockposition, IBlockData iblockdata, VoxelShapeCollision voxelshapecoll) {
+ VoxelShape voxelshape = RayTrace.BlockCollisionOption.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll);
+ MovingObjectPositionBlock movingobjectpositionblock = this.rayTrace(vec3d, vec3d1, blockposition, voxelshape, iblockdata);
+
+ return movingobjectpositionblock == null ? null : movingobjectpositionblock.getType();
+ }
+ // AirplaneL end
+ // Airplane end
+
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) {
// Paper start - Prevent raytrace from loading chunks
diff --git a/src/main/java/net/minecraft/server/MathHelper.java b/src/main/java/net/minecraft/server/MathHelper.java
index 2e7721a650c5a351b3584665bd236f92ef577761..8a6b623084fdc5ee2b0718f9e72f7c52a0d58d91 100644
index 2e7721a650c5a351b3584665bd236f92ef577761..b3c2b461b2a654a9e37a57f2f62b3ba8b5bb1634 100644
--- a/src/main/java/net/minecraft/server/MathHelper.java
+++ b/src/main/java/net/minecraft/server/MathHelper.java
@@ -238,6 +238,7 @@ public class MathHelper {
return f - (float) d(f);
}
+ public static double getDecimals(double num) { return h(num); } // AirplaneL
+ public static double getDecimals(double num) { return h(num); } // Airplane
public static double h(double d0) {
return d0 - (double) d(d0);
}
@ -75,7 +75,7 @@ index 2e7721a650c5a351b3584665bd236f92ef577761..8a6b623084fdc5ee2b0718f9e72f7c52
return f1 + f * (f2 - f1);
}
+ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // AirplaneL - OBFHELPER
+ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // Airplane - OBFHELPER
public static double d(double d0, double d1, double d2) {
return d1 + d0 * (d2 - d1);
}
@ -83,19 +83,19 @@ index 2e7721a650c5a351b3584665bd236f92ef577761..8a6b623084fdc5ee2b0718f9e72f7c52
return d0 * d0 * d0 * (d0 * (d0 * 6.0D - 15.0D) + 10.0D);
}
+ public static int sign(double num) { return k(num); } // AirplaneL - OBFHELPER
+ public static int sign(double num) { return k(num); } // Airplane - OBFHELPER
public static int k(double d0) {
return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1);
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 91aa8a2bc111ee6935ada0ae471fe1a3bc8fad80..87a4e53ad1ea1978bc9a0c335293190460efde8b 100644
index 7c367fe6152c30aab3e53c8f88cceba606891c93..6e6059daba05d7ce3aabeed85cc0e0d2daa04f92 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -332,6 +332,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return null;
}
+ // AirplaneL start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace)
+ // Airplane start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace)
+ protected MovingObjectPosition.EnumMovingObjectType rayTraceDirect(Vec3D vec3d, Vec3D vec3d1, VoxelShapeCollision voxelshapecoll) {
+ // most of this code comes from IBlockAccess#a(RayTrace, BiFunction, Function), but removes the needless functions
+ if (vec3d.equals(vec3d1)) {
@ -178,7 +178,7 @@ index 91aa8a2bc111ee6935ada0ae471fe1a3bc8fad80..87a4e53ad1ea1978bc9a0c3352931904
+
+ return result;
+ }
+ // AirplaneL end
+ // Airplane end
+
public static boolean isValidLocation(BlockPosition blockposition) {
return blockposition.isValidLocation(); // Paper - use better/optimized check

View File

@ -7,7 +7,7 @@ Paper added a fancy sorting comparison due to Bukkit recipes breaking
the vanilla one, however this is far more advanced than what you need
for all the vanilla recipes.
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -24,23 +24,23 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java
index 61d88dbaa1f5c543be610ce0914b2c89d8ad40ee..e7870de2467ca28070c234a39452778a3ac08862 100644
index 61d88dbaa1f5c543be610ce0914b2c89d8ad40ee..11fbbe86978055ece0cb47eee531093e59f61dcf 100644
--- a/src/main/java/net/minecraft/server/ShapelessRecipes.java
+++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java
@@ -17,8 +17,16 @@ public class ShapelessRecipes implements RecipeCrafting {
private final String group;
private final ItemStack result;
private final NonNullList<RecipeItemStack> ingredients;
+ private final boolean isBukkit; // AirplaneL
+ private final boolean isBukkit; // Airplane
+ // AirplaneL start - add isBukkit constructor param
+ // Airplane start - add isBukkit constructor param
public ShapelessRecipes(MinecraftKey minecraftkey, String s, ItemStack itemstack, NonNullList<RecipeItemStack> nonnulllist) {
+ this(minecraftkey, s, itemstack, nonnulllist, false);
+ }
+
+ public ShapelessRecipes(MinecraftKey minecraftkey, String s, ItemStack itemstack, NonNullList<RecipeItemStack> nonnulllist, boolean isBukkit) {
+ this.isBukkit = isBukkit;
+ // AirplaneL end
+ // Airplane end
this.key = minecraftkey;
this.group = s;
this.result = itemstack;
@ -48,7 +48,7 @@ index 61d88dbaa1f5c543be610ce0914b2c89d8ad40ee..e7870de2467ca28070c234a39452778a
}
public boolean a(InventoryCrafting inventorycrafting, World world) {
+ // AirplaneL start
+ // Airplane start
+ if (!this.isBukkit) {
+ java.util.List<RecipeItemStack> ingredients = com.google.common.collect.Lists.newArrayList(this.ingredients.toArray(new RecipeItemStack[0]));
+
@ -68,13 +68,13 @@ index 61d88dbaa1f5c543be610ce0914b2c89d8ad40ee..e7870de2467ca28070c234a39452778a
+
+ return ingredients.isEmpty();
+ }
+ // AirplaneL end
+ // Airplane end
+
AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager();
int i = 0;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
index 4aba511fe8078164bf1467b39645dd9bf6a931e7..e1a8f54450de4f173e59cd1851124b7b8621af7d 100644
index 4aba511fe8078164bf1467b39645dd9bf6a931e7..56b781e438f0cf1c12dd55eb37356601e47de47f 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
@@ -44,6 +44,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe
@ -82,6 +82,6 @@ index 4aba511fe8078164bf1467b39645dd9bf6a931e7..e1a8f54450de4f173e59cd1851124b7b
}
- MinecraftServer.getServer().getCraftingManager().addRecipe(new ShapelessRecipes(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data));
+ MinecraftServer.getServer().getCraftingManager().addRecipe(new ShapelessRecipes(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data, true)); // AirplaneL
+ MinecraftServer.getServer().getCraftingManager().addRecipe(new ShapelessRecipes(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data, true)); // Airplane
}
}

View File

@ -3,7 +3,7 @@ From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 19:03:25 -0500
Subject: [PATCH] Queue lighting update only once
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -20,14 +20,14 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 38ca1c042afd41a1f660f88e398fedde00f34e39..45db17d2f415197849c1fac5adce46d893e2a81d 100644
index 9e6381a60b804a957eda5b72582d5545faebcb3e..1da5c7def8b476cf638548b05d3e2015bc372f51 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -996,6 +996,7 @@ public class ChunkProviderServer extends IChunkProvider {
// Paper - moved up
// Tuinity start - optimise chunk tick iteration
com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<Chunk> iterator = this.entityTickingChunks.iterator();
+ boolean updateLighting = false; // AirplaneL
+ boolean updateLighting = false; // Airplane
try {
while (iterator.hasNext()) {
Chunk chunk = iterator.next();
@ -36,7 +36,7 @@ index 38ca1c042afd41a1f660f88e398fedde00f34e39..45db17d2f415197849c1fac5adce46d8
this.world.timings.chunkTicks.startTiming(); // Spigot // Paper
- this.world.a(chunk, k);
+ if (this.world.abool(chunk, k)) updateLighting = true; // AirplaneL
+ if (this.world.abool(chunk, k)) updateLighting = true; // Airplane
this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper
MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick
}
@ -44,12 +44,12 @@ index 38ca1c042afd41a1f660f88e398fedde00f34e39..45db17d2f415197849c1fac5adce46d8
} finally {
iterator.finishedIterating();
}
+ if (updateLighting) this.getLightEngine().queueUpdate(); // AirplaneL
+ if (updateLighting) this.getLightEngine().queueUpdate(); // Airplane
// Tuinity end - optimise chunk tick iteration
this.world.getMethodProfiler().enter("customSpawners");
if (flag1) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 6d5616dc4a899a1c01a21daece17f1c2cf0411bd..ff3918adeaad7636f179e33df5b0169dbb84b16c 100644
index cb2c429bda81b8c151a50ef3627716fef1e422d0..7e48b44047b09b44b2005e67ea1ef6bb2f2de6bc 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1019,7 +1019,10 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -57,10 +57,10 @@ index 6d5616dc4a899a1c01a21daece17f1c2cf0411bd..ff3918adeaad7636f179e33df5b0169d
// Paper end
- public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
+ // AirplaneL start - create version of chunk tick that returns a bool for updating lighting
+ // Airplane start - create version of chunk tick that returns a bool for updating lighting
+ public void a(Chunk chunk, int i) { this.abool(chunk, i); }
+ public boolean abool(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
+ // AirplaneL end
+ // Airplane end
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
int j = chunkcoordintpair.d();
@ -69,13 +69,13 @@ index 6d5616dc4a899a1c01a21daece17f1c2cf0411bd..ff3918adeaad7636f179e33df5b0169d
gameprofilerfiller.exit();
timings.chunkTicksBlocks.stopTiming(); // Paper
- getChunkProvider().getLightEngine().queueUpdate(); // Paper
+ // AirplaneL start
+ // Airplane start
+ //getChunkProvider().getLightEngine().queueUpdate(); // Paper
+ return true;
+ // AirplaneL end
+ // Airplane end
// Paper end
}
+ return false; // AirplaneL
+ return false; // Airplane
}
protected BlockPosition a(BlockPosition blockposition) {

View File

@ -3,7 +3,7 @@ From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 19:22:37 -0500
Subject: [PATCH] Use unmodifiableMap instead of making copy
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/LootTableInfo.java b/src/main/java/net/minecraft/server/LootTableInfo.java
index 268147484805e9fff298d2f5006f1c594c485342..1a87d73e116d3662bbc709adaf2ef7e4dd12f865 100644
index cbd034127de8a30b82b27c367bdd9270b43b98b0..25b6e240cf135da0643250b3f498a077dae070da 100644
--- a/src/main/java/net/minecraft/server/LootTableInfo.java
+++ b/src/main/java/net/minecraft/server/LootTableInfo.java
@@ -34,8 +34,8 @@ public class LootTableInfo {
@ -29,8 +29,8 @@ index 268147484805e9fff298d2f5006f1c594c485342..1a87d73e116d3662bbc709adaf2ef7e4
this.f = function1;
- this.h = ImmutableMap.copyOf(map);
- this.i = ImmutableMap.copyOf(map1);
+ this.h = java.util.Collections.unmodifiableMap(map); // AirplaneL
+ this.i = java.util.Collections.unmodifiableMap(map1); // AirplaneL
+ this.h = java.util.Collections.unmodifiableMap(map); // Airplane
+ this.i = java.util.Collections.unmodifiableMap(map1); // Airplane
}
public boolean hasContextParameter(LootContextParameter<?> lootcontextparameter) {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Swap priority of checks in chunk ticking
World.V showed up a lot in lag spikes for some reason, although I wonder
if it's just Spark getting JVM safe points.
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -23,7 +23,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index ff3918adeaad7636f179e33df5b0169dbb84b16c..ca69b5e5126eef423bee24af4f63f4bb442c560f 100644
index 7e48b44047b09b44b2005e67ea1ef6bb2f2de6bc..994c1822a4b53552befc64d88e922285715fa31d 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1032,7 +1032,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -31,7 +31,7 @@ index ff3918adeaad7636f179e33df5b0169dbb84b16c..ca69b5e5126eef423bee24af4f63f4bb
final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
- if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder
+ if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // AirplaneL - check this.W last
+ if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // Airplane - check this.W last
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);

View File

@ -3,7 +3,7 @@ From: Paul Sauve <paul@technove.co>
Date: Sun, 13 Dec 2020 17:52:35 -0600
Subject: [PATCH] Reduce projectile chunk loading
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java
index d85a19905efab7189e461a61becb6ca2b8c50803..71ff64c09858890b61b1cc9ea8e591ff4cf6c28b 100644
index d85a19905efab7189e461a61becb6ca2b8c50803..4b3d5731a18177c74f02eef91820720104145d1c 100644
--- a/src/main/java/net/minecraft/server/EntityProjectile.java
+++ b/src/main/java/net/minecraft/server/EntityProjectile.java
@@ -85,6 +85,37 @@ public abstract class EntityProjectile extends IProjectile {
@ -32,7 +32,7 @@ index d85a19905efab7189e461a61becb6ca2b8c50803..71ff64c09858890b61b1cc9ea8e591ff
+
+ private int buffered = 0;
+
+ // AirplaneL start
+ // Airplane start
+ @Override
+ public void setPosition(double d0, double d1, double d2) {
+ if (loadedTick != MinecraftServer.currentTick) {
@ -44,8 +44,8 @@ index d85a19905efab7189e461a61becb6ca2b8c50803..71ff64c09858890b61b1cc9ea8e591ff
+ if (previousX != newX || previousZ != newZ) {
+ boolean isLoaded = this.world.isChunkLoaded(newX, newZ);
+ if (!isLoaded) {
+ if (loadedThisTick > 10) { // AirplaneL 10 = max chunks to load from projectiles in a tick todo config
+ if (++buffered > 20) { // AirplaneL 20 = max chunks a single projectile loads overall todo config
+ if (loadedThisTick > 10) { // Airplane 10 = max chunks to load from projectiles in a tick todo config
+ if (++buffered > 20) { // Airplane 20 = max chunks a single projectile loads overall todo config
+ this.die();
+ }
+ return;
@ -56,7 +56,7 @@ index d85a19905efab7189e461a61becb6ca2b8c50803..71ff64c09858890b61b1cc9ea8e591ff
+ }
+ super.setPosition(d0, d1, d2);
+ }
+ // AirplaneL end
+ // Airplane end
+
protected float k() {
return 0.03F;

View File

@ -17,7 +17,7 @@ it, while checking if it's 0 for the current chunk.
Depending on configuration for things that tick in a chunk, this is a
5-10% improvement.
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -34,58 +34,67 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index ae07ea2a34f5cd82ce2eae523359cb7540065335..8b7fd21e6b366196fbc9cd44a340335c4cf9205f 100644
index 68d6fb69a0c1b98b3c11b6d80783faaa58272526..fa1d559a07199bf52d8ae04b2c34261efdebdcdb 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -53,6 +53,17 @@ public class Chunk implements IChunkAccess {
@@ -53,6 +53,18 @@ public class Chunk implements IChunkAccess {
private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key
private volatile boolean x;
+ // AirplaneL start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
+ private int lightningTick = -1;
+ public boolean shouldDoLightning() {
+ boolean doTick = this.lightningTick == 0;
+ // Airplane start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
+ private int lightningTick;
+ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline
+ public final boolean shouldDoLightning(java.util.Random random) {
+ if (this.lightningTick-- <= 0) {
+ this.lightningTick = this.world.random.nextInt(100000) << 1;
+ this.lightningTick = random.nextInt(100000) << 1;
+ return true;
+ }
+ return doTick;
+ return false;
+ }
+ // AirplaneL end
+ // Airplane end
+
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) {
this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null);
}
@@ -325,6 +337,7 @@ public class Chunk implements IChunkAccess {
// CraftBukkit start
this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
+ this.lightningTick = this.world.random.nextInt(100000) << 1; // Airplane - initialize lightning tick
}
public org.bukkit.Chunk bukkitChunk;
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 45db17d2f415197849c1fac5adce46d893e2a81d..ce2864f44dcc2003a85f7a211073b2b0bb617cd2 100644
index 1da5c7def8b476cf638548b05d3e2015bc372f51..03bcd704e3c08f5b54b124df1583e3ccdb4cb485 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -965,6 +965,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
// Paper end - optimize isOutisdeRange
this.world.getMethodProfiler().enter("pollingChunks");
+ this.world.resetIceAndSnowTick(); // AirplaneL - reset ice & snow tick random
+ this.world.resetIceAndSnowTick(); // Airplane - reset ice & snow tick random
int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED);
boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index ca69b5e5126eef423bee24af4f63f4bb442c560f..970a71fb66d235bf772aeddd02c50390ab7e568b 100644
index 994c1822a4b53552befc64d88e922285715fa31d..f3e8e5dafa528075acc76fa2e75907f63438a93d 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1019,6 +1019,8 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom();
// Paper end
+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // AirplaneL
+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane
+
// AirplaneL start - create version of chunk tick that returns a bool for updating lighting
// Airplane start - create version of chunk tick that returns a bool for updating lighting
public void a(Chunk chunk, int i) { this.abool(chunk, i); }
public boolean abool(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
@@ -1032,7 +1034,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("thunder");
final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
- if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // AirplaneL - check this.W last
+ if (!this.paperConfig.disableThunder && flag && chunk.shouldDoLightning() && this.W()) { // Paper - Disable thunder // AirplaneL - check this.W last // AirplaneL - replace random with shouldDoLighting
- if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // Airplane - check this.W last
+ if (!this.paperConfig.disableThunder && flag && chunk.shouldDoLightning(this.random) && this.W()) { // Paper - Disable thunder // Airplane - check this.W last // Airplane - replace random with shouldDoLighting
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);
@ -94,7 +103,7 @@ index ca69b5e5126eef423bee24af4f63f4bb442c560f..970a71fb66d235bf772aeddd02c50390
gameprofilerfiller.exitEnter("iceandsnow");
- if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
+ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // AirplaneL - optimize further random ticking
+ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - optimize further random ticking
// Paper start - optimise chunk ticking
this.getRandomBlockPosition(j, 0, k, 15, blockposition);
int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15);

View File

@ -3,7 +3,7 @@ From: Paul Sauve <paul@technove.co>
Date: Fri, 15 Jan 2021 20:08:54 -0600
Subject: [PATCH] Don't get entity equipment if not needed
Airplane Lite
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
@ -20,23 +20,23 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index c86f947a4c9843beec08f2b2ac52c0021063c285..0dbd3e0cf72881b766b624621f8dcd0fff3b66b4 100644
index 15d74cb75725b4c53747848ca9b034c95a372a2f..95ccaab19b46785dd515b9d444557ae56de8ab89 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -819,11 +819,13 @@ public abstract class EntityLiving extends Entity {
@@ -820,11 +820,13 @@ public abstract class EntityLiving extends Entity {
}
if (entity != null) {
- ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD);
- Item item = itemstack.getItem();
+ // AirplaneL start - don't get equipment if not needed
+ // Airplane start - don't get equipment if not needed
+ //ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD);
+ //Item item = itemstack.getItem();
EntityTypes<?> entitytypes = entity.getEntityType();
- if (entitytypes == EntityTypes.SKELETON && item == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && item == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && item == Items.CREEPER_HEAD) {
+ if (entitytypes == EntityTypes.SKELETON && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.CREEPER_HEAD) {
+ // AirplaneL end
+ // Airplane end
d0 *= 0.5D;
}
}

View File

@ -0,0 +1,251 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Fri, 15 Jan 2021 19:05:01 -0600
Subject: [PATCH] Dynamic activation range
This replaces the current method of ticking an inactive entity's
pathfinder 1/4 times with a new method that's dynamic based off how far
away it is from a player. If an entity is within 32 blocks, it gets
ticked every tick. If it's within 45 blocks, it gets ticked every other
tick. If it's within 55 blocks, it gets ticked once every three ticks.
(these numbers have since been changed, but the idea is the same.)
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
index 4feb9686f45ce4ae9f474447496b8e0f6fcb7e31..c39c9929a251b41ab60e1509b4e6c90d0825dc0c 100644
--- a/src/main/java/gg/airplane/AirplaneConfig.java
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -43,4 +43,29 @@ public class AirplaneConfig {
}
}
+
+ public static int maximumActivationPrio = 20;
+ public static int activationDistanceMod = 9;
+ public static boolean dynamicVillagerBehavior = true;
+ public static boolean dynamicPiglinBehavior = true;
+ public static boolean dynamicHoglinBehavior = true;
+
+ private static void dynamicActivationRange() {
+ manual.setComment("activation-range", "Optimizes how entities act when", "they're far away from the player");
+
+ maximumActivationPrio = manual.get("activation-range.max-tick-freq", maximumActivationPrio,
+ "This value defines how often in ticks, the furthest entity",
+ "will get their pathfinders and behaviors ticked. 20 = 1s");
+ activationDistanceMod = manual.get("activation-range.activation-dist-mod", activationDistanceMod,
+ "This value defines how much distance modifies an entity's",
+ "tick frequency. freq = (distanceToPlayer^2) / (2^value)",
+ "If you want further away entities to tick less often, use 8.",
+ "If you want further away entities to tick more often, try 10.");
+
+ manual.setComment("behavior-activation", "A list of entities to use the dynamic activation range", "to modify how often their behaviors are ticked");
+ dynamicVillagerBehavior = manual.get("behavior-activation.villager", dynamicVillagerBehavior);
+ dynamicPiglinBehavior = manual.get("behavior-activation.piglin", dynamicPiglinBehavior);
+ dynamicHoglinBehavior = manual.get("behavior-activation.hoglin", dynamicHoglinBehavior);
+ }
+
}
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index a2ba87dac005572d2617b6fe2c92f6984665588c..0fe4c8f9c669f343fef3e2869f22b46d8ef7136b 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -197,6 +197,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
public void inactiveTick() { }
// Spigot end
public boolean shouldBeRemoved; // Paper
+ // Airplane start
+ public int activatedPriority = gg.airplane.AirplaneConfig.maximumActivationPrio; // golf score
+ // Airplane end
public float getBukkitYaw() {
return this.yaw;
diff --git a/src/main/java/net/minecraft/server/EntityHoglin.java b/src/main/java/net/minecraft/server/EntityHoglin.java
index 4a3469aca9f9e47d2ea3f3bae6ce77f5f11d6b50..5af5b50889961b10e812598dbea657c4e2aeceeb 100644
--- a/src/main/java/net/minecraft/server/EntityHoglin.java
+++ b/src/main/java/net/minecraft/server/EntityHoglin.java
@@ -102,13 +102,18 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin {
return (BehaviorController<EntityHoglin>) super.getBehaviorController(); // Purpur - decompile error
}
+ private int behaviorTick; // Airplane
@Override
protected void mobTick() {
+ // Airplane - dynamic tick
+ if (!gg.airplane.AirplaneConfig.dynamicHoglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
this.world.getMethodProfiler().enter("hoglinBrain");
if (getRider() == null) // Purpur - only use brain if no rider
this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error
this.world.getMethodProfiler().exit();
HoglinAI.a(this);
+ }
+ // Airplane end
if (this.isConverting()) {
++this.conversionTicks;
if (this.conversionTicks > 300) {
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 65841a7bb58e210f07c0afd74c2fd5b3873bdd60..4c2e0b8aafecbc2a4b68e2c30b64db1c692d3667 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -133,10 +133,10 @@ public abstract class EntityInsentient extends EntityLiving {
@Override
public void inactiveTick() {
super.inactiveTick();
- if (this.goalSelector.inactiveTick()) {
+ if (this.goalSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priroity
this.goalSelector.doTick();
}
- if (this.targetSelector.inactiveTick()) {
+ if (this.targetSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priority
this.targetSelector.doTick();
}
}
@@ -797,9 +797,11 @@ public abstract class EntityInsentient extends EntityLiving {
this.bo.a();
this.world.getMethodProfiler().exit();
this.world.getMethodProfiler().enter("targetSelector");
+ if (this.targetSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking
this.targetSelector.doTick();
this.world.getMethodProfiler().exit();
this.world.getMethodProfiler().enter("goalSelector");
+ if (this.goalSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking
this.goalSelector.doTick();
this.world.getMethodProfiler().exit();
this.world.getMethodProfiler().enter("navigation");
diff --git a/src/main/java/net/minecraft/server/EntityPiglin.java b/src/main/java/net/minecraft/server/EntityPiglin.java
index 4849829df1041568a9fcac6d16501fc0606d95da..2ac74751ac8cea0b829b3d0ed03f052162a78781 100644
--- a/src/main/java/net/minecraft/server/EntityPiglin.java
+++ b/src/main/java/net/minecraft/server/EntityPiglin.java
@@ -216,13 +216,18 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow {
return !this.cannotHunt;
}
+ private int behaviorTick; // Airplane
@Override
protected void mobTick() {
+ // Airplane - dynamic tick
+ if (!gg.airplane.AirplaneConfig.dynamicPiglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
this.world.getMethodProfiler().enter("piglinBrain");
if (getRider() == null) // Purpur - only use brain if no rider
this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error
this.world.getMethodProfiler().exit();
PiglinAI.b(this);
+ }
+ // Airplane end
super.mobTick();
}
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index eef51f8e5734b897164ca9514e7b49b2678416e6..5fc57e2e2afe383ddc9b6d4db714a678c881fa77 100644
--- a/src/main/java/net/minecraft/server/EntityVillager.java
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
@@ -212,6 +212,8 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
}
// Purpur end
+ private int behaviorTick = 0;
+
@Override
protected void mobTick() { mobTick(false); }
protected void mobTick(boolean inactive) {
@@ -221,7 +223,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
boolean tick = (world.getTime() + brainTickOffset) % world.purpurConfig.villagerBrainTicks == 0;
if (((WorldServer) world).getMinecraftServer().lagging ? tick : world.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick)
// Purpur end
- if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+ if (!inactive) {
+ if (!gg.airplane.AirplaneConfig.dynamicVillagerBehavior || behaviorTick++ % this.activatedPriority == 0) {
+ this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+ }
+ }
else if (shouldRestock()) doRestock(); // Purpur
this.world.getMethodProfiler().exit();
if (this.bF) {
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
index 9cad895c7d008487ce885cbcc2c3966645df4c19..2ce5e07f4dcd0c76073840c35be66b7c65c6e7e8 100644
--- a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
+++ b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
@@ -43,9 +43,14 @@ public class PathfinderGoalSelector {
}
// Paper start
- public boolean inactiveTick() {
- incRate();
- return getCurRate() % getTickRate() == 0;
+ public boolean inactiveTick(int tickRate) { // Airplane - take tick rate
+ tickRate = Math.max(tickRate, getTickRate()); // Airplane
+ if (this.curRate++ % tickRate != 0) { // Airplane - use tick rate / increment curRate every tick
+ //incRate();
+ return false;
+ } else {
+ return true;
+ }
}
public boolean hasTasks() {
for (PathfinderGoalWrapped task : getTasks()) {
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 66b7c75929cd98737628b9d4f22829b5b65b8373..ea3d813759d90a6d229ca065abe044743be4780f 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -48,6 +48,9 @@ import net.minecraft.server.EntityInsentient;
import net.minecraft.server.EntityLlama;
import net.minecraft.server.EntityWaterAnimal;
// Paper end
+// Airplane start
+import net.minecraft.server.Vec3D;
+// Airplane end
public class ActivationRange
{
@@ -229,7 +232,7 @@ public class ActivationRange
Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper
if ( chunk != null )
{
- activateChunkEntities( chunk );
+ activateChunkEntities( chunk, player.getPositionVector() ); // Airplane
}
}
}
@@ -242,7 +245,7 @@ public class ActivationRange
*
* @param chunk
*/
- private static void activateChunkEntities(Chunk chunk)
+ private static void activateChunkEntities(Chunk chunk, Vec3D playerVec) // Airplane - add player location
{
// Paper start
Entity[] rawData = chunk.entities.getRawData();
@@ -251,11 +254,19 @@ public class ActivationRange
//for ( Entity entity : (Collection<Entity>) slice )
// Paper end
{
+ // Airplane start
+ Vec3D entityVec = entity.getPositionVector();
+ double diffX = playerVec.x - entityVec.x, diffY = playerVec.y - entityVec.y, diffZ = playerVec.z - entityVec.z;
+ int priority = Math.max(1, (int) (diffX * diffX + diffY * diffY + diffZ * diffZ) >> gg.airplane.AirplaneConfig.activationDistanceMod);
if (MinecraftServer.currentTick > entity.activatedTick) {
if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper
entity.activatedTick = MinecraftServer.currentTick;
}
+ entity.activatedPriority = Math.min(gg.airplane.AirplaneConfig.maximumActivationPrio, priority);
+ } else {
+ entity.activatedPriority = Math.min(gg.airplane.AirplaneConfig.maximumActivationPrio, Math.min(priority, entity.activatedPriority));
}
+ // Airplane end
}
}
}

View File

@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 4 Feb 2021 23:24:20 -0600
Subject: [PATCH] Reduce allocs & improve perf of StructureManager
Focuses on two methods, getStructureStarts & getFeatureStarts. For
getStructureStarts, it inlines getFeatureStarts so it doesn't have to
calculate an entire list when it returns early. As well, it uses a
LongIterator in order to not allocate longs for each position.
diff --git a/src/main/java/net/minecraft/server/StructureManager.java b/src/main/java/net/minecraft/server/StructureManager.java
index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52ceeeda4b 100644
--- a/src/main/java/net/minecraft/server/StructureManager.java
+++ b/src/main/java/net/minecraft/server/StructureManager.java
@@ -5,6 +5,11 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper
import java.util.stream.Stream;
import javax.annotation.Nullable;
+// Airplane start
+import it.unimi.dsi.fastutil.longs.LongIterator;
+import it.unimi.dsi.fastutil.longs.LongSet;
+// Airplane end
+
public class StructureManager {
private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER
@@ -41,13 +46,15 @@ public class StructureManager {
public java.util.List<StructureStart<?>> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator<?> structureGenerator, IWorldReader world) {
// Tuinity end - add world parameter
java.util.List<StructureStart<?>> list = new ObjectArrayList<>();
- for (Long curLong: (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { // Tuinity - fix deadlock on world gen - chunk can be unloaded while generating, so we should be using the generator's regionlimitedaccess so we always get the chunk
- SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0);
+ // Airplane start - skip allocating Longs
+ (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator).forEach((java.util.function.LongConsumer) curLong -> {
+ SectionPosition sectionPosition1 = SectionPosition.a(ChunkCoordIntPair.getX(curLong), 0, ChunkCoordIntPair.getZ(curLong)); // don't allocate ChunkCoordIntPair
StructureStart<?> structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS));
if (structurestart != null && structurestart.e()) {
list.add(structurestart);
}
- }
+ });
+ // Airplane end
return list;
}
// Paper end
@@ -75,7 +82,18 @@ public class StructureManager {
}
public StructureStart<?> getStructureStarts(BlockPosition blockposition, boolean flag, StructureGenerator<?> structuregenerator, IWorldReader world) {
// Paper start - remove structure streams
- for (StructureStart<?> structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator, world)) { // Tuinity end - add world parameter
+ // Airplane start - inline getFeatureStarts to skip creating the list
+ SectionPosition sectionPosition = SectionPosition.a(blockposition);
+
+ // use iterator here instead of forEach like in getFeatureStarts so we can return early
+ LongSet longSet = (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structuregenerator);
+ LongIterator iterator = longSet.iterator();
+ while (iterator.hasNext()) {
+ long curLong = iterator.nextLong();
+ SectionPosition sectionPosition1 = SectionPosition.a(ChunkCoordIntPair.getX(curLong), 0, ChunkCoordIntPair.getZ(curLong)); // don't allocate ChunkCoordIntPair
+ StructureStart<?> structurestart = a(sectionPosition1, structuregenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS));
+ if (structurestart != null && structurestart.e()) {
+
if (structurestart.c().b(blockposition)) {
if (!flag) {
return structurestart;
@@ -86,7 +104,10 @@ public class StructureManager {
}
}
}
+
+ }
}
+ // Airplane end
return StructureStart.a;
// Paper end
}

View File

@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 4 Feb 2021 23:28:46 -0600
Subject: [PATCH] Cache palette array
The reasoning for reusing it in ChunkRegionLoader is because ThreadLocal
lookups are fairly expensive, and if we put it in DataPaletteBlock the
ThreadLocal lookup would happen 18 times.
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 5f04591193d58ba7897194142da5efcbec3763dd..e77da341b765725771726283d3a8249b514b40da 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -424,6 +424,7 @@ public class ChunkRegionLoader {
public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) {
return saveChunk(worldserver, ichunkaccess, null);
}
+ private static final ThreadLocal<int[]> paletteArray = ThreadLocal.withInitial(() -> new int[4096]); // Airplane
public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) {
// Paper end
// Tuinity start - rewrite light impl
@@ -454,6 +455,7 @@ public class ChunkRegionLoader {
NBTTagCompound nbttagcompound2;
+ int[] aint = paletteArray.get(); // Airplane - use cached
for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change
int finalI = i; // CraftBukkit - decompile errors
ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> {
@@ -474,7 +476,7 @@ public class ChunkRegionLoader {
nbttagcompound2 = new NBTTagCompound();
nbttagcompound2.setByte("Y", (byte) (i & 255));
if (chunksection != Chunk.a) {
- chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates");
+ chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates", aint); // Airplane
}
if (nibblearray != null && !nibblearray.c()) {
diff --git a/src/main/java/net/minecraft/server/DataPaletteBlock.java b/src/main/java/net/minecraft/server/DataPaletteBlock.java
index 73163b417af7e522a4509bf9c1ab56d6499be622..2855a2757c35afc5751a7ca6f3a12cc27c24bf96 100644
--- a/src/main/java/net/minecraft/server/DataPaletteBlock.java
+++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java
@@ -226,12 +226,16 @@ public class DataPaletteBlock<T> implements DataPaletteExpandable<T> {
this.b();
}
+ // Airplane start - add parameter for reusing aint
public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize
+ a(nbttagcompound, s, s1, new int[4096]);
+ }
+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1, int[] aint) { // Paper - synchronize // Airplane end
this.a();
DataPaletteHash<T> datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f);
T t0 = this.g;
int i = datapalettehash.a(this.g);
- int[] aint = new int[4096];
+ //int[] aint = new int[4096]; // Airplane - use parameter
for (int j = 0; j < 4096; ++j) {
T t1 = this.a(j);

View File

@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 4 Feb 2021 23:33:52 -0600
Subject: [PATCH] Reduce chunk loading & lookups
diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java
index b884addf2ce6f1ef7394658078deb2e75370654f..e20b91b36587d1191f8f9e8dd501607bf085e76d 100644
--- a/src/main/java/net/minecraft/server/EntityEnderman.java
+++ b/src/main/java/net/minecraft/server/EntityEnderman.java
@@ -279,11 +279,18 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
private boolean p(double d0, double d1, double d2) {
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d1, d2);
- while (blockposition_mutableblockposition.getY() > 0 && !this.world.getType(blockposition_mutableblockposition).getMaterial().isSolid()) {
+ // Airplane start - single chunk lookup
+ Chunk chunk = this.world.getChunkIfLoaded(blockposition_mutableblockposition);
+ if (chunk == null) {
+ return false;
+ }
+
+ while (blockposition_mutableblockposition.getY() > 0 && !chunk.getType(blockposition_mutableblockposition).getMaterial().isSolid()) { // use chunk lookup
blockposition_mutableblockposition.c(EnumDirection.DOWN);
}
- IBlockData iblockdata = this.world.getType(blockposition_mutableblockposition);
+ IBlockData iblockdata = chunk.getType(blockposition_mutableblockposition); // use chunk lookup
+ // Airplane end
boolean flag = iblockdata.getMaterial().isSolid();
boolean flag1 = iblockdata.getFluid().a((Tag) TagsFluid.WATER);
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index ee91c33a7a2edca02caf5c71fd6429f97eac7e2d..324b78a51557cdd97e125f22eff8a4f54153d9f4 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -372,7 +372,10 @@ public final class SpawnerCreature {
}
private static List<BiomeSettingsMobs.c> a(WorldServer worldserver, StructureManager structuremanager, ChunkGenerator chunkgenerator, EnumCreatureType enumcreaturetype, BlockPosition blockposition, @Nullable BiomeBase biomebase) {
- return enumcreaturetype == EnumCreatureType.MONSTER && worldserver.getType(blockposition.down()).getBlock() == Blocks.NETHER_BRICKS && structuremanager.a(blockposition, false, StructureGenerator.FORTRESS).e() ? StructureGenerator.FORTRESS.c() : chunkgenerator.getMobsFor(biomebase != null ? biomebase : worldserver.getBiome(blockposition), structuremanager, enumcreaturetype, blockposition);
+ // Airplane start - single chunk lookup
+ Chunk chunk;
+ return enumcreaturetype == EnumCreatureType.MONSTER && (chunk = worldserver.getChunkIfLoaded(blockposition)) != null && chunk.getType(blockposition.down()).getBlock() == Blocks.NETHER_BRICKS && structuremanager.a(blockposition, false, StructureGenerator.FORTRESS).e() ? StructureGenerator.FORTRESS.c() : chunkgenerator.getMobsFor(biomebase != null ? biomebase : worldserver.getBiome(blockposition), structuremanager, enumcreaturetype, blockposition);
+ // Airplane end
}
private static BlockPosition getRandomPosition(World world, Chunk chunk) {

View File

@ -0,0 +1,209 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Tue, 9 Feb 2021 19:05:58 -0600
Subject: [PATCH] Reduce memory allocations
diff --git a/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java
index 7b29d47dfdef7611db58068af285f76d92a9f12a..6c5d96853d47850b81ce85e56a516c554819ef25 100644
--- a/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java
+++ b/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java
@@ -43,8 +43,14 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow {
if (worldserver.getLightLevel(blockposition.up()) >= 9) {
IBlockData iblockdata1 = this.getBlockData();
+ // Airplane start - use mutable position
+ BlockPosition.MutableBlockPosition blockposition1 = new BlockPosition.MutableBlockPosition();
for (int i = 0; i < 4; ++i) {
+ blockposition1.setValues(blockposition).addValues(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
+ /*
BlockPosition blockposition1 = blockposition.b(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
+ */
+ // Airplane end
if (worldserver.getType(blockposition1).a(Blocks.DIRT) && c(iblockdata1, (IWorldReader) worldserver, blockposition1)) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, (IBlockData) iblockdata1.set(BlockDirtSnowSpreadable.a, worldserver.getType(blockposition1.up()).a(Blocks.SNOW))); // CraftBukkit
diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java
index bc61aaff65a7dc1e7534452b285953b83adb7000..f38382cc681f03d9a6a0efa85f045e3770398739 100644
--- a/src/main/java/net/minecraft/server/BlockPosition.java
+++ b/src/main/java/net/minecraft/server/BlockPosition.java
@@ -438,6 +438,14 @@ public class BlockPosition extends BaseBlockPosition {
public BlockPosition b(int i, int j, int k) {
return super.b(i, j, k).immutableCopy();
}
+ // Airplane start - version of b that doesn't copy
+ public BlockPosition addValues(int x, int y, int z) {
+ ((BaseBlockPosition)this).a += x;
+ ((BaseBlockPosition)this).b += y;
+ ((BaseBlockPosition)this).e += z;
+ return this;
+ }
+ // Airplane end
@Override
public BlockPosition shift(EnumDirection enumdirection, int i) {
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
index 631eb682e81e30d2a937fd1eafccd8a9ab82d21e..dc07376845f84ea949a2153cb75d2cd9d46a419e 100644
--- a/src/main/java/net/minecraft/server/EntityTypes.java
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
@@ -140,6 +140,8 @@ public class EntityTypes<T extends Entity> {
public void setEntitySize(EntitySize entitySize) { this.br = entitySize; } // Purpur - OBFHELPER
private EntitySize br; // Purpur - remove final
+ public java.util.function.Supplier<String> getEntityName = () -> IRegistry.ENTITY_TYPE.getKey(this).toString(); // Airplane - create lambda ones
+
private static <T extends Entity> EntityTypes<T> a(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error
return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s));
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index a42571cfd2c9c80df27e59db832cb64c2a64e141..c5546838187e3dc0d752e69c1eafa0dbc3804b0c 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -638,7 +638,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return d2 * d2 + d3 * d3;
}
- private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) {
+ // Airplane start - create copy that accepts x/z instead of allocating pair
+ private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { return someDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, entityplayer, flag); }
+ private static int someDistanceCalculation(int x, int z, EntityPlayer entityplayer, boolean flag) {
int i;
int j;
@@ -652,12 +654,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
j = MathHelper.floor(entityplayer.locZ() / 16.0D);
}
- return a(chunkcoordintpair, i, j);
+ return someOtherDistanceCalculation(x, z, i, j);
+ // Airplane end
}
- private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) {
- int k = chunkcoordintpair.x - i;
- int l = chunkcoordintpair.z - j;
+ // Airplane start - create copy that accepts x/z instead of allocating pair
+ private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { return someOtherDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, i, j); }
+ private static int someOtherDistanceCalculation(int x, int z, int i, int j) {
+ int k = x - i;
+ int l = z - j;
+ // Airplane end
return Math.max(Math.abs(k), Math.abs(l));
}
@@ -2498,11 +2504,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
boolean flag1 = this.tracker.attachedToPlayer;
if (!flag1) {
+ // Airplane start - use int/longs instead of ChunkCoordIntPair
+ /*
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ);
- PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair());
+ */
+ int x = this.tracker.chunkX, z = this.tracker.chunkZ;
+ long chunkcoordintpair = ChunkCoordIntPair.pair(x, z);
+ PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair);
if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance
- flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance;
+ flag1 = PlayerChunkMap.someDistanceCalculation(x, z, entityplayer, false) <= PlayerChunkMap.this.viewDistance;
+ // Airplane end
}
}
@@ -2532,8 +2544,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
}
private int b() {
+ // Airplane start
+ int i = this.trackingDistance; // move out of if statement
+ if (!this.tracker.passengers.isEmpty()) {
Collection<Entity> collection = this.tracker.getAllPassengers();
- int i = this.trackingDistance;
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
@@ -2545,6 +2559,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
i = j;
}
}
+ }
+ // Airplane end
return this.a(i);
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 6e6059daba05d7ce3aabeed85cc0e0d2daa04f92..6e4c7a9b32c9e8057db3cbcead0b75d858fd6e18 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1055,19 +1055,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public void a(Consumer<Entity> consumer, Entity entity) {
try {
- consumer.accept(entity);
+ consumer.accept(entity); // Airplane - error on change
} catch (Throwable throwable) {
if (throwable instanceof ThreadDeath) throw throwable; // Paper
// Paper start - Prevent tile entity and entity crashes
String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ();
System.err.println(msg);
throwable.printStackTrace();
- getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); // Airplane - error on change
entity.dead = true;
return;
// Paper end
}
- MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick // Airplane - error on change
}
// Paper start - Prevent armor stands from doing entity lookups
@Override
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index f3e8e5dafa528075acc76fa2e75907f63438a93d..4d47cca6db7a771677c31ade9425ed3ad83393ea 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -907,7 +907,28 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("tick");
if (!entity.dead && !(entity instanceof EntityComplexPart)) {
+ // Airplane start - inline this.a to prevent creation of lambda
+ /*
this.a(this::entityJoinedWorld, entity);
+ */
+ boolean doMidTick = false; // usually there's a returns in the catch, so treat it like that
+ try {
+ this.entityJoinedWorld(entity);
+ doMidTick = true;
+ } catch (Throwable throwable) {
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper
+ // Paper start - Prevent tile entity and entity crashes
+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ();
+ System.err.println(msg);
+ throwable.printStackTrace();
+ getServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable)));
+ entity.dead = true;
+ // Paper end
+ }
+ if (doMidTick) {
+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
+ }
+ // Airplane end
}
gameprofilerfiller.exit();
@@ -1278,9 +1299,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
++entity.ticksLived;
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
+ // Airplane start - create debug lambda once, todo do we even WANT the method profiler?
+ /*
gameprofilerfiller.a(() -> {
return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString();
});
+ */
+ gameprofilerfiller.a(entity.getEntityType().getEntityName);
+ // Airplane end
gameprofilerfiller.c("tickNonPassenger");
if (isActive) { // Paper - EAR 2
TimingHistory.activatedEntityTicks++; // Paper

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Disable the Snooper
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 760799782d0cb01e2b14408a9b085f78034ec78d..f6e3bf632a6dd559a58d73eab07f15d6b69c5c13 100644
index 33d43478b1bc4b0ca3f16ba80e0cd99bc6f5311e..d4dc05a1066bfcd4cdc1bfa04e46aa2d8d6e2fe5 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1321,6 +1321,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1322,6 +1322,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
//} // Paper
this.methodProfiler.enter("snooper");
@ -17,7 +17,7 @@ index 760799782d0cb01e2b14408a9b085f78034ec78d..f6e3bf632a6dd559a58d73eab07f15d6
if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot
this.snooper.a();
}
@@ -1328,6 +1330,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1329,6 +1331,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && this.ticks % 6000 == 0) { // Spigot
this.snooper.b();
}

View File

@ -90,10 +90,10 @@ index cb6f55c4d870ea1ce146f64ac13e7090f2de3bc8..f7b54111ba86d9ee131e320f573f568c
if (this.world != null) BlockLectern.a(this.getWorld(), this.getPosition(), this.getBlock()); // CraftBukkit
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 53917d3b381730efb079113fdffecdc29939d6ea..37d71def297c3f34e9afc74821df6090f3737156 100644
index 2318d19b21514effe28b4d21c0196c8f778d22db..a106069e9122313d73b0d23d689b0d1e70025cc8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -32,6 +32,7 @@ import net.minecraft.server.PacketPlayInCloseWindow;
@@ -31,6 +31,7 @@ import net.minecraft.server.PacketPlayInCloseWindow;
import net.minecraft.server.PacketPlayOutOpenWindow;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityContainer;
@ -101,7 +101,7 @@ index 53917d3b381730efb079113fdffecdc29939d6ea..37d71def297c3f34e9afc74821df6090
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -300,6 +301,11 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@@ -299,6 +300,11 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
if (craft.getInventory() instanceof ITileInventory) {
iinventory = (ITileInventory) craft.getInventory();
}

View File

@ -19,7 +19,7 @@ index 657885cdaa086293f6b5aa6f3058acd16df0ba35..8724ad342bec7c733b3c825bd62dbfa5
Block.a(iblockdata, iblockdata1, generatoraccess, blockposition_mutableblockposition, i, j);
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 87a4e53ad1ea1978bc9a0c335293190460efde8b..f2512fd66849cfa743cf7bfdffcb4c26178ffebf 100644
index 6e4c7a9b32c9e8057db3cbcead0b75d858fd6e18..c0872f8a53b862558c7fa2fe17ebb0a796da03ce 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -774,7 +774,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

View File

@ -129,7 +129,7 @@ index 0000000000000000000000000000000000000000..fe7330fabe386966c2d203a190a00a78
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index f2512fd66849cfa743cf7bfdffcb4c26178ffebf..b47bc7cadd34f4592605c1ecfdfcb33e2d580034 100644
index c0872f8a53b862558c7fa2fe17ebb0a796da03ce..77c748ad07ee257742c4d36825bdd9e916b5d851 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -97,6 +97,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -150,10 +150,10 @@ index f2512fd66849cfa743cf7bfdffcb4c26178ffebf..b47bc7cadd34f4592605c1ecfdfcb33e
this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray
this.generator = gen;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 413c55feb6b1c2ddc80aa8dc1c83ed13b2c4c4a5..53deddce357170a712913d916ba1d58e663fc1a1 100644
index dfe6777db04bb550ae0e761addd26b2d5abf3baf..48dd6de4acf0ef0536a4c562f3eb5f2f90878924 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -863,6 +863,7 @@ public final class CraftServer implements Server {
@@ -862,6 +862,7 @@ public final class CraftServer implements Server {
com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper
com.tuinity.tuinity.config.TuinityConfig.init((File) console.options.valueOf("tuinity-settings")); // Tuinity - Server Config
net.pl3x.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur
@ -161,7 +161,7 @@ index 413c55feb6b1c2ddc80aa8dc1c83ed13b2c4c4a5..53deddce357170a712913d916ba1d58e
for (WorldServer world : console.getWorlds()) {
world.worldDataServer.setDifficulty(config.difficulty);
world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals);
@@ -899,6 +900,7 @@ public final class CraftServer implements Server {
@@ -898,6 +899,7 @@ public final class CraftServer implements Server {
world.paperConfig.init(); // Paper
world.tuinityConfig.init(); // Tuinity - Server Config
world.purpurConfig.init(); // Purpur

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Don't wake up entities when damage event is cancelled
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 0dbd3e0cf72881b766b624621f8dcd0fff3b66b4..93a5c897e9154c26b201177a4372bb6e5af42a78 100644
index 95ccaab19b46785dd515b9d444557ae56de8ab89..a198bdf26b60caea8c8b105cb0e4b82c0340fede 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -1117,9 +1117,12 @@ public abstract class EntityLiving extends Entity {
@@ -1118,9 +1118,12 @@ public abstract class EntityLiving extends Entity {
} else if (damagesource.isFire() && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
return false;
} else {
@ -24,7 +24,7 @@ index 0dbd3e0cf72881b766b624621f8dcd0fff3b66b4..93a5c897e9154c26b201177a4372bb6e
this.ticksFarFromPlayer = 0;
float f1 = f;
@@ -1865,6 +1868,11 @@ public abstract class EntityLiving extends Entity {
@@ -1873,6 +1876,11 @@ public abstract class EntityLiving extends Entity {
if (event.isCancelled()) {
return false;
}

View File

@ -1,107 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Tue, 11 Feb 2020 21:56:38 -0600
Subject: [PATCH] EntityMoveEvent
diff --git a/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java b/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c48c525b8ee527a5766ac679619fd88956002d64
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java
@@ -0,0 +1,95 @@
+package net.pl3x.purpur.event.entity;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.Location;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Holds information for living entity movement events
+ */
+public class EntityMoveEvent extends EntityEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean canceled;
+ private Location from;
+ private Location to;
+
+ public EntityMoveEvent(@NotNull LivingEntity entity, @NotNull Location from, @NotNull Location to) {
+ super(entity);
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ @NotNull
+ public LivingEntity getEntity() {
+ return (LivingEntity) entity;
+ }
+
+ public boolean isCancelled() {
+ return canceled;
+ }
+
+ public void setCancelled(boolean cancel) {
+ canceled = cancel;
+ }
+
+ /**
+ * Gets the location this entity moved from
+ *
+ * @return Location the entity moved from
+ */
+ @NotNull
+ public Location getFrom() {
+ return from;
+ }
+
+ /**
+ * Sets the location to mark as where the entity moved from
+ *
+ * @param from New location to mark as the entity's previous location
+ */
+ public void setFrom(@NotNull Location from) {
+ validateLocation(from);
+ this.from = from;
+ }
+
+ /**
+ * Gets the location this entity moved to
+ *
+ * @return Location the entity moved to
+ */
+ @NotNull
+ public Location getTo() {
+ return to;
+ }
+
+ /**
+ * Sets the location that this entity will move to
+ *
+ * @param to New Location this entity will move to
+ */
+ public void setTo(@NotNull Location to) {
+ validateLocation(to);
+ this.to = to;
+ }
+
+ private void validateLocation(@NotNull Location loc) {
+ Preconditions.checkArgument(loc != null, "Cannot use null location!");
+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!");
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack convenience methods
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
index 4ba991b79f13219182df35b4ce0c5cf57cbd208b..a2e476f154344f9473dd9b48866505448de56d84 100644
index 2a3becabbd10fa8ffd19f35a3f6d8a6bfcb388c3..f71c9fd069309ef330d9065760b80ec10de7e18b 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
@@ -8645,4 +8645,36 @@ public enum Material implements Keyed {
@@ -8642,4 +8642,36 @@ public enum Material implements Keyed {
// </editor-fold>
}
}

View File

@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 30 Jul 2020 18:15:04 -0500
Subject: [PATCH] DragonEggPlaceEvent
diff --git a/src/main/java/net/pl3x/purpur/event/block/DragonEggPlaceEvent.java b/src/main/java/net/pl3x/purpur/event/block/DragonEggPlaceEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdabfd2b5f64b0e65c4eb09958282962620cdda2
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/event/block/DragonEggPlaceEvent.java
@@ -0,0 +1,47 @@
+package net.pl3x.purpur.event.block;
+
+import org.bukkit.Location;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+
+public class DragonEggPlaceEvent extends Event implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private Location location;
+ private boolean cancelled;
+
+ public DragonEggPlaceEvent(@NotNull Location location) {
+ this.location = location;
+ }
+
+ @NotNull
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(@NotNull Location location) {
+ this.location = location;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ cancelled = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@ -1157,10 +1157,10 @@ index 7d23333e71482920cc42a4d8f3f38a7525aefe1f..765aa67f4cbb535128070d3310d1be9e
/**
* When a zombie gets cured and a villager is spawned.
diff --git a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java
index a33986a0c437a673435206fc337031a7eebdab3b..99a8e452904de21a5bd82f13f6b2d46537d07289 100644
index e0e068799a1868c8e561869015f41f553ef4fbdb..9fa0ba2f81a6724491c22446c87135841d099fb0 100644
--- a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java
@@ -37,6 +37,9 @@ public class EntityUnleashEvent extends EntityEvent {
@@ -66,6 +66,9 @@ public class EntityUnleashEvent extends EntityEvent {
return handlers;
}

View File

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 9 Jan 2021 21:21:27 +0100
Subject: [PATCH] Add unsafe Entity serialization API
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index 97b9ade0e771eae663fb42f91e15545034d58fc9..0c9d3c8a28a791fe26bb1c014b568e955eca0e8f 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -135,4 +135,28 @@ public interface UnsafeValues {
public int nextEntityId();
// Paper end
+
+ // Purpur start
+
+ /**
+ * Serialize entity to byte array
+ *
+ * @param entity entity to serialize
+ * @return serialized entity
+ */
+ byte[] serializeEntity(org.bukkit.entity.Entity entity);
+
+ /**
+ * Deserialize an entity from byte array
+ * <p>
+ * The entity is not automatically spawned in the world. You will have to spawn
+ * the entity yourself with {@link org.bukkit.entity.Entity#spawnAt(Location)} or
+ * {@link org.bukkit.entity.Entity#spawnAt(Location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason)}
+ *
+ * @param data serialized entity
+ * @param world world entity belongs in
+ * @return deserialized entity
+ */
+ org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world);
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 08dbe8208fad174f03a0e08c26bb48a0729ec0ce..2b7e8c7f24b2d9dd49db901f6279b8b5930a3006 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -745,5 +745,24 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* @return True if ridable in water
*/
boolean isRidableInWater();
+
+ /**
+ * Spawn this entity in the world at the given {@link Location} with the default spawn reason.
+ *
+ * @param location The location at which to spawn the entity.
+ * @return Whether the entity was successfully spawned.
+ */
+ default boolean spawnAt(@NotNull Location location) {
+ return spawnAt(location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ /**
+ * Spawn this entity in the world at the given {@link Location} with the reason given.
+ *
+ * @param location The location at which to spawn the entity.
+ * @param spawnReason The reason for which the entity was spawned.
+ * @return Whether the entity was successfully spawned.
+ */
+ boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason);
// Purpur end
}

View File

@ -48,10 +48,10 @@ index 229c3b0f0c650b501f31147adaa17194af57fedd..f88cf526d272fe47b5a474c0b344b748
throwable = throwable1;
throw throwable1;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 45e310e249a83714d0001d85b2ead8d4f8a2d742..af5c1479d2cb8092d84e2d3d5166060d9ff2df71 100644
index 1768554b00ea0b7a57ebbed1f0bc5d8fd6f02f76..fe4ef4ea7117a6f38e4d068aae5b5ec6de06507b 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1511,7 +1511,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1513,7 +1513,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
public String getServerModName() {
@ -182,10 +182,10 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index bd7bccbea1a0a052ef7bd6ab299ae72336874911..5100460bab83cd75ac8dcdcc50ea663b1c486d00 100644
index 44524e08bed8897e43e408b6f179bf798fed9b62..19a209cfc71e30edd3ff2d8c319df5e8b331e6cf 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
@@ -231,7 +231,7 @@ import javax.annotation.Nullable; // Paper
import javax.annotation.Nonnull; // Paper
public final class CraftServer implements Server {

View File

@ -78,7 +78,7 @@ index de9ea6770b8afc5e1020bef04ac6cca93b6b420c..21d0570a59240e955ff148bac0226b22
if (this.bF) {
this.bF = false;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 28ee325fcc8b50397768363403823f2e3391d8c8..fb650c09dbcefa0ff021f7c508ff6811a48bee7a 100644
index 93c0c3376c3cb2fe416c8ae3e740ffda5f985b78..226b5cd399449ca3587964221765e4d241dfc739 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -95,6 +95,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -373,10 +373,10 @@ index 0000000000000000000000000000000000000000..4904be939c7a4b1d1583fd7b6232c930
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 5100460bab83cd75ac8dcdcc50ea663b1c486d00..b5d274c1fe214ea274057084bc40d6eeb618b21d 100644
index 19a209cfc71e30edd3ff2d8c319df5e8b331e6cf..8cd8db287bb4110e17ec0da57ee1547ca1f221d7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -862,6 +862,7 @@ public final class CraftServer implements Server {
@@ -861,6 +861,7 @@ public final class CraftServer implements Server {
org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot
com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper
com.tuinity.tuinity.config.TuinityConfig.init((File) console.options.valueOf("tuinity-settings")); // Tuinity - Server Config
@ -384,7 +384,7 @@ index 5100460bab83cd75ac8dcdcc50ea663b1c486d00..b5d274c1fe214ea274057084bc40d6ee
for (WorldServer world : console.getWorlds()) {
world.worldDataServer.setDifficulty(config.difficulty);
world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals);
@@ -897,6 +898,7 @@ public final class CraftServer implements Server {
@@ -896,6 +897,7 @@ public final class CraftServer implements Server {
world.spigotConfig.init(); // Spigot
world.paperConfig.init(); // Paper
world.tuinityConfig.init(); // Tuinity - Server Config
@ -392,7 +392,7 @@ index 5100460bab83cd75ac8dcdcc50ea663b1c486d00..b5d274c1fe214ea274057084bc40d6ee
}
Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper
@@ -915,6 +917,7 @@ public final class CraftServer implements Server {
@@ -914,6 +916,7 @@ public final class CraftServer implements Server {
reloadData();
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper

View File

@ -5,10 +5,10 @@ Subject: [PATCH] AFK API
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index 9796b4e57d6680c9f0dc76decdd985572daafb7e..f15ec5c45d95c6828ed628451917ac3426a76f1f 100644
index 59b00c78f8d92bcceca35d0f25e4d94b3ebdc6e2..e0cf2af8fcbfc66fc32aa8e693b62160b24f8672 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -84,6 +84,15 @@ public abstract class EntityHuman extends EntityLiving {
@@ -82,6 +82,15 @@ public abstract class EntityHuman extends EntityLiving {
}
// CraftBukkit end
@ -25,10 +25,10 @@ index 9796b4e57d6680c9f0dc76decdd985572daafb7e..f15ec5c45d95c6828ed628451917ac34
super(EntityTypes.PLAYER, world);
this.bL = ItemStack.b;
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 9f5b7243ccbe0729a061345c25033d9145b91b3f..6bab47ab2583735c36d74d849ab0923494a265db 100644
index 173a210392d71cdfc551f095dc0d9c9040d22d3f..7d7a512ad752e15fbe0edce47da1da76c01df3b3 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1904,8 +1904,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@@ -1927,8 +1927,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public void resetIdleTimer() {
this.ca = SystemUtils.getMonotonicMillis();
@ -193,10 +193,10 @@ index 4058c1f7ada7d0c9e4ba73a0073b4f94bf410a8f..caf9ce94a7cb6154981d42953c81b588
if (from.getX() != Double.MAX_VALUE) {
Location oldTo = to.clone();
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 6ff5ef6b710652f1c4fe6461ff230ee78988f623..efe2a9ad2ece23bd71f4ad63b2c6f54f42345b55 100644
index 9c11a6ba0384baafaec1403a6a7c3f894d5cd7b3..e99c3ad507f1381c9aa495052d2014ba8b7e0750 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -781,7 +781,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -782,7 +782,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end
if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> {
@ -205,7 +205,7 @@ index 6ff5ef6b710652f1c4fe6461ff230ee78988f623..efe2a9ad2ece23bd71f4ad63b2c6f54f
})) {
// CraftBukkit start
long l = this.worldData.getDayTime() + 24000L;
@@ -1118,7 +1118,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1119,7 +1119,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
while (iterator.hasNext()) {
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
@ -263,10 +263,10 @@ index 361f7857e461578e90cb71e15027dadaf794cb69..2578a4677d1ee060f687be531e696b7c
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7c18b22c7b93b6ca1189e481dde17476797b8fd5..debf252a23d0178f06fdadb9c27c3c66b9bbc2d0 100644
index ed7b91bf703c7e7d5cbe323d9ab1c299c33ebad1..e319f3b1282af8019ae706f46e3978e789fbc877 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2223,4 +2223,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2222,4 +2222,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return spigot;
}
// Spigot end
@ -289,10 +289,10 @@ index 7c18b22c7b93b6ca1189e481dde17476797b8fd5..debf252a23d0178f06fdadb9c27c3c66
+ // Purpur end
}
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 0b93635ba59df4eb4456a97c5e9b51ab5aeda53f..b47d6fa2de3368d1afe329573bc18c3541bb7377 100644
index 6ade13fd88c381280f619daaa8d6b241c67dd9d9..f80526939be358ac46430f35f3fdc7f88038c262 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -207,6 +207,7 @@ public class ActivationRange
@@ -205,6 +205,7 @@ public class ActivationRange
{
player.activatedTick = MinecraftServer.currentTick;

View File

@ -17,10 +17,10 @@ index 65961a03728852bd75367083a0de6fd0082b17cb..780474397acb4d0e7ecb4540e1a2db57
public final boolean spawnNpcs = this.getBoolean("spawn-npcs", true);
public final boolean pvp = this.getBoolean("pvp", true);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index b5d274c1fe214ea274057084bc40d6eeb618b21d..43ee4f6ba778ceb0b34906ace86f0f12587a8e8d 100644
index 8cd8db287bb4110e17ec0da57ee1547ca1f221d7..529f50aa6755c202ac2d3a6d0e4dfd38c4eaf6e8 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2450,4 +2450,11 @@ public final class CraftServer implements Server {
@@ -2451,4 +2451,11 @@ public final class CraftServer implements Server {
return mobGoals;
}
// Paper end

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Configurable server mod name
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index af5c1479d2cb8092d84e2d3d5166060d9ff2df71..90556fca9315e71c4f3fbd231ac6d765677ca271 100644
index fe4ef4ea7117a6f38e4d068aae5b5ec6de06507b..2f5ef91a5732800d9b9a7acbb52ad29b5c0729a3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1511,7 +1511,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1513,7 +1513,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
public String getServerModName() {

View File

@ -30,10 +30,10 @@ index 2a91f07ca9c4dc0cb3b5aef5c9c1db7f69773530..7604fd83de9cfe93d427a9a1f6bbbee7
protected int getChestSlots() {
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 4fe5a8d0201d662c68dd58eeb8cf1d304787edb4..279662570c0bbd6c00b5732881cd35dfe694b25d 100644
index 87b66c284208f12e9e7cd1c9950ada8d0fbf26a5..59699bb23a189b7e53737b2f8f5263608a64109c 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -132,6 +132,7 @@ public abstract class EntityLiving extends Entity {
@@ -133,6 +133,7 @@ public abstract class EntityLiving extends Entity {
// CraftBukkit start
public int expToDrop;
public int maxAirTicks = 300;
@ -41,7 +41,7 @@ index 4fe5a8d0201d662c68dd58eeb8cf1d304787edb4..279662570c0bbd6c00b5732881cd35df
boolean forceDrops;
ArrayList<org.bukkit.inventory.ItemStack> drops = new ArrayList<org.bukkit.inventory.ItemStack>();
public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
@@ -226,8 +227,8 @@ public abstract class EntityLiving extends Entity {
@@ -227,8 +228,8 @@ public abstract class EntityLiving extends Entity {
this.cR();
}
@ -52,7 +52,7 @@ index 4fe5a8d0201d662c68dd58eeb8cf1d304787edb4..279662570c0bbd6c00b5732881cd35df
if (!iblockdata.isAir()) {
double d1 = Math.min((double) (0.2F + f / 15.0F), 2.5D);
@@ -1685,7 +1686,7 @@ public abstract class EntityLiving extends Entity {
@@ -1693,7 +1694,7 @@ public abstract class EntityLiving extends Entity {
MobEffect mobeffect = this.getEffect(MobEffects.JUMP);
float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1);
@ -62,10 +62,10 @@ index 4fe5a8d0201d662c68dd58eeb8cf1d304787edb4..279662570c0bbd6c00b5732881cd35df
protected void playBlockStepSound() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 16e69cfd4994fd6850ee3635ea819379412351c9..0292cae6225ae2ee156f436c8827a018e8ffa723 100644
index c1350bbf62fc5c5e18509f378edf16e8b210cfe8..84aeffac2c2c12d98e9cec05314668a93bb5ed91 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -826,4 +826,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@@ -833,4 +833,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
getHandle().setHurtDirection(hurtDirection);
}
// Paper end

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Lagging threshold
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 90556fca9315e71c4f3fbd231ac6d765677ca271..e12fecf47798f638b85e7c6d54055a526097811c 100644
index 2f5ef91a5732800d9b9a7acbb52ad29b5c0729a3..64cd02072536e69cd219932769bbade87b47601a 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -163,6 +163,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -164,6 +164,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
public static final int TICK_TIME = 1000000000 / TPS;
private static final int SAMPLE_INTERVAL = 20; // Paper
public final double[] recentTps = new double[ 3 ];
@ -16,7 +16,7 @@ index 90556fca9315e71c4f3fbd231ac6d765677ca271..e12fecf47798f638b85e7c6d54055a52
public final SlackActivityAccountant slackActivityAccountant = new SlackActivityAccountant();
// Spigot end
@@ -984,6 +985,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -985,6 +986,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
recentTps[1] = tps5.getAverage();
recentTps[2] = tps15.getAverage();
// Paper end
@ -41,10 +41,10 @@ index 4627261562a1482aecf4034b8717ecccc2dd9eb0..a34ed978596f1a466b0b48e7db92ac4f
public static boolean enderChestSixRows = false;
public static boolean enderChestPermissionRows = false;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 43ee4f6ba778ceb0b34906ace86f0f12587a8e8d..2ddf0e5589b6f45f502e6f675000fec361b186fe 100644
index 529f50aa6755c202ac2d3a6d0e4dfd38c4eaf6e8..cb54a5c340a8f2b82668fc7b8e3beeb977cd3c80 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2456,5 +2456,10 @@ public final class CraftServer implements Server {
@@ -2457,5 +2457,10 @@ public final class CraftServer implements Server {
public String getServerName() {
return getProperties().serverName;
}

View File

@ -1,55 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Tue, 11 Feb 2020 21:56:48 -0600
Subject: [PATCH] EntityMoveEvent
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 279662570c0bbd6c00b5732881cd35dfe694b25d..50cb2551598101d1c12007c53421b6c2f59ce2aa 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -2813,6 +2813,20 @@ public abstract class EntityLiving extends Entity {
this.collideNearby();
this.world.getMethodProfiler().exit();
+ // Purpur start
+ if (((WorldServer) world).hasEntityMoveEvent) {
+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) {
+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch);
+ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch);
+ net.pl3x.purpur.event.entity.EntityMoveEvent event = new net.pl3x.purpur.event.entity.EntityMoveEvent(getBukkitLivingEntity(), from, to.clone());
+ if (!event.callEvent()) {
+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
+ } else if (!to.equals(event.getTo())) {
+ setLocation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
+ }
+ }
+ }
+ // Purpur end
if (!this.world.isClientSide && this.dO() && this.aG()) {
this.damageEntity(DamageSource.DROWN, 1.0F);
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index e12fecf47798f638b85e7c6d54055a526097811c..d79cf993cdadfe7fadd6c7e65b9fc691a298c702 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1398,6 +1398,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
while (iterator.hasNext()) {
WorldServer worldserver = (WorldServer) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ worldserver.hasEntityMoveEvent = net.pl3x.purpur.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur
TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
this.methodProfiler.a(() -> {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index efe2a9ad2ece23bd71f4ad63b2c6f54f42345b55..2315c71465e4c1ea00a4c355b43de1e3fb0ca995 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -101,6 +101,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public final Convertable.ConversionSession convertable;
public final UUID uuid;
boolean hasPhysicsEvent = true; // Paper
+ boolean hasEntityMoveEvent = false; // Purpur
private static Throwable getAddToWorldStackTrace(Entity entity) {
return new Throwable(entity + " Added to world at " + new java.util.Date());
}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Player invulnerabilities
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 6bab47ab2583735c36d74d849ab0923494a265db..6e292d91d509327fa5b9dea947811d04e78e1e93 100644
index 7d7a512ad752e15fbe0edce47da1da76c01df3b3..9b09d68435290add2781a72e5bc62ce50a79e39f 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -150,6 +150,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@@ -151,6 +151,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.canPickUpLoot = true;
this.maxHealthCache = this.getMaxHealth();
this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
@ -17,7 +17,7 @@ index 6bab47ab2583735c36d74d849ab0923494a265db..6e292d91d509327fa5b9dea947811d04
}
// Paper start
public BlockPosition getPointInFront(double inFront) {
@@ -991,6 +993,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@@ -992,6 +994,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
}
@ -30,7 +30,7 @@ index 6bab47ab2583735c36d74d849ab0923494a265db..6e292d91d509327fa5b9dea947811d04
@Override
public boolean damageEntity(DamageSource damagesource, float f) {
if (this.isInvulnerable(damagesource)) {
@@ -998,7 +1006,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@@ -999,7 +1007,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
} else {
boolean flag = this.server.j() && this.canPvP() && "fall".equals(damagesource.translationIndex);
@ -39,15 +39,15 @@ index 6bab47ab2583735c36d74d849ab0923494a265db..6e292d91d509327fa5b9dea947811d04
return false;
} else {
if (damagesource instanceof EntityDamageSource) {
@@ -1169,6 +1177,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
// CraftBukkit end
@@ -1175,6 +1183,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
}
// Paper end
+ this.invulnerableTicks = worldserver.purpurConfig.playerSpawnInvulnerableTicks; // Purpur
return this;
}
}
@@ -2322,9 +2331,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@@ -2345,9 +2354,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@Override
public boolean isFrozen() { // Paper - protected > public
@ -108,10 +108,10 @@ index 2578a4677d1ee060f687be531e696b7c7be89e84..c441fcea9b2b5a77b801c8a69541cf42
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index debf252a23d0178f06fdadb9c27c3c66b9bbc2d0..8a28c68c5fc22838c62ceef738b330afb840c4c6 100644
index e319f3b1282af8019ae706f46e3978e789fbc877..62ef7bb712e91fed150bf9c16c11635a9aaaab67 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2239,5 +2239,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2238,5 +2238,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void resetIdleTimer() {
getHandle().resetIdleTimer();
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Giants AI settings
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 013c44f80f74376e8bbb37afb5de07aa5d8fb1bc..39036105b51dddbce8e4986e3be226f31fb13051 100644
index 2b76b5a70280def08f239ff387407a9d328d484c..ceb30228fefee86d5706b3ac0c5f2ea83d336dfb 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -136,7 +136,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@ -98,10 +98,10 @@ index 9f4f56c47ecd4b35ebf33ca0bf9a040074ababf2..565c938d879940d8e12fe320ea8524d2
}
}
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 7582a3a0955db2bc79daeced8e9c869f4276815a..7d9027d881e6e3eb0d1f8478ac7a1501dc5dec1d 100644
index 8a5e2806e68e5f4431fd9563fae780861e87632f..3936741bb8c1b3ad766d651e4bb8c9f5ddbe4f08 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -949,6 +949,7 @@ public abstract class EntityInsentient extends EntityLiving {
@@ -950,6 +950,7 @@ public abstract class EntityInsentient extends EntityLiving {
return f;
}
@ -109,7 +109,7 @@ index 7582a3a0955db2bc79daeced8e9c869f4276815a..7d9027d881e6e3eb0d1f8478ac7a1501
protected void a(DifficultyDamageScaler difficultydamagescaler) {
if (this.random.nextFloat() < 0.15F * difficultydamagescaler.d()) {
int i = this.random.nextInt(2);
@@ -1056,6 +1057,7 @@ public abstract class EntityInsentient extends EntityLiving {
@@ -1057,6 +1058,7 @@ public abstract class EntityInsentient extends EntityLiving {
}
}
@ -118,10 +118,10 @@ index 7582a3a0955db2bc79daeced8e9c869f4276815a..7d9027d881e6e3eb0d1f8478ac7a1501
float f = difficultydamagescaler.d();
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 50cb2551598101d1c12007c53421b6c2f59ce2aa..02a49d9ddc58f44471f92cd40b8b968fc7984e73 100644
index 59699bb23a189b7e53737b2f8f5263608a64109c..8ebfc9b8cf82ba914d5e56aca330033f176be334 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -165,6 +165,7 @@ public abstract class EntityLiving extends Entity {
@@ -166,6 +166,7 @@ public abstract class EntityLiving extends Entity {
this.activeItem = ItemStack.b;
this.by = Optional.empty();
this.attributeMap = new AttributeMapBase(AttributeDefaults.a(entitytypes));
@ -129,7 +129,7 @@ index 50cb2551598101d1c12007c53421b6c2f59ce2aa..02a49d9ddc58f44471f92cd40b8b968f
this.craftAttributes = new CraftAttributeMap(attributeMap); // CraftBukkit
// CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor
this.datawatcher.set(EntityLiving.HEALTH, (float) this.getAttributeInstance(GenericAttributes.MAX_HEALTH).getValue());
@@ -180,6 +181,8 @@ public abstract class EntityLiving extends Entity {
@@ -181,6 +182,8 @@ public abstract class EntityLiving extends Entity {
this.bg = this.a(new Dynamic(dynamicopsnbt, dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), dynamicopsnbt.emptyMap()))));
}
@ -138,7 +138,7 @@ index 50cb2551598101d1c12007c53421b6c2f59ce2aa..02a49d9ddc58f44471f92cd40b8b968f
public BehaviorController<?> getBehaviorController() {
return this.bg;
}
@@ -2171,7 +2174,7 @@ public abstract class EntityLiving extends Entity {
@@ -2179,7 +2182,7 @@ public abstract class EntityLiving extends Entity {
this.enderTeleportTo(vec3d.x, vec3d.y, vec3d.z);
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Zombie horse naturally spawn
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2315c71465e4c1ea00a4c355b43de1e3fb0ca995..2f41a537fb1d8348b5f65a3e85da841761311744 100644
index e99c3ad507f1381c9aa495052d2014ba8b7e0750..49ae8bd50810473d121e786a06a813b777909904 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -996,12 +996,18 @@ public class WorldServer extends World implements GeneratorAccessSeed {

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