diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e3d0cf..67c0116 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,16 +44,6 @@ jobs: with: name: Artifacts path: build/libs - - - name: Release Artifacts - if: github.ref_name == env.branch - uses: marvinpinto/action-automatic-releases@latest - with: - title: "Release #${{ env.workflow }}" - automatic_release_tag: release-${{ env.workflow }} - repo_token: "${{ secrets.GITHUB_TOKEN }}" - files: build/libs/*.jar - prerelease: false - name: Release Artifacts (Latest) if: github.ref_name == env.branch @@ -63,4 +53,4 @@ jobs: automatic_release_tag: latest-${{ env.version }} repo_token: "${{ secrets.GITHUB_TOKEN }}" files: build/libs/*.jar - prerelease: false \ No newline at end of file + prerelease: false diff --git a/DivineMC/.github/ISSUE_TEMPLATE/bug_report.yml b/DivineMC/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..3f4e9b0 --- /dev/null +++ b/DivineMC/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,64 @@ +name: Bug Report +description: File a bug report +body: + - type: markdown + attributes: + value: | + Before reporting a crash here, please make sure you are on the latest version of DivineMC. + - type: textarea + attributes: + label: Expected behavior + description: What you expected to see. + validations: + required: true + - type: textarea + attributes: + label: Observed/Actual behavior + description: What you actually saw. + validations: + required: true + - type: textarea + attributes: + label: Steps/models to reproduce + description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. + validations: + required: true + - type: textarea + attributes: + label: DivineMC version + description: | + Run `/version` on your server and **paste** the full, unmodified output here. + "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue. + Additionally, do NOT provide a screenshot, you MUST paste the entire output. +
+ Example + + ``` + > version + [17:22:05] [Thread-6/INFO]: Checking version, please wait... + [17:22:07] [Thread-6/INFO]: This server is running DivineMC version git-DivineMC-"98074bc" (MC: 1.19.2) (Implementing API version Unknown-Version) (Git: 98074bc on ver/1.19.2) + [17:22:07] [Thread-6/INFO]: You are running 2 versions beyond. Please update your server when possible to maintain stability, security, and receive the latest optimizations. + ``` + +
+ validations: + required: true + - type: checkboxes + attributes: + label: Agreements + description: Please agree to the following. + options: + - label: I am running the latest version of DivineMC from [here](https://github.com/DivineMC/DivineMC/releases). + required: true + - label: I have searched for and ensured there isn't already an open issue regarding this. + required: true + - label: My version of Minecraft is supported by DivineMC. + required: true + - type: textarea + attributes: + label: Other + description: | + Please include other helpful information below. + The more information we receive, the quicker and more effective we can be at finding the solution to the issue. + validations: + required: false \ No newline at end of file diff --git a/DivineMC/.github/ISSUE_TEMPLATE/config.yml b/DivineMC/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..87bebdf --- /dev/null +++ b/DivineMC/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: DivineMC Discord + url: https://discord.gg/PrKTKfR579 + about: If you are having issues, come ask us on our Discord server! + - name: DivineMC Docs + url: https://divinemc.bxteam.gq/docs + about: You can find some Q&A at our DivineMC docs \ No newline at end of file diff --git a/DivineMC/.github/workflows/build.yml b/DivineMC/.github/workflows/build.yml new file mode 100644 index 0000000..67c0116 --- /dev/null +++ b/DivineMC/.github/workflows/build.yml @@ -0,0 +1,56 @@ +name: Build DivineMC +on: + push: + workflow_dispatch: + +env: + version: 1.19.2 + branch: ver/1.19.2 + debug: 'false' + +jobs: + build: + runs-on: ubuntu-latest + if: "!contains(github.event.commits[0].message, '[ci-skip]')" + steps: + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1 + + - name: Setup JDK 17 + uses: actions/setup-java@v2 + with: + distribution: temurin + java-version: 17 + cache: 'gradle' + + - name: Configure Git + run: | + git config --global user.email "no-reply@github.com" && git config --global user.name "Github Actions" + echo "workflow=$GITHUB_RUN_NUMBER" >> $GITHUB_ENV + chmod +x gradlew + + - name: Patch + run: ./gradlew applyPatches --stacktrace + + - name: Create Reobf Jar + run: ./gradlew createReobfPaperclipJar --stacktrace + + - name: Create Mojmap Jar + run: ./gradlew createMojmapPaperclipJar --stacktrace + + - name: Upload Artifacts + if: env.debug == 'true' || github.ref_name != env.branch + uses: actions/upload-artifact@main + with: + name: Artifacts + path: build/libs + + - name: Release Artifacts (Latest) + if: github.ref_name == env.branch + uses: marvinpinto/action-automatic-releases@latest + with: + title: "Release #${{ env.workflow }}" + automatic_release_tag: latest-${{ env.version }} + repo_token: "${{ secrets.GITHUB_TOKEN }}" + files: build/libs/*.jar + prerelease: false diff --git a/DivineMC/.gitignore b/DivineMC/.gitignore new file mode 100644 index 0000000..2a4a725 --- /dev/null +++ b/DivineMC/.gitignore @@ -0,0 +1,6 @@ +DivineMC-API +DivineMC-Server + +build/ +.gradle/ +run/ \ No newline at end of file diff --git a/DivineMC/PATCHES-LICENSE b/DivineMC/PATCHES-LICENSE new file mode 100644 index 0000000..810fce6 --- /dev/null +++ b/DivineMC/PATCHES-LICENSE @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/DivineMC/README.md b/DivineMC/README.md new file mode 100644 index 0000000..c363616 --- /dev/null +++ b/DivineMC/README.md @@ -0,0 +1,45 @@ +DivineMC Face +
+

DivineMC

+

Fork of Paper compatible with Spigot plugins, offering best performance for your server.

+

DivineMC is ❗ under heavy development ❗ and contributions are welcome!

+
+ + ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/DivineMC/DivineMC/Build%20DivineMC?style=for-the-badge) + [![Discord](https://img.shields.io/discord/931595732752953375?color=5865F2&label=discord&style=for-the-badge)](https://discord.gg/PrKTKfR579) +
+ +## Features + +- **DivineMC is a fork of [Pufferfish](https://github.com/pufferfish-gg/Pufferfish)** which a the best performance Minecraft core. +- **Contains [Lithium](https://github.com/CaffeineMC/lithium-fabric) patches** which is optimize many areas in game. +- **Bug fixes** for several Minecraft issues. +- **Faster process** for Vanilla methods. +- **Plugin compatibility** with Spigot & Paper plugins. + +## We use patches from the following projects + +* **[Paper](https://github.com/PaperMC/Paper)** +* **[Purpur](https://github.com/pl3xgaming/Purpur)** +* **[Mirai](https://github.com/etil2jz/Mirai)** +* **NOTE: We also borrow some patches from [Yatopia](https://github.com/YatopiaMC/Yatopia).** + +## Downloads +For now, we have a Jenkins bug and builds in Jenkins is not available, so you can download DivineMC from Github artifacts [here](https://github.com/DivineMC/DivineMC/actions)! + +**Please note Java >= 17 is required.** + +##### Soon we will request free repo at CodeMC + +## Building +In order to distribute and use this server software, you need a paperclip file: + +```bash +./gradlew applyPatches && ./gradlew createReobfPaperclipJar +``` + +## License +Patches are licensed under GPL-3.0. +All other files are licensed under MIT. + +###### And we dont stealed logo from YatopiaMC!!! diff --git a/DivineMC/build-data/dev-imports.txt b/DivineMC/build-data/dev-imports.txt new file mode 100644 index 0000000..b818b96 --- /dev/null +++ b/DivineMC/build-data/dev-imports.txt @@ -0,0 +1,10 @@ +# You can use this file to import files from minecraft libraries into the project +# format: +# +# both fully qualified and a file based syntax are accepted for : +# authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +# datafixerupper com.mojang.datafixers.DataFixerBuilder +# datafixerupper com/mojang/datafixers/util/Either.java +# To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId: +# minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter +# minecraft net/minecraft/world/level/entity/LevelEntityGetter.java diff --git a/DivineMC/build.gradle.kts b/DivineMC/build.gradle.kts new file mode 100644 index 0000000..61b312a --- /dev/null +++ b/DivineMC/build.gradle.kts @@ -0,0 +1,62 @@ +plugins { + java + id("com.github.johnrengelman.shadow") version "7.1.2" apply false + id("io.papermc.paperweight.patcher") version "1.3.8" +} + +repositories { + mavenCentral() + maven("https://papermc.io/repo/repository/maven-public/") +} + +dependencies { + remapper("net.fabricmc:tiny-remapper:0.7.0:fat") + decompiler("net.minecraftforge:forgeflower:1.5.498.22") + paperclip("io.papermc:paperclip:3.0.2") +} + +subprojects { + apply(plugin = "java") + + java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } } + + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(17) + } + + repositories { + mavenCentral() + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://ci.emc.gs/nexus/content/groups/aikar/") + maven("https://repo.aikar.co/content/groups/aikar") + maven("https://repo.md-5.net/content/repositories/releases/") + maven("https://hub.spigotmc.org/nexus/content/groups/public/") + maven("https://oss.sonatype.org/content/repositories/snapshots/") + maven("https://jitpack.io") + } +} + +paperweight { + serverProject.set(project(":DivineMC-Server")) + + remapRepo.set("https://maven.fabricmc.net/") + decompileRepo.set("https://files.minecraftforge.net/maven/") + + useStandardUpstream("pufferfish") { + url.set(github("pufferfish-gg", "Pufferfish")) + ref.set(providers.gradleProperty("pufferfishRef")) + + withStandardPatcher { + apiSourceDirPath.set("pufferfish-api") + serverSourceDirPath.set("pufferfish-server") + + apiPatchDir.set(layout.projectDirectory.dir("patches/api")) + serverPatchDir.set(layout.projectDirectory.dir("patches/server")) + + apiOutputDir.set(layout.projectDirectory.dir("DivineMC-API")) + serverOutputDir.set(layout.projectDirectory.dir("DivineMC-Server")) + } + } +} diff --git a/DivineMC/gradle.properties b/DivineMC/gradle.properties new file mode 100644 index 0000000..46ba70a --- /dev/null +++ b/DivineMC/gradle.properties @@ -0,0 +1,12 @@ +group=gq.bxteam.divinemc + +version=1.19.2-R0.1-SNAPSHOT +mcVersion=1.19.2 +pufferfishRef=deb9638cd5243286685c20d254fdec9c2754979b + +org.gradle.jvmargs=-Xmx2G + +org.gradle.caching=true +org.gradle.parallel=true +org.gradle.parallel.threads=8 +org.gradle.daemon=true diff --git a/DivineMC/gradle/wrapper/gradle-wrapper.jar b/DivineMC/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7454180 Binary files /dev/null and b/DivineMC/gradle/wrapper/gradle-wrapper.jar differ diff --git a/DivineMC/gradle/wrapper/gradle-wrapper.properties b/DivineMC/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ae04661 --- /dev/null +++ b/DivineMC/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/DivineMC/gradlew b/DivineMC/gradlew new file mode 100644 index 0000000..744e882 --- /dev/null +++ b/DivineMC/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/DivineMC/gradlew.bat b/DivineMC/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/DivineMC/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/DivineMC/patches/api/0001-Add-last-tick-time-API.patch b/DivineMC/patches/api/0001-Add-last-tick-time-API.patch new file mode 100644 index 0000000..21f3104 --- /dev/null +++ b/DivineMC/patches/api/0001-Add-last-tick-time-API.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Sun, 27 Sep 2020 18:01:50 +0300 +Subject: [PATCH] Add last tick time API + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 232c08c9a588d957d90f198ce479e57615c6e650..bfa71be59dd84459bd420ace2d6694e1d80aee81 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2430,6 +2430,16 @@ public final class Bukkit { + return server.isStopping(); + } + ++ // Yatopia start ++ @Deprecated ++ public static long getLastTickMs() { ++ return server.getLastTickMs(); ++ } ++ @NotNull public static java.time.Duration getLastTickTime() { ++ return server.getLastTickTime(); ++ } ++ // Yatopia end ++ + /** + * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index e43fef0152468944d8a33036344a43e95fe58476..6f4250d7750c7d834db87be14d82caaa4d94b51c 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2116,6 +2116,26 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + boolean isStopping(); + ++ // Yatopia start ++ /** ++ * Returns the time the last tick took in milliseconds. ++ * ++ * @return long time value ++ * @deprecated newer method with java's Duration and a possibility to convert it from millis to something else ++ */ ++ @Deprecated ++ default long getLastTickMs() { ++ return getLastTickTime().toMillis(); ++ } ++ /** ++ * Returns the time in {@link java.time.Duration} the last tick took. ++ * ++ * @return duration ++ */ ++ @NotNull ++ java.time.Duration getLastTickTime(); ++ // Yatopia end ++ + /** + * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager + * diff --git a/DivineMC/patches/api/0002-Optimize-Spigot-event-bus.patch b/DivineMC/patches/api/0002-Optimize-Spigot-event-bus.patch new file mode 100644 index 0000000..5ddc5b4 --- /dev/null +++ b/DivineMC/patches/api/0002-Optimize-Spigot-event-bus.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Thu, 9 Dec 2021 01:53:30 +0100 +Subject: [PATCH] Optimize Spigot event bus + +Original code by lynxplay, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/lynxplay/ktp + +diff --git a/src/main/java/org/bukkit/plugin/RegisteredListener.java b/src/main/java/org/bukkit/plugin/RegisteredListener.java +index 419aec56b0e3fa8bcec2ea7f340caa3456b57d00..8530d926931a54ed1300c40cd1e0908b2d9b594d 100644 +--- a/src/main/java/org/bukkit/plugin/RegisteredListener.java ++++ b/src/main/java/org/bukkit/plugin/RegisteredListener.java +@@ -62,8 +62,10 @@ public class RegisteredListener { + * @throws EventException If an event handler throws an exception. + */ + public void callEvent(@NotNull final Event event) throws EventException { +- if (event instanceof Cancellable) { +- if (((Cancellable) event).isCancelled() && isIgnoringCancelled()) { ++ // KTP start - optimize spigot event bus ++ if (isIgnoringCancelled()) { ++ if (event instanceof Cancellable cancellable && cancellable.isCancelled()) { ++ // KTP end - optimize spigot event bus + return; + } + } +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 49a4611ed4891cce10fd6e01b4062740ad18ee6f..d70c0e3172828b43bc7dea2c84d92282403a7fa8 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -654,11 +654,15 @@ public final class SimplePluginManager implements PluginManager { + @Override + public void callEvent(@NotNull Event event) { + // Paper - replace callEvent by merging to below method +- if (event.isAsynchronous() && server.isPrimaryThread()) { ++ // KTP start - optimize spigot event bus ++ final boolean isAsync = event.isAsynchronous(); ++ final boolean isPrimary = server.isPrimaryThread(); // Cache to prevent multiple thread object comparisons. ++ if (isAsync && isPrimary) { + throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); +- } else if (!event.isAsynchronous() && !server.isPrimaryThread() && !server.isStopping() ) { ++ } else if (!isAsync && !isPrimary && !server.isStopping() ) { + throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); + } ++ // KTP end - optimize spigot event bus + + HandlerList handlers = event.getHandlers(); + RegisteredListener[] listeners = handlers.getRegisteredListeners(); diff --git a/DivineMC/patches/server/0001-Divine-Branding.patch b/DivineMC/patches/server/0001-Divine-Branding.patch new file mode 100644 index 0000000..ed62e5a --- /dev/null +++ b/DivineMC/patches/server/0001-Divine-Branding.patch @@ -0,0 +1,262 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAY +Date: Fri, 4 Nov 2022 17:00:07 +0300 +Subject: [PATCH] Divine Branding + + +diff --git a/build.gradle.kts b/build.gradle.kts +index f0d22a733e3b97fb959cd566fb6c93c6d5681e16..91aa2bbb1a5d860e61ebd77fb7af6edf804c4a45 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -9,7 +9,7 @@ plugins { + } + + dependencies { +- implementation(project(":pufferfish-api")) // Pufferfish // Paper ++ implementation(project(":DivineMC-API")) // DivineMC // Pufferfish // Paper + // Pufferfish start + implementation("io.papermc.paper:paper-mojangapi:1.19.2-R0.1-SNAPSHOT") { + exclude("io.papermc.paper", "paper-api") +@@ -84,7 +84,7 @@ tasks.jar { + attributes( + "Main-Class" to "org.bukkit.craftbukkit.Main", + "Implementation-Title" to "CraftBukkit", +- "Implementation-Version" to "git-Pufferfish-$implementationVersion", // Pufferfish ++ "Implementation-Version" to "git-DivineMC-$implementationVersion", // DivineMC // Pufferfish + "Implementation-Vendor" to date, // Paper + "Specification-Title" to "Bukkit", + "Specification-Version" to project.version, +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 061716934ba0a1f01e4d85d664034f72b3c7a765..728c176fd19d3b322f9092153b3c1d189aec3fe8 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -593,7 +593,7 @@ public class Metrics { + boolean logFailedRequests = config.getBoolean("logFailedRequests", false); + // Only start Metrics, if it's enabled in the config + if (config.getBoolean("enabled", true)) { +- Metrics metrics = new Metrics("Pufferfish", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish ++ Metrics metrics = new Metrics("DivineMC", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish // DivineMC + + metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { + String minecraftVersion = Bukkit.getVersion(); +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index c5d5648f4ca603ef2b1df723b58f9caf4dd3c722..05478a1ea04ec0396bc8c97090edef4a2aced2a9 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -17,7 +17,7 @@ public final class PaperConsole extends SimpleTerminalConsole { + @Override + protected LineReader buildReader(LineReaderBuilder builder) { + builder +- .appName("Paper") ++ .appName("DivineMC") // DivineMC + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) + .option(LineReader.Option.COMPLETE_IN_WORD, true); +diff --git a/src/main/java/gq/bxteam/divinemc/DivineVersionFetcher.java b/src/main/java/gq/bxteam/divinemc/DivineVersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b222c6480376a8167dbf95db69ec046780753515 +--- /dev/null ++++ b/src/main/java/gq/bxteam/divinemc/DivineVersionFetcher.java +@@ -0,0 +1,137 @@ ++package gq.bxteam.divinemc; ++ ++import com.destroystokyo.paper.VersionHistoryManager; ++import com.destroystokyo.paper.util.VersionFetcher; ++import com.google.gson.Gson; ++import com.google.gson.JsonObject; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.JoinConfiguration; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextDecoration; ++import org.bukkit.craftbukkit.CraftServer; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.io.IOException; ++import java.net.URI; ++import java.net.http.HttpClient; ++import java.net.http.HttpRequest; ++import java.net.http.HttpResponse; ++import java.nio.charset.StandardCharsets; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import static net.kyori.adventure.text.Component.text; ++import static net.kyori.adventure.text.format.NamedTextColor.GREEN; ++import static net.kyori.adventure.text.format.NamedTextColor.RED; ++ ++public class DivineVersionFetcher implements VersionFetcher { ++ private static final Logger LOGGER = Logger.getLogger("DivineVersionFetcher"); ++ private static final HttpClient client = HttpClient.newHttpClient(); ++ ++ private static final URI JENKINS_URI = URI.create("https://ci.bxteam.gq/job/DivineMC/job/DivineMC-1.19/lastSuccessfulBuild/buildNumber"); ++ private static final String GITHUB_FORMAT = "https://api.github.com/repos/DivineMC/DivineMC/compare/ver/1.19.2...%s"; ++ ++ private static final HttpResponse.BodyHandler JSON_OBJECT_BODY_HANDLER = responseInfo -> HttpResponse.BodySubscribers.mapping( ++ HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8), ++ string -> new Gson().fromJson(string, JsonObject.class) ++ ); ++ ++ @Override ++ public long getCacheTime() { ++ return TimeUnit.MINUTES.toMillis(30); ++ } ++ ++ @Override ++ public @NotNull Component getVersionMessage(final @NotNull String serverVersion) { ++ final String[] parts = CraftServer.class.getPackage().getImplementationVersion().split("-"); ++ @NotNull Component component; ++ ++ if (parts.length != 3) { ++ component = text("Unknown server version.", RED); ++ } else { ++ final String versionString = parts[2]; ++ ++ try { ++ component = this.fetchJenkinsVersion(Integer.parseInt(versionString)); ++ } catch (NumberFormatException e) { ++ component = this.fetchGithubVersion(versionString.substring(1, versionString.length() - 1)); ++ } ++ } ++ ++ final @Nullable Component history = this.getHistory(); ++ return history != null ? Component.join(JoinConfiguration.noSeparators(), component, Component.newline(), this.getHistory()) : component; ++ } ++ ++ private @NotNull ++ Component fetchJenkinsVersion(final int versionNumber) { ++ final HttpRequest request = HttpRequest.newBuilder(JENKINS_URI).build(); ++ try { ++ final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); ++ if (response.statusCode() != 200) { ++ return text("Received invalid status code (" + response.statusCode() + ") from server.", RED); ++ } ++ ++ int latestVersionNumber; ++ try { ++ latestVersionNumber = Integer.parseInt(response.body()); ++ } catch (NumberFormatException e) { ++ LOGGER.log(Level.WARNING, "Received invalid response from Jenkins \"" + response.body() + "\"."); ++ return text("Received invalid response from server.", RED); ++ } ++ ++ final int versionDiff = latestVersionNumber - versionNumber; ++ return this.getResponseMessage(versionDiff); ++ } catch (IOException | InterruptedException e) { ++ LOGGER.log(Level.WARNING, "Failed to look up version from Jenkins", e); ++ return text("Failed to retrieve version from server.", RED); ++ } ++ } ++ ++ // Based off code contributed by Techcable in Paper/GH-65 ++ private @NotNull ++ Component fetchGithubVersion(final @NotNull String hash) { ++ final URI uri = URI.create(String.format(GITHUB_FORMAT, hash)); ++ final HttpRequest request = HttpRequest.newBuilder(uri).build(); ++ try { ++ final HttpResponse response = client.send(request, JSON_OBJECT_BODY_HANDLER); ++ if (response.statusCode() != 200) { ++ return text("Received invalid status code (" + response.statusCode() + ") from server.", RED); ++ } ++ ++ final JsonObject obj = response.body(); ++ final int versionDiff = obj.get("behind_by").getAsInt(); ++ ++ return this.getResponseMessage(versionDiff); ++ } catch (IOException | InterruptedException e) { ++ LOGGER.log(Level.WARNING, "Failed to look up version from GitHub", e); ++ return text("Failed to retrieve version from server.", RED); ++ } ++ } ++ ++ private @NotNull ++ Component getResponseMessage(final int versionDiff) { ++ return switch (Math.max(-1, Math.min(1, versionDiff))) { ++ case -1 -> text("You are running an unsupported version of DivineMC.", RED); ++ case 0 -> text("You are on the latest version!", GREEN); ++ default -> text("You are running " + versionDiff + " version" + (versionDiff == 1 ? "" : "s") + " beyond. " + ++ "Please update your server when possible to maintain stability, security, and receive the latest optimizations.", RED); ++ }; ++ } ++ ++ private @Nullable ++ Component getHistory() { ++ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); ++ if (data == null) { ++ return null; ++ } ++ ++ final String oldVersion = data.getOldVersion(); ++ if (oldVersion == null) { ++ return null; ++ } ++ ++ return text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index af9da39dffda01325af2ab3dd8b5e1efb18e013a..6b4dbf0e1b5ddcf2bd33a917e4ee3654be511147 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1656,7 +1656,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "DivineMC"; // DivineMC - DivineMC > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public SystemReport fillSystemReport(SystemReport details) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b8efe50c860a7537f345f46f3b3d68906ad54006..662d9f8474ad2bc2d741875fb6e78804fda6f17c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -248,7 +248,7 @@ import javax.annotation.Nullable; // Paper + import javax.annotation.Nonnull; // Paper + + public final class CraftServer implements Server { +- private final String serverName = "Pufferfish"; // Paper // Pufferfish ++ private final String serverName = "DivineMC"; // Paper // Pufferfish // DivineMC + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index f30621be24c6c3a4f173436fce1ad1c13507c84f..490ef861ecb5c1001d7ab8de09d8be2961b6579f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -278,7 +278,7 @@ public class Main { + if (buildDate.before(deadline.getTime())) { + // Paper start - This is some stupid bullshit + System.err.println("*** Warning, you've not updated in a while! ***"); +- System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper ++ System.err.println("*** Please download a new build as per instructions from https://ci.bxteam.gq ***"); // Paper // DivineMC + //System.err.println("*** Server will start in 20 seconds ***"); + //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + // Paper End +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 05cc8f9cdcd7e920bf9503f68efb16cd74a359a2..dfa5965f30ba9f9a8f921ba73e340a9166a6ed8b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -430,7 +430,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { +- return new gg.pufferfish.pufferfish.PufferfishVersionFetcher(); // Pufferfish ++ return new gq.bxteam.divinemc.DivineVersionFetcher(); // Pufferfish // DivineMC + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 80553face9c70c2a3d897681e7761df85b22d464..627ceea9fa0fccd3e466eb34d59e760be30a69a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/gg.pufferfish.pufferfish/pufferfish-api/pom.properties"); // Pufferfish ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/gq.bxteam.divinemc/divinemc-api/pom.properties"); // Pufferfish // DivineMC + Properties properties = new Properties(); + + if (stream != null) { diff --git a/DivineMC/patches/server/0002-Global-Eula-file.patch b/DivineMC/patches/server/0002-Global-Eula-file.patch new file mode 100644 index 0000000..a557de6 --- /dev/null +++ b/DivineMC/patches/server/0002-Global-Eula-file.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Sat, 25 Jul 2020 17:16:18 +0200 +Subject: [PATCH] Global Eula file + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/net/minecraft/server/Eula.java b/src/main/java/net/minecraft/server/Eula.java +index 30599028f6263fbf61ab95d68573073426db19db..9e169c96fa1bc9dea9efb27cb996b4dd5d2a4c0c 100644 +--- a/src/main/java/net/minecraft/server/Eula.java ++++ b/src/main/java/net/minecraft/server/Eula.java +@@ -16,12 +16,26 @@ public class Eula { + + public Eula(Path eulaFile) { + this.file = eulaFile; +- this.agreed = SharedConstants.IS_RUNNING_IN_IDE || this.readFile(); ++ this.agreed = SharedConstants.IS_RUNNING_IN_IDE || globalEula() || this.readFile(eulaFile); + } + +- private boolean readFile() { ++ // Yatopia start - global eula file ++ private boolean globalEula() { ++ java.io.File globalEula = new java.io.File(System.getProperty("user.home"), "eula.txt"); ++ ++ if (globalEula.exists()) { ++ System.out.println("Loaded global eula file from " + globalEula.getAbsolutePath()); ++ return readFile(globalEula.toPath()); ++ } else { ++ System.out.println("No global eula file found at " + globalEula.getAbsolutePath()); ++ } ++ return false; ++ } ++ // Yatopia end ++ ++ private boolean readFile(java.nio.file.Path path) { + try { +- InputStream inputStream = Files.newInputStream(this.file); ++ InputStream inputStream = Files.newInputStream(path); + + boolean var3; + try { diff --git a/DivineMC/patches/server/0003-Time-Utilities.patch b/DivineMC/patches/server/0003-Time-Utilities.patch new file mode 100644 index 0000000..df0c908 --- /dev/null +++ b/DivineMC/patches/server/0003-Time-Utilities.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Fri, 23 Oct 2020 09:20:01 -0700 +Subject: [PATCH] Time Utilities + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java b/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bb023bcb4b1e1ab5261c83358ce0951cc35ba16d +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java +@@ -0,0 +1,27 @@ ++package org.yatopiamc.yatopia.server.util; ++ ++import java.util.concurrent.TimeUnit; ++ ++public class TimeUtils { ++ ++ public static String getFriendlyName(TimeUnit unit) { ++ switch (unit) { ++ case NANOSECONDS: ++ return "ns"; ++ case MILLISECONDS: ++ return "ms"; ++ case MICROSECONDS: ++ return "micros"; ++ case SECONDS: ++ return "s"; ++ case MINUTES: ++ return "m"; ++ case DAYS: ++ return "d"; ++ case HOURS: ++ return "h"; ++ default: ++ throw new AssertionError(); ++ } ++ } ++} +\ No newline at end of file diff --git a/DivineMC/patches/server/0004-Reduce-constants-allocations.patch b/DivineMC/patches/server/0004-Reduce-constants-allocations.patch new file mode 100644 index 0000000..9332bdb --- /dev/null +++ b/DivineMC/patches/server/0004-Reduce-constants-allocations.patch @@ -0,0 +1,708 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Simon Gardling +Date: Tue, 9 Nov 2021 16:53:39 -0500 +Subject: [PATCH] Reduce constants allocations + +This patch includes code from the lithium project under the GNU Lesser General Public License v3.0: https://github.com/CaffeineMC/lithium-fabric/ but also original code created by your's truly + +Original code by Titaniumtown, licensed under GNU General Public License v3.0 +You can find the original code on https://gitlab.com/Titaniumtown/JettPack + +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +index 0133ea6feb1ab88f021f66855669f58367e7420b..5f4ad69862b24b568b9e907563289624d196d6ea 100644 +--- a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +@@ -17,9 +17,9 @@ public final class EntityList implements Iterable { + this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); + } + +- protected static final Entity[] EMPTY_LIST = new Entity[0]; ++ //protected static final Entity[] EMPTY_LIST = new Entity[0]; // JettPack + +- protected Entity[] entities = EMPTY_LIST; ++ protected Entity[] entities = me.titaniumtown.Constants.EMPTY_entity_arr; // JettPack + protected int count; + + public int size() { +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +index 277cfd9d1e8fff5d9b5e534b75c3c5162d58b0b7..093170c13b3980791373fb240c9ec6c5adfc1519 100644 +--- a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +@@ -20,9 +20,9 @@ public final class IBlockDataList { + this.map.defaultReturnValue(Long.MAX_VALUE); + } + +- private static final long[] EMPTY_LIST = new long[0]; ++ //private static final long[] EMPTY_LIST = new long[0]; // JettPack + +- private long[] byIndex = EMPTY_LIST; ++ private long[] byIndex = me.titaniumtown.Constants.EMPTY_long_arr; // JettPack + private int size; + + public static int getLocationKey(final int x, final int y, final int z) { +diff --git a/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java +index ae60bd96b5284d54676d8e7e4dd5d170b526ec1e..2344ea858eda8e54c2eb3ccbdad464ed5934650c 100644 +--- a/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java ++++ b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java +@@ -14,7 +14,7 @@ public final class VersionCommand implements PaperSubcommand { + public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { + final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); + if (ver != null) { +- ver.execute(sender, "paper", new String[0]); ++ ver.execute(sender, "paper", me.titaniumtown.Constants.EMPTY_string_arr); // JettPack + } + return true; + } +diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +index f597d65d56964297eeeed6c7e77703764178fee0..209c4f0b25470bff7278c0a8dcd30576900b9933 100644 +--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java ++++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +@@ -81,7 +81,7 @@ public final class ChunkEntitySlices { + } + } + +- return ret.toArray(new org.bukkit.entity.Entity[0]); ++ return ret.toArray(me.titaniumtown.Constants.EMPTY_bukkit_entity_arr); // JettPack + } + + public CompoundTag save() { +@@ -298,7 +298,7 @@ public final class ChunkEntitySlices { + + protected static final class BasicEntityList { + +- protected static final Entity[] EMPTY = new Entity[0]; ++ //protected static final Entity[] EMPTY = new Entity[0]; // JettPack + protected static final int DEFAULT_CAPACITY = 4; + + protected E[] storage; +@@ -309,7 +309,7 @@ public final class ChunkEntitySlices { + } + + public BasicEntityList(final int cap) { +- this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]); ++ this.storage = (E[])(cap <= 0 ? me.titaniumtown.Constants.EMPTY_entity_arr : new Entity[cap]); // JettPack + } + + public boolean isEmpty() { +@@ -321,7 +321,7 @@ public final class ChunkEntitySlices { + } + + private void resize() { +- if (this.storage == EMPTY) { ++ if (this.storage == me.titaniumtown.Constants.EMPTY_entity_arr) { // JettPack + this.storage = (E[])new Entity[DEFAULT_CAPACITY]; + } else { + this.storage = Arrays.copyOf(this.storage, this.storage.length * 2); +diff --git a/src/main/java/me/titaniumtown/Constants.java b/src/main/java/me/titaniumtown/Constants.java +new file mode 100644 +index 0000000000000000000000000000000000000000..60bf30759a26c04c0f79ba739426aab1de955243 +--- /dev/null ++++ b/src/main/java/me/titaniumtown/Constants.java +@@ -0,0 +1,16 @@ ++package me.titaniumtown; ++ ++import net.minecraft.core.BlockPos; ++ ++public final class Constants { ++ private Constants() {} ++ ++ public static final Object[] EMPTY_object_arr = new Object[0]; ++ public static final int[] EMPTY_int_arr = new int[0]; ++ public static final int[] ZERO_int_arr = new int[]{0}; ++ public static final byte[] EMPTY_byte_arr = new byte[0]; ++ public static final String[] EMPTY_string_arr = new String[0]; ++ public static final long[] EMPTY_long_arr = new long[0]; ++ public static final org.bukkit.entity.Entity[] EMPTY_bukkit_entity_arr = new org.bukkit.entity.Entity[0]; ++ public static final net.minecraft.world.entity.Entity[] EMPTY_entity_arr = new net.minecraft.world.entity.Entity[0]; ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/advancements/RequirementsStrategy.java b/src/main/java/net/minecraft/advancements/RequirementsStrategy.java +index 57d504d15794b1640ff7186f563d6ca5c2453d8c..97ca3c80af66884e74595a051224d54b9a8bde21 100644 +--- a/src/main/java/net/minecraft/advancements/RequirementsStrategy.java ++++ b/src/main/java/net/minecraft/advancements/RequirementsStrategy.java +@@ -14,7 +14,7 @@ public interface RequirementsStrategy { + return strings; + }; + RequirementsStrategy OR = (collection) -> { +- return new String[][]{collection.toArray(new String[0])}; ++ return new String[][]{collection.toArray(me.titaniumtown.Constants.EMPTY_string_arr)}; // JettPack + }; + + String[][] createRequirements(Collection criteriaNames); +diff --git a/src/main/java/net/minecraft/nbt/ByteArrayTag.java b/src/main/java/net/minecraft/nbt/ByteArrayTag.java +index 3dd8a189c26f41759c59c3b9d0e5282038989a9f..147beddf8ef369cdae4b1ed2dcd0d7b2fd865315 100644 +--- a/src/main/java/net/minecraft/nbt/ByteArrayTag.java ++++ b/src/main/java/net/minecraft/nbt/ByteArrayTag.java +@@ -170,7 +170,7 @@ public class ByteArrayTag extends CollectionTag { + } + + public void clear() { +- this.data = new byte[0]; ++ this.data = me.titaniumtown.Constants.EMPTY_byte_arr; // JettPack + } + + @Override +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 912fd5135e89348bdd3c0a8b6c07860ebc106df3..beecf9d1effea5cd12d1f826cc8071cd83b5a4d5 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -364,7 +364,7 @@ public class CompoundTag implements Tag { + throw new ReportedException(this.createReport(key, ByteArrayTag.TYPE, var3)); + } + +- return new byte[0]; ++ return me.titaniumtown.Constants.EMPTY_byte_arr; // JettPack + } + + public int[] getIntArray(String key) { +@@ -376,7 +376,7 @@ public class CompoundTag implements Tag { + throw new ReportedException(this.createReport(key, IntArrayTag.TYPE, var3)); + } + +- return new int[0]; ++ return me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + public long[] getLongArray(String key) { +@@ -388,7 +388,7 @@ public class CompoundTag implements Tag { + throw new ReportedException(this.createReport(key, LongArrayTag.TYPE, var3)); + } + +- return new long[0]; ++ return me.titaniumtown.Constants.EMPTY_long_arr; // JettPack + } + + public CompoundTag getCompound(String key) { +diff --git a/src/main/java/net/minecraft/nbt/IntArrayTag.java b/src/main/java/net/minecraft/nbt/IntArrayTag.java +index a14b01cee7a8d7022c4fa7264d349a76be143ba5..44f441d6c102fa5bd50071cae991a8a6ba0ec713 100644 +--- a/src/main/java/net/minecraft/nbt/IntArrayTag.java ++++ b/src/main/java/net/minecraft/nbt/IntArrayTag.java +@@ -184,7 +184,7 @@ public class IntArrayTag extends CollectionTag { + } + + public void clear() { +- this.data = new int[0]; ++ this.data = me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + @Override +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index 6a5e33d9821221be73f9c16afc17c9130248a231..29b7bde3ef3c5817910ccd5248e791f9e2948af7 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -218,7 +218,7 @@ public class ListTag extends CollectionTag { + } + } + +- return new int[0]; ++ return me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + public long[] getLongArray(int index) { +@@ -229,7 +229,7 @@ public class ListTag extends CollectionTag { + } + } + +- return new long[0]; ++ return me.titaniumtown.Constants.EMPTY_long_arr; // JettPack + } + + public double getDouble(int index) { +diff --git a/src/main/java/net/minecraft/nbt/LongArrayTag.java b/src/main/java/net/minecraft/nbt/LongArrayTag.java +index a39baec88dc9c73f1b592881ed96d11ab64ad785..710bb5579e23258c38a767f99d751576524f88f0 100644 +--- a/src/main/java/net/minecraft/nbt/LongArrayTag.java ++++ b/src/main/java/net/minecraft/nbt/LongArrayTag.java +@@ -188,7 +188,7 @@ public class LongArrayTag extends CollectionTag { + + @Override + public void clear() { +- this.data = new long[0]; ++ this.data = me.titaniumtown.Constants.EMPTY_long_arr; // JettPack + } + + @Override +diff --git a/src/main/java/net/minecraft/network/CipherBase.java b/src/main/java/net/minecraft/network/CipherBase.java +index a2920b8a9eff77d9c5d1d7f70ad3abdacba8f0fa..f7f19e360d712211625ff28e92f83949197c93b0 100644 +--- a/src/main/java/net/minecraft/network/CipherBase.java ++++ b/src/main/java/net/minecraft/network/CipherBase.java +@@ -7,8 +7,8 @@ import javax.crypto.ShortBufferException; + + public class CipherBase { + private final Cipher cipher; +- private byte[] heapIn = new byte[0]; +- private byte[] heapOut = new byte[0]; ++ private byte[] heapIn = me.titaniumtown.Constants.EMPTY_byte_arr; // JettPack ++ private byte[] heapOut = me.titaniumtown.Constants.EMPTY_byte_arr; // JettPack + + protected CipherBase(Cipher cipher) { + this.cipher = cipher; +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index cd386a13d8c0909d4ac971a5df751cd23e609b1b..5344f1f81797344130bd48f16689161af8261882 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -311,7 +311,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void setListener(PacketListener listener) { +- Validate.notNull(listener, "packetListener", new Object[0]); ++ Validate.notNull(listener, "packetListener", me.titaniumtown.Constants.EMPTY_object_arr); // JettPack + this.packetListener = listener; + } + // Paper start +diff --git a/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java b/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java +index 02fb51f7f699992caf13d088c75b8275ec5267bb..11cb4ac19ddc09889117690ffec5191534a8adee 100644 +--- a/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java ++++ b/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java +@@ -20,7 +20,7 @@ import net.minecraft.network.chat.Style; + import net.minecraft.world.entity.Entity; + + public class TranslatableContents implements ComponentContents { +- private static final Object[] NO_ARGS = new Object[0]; ++ private static final Object[] NO_ARGS = me.titaniumtown.Constants.EMPTY_object_arr; // JettPack + private static final FormattedText TEXT_PERCENT = FormattedText.of("%"); + private static final FormattedText TEXT_NULL = FormattedText.of("null"); + private final String key; +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 5962f7a2b185d7d54a0f9e341a4fdf6e6f1c1ec5..0b677d128cbd108bb58d74d3cfe6015551e94143 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -85,7 +85,7 @@ public class Main { + OptionSpec optionspec6 = optionparser.accepts("safeMode", "Loads level with vanilla datapack only"); + OptionSpec optionspec7 = optionparser.accepts("help").forHelp(); + OptionSpec optionspec8 = optionparser.accepts("singleplayer").withRequiredArg(); +- OptionSpec optionspec9 = optionparser.accepts("universe").withRequiredArg().defaultsTo(".", new String[0]); ++ OptionSpec optionspec9 = optionparser.accepts("universe").withRequiredArg().defaultsTo(".", me.titaniumtown.Constants.EMPTY_string_arr); // JettPack + OptionSpec optionspec10 = optionparser.accepts("world").withRequiredArg(); + OptionSpec optionspec11 = optionparser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1, new Integer[0]); + OptionSpec optionspec12 = optionparser.accepts("serverId").withRequiredArg(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index da9623b90f3d25dc4c3e3aa269c4ccd2c8a0a52c..7ace6c1e81519b3e4f673d23627ca603fecb646d 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1354,8 +1354,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> list = Lists.newArrayList(); +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index e802ee2b2dc458f52dbce9746fc9891eebb6dcc1..f4280eb9f77568e4f3af6f264fc60901e667a936 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -909,7 +909,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + BlockPos blockposition2 = blockposition.set(j + randomX, randomY, k + randomZ); + BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); + +- iblockdata.randomTick(this, blockposition2, this.randomTickRandom); ++ iblockdata.randomTick(this, blockposition2.immutable(), this.randomTickRandom); // JettPack + // We drop the fluid tick since LAVA is ALREADY TICKED by the above method (See LiquidBlock). + // TODO CHECK ON UPDATE + } +@@ -1164,7 +1164,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + + public static List getCurrentlyTickingEntities() { + Entity ticking = currentlyTickingEntity.get(); +- List ret = java.util.Arrays.asList(ticking == null ? new Entity[0] : new Entity[] { ticking }); ++ List ret = java.util.Arrays.asList(ticking == null ? me.titaniumtown.Constants.EMPTY_entity_arr : new Entity[] { ticking }); // JettPack + + return ret; + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 4e615e5d5b8d79f6eaac2136be03961415fd093e..633fe61c98c1fc181f38b4195651c3ed6fc1db42 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -410,7 +410,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + if (this.keepAlivePending) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info +- this.disconnect(Component.translatable("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause ++ this.disconnect(Component.translatable("disconnect.timeout", me.titaniumtown.Constants.EMPTY_object_arr), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause // JettPack + } + } else { + if (elapsedTime >= 15000L) { // 15 seconds +@@ -876,13 +876,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // Paper - run this async + // CraftBukkit start + if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable +- server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause ++ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", me.titaniumtown.Constants.EMPTY_object_arr), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause // JettPack + return; + } + // Paper start + String str = packet.getCommand(); int index = -1; + if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { +- server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause ++ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", me.titaniumtown.Constants.EMPTY_object_arr), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause // JettPack + return; + } + // Paper end +@@ -3398,7 +3398,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + // Paper start + if (!org.bukkit.Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) { +- server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause ++ server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam", me.titaniumtown.Constants.EMPTY_object_arr), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause // JettPack + return; + } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index ea9b56fd6ae1d5577da5bd3e0c38abfeec8f3646..f1105edce8484cac39d8fb33a42c9ed8d44fe5c0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -269,8 +269,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se + + @Override + public void handleHello(ServerboundHelloPacket packet) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]); +- Validate.validState(ServerLoginPacketListenerImpl.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", me.titaniumtown.Constants.EMPTY_object_arr); // JettPack ++ Validate.validState(ServerLoginPacketListenerImpl.isValidUsername(packet.name()), "Invalid characters in username", me.titaniumtown.Constants.EMPTY_object_arr); // JettPack + // Paper start - validate usernames + if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation) { + if (!this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation && !validateUsername(packet.name())) { +@@ -330,7 +330,7 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se + + @Override + public void handleKey(ServerboundKeyPacket packet) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.KEY, "Unexpected key packet", new Object[0]); ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.State.KEY, "Unexpected key packet", me.titaniumtown.Constants.EMPTY_object_arr); // JettPack + + final String s; + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 06eda955f96b5fe2d08ed0d39229c7a6ebb88931..3fc95b7d7b41e078e1d219e29ada27aeab1320bf 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -741,7 +741,7 @@ public abstract class PlayerList { + while (iterator.hasNext()) { + entityplayer = (ServerPlayer) iterator.next(); + this.save(entityplayer); // CraftBukkit - Force the player's inventory to be saved +- entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login", me.titaniumtown.Constants.EMPTY_object_arr), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause // JettPack + } + + // Instead of kicking then returning, we need to store the kick reason +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 4fd709a550bf8da1e996894a1ca6b91206c31e9e..63c0fe30ff035b6b5c1b4b35d3ad6c649d94e421 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -95,7 +95,7 @@ public abstract class StoredUserList> { + } + + public String[] getUserList() { +- return (String[]) this.map.keySet().toArray(new String[0]); ++ return (String[]) this.map.keySet().toArray(me.titaniumtown.Constants.EMPTY_string_arr); // JettPack + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/util/MemoryReserve.java b/src/main/java/net/minecraft/util/MemoryReserve.java +index 0ee04fe6ff6a4d09754f326526ae04fe7226bab2..58217ddb1d63f3bb628cc40e5cc0959657a17938 100644 +--- a/src/main/java/net/minecraft/util/MemoryReserve.java ++++ b/src/main/java/net/minecraft/util/MemoryReserve.java +@@ -11,6 +11,6 @@ public class MemoryReserve { + } + + public static void release() { +- reserve = new byte[0]; ++ reserve = me.titaniumtown.Constants.EMPTY_byte_arr; // JettPack + } + } +diff --git a/src/main/java/net/minecraft/util/ZeroBitStorage.java b/src/main/java/net/minecraft/util/ZeroBitStorage.java +index 5d8e9bdf5538b19681f21949368d862fab8a89ad..97c744508cc535418eba65fa722859c81c22d647 100644 +--- a/src/main/java/net/minecraft/util/ZeroBitStorage.java ++++ b/src/main/java/net/minecraft/util/ZeroBitStorage.java +@@ -5,7 +5,7 @@ import java.util.function.IntConsumer; + import org.apache.commons.lang3.Validate; + + public class ZeroBitStorage implements BitStorage { +- public static final long[] RAW = new long[0]; ++ public static final long[] RAW = me.titaniumtown.Constants.EMPTY_long_arr; // JettPack + private final int size; + + public ZeroBitStorage(int size) { +diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +index c82bb38b5b1c9204daef21455723d21509ad1c44..4aa044ab8748c01b0022096733e5bacf7220510a 100644 +--- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java ++++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +@@ -12,6 +12,7 @@ public enum EquipmentSlot { + private final int index; + private final int filterFlag; + private final String name; ++ public static final EquipmentSlot[] VALUES = EquipmentSlot.values(); // JettPack + + private EquipmentSlot(EquipmentSlot.Type type, int entityId, int armorStandId, String name) { + this.type = type; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 26efc49b4530112c8bd3f580ce375ab4203c9609..c0e316582e085873c05a76c16e612eabd2e8cf2a 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3070,7 +3070,7 @@ public abstract class LivingEntity extends Entity { + @Nullable + private Map collectEquipmentChanges() { + Map map = null; +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index e89b88eb3d4202ea7ff043dc9e92163332cd10d3..78b1fc7b4cacfc98a9e3e6ba93e17c3307d5449c 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1027,7 +1027,7 @@ public abstract class Mob extends LivingEntity { + @Override + protected void dropCustomDeathLoot(DamageSource source, int lootingMultiplier, boolean allowDrops) { + super.dropCustomDeathLoot(source, lootingMultiplier, allowDrops); +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int j = aenumitemslot.length; + + for (int k = 0; k < j; ++k) { +@@ -1089,7 +1089,7 @@ public abstract class Mob extends LivingEntity { + } + + boolean flag = true; +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int j = aenumitemslot.length; + + for (int k = 0; k < j; ++k) { +@@ -1176,7 +1176,7 @@ public abstract class Mob extends LivingEntity { + float f = localDifficulty.getSpecialMultiplier(); + + this.enchantSpawnedWeapon(random, f); +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +@@ -1390,7 +1390,7 @@ public abstract class Mob extends LivingEntity { + t0.setInvulnerable(this.isInvulnerable()); + if (flag) { + t0.setCanPickUpLoot(this.canPickUpLoot()); +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +index fb0a77b4cf1ba47c73c00993bd9b7454240fe5d6..df1dfaea8b49794d9e3ecb792a129113829b60c9 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -233,7 +233,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { + return; + } + // CraftBukkit end +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index c18a0bc94d0210396046f4475e49a739088593f3..4fea1c9873b4dd9c9f21722adbb02200487caf3c 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -969,7 +969,7 @@ public final class ItemStack { + int k; + + if (ItemStack.shouldShowInTooltip(i, ItemStack.TooltipPart.MODIFIERS)) { +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.VALUES; // JettPack + + k = aenumitemslot.length; + +diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java +index 9e3f9099cc47e6c6e40d11ef6d6e83fbf19a3cf7..b9c1db394ee35ed1acead620f7e9e47c60fa1532 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java ++++ b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java +@@ -242,7 +242,7 @@ public class ShapedRecipe implements CraftingRecipe { + } + + if (pattern.length == l) { +- return new String[0]; ++ return me.titaniumtown.Constants.EMPTY_string_arr; // JettPack + } else { + String[] astring1 = new String[pattern.length - l - k]; + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantments.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantments.java +index 1367908a54e1c1703d14b3c25852da5ec1b02019..be33c4c28bbc0bf80cbf2921664fcc4aaa465950 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantments.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantments.java +@@ -43,8 +43,8 @@ public class Enchantments { + public static final Enchantment MULTISHOT = Enchantments.register("multishot", new MultiShotEnchantment(Enchantment.Rarity.RARE, new EquipmentSlot[]{EquipmentSlot.MAINHAND})); + public static final Enchantment QUICK_CHARGE = Enchantments.register("quick_charge", new QuickChargeEnchantment(Enchantment.Rarity.UNCOMMON, new EquipmentSlot[]{EquipmentSlot.MAINHAND})); + public static final Enchantment PIERCING = Enchantments.register("piercing", new ArrowPiercingEnchantment(Enchantment.Rarity.COMMON, new EquipmentSlot[]{EquipmentSlot.MAINHAND})); +- public static final Enchantment MENDING = Enchantments.register("mending", new MendingEnchantment(Enchantment.Rarity.RARE, EquipmentSlot.values())); +- public static final Enchantment VANISHING_CURSE = Enchantments.register("vanishing_curse", new VanishingCurseEnchantment(Enchantment.Rarity.VERY_RARE, EquipmentSlot.values())); ++ public static final Enchantment MENDING = Enchantments.register("mending", new MendingEnchantment(Enchantment.Rarity.RARE, EquipmentSlot.VALUES)); // JettPack ++ public static final Enchantment VANISHING_CURSE = Enchantments.register("vanishing_curse", new VanishingCurseEnchantment(Enchantment.Rarity.VERY_RARE, EquipmentSlot.VALUES)); // JettPack + + // CraftBukkit start + static { +diff --git a/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java b/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java +index 2f9f15d99f8b31e9f13f7f32378b2a9e09bcb5e5..b9579e3d1610ddcb5251baa2dd9462e0557c4cf4 100644 +--- a/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java ++++ b/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java +@@ -15,9 +15,17 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula + + @Override + public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState) { +- return super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState).map((max) -> { +- return this.source.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState, max); +- }); ++ // JettPack start - lithium: reduce allocs ++ Optional optionalBlastResistance = super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState); ++ if (optionalBlastResistance.isPresent()) { ++ float blastResistance = optionalBlastResistance.get(); ++ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState, blastResistance); ++ if (effectiveExplosionResistance != blastResistance) { ++ return Optional.of(effectiveExplosionResistance); ++ } ++ } ++ return optionalBlastResistance; ++ // JettPack end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0277633fd328ef9993fea4ac29df83b5b00c0f42..0948242ecebe507c90af343faeffc7c9388fa7e4 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1521,7 +1521,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public org.bukkit.entity.Entity[] getChunkEntities(int chunkX, int chunkZ) { + io.papermc.paper.world.ChunkEntitySlices slices = ((ServerLevel)this).getEntityLookup().getChunk(chunkX, chunkZ); + if (slices == null) { +- return new org.bukkit.entity.Entity[0]; ++ return me.titaniumtown.Constants.EMPTY_bukkit_entity_arr; // JettPack + } + return slices.getChunkEntities(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java +index 492e3ffd6a4588a521486db631f3e8b2a25b74ec..111635d43ac0b93e089f5a115521a502ca463c39 100644 +--- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java +@@ -383,7 +383,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { + + @Override + public int[] getSlotsForFace(Direction side) { +- return side == Direction.DOWN ? new int[]{0} : new int[0]; ++ return side == Direction.DOWN ? me.titaniumtown.Constants.ZERO_int_arr : me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + @Override +@@ -432,7 +432,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { + + @Override + public int[] getSlotsForFace(Direction side) { +- return side == Direction.UP ? new int[]{0} : new int[0]; ++ return side == Direction.UP ? me.titaniumtown.Constants.ZERO_int_arr : me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + @Override +@@ -469,7 +469,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { + + @Override + public int[] getSlotsForFace(Direction side) { +- return new int[0]; ++ return me.titaniumtown.Constants.EMPTY_int_arr; // JettPack + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index c6aeda6497cb59673b469588142f5f15a338389d..ebf718cea97d4ff88e888675eeceeca253dc01cb 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -64,7 +64,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + protected static final int SLOT_FUEL = 1; + protected static final int SLOT_RESULT = 2; + public static final int DATA_LIT_TIME = 0; +- private static final int[] SLOTS_FOR_UP = new int[]{0}; ++ private static final int[] SLOTS_FOR_UP = me.titaniumtown.Constants.ZERO_int_arr; // JettPack + private static final int[] SLOTS_FOR_DOWN = new int[]{2, 1}; + private static final int[] SLOTS_FOR_SIDES = new int[]{1}; + public static final int DATA_LIT_DURATION = 1; +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 601f8099f74e81c17600566b3c9b7a6dd39c9bcb..f816fae46568b83ef4441bd3bb06f2081308921e 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -119,7 +119,7 @@ public class PlayerDataStorage { + String[] astring = this.playerDir.list(); + + if (astring == null) { +- astring = new String[0]; ++ astring = me.titaniumtown.Constants.EMPTY_string_arr; // JettPack + } + + for (int i = 0; i < astring.length; ++i) { +diff --git a/src/main/java/net/minecraft/world/scores/Team.java b/src/main/java/net/minecraft/world/scores/Team.java +index 16d2aa4556bc9f32a2def7f9ca282aa3fa23fb87..290a0d35e1e4ca8b7281aa6d8cdb66dabdadf0f7 100644 +--- a/src/main/java/net/minecraft/world/scores/Team.java ++++ b/src/main/java/net/minecraft/world/scores/Team.java +@@ -80,7 +80,7 @@ public abstract class Team { + public final int id; + + public static String[] getAllNames() { +- return BY_NAME.keySet().toArray(new String[0]); ++ return BY_NAME.keySet().toArray(me.titaniumtown.Constants.EMPTY_string_arr); // JettPack + } + + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftEquipmentSlot.java b/src/main/java/org/bukkit/craftbukkit/CraftEquipmentSlot.java +index 402a238cf502003a232bb95473bd13e59e067fab..6ab50d7ed8481d14152f19a4b63a3d96e52a40a7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftEquipmentSlot.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftEquipmentSlot.java +@@ -5,8 +5,8 @@ import org.bukkit.inventory.EquipmentSlot; + + public class CraftEquipmentSlot { + +- private static final net.minecraft.world.entity.EquipmentSlot[] slots = new net.minecraft.world.entity.EquipmentSlot[EquipmentSlot.values().length]; +- private static final EquipmentSlot[] enums = new EquipmentSlot[net.minecraft.world.entity.EquipmentSlot.values().length]; ++ private static final net.minecraft.world.entity.EquipmentSlot[] slots = net.minecraft.world.entity.EquipmentSlot.VALUES; // JettPack ++ private static final EquipmentSlot[] enums = new EquipmentSlot[net.minecraft.world.entity.EquipmentSlot.VALUES.length]; // JettPack + + static { + set(EquipmentSlot.HAND, net.minecraft.world.entity.EquipmentSlot.MAINHAND); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +index 6827979a5b270ced53b46ecb9eff548727dadb81..4b42ae96bc786d2a9d57086ae8d1f5cadc70f2bb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +@@ -165,7 +165,7 @@ public class CraftEntityEquipment implements EntityEquipment { + + @Override + public void clear() { +- for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.values()) { ++ for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.VALUES) { // JettPack + this.setEquipment(slot, null, false); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java +index 049d750d3af991dd14ac8cf644330404e74b2151..2f69484a8970f78c11f8fbb187e7a9f8f0fb994d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java +@@ -166,7 +166,7 @@ public final class WeakCollection implements Collection { + + @Override + public Object[] toArray() { +- return this.toArray(new Object[0]); ++ return this.toArray(me.titaniumtown.Constants.EMPTY_object_arr); // JettPack + } + + @Override diff --git a/DivineMC/patches/server/0005-lithium-fast-util.patch b/DivineMC/patches/server/0005-lithium-fast-util.patch new file mode 100644 index 0000000..6cdcdbe --- /dev/null +++ b/DivineMC/patches/server/0005-lithium-fast-util.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Tue, 14 Dec 2021 12:04:01 -0500 +Subject: [PATCH] lithium: fast util + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index a3bbebcdaea9e0dfddd9825272f84fc76cd13e89..ee725b972d3d5fb22538aaff9c72e47c6bad0cea 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -196,7 +196,7 @@ public enum Direction implements StringRepresentable { + } + + public Direction getOpposite() { +- return from3DDataValue(this.oppositeIndex); ++ return VALUES[this.oppositeIndex]; // JettPack - lithium: fast util + } + + public Direction getClockWise(Direction.Axis axis) { +@@ -446,7 +446,7 @@ public enum Direction implements StringRepresentable { + } + + public static Direction getRandom(RandomSource random) { +- return Util.getRandom(VALUES, random); ++ return VALUES[random.nextInt(VALUES.length)]; // JettPack - lithium: fast util + } + + public static Direction getNearest(double x, double y, double z) { +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index 68cc6f2a78a06293a29317fda72ab3ee79b3533a..c5ff387a78693b0d5b18653dae67eb4a03324ff7 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -16,6 +16,15 @@ public class AABB { + public final double maxY; + public final double maxZ; + ++ // JettPack start - lithium: fast_util ++ static { ++ assert Direction.Axis.X.ordinal() == 0; ++ assert Direction.Axis.Y.ordinal() == 1; ++ assert Direction.Axis.Z.ordinal() == 2; ++ assert Direction.Axis.values().length == 3; ++ } ++ // JettPack end ++ + public AABB(double x1, double y1, double z1, double x2, double y2, double z2) { + this.minX = Math.min(x1, x2); + this.minY = Math.min(y1, y2); +@@ -81,11 +90,33 @@ public class AABB { + } + + public double min(Direction.Axis axis) { +- return axis.choose(this.minX, this.minY, this.minZ); ++ // JettPack start - lithium: fast_util ++ switch (axis.ordinal()) { ++ case 0: //X ++ return this.minX; ++ case 1: //Y ++ return this.minY; ++ case 2: //Z ++ return this.minZ; ++ } ++ ++ throw new IllegalArgumentException(); ++ // JettPack end + } + + public double max(Direction.Axis axis) { +- return axis.choose(this.maxX, this.maxY, this.maxZ); ++ // JettPack start - lithium: fast_util ++ switch (axis.ordinal()) { ++ case 0: //X ++ return this.maxX; ++ case 1: //Y ++ return this.maxY; ++ case 2: //Z ++ return this.maxZ; ++ } ++ ++ throw new IllegalArgumentException(); ++ // JettPack end + } + + @Override diff --git a/DivineMC/patches/server/0006-lithium-HashedReferenceList.patch b/DivineMC/patches/server/0006-lithium-HashedReferenceList.patch new file mode 100644 index 0000000..ec716d6 --- /dev/null +++ b/DivineMC/patches/server/0006-lithium-HashedReferenceList.patch @@ -0,0 +1,312 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 31 Jul 2020 21:46:32 -0500 +Subject: [PATCH] lithium: HashedReferenceList + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedReferenceList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedReferenceList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4128567173d3985257a1bdd4412c7db0ff81535d +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedReferenceList.java +@@ -0,0 +1,281 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ReferenceArrayList; ++import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.*; ++ ++/** ++ * Wraps a {@link List} with a hash table which provides O(1) lookups for {@link Collection#contains(Object)}. The type ++ * contained by this list must use reference-equality semantics. ++ */ ++@SuppressWarnings("SuspiciousMethodCalls") ++public class HashedReferenceList implements List { ++ private final ReferenceArrayList list; ++ private final Reference2IntOpenHashMap counter; ++ ++ public HashedReferenceList(List list) { ++ this.list = new ReferenceArrayList<>(); ++ this.list.addAll(list); ++ ++ this.counter = new Reference2IntOpenHashMap<>(); ++ this.counter.defaultReturnValue(0); ++ ++ for (T obj : this.list) { ++ this.counter.addTo(obj, 1); ++ } ++ } ++ ++ @Override ++ public int size() { ++ return this.list.size(); ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.list.isEmpty(); ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return this.counter.containsKey(o); ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.listIterator(); ++ } ++ ++ @Override ++ public Object[] toArray() { ++ return this.list.toArray(); ++ } ++ ++ @SuppressWarnings("SuspiciousToArrayCall") ++ @Override ++ public T1[] toArray(T1 @NotNull [] a) { ++ return this.list.toArray(a); ++ } ++ ++ @Override ++ public boolean add(T t) { ++ this.trackReferenceAdded(t); ++ ++ return this.list.add(t); ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ this.trackReferenceRemoved(o); ++ ++ return this.list.remove(o); ++ } ++ ++ @Override ++ public boolean containsAll(Collection c) { ++ for (Object obj : c) { ++ if (!this.counter.containsKey(obj)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(c); ++ } ++ ++ @Override ++ public boolean addAll(int index, Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(index, c); ++ } ++ ++ @Override ++ public boolean removeAll(@NotNull Collection c) { ++ if (this.size() >= 2 && c.size() > 4 && c instanceof List) { ++ //HashReferenceList uses reference equality, so using ReferenceOpenHashSet is fine ++ c = new ReferenceOpenHashSet<>(c); ++ } ++ this.counter.keySet().removeAll(c); ++ return this.list.removeAll(c); ++ } ++ ++ @Override ++ public boolean retainAll(@NotNull Collection c) { ++ this.counter.keySet().retainAll(c); ++ return this.list.retainAll(c); ++ } ++ ++ @Override ++ public void clear() { ++ this.counter.clear(); ++ this.list.clear(); ++ } ++ ++ @Override ++ public T get(int index) { ++ return this.list.get(index); ++ } ++ ++ @Override ++ public T set(int index, T element) { ++ T prev = this.list.set(index, element); ++ ++ if (prev != element) { ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ this.trackReferenceAdded(element); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public void add(int index, T element) { ++ this.trackReferenceAdded(element); ++ ++ this.list.add(index, element); ++ } ++ ++ @Override ++ public T remove(int index) { ++ T prev = this.list.remove(index); ++ ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public int indexOf(Object o) { ++ return this.list.indexOf(o); ++ } ++ ++ @Override ++ public int lastIndexOf(Object o) { ++ return this.list.lastIndexOf(o); ++ } ++ ++ @Override ++ public ListIterator listIterator() { ++ return this.listIterator(0); ++ } ++ ++ @Override ++ public ListIterator listIterator(int index) { ++ return new ListIterator<>() { ++ private final ListIterator inner = HashedReferenceList.this.list.listIterator(index); ++ ++ @Override ++ public boolean hasNext() { ++ return this.inner.hasNext(); ++ } ++ ++ @Override ++ public T next() { ++ return this.inner.next(); ++ } ++ ++ @Override ++ public boolean hasPrevious() { ++ return this.inner.hasPrevious(); ++ } ++ ++ @Override ++ public T previous() { ++ return this.inner.previous(); ++ } ++ ++ @Override ++ public int nextIndex() { ++ return this.inner.nextIndex(); ++ } ++ ++ @Override ++ public int previousIndex() { ++ return this.inner.previousIndex(); ++ } ++ ++ @Override ++ public void remove() { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedReferenceList.this.get(last); ++ ++ if (prev != null) { ++ HashedReferenceList.this.trackReferenceRemoved(prev); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void set(T t) { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedReferenceList.this.get(last); ++ ++ if (prev != t) { ++ if (prev != null) { ++ HashedReferenceList.this.trackReferenceRemoved(prev); ++ } ++ ++ HashedReferenceList.this.trackReferenceAdded(t); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void add(T t) { ++ HashedReferenceList.this.trackReferenceAdded(t); ++ ++ this.inner.add(t); ++ } ++ }; ++ } ++ ++ @Override ++ public List subList(int fromIndex, int toIndex) { ++ return this.list.subList(fromIndex, toIndex); ++ } ++ ++ private void trackReferenceAdded(T t) { ++ this.counter.addTo(t, 1); ++ } ++ ++ @SuppressWarnings("unchecked") ++ private void trackReferenceRemoved(Object o) { ++ if (this.counter.addTo((T) o, -1) <= 1) { ++ this.counter.removeInt(o); ++ } ++ } ++ ++ public static HashedReferenceList wrapper(List list) { ++ return new HashedReferenceList<>(list); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index a4e29b171a4f47bafdc9ff278ca00a071b4269c0..c81520efe726efa7d6ac61c37f8eadc3cda5bc97 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -117,9 +117,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper ++ protected final List blockEntityTickers = me.jellysquid.mods.lithium.common.util.collections.HashedReferenceList.wrapper(Lists.newArrayList()); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper // Jettpack - lithium: HashedReferenceList + protected final NeighborUpdater neighborUpdater; +- private final List pendingBlockEntityTickers = Lists.newArrayList(); ++ private final List pendingBlockEntityTickers = me.jellysquid.mods.lithium.common.util.collections.HashedReferenceList.wrapper(Lists.newArrayList()); // Jettpack - lithium: HashedReferenceList + private boolean tickingBlockEntities; + public final Thread thread; + private final boolean isDebug; diff --git a/DivineMC/patches/server/0007-lithium-CompactSineLUT.patch b/DivineMC/patches/server/0007-lithium-CompactSineLUT.patch new file mode 100644 index 0000000..00ad946 --- /dev/null +++ b/DivineMC/patches/server/0007-lithium-CompactSineLUT.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 5 Feb 2021 00:16:30 -0600 +Subject: [PATCH] lithium: CompactSineLUT + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java b/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b8c9cb28876c2c1781cd72870076d528b9647916 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java +@@ -0,0 +1,90 @@ ++package me.jellysquid.mods.lithium.common.util.math; ++ ++import net.minecraft.util.Mth; ++ ++/** ++ * A replacement for the sine angle lookup table used in {@link Mth}, both reducing the size of LUT and improving ++ * the access patterns for common paired sin/cos operations. ++ * ++ * sin(-x) = -sin(x) ++ * ... to eliminate negative angles from the LUT. ++ * ++ * sin(x) = sin(pi/2 - x) ++ * ... to eliminate supplementary angles from the LUT. ++ * ++ * Using these identities allows us to reduce the LUT from 64K entries (256 KB) to just 16K entries (64 KB), enabling ++ * it to better fit into the CPU's caches at the expense of some cycles on the fast path. The implementation has been ++ * tightly optimized to avoid branching where possible and to use very quick integer operations. ++ * ++ * Generally speaking, reducing the size of a lookup table is always a good optimization, but since we need to spend ++ * extra CPU cycles trying to maintain parity with vanilla, there is the potential risk that this implementation ends ++ * up being slower than vanilla when the lookup table is able to be kept in cache memory. ++ * ++ * Unlike other "fast math" implementations, the values returned by this class are *bit-for-bit identical* with those ++ * from {@link Mth}. Validation is performed during runtime to ensure that the table is correct. ++ * ++ * @author coderbot16 Author of the original (and very clever) implementation in Rust: ++ * https://gitlab.com/coderbot16/i73/-/tree/master/i73-trig/src ++ * @author jellysquid3 Additional optimizations, port to Java ++ */ ++public class CompactSineLUT { ++ private static final int[] SINE_TABLE_INT = new int[16384 + 1]; ++ private static final float SINE_TABLE_MIDPOINT; ++ ++ static { ++ final float[] SINE_TABLE = Mth.getSinTable(); ++ // Copy the sine table, covering to raw int bits ++ for (int i = 0; i < SINE_TABLE_INT.length; i++) { ++ SINE_TABLE_INT[i] = Float.floatToRawIntBits(SINE_TABLE[i]); ++ } ++ ++ SINE_TABLE_MIDPOINT = SINE_TABLE[SINE_TABLE.length / 2]; ++ ++ // Test that the lookup table is correct during runtime ++ for (int i = 0; i < SINE_TABLE.length; i++) { ++ float expected = SINE_TABLE[i]; ++ float value = lookup(i); ++ ++ if (expected != value) { ++ throw new IllegalArgumentException(String.format("LUT error at index %d (expected: %s, found: %s)", i, expected, value)); ++ } ++ } ++ } ++ ++ // [VanillaCopy] MathHelper#sin(float) ++ public static float sin(float f) { ++ return lookup((int) (f * 10430.378f) & 0xFFFF); ++ } ++ ++ // [VanillaCopy] MathHelper#cos(float) ++ public static float cos(float f) { ++ return lookup((int) (f * 10430.378f + 16384.0f) & 0xFFFF); ++ } ++ ++ private static float lookup(int index) { ++ // A special case... Is there some way to eliminate this? ++ if (index == 32768) { ++ return SINE_TABLE_MIDPOINT; ++ } ++ ++ // Trigonometric identity: sin(-x) = -sin(x) ++ // Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi. ++ // This allows the sin table size to be halved. ++ int neg = (index & 0x8000) << 16; ++ ++ // All bits set if (pi/2 <= x), none set otherwise ++ // Extracts the 15th bit from 'half' ++ int mask = (index << 17) >> 31; ++ ++ // Trigonometric identity: sin(x) = sin(pi/2 - x) ++ int pos = (0x8001 & mask) + (index ^ mask); ++ ++ // Wrap the position in the table. Moving this down to immediately before the array access ++ // seems to help the Hotspot compiler optimize the bit math better. ++ pos &= 0x7fff; ++ ++ // Fetch the corresponding value from the LUT and invert the sign bit as needed ++ // This directly manipulate the sign bit on the float bits to simplify logic ++ return Float.intBitsToFloat(SINE_TABLE_INT[pos] ^ neg); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index 9b22034aa655ceb0da151d9d8ca3147f6487889a..ec587cf6592a1dc0d90d6f54af1bdfab97aec7c6 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -32,6 +32,7 @@ public class Mth { + + }); + private static final RandomSource RANDOM = RandomSource.createThreadSafe(); ++ public static float[] getSinTable() { return SIN; } // DivineMC - lithium: CompactSineLUT + private static final int[] MULTIPLY_DE_BRUIJN_BIT_POSITION = new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; + private static final double ONE_SIXTH = 0.16666666666666666D; + private static final int FRAC_EXP = 8; +@@ -41,11 +42,11 @@ public class Mth { + private static final double[] COS_TAB = new double[257]; + + public static float sin(float value) { +- return SIN[(int)(value * 10430.378F) & '\uffff']; ++ return me.jellysquid.mods.lithium.common.util.math.CompactSineLUT.sin(value); // DivineMC - lithium: CompactSineLUT + } + + public static float cos(float value) { +- return SIN[(int)(value * 10430.378F + 16384.0F) & '\uffff']; ++ return me.jellysquid.mods.lithium.common.util.math.CompactSineLUT.cos(value); // DivineMC - lithium: CompactSineLUT + } + + public static float sqrt(float value) { diff --git a/DivineMC/patches/server/0008-lithium-fast-retrieval.patch b/DivineMC/patches/server/0008-lithium-fast-retrieval.patch new file mode 100644 index 0000000..4760e9d --- /dev/null +++ b/DivineMC/patches/server/0008-lithium-fast-retrieval.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Wed, 15 Dec 2021 11:20:48 -0500 +Subject: [PATCH] lithium: fast retrieval + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +index f54ca6383298848b2ee7108c41fcea593f924881..ad12d9660cd57d147859a0e3e123c5b87c8e9748 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +@@ -33,7 +33,7 @@ public class EntitySectionStorage { + } + + public void forEachAccessibleNonEmptySection(AABB box, Consumer> action) { +- int i = 2; ++ // DivineMC start - lithium: fast retrieval + int j = SectionPos.posToSectionCoord(box.minX - 2.0D); + int k = SectionPos.posToSectionCoord(box.minY - 4.0D); + int l = SectionPos.posToSectionCoord(box.minZ - 2.0D); +@@ -41,25 +41,67 @@ public class EntitySectionStorage { + int n = SectionPos.posToSectionCoord(box.maxY + 0.0D); + int o = SectionPos.posToSectionCoord(box.maxZ + 2.0D); + +- for(int p = j; p <= m; ++p) { +- long q = SectionPos.asLong(p, 0, 0); +- long r = SectionPos.asLong(p, -1, -1); +- LongIterator longIterator = this.sectionIds.subSet(q, r + 1L).iterator(); +- +- while(longIterator.hasNext()) { +- long s = longIterator.nextLong(); +- int t = SectionPos.y(s); +- int u = SectionPos.z(s); +- if (t >= k && t <= n && u >= l && u <= o) { +- EntitySection entitySection = this.sections.get(s); +- if (entitySection != null && !entitySection.isEmpty() && entitySection.getStatus().isAccessible()) { +- action.accept(entitySection); ++ if (m >= j + 4 || o >= l + 4) { ++ // Vanilla is likely more optimized when shooting entities with TNT cannons over huge distances. ++ // Choosing a cutoff of 4 chunk size, as it becomes more likely that these entity sections do not exist when ++ // they are far away from the shot entity (player despawn range, position maybe not on the ground, etc) ++ for (int p = j; p <= m; p++) { ++ long q = SectionPos.asLong(p, 0, 0); ++ long r = SectionPos.asLong(p, -1, -1); ++ LongIterator longIterator = this.sectionIds.subSet(q, r + 1L).iterator(); ++ ++ while (longIterator.hasNext()) { ++ long s = longIterator.nextLong(); ++ int t = SectionPos.y(s); ++ int u = SectionPos.z(s); ++ if (t >= k && t <= n && u >= l && u <= o) { ++ EntitySection entitySection = this.sections.get(s); ++ if (entitySection != null && !entitySection.isEmpty() && entitySection.getStatus().isAccessible()) { ++ action.accept(entitySection); ++ } + } + } + } ++ } else { ++ // Vanilla order of the AVL long set is sorting by ascending long value. The x, y, z positions are packed into ++ // a long with the x position's lowest 22 bits placed at the MSB. ++ // Therefore the long is negative iff the 22th bit of the x position is set, which happens iff the x position ++ // is negative. A positive x position will never have its 22th bit set, as these big coordinates are far outside ++ // the world. y and z positions are treated as unsigned when sorting by ascending long value, as their sign bits ++ // are placed somewhere inside the packed long ++ for (int x = j; x <= m; x++) { ++ for (int z = Math.max(l, 0); z <= o; z++) { ++ this.forEachInColumn(x, k, n, z, action); ++ } ++ ++ int bound = Math.min(-1, o); ++ for (int z = l; z <= bound; z++) { ++ this.forEachInColumn(x, k, n, z, action); ++ } ++ } + } ++ // DivineMC end ++ } + ++ // DivineMC start - lithium: fast retrieval ++ private void forEachInColumn(int x, int k, int n, int z, Consumer> action) { ++ //y from negative to positive, but y is treated as unsigned ++ for (int y = Math.max(k, 0); y <= n; y++) { ++ this.consumeSection(SectionPos.asLong(x, y, z), action); ++ } ++ int bound = Math.min(-1, n); ++ for (int y = k; y <= bound; y++) { ++ this.consumeSection(SectionPos.asLong(x, y, z), action); ++ } ++ } ++ ++ private void consumeSection(long pos, Consumer> action) { ++ EntitySection entitySection = this.getSection(pos); ++ if (entitySection != null && 0 != entitySection.size() && entitySection.getStatus().isAccessible()) { ++ action.accept(entitySection); ++ } + } ++ // DivineMC end + + public LongStream getExistingSectionPositionsInChunk(long chunkPos) { + int i = ChunkPos.getX(chunkPos); diff --git a/DivineMC/patches/server/0009-Add-last-tick-time-API.patch b/DivineMC/patches/server/0009-Add-last-tick-time-API.patch new file mode 100644 index 0000000..f8793f9 --- /dev/null +++ b/DivineMC/patches/server/0009-Add-last-tick-time-API.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Sun, 27 Sep 2020 18:30:10 +0300 +Subject: [PATCH] Add last tick time API + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 7ace6c1e81519b3e4f673d23627ca603fecb646d..3378298b0c465c0df9618804c390930e875bcce3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1095,6 +1095,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { + sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); + if (!hasShownMemoryWarning) { +@@ -50,4 +54,15 @@ public class TicksPerSecondCommand extends Command + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() + + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } ++ ++ // Yatopia start - Last tick time API ++ public static String formatTo(java.time.Duration duration, java.util.concurrent.TimeUnit unit) { ++ java.util.concurrent.TimeUnit nanosUnit = java.util.concurrent.TimeUnit.NANOSECONDS; ++ long nanos = duration.toNanos(); ++ long toAskedUnit = unit.convert( nanos, nanosUnit ); ++ long ms = nanosUnit.toMillis( nanos ); ++ ChatColor startingColor = ms < 40 ? ChatColor.GREEN : ( ms < 50 ) ? ChatColor.YELLOW : ChatColor.RED; ++ return startingColor.toString() + toAskedUnit + ChatColor.GOLD + org.yatopiamc.yatopia.server.util.TimeUtils.getFriendlyName( unit ); ++ } ++ // Yatopia end + } diff --git a/DivineMC/patches/server/0010-lithium-shapes.blockstate_cache.patch b/DivineMC/patches/server/0010-lithium-shapes.blockstate_cache.patch new file mode 100644 index 0000000..9f8cf6d --- /dev/null +++ b/DivineMC/patches/server/0010-lithium-shapes.blockstate_cache.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gegy +Date: Fri, 21 Jan 2022 10:19:06 -0500 +Subject: [PATCH] lithium: shapes.blockstate_cache + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a833ec84b2053c805dd33821cc08939c1cb79e96 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java +@@ -0,0 +1,59 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import it.unimi.dsi.fastutil.HashCommon; ++import java.util.function.Predicate; ++import net.minecraft.util.Mth; ++ ++/** ++ * A lossy hashtable implementation that stores a mapping between an object and a boolean. ++ *

++ * Any hash collisions will result in an overwrite: this is safe because the correct value can always be recomputed, ++ * given that the given operator is deterministic. ++ *

++ * This implementation is safe to use from multiple threads ++ */ ++public final class Object2BooleanCacheTable { ++ private final int mask; ++ ++ private final Node[] nodes; ++ ++ private final Predicate operator; ++ ++ @SuppressWarnings("unchecked") ++ public Object2BooleanCacheTable(int capacity, Predicate operator) { ++ int capacity1 = Mth.smallestEncompassingPowerOfTwo(capacity); ++ this.mask = capacity1 - 1; ++ ++ this.nodes = (Node[]) new Node[capacity1]; ++ ++ this.operator = operator; ++ } ++ ++ private static int hash(T key) { ++ return HashCommon.mix(key.hashCode()); ++ } ++ ++ public boolean get(T key) { ++ int idx = hash(key) & this.mask; ++ ++ Node node = this.nodes[idx]; ++ if (node != null && key.equals(node.key)) { ++ return node.value; ++ } ++ ++ boolean test = this.operator.test(key); ++ this.nodes[idx] = new Node<>(key, test); ++ ++ return test; ++ } ++ ++ static class Node { ++ final T key; ++ final boolean value; ++ ++ Node(T key, boolean value) { ++ this.key = key; ++ this.value = value; ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index dfe1e522a747b894d43124b97eaceb0ab196ac44..1834470b549d8352317cf081173ff542c9faac1e 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -64,17 +64,19 @@ import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; ++import me.jellysquid.mods.lithium.common.util.collections.Object2BooleanCacheTable; // JettPack + + public class Block extends BlockBehaviour implements ItemLike { + + private static final Logger LOGGER = LogUtils.getLogger(); + private final Holder.Reference builtInRegistryHolder; + public static final IdMapper BLOCK_STATE_REGISTRY = new IdMapper<>(); +- private static final LoadingCache SHAPE_FULL_BLOCK_CACHE = CacheBuilder.newBuilder().maximumSize(512L).weakKeys().build(new CacheLoader() { +- public Boolean load(VoxelShape voxelshape) { +- return !Shapes.joinIsNotEmpty(Shapes.block(), voxelshape, BooleanOp.NOT_SAME); +- } +- }); ++ // JettPack start - lithium: shapes.blockstate_cache ++ private static final Object2BooleanCacheTable FULL_CUBE_CACHE = new Object2BooleanCacheTable<>( ++ 512, ++ shape -> !Shapes.joinIsNotEmpty(Shapes.block(), shape, BooleanOp.NOT_SAME) ++ ); ++ // JettPack end + public static final int UPDATE_NEIGHBORS = 1; + public static final int UPDATE_CLIENTS = 2; + public static final int UPDATE_INVISIBLE = 4; +@@ -281,7 +283,7 @@ public class Block extends BlockBehaviour implements ItemLike { + } + + public static boolean isShapeFullBlock(VoxelShape shape) { +- return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape); ++ return FULL_CUBE_CACHE.get(shape); // JettPack - lithium: shapes.blockstate_cache + } + + public boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) { diff --git a/DivineMC/patches/server/0011-lithium-ai.raid.patch b/DivineMC/patches/server/0011-lithium-ai.raid.patch new file mode 100644 index 0000000..fb88c6e --- /dev/null +++ b/DivineMC/patches/server/0011-lithium-ai.raid.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jellysquid3 +Date: Tue, 18 Jan 2022 10:37:18 -0500 +Subject: [PATCH] lithium: ai.raid + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java +index 6a0a1731fd6804eb69d3641213712d31bce085b2..5f4bb589474ce7d4f214e32ab0bc4b9cb71638d0 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raid.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java +@@ -269,7 +269,16 @@ public class Raid { + this.status = Raid.RaidStatus.STOPPED; + } + ++ private boolean isBarDirty; // JettPack + public void tick() { ++ // JettPack start - lithium: ai.raid ++ if (this.isBarDirty) { ++ this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F)); ++ ++ this.isBarDirty = false; ++ } ++ // JettPack end ++ + if (!this.isStopped()) { + if (this.status == Raid.RaidStatus.ONGOING) { + boolean flag = this.active; +@@ -626,7 +635,7 @@ public class Raid { + } + + public void updateBossbar() { +- this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F)); ++ this.isBarDirty = true; // JettPack - lithium: ai.raid + } + + public float getHealthOfLivingRaiders() { +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java +index 8877423a99e387c18d1d994518bf15d8d9ba64af..a65e82c8e2975244d725ff2f4931df183f25b63f 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java +@@ -46,8 +46,9 @@ import net.minecraft.world.phys.Vec3; + public abstract class Raider extends PatrollingMonster { + + protected static final EntityDataAccessor IS_CELEBRATING = SynchedEntityData.defineId(Raider.class, EntityDataSerializers.BOOLEAN); ++ public static final ItemStack CACHED_OMINOUS_BANNER = Raid.getLeaderBannerInstance(); // JettPack - lithium: ai.raid + static final Predicate ALLOWED_ITEMS = (entityitem) -> { +- return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), Raid.getLeaderBannerInstance()); ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), CACHED_OMINOUS_BANNER); // JettPack - lithium: ai.raid + }; + @Nullable + protected Raid raid; +@@ -149,7 +150,7 @@ public abstract class Raider extends PatrollingMonster { + } + } + +- if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance()) && entityhuman != null) { ++ if (!itemstack.isEmpty() && ItemStack.matches(itemstack, CACHED_OMINOUS_BANNER) && entityhuman != null) { // JettPack - lithium: ai.raid + MobEffectInstance mobeffect = entityhuman.getEffect(MobEffects.BAD_OMEN); + byte b0 = 1; + int i; +@@ -309,6 +310,7 @@ public abstract class Raider extends PatrollingMonster { + public class ObtainRaidLeaderBannerGoal extends Goal { + + private final T mob; ++ private static final ItemStack CACHED_OMINOUS_BANNER = Raid.getLeaderBannerInstance(); // JettPack + + public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error + this.mob = entityraider; +@@ -320,7 +322,7 @@ public abstract class Raider extends PatrollingMonster { + if (!this.mob.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items + Raid raid = this.mob.getCurrentRaid(); + +- if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { ++ if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), CACHED_OMINOUS_BANNER)) { // JettPack - lithium: ai.raid + Raider entityraider = raid.getLeader(this.mob.getWave()); + + if (entityraider == null || !entityraider.isAlive()) { diff --git a/DivineMC/patches/server/0012-Stop-wasting-resources-on-JsonList-get.patch b/DivineMC/patches/server/0012-Stop-wasting-resources-on-JsonList-get.patch new file mode 100644 index 0000000..6d96bd1 --- /dev/null +++ b/DivineMC/patches/server/0012-Stop-wasting-resources-on-JsonList-get.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Fri, 4 Sep 2020 10:07:42 +0300 +Subject: [PATCH] Stop wasting resources on JsonList#get + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 3fc95b7d7b41e078e1d219e29ada27aeab1320bf..faaf13f46bc7bf0ffc1fe61f45e9f11cb9c8b4d5 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -758,13 +758,19 @@ public abstract class PlayerList { + if (getBans().isBanned(gameprofile) && (gameprofilebanentry = getBans().get(gameprofile)) != null) { + // Paper end + +- ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); +- if (gameprofilebanentry.getExpires() != null) { +- ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); +- } ++ // Yatopia start - Stop wasting resources on JsonList#get ++ if (!gameprofilebanentry.hasExpired()) { ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); ++ if (gameprofilebanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); ++ } + +- // return chatmessage; +- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure ++ } else { ++ getBans().remove(gameprofile); ++ } ++ // Yatopia end + } else if (!this.isWhiteListed(gameprofile, event)) { // Paper + //ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - moved to isWhitelisted +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 63c0fe30ff035b6b5c1b4b35d3ad6c649d94e421..109e08e098a6c1ca1ba3dc2a9a293eaf9d5d7cb7 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -73,9 +73,12 @@ public abstract class StoredUserList> { + // Paper start + // this.g(); + // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error +- return (V) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> { ++ // Yatopia start - Stop wasting resources on JsonList#get ++ return this.map.get(this.getKeyForUser(key)); ++ /*return (V) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> { + return v.hasExpired() ? null : v; +- }); ++ });*/ ++ // Yatopia end + // Paper end + } + +@@ -150,7 +153,8 @@ public abstract class StoredUserList> { + public void save() throws IOException { + this.removeExpired(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); +- Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error ++ // Yatopia start - Stop wasting resources on JsonList#get ++ /*Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); + + Objects.requireNonNull(jsonlistentry); +@@ -158,7 +162,13 @@ public abstract class StoredUserList> { + }); + + Objects.requireNonNull(jsonarray); +- stream.forEach(jsonarray::add); ++ stream.forEach(jsonarray::add);*/ ++ for (V value : this.map.values()) { ++ JsonObject obj = new JsonObject(); ++ value.serialize(obj); ++ jsonarray.add(obj); ++ } ++ // Yatopia end + BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); + + try { diff --git a/DivineMC/patches/server/0013-Fix-outdated-server-showing-in-ping-before-server-fu.patch b/DivineMC/patches/server/0013-Fix-outdated-server-showing-in-ping-before-server-fu.patch new file mode 100644 index 0000000..2a52723 --- /dev/null +++ b/DivineMC/patches/server/0013-Fix-outdated-server-showing-in-ping-before-server-fu.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Tue, 4 Jun 2019 15:50:08 -0500 +Subject: [PATCH] Fix 'outdated server' showing in ping before server fully + boots + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index 29a22da1b94d51300481c071aa16bfd8cd02178f..f67cbb1badc007987e62872bb0160ad6d05e3d97 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -153,6 +153,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + this.connection.send(new ClientboundStatusResponsePacket(ping)); + // CraftBukkit end + */ ++ if (this.server.getStatus().getVersion() == null) return; // Purpur - do not respond to pings before we know the protocol version + com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); + // Paper end + } diff --git a/DivineMC/patches/server/0014-Remove-TickTask.patch b/DivineMC/patches/server/0014-Remove-TickTask.patch new file mode 100644 index 0000000..1128a2e --- /dev/null +++ b/DivineMC/patches/server/0014-Remove-TickTask.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Thu, 1 Jul 2021 11:59:11 +0000 +Subject: [PATCH] Remove TickTask + +Original code by PatinaMC, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/PatinaMC/Patina + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 3378298b0c465c0df9618804c390930e875bcce3..904ce75db06d3a50025bf758279e84346912ef6c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -182,7 +182,7 @@ import org.bukkit.event.server.ServerLoadEvent; + + import co.aikar.timings.MinecraftTimings; // Paper + +-public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements CommandSource, AutoCloseable { ++public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements CommandSource, AutoCloseable { // Patina + + private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogUtils.getLogger(); +@@ -1297,19 +1297,21 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {}; + } + // Paper end +- return new TickTask(this.tickCount, runnable); ++ return runnable; // Patina + } + ++ /* // Patina + protected boolean shouldRun(TickTask ticktask) { + return ticktask.getTick() + 3 < this.tickCount || this.haveTime(); + } ++ */ + + @Override + public boolean pollTask() { +@@ -1341,10 +1343,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop optional = Optional.of(this.getFile("server-icon.png")).filter(File::isFile); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 7266e6703d5cd0fea90ec88c74a7d4567f2420ae..16ee24bef4eb2184d821565665f3c1ddf0f3bb39 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -1007,10 +1007,12 @@ public class ServerChunkCache extends ChunkSource { + return runnable; + } + ++ /* // Patina + @Override + protected boolean shouldRun(Runnable task) { + return true; + } ++ */ + + @Override + protected boolean scheduleExecutables() { +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index 7a4ade1a4190bf4fbb048919ae2be230f7b80fff..8bf10c68c233a445902a143eaeb5252247c74a75 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -29,7 +29,7 @@ public abstract class BlockableEventLoop implements Profiler + + protected abstract R wrapRunnable(Runnable runnable); + +- protected abstract boolean shouldRun(R task); ++ //protected abstract boolean shouldRun(R task); // Patina + + public boolean isSameThread() { + return Thread.currentThread() == this.getRunningThread(); +@@ -120,7 +120,7 @@ public abstract class BlockableEventLoop implements Profiler + R runnable = this.pendingRunnables.peek(); + if (runnable == null) { + return false; +- } else if (this.blockingCount == 0 && !this.shouldRun(runnable)) { ++ } else if (this.blockingCount == 0 && !true/*this.shouldRun(runnable)*/) { // Patina + return false; + } else { + this.doRunTask(this.pendingRunnables.remove()); diff --git a/DivineMC/patches/server/0015-Make-a-field-final.patch b/DivineMC/patches/server/0015-Make-a-field-final.patch new file mode 100644 index 0000000..04cfb33 --- /dev/null +++ b/DivineMC/patches/server/0015-Make-a-field-final.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Thu, 1 Jul 2021 12:11:49 +0000 +Subject: [PATCH] Make a field final + +Original code by PatinaMC, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/PatinaMC/Patina + +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index e0dd0fc1638377f4d4226d4b2976b901d635dff0..e75a428ff261a52b8d5f72d5c46437feef5b8ac4 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -59,7 +59,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + private final Vec2 rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; +- public java.util.Map currentCommand = new java.util.concurrent.ConcurrentHashMap<>(); // CraftBukkit // Paper ++ public final java.util.Map currentCommand = new java.util.concurrent.ConcurrentHashMap<>(); // CraftBukkit // Paper // Patina - make a field final + + public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) { + this(output, pos, rot, world, level, name, displayName, server, entity, false, (commandcontext, flag, j) -> { diff --git a/DivineMC/patches/server/0016-Don-t-create-new-random-instance.patch b/DivineMC/patches/server/0016-Don-t-create-new-random-instance.patch new file mode 100644 index 0000000..2ced06c --- /dev/null +++ b/DivineMC/patches/server/0016-Don-t-create-new-random-instance.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Thu, 1 Jul 2021 12:17:44 +0000 +Subject: [PATCH] Don't create new random instance + +Original code by PatinaMC, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/PatinaMC/Patina + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index e5af7ef4ada68922a70f593ccec555ecb50627a9..eb634c540842a06bfea196bc9fe4bfbd73012bf1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -380,7 +380,7 @@ public class ServerPlayer extends Player { + long l = k * k; + int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; + int j1 = this.getCoprime(i1); +- int k1 = RandomSource.create().nextInt(i1); ++ int k1 = worldserver.random.nextInt(i1); // Patina - don't create new random instance + + for (int l1 = 0; l1 < i1; ++l1) { + int i2 = (k1 + j1 * l1) % i1; +@@ -417,7 +417,7 @@ public class ServerPlayer extends Player { + long l = k * k; + int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; + int j1 = this.getCoprime(i1); +- int k1 = RandomSource.create().nextInt(i1); ++ int k1 = world.random.nextInt(i1); // Patina - don't create new random instance + + for (int l1 = 0; l1 < i1; ++l1) { + int i2 = (k1 + j1 * l1) % i1; +diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +index 1ef089dbf83de35d875c00efdf468c397be56978..c345f10cbf7f3451edc604f97cdf959d70639e17 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +@@ -349,7 +349,7 @@ public class QueryThreadGs4 extends GenericThread { + this.identBytes[2] = bs[5]; + this.identBytes[3] = bs[6]; + this.ident = new String(this.identBytes, StandardCharsets.UTF_8); +- this.challenge = RandomSource.create().nextInt(16777216); ++ this.challenge = java.util.concurrent.ThreadLocalRandom.current().nextInt(16777216); // Patina - don't create new random instance + this.challengeBytes = String.format(Locale.ROOT, "\t%s%d\u0000", this.ident, this.challenge).getBytes(StandardCharsets.UTF_8); + } + diff --git a/DivineMC/patches/server/0017-Completely-remove-bootstrapExecutor.patch b/DivineMC/patches/server/0017-Completely-remove-bootstrapExecutor.patch new file mode 100644 index 0000000..95fd7a9 --- /dev/null +++ b/DivineMC/patches/server/0017-Completely-remove-bootstrapExecutor.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Thu, 1 Jul 2021 12:26:15 +0000 +Subject: [PATCH] Completely remove bootstrapExecutor + +Original code by PatinaMC, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/PatinaMC/Patina + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index cdb7aea969b56f59d88f60bc3744e4932228c50a..59ecf5ff33617a6b9d2a3ae317315484235da804 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -79,7 +79,7 @@ public class Util { + private static final int DEFAULT_MAX_THREADS = 255; + private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads"; + private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); +- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority ++ //private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority // Patina + private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority + // Paper start - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread + public static final ExecutorService PROFILE_EXECUTOR = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() { +@@ -207,7 +207,7 @@ public class Util { + } + + public static ExecutorService bootstrapExecutor() { +- return BOOTSTRAP_EXECUTOR; ++ return BACKGROUND_EXECUTOR; // Patina + } + + public static ExecutorService backgroundExecutor() { diff --git a/DivineMC/patches/server/0018-Fix-rotating-UP-DOWN-CW-and-CCW.patch b/DivineMC/patches/server/0018-Fix-rotating-UP-DOWN-CW-and-CCW.patch new file mode 100644 index 0000000..27fc4c6 --- /dev/null +++ b/DivineMC/patches/server/0018-Fix-rotating-UP-DOWN-CW-and-CCW.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 6 Jan 2021 02:19:29 -0600 +Subject: [PATCH] Fix rotating UP/DOWN CW and CCW + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index ee725b972d3d5fb22538aaff9c72e47c6bad0cea..2217968eb5ecac0a2063cf1eae7d754d760e9f28 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -252,6 +252,12 @@ public enum Direction implements StringRepresentable { + case EAST: + var10000 = SOUTH; + break; ++ // Purpur start ++ case UP: ++ return UP; ++ case DOWN: ++ return DOWN; ++ // Purpur end + default: + throw new IllegalStateException("Unable to get Y-rotated facing of " + this); + } +@@ -364,6 +370,12 @@ public enum Direction implements StringRepresentable { + case EAST: + var10000 = NORTH; + break; ++ // Purpur start ++ case UP: ++ return UP; ++ case DOWN: ++ return DOWN; ++ // Purpur end + default: + throw new IllegalStateException("Unable to get CCW facing of " + this); + } diff --git a/DivineMC/patches/server/0019-Fix-vanilla-command-permission-handler.patch b/DivineMC/patches/server/0019-Fix-vanilla-command-permission-handler.patch new file mode 100644 index 0000000..9352e63 --- /dev/null +++ b/DivineMC/patches/server/0019-Fix-vanilla-command-permission-handler.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 28 Mar 2020 01:51:32 -0500 +Subject: [PATCH] Fix vanilla command permission handler + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 39844531b03eb8a6c70700b4ecbf0ff1a557424d..632ae75cb3bbc7a3955872d14ad0fbc2459f32e8 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -35,6 +35,7 @@ public abstract class CommandNode implements Comparable> { + private final boolean forks; + private Command command; + public LiteralCommandNode clientNode = null; // Paper ++ private String permission = null; public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } // Purpur + // CraftBukkit start + public void removeCommand(String name) { + this.children.remove(name); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +index 6035af2cf08353b3d3801220d8116d8611a0cd37..7774ab6a2e553a40def4bb4dceea9e5f58d31c1e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +@@ -94,6 +94,7 @@ public final class VanillaCommandWrapper extends BukkitCommand { + } + + public static String getPermission(CommandNode vanillaCommand) { ++ if (vanillaCommand.getPermission() != null) return vanillaCommand.getPermission(); // Purpur + // Paper start + final String commandName; + if (vanillaCommand.getRedirect() == null) { diff --git a/DivineMC/patches/server/0020-Remove-sync-chunk-writes-in-server.properties.patch b/DivineMC/patches/server/0020-Remove-sync-chunk-writes-in-server.properties.patch new file mode 100644 index 0000000..dc3fd38 --- /dev/null +++ b/DivineMC/patches/server/0020-Remove-sync-chunk-writes-in-server.properties.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Simon Gardling +Date: Mon, 6 Dec 2021 10:27:12 -0500 +Subject: [PATCH] Remove 'sync-chunk-writes' in server.properties + +Original code by Titaniumtown, licensed under GNU General Public License v3.0 +You can find the original code on https://gitlab.com/Titaniumtown/JettPack + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index d4efadbc87ee0b6cb8564c57fc9dcbb48367a767..300e61a9ebaece1f337031b27181f270f90e7a52 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -392,7 +392,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + BufferedWriter bufferedwriter = Files.newBufferedWriter(file); + + try { +- bufferedwriter.write(String.format(Locale.ROOT, "sync-chunk-writes=%s%n", dedicatedserverproperties.syncChunkWrites)); ++ //bufferedwriter.write(String.format(Locale.ROOT, "sync-chunk-writes=%s%n", dedicatedserverproperties.syncChunkWrites)); // JettPack - remove 'sync-chunk-writes' in server.properties + bufferedwriter.write(String.format(Locale.ROOT, "gamemode=%s%n", dedicatedserverproperties.gamemode)); + bufferedwriter.write(String.format(Locale.ROOT, "spawn-monsters=%s%n", dedicatedserverproperties.spawnMonsters)); + bufferedwriter.write(String.format(Locale.ROOT, "entity-broadcast-range-percentage=%d%n", dedicatedserverproperties.entityBroadcastRangePercentage)); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index a32cfa75a9bea896f558bab646d0868391b069a9..3e4a3915cdf29fc964e0314ce01d156dd2f4f873 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -136,7 +136,7 @@ public class DedicatedServerProperties extends Settings { + return Mth.clamp(integer, (int) 1, 29999984); + }, 29999984); +- this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag ++ this.syncChunkWrites = Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag // JettPack - remove 'sync-chunk-writes' in server.properties + this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); + this.enableStatus = this.get("enable-status", true); + this.hideOnlinePlayers = this.get("hide-online-players", false); diff --git a/DivineMC/patches/server/0021-Remove-Spigot-tick-limiter.patch b/DivineMC/patches/server/0021-Remove-Spigot-tick-limiter.patch new file mode 100644 index 0000000..f68db39 --- /dev/null +++ b/DivineMC/patches/server/0021-Remove-Spigot-tick-limiter.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Simon Gardling +Date: Mon, 6 Dec 2021 10:34:33 -0500 +Subject: [PATCH] Remove Spigot tick limiter + +Original code by Titaniumtown, licensed under GNU General Public License v3.0 +You can find the original code on https://gitlab.com/Titaniumtown/JettPack + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 13aee2a785b3ddb481744277a25c1ab95e036d4a..7fc3c9892d69d14de694d5328fe17a971019cc54 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -176,8 +176,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot +- private org.spigotmc.TickLimiter entityLimiter; +- private org.spigotmc.TickLimiter tileLimiter; ++ //private org.spigotmc.TickLimiter entityLimiter; // JettPack - remove tick limiter ++ //private org.spigotmc.TickLimiter tileLimiter; // JettPack - remove tick limiter + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here +@@ -371,8 +371,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit end + timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings + this.keepSpawnInMemory = this.paperConfig().spawn.keepSpawnLoaded; // Paper +- this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); +- this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); ++ //this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); // JettPack - remove tick limiter ++ //this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); // JettPack - remove tick limiter + this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + } + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 46ef3400605cc420bd88f13838df7d1f1106235e..a5a2e497eb3e651f3e715f995a80161d919ebab9 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -446,6 +446,7 @@ public class SpigotWorldConfig + this.hangingTickFrequency = this.getInt( "hanging-tick-frequency", 100 ); + } + ++ /* JettPack - remove tick limiter + public int tileMaxTickTime; + public int entityMaxTickTime; + private void maxTickTimes() +@@ -454,6 +455,7 @@ public class SpigotWorldConfig + this.entityMaxTickTime = this.getInt("max-tick-time.entity", 50); + this.log("Tile Max Tick Time: " + this.tileMaxTickTime + "ms Entity max Tick Time: " + this.entityMaxTickTime + "ms"); + } ++ */ + + public int thunderChance; + private void thunderChance() +diff --git a/src/main/java/org/spigotmc/TickLimiter.java b/src/main/java/org/spigotmc/TickLimiter.java +deleted file mode 100644 +index 4074538ea6090bf99d8ab04b1e98c2832a0e9a98..0000000000000000000000000000000000000000 +--- a/src/main/java/org/spigotmc/TickLimiter.java ++++ /dev/null +@@ -1,20 +0,0 @@ +-package org.spigotmc; +- +-public class TickLimiter { +- +- private final int maxTime; +- private long startTime; +- +- public TickLimiter(int maxtime) { +- this.maxTime = maxtime; +- } +- +- public void initTick() { +- this.startTime = System.currentTimeMillis(); +- } +- +- public boolean shouldContinue() { +- long remaining = System.currentTimeMillis() - this.startTime; +- return remaining < this.maxTime; +- } +-} diff --git a/DivineMC/patches/server/0022-Spread-out-and-optimise-player-list-ticksSpread-out-.patch b/DivineMC/patches/server/0022-Spread-out-and-optimise-player-list-ticksSpread-out-.patch new file mode 100644 index 0000000..9225aad --- /dev/null +++ b/DivineMC/patches/server/0022-Spread-out-and-optimise-player-list-ticksSpread-out-.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: James Lyne +Date: Mon, 7 Dec 2020 17:52:36 +0000 +Subject: [PATCH] Spread out and optimise player list ticksSpread out and + optimise player list ticks + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index faaf13f46bc7bf0ffc1fe61f45e9f11cb9c8b4d5..f4b554da231ed968c6fa7d71380da361d463d6c5 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1032,22 +1032,22 @@ public abstract class PlayerList { + } + + public void tick() { +- if (++this.sendAllPlayerInfoIn > 600) { +- // CraftBukkit start +- for (int i = 0; i < this.players.size(); ++i) { +- final ServerPlayer target = (ServerPlayer) this.players.get(i); +- +- target.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_LATENCY, this.players.stream().filter(new Predicate() { +- @Override +- public boolean test(ServerPlayer input) { +- return target.getBukkitEntity().canSee(input.getBukkitEntity()); +- } +- }).collect(Collectors.toList()))); ++ // Purpur start ++ if (this.sendAllPlayerInfoIn < this.players.size()) { ++ final org.bukkit.craftbukkit.entity.CraftPlayer target = this.players.get(this.sendAllPlayerInfoIn).getBukkitEntity(); ++ final List list = new java.util.ArrayList<>(); ++ for (ServerPlayer player : this.players) { ++ if (target.canSee(player.getUUID())) { ++ list.add(player); ++ } + } +- // CraftBukkit end +- this.sendAllPlayerInfoIn = 0; ++ target.getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_LATENCY, list)); + } + ++ if (++this.sendAllPlayerInfoIn > 600) { ++ this.sendAllPlayerInfoIn = 0; ++ } ++ // Purpur end + } + + public void broadcastAll(Packet packet) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b1136b9c39b16cbb9dfe460f88000f74ccd4f571..cfbabdcade291b2fcdbe83206b060b8762f50f41 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1883,7 +1883,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public boolean canSee(org.bukkit.entity.Entity entity) { +- return !this.hiddenEntities.containsKey(entity.getUniqueId()); ++ // Purpur start ++ return this.canSee(entity.getUniqueId()); ++ } ++ ++ public boolean canSee(UUID uuid) { ++ return !this.hiddenEntities.containsKey(uuid); ++ // Purpur end + } + + @Override diff --git a/DivineMC/patches/server/0023-Don-t-save-Fireworks.patch b/DivineMC/patches/server/0023-Don-t-save-Fireworks.patch new file mode 100644 index 0000000..b2c6986 --- /dev/null +++ b/DivineMC/patches/server/0023-Don-t-save-Fireworks.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 28 Dec 2013 21:25:06 -0500 +Subject: [PATCH] Don't save Fireworks + +Original code by Starlis, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/starlis/empirecraft + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 61252ef8a79bac0ea2d3d231ec6b12166f39d072..d01654155b200b53d7822f6695d1ab94aabb8a52 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -358,4 +358,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + public boolean isAttackable() { + return false; + } ++ ++ // EMC start ++ @Override ++ public boolean shouldBeSaved() { ++ return false; ++ } ++ // EMC end + } diff --git a/DivineMC/patches/server/0024-Do-not-drop-items-from-Give-command.patch b/DivineMC/patches/server/0024-Do-not-drop-items-from-Give-command.patch new file mode 100644 index 0000000..53a6cb7 --- /dev/null +++ b/DivineMC/patches/server/0024-Do-not-drop-items-from-Give-command.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 14 Jan 2016 00:49:14 -0500 +Subject: [PATCH] Do not drop items from Give command + +Original code by Starlis, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/starlis/empirecraft + +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java +index 06e3a868e922f1b7a586d0ca28f64a67ae463b68..00c481ebf012efa5424e32521e7aecf4b36f24c0 100644 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -58,6 +58,7 @@ public class GiveCommand { + boolean flag = entityplayer.getInventory().add(itemstack); + ItemEntity entityitem; + ++ if (true) { continue; } // EMC - never drop items + if (flag && itemstack.isEmpty()) { + itemstack.setCount(1); + entityitem = entityplayer.drop(itemstack, false, false, false); // SPIGOT-2942: Add boolean to call event diff --git a/DivineMC/patches/server/0025-Do-not-process-chat-commands-before-player-has-joine.patch b/DivineMC/patches/server/0025-Do-not-process-chat-commands-before-player-has-joine.patch new file mode 100644 index 0000000..2fc441d --- /dev/null +++ b/DivineMC/patches/server/0025-Do-not-process-chat-commands-before-player-has-joine.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 3 Aug 2021 10:39:44 -0500 +Subject: [PATCH] Do not process chat/commands before player has joined + +Original code by Starlis, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/starlis/empirecraft + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 65362a582d19ab690bcdd68533319f70a7e585f1..ca245019669591a5468de2df6dedc3080b61282e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2346,6 +2346,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + } else if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); + return false; ++ } else if (!player.didPlayerJoinEvent) { return false; // EMC - do not handle chat messages before they joined + } else { + LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessagesValidator; + Set set; diff --git a/DivineMC/patches/server/0026-Fix-cow-rotation-when-shearing-mooshroom.patch b/DivineMC/patches/server/0026-Fix-cow-rotation-when-shearing-mooshroom.patch new file mode 100644 index 0000000..3815c53 --- /dev/null +++ b/DivineMC/patches/server/0026-Fix-cow-rotation-when-shearing-mooshroom.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 3 May 2019 23:53:16 -0500 +Subject: [PATCH] Fix cow rotation when shearing mooshroom + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +index e84d4ecc1fd8e196743a37b18306a4769abbcb77..a715465611be53dc94770feee0f13381f7d82e24 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +@@ -180,7 +180,13 @@ public class MushroomCow extends Cow implements Shearable { + + entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + entitycow.setHealth(this.getHealth()); ++ // Purpur start ++ entitycow.copyPosition(this); + entitycow.yBodyRot = this.yBodyRot; ++ entitycow.setYHeadRot(this.getYHeadRot()); ++ entitycow.yRotO = this.yRotO; ++ entitycow.xRotO = this.xRotO; ++ // Purpur end + if (this.hasCustomName()) { + entitycow.setCustomName(this.getCustomName()); + entitycow.setCustomNameVisible(this.isCustomNameVisible()); diff --git a/DivineMC/patches/server/0027-End-gateway-should-check-if-entity-can-use-portal.patch b/DivineMC/patches/server/0027-End-gateway-should-check-if-entity-can-use-portal.patch new file mode 100644 index 0000000..fe2b31d --- /dev/null +++ b/DivineMC/patches/server/0027-End-gateway-should-check-if-entity-can-use-portal.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 21 Mar 2020 18:33:05 -0500 +Subject: [PATCH] End gateway should check if entity can use portal + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 56d68b87287f0bb2c79ce0bed02fa333b85c4287..5c7e30eb5e8a2a1ab18750a2cd2ec7364e8c52e0 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -177,6 +177,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + + public static void teleportEntity(Level world, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) { + if (world instanceof ServerLevel && !blockEntity.isCoolingDown()) { ++ if (!entity.canChangeDimensions()) return; // Purpur + ServerLevel worldserver = (ServerLevel) world; + + blockEntity.teleportCooldown = 100; diff --git a/DivineMC/patches/server/0028-Arrows-should-not-reset-despawn-counter.patch b/DivineMC/patches/server/0028-Arrows-should-not-reset-despawn-counter.patch new file mode 100644 index 0000000..693b1fb --- /dev/null +++ b/DivineMC/patches/server/0028-Arrows-should-not-reset-despawn-counter.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 4 Nov 2020 13:12:50 -0600 +Subject: [PATCH] Arrows should not reset despawn counter + +This prevents keeping arrows alive indefinitely (such as when the block +the arrow is stuck in gets removed, like a piston head going up/down) + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +index bc01e5014e1355a225bdf5c47f2965290b45e2d2..49f093b21aa1268d40aa54ebfce06976bd79ae81 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -322,7 +322,7 @@ public abstract class AbstractArrow extends Projectile { + Vec3 vec3d = this.getDeltaMovement(); + + this.setDeltaMovement(vec3d.multiply((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); +- this.life = 0; ++ // this.life = 0; // Purpur - do not reset despawn counter + } + + @Override diff --git a/DivineMC/patches/server/0029-PaperPR-Use-DataConverter-for-itemstack-entity-deser.patch b/DivineMC/patches/server/0029-PaperPR-Use-DataConverter-for-itemstack-entity-deser.patch new file mode 100644 index 0000000..07237fc --- /dev/null +++ b/DivineMC/patches/server/0029-PaperPR-Use-DataConverter-for-itemstack-entity-deser.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> +Date: Fri, 10 Dec 2021 08:15:36 -0500 +Subject: [PATCH] PaperPR Use DataConverter for itemstack/entity + deserialization + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index eff5dda2232fec841e5a5ba393f09475b0ce2861..26402ccd5dfc4713df5514354e2f8baa6c767530 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -453,8 +453,8 @@ public final class CraftMagicNumbers implements UnsafeValues { + + CompoundTag compound = deserializeNbtFromBytes(data); + int dataVersion = compound.getInt("DataVersion"); +- Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); +- return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue())); ++ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, getDataVersion()); // Paper - rewrite dataconverter ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound)); + } + + @Override +@@ -474,8 +474,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + + CompoundTag compound = deserializeNbtFromBytes(data); + int dataVersion = compound.getInt("DataVersion"); +- Dynamic converted = DataFixers.getDataFixer().update(References.ENTITY_TREE, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); +- compound = (CompoundTag) converted.getValue(); ++ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY, compound, dataVersion, getDataVersion()); // Paper - rewrite dataconverter + if (!preserveUUID) compound.remove("UUID"); // Generate a new UUID so we don't have to worry about deserializing the same entity twice + return net.minecraft.world.entity.EntityType.create(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle()) + .orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity(); diff --git a/DivineMC/patches/server/0030-Dont-eat-blocks-in-non-ticking-chunks.patch b/DivineMC/patches/server/0030-Dont-eat-blocks-in-non-ticking-chunks.patch new file mode 100644 index 0000000..2c7240d --- /dev/null +++ b/DivineMC/patches/server/0030-Dont-eat-blocks-in-non-ticking-chunks.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 15 Jan 2022 06:23:04 -0600 +Subject: [PATCH] Dont eat blocks in non ticking chunks + +Original code by PurpurMC, licensed under MIT +You can find the original code on https://github.com/PurpurMC/Purpur + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 9ce60dd72dee4d3ceef38f425b13aed18fd5e002..9976630fad886392057f642e84f919f0b95cc040 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -983,7 +983,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return this.anyPlayerCloseEnoughForSpawning(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); + } + +- final boolean anyPlayerCloseEnoughForSpawning(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { ++ public final boolean anyPlayerCloseEnoughForSpawning(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { // Purpur - package -> public + // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance + // tested and confirmed via System.nanoTime() + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +index 80aa539f7c6a6ee44338de084cdcdf5fb4ef996a..9c2c2b3557f4a70c6c965f159a57682e1827d1ad 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +@@ -31,6 +31,12 @@ public class EatBlockGoal extends Goal { + + @Override + public boolean canUse() { ++ // Purpur start ++ net.minecraft.world.level.chunk.LevelChunk chunk = this.mob.level.getChunkIfLoaded(this.mob.blockPosition); ++ if (chunk == null || chunk.playerChunk == null || !((net.minecraft.server.level.ServerLevel) this.mob.level).getChunkSource().chunkMap.anyPlayerCloseEnoughForSpawning(chunk.playerChunk, this.mob.chunkPosition(), false)) { ++ return false; ++ } ++ // Purpur end + if (this.mob.getRandom().nextInt(this.mob.isBaby() ? 50 : 1000) != 0) { + return false; + } else { diff --git a/DivineMC/patches/server/0031-carpetfixes-BiomeAccess-prediction.patch b/DivineMC/patches/server/0031-carpetfixes-BiomeAccess-prediction.patch new file mode 100644 index 0000000..710d7e3 --- /dev/null +++ b/DivineMC/patches/server/0031-carpetfixes-BiomeAccess-prediction.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Fri, 22 Apr 2022 22:44:56 +0200 +Subject: [PATCH] carpetfixes: BiomeAccess prediction + +Author: fxmorin + +Original license: MIT +Original project: https://github.com/fxmorin/carpet-fixes (Yarn mappings) + +Copyright (c) 2020 Fx Morin + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +index 5695c5116c8a338b2e41aafcb2dc9f2146856970..6ee0a42dd048352c3df5d4788ea09170010a95b5 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +@@ -28,41 +28,72 @@ public class BiomeManager { + return new BiomeManager(storage, this.biomeZoomSeed); + } + ++ // DivineMC start - carpetfixes: BiomeAccess prediction ++ private static final double maxOffset = 0.4500000001D; // DivineMC - carpetfixes: BiomeAccess prediction + public Holder getBiome(BlockPos pos) { +- int i = pos.getX() - 2; +- int j = pos.getY() - 2; +- int k = pos.getZ() - 2; +- int l = i >> 2; +- int m = j >> 2; +- int n = k >> 2; +- double d = (double)(i & 3) / 4.0D; +- double e = (double)(j & 3) / 4.0D; +- double f = (double)(k & 3) / 4.0D; +- int o = 0; +- double g = Double.POSITIVE_INFINITY; +- +- for(int p = 0; p < 8; ++p) { +- boolean bl = (p & 4) == 0; +- boolean bl2 = (p & 2) == 0; +- boolean bl3 = (p & 1) == 0; +- int q = bl ? l : l + 1; +- int r = bl2 ? m : m + 1; +- int s = bl3 ? n : n + 1; +- double h = bl ? d : d - 1.0D; +- double t = bl2 ? e : e - 1.0D; +- double u = bl3 ? f : f - 1.0D; +- double v = getFiddledDistance(this.biomeZoomSeed, q, r, s, h, t, u); +- if (g > v) { +- o = p; +- g = v; ++ int xMinus2 = pos.getX() - 2; ++ int yMinus2 = pos.getY() - 2; ++ int zMinus2 = pos.getZ() - 2; ++ int x = xMinus2 >> 2; // BlockPos to BiomePos ++ int y = yMinus2 >> 2; ++ int z = zMinus2 >> 2; ++ double quartX = (double) (xMinus2 & 3) / 4.0D; // quartLocal divided by 4 ++ double quartY = (double) (yMinus2 & 3) / 4.0D; // 0/4, 1/4, 2/4, 3/4 ++ double quartZ = (double) (zMinus2 & 3) / 4.0D; // [0, 0.25, 0.5, 0.75] ++ int smallestX = 0; ++ double smallestDist = Double.POSITIVE_INFINITY; ++ for (int biomeX = 0; biomeX < 8; ++biomeX) { ++ boolean everyOtherQuad = (biomeX & 4) == 0; // 1 1 1 1 0 0 0 0 ++ boolean everyOtherPair = (biomeX & 2) == 0; // 1 1 0 0 1 1 0 0 ++ boolean everyOther = (biomeX & 1) == 0; // 1 0 1 0 1 0 1 0 ++ double quartXX = everyOtherQuad ? quartX : quartX - 1.0D; //[-1.0,-0.75,-0.5,-0.25,0.0,0.25,0.5,0.75] ++ double quartYY = everyOtherPair ? quartY : quartY - 1.0D; ++ double quartZZ = everyOther ? quartZ : quartZ - 1.0D; ++ ++ //This code block is new ++ double maxQuartYY = 0.0D, maxQuartZZ = 0.0D; ++ if (biomeX != 0) { ++ maxQuartYY = Mth.square(Math.max(quartYY + maxOffset, Math.abs(quartYY - maxOffset))); ++ maxQuartZZ = Mth.square(Math.max(quartZZ + maxOffset, Math.abs(quartZZ - maxOffset))); ++ double maxQuartXX = Mth.square(Math.max(quartXX + maxOffset,Math.abs(quartXX - maxOffset))); ++ if (smallestDist < maxQuartXX + maxQuartYY + maxQuartZZ) continue; ++ } ++ ++ int xx = everyOtherQuad ? x : x + 1; ++ int yy = everyOtherPair ? y : y + 1; ++ int zz = everyOther ? z : z + 1; ++ ++ //I transferred the code from method_38106 to here, so I could call continue halfway through ++ long seed = LinearCongruentialGenerator.next(this.biomeZoomSeed, xx); ++ seed = LinearCongruentialGenerator.next(seed, yy); ++ seed = LinearCongruentialGenerator.next(seed, zz); ++ seed = LinearCongruentialGenerator.next(seed, xx); ++ seed = LinearCongruentialGenerator.next(seed, yy); ++ seed = LinearCongruentialGenerator.next(seed, zz); ++ double offsetX = getFiddle(seed); ++ double sqrX = Mth.square(quartXX + offsetX); ++ if (biomeX != 0 && smallestDist < sqrX + maxQuartYY + maxQuartZZ) continue; //skip the rest of the loop ++ seed = LinearCongruentialGenerator.next(seed, this.biomeZoomSeed); ++ double offsetY = getFiddle(seed); ++ double sqrY = Mth.square(quartYY + offsetY); ++ if (biomeX != 0 && smallestDist < sqrX + sqrY + maxQuartZZ) continue; // skip the rest of the loop ++ seed = LinearCongruentialGenerator.next(seed, this.biomeZoomSeed); ++ double offsetZ = getFiddle(seed); ++ double biomeDist = sqrX + sqrY + Mth.square(quartZZ + offsetZ); ++ ++ if (smallestDist > biomeDist) { ++ smallestX = biomeX; ++ smallestDist = biomeDist; + } + } + +- int w = (o & 4) == 0 ? l : l + 1; +- int x = (o & 2) == 0 ? m : m + 1; +- int y = (o & 1) == 0 ? n : n + 1; +- return this.noiseBiomeSource.getNoiseBiome(w, x, y); ++ return(this.noiseBiomeSource.getNoiseBiome( ++ (smallestX & 4) == 0 ? x : x + 1, ++ (smallestX & 2) == 0 ? y : y + 1, ++ (smallestX & 1) == 0 ? z : z + 1 ++ )); + } ++ // DivineMC end + + public Holder getNoiseBiomeAtPosition(double x, double y, double z) { + int i = QuartPos.fromBlock(Mth.floor(x)); diff --git a/DivineMC/patches/server/0032-Fix-MC-121706.patch b/DivineMC/patches/server/0032-Fix-MC-121706.patch new file mode 100644 index 0000000..179f8b4 --- /dev/null +++ b/DivineMC/patches/server/0032-Fix-MC-121706.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Etil <81570777+etil2jz@users.noreply.github.com> +Date: Sun, 2 Jan 2022 20:37:30 +0100 +Subject: [PATCH] Fix MC-121706 + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java +index 6558b0d4bea99948fdc2b51751f3cfdc239d4b67..edb296ceaebfc296cf76682beeeda95d6ac2d93a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java +@@ -111,10 +111,10 @@ public class RangedBowAttackGoal extends Go + + this.mob.getMoveControl().strafe(this.strafingBackwards ? -0.5F : 0.5F, this.strafingClockwise ? 0.5F : -0.5F); + this.mob.lookAt(livingEntity, 30.0F, 30.0F); +- } else { +- this.mob.getLookControl().setLookAt(livingEntity, 30.0F, 30.0F); + } + ++ this.mob.getLookControl().setLookAt(livingEntity, 30.0F, 30.0F); // DivineMC - fix MC-121706 ++ + if (this.mob.isUsingItem()) { + if (!bl && this.seeTime < -60) { + this.mob.stopUsingItem(); diff --git a/DivineMC/patches/server/0033-PaperPR-Add-more-collision-code-skipping-logic.patch b/DivineMC/patches/server/0033-PaperPR-Add-more-collision-code-skipping-logic.patch new file mode 100644 index 0000000..c1b3a8c --- /dev/null +++ b/DivineMC/patches/server/0033-PaperPR-Add-more-collision-code-skipping-logic.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Sat, 19 Mar 2022 16:27:30 +0100 +Subject: [PATCH] PaperPR Add more collision code skipping logic + +Taken from https://github.com/PaperMC/Paper/pull/7581 + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c0e316582e085873c05a76c16e612eabd2e8cf2a..dd881ca1460ad3d1f17b40969a872c3226d9d0c9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3466,6 +3466,10 @@ public abstract class LivingEntity extends Entity { + + protected void pushEntities() { + // Paper start - don't run getEntities if we're not going to use its result ++ if (!isCollidable(level.paperConfig().collisions.fixClimbingBypassingCrammingRule)) return; ++ net.minecraft.world.scores.Team team = getTeam(); ++ if (team != null && team.getCollisionRule() == net.minecraft.world.scores.Team.CollisionRule.NEVER) return; ++ + int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); + if (i <= 0 && level.paperConfig().collisions.maxEntityCollisions <= 0) { + return; diff --git a/DivineMC/patches/server/0034-Fix-tick-function-tag-running-before-load.patch b/DivineMC/patches/server/0034-Fix-tick-function-tag-running-before-load.patch new file mode 100644 index 0000000..737ef16 --- /dev/null +++ b/DivineMC/patches/server/0034-Fix-tick-function-tag-running-before-load.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Fri, 8 Apr 2022 21:20:50 +0200 +Subject: [PATCH] Fix tick function tag running before load + + +diff --git a/src/main/java/net/minecraft/server/ServerFunctionManager.java b/src/main/java/net/minecraft/server/ServerFunctionManager.java +index 00a50196f6a4768d84acfbbeec79a0753308f091..3452ff5d378a2703fb0959c8163ee0274236e839 100644 +--- a/src/main/java/net/minecraft/server/ServerFunctionManager.java ++++ b/src/main/java/net/minecraft/server/ServerFunctionManager.java +@@ -46,13 +46,14 @@ public class ServerFunctionManager { + } + + public void tick() { +- this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); ++ //this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); // DivineMC - moved down + if (this.postReload) { + this.postReload = false; + Collection collection = this.library.getTag(ServerFunctionManager.LOAD_FUNCTION_TAG); + + this.executeTagFunctions(collection, ServerFunctionManager.LOAD_FUNCTION_TAG); + } ++ this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); // DivineMC - fix tick function tag running before load + + } + diff --git a/DivineMC/patches/server/0035-Optimize-default-values-for-configs.patch b/DivineMC/patches/server/0035-Optimize-default-values-for-configs.patch new file mode 100644 index 0000000..3264577 --- /dev/null +++ b/DivineMC/patches/server/0035-Optimize-default-values-for-configs.patch @@ -0,0 +1,379 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Sun, 8 May 2022 13:13:02 +0200 +Subject: [PATCH] Optimize default values for configs + + +diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +index 34eb43ca2bf446504c372f98dfbe6dbfd0a81369..40d61b50ad783a6d68fc7b43ae0d3fa9cc579ecb 100644 +--- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java ++++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +@@ -217,7 +217,7 @@ public class PufferfishConfig { + public static int maxProjectileLoadsPerProjectile; + private static void projectileLoading() { + maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); +- maxProjectileLoadsPerProjectile = getInt("projectile.max-loads-per-projectile", 10, "Controls how many chunks a projectile", "can load in its lifetime before it gets", "automatically removed."); ++ maxProjectileLoadsPerProjectile = getInt("projectile.max-loads-per-projectile", 8, "Controls how many chunks a projectile", "can load in its lifetime before it gets", "automatically removed."); // DivineMC - optimize default values for configs + + setComment("projectile", "Optimizes projectile settings"); + } +diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +index 54bca103347e89f116fb7fbf37449a32ac094286..4c6ce35aa6f0ccdcbbf66e0e53a1cc8421b04ef0 100644 +--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java ++++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +@@ -55,7 +55,7 @@ public class GlobalConfiguration extends ConfigurationPart { + public boolean enabled = true; + public boolean reallyEnabled = false; + public boolean verbose = true; +- public String url = "https://timings.aikar.co/"; ++ public String url = "https://timin.gs/"; // DivineMC - optimize default values for configs + public boolean serverNamePrivacy = false; + public List hiddenConfigEntries = List.of( + "database", +@@ -289,9 +289,9 @@ public class GlobalConfiguration extends ConfigurationPart { + public boolean fixEntityPositionDesync = true; + public boolean loadPermissionsYmlBeforePlugins = true; + @Constraints.Min(4) +- public int regionFileCacheSize = 256; ++ public int regionFileCacheSize = 512; // DivineMC - optimize default values for configs + @Comment("See https://luckformula.emc.gs") +- public boolean useAlternativeLuckFormula = false; ++ public boolean useAlternativeLuckFormula = true; // DivineMC - optimize default values for configs + public boolean lagCompensateBlockBreaking = true; + public boolean useDimensionTypeForCustomSpawners = false; + public boolean strictAdvancementDimensionCheck = false; +diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +index 3d2e67dc559ee3910b17ca86a46030ec05232250..71ef6082b459bb9812f362141d8fadfc162c88ea 100644 +--- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java ++++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +@@ -113,8 +113,8 @@ public class WorldConfiguration extends ConfigurationPart { + public ArmorStands armorStands; + + public class ArmorStands extends ConfigurationPart { +- public boolean doCollisionEntityLookups = true; +- public boolean tick = true; ++ public boolean doCollisionEntityLookups = false; // DivineMC - optimize default values for configs ++ public boolean tick = false; // DivineMC - optimize default values for configs + } + + public Spawning spawning; +@@ -197,8 +197,8 @@ public class WorldConfiguration extends ConfigurationPart { + public Behavior behavior; + + public class Behavior extends ConfigurationPart { +- public boolean disableChestCatDetection = false; +- public boolean spawnerNerfedMobsShouldJump = false; ++ public boolean disableChestCatDetection = true; // DivineMC - optimize default values for configs ++ public boolean spawnerNerfedMobsShouldJump = true; // DivineMC - optimize default values for configs + public int experienceMergeMaxValue = -1; + public boolean shouldRemoveDragon = false; + public boolean zombiesTargetTurtleEggs = true; +@@ -241,7 +241,7 @@ public class WorldConfiguration extends ConfigurationPart { + public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; + public boolean phantomsDoNotSpawnOnCreativePlayers = true; + public boolean phantomsOnlyAttackInsomniacs = true; +- public boolean parrotsAreUnaffectedByPlayerMovement = false; ++ public boolean parrotsAreUnaffectedByPlayerMovement = true; // DivineMC - optimize default values for configs + public double zombieVillagerInfectionChance = -1.0; + public MobsCanAlwaysPickUpLoot mobsCanAlwaysPickUpLoot; + +@@ -251,7 +251,7 @@ public class WorldConfiguration extends ConfigurationPart { + } + + public boolean disablePlayerCrits = false; +- public boolean nerfPigmenFromNetherPortals = false; ++ public boolean nerfPigmenFromNetherPortals = true; // DivineMC - optimize default values for configs + public PillagerPatrols pillagerPatrols; + + public class PillagerPatrols extends ConfigurationPart { +@@ -309,7 +309,7 @@ public class WorldConfiguration extends ConfigurationPart { + public class Environment extends ConfigurationPart { + public boolean disableThunder = false; + public boolean disableIceAndSnow = false; +- public boolean optimizeExplosions = false; ++ public boolean optimizeExplosions = true; // DivineMC - optimize default values for configs + public boolean disableExplosionKnockback = false; + public boolean generateFlatBedrock = false; + public FrostedIce frostedIce; +@@ -354,7 +354,7 @@ public class WorldConfiguration extends ConfigurationPart { + + public class Maps extends ConfigurationPart { + public int itemFrameCursorLimit = 128; +- public int itemFrameCursorUpdateInterval = 10; ++ public int itemFrameCursorUpdateInterval = 20; // DivineMC - optimize default values for configs + } + + public Fixes fixes; +@@ -380,7 +380,7 @@ public class WorldConfiguration extends ConfigurationPart { + public class Hopper extends ConfigurationPart { + public boolean cooldownWhenFull = true; + public boolean disableMoveEvent = false; +- public boolean ignoreOccludingBlocks = false; ++ public boolean ignoreOccludingBlocks = true; // DivineMC - optimize default values for configs + } + + public Collisions collisions; +@@ -388,9 +388,9 @@ public class WorldConfiguration extends ConfigurationPart { + public class Collisions extends ConfigurationPart { + public boolean onlyPlayersCollide = false; + public boolean allowVehicleCollisions = true; +- public boolean fixClimbingBypassingCrammingRule = false; ++ public boolean fixClimbingBypassingCrammingRule = true; // DivineMC - optimize default values for configs + @RequiresSpigotInitialization(MaxEntityCollisionsInitializer.class) +- public int maxEntityCollisions = 8; ++ public int maxEntityCollisions = 2; // DivineMC - optimize default values for configs + public boolean allowPlayerCrammingDamage = false; + } + +@@ -398,18 +398,32 @@ public class WorldConfiguration extends ConfigurationPart { + + public class Chunks extends ConfigurationPart { + public AutosavePeriod autoSaveInterval = AutosavePeriod.def(); +- public int maxAutoSaveChunksPerTick = 24; ++ public int maxAutoSaveChunksPerTick = 12; // DivineMC - optimize default values for configs + public int fixedChunkInhabitedTime = -1; +- public boolean preventMovingIntoUnloadedChunks = false; +- public Duration delayChunkUnloadsBy = Duration.of("10s"); ++ public boolean preventMovingIntoUnloadedChunks = true; // DivineMC - optimize default values for configs ++ public Duration delayChunkUnloadsBy = Duration.of("5s"); // DivineMC - optimize default values for configs + public Reference2IntMap> entityPerChunkSaveLimit = Util.make(new Reference2IntOpenHashMap<>(Registry.ENTITY_TYPE.size()), map -> { + map.defaultReturnValue(-1); +- map.put(EntityType.EXPERIENCE_ORB, -1); +- map.put(EntityType.SNOWBALL, -1); +- map.put(EntityType.ENDER_PEARL, -1); +- map.put(EntityType.ARROW, -1); +- map.put(EntityType.FIREBALL, -1); +- map.put(EntityType.SMALL_FIREBALL, -1); ++ // DivineMC start - optimize default values for configs ++ map.put(EntityType.EXPERIENCE_ORB, 16); ++ map.put(EntityType.SNOWBALL, 8); ++ map.put(EntityType.ENDER_PEARL, 8); ++ map.put(EntityType.ARROW, 16); ++ map.put(EntityType.FIREBALL, 8); ++ map.put(EntityType.SMALL_FIREBALL, 8); ++ map.put(EntityType.DRAGON_FIREBALL, 3); ++ map.put(EntityType.EGG, 8); ++ map.put(EntityType.EYE_OF_ENDER, 8); ++ map.put(EntityType.FIREWORK_ROCKET, 8); ++ map.put(EntityType.POTION, 8); ++ map.put(EntityType.LLAMA_SPIT, 3); ++ map.put(EntityType.SHULKER_BULLET, 8); ++ map.put(EntityType.SPECTRAL_ARROW, 16); ++ map.put(EntityType.EXPERIENCE_BOTTLE, 3); ++ map.put(EntityType.TRIDENT, 16); ++ map.put(EntityType.WITHER_SKULL, 4); ++ map.put(EntityType.AREA_EFFECT_CLOUD, 8); ++ // DivineMC end + }); + } + +@@ -423,11 +437,22 @@ public class WorldConfiguration extends ConfigurationPart { + public TickRates tickRates; + + public class TickRates extends ConfigurationPart { +- public int grassSpread = 1; +- public int containerUpdate = 1; +- public int mobSpawner = 1; +- public Table, String, Integer> sensor = Util.make(HashBasedTable.create(), table -> table.put(EntityType.VILLAGER, "secondarypoisensor", 40)); +- public Table, String, Integer> behavior = Util.make(HashBasedTable.create(), table -> table.put(EntityType.VILLAGER, "validatenearbypoi", -1)); ++ // DivineMC start - optimize default values for configs ++ public int grassSpread = 4; ++ public int containerUpdate = 3; ++ public int mobSpawner = 2; ++ public Table, String, Integer> sensor = Util.make(HashBasedTable.create(), table -> { ++ table.put(EntityType.VILLAGER, "secondarypoisensor", 80); ++ table.put(EntityType.VILLAGER, "nearestbedsensor", 80); ++ table.put(EntityType.VILLAGER, "villagerbabiessensor", 40); ++ table.put(EntityType.VILLAGER, "playersensor", 40); ++ table.put(EntityType.VILLAGER, "nearestlivingentitysensor", 40); ++ }); ++ public Table, String, Integer> behavior = Util.make(HashBasedTable.create(), table -> { ++ table.put(EntityType.VILLAGER, "validatenearbypoi", 60); ++ table.put(EntityType.VILLAGER, "acquirepoi", 120); ++ }); ++ // DivineMC end + } + + @Setting(FeatureSeedsGeneration.FEATURE_SEEDS_KEY) +@@ -435,7 +460,7 @@ public class WorldConfiguration extends ConfigurationPart { + + public class FeatureSeeds extends ConfigurationPart.Post { + @Setting(FeatureSeedsGeneration.GENERATE_KEY) +- public boolean generateRandomSeedsForAll = false; ++ public boolean generateRandomSeedsForAll = true; // DivineMC - optimize default values for configs + @Setting(FeatureSeedsGeneration.FEATURES_KEY) + public Reference2LongMap>> features = new Reference2LongOpenHashMap<>(); + +@@ -449,9 +474,9 @@ public class WorldConfiguration extends ConfigurationPart { + + public class Misc extends ConfigurationPart { + public int lightQueueSize = 20; +- public boolean updatePathfindingOnBlockUpdate = true; ++ public boolean updatePathfindingOnBlockUpdate = false; // DivineMC - optimize default values for configs + public boolean showSignClickCommandFailureMsgsToPlayer = false; +- public RedstoneImplementation redstoneImplementation = RedstoneImplementation.VANILLA; ++ public RedstoneImplementation redstoneImplementation = RedstoneImplementation.ALTERNATE_CURRENT; // DivineMC - optimize default values for configs + public boolean disableEndCredits = false; + public float maxLeashDistance = 10f; + public boolean disableSprintInterruptionOnAttack = false; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index a5a2e497eb3e651f3e715f995a80161d919ebab9..b88bda3a9a8b3d4e77569f7e3b405bc4b0fbf0df 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -150,14 +150,14 @@ public class SpigotWorldConfig + public double itemMerge; + private void itemMerge() + { +- this.itemMerge = this.getDouble("merge-radius.item", 2.5 ); ++ this.itemMerge = this.getDouble("merge-radius.item", 3.5 ); // DivineMC - optimize default values for configs + this.log( "Item Merge Radius: " + this.itemMerge ); + } + + public double expMerge; + private void expMerge() + { +- this.expMerge = this.getDouble("merge-radius.exp", 3.0 ); ++ this.expMerge = this.getDouble("merge-radius.exp", 4.0 ); // DivineMC - optimize default values for configs + this.log( "Experience Merge Radius: " + this.expMerge ); + } + +@@ -196,7 +196,7 @@ public class SpigotWorldConfig + public byte mobSpawnRange; + private void mobSpawnRange() + { +- this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla ++ this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 2 ); // Paper - Vanilla // DivineMC - optimize default values for configs + this.log( "Mob Spawn Range: " + this.mobSpawnRange ); + } + +@@ -207,14 +207,14 @@ public class SpigotWorldConfig + this.log( "Item Despawn Rate: " + this.itemDespawnRate ); + } + +- public int animalActivationRange = 32; +- public int monsterActivationRange = 32; ++ public int animalActivationRange = 16; // DivineMC - optimize default values for configs ++ public int monsterActivationRange = 24; // DivineMC - optimize default values for configs + public int raiderActivationRange = 48; +- public int miscActivationRange = 16; ++ public int miscActivationRange = 8; // DivineMC - optimize default values for configs + // Paper start + public int flyingMonsterActivationRange = 32; +- public int waterActivationRange = 16; +- public int villagerActivationRange = 32; ++ public int waterActivationRange = 8; // DivineMC - optimize default values for configs ++ public int villagerActivationRange = 16; // DivineMC - optimize default values for configs + public int wakeUpInactiveAnimals = 4; + public int wakeUpInactiveAnimalsEvery = 60*20; + public int wakeUpInactiveAnimalsFor = 5*20; +@@ -231,7 +231,7 @@ public class SpigotWorldConfig + public int villagersWorkImmunityFor = 20; + public boolean villagersActiveForPanic = true; + // Paper end +- public boolean tickInactiveVillagers = true; ++ public boolean tickInactiveVillagers = false; // DivineMC - optimize default values for configs + public boolean ignoreSpectatorActivation = false; + private void activationRange() + { +@@ -297,7 +297,7 @@ public class SpigotWorldConfig + { + this.set( "ticks-per.hopper-check", 1 ); + } +- this.hopperCheck = this.getInt( "ticks-per.hopper-check", 1 ); ++ this.hopperCheck = this.getInt( "ticks-per.hopper-check", 8 ); // DivineMC - optimize default values for configs + this.hopperAmount = this.getInt( "hopper-amount", 1 ); + this.hopperCanLoadChunks = this.getBoolean( "hopper-can-load-chunks", false ); + this.log( "Hopper Transfer: " + this.hopperTransfer + " Hopper Check: " + this.hopperCheck + " Hopper Amount: " + this.hopperAmount + " Hopper Can Load Chunks: " + this.hopperCanLoadChunks ); +@@ -307,7 +307,7 @@ public class SpigotWorldConfig + public int tridentDespawnRate; + private void arrowDespawnRate() + { +- this.arrowDespawnRate = this.getInt( "arrow-despawn-rate", 1200 ); ++ this.arrowDespawnRate = this.getInt( "arrow-despawn-rate", 300 ); // DivineMC - optimize default values for configs + this.tridentDespawnRate = this.getInt( "trident-despawn-rate", this.arrowDespawnRate ); + this.log( "Arrow Despawn Rate: " + this.arrowDespawnRate + " Trident Respawn Rate:" + this.tridentDespawnRate ); + } +@@ -322,14 +322,14 @@ public class SpigotWorldConfig + public boolean nerfSpawnerMobs; + private void nerfSpawnerMobs() + { +- this.nerfSpawnerMobs = this.getBoolean( "nerf-spawner-mobs", false ); ++ this.nerfSpawnerMobs = this.getBoolean( "nerf-spawner-mobs", true ); // DivineMC - optimize default values for configs + this.log( "Nerfing mobs spawned from spawners: " + this.nerfSpawnerMobs ); + } + + public boolean enableZombiePigmenPortalSpawns; + private void enableZombiePigmenPortalSpawns() + { +- this.enableZombiePigmenPortalSpawns = this.getBoolean( "enable-zombie-pigmen-portal-spawns", true ); ++ this.enableZombiePigmenPortalSpawns = this.getBoolean( "enable-zombie-pigmen-portal-spawns", false ); // DivineMC - optimize default values for configs + this.log( "Allow Zombie Pigmen to spawn from portal blocks: " + this.enableZombiePigmenPortalSpawns ); + } + +@@ -443,7 +443,7 @@ public class SpigotWorldConfig + public int hangingTickFrequency; + private void hangingTickFrequency() + { +- this.hangingTickFrequency = this.getInt( "hanging-tick-frequency", 100 ); ++ this.hangingTickFrequency = this.getInt( "hanging-tick-frequency", 200 ); // DivineMC - optimize default values for configs + } + + /* JettPack - remove tick limiter +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index eef7c125b2689f29cae5464659eacdf33f5695b2..c6b04acb5371a0ac454c5e377bccad5b0972aed8 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -18,28 +18,28 @@ settings: + update-folder: update + plugin-profiling: false + connection-throttle: 4000 +- query-plugins: true ++ query-plugins: false + deprecated-verbose: default + shutdown-message: Server closed + minimum-api: none + use-map-color-cache: true + spawn-limits: +- monsters: 70 +- animals: 10 +- water-animals: 5 +- water-ambient: 20 +- water-underground-creature: 5 +- axolotls: 5 +- ambient: 15 ++ monsters: 20 ++ animals: 5 ++ water-animals: 2 ++ water-ambient: 2 ++ water-underground-creature: 3 ++ axolotls: 3 ++ ambient: 1 + chunk-gc: +- period-in-ticks: 600 ++ period-in-ticks: 400 + ticks-per: + animal-spawns: 400 +- monster-spawns: 1 +- water-spawns: 1 +- water-ambient-spawns: 1 +- water-underground-creature-spawns: 1 +- axolotl-spawns: 1 +- ambient-spawns: 1 ++ monster-spawns: 10 ++ water-spawns: 400 ++ water-ambient-spawns: 400 ++ water-underground-creature-spawns: 400 ++ axolotl-spawns: 400 ++ ambient-spawns: 400 + autosave: 6000 + aliases: now-in-commands.yml +diff --git a/src/main/resources/configurations/commands.yml b/src/main/resources/configurations/commands.yml +index 18f54571200e2eca09a39b88f170fe7b99d8618f..1b57d51d92c5c69286800d10baeaa936fa208cae 100644 +--- a/src/main/resources/configurations/commands.yml ++++ b/src/main/resources/configurations/commands.yml +@@ -12,5 +12,3 @@ + command-block-overrides: [] + ignore-vanilla-permissions: false + aliases: +- icanhasbukkit: +- - "version $1-" diff --git a/DivineMC/patches/server/0036-Fix-hunger-saturation-depleting-on-peaceful.patch b/DivineMC/patches/server/0036-Fix-hunger-saturation-depleting-on-peaceful.patch new file mode 100644 index 0000000..60230f6 --- /dev/null +++ b/DivineMC/patches/server/0036-Fix-hunger-saturation-depleting-on-peaceful.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Fri, 22 Apr 2022 18:50:49 +0200 +Subject: [PATCH] Fix hunger saturation depleting on peaceful + +The food saturation value is depleted on peaceful, even though +the displayed hunger bar never goes down. Hunger (or any related value, including saturation) +should not go down on peaceful. See https://bugs.mojang.com/browse/MC-31819. + +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 9b131f0a827413e9f5d6d0f7491c5481576cb8b1..3ec10c8f6cdf98cbf3789845a0d87572e8687ba9 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1919,6 +1919,7 @@ public abstract class Player extends LivingEntity { + } + + public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ if (this.level.getDifficulty() == Difficulty.PEACEFUL) return; // DivineMC - fix hunger saturation depleting on peaceful + // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level.isClientSide) { diff --git a/DivineMC/patches/server/0037-Fix-mobs-attacking-themselves.patch b/DivineMC/patches/server/0037-Fix-mobs-attacking-themselves.patch new file mode 100644 index 0000000..e0f5cc5 --- /dev/null +++ b/DivineMC/patches/server/0037-Fix-mobs-attacking-themselves.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Fri, 29 Apr 2022 12:08:22 +0200 +Subject: [PATCH] Fix mobs attacking themselves + +If an entity is provoked by a second one using commands, +the second will join in the fight against itself, +causing it to attack itself repeatedly. See https://bugs.mojang.com/browse/MC-110386. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java +index 39ea15c7577af186d93d4ad9a48034d746a86fc8..1de734820a5a4b1580c123a8e4a2513d52c42a4b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java +@@ -114,6 +114,7 @@ public class HurtByTargetGoal extends TargetGoal { + } + + protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob == target) return; // DivineMC - avoid entities with suicidal thoughts /s + mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit - reason + } + } diff --git a/DivineMC/patches/server/0038-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch b/DivineMC/patches/server/0038-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch new file mode 100644 index 0000000..5473fa3 --- /dev/null +++ b/DivineMC/patches/server/0038-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Sun, 8 May 2022 16:34:27 +0200 +Subject: [PATCH] Fix brewing stands resetting their brewTime when being + unloaded + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +index 55006724ccec9f3de828ec18693728e9741ff65f..694dfd4e5d77f94b17c5c3927e09e962a566b4ed 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +@@ -295,6 +295,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements + ContainerHelper.loadAllItems(nbt, this.items); + this.brewTime = nbt.getShort("BrewTime"); + this.fuel = nbt.getByte("Fuel"); ++ this.ingredient = net.minecraft.core.Registry.ITEM.get(new net.minecraft.resources.ResourceLocation(nbt.getString("DivineMC.ingredient"))); // DivineMC - fix brewing stands resetting their brewTime when being unloaded + } + + @Override +@@ -303,6 +304,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements + nbt.putShort("BrewTime", (short) this.brewTime); + ContainerHelper.saveAllItems(nbt, this.items); + nbt.putByte("Fuel", (byte) this.fuel); ++ nbt.putString("DivineMC.ingredient", net.minecraft.core.Registry.ITEM.getKey(this.ingredient).toString()); // DivineMC - fix brewing stands resetting their brewTime when being unloaded + } + + @Override diff --git a/DivineMC/patches/server/0039-PaperPR-Optimize-VarInts.patch b/DivineMC/patches/server/0039-PaperPR-Optimize-VarInts.patch new file mode 100644 index 0000000..2a77b65 --- /dev/null +++ b/DivineMC/patches/server/0039-PaperPR-Optimize-VarInts.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: astei +Date: Sat, 1 Oct 2022 09:56:47 +0200 +Subject: [PATCH] PaperPR Optimize VarInts + +Original license: GPLv3 +Original project: https://github.com/PaperMC/Velocity +Paper pull request: https://github.com/PaperMC/Paper/pull/8418 + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 35377576ed182814051c11f902e02e8e921e84e3..4b4a3c0da7a512e16d9a5758ed7312dc9ddc1e28 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -87,15 +87,18 @@ public class FriendlyByteBuf extends ByteBuf { + this.source = parent; + } + +- public static int getVarIntSize(int value) { +- for (int j = 1; j < 5; ++j) { +- if ((value & -1 << j * 7) == 0) { +- return j; +- } ++ //Paper start - Optimize VarInts ++ private static final int[] VARINT_EXACT_BYTE_LENGTHS = new int[33]; ++ static { ++ for (int i = 0; i <= 32; ++i) { ++ VARINT_EXACT_BYTE_LENGTHS[i] = (int) Math.ceil((31d - (i - 1)) / 7d); + } +- +- return 5; ++ VARINT_EXACT_BYTE_LENGTHS[32] = 1; // Special case for the number 0. ++ } ++ public static int getVarIntSize(int value) { ++ return VARINT_EXACT_BYTE_LENGTHS[Integer.numberOfLeadingZeros(value)]; // Paper - Optimize VarInts + } ++ //Paper end - Optimize VarInts + + public static int getVarLongSize(long value) { + for (int j = 1; j < 10; ++j) { +@@ -503,7 +506,22 @@ public class FriendlyByteBuf extends ByteBuf { + return new UUID(this.readLong(), this.readLong()); + } + ++ // Paper start - Optimize VarInts + public FriendlyByteBuf writeVarInt(int value) { ++ // Peel the one and two byte count cases explicitly as they are the most common VarInt sizes ++ // that the proxy will write, to improve inlining. ++ if ((value & (0xFFFFFFFF << 7)) == 0) { ++ writeByte(value); ++ } else if ((value & (0xFFFFFFFF << 14)) == 0) { ++ int w = (value & 0x7F | 0x80) << 8 | (value >>> 7); ++ writeShort(w); ++ } else { ++ writeVarInt_(value); ++ } ++ return this; ++ } ++ public FriendlyByteBuf writeVarInt_(int value) { ++ // Paper end - Optimize VarInts + while ((value & -128) != 0) { + this.writeByte(value & 127 | 128); + value >>>= 7; diff --git a/DivineMC/patches/server/0040-PaperPR-Fix-exact-choice-recipe-book-clicks.patch b/DivineMC/patches/server/0040-PaperPR-Fix-exact-choice-recipe-book-clicks.patch new file mode 100644 index 0000000..020cc11 --- /dev/null +++ b/DivineMC/patches/server/0040-PaperPR-Fix-exact-choice-recipe-book-clicks.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 14 May 2022 15:42:34 -0700 +Subject: [PATCH] PaperPR Fix exact choice recipe book clicks + +Taken from https://github.com/PaperMC/Paper/pull/7822 + +diff --git a/src/main/java/net/minecraft/world/entity/player/StackedContents.java b/src/main/java/net/minecraft/world/entity/player/StackedContents.java +index efee1a8e0e3ad566cd550e51d3e559c5a495889a..f75ff62be1630e3a86f917e18432769eb6d61abc 100644 +--- a/src/main/java/net/minecraft/world/entity/player/StackedContents.java ++++ b/src/main/java/net/minecraft/world/entity/player/StackedContents.java +@@ -37,8 +37,62 @@ public class StackedContents { + int i = getStackingIndex(stack); + int j = Math.min(maxCount, stack.getCount()); + this.put(i, j); ++ // Paper start ++ if (stack.hasTag()) { ++ this.put(getExactStackingIndex(stack), j); ++ } ++ } ++ ++ } ++ private static final net.minecraft.core.IdMap EXACT_MATCHES_ID_MAP = new net.minecraft.core.IdMap<>() { ++ private final java.util.concurrent.atomic.AtomicInteger idCounter = new java.util.concurrent.atomic.AtomicInteger(Registry.ITEM.size()); ++ private final it.unimi.dsi.fastutil.objects.Object2IntMap itemstackToId = new it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap<>(new it.unimi.dsi.fastutil.Hash.Strategy<>() { ++ @Override ++ public int hashCode(ItemStack o) { ++ return java.util.Objects.hash(o.getItem(), o.getTag()); ++ } ++ ++ @Override ++ public boolean equals(@Nullable ItemStack a, @Nullable ItemStack b) { ++ if (a == null || b == null) { ++ return false; ++ } ++ return ItemStack.isSameItemSameTags(a, b); ++ } ++ }); ++ private final it.unimi.dsi.fastutil.ints.Int2ObjectMap idToItemstack = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); ++ ++ @Override ++ public int getId(ItemStack value) { ++ if (!this.itemstackToId.containsKey(value)) { ++ final int id = this.idCounter.incrementAndGet(); ++ final ItemStack copy = value.copy(); ++ this.itemstackToId.put(copy, id); ++ this.idToItemstack.put(id, copy); ++ return id; ++ } ++ return this.itemstackToId.getInt(value); ++ } ++ ++ @Override ++ public @Nullable ItemStack byId(int index) { ++ return this.idToItemstack.get(index); ++ } ++ ++ @Override ++ public int size() { ++ return this.itemstackToId.size(); ++ } ++ ++ @Override ++ public java.util.Iterator iterator() { ++ return this.idToItemstack.values().iterator(); + } ++ }; + ++ public static int getExactStackingIndex(ItemStack stack) { ++ return EXACT_MATCHES_ID_MAP.getId(stack); ++ // Paper end + } + + public static int getStackingIndex(ItemStack stack) { +@@ -80,6 +134,12 @@ public class StackedContents { + } + + public static ItemStack fromStackingIndex(int itemId) { ++ // Paper start ++ if (itemId > Registry.ITEM.size()) { ++ final ItemStack stack = EXACT_MATCHES_ID_MAP.byId(itemId); ++ return stack == null ? ItemStack.EMPTY : stack.copy(); ++ } ++ // Paper end + return itemId == 0 ? ItemStack.EMPTY : new ItemStack(Item.byId(itemId)); + } + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 4fea1c9873b4dd9c9f21722adbb02200487caf3c..cd47b6882509888f7d34e95b4687ca7a9eab6caf 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -105,6 +105,7 @@ import org.bukkit.event.world.StructureGrowEvent; + + public final class ItemStack { + ++ public boolean isExactRecipeIngredient = false; // Paper + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(Registry.ITEM.byNameCodec().fieldOf("id").forGetter((itemstack) -> { + return itemstack.item; +diff --git a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java +index 895c0f1600139e340aa22a7c398978add56fa706..d5ced4c4ad354bbe6e6d256853de659923044299 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java ++++ b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java +@@ -54,7 +54,11 @@ public final class Ingredient implements Predicate { + if (this.itemStacks == null) { + this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((recipeitemstack_provider) -> { + return recipeitemstack_provider.getItems().stream(); +- }).distinct().toArray((i) -> { ++ // Paper start ++ }).distinct().peek(stack -> { ++ stack.isExactRecipeIngredient = this.exact; ++ }).toArray((i) -> { ++ // Paper end + return new ItemStack[i]; + }); + } +@@ -104,7 +108,13 @@ public final class Ingredient implements Predicate { + for (int j = 0; j < i; ++j) { + ItemStack itemstack = aitemstack[j]; + ++ // Paper start ++ if (itemstack.isExactRecipeIngredient) { ++ this.stackingIds.add(StackedContents.getExactStackingIndex(itemstack)); ++ } else { ++ // Paper end + this.stackingIds.add(StackedContents.getStackingIndex(itemstack)); ++ } // Paper + } + + this.stackingIds.sort(IntComparators.NATURAL_COMPARATOR); diff --git a/DivineMC/patches/server/0041-Fix-MC-238526.patch b/DivineMC/patches/server/0041-Fix-MC-238526.patch new file mode 100644 index 0000000..ebd211e --- /dev/null +++ b/DivineMC/patches/server/0041-Fix-MC-238526.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Mon, 8 Aug 2022 11:21:49 +0200 +Subject: [PATCH] Fix MC-238526 + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java +index 18389f46902bb9879ac6d734723e9a720724dc48..a50dff923743c9f916747abbf5c7d8c729ac8efe 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java +@@ -83,6 +83,6 @@ public abstract class WaterAnimal extends PathfinderMob { + i = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(i); + j = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(j); + // Paper end +- return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); ++ return ((reason == MobSpawnType.SPAWNER) || (pos.getY() >= j && pos.getY() <= i)) && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); // DivineMC + } + } diff --git a/DivineMC/patches/server/0042-lithium-replace-AI-goal-set-with-optimized-collectio.patch b/DivineMC/patches/server/0042-lithium-replace-AI-goal-set-with-optimized-collectio.patch new file mode 100644 index 0000000..270f64b --- /dev/null +++ b/DivineMC/patches/server/0042-lithium-replace-AI-goal-set-with-optimized-collectio.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sun, 12 Dec 2021 16:41:06 -0500 +Subject: [PATCH] lithium: replace AI goal set with optimized collection + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 0cc0d719e95e108263683b7a40f4ce3a8ca9465b..abc27a60986602e84eb556436a65b997617852a1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -12,6 +12,7 @@ import java.util.function.Supplier; + import java.util.stream.Stream; + import net.minecraft.util.profiling.ProfilerFiller; + import org.slf4j.Logger; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; // Lithium + + public class GoalSelector { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -27,7 +28,7 @@ public class GoalSelector { + } + }; + private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); +- public final Set availableGoals = Sets.newLinkedHashSet(); ++ public final Set availableGoals = new ObjectLinkedOpenHashSet<>(); // Lithium - replace AI goal set with optimized collection + private final Supplier profiler; + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector diff --git a/DivineMC/patches/server/0043-lithium-cached-hashcode.patch b/DivineMC/patches/server/0043-lithium-cached-hashcode.patch new file mode 100644 index 0000000..70a534f --- /dev/null +++ b/DivineMC/patches/server/0043-lithium-cached-hashcode.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jellysquid3 +Date: Wed, 15 Dec 2021 11:30:23 -0500 +Subject: [PATCH] lithium: cached hashcode + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 9aa3aca48d443f81201e93402ec413a26bd92cf4..1834470b549d8352317cf081173ff542c9faac1e 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -614,11 +614,18 @@ public class Block extends BlockBehaviour implements ItemLike { + private final BlockState first; + private final BlockState second; + private final Direction direction; ++ private int hash; // JettPack + + public BlockStatePairKey(BlockState self, BlockState other, Direction facing) { + this.first = self; + this.second = other; + this.direction = facing; ++ // JettPack start - lithium: cached_hashcode ++ int hash = this.first.hashCode(); ++ hash = 31 * hash + this.second.hashCode(); ++ hash = 31 * hash + this.direction.hashCode(); ++ this.hash = hash; ++ // JettPack end + } + + public boolean equals(Object object) { +@@ -634,11 +641,7 @@ public class Block extends BlockBehaviour implements ItemLike { + } + + public int hashCode() { +- int i = this.first.hashCode(); +- +- i = 31 * i + this.second.hashCode(); +- i = 31 * i + this.direction.hashCode(); +- return i; ++ return this.hash; // JettPack + } + } + } diff --git a/DivineMC/patches/server/0044-vmp-skip-entity-move-if-movement-is-zero.patch b/DivineMC/patches/server/0044-vmp-skip-entity-move-if-movement-is-zero.patch new file mode 100644 index 0000000..893fbe0 --- /dev/null +++ b/DivineMC/patches/server/0044-vmp-skip-entity-move-if-movement-is-zero.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Sun, 12 Dec 2021 17:19:00 -0500 +Subject: [PATCH] vmp: skip entity move if movement is zero + +Copyright (c) 2021-2022 ishland + +Original code by RelativityMC, licensed under MIT +You can find the original code on https://github.com/RelativityMC/VMP-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d96422f871c18303ce7ff7a182c685b0ddbfa04d..8a614fd335810b38c95f9f8b71f98b378893b985 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -299,6 +299,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + public float yRotO; + public float xRotO; + private AABB bb; ++ private boolean boundingBoxChanged = false; // DivineMC - vmp: skip entity move if movement is zero + public boolean onGround; + public boolean horizontalCollision; + public boolean verticalCollision; +@@ -1032,6 +1033,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + // Paper end - detailed watchdog information + + public void move(MoverType movementType, Vec3 movement) { ++ // DivineMC start - vmp: skip entity move if movement is zero ++ if (!boundingBoxChanged && movement.equals(Vec3.ZERO)) { ++ boundingBoxChanged = false; ++ return; ++ } ++ // DivineMC end + // Paper start - detailed watchdog information + io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main"); + synchronized (this.posLock) { +@@ -3755,6 +3762,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + } + + public final void setBoundingBox(AABB boundingBox) { ++ if (!this.bb.equals(boundingBox)) boundingBoxChanged = true; // DivineMC - vmp: skip entity move if movement is zero + // CraftBukkit start - block invalid bounding boxes + double minX = boundingBox.minX, + minY = boundingBox.minY, diff --git a/DivineMC/patches/server/0045-lithium-suffocation.patch b/DivineMC/patches/server/0045-lithium-suffocation.patch new file mode 100644 index 0000000..15f50a9 --- /dev/null +++ b/DivineMC/patches/server/0045-lithium-suffocation.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Fri, 8 Apr 2022 22:21:48 +0200 +Subject: [PATCH] lithium: suffocation + +Author: 2No2Name <2No2Name@web.de> + +Original license: GNU Lesser General Public License v3.0 +Original project: https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 8a614fd335810b38c95f9f8b71f98b378893b985..e1edcc723428717b5a03621fcf6072ca857f5c28 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2584,39 +2584,64 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + return !this.isRemoved(); + } + ++ // DivineMC start - lithium: suffocation ++ /** ++ * @author 2No2Name ++ * @reason Avoid stream code, use optimized chunk section iteration order ++ */ + public boolean isInWall() { ++ // [VanillaCopy] The whole method functionality including bug below. Cannot use ChunkAwareBlockCollisionSweeper due to ignoring of oversized blocks + if (this.noPhysics) { + return false; +- } else { +- float f = this.dimensions.width * 0.8F; +- AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f); +- +- BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos(); +- int minX = Mth.floor(axisalignedbb.minX); +- int minY = Mth.floor(axisalignedbb.minY); +- int minZ = Mth.floor(axisalignedbb.minZ); +- int maxX = Mth.floor(axisalignedbb.maxX); +- int maxY = Mth.floor(axisalignedbb.maxY); +- int maxZ = Mth.floor(axisalignedbb.maxZ); +- for (int fz = minZ; fz <= maxZ; ++fz) { +- for (int fx = minX; fx <= maxX; ++fx) { +- for (int fy = minY; fy <= maxY; ++fy) { +- net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)this.level.getChunkIfLoadedImmediately(fx >> 4, fz >> 4); +- if (chunk == null) { +- continue; ++ } ++ Vec3 position = this.getEyePosition(); ++ double suffocationRadius = Math.abs((double) (this.dimensions.width * 0.8f) / 2.0); ++ ++ double suffocationMinX = position.x - suffocationRadius; ++ double suffocationMinY = position.y - 5.0E-7; ++ double suffocationMinZ = position.z - suffocationRadius; ++ double suffocationMaxX = position.x + suffocationRadius; ++ double suffocationMaxY = position.y + 5.0E-7; ++ double suffocationMaxZ = position.z + suffocationRadius; ++ int minX = Mth.floor(suffocationMinX); ++ int minY = Mth.floor(suffocationMinY); ++ int minZ = Mth.floor(suffocationMinZ); ++ int maxX = Mth.floor(suffocationMaxX); ++ int maxY = Mth.floor(suffocationMaxY); ++ int maxZ = Mth.floor(suffocationMaxZ); ++ ++ Level level = this.level; ++ //skip getting blocks when the entity is outside the world height ++ //also avoids infinite loop with entities below y = Integer.MIN_VALUE (some modded servers do that) ++ if (level.getMinBuildHeight() > maxY || level.getMaxBuildHeight() < minY) { ++ return false; ++ } ++ ++ BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos(); ++ VoxelShape suffocationShape = null; ++ ++ for (int y = minY; y <= maxY; y++) { ++ for (int z = minZ; z <= maxZ; z++) { ++ for (int x = minX; x <= maxX; x++) { ++ blockposition.set(x, y, z); ++ BlockState iblockdata = level.getBlockState(blockposition); ++ if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition)) { ++ if (suffocationShape == null) { ++ suffocationShape = Shapes.create(new AABB(suffocationMinX, suffocationMinY, suffocationMinZ, suffocationMaxX, suffocationMaxY, suffocationMaxZ)); + } + +- BlockState iblockdata = chunk.getBlockStateFinal(fx, fy, fz); +- blockposition.set(fx, fy, fz); +- if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND)) { ++ if (Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition). ++ move(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ suffocationShape, BooleanOp.AND)) { + return true; + } + } + } + } +- return false; + } ++ return false; + } ++ // DivineMC end + + public InteractionResult interact(Player player, InteractionHand hand) { + return InteractionResult.PASS; diff --git a/DivineMC/patches/server/0046-lithium-ai.sensor.secondary_poi.patch b/DivineMC/patches/server/0046-lithium-ai.sensor.secondary_poi.patch new file mode 100644 index 0000000..eb5defb --- /dev/null +++ b/DivineMC/patches/server/0046-lithium-ai.sensor.secondary_poi.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Tue, 15 Mar 2022 07:14:26 +0100 +Subject: [PATCH] lithium: ai.sensor.secondary_poi + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java +index cb1d91f9fe98f21c2afbe3894dfd9bca3bdd3ba6..d3f1a26cf3b68d85b8d8daef73730f5c4af76cf1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java +@@ -22,6 +22,12 @@ public class SecondaryPoiSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, Villager entity) { ++ // DivineMC start - lithium: ai.sensor.secondary_poi ++ if (entity.getVillagerData().getProfession().secondaryPoi().isEmpty()) { ++ entity.getBrain().eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE); ++ return; ++ } ++ // DivineMC end + ResourceKey resourceKey = world.dimension(); + BlockPos blockPos = entity.blockPosition(); + List list = Lists.newArrayList(); diff --git a/DivineMC/patches/server/0047-lithium-store-gamerules-in-fastutil-hashmap.patch b/DivineMC/patches/server/0047-lithium-store-gamerules-in-fastutil-hashmap.patch new file mode 100644 index 0000000..21ee0bf --- /dev/null +++ b/DivineMC/patches/server/0047-lithium-store-gamerules-in-fastutil-hashmap.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Tue, 21 Dec 2021 09:43:24 -0500 +Subject: [PATCH] lithium: store gamerules in fastutil hashmap + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java +index 17e869074b8cf29a8c3280499a27e95179896750..97a5aec7da267b8b9f6d191c871316ccb89c448c 100644 +--- a/src/main/java/net/minecraft/world/level/GameRules.java ++++ b/src/main/java/net/minecraft/world/level/GameRules.java +@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerPlayer; + import org.slf4j.Logger; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // JettPack + + public class GameRules { + +@@ -111,14 +112,16 @@ public class GameRules { + + public GameRules() { + // Pufferfish start - use this to ensure gameruleArray is initialized +- this((Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { ++ // JettPack start - lithium: store gamerules in fastutil hashmap ++ this(new Object2ObjectOpenHashMap<>((Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { + return ((GameRules.Type) entry.getValue()).createRule(); +- }))); ++ })))); ++ // JettPack end + // Pufferfish end + } + + private GameRules(Map, GameRules.Value> rules) { +- this.rules = rules; ++ this.rules = new Object2ObjectOpenHashMap<>(rules); // JettPack - lithium: store gamerules in fastutil hashmap + + // Pufferfish start + int arraySize = rules.keySet().stream().mapToInt(key -> key.gameRuleIndex).max().orElse(-1) + 1; diff --git a/DivineMC/patches/server/0048-lithium-precompute-shape-arrays.patch b/DivineMC/patches/server/0048-lithium-precompute-shape-arrays.patch new file mode 100644 index 0000000..6a8af23 --- /dev/null +++ b/DivineMC/patches/server/0048-lithium-precompute-shape-arrays.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jellysquid3 +Date: Sat, 1 Jan 2022 03:59:58 -0500 +Subject: [PATCH] lithium: precompute shape arrays + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index 2217968eb5ecac0a2063cf1eae7d754d760e9f28..445f21c3764d148de937f558e3f087ae2006733d 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -41,7 +41,7 @@ public enum Direction implements StringRepresentable { + private final Direction.Axis axis; + private final Direction.AxisDirection axisDirection; + private final Vec3i normal; +- private static final Direction[] VALUES = values(); ++ public static final Direction[] VALUES = values(); // JettPack + private static final Direction[] BY_3D_DATA = Arrays.stream(VALUES).sorted(Comparator.comparingInt((direction) -> { + return direction.data3d; + })).toArray((i) -> { +diff --git a/src/main/java/net/minecraft/world/phys/shapes/CubePointRange.java b/src/main/java/net/minecraft/world/phys/shapes/CubePointRange.java +index a544db042c8d2ecec8d323770552c4f10ca758a6..c04da8da5b40430b61972bce32cec4e8c0370bac 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/CubePointRange.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/CubePointRange.java +@@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.doubles.AbstractDoubleList; + + public class CubePointRange extends AbstractDoubleList { + private final int parts; ++ private double scale; // JettPack - lithium: shapes.precompute_shape_arrays + + CubePointRange(int sectionCount) { + if (sectionCount <= 0) { +@@ -11,10 +12,11 @@ public class CubePointRange extends AbstractDoubleList { + } else { + this.parts = sectionCount; + } ++ this.scale = 1.0D / sectionCount; // JettPack - lithium: shapes.precompute_shape_arrays + } + + public double getDouble(int i) { +- return (double)i / (double)this.parts; ++ return i * this.scale; // JettPack - lithium: shapes.precompute_shape_arrays + } + + public int size() { +diff --git a/src/main/java/net/minecraft/world/phys/shapes/CubeVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/CubeVoxelShape.java +index 68e89dbd79171627046e89699057964e44c40e7d..959588962acb0196ec9f1cc2502e62117f6ccdc4 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/CubeVoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/CubeVoxelShape.java +@@ -3,15 +3,25 @@ package net.minecraft.world.phys.shapes; + import it.unimi.dsi.fastutil.doubles.DoubleList; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; ++import net.minecraft.world.phys.shapes.CubePointRange; // JettPack + + public final class CubeVoxelShape extends VoxelShape { ++ private DoubleList[] list; // JettPack - lithium: shapes.precompute_shape_arrays ++ + protected CubeVoxelShape(DiscreteVoxelShape voxels) { + super(voxels); ++ // JettPack start - lithium: shapes.precompute_shape_arrays ++ this.list = new DoubleList[Direction.VALUES.length]; ++ ++ for (Direction.Axis axis : Direction.Axis.VALUES) { ++ this.list[axis.ordinal()] = new CubePointRange(voxels.getSize(axis)); ++ } ++ // JettPack end + } + + @Override + protected DoubleList getCoords(Direction.Axis axis) { +- return new CubePointRange(this.shape.getSize(axis)); ++ return this.list[axis.ordinal()]; // JettPack - lithium: shapes.precompute_shape_arrays + } + + @Override diff --git a/DivineMC/patches/server/0049-lithium-entity.fast_elytra_check.patch b/DivineMC/patches/server/0049-lithium-entity.fast_elytra_check.patch new file mode 100644 index 0000000..6a83da1 --- /dev/null +++ b/DivineMC/patches/server/0049-lithium-entity.fast_elytra_check.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sat, 8 Jan 2022 04:32:41 +0100 +Subject: [PATCH] lithium: entity.fast_elytra_check + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c0e316582e085873c05a76c16e612eabd2e8cf2a..dbcabd230bd9bd070e157f35d098553f3ed06987 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3428,6 +3428,8 @@ public abstract class LivingEntity extends Entity { + } + + private void updateFallFlying() { ++ if (!this.isFallFlying()) return; // DivineMC ++ + boolean flag = this.getSharedFlag(7); + + if (flag && !this.onGround && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { diff --git a/DivineMC/patches/server/0050-lithium-entity.fast_hand_swing.patch b/DivineMC/patches/server/0050-lithium-entity.fast_hand_swing.patch new file mode 100644 index 0000000..b40ce55 --- /dev/null +++ b/DivineMC/patches/server/0050-lithium-entity.fast_hand_swing.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sun, 9 Jan 2022 06:03:28 +0100 +Subject: [PATCH] lithium: entity.fast_hand_swing + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index dbcabd230bd9bd070e157f35d098553f3ed06987..2cd8dfe953ac72f6be14557ab39d3cec1108499e 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2488,6 +2488,8 @@ public abstract class LivingEntity extends Entity { + } + + protected void updateSwingTime() { ++ if (!this.swinging && this.swingTime == 0) return; // DivineMC ++ + int i = this.getCurrentSwingDuration(); + + if (this.swinging) { diff --git a/DivineMC/patches/server/0051-lithium-entity.fast_powder_snow_check.patch b/DivineMC/patches/server/0051-lithium-entity.fast_powder_snow_check.patch new file mode 100644 index 0000000..f4a24fe --- /dev/null +++ b/DivineMC/patches/server/0051-lithium-entity.fast_powder_snow_check.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sat, 8 Jan 2022 03:51:28 +0100 +Subject: [PATCH] lithium: entity.fast_powder_snow_check + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 2cd8dfe953ac72f6be14557ab39d3cec1108499e..d6f7fd9dc4804e7565c89a9cbb0948f256559f03 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -569,11 +569,11 @@ public abstract class LivingEntity extends Entity { + } + + protected void tryAddFrost() { +- if (!this.getBlockStateOnLegacy().isAir()) { ++ //if (!this.getBlockStateOnLegacy().isAir()) { // DivineMC + int i = this.getTicksFrozen(); + + if (i > 0) { +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getBlockStateOnLegacy().isAir() ? null : this.getAttribute(Attributes.MOVEMENT_SPEED); // DivineMC + + if (attributemodifiable == null) { + return; +@@ -583,7 +583,7 @@ public abstract class LivingEntity extends Entity { + + attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION)); + } +- } ++ //} // DivineMC + + } + diff --git a/DivineMC/patches/server/0052-lithium-collections.attributes.patch b/DivineMC/patches/server/0052-lithium-collections.attributes.patch new file mode 100644 index 0000000..8cc6009 --- /dev/null +++ b/DivineMC/patches/server/0052-lithium-collections.attributes.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sun, 9 Jan 2022 17:53:11 +0100 +Subject: [PATCH] lithium: collections.attributes + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +index 9bce290eb0c2cfef4896a3f2076c80bf3d76bd56..ac56484b1bf19dabe4bdd5b25eafa4ac38f08cbe 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +@@ -16,11 +16,13 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.resources.ResourceLocation; + import org.slf4j.Logger; ++import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; // DivineMC ++import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // DivineMC + + public class AttributeMap { + private static final Logger LOGGER = LogUtils.getLogger(); +- private final Map attributes = Maps.newHashMap(); +- private final Set dirtyAttributes = Sets.newHashSet(); ++ private final Map attributes = new Reference2ReferenceOpenHashMap<>(0); // DivineMC ++ private final Set dirtyAttributes = new ReferenceOpenHashSet<>(0); // DivineMC + private final AttributeSupplier supplier; + private final java.util.function.Function createInstance; // Pufferfish + diff --git a/DivineMC/patches/server/0053-lithium-collections.entity_by_type.patch b/DivineMC/patches/server/0053-lithium-collections.entity_by_type.patch new file mode 100644 index 0000000..ab195eb --- /dev/null +++ b/DivineMC/patches/server/0053-lithium-collections.entity_by_type.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Fri, 7 Jan 2022 06:43:30 +0100 +Subject: [PATCH] lithium: collections.entity_by_type + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java +index 50a9f33aa31e9273c7c52d4bb2b02f0f884f7ba5..9698c093dd8c18a5a5a4b157c3799191841552e2 100644 +--- a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java ++++ b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java +@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterators; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; ++import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; // JettPack + import java.util.AbstractCollection; + import java.util.Collection; + import java.util.Collections; +@@ -13,7 +14,7 @@ import java.util.Map; + import java.util.stream.Collectors; + + public class ClassInstanceMultiMap extends AbstractCollection { +- private final Map, List> byClass = Maps.newHashMap(); ++ private final Map, List> byClass = new Reference2ReferenceOpenHashMap<>(); // JettPack + private final Class baseClass; + private final List allInstances = Lists.newArrayList(); + +@@ -58,7 +59,7 @@ public class ClassInstanceMultiMap extends AbstractCollection { + if (!this.baseClass.isAssignableFrom(type)) { + throw new IllegalArgumentException("Don't know how to search for " + type); + } else { +- List list = this.byClass.computeIfAbsent(type, (typeClass) -> { ++ List list = this.byClass.computeIfAbsent(type, (typeClass) -> { // JettPack - decomp fix + return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList()); + }); + return Collections.unmodifiableCollection(list); diff --git a/DivineMC/patches/server/0054-lithium-collections.entity_filtering.patch b/DivineMC/patches/server/0054-lithium-collections.entity_filtering.patch new file mode 100644 index 0000000..4280e8a --- /dev/null +++ b/DivineMC/patches/server/0054-lithium-collections.entity_filtering.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Sat, 8 Jan 2022 03:33:04 +0100 +Subject: [PATCH] lithium: collections.entity_filtering + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java +index 9698c093dd8c18a5a5a4b157c3799191841552e2..6f181fc878a96b09f126ea8d3b19ce3ee4588e19 100644 +--- a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java ++++ b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java +@@ -56,15 +56,32 @@ public class ClassInstanceMultiMap extends AbstractCollection { + } + + public Collection find(Class type) { +- if (!this.baseClass.isAssignableFrom(type)) { +- throw new IllegalArgumentException("Don't know how to search for " + type); +- } else { +- List list = this.byClass.computeIfAbsent(type, (typeClass) -> { // JettPack - decomp fix +- return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList()); +- }); +- return Collections.unmodifiableCollection(list); ++ // JettPack start ++ Collection collection = this.byClass.get(type); ++ ++ if (collection == null) { ++ collection = this.createAllOfType(type); + } ++ ++ return (Collection) Collections.unmodifiableCollection(collection); ++ // JettPack end ++ } ++ ++ // JettPack start ++ private Collection createAllOfType(Class type) { ++ List list = new java.util.ArrayList<>(); ++ ++ for (T allElement : this.allInstances) { ++ if (type.isInstance(allElement)) { ++ list.add(allElement); ++ } ++ } ++ ++ this.byClass.put(type, list); ++ ++ return list; + } ++ // JettPack end + + @Override + public Iterator iterator() { diff --git a/DivineMC/patches/server/0055-lithium-chunk.serialization.patch b/DivineMC/patches/server/0055-lithium-chunk.serialization.patch new file mode 100644 index 0000000..073c398 --- /dev/null +++ b/DivineMC/patches/server/0055-lithium-chunk.serialization.patch @@ -0,0 +1,458 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jellysquid3 +Date: Mon, 10 Jan 2022 15:27:58 -0500 +Subject: [PATCH] lithium: chunk.serialization + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java +new file mode 100644 +index 0000000000000000000000000000000000000000..16debe176798f316c122e8e7aef2b50ecb9883a6 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java +@@ -0,0 +1,189 @@ ++package me.jellysquid.mods.lithium.common.world.chunk; ++ ++import com.google.common.collect.ImmutableList; ++import it.unimi.dsi.fastutil.HashCommon; ++import it.unimi.dsi.fastutil.objects.Reference2IntMap; ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; ++import java.util.Arrays; ++import java.util.List; ++import java.util.function.Predicate; ++import net.minecraft.core.IdMap; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.world.level.chunk.Palette; ++import net.minecraft.world.level.chunk.PaletteResize; ++ ++import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; ++ ++/** ++ * Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling ++ * {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. ++ */ ++public class LithiumHashPalette implements Palette { ++ private static final int ABSENT_VALUE = -1; ++ ++ private final IdMap idList; ++ private final PaletteResize resizeHandler; ++ private final int indexBits; ++ ++ private final Reference2IntMap table; ++ private T[] entries; ++ private int size = 0; ++ ++ public LithiumHashPalette(IdMap idList, PaletteResize resizeHandler, int indexBits, T[] entries, Reference2IntMap table, int size) { ++ this.idList = idList; ++ this.resizeHandler = resizeHandler; ++ this.indexBits = indexBits; ++ this.entries = entries; ++ this.table = table; ++ this.size = size; ++ } ++ ++ public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler, List list) { ++ this(idList, bits, resizeHandler); ++ ++ for (T t : list) { ++ this.addEntry(t); ++ } ++ } ++ ++ @SuppressWarnings("unchecked") ++ public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler) { ++ this.idList = idList; ++ this.indexBits = bits; ++ this.resizeHandler = resizeHandler; ++ ++ int capacity = 1 << bits; ++ ++ this.entries = (T[]) new Object[capacity]; ++ this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); ++ this.table.defaultReturnValue(ABSENT_VALUE); ++ } ++ ++ @Override ++ public int idFor(T obj) { ++ int id = this.table.getInt(obj); ++ ++ if (id == ABSENT_VALUE) { ++ id = this.computeEntry(obj); ++ } ++ ++ return id; ++ } ++ ++ @Override ++ public boolean maybeHas(Predicate predicate) { ++ for (int i = 0; i < this.size; ++i) { ++ if (predicate.test(this.entries[i])) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ private int computeEntry(T obj) { ++ int id = this.addEntry(obj); ++ ++ if (id >= 1 << this.indexBits) { ++ if (this.resizeHandler == null) { ++ throw new IllegalStateException("Cannot grow"); ++ } else { ++ id = this.resizeHandler.onResize(this.indexBits + 1, obj); ++ } ++ } ++ ++ return id; ++ } ++ ++ private int addEntry(T obj) { ++ int nextId = this.size; ++ ++ if (nextId >= this.entries.length) { ++ this.resize(this.size); ++ } ++ ++ this.table.put(obj, nextId); ++ this.entries[nextId] = obj; ++ ++ this.size++; ++ ++ return nextId; ++ } ++ ++ private void resize(int neededCapacity) { ++ this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); ++ } ++ ++ @Override ++ public T valueFor(int id) { ++ T[] entries = this.entries; ++ ++ if (id >= 0 && id < entries.length) { ++ return entries[id]; ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public void read(FriendlyByteBuf buf) { ++ this.clear(); ++ ++ int entryCount = buf.readVarInt(); ++ ++ for (int i = 0; i < entryCount; ++i) { ++ this.addEntry(this.idList.byId(buf.readVarInt())); ++ } ++ } ++ ++ @Override ++ public void write(FriendlyByteBuf buf) { ++ int size = this.size; ++ buf.writeVarInt(size); ++ ++ for (int i = 0; i < size; ++i) { ++ buf.writeVarInt(this.idList.getId(this.valueFor(i))); ++ } ++ } ++ ++ @Override ++ public int getSerializedSize() { ++ int size = FriendlyByteBuf.getVarIntSize(this.size); ++ ++ for (int i = 0; i < this.size; ++i) { ++ size += FriendlyByteBuf.getVarIntSize(this.idList.getId(this.valueFor(i))); ++ } ++ ++ return size; ++ } ++ ++ @Override ++ public int getSize() { ++ return this.size; ++ } ++ ++ @Override ++ public Palette copy() { ++ return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); ++ } ++ ++ private void clear() { ++ Arrays.fill(this.entries, null); ++ this.table.clear(); ++ this.size = 0; ++ } ++ ++ public List getElements() { ++ ImmutableList.Builder builder = new ImmutableList.Builder<>(); ++ for (T entry : this.entries) { ++ if (entry != null) { ++ builder.add(entry); ++ } ++ } ++ return builder.build(); ++ } ++ ++ public static Palette create(int bits, IdMap idList, PaletteResize listener, List list) { ++ return new LithiumHashPalette<>(idList, bits, listener, list); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 106610ccc74b70b557b01c61262d56c4f1147acf..fc986f02290fbe20246022072944980f35dd200c 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -1,6 +1,7 @@ + package net.minecraft.util; + + import java.util.function.IntConsumer; ++import net.minecraft.world.level.chunk.Palette; // JettPack + + public interface BitStorage { + int getAndSet(int index, int value); +@@ -31,4 +32,6 @@ public interface BitStorage { + + } + // Paper end ++ ++ void compact(Palette srcPalette, Palette dstPalette, short[] out); // JettPack - lithium: chunk.serialization + } +diff --git a/src/main/java/net/minecraft/util/SimpleBitStorage.java b/src/main/java/net/minecraft/util/SimpleBitStorage.java +index 36e33923bf48e56c743ed043bcbc66bc32f0422f..0272dee738e86e066108f5cc3729136335d8197e 100644 +--- a/src/main/java/net/minecraft/util/SimpleBitStorage.java ++++ b/src/main/java/net/minecraft/util/SimpleBitStorage.java +@@ -2,6 +2,7 @@ package net.minecraft.util; + + import java.util.function.IntConsumer; + import javax.annotation.Nullable; ++import net.minecraft.world.level.chunk.Palette; // JettPack + import org.apache.commons.lang3.Validate; + + public class SimpleBitStorage implements BitStorage { +@@ -201,4 +202,44 @@ public class SimpleBitStorage implements BitStorage { + super(message); + } + } ++ ++ // JettPack start - lithium: chunk.serialization ++ @Override ++ public void compact(Palette srcPalette, Palette dstPalette, short[] out) { ++ if (this.size >= Short.MAX_VALUE) { ++ throw new IllegalStateException("Array too large"); ++ } ++ ++ if (this.size != out.length) { ++ throw new IllegalStateException("Array size mismatch"); ++ } ++ ++ short[] mappings = new short[(int) (this.mask + 1)]; ++ ++ int idx = 0; ++ ++ for (long word : this.data) { ++ long bits = word; ++ ++ for (int elementIdx = 0; elementIdx < this.valuesPerLong; ++elementIdx) { ++ int value = (int) (bits & this.mask); ++ int remappedId = mappings[value]; ++ ++ if (remappedId == 0) { ++ remappedId = dstPalette.idFor(srcPalette.valueFor(value)) + 1; ++ mappings[value] = (short) remappedId; ++ } ++ ++ out[idx] = (short) (remappedId - 1); ++ bits >>= this.bits; ++ ++ ++idx; ++ ++ if (idx >= this.size) { ++ return; ++ } ++ } ++ } ++ } ++ // JettPack end + } +diff --git a/src/main/java/net/minecraft/util/ZeroBitStorage.java b/src/main/java/net/minecraft/util/ZeroBitStorage.java +index 97c744508cc535418eba65fa722859c81c22d647..a2ea0a2864b9c4f847f1a14ffc0900e67c18f9ee 100644 +--- a/src/main/java/net/minecraft/util/ZeroBitStorage.java ++++ b/src/main/java/net/minecraft/util/ZeroBitStorage.java +@@ -2,6 +2,7 @@ package net.minecraft.util; + + import java.util.Arrays; + import java.util.function.IntConsumer; ++import net.minecraft.world.level.chunk.Palette; // JettPack + import org.apache.commons.lang3.Validate; + + public class ZeroBitStorage implements BitStorage { +@@ -72,4 +73,6 @@ public class ZeroBitStorage implements BitStorage { + public BitStorage copy() { + return this; + } ++ ++ @Override public void compact(Palette srcPalette, Palette dstPalette, short[] out) {} // JettPack + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java +index acae3eb30e0689048937f479dc3070f0688abdad..9c2b79655f2c63a208c7087d5d897db0fb23f697 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java +@@ -1,5 +1,5 @@ + package net.minecraft.world.level.chunk; + +-interface PaletteResize { ++public interface PaletteResize { // JettPack - make public + int onResize(int newBits, T object); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 7908360dd47937b2cb702e381802b7b278a5198e..5f578da4a7251b17d6a12821a3cd090e66b52a8a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -22,8 +22,23 @@ import net.minecraft.util.Mth; + import net.minecraft.util.SimpleBitStorage; + import net.minecraft.util.ThreadingDetector; + import net.minecraft.util.ZeroBitStorage; ++import me.jellysquid.mods.lithium.common.world.chunk.LithiumHashPalette; // JettPack + + public class PalettedContainer implements PaletteResize, PalettedContainerRO { ++ // JettPack start - lithium: chunk.serialization ++ private static final ThreadLocal CACHED_ARRAY_4096 = ThreadLocal.withInitial(() -> new short[4096]); ++ private static final ThreadLocal CACHED_ARRAY_64 = ThreadLocal.withInitial(() -> new short[64]); ++ private Optional asOptional(long[] data) { ++ return Optional.of(Arrays.stream(data)); ++ } ++ private short[] getOrCreate(int size) { ++ return switch (size) { ++ case 64 -> CACHED_ARRAY_64.get(); ++ case 4096 -> CACHED_ARRAY_4096.get(); ++ default -> new short[size]; ++ }; ++ } ++ // JettPack end + private static final int MIN_PALETTE_BITS = 0; + private final PaletteResize dummyPaletteResize = (newSize, added) -> { + return 0; +@@ -299,30 +314,54 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + public synchronized PalettedContainerRO.PackedData pack(IdMap idList, PalettedContainer.Strategy paletteProvider) { // Paper - synchronize + this.acquire(); + +- PalettedContainerRO.PackedData var12; ++ // JettPack start - lithium: chunk.serialization ++ Optional data = Optional.empty(); ++ List elements = null; + try { +- HashMapPalette hashMapPalette = new HashMapPalette<>(idList, this.data.storage.getBits(), this.dummyPaletteResize); +- int i = paletteProvider.size(); +- int[] is = new int[i]; +- this.data.storage.unpack(is); +- swapPalette(is, (id) -> { +- return hashMapPalette.idFor(this.data.palette.valueFor(id)); +- }); +- int j = paletteProvider.calculateBitsForSerialization(idList, hashMapPalette.getSize()); +- Optional optional; +- if (j != 0) { +- SimpleBitStorage simpleBitStorage = new SimpleBitStorage(j, i, is); +- optional = Optional.of(Arrays.stream(simpleBitStorage.getRaw())); +- } else { +- optional = Optional.empty(); ++ // The palette that will be serialized ++ LithiumHashPalette hashPalette = null; ++ ++ final Palette palette = this.data.palette(); ++ final BitStorage storage = this.data.storage(); ++ if (storage instanceof ZeroBitStorage || palette.getSize() == 1) { ++ // If the palette only contains one entry, don't attempt to repack it. ++ elements = List.of(palette.valueFor(0)); ++ } else if (palette instanceof LithiumHashPalette lithiumHashPalette) { ++ hashPalette = lithiumHashPalette; + } + +- var12 = new PalettedContainerRO.PackedData<>(hashMapPalette.getEntries(), optional); ++ if (elements == null) { ++ LithiumHashPalette compactedPalette = new LithiumHashPalette<>(idList, storage.getBits(), this.dummyPaletteResize); ++ short[] array = this.getOrCreate(paletteProvider.size()); ++ ++ storage.compact(this.data.palette(), compactedPalette, array); ++ ++ // If the palette didn't change during compaction, do a simple copy of the data array ++ if (hashPalette != null && hashPalette.getSize() == compactedPalette.getSize() && storage.getBits() == paletteProvider.calculateBitsForSerialization(idList, hashPalette.getSize())) { // paletteSize can de-sync from palette - see https://github.com/CaffeineMC/lithium-fabric/issues/279 ++ data = this.asOptional(storage.getRaw().clone()); ++ elements = hashPalette.getElements(); ++ } else { ++ int bits = paletteProvider.calculateBitsForSerialization(idList, compactedPalette.getSize()); ++ if (bits != 0) { ++ // Re-pack the integer array as the palette has changed size ++ SimpleBitStorage copy = new SimpleBitStorage(bits, array.length); ++ for (int i = 0; i < array.length; ++i) { ++ copy.set(i, array[i]); ++ } ++ ++ // We don't need to clone the data array as we are the sole owner of it ++ data = this.asOptional(copy.getRaw()); ++ } ++ ++ elements = compactedPalette.getElements(); ++ } ++ } + } finally { + this.release(); + } + +- return var12; ++ return new PalettedContainerRO.PackedData<>(elements, data); ++ // JettPack end + } + + private static void swapPalette(int[] is, IntUnaryOperator applier) { +@@ -362,17 +401,37 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + + @Override + public void count(PalettedContainer.CountConsumer counter) { +- if (this.data.palette.getSize() == 1) { +- counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize()); +- } else { +- Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap(); +- this.data.storage.getAll((key) -> { +- int2IntOpenHashMap.addTo(key, 1); +- }); +- int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> { +- counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue()); +- }); ++ // JettPack start - lithium: chunk.serialization ++ int len = this.data.palette().getSize(); ++ ++ // Do not allocate huge arrays if we're using a large palette ++ if (len > 4096) { ++ // VanillaCopy ++ if (this.data.palette.getSize() == 1) { ++ counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize()); ++ } else { ++ Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap(); ++ this.data.storage.getAll((key) -> { ++ int2IntOpenHashMap.addTo(key, 1); ++ }); ++ int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> { ++ counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue()); ++ }); ++ } ++ } ++ ++ short[] counts = new short[len]; ++ ++ this.data.storage().getAll(i -> counts[i]++); ++ ++ for (int i = 0; i < counts.length; i++) { ++ T obj = this.data.palette().valueFor(i); ++ ++ if (obj != null) { ++ counter.accept(obj, counts[i]); ++ } + } ++ // JettPack end + } + + static record Configuration(Palette.Factory factory, int bits) { diff --git a/DivineMC/patches/server/0056-lithium-cache-iterate-outwards.patch b/DivineMC/patches/server/0056-lithium-cache-iterate-outwards.patch new file mode 100644 index 0000000..8664b26 --- /dev/null +++ b/DivineMC/patches/server/0056-lithium-cache-iterate-outwards.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Thu, 13 Jan 2022 15:38:29 -0500 +Subject: [PATCH] lithium: cache iterate outwards + +Original code by the PR below, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric/pull/123 (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a5d3aa309d3fdaab9e0fea2dfb91a080a3ac1193 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java +@@ -0,0 +1,71 @@ ++package me.jellysquid.mods.lithium.common.cached_blockpos_iteration; ++ ++import it.unimi.dsi.fastutil.longs.LongArrayList; ++import it.unimi.dsi.fastutil.longs.LongList; ++import java.util.Iterator; ++import java.util.Random; ++import java.util.concurrent.ConcurrentHashMap; ++import net.minecraft.core.BlockPos; ++ ++/** ++ * @author 2No2Name, original implemenation by SuperCoder7979 and Gegy1000 ++ */ ++public class IterateOutwardsCache { ++ //POS_ZERO must not be replaced with BlockPos.ORIGIN, otherwise iterateOutwards at BlockPos.ORIGIN will not use the cache ++ public static final BlockPos POS_ZERO = new BlockPos(0,0,0); ++ ++ ++ private final ConcurrentHashMap table; ++ private final int capacity; ++ private final Random random; ++ ++ public IterateOutwardsCache(int capacity) { ++ this.capacity = capacity; ++ this.table = new ConcurrentHashMap<>(31); ++ this.random = new Random(); ++ } ++ ++ private void fillPositionsWithIterateOutwards(LongList entry, int xRange, int yRange, int zRange) { ++ // Add all positions to the cached list ++ for (BlockPos pos : BlockPos.withinManhattan(POS_ZERO, xRange, yRange, zRange)) { ++ entry.add(pos.asLong()); ++ } ++ } ++ ++ public LongList getOrCompute(int xRange, int yRange, int zRange) { ++ long key = BlockPos.asLong(xRange, yRange, zRange); ++ ++ LongArrayList entry = this.table.get(key); ++ if (entry != null) { ++ return entry; ++ } ++ ++ // Cache miss: compute and store ++ entry = new LongArrayList(128); ++ ++ this.fillPositionsWithIterateOutwards(entry, xRange, yRange, zRange); ++ ++ //decrease the array size, as of now it won't be modified anymore anyways ++ entry.trim(); ++ ++ //this might overwrite an entry as the same entry could have been computed and added during this thread's computation ++ //we do not use computeIfAbsent, as it can delay other threads for too long ++ Object previousEntry = this.table.put(key, entry); ++ ++ ++ if (previousEntry == null && this.table.size() > this.capacity) { ++ //prevent a memory leak by randomly removing about 1/8th of the elements when the exceed the desired capacity is exceeded ++ final Iterator iterator = this.table.keySet().iterator(); ++ //prevent an unlikely infinite loop caused by another thread filling the table concurrently using counting ++ for (int i = -this.capacity; iterator.hasNext() && i < 5; i++) { ++ Long key2 = iterator.next(); ++ //random is not threadsafe, but it doesn't matter here, because we don't need quality random numbers ++ if (this.random.nextInt(8) == 0 && key2 != key) { ++ iterator.remove(); ++ } ++ } ++ } ++ ++ return entry; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..493661ff3ac7247b68b7b02784b09b0eaf88fc52 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java +@@ -0,0 +1,46 @@ ++package me.jellysquid.mods.lithium.common.cached_blockpos_iteration; ++ ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongList; ++import java.util.Iterator; ++import net.minecraft.core.BlockPos; ++ ++/** ++ * @author 2No2Name ++ */ ++public class LongList2BlockPosMutableIterable implements Iterable { ++ ++ private final LongList positions; ++ private final int xOffset, yOffset, zOffset; ++ ++ public LongList2BlockPosMutableIterable(BlockPos offset, LongList posList) { ++ this.xOffset = offset.getX(); ++ this.yOffset = offset.getY(); ++ this.zOffset = offset.getZ(); ++ this.positions = posList; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ private final LongIterator it = LongList2BlockPosMutableIterable.this.positions.iterator(); ++ private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ ++ @Override ++ public boolean hasNext() { ++ return it.hasNext(); ++ } ++ ++ @Override ++ public net.minecraft.core.BlockPos next() { ++ long nextPos = this.it.nextLong(); ++ return this.pos.set( ++ LongList2BlockPosMutableIterable.this.xOffset + BlockPos.getX(nextPos), ++ LongList2BlockPosMutableIterable.this.yOffset + BlockPos.getY(nextPos), ++ LongList2BlockPosMutableIterable.this.zOffset + BlockPos.getZ(nextPos)); ++ } ++ }; ++ } ++ ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 153451ecd5b3c8e8ecb2d5ec91ccd582d4300899..4487752469f9ab95e9d2aeb76a9627dc02095d76 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -18,6 +18,12 @@ import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++// JettPack start ++import it.unimi.dsi.fastutil.longs.LongList; ++import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache; ++import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.LongList2BlockPosMutableIterable; ++import static me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache.POS_ZERO; ++// JettPack end + + @Immutable + public class BlockPos extends Vec3i { +@@ -284,7 +290,18 @@ public class BlockPos extends Vec3i { + }; + } + ++ // JettPack start - lithium: cached iterate outwards ++ private static final IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new IterateOutwardsCache(50); ++ private static final LongList HOGLIN_PIGLIN_CACHE = ITERATE_OUTWARDS_CACHE.getOrCompute(8, 4, 8); ++ // JettPack end ++ + public static Iterable withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) { ++ // JettPack start - lithium: cached iterate outwards ++ if (center != POS_ZERO) { ++ final LongList positions = rangeX == 8 && rangeY == 4 && rangeZ == 8 ? HOGLIN_PIGLIN_CACHE : ITERATE_OUTWARDS_CACHE.getOrCompute(rangeX, rangeY, rangeZ); ++ return new LongList2BlockPosMutableIterable(center, positions); ++ } ++ // JettPack end + int i = rangeX + rangeY + rangeZ; + // Paper start - rename variables to fix conflict with anonymous class (remap fix) + int centerX = center.getX(); diff --git a/DivineMC/patches/server/0057-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch b/DivineMC/patches/server/0057-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch new file mode 100644 index 0000000..e4e7b11 --- /dev/null +++ b/DivineMC/patches/server/0057-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Sat, 12 Mar 2022 16:03:35 +0100 +Subject: [PATCH] vmp: use linked map for entity trackers for faster iteration + +Copyright (c) 2021-2022 ishland + +Original code by RelativityMC, licensed under MIT +You can find the original code on https://github.com/RelativityMC/VMP-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 9976630fad886392057f642e84f919f0b95cc040..c01c22b6fda9e36a2336a992c760b813b71469ce 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -111,6 +111,7 @@ import org.bukkit.entity.Player; + // CraftBukkit end + + import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper ++import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; // DivineMC - vmp: use linked map for entity trackers for faster iteration + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + +@@ -291,7 +292,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper - rewrite chunk system + this.tickingGenerated = new AtomicInteger(); + this.playerMap = new PlayerMap(); +- this.entityMap = new Int2ObjectOpenHashMap(); ++ this.entityMap = new Int2ObjectLinkedOpenHashMap<>(); // DivineMC - vmp: use linked map for entity trackers for faster iteration + this.chunkTypeCache = new Long2ByteOpenHashMap(); + this.chunkSaveCooldowns = new Long2LongOpenHashMap(); + this.unloadQueue = Queues.newConcurrentLinkedQueue(); diff --git a/DivineMC/patches/server/0058-lithium-block.moving_block_shapes.patch b/DivineMC/patches/server/0058-lithium-block.moving_block_shapes.patch new file mode 100644 index 0000000..c230043 --- /dev/null +++ b/DivineMC/patches/server/0058-lithium-block.moving_block_shapes.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <2No2Name@web.de> +Date: Fri, 21 Jan 2022 08:41:34 -0500 +Subject: [PATCH] lithium: block.moving_block_shapes + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 7c59d44a3bafdc65f453d77ff3e25cffb742ad6c..636721a111cad13e7329f1157981ca03a8f339b3 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -52,6 +52,74 @@ public class PistonMovingBlockEntity extends BlockEntity { + this.extending = extending; + this.isSourcePiston = source; + } ++ // JettPack start - lithium: block.moving_block_shapes ++ private static final VoxelShape[] PISTON_BASE_WITH_MOVING_HEAD_SHAPES = precomputePistonBaseWithMovingHeadShapes(); ++ ++ /** ++ * We cache the offset and simplified VoxelShapes that are otherwise constructed on every call of getCollisionShape. ++ * For each offset direction and distance (6 directions, 2 distances each, and no direction with 0 distance) we ++ * store the offset and simplified VoxelShapes in the original VoxelShape when they are accessed the first time. ++ * We use safe publication, because both the Render and Server thread are using the cache. ++ * ++ * @param blockShape the original shape, must not be modified after passing it as an argument to this method ++ * @param offset the offset distance ++ * @param direction the offset direction ++ * @return blockShape offset and simplified ++ */ ++ private static VoxelShape getOffsetAndSimplified(VoxelShape blockShape, float offset, Direction direction) { ++ VoxelShape offsetSimplifiedShape = blockShape.getOffsetSimplifiedShape(offset, direction); ++ if (offsetSimplifiedShape == null) { ++ //create the offset shape and store it for later use ++ offsetSimplifiedShape = blockShape.move(direction.getStepX() * offset, direction.getStepY() * offset, direction.getStepZ() * offset).optimize(); ++ blockShape.setShape(offset, direction, offsetSimplifiedShape); ++ } ++ return offsetSimplifiedShape; ++ } ++ ++ /** ++ * Precompute all 18 possible configurations for the merged piston base and head shape. ++ * ++ * @return The array of the merged VoxelShapes, indexed by {@link PistonBlockEntityMixin#getIndexForMergedShape(float, Direction)} ++ */ ++ private static VoxelShape[] precomputePistonBaseWithMovingHeadShapes() { ++ float[] offsets = {0f, 0.5f, 1f}; ++ Direction[] directions = Direction.values(); ++ ++ VoxelShape[] mergedShapes = new VoxelShape[offsets.length * directions.length]; ++ ++ for (Direction facing : directions) { ++ VoxelShape baseShape = Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.EXTENDED, true) ++ .setValue(PistonBaseBlock.FACING, facing).getCollisionShape(null, null); ++ for (float offset : offsets) { ++ //this cache is only required for the merged piston head + base shape. ++ //this shape is only used when !this.extending ++ //here: isShort = this.extending != 1.0F - this.progress < 0.25F can be simplified to: ++ //isShort = f < 0.25F , because f = getAmountExtended(this.progress) can be simplified to f == 1.0F - this.progress ++ //therefore isShort is dependent on the offset: ++ boolean isShort = offset < 0.25f; ++ ++ VoxelShape headShape = (Blocks.PISTON_HEAD.defaultBlockState().setValue(PistonHeadBlock.FACING, facing)) ++ .setValue(PistonHeadBlock.SHORT, isShort).getCollisionShape(null, null); ++ ++ VoxelShape offsetHead = headShape.move(facing.getStepX() * offset, ++ facing.getStepY() * offset, ++ facing.getStepZ() * offset); ++ mergedShapes[getIndexForMergedShape(offset, facing)] = Shapes.or(baseShape, offsetHead); ++ } ++ ++ } ++ ++ return mergedShapes; ++ } ++ ++ private static int getIndexForMergedShape(float offset, Direction direction) { ++ if (offset != 0f && offset != 0.5f && offset != 1f) { ++ return -1; ++ } ++ //shape of offset 0 is still dependent on the direction, due to piston head and base being directional blocks ++ return (int) (2 * offset) + (3 * direction.get3DDataValue()); ++ } ++ // JettPack end + + @Override + public CompoundTag getUpdateTag() { +@@ -351,10 +419,27 @@ public class PistonMovingBlockEntity extends BlockEntity { + } + + float f = this.getExtendedProgress(this.progress); ++ // JettPack start - lithium: block.moving_block_shapes ++ if (this.extending || !this.isSourcePiston || !(this.movedState.getBlock() instanceof PistonBaseBlock)) { ++ //here voxelShape2.isEmpty() is guaranteed, vanilla code would call union() which calls simplify() ++ VoxelShape blockShape = blockState.getCollisionShape(world, pos); ++ ++ //we cache the simplified shapes, as the simplify() method costs a lot of CPU time and allocates several objects ++ VoxelShape offsetAndSimplified = getOffsetAndSimplified(blockShape, Math.abs(f), f < 0f ? this.direction.getOpposite() : this.direction); ++ return offsetAndSimplified; ++ } else { ++ //retracting piston heads have to act like their base as well, as the base block is replaced with the moving block ++ //f >= 0f is guaranteed (assuming no other mod interferes) ++ int index = getIndexForMergedShape(f, this.direction); ++ return PISTON_BASE_WITH_MOVING_HEAD_SHAPES[index]; ++ } ++ /* + double d = (double)((float)this.direction.getStepX() * f); + double e = (double)((float)this.direction.getStepY() * f); + double g = (double)((float)this.direction.getStepZ() * f); + return Shapes.or(voxelShape, blockState.getCollisionShape(world, pos).move(d, e, g)); ++ */ ++ // JettPack end + } + } + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 2182afd1b95acf14c55bddfeec17dae0a63e1f00..461ac9a464c4a66e302798032c6019bb60f6862b 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -26,6 +26,44 @@ public abstract class VoxelShape { + } + // Paper end + ++ // JettPack start - lithium: block.moving_block_shapes ++ private volatile VoxelShape[] offsetAndSimplified; ++ ++ public void setShape(float offset, Direction direction, VoxelShape offsetShape) { ++ if (offsetShape == null) { ++ throw new IllegalArgumentException("offsetShape must not be null!"); ++ } ++ int index = getIndexForOffsetSimplifiedShapes(offset, direction); ++ VoxelShape[] offsetAndSimplifiedShapes = this.offsetAndSimplified; ++ if (offsetAndSimplifiedShapes == null) { ++ offsetAndSimplifiedShapes = new VoxelShape[1 + 2 * 6]; ++ } else { ++ offsetAndSimplifiedShapes = offsetAndSimplifiedShapes.clone(); ++ } ++ offsetAndSimplifiedShapes[index] = offsetShape; ++ this.offsetAndSimplified = offsetAndSimplifiedShapes; ++ } ++ ++ public VoxelShape getOffsetSimplifiedShape(float offset, Direction direction) { ++ VoxelShape[] offsetAndSimplified = this.offsetAndSimplified; ++ if (offsetAndSimplified == null) { ++ return null; ++ } ++ int index = getIndexForOffsetSimplifiedShapes(offset, direction); ++ return offsetAndSimplified[index]; ++ } ++ ++ private static int getIndexForOffsetSimplifiedShapes(float offset, Direction direction) { ++ if (offset != 0f && offset != 0.5f && offset != 1f) { ++ throw new IllegalArgumentException("offset must be one of {0f, 0.5f, 1f}"); ++ } ++ if (offset == 0f) { ++ return 0; //can treat offsetting by 0 in all directions the same ++ } ++ return (int) (2 * offset) + 2 * direction.get3DDataValue(); ++ } ++ // JettPack end ++ + protected VoxelShape(DiscreteVoxelShape voxels) { // Paper - protected + this.shape = voxels; + } diff --git a/DivineMC/patches/server/0059-Skip-cloning-loot-parameters.patch b/DivineMC/patches/server/0059-Skip-cloning-loot-parameters.patch new file mode 100644 index 0000000..c18553a --- /dev/null +++ b/DivineMC/patches/server/0059-Skip-cloning-loot-parameters.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAY +Date: Fri, 11 Nov 2022 16:53:54 +0300 +Subject: [PATCH] Skip cloning loot parameters + + +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index 2c01231dcfbb992c9d2f034fcfd4af52fe8ac265..7ed9ca7d220c2af764a2febe2c1d7cb208593074 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -45,7 +45,7 @@ public class Advancement { + public Advancement(ResourceLocation id, @Nullable Advancement parent, @Nullable DisplayInfo display, AdvancementRewards rewards, Map criteria, String[][] requirements) { + this.id = id; + this.display = display; +- this.criteria = ImmutableMap.copyOf(criteria); ++ this.criteria = java.util.Collections.unmodifiableMap(criteria); // DivineMC - Skip cloning loot parameters + this.parent = parent; + this.rewards = rewards; + this.requirements = requirements; diff --git a/DivineMC/patches/server/0060-lithium-gen.patch b/DivineMC/patches/server/0060-lithium-gen.patch new file mode 100644 index 0000000..854ea2f --- /dev/null +++ b/DivineMC/patches/server/0060-lithium-gen.patch @@ -0,0 +1,243 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> +Date: Fri, 22 Jan 2021 16:38:19 -0500 +Subject: [PATCH] lithium: gen + +Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 +You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java b/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c99eff34c1be07508c88fe9525c3ae1a087fdef7 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java +@@ -0,0 +1,92 @@ ++package me.jellysquid.mods.lithium.common.util; ++ ++import net.minecraft.core.SectionPos; ++import net.minecraft.world.level.LevelHeightAccessor; ++ ++public class Pos { ++ ++ public static class BlockCoord { ++ public static int getYSize(LevelHeightAccessor view) { ++ return view.getHeight(); ++ } ++ public static int getMinY(LevelHeightAccessor view) { ++ return view.getMinBuildHeight(); ++ } ++ public static int getMaxYInclusive(LevelHeightAccessor view) { ++ return view.getMaxBuildHeight() - 1; ++ } ++ public static int getMaxYExclusive(LevelHeightAccessor view) { ++ return view.getMaxBuildHeight(); ++ } ++ ++ public static int getMaxInSectionCoord(int sectionCoord) { ++ return 15 + getMinInSectionCoord(sectionCoord); ++ } ++ ++ public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex){ ++ return getMaxInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex)); ++ } ++ ++ public static int getMinInSectionCoord(int sectionCoord) { ++ return SectionPos.sectionToBlockCoord(sectionCoord); ++ } ++ ++ public static int getMinYInSectionIndex(LevelHeightAccessor view, int sectionIndex) { ++ return getMinInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex)); ++ } ++ } ++ ++ public static class ChunkCoord { ++ public static int fromBlockCoord(int blockCoord) { ++ return SectionPos.blockToSectionCoord(blockCoord); ++ } ++ ++ public static int fromBlockSize(int i) { ++ return i >> 4; //same method as fromBlockCoord, just be clear about coord/size semantic difference ++ } ++ } ++ ++ public static class SectionYCoord { ++ public static int getNumYSections(LevelHeightAccessor view) { ++ return view.getSectionsCount(); ++ } ++ public static int getMinYSection(LevelHeightAccessor view) { ++ return view.getMinSection(); ++ } ++ public static int getMaxYSectionInclusive(LevelHeightAccessor view) { ++ return view.getMaxSection() - 1; ++ } ++ public static int getMaxYSectionExclusive(LevelHeightAccessor view) { ++ return view.getMaxSection(); ++ } ++ ++ public static int fromSectionIndex(LevelHeightAccessor view, int sectionCoord) { ++ return sectionCoord + SectionYCoord.getMinYSection(view); ++ } ++ public static int fromBlockCoord(int blockCoord) { ++ return SectionPos.blockToSectionCoord(blockCoord); ++ } ++ } ++ ++ public static class SectionYIndex { ++ public static int getNumYSections(LevelHeightAccessor view) { ++ return view.getSectionsCount(); ++ } ++ public static int getMinYSectionIndex(LevelHeightAccessor view) { ++ return 0; ++ } ++ public static int getMaxYSectionIndexInclusive(LevelHeightAccessor view) { ++ return view.getSectionsCount() - 1; ++ } ++ public static int getMaxYSectionIndexExclusive(LevelHeightAccessor view) { ++ return view.getSectionsCount(); ++ } ++ ++ public static int fromSectionCoord(LevelHeightAccessor view, int sectionCoord) { ++ return sectionCoord - SectionYCoord.getMinYSection(view); ++ } ++ public static int fromBlockCoord(LevelHeightAccessor view, int blockCoord) { ++ return fromSectionCoord(view, SectionPos.blockToSectionCoord(blockCoord)); ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +index 91b273d058d2fe83207cc562a25711e4d621c862..982ebf0fe6aa4d4f42e8e3b8820fbaf1f7736849 100644 +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -54,6 +54,7 @@ import net.minecraft.world.phys.Vec3; + import net.minecraft.world.ticks.LevelTickAccess; + import net.minecraft.world.ticks.WorldGenTickAccess; + import org.slf4j.Logger; ++import me.jellysquid.mods.lithium.common.util.Pos; // DivineMC - lithium: gen + + public class WorldGenRegion implements WorldGenLevel { + +@@ -82,6 +83,8 @@ public class WorldGenRegion implements WorldGenLevel { + private Supplier currentlyGenerating; + private final AtomicLong subTickCount = new AtomicLong(); + private static final ResourceLocation WORLDGEN_REGION_RANDOM = new ResourceLocation("worldgen_region_random"); ++ private ChunkAccess[] chunksArr; // DivineMC - lithium: gen ++ private int minChunkX, minChunkZ; // DivineMC - lithium: gen + + public WorldGenRegion(ServerLevel world, List chunks, ChunkStatus status, int placementRadius) { + this.generatingStatus = status; +@@ -104,6 +107,12 @@ public class WorldGenRegion implements WorldGenLevel { + this.lastPos = ((ChunkAccess) chunks.get(chunks.size() - 1)).getPos(); + this.structureManager = world.structureManager().forWorldGenRegion(this); + } ++ // DivineMC start - lithium: gen ++ this.minChunkX = this.firstPos.x; ++ this.minChunkZ = this.firstPos.z; ++ ++ this.chunksArr = chunks.toArray(new ChunkAccess[0]); ++ // DivineMC end + } + + public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { +@@ -119,11 +128,33 @@ public class WorldGenRegion implements WorldGenLevel { + this.currentlyGenerating = structureName; + } + ++ // DivineMC start - lithium: gen ++ /** ++ * @reason Use the chunk array for faster access ++ * @author SuperCoder7979, 2No2Name ++ */ + @Override + public ChunkAccess getChunk(int chunkX, int chunkZ) { +- return this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY); ++ int x = chunkX - this.minChunkX; ++ int z = chunkZ - this.minChunkZ; ++ int w = this.size; ++ ++ if (x >= 0 && z >= 0 && x < w && z < w) { ++ return this.chunksArr[x + z * w]; ++ } else { ++ throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ)); ++ } + } + ++ /** ++ * Use our chunk fetch function ++ */ ++ public ChunkAccess getChunk(BlockPos pos) { ++ // Skip checking chunk.getStatus().isAtLeast(ChunkStatus.EMPTY) here, because it is always true ++ return this.getChunk(Pos.ChunkCoord.fromBlockCoord(pos.getX()), Pos.ChunkCoord.fromBlockCoord(pos.getZ())); ++ } ++ // DivineMC end ++ + @Nullable + @Override + public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { +@@ -179,10 +210,24 @@ public class WorldGenRegion implements WorldGenLevel { + } + // Paper end + ++ // DivineMC start - lithium: gen ++ /** ++ * @reason Avoid pointer de-referencing, make method easier to inline ++ * @author JellySquid ++ */ + @Override + public BlockState getBlockState(BlockPos pos) { +- return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); ++ int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.minChunkX; ++ int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.minChunkZ; ++ int w = this.size; ++ ++ if (x >= 0 && z >= 0 && x < w && z < w) { ++ return this.chunksArr[x + z * w].getBlockState(pos); ++ } else { ++ throw new NullPointerException("No chunk exists at " + new ChunkPos(pos)); ++ } + } ++ // DivineMC end + + @Override + public FluidState getFluidState(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index cf87490a446285132daaf9d90154ac6d477a62fe..3d6c50822701a3828cbde704f419d1c900a67954 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -67,6 +67,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + public final Registry noises; + public final Holder settings; + private final Aquifer.FluidPicker globalFluidPicker; ++ private int cachedSeaLevel; // DivineMC - lithium: gen + + public NoiseBasedChunkGenerator(Registry structureSetRegistry, Registry noiseRegistry, BiomeSource populationSource, Holder settings) { + super(structureSetRegistry, Optional.empty(), populationSource); +@@ -83,6 +84,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + this.globalFluidPicker = (j, k, l) -> { + return k < Math.min(-54, i) ? aquifer_b : aquifer_b1; + }; ++ this.cachedSeaLevel = ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); // DivineMC - lithium: gen + } + + @Override +@@ -398,10 +400,19 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().height(); + } + ++ // DivineMC start - lithium: gen ++ /** ++ * Use cached sea level instead of retrieving from the registry every time. ++ * This method is called for every block in the chunk so this will save a lot of registry lookups. ++ * ++ * @author SuperCoder79 ++ * @reason avoid registry lookup ++ */ + @Override + public int getSeaLevel() { +- return ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); ++ return this.cachedSeaLevel; + } ++ // DivineMC end + + @Override + public int getMinY() { diff --git a/DivineMC/settings.gradle.kts b/DivineMC/settings.gradle.kts new file mode 100644 index 0000000..c1bac2e --- /dev/null +++ b/DivineMC/settings.gradle.kts @@ -0,0 +1,11 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + maven("https://papermc.io/repo/repository/maven-public/") + } +} + +rootProject.name = "DivineMC" + +include("DivineMC-API", "DivineMC-Server") \ No newline at end of file diff --git a/patches/server/0001-Divine-Branding.patch b/patches/server/0001-Divine-Branding.patch index ed62e5a..024ce2c 100644 --- a/patches/server/0001-Divine-Branding.patch +++ b/patches/server/0001-Divine-Branding.patch @@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..b222c6480376a8167dbf95db69ec0467 + private static final Logger LOGGER = Logger.getLogger("DivineVersionFetcher"); + private static final HttpClient client = HttpClient.newHttpClient(); + -+ private static final URI JENKINS_URI = URI.create("https://ci.bxteam.gq/job/DivineMC/job/DivineMC-1.19/lastSuccessfulBuild/buildNumber"); ++ private static final URI JENKINS_URI = URI.create("https://api.bxteam.gq/v3/divine-latestBuild"); + private static final String GITHUB_FORMAT = "https://api.github.com/repos/DivineMC/DivineMC/compare/ver/1.19.2...%s"; + + private static final HttpResponse.BodyHandler JSON_OBJECT_BODY_HANDLER = responseInfo -> HttpResponse.BodySubscribers.mapping(