From cc6d3e744bb6c242f5e1de706a0de53c23b72a87 Mon Sep 17 00:00:00 2001 From: "Kira M. Backes" Date: Sun, 15 Dec 2024 04:17:49 +0100 Subject: [PATCH] Release new version based on minecart experiments for Minecraft 1.21.3 and 1.21.4 --- CHANGELOG.md | 16 +- LICENSE | 558 ++++++++++++++---- build.gradle | 3 +- gradle.properties | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/audaki/cart_engine/AceGameRules.java | 15 + src/main/java/audaki/cart_engine/AceMod.java | 10 + .../mixin/AbstractMinecartEntityMixin.java | 551 ----------------- .../mixin/AbstractMinecartMixin.java | 56 ++ .../mixin/NewMinecartBehaviorMixin.java | 29 + .../resources/audaki_cart_engine.mixins.json | 5 +- src/main/resources/fabric.mod.json | 7 +- 12 files changed, 578 insertions(+), 682 deletions(-) create mode 100644 src/main/java/audaki/cart_engine/AceGameRules.java create mode 100644 src/main/java/audaki/cart_engine/AceMod.java delete mode 100644 src/main/java/audaki/cart_engine/mixin/AbstractMinecartEntityMixin.java create mode 100644 src/main/java/audaki/cart_engine/mixin/AbstractMinecartMixin.java create mode 100644 src/main/java/audaki/cart_engine/mixin/NewMinecartBehaviorMixin.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f3fc25b..b5e94fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.0.0] - 2024-12-15 +- Base mod on improved minecarts experiment + - The experimental code will be activated for all carts + - Rideable carts will be set to /gamerule aceCartSpeed (default 20) blocks per second + - All other carts will be set to 8 blocks per second speed +- Due to the new minecart experiment we now have the following features + - Full-Speed around corners + - Full-Speed around hills + - Consistent Jumps + - Perfect 1-tile breaks + - ROLLER COASTER MECHANICS + ## [3.1.1] - 2024-05-25 - Make backwards compatible - from Minecraft 1.21 down to Minecraft 1.17 @@ -50,12 +62,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - A little more slowdown before descending rails. Due to the vanilla parity you now start descending with 8m/s instead of 9.2m/s - A little more slowdown before detector / activator rails. On and directly before detector/activator rails you also move with 8m/s instead of 9.2m/s now. - Mod Compatibility: We only overwrite the moveOnRail function now when there is actually a LivingEntity riding the cart -- (technical) Mixin is targeting AbstractMinecartEntity again so we can inject and cancel the overwrite +- (technical) Mixin is targeting AbstractMinecart again so we can inject and cancel the overwrite - Built for Minecraft 1.19.4 ## [2.0.2] - 2023-03-15 - Starting with this version only mc 1.19+ receives mod updates (2.0.1 is very stable for mc 1.18 and 1.17) -- (technical) Refactored mixin to target MinecartEntity directly instead of AbstractMinecartEntity, therefore potentially increasing compatibility to other mods even more +- (technical) Refactored mixin to target MinecartEntity directly instead of AbstractMinecart, therefore potentially increasing compatibility to other mods even more - Built for Minecraft 1.19.4 ## [2.0.1] - 2023-02-20 diff --git a/LICENSE b/LICENSE index 0e259d4..93047ee 100644 --- a/LICENSE +++ b/LICENSE @@ -1,121 +1,437 @@ -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. +Attribution-NonCommercial-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/build.gradle b/build.gradle index 7ea694e..17be2e9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.6-SNAPSHOT' + id 'fabric-loom' version '1.9-SNAPSHOT' } version = project.mod_version @@ -14,6 +14,7 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index d9da8ec..5e8115b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,10 +3,12 @@ org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true # Fabric Properties, @see https://fabricmc.net/develop -minecraft_version=1.20.6 -loader_version=0.15.11 +minecraft_version=1.21.3 +loader_version=0.16.9 + +fabric_api_version=0.112.0+1.21.3 # Mod Properties -mod_version = 3.1.1 +mod_version = 4.0.0 maven_group = audaki.minecraft archives_base_name = ACE diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..7cf748e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/audaki/cart_engine/AceGameRules.java b/src/main/java/audaki/cart_engine/AceGameRules.java new file mode 100644 index 0000000..940fe00 --- /dev/null +++ b/src/main/java/audaki/cart_engine/AceGameRules.java @@ -0,0 +1,15 @@ +package audaki.cart_engine; + +import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory; +import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry; +import net.minecraft.world.level.GameRules; + +public class AceGameRules { + public static GameRules.Key ACE_CART_SPEED; + + public static void register() { + ACE_CART_SPEED = GameRuleRegistry.register("aceCartSpeed", + GameRules.Category.PLAYER, + GameRuleFactory.createIntRule(20)); + } +} diff --git a/src/main/java/audaki/cart_engine/AceMod.java b/src/main/java/audaki/cart_engine/AceMod.java new file mode 100644 index 0000000..0c02823 --- /dev/null +++ b/src/main/java/audaki/cart_engine/AceMod.java @@ -0,0 +1,10 @@ +package audaki.cart_engine; + +import net.fabricmc.api.ModInitializer; + +public class AceMod implements ModInitializer { + @Override + public void onInitialize() { + AceGameRules.register(); + } +} diff --git a/src/main/java/audaki/cart_engine/mixin/AbstractMinecartEntityMixin.java b/src/main/java/audaki/cart_engine/mixin/AbstractMinecartEntityMixin.java deleted file mode 100644 index 7c4c8a2..0000000 --- a/src/main/java/audaki/cart_engine/mixin/AbstractMinecartEntityMixin.java +++ /dev/null @@ -1,551 +0,0 @@ -package audaki.cart_engine.mixin; - -import com.mojang.datafixers.util.Pair; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MoverType; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.entity.vehicle.AbstractMinecart.Type; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BaseRailBlock; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.PoweredRailBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.RailShape; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -/* - AbstractMinecart is extending VehicleEntity - But this is only available from 1.20.3 - So we stay with extends Entity for now - */ - -@Mixin(AbstractMinecart.class) -public abstract class AbstractMinecartEntityMixin extends Entity { - - public AbstractMinecartEntityMixin(EntityType type, Level level) { - super(type, level); - } - - @Shadow - protected abstract boolean isRedstoneConductor(BlockPos pos); - - @Shadow - public abstract Vec3 getPos(double x, double y, double z); - - @Shadow - protected abstract void applyNaturalSlowdown(); - - @Shadow - protected abstract double getMaxSpeed(); - - @Shadow - public abstract Type getMinecartType(); - - @Shadow - private static Pair exits(RailShape shape) { - // This is just fake code, the shadowed private function will be executed - return Pair.of(Direction.NORTH.getNormal(), Direction.SOUTH.getNormal()); - } - - private static boolean isEligibleFastRail(BlockState state) { - return state.is(Blocks.RAIL) || (state.is(Blocks.POWERED_RAIL) && state.getValue(PoweredRailBlock.POWERED)); - } - - private static RailShape getRailShape(BlockState state) { - if (!(state.getBlock() instanceof BaseRailBlock railBlock)) - throw new IllegalArgumentException("No rail shape found"); - - return state.getValue(railBlock.getShapeProperty()); - } - - @Inject(at = @At("HEAD"), method = "moveAlongTrack", cancellable = true) - protected void moveAlongTrackOverwrite(BlockPos pos, BlockState state, CallbackInfo ci) { - - // We only change logic for rideable minecarts, so we don't break hopper/chest minecart creations - if (this.getMinecartType() != Type.RIDEABLE) { - return; - } - - // We only change logic when the minecart is currently being ridden by a living entity (player/villager/mob) - boolean hasLivingRider = this.getFirstPassenger() instanceof LivingEntity; - if (!hasLivingRider) { - return; - } - - this.modifiedMoveAlongTrack(pos, state); - ci.cancel(); - } - - protected void modifiedMoveAlongTrack(BlockPos startPos, BlockState state) { - - // Minecraft 1.17 - 1.19 -// Level level = this.level; - // Minecraft 1.20+ - Level level = this.level(); - - final double tps = 20.; - final double maxSpeed = 34. / tps; - final double maxMomentum = maxSpeed * 5.; - final double vanillaMaxSpeed = 8. / tps; - final double vanillaMaxMomentum = 40. / tps; - - /* - From 1.18 resetFallDistance() is used, but for backwards compatibility we copied the code - So far (2024-05-25) no different code is executed in that function - */ - this.fallDistance = 0.0F; - - double thisX = this.getX(); - double thisY = this.getY(); - double thisZ = this.getZ(); - - Vec3 vec3 = this.getPos(thisX, thisY, thisZ); - - thisY = startPos.getY(); - boolean onPoweredRail = false; - boolean onBrakeRail = false; - if (state.is(Blocks.POWERED_RAIL)) { - onPoweredRail = state.getValue(PoweredRailBlock.POWERED); - onBrakeRail = !onPoweredRail; - } - - double g = 0.0078125D; - if (this.isInWater()) { - g *= 0.2D; - } - - Vec3 momentum = this.getDeltaMovement(); - RailShape railShape = getRailShape(state); - boolean isAscending = railShape.isAscending(); - boolean isDiagonal = (railShape == RailShape.SOUTH_WEST || railShape == RailShape.NORTH_EAST || - railShape == RailShape.SOUTH_EAST || railShape == RailShape.NORTH_WEST); - - switch (railShape) { - case ASCENDING_EAST -> { - this.setDeltaMovement(momentum.add(-g, 0.0D, 0.0D)); - ++thisY; - } - case ASCENDING_WEST -> { - this.setDeltaMovement(momentum.add(g, 0.0D, 0.0D)); - ++thisY; - } - case ASCENDING_NORTH -> { - this.setDeltaMovement(momentum.add(0.0D, 0.0D, g)); - ++thisY; - } - case ASCENDING_SOUTH -> { - this.setDeltaMovement(momentum.add(0.0D, 0.0D, -g)); - ++thisY; - } - } - - - momentum = this.getDeltaMovement(); - Pair exitPair = exits(railShape); - Vec3i exitRelPos1 = exitPair.getFirst(); - Vec3i exitRelPos2 = exitPair.getSecond(); - // The exit relative X and Z here can be either -1, 0 or 1 - // - // Example for an EAST_WEST rail would be: - // exitRelPos1.getX() = -1 - // exitRelPos2.getX() = 1 - // exitRelPos1.getZ() = 0 - // exitRelPos2.getZ() = 0 - // Therefore - // exitDiffX = 2 - // exitDiffZ = 0 - // exitHypotenuse = 4 - // - // Example for an SOUTH_EAST rail would be: - // exitRelPos1.getX() = 0 - // exitRelPos2.getX() = 1 - // exitRelPos1.getZ() = 1 - // exitRelPos2.getZ() = 0 - // Therefore - // exitDiffX = 1 - // exitDiffZ = -1 - // exitHypotenuse = 1.414 - // - // Note: exitDiffX and exitDiffY can be either -1, 0, 1 or 2 - // (-2 isn’t possible, I think the south-east rule starts here) - // - // By some magic, this works out to find the correct new velocity depending on incoming velocity and rail shape - double exitDiffX = exitRelPos2.getX() - exitRelPos1.getX(); - double exitDiffZ = exitRelPos2.getZ() - exitRelPos1.getZ(); - double exitHypotenuse = Math.sqrt(exitDiffX * exitDiffX + exitDiffZ * exitDiffZ); - double k = momentum.x * exitDiffX + momentum.z * exitDiffZ; - // Every rail shape has a "forward" movement according to the diffs using the exits() - // If it’s backwards the direction is flipped. - boolean movementIsBackwards = k < 0.0D; - if (movementIsBackwards) { - exitDiffX = -exitDiffX; - exitDiffZ = -exitDiffZ; - } - - double horizontalMomentum = Math.min(this.getDeltaMovement().horizontalDistance(), maxMomentum); - // The horizontal speed is redistributed using the hypotenuse of the exit rail positions - this.setDeltaMovement(new Vec3(horizontalMomentum * exitDiffX / exitHypotenuse, momentum.y, horizontalMomentum * exitDiffZ / exitHypotenuse)); - - - BlockPos exitPos; - boolean exitIsAir; - { - BlockPos pos = isAscending ? startPos.above() : startPos; - BlockPos exitPos1 = pos.offset(exitRelPos1); - if (level.getBlockState(new BlockPos(exitPos1.getX(), exitPos1.getY() - 1, exitPos1.getZ())).is(BlockTags.RAILS)) { - exitPos1 = exitPos1.below(); - } - BlockPos exitPos2 = pos.offset(exitRelPos2); - if (level.getBlockState(new BlockPos(exitPos2.getX(), exitPos2.getY() - 1, exitPos2.getZ())).is(BlockTags.RAILS)) { - exitPos2 = exitPos2.below(); - } - - Vec3 posCenter = Vec3.atCenterOf(pos); - Vec3 exit1Center = Vec3.atCenterOf(exitPos1); - Vec3 exit2Center = Vec3.atCenterOf(exitPos2); - - Vec3 momentumPos = posCenter.add(this.getDeltaMovement()).multiply(1, 0, 1); - exitPos = momentumPos.distanceTo(exit1Center.multiply(1, 0, 1)) < momentumPos.distanceTo(exit2Center.multiply(1, 0, 1)) ? exitPos1 : exitPos2; - BlockState exitState = level.getBlockState(exitPos); - exitIsAir = exitState.is(Blocks.AIR); - } - - ArrayList adjRailPositions = new ArrayList<>(); - Supplier calculateMaxSpeedForThisTick = () -> { - - double fallback = this.getMaxSpeed(); - - if (!this.isVehicle()) - return fallback; - - if (this.getDeltaMovement().horizontalDistance() < vanillaMaxSpeed) - return fallback; - - if (!isEligibleFastRail(state)) - return fallback; - - HashSet checkedPositions = new HashSet<>(); - checkedPositions.add(startPos); - - - BiFunction>> checkNeighbors = (checkPos, checkRailShape) -> { - - Pair nExitPair = exits(checkRailShape); - - ArrayList> newNeighbors = new ArrayList<>(); - - BlockPos sourcePos = checkRailShape.isAscending() ? checkPos.above() : checkPos; - - for (Vec3i nExitRelPos: List.of(nExitPair.getFirst(), nExitPair.getSecond())) { - BlockPos nPos = sourcePos.offset(nExitRelPos); - if (level.getBlockState(new BlockPos(nPos.getX(), nPos.getY() - 1, nPos.getZ())).is(BlockTags.RAILS)) { - nPos = nPos.below(); - } - - if (checkedPositions.contains(nPos)) - continue; - - BlockState nState = level.getBlockState(nPos); - if (!isEligibleFastRail(nState)) - return new ArrayList<>(); - - RailShape nShape = getRailShape(nState); - boolean sameDiagonal = (railShape == RailShape.SOUTH_WEST && nShape == RailShape.NORTH_EAST - || railShape == RailShape.NORTH_EAST && nShape == RailShape.SOUTH_WEST - || railShape == RailShape.SOUTH_EAST && nShape == RailShape.NORTH_WEST - || railShape == RailShape.NORTH_WEST && nShape == RailShape.SOUTH_EAST); - - if (nShape != railShape && !sameDiagonal) - return new ArrayList<>(); - - checkedPositions.add(nPos); - adjRailPositions.add(nPos); - // Adding the neighbor rail shape currently has no use, since we abort on rail shape change anyway - // Code stays as is for now so we can differentiate between types of rail shape changes later - newNeighbors.add(Pair.of(nPos, nShape)); - } - - return newNeighbors; - }; - - - ArrayList> newNeighbors = checkNeighbors.apply(startPos, railShape); - - double checkFactor = (isDiagonal || isAscending) ? 2. : 1.; - final int cutoffPoint = 3; - int sizeToCheck = (int)(2 * (cutoffPoint + (checkFactor * maxSpeed))); - sizeToCheck -= (sizeToCheck % 2); - - while (!newNeighbors.isEmpty() && adjRailPositions.size() < sizeToCheck) { - ArrayList> tempNewNeighbors = new ArrayList<>(newNeighbors); - newNeighbors.clear(); - - for (Pair newNeighbor : tempNewNeighbors) { - ArrayList> result = checkNeighbors.apply(newNeighbor.getFirst(), newNeighbor.getSecond()); - - // Abort when one direction is empty - if (result.isEmpty()) { - newNeighbors.clear(); - break; - } - - newNeighbors.addAll(result); - } - } - - int railCountEachDirection = adjRailPositions.size() / 2; - final double cutoffSpeedPerSec = 20.; - switch (railCountEachDirection) { - case 0: - case 1: - return fallback; - case 2: - return 12. / tps; - case 3: - return cutoffSpeedPerSec / tps; - default: - } - - int railCountPastBegin = railCountEachDirection - cutoffPoint; - return (cutoffSpeedPerSec + ((20. / checkFactor) * railCountPastBegin)) / tps; - }; - - double maxSpeedForThisTick = Math.min(calculateMaxSpeedForThisTick.get(), maxSpeed); - if (isDiagonal || isAscending) { - // Diagonal and Ascending/Descending is 1.4142 times faster, we correct this here - maxSpeedForThisTick = Math.min(maxSpeedForThisTick, 0.7071 * maxSpeed); - } - - Entity entity = this.getFirstPassenger(); - if (entity instanceof Player) { - Vec3 playerDeltaMovement = entity.getDeltaMovement(); - double m = playerDeltaMovement.horizontalDistanceSqr(); - double n = this.getDeltaMovement().horizontalDistanceSqr(); - if (m > 1.0E-4D && n < 0.01D) { - this.setDeltaMovement(this.getDeltaMovement().add(playerDeltaMovement.x * 0.1D, 0.0D, playerDeltaMovement.z * 0.1D)); - onBrakeRail = false; - } - } - - - /* - Braking Algorithm - Original: - double o; - if (bl2) { - o = this.getDeltaMovement().horizontalDistance(); - if (o < 0.03) { - this.setDeltaMovement(Vec3.ZERO); - } else { - this.setDeltaMovement(this.getDeltaMovement().multiply(0.5, 0.0, 0.5)); - } - } - */ - if (onBrakeRail) { - momentum = this.getDeltaMovement(); - horizontalMomentum = momentum.horizontalDistance(); - - if (horizontalMomentum < 0.03) { - this.setDeltaMovement(Vec3.ZERO); - } else { - - if (horizontalMomentum > vanillaMaxSpeed) { - double ratioToSlowdown = vanillaMaxSpeed / horizontalMomentum; - this.setDeltaMovement(momentum.multiply(ratioToSlowdown, 1., ratioToSlowdown)); - } - - double brakeFactor = 0.59; - this.setDeltaMovement(this.getDeltaMovement().multiply(brakeFactor, 0., brakeFactor)); - } - } - - double p = (double) startPos.getX() + 0.5D + (double) exitRelPos1.getX() * 0.5D; - double q = (double) startPos.getZ() + 0.5D + (double) exitRelPos1.getZ() * 0.5D; - double r = (double) startPos.getX() + 0.5D + (double) exitRelPos2.getX() * 0.5D; - double s = (double) startPos.getZ() + 0.5D + (double) exitRelPos2.getZ() * 0.5D; - exitDiffX = r - p; - exitDiffZ = s - q; - double x; - double v; - double w; - if (exitDiffX == 0.0D) { - x = thisZ - (double) startPos.getZ(); - } else if (exitDiffZ == 0.0D) { - x = thisX - (double) startPos.getX(); - } else { - v = thisX - p; - w = thisZ - q; - x = (v * exitDiffX + w * exitDiffZ) * 2.0D; - } - - thisX = p + exitDiffX * x; - thisZ = q + exitDiffZ * x; - - v = this.isVehicle() ? 0.75D : 1.0D; - w = maxSpeedForThisTick; - momentum = this.getDeltaMovement(); - // The clamp here differentiates between momentum and actual allowed speed in this tick - Vec3 movement = new Vec3(Mth.clamp(v * momentum.x, -w, w), 0.0D, Mth.clamp(v * momentum.z, -w, w)); - - double extraY = 0; - if (railShape.isAscending()) { - if (exitPos.getY() > startPos.getY()) { -// System.out.println("is higher!"); - extraY = (int) (0.5 + movement.horizontalDistance()); - thisY += extraY; - } - } - - this.setPos(thisX, thisY, thisZ); - this.move(MoverType.SELF, movement); - -// System.out.println("Actual: " + movement.horizontalDistance() -// + " " + level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 2.), Mth.floor(this.getZ()))).is(BlockTags.RAILS) -// + " " + level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 1.), Mth.floor(this.getZ()))).is(BlockTags.RAILS) -// + " " + level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 0.), Mth.floor(this.getZ()))).is(BlockTags.RAILS) -// + " " + level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() + 1.), Mth.floor(this.getZ()))).is(BlockTags.RAILS)); - - { - // Snap down after extra snap ups on ascending rails - // Also snap down on descending rails - if (railShape.isAscending() - && !level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()))).is(BlockTags.RAILS) - && !level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 1.), Mth.floor(this.getZ()))).is(BlockTags.RAILS)) { - - if (level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 2.), Mth.floor(this.getZ()))).is(BlockTags.RAILS)) { - this.setPos(this.getX(), this.getY() - 1, this.getZ()); - } else if (level.getBlockState(new BlockPos(Mth.floor(this.getX()), Mth.floor(this.getY() - 3.), Mth.floor(this.getZ()))).is(BlockTags.RAILS)) { - this.setPos(this.getX(), this.getY() - 2, this.getZ()); - } - } - - // Old vanilla code to snap down on descending rails (only the descending exit had a different Y rel pos) -// if (exitRelPos1.getY() != 0 && Mth.floor(this.getX()) - startPos.getX() == exitRelPos1.getX() && Mth.floor(this.getZ()) - startPos.getZ() == exitRelPos1.getZ()) { -// this.setPos(this.getX(), this.getY() + (double) exitRelPos1.getY(), this.getZ()); -// } else if (exitRelPos2.getY() != 0 && Mth.floor(this.getX()) - startPos.getX() == exitRelPos2.getX() && Mth.floor(this.getZ()) - startPos.getZ() == exitRelPos2.getZ()) { -// this.setPos(this.getX(), this.getY() + (double) exitRelPos2.getY(), this.getZ()); -// } - } - - - - this.applyNaturalSlowdown(); - - // Todo: 100% understand this vanilla code block & rename variables - Vec3 vec3d4 = this.getPos(this.getX(), this.getY(), this.getZ()); - if (vec3d4 != null && vec3 != null) { - double aa = (vec3.y - vec3d4.y) * 0.05D; - momentum = this.getDeltaMovement(); - horizontalMomentum = momentum.horizontalDistance(); - if (horizontalMomentum > 0.0D) { - this.setDeltaMovement(momentum.multiply((horizontalMomentum + aa) / horizontalMomentum, 1.0D, (horizontalMomentum + aa) / horizontalMomentum)); - } - - this.setPos(this.getX(), vec3d4.y, this.getZ()); - } - - // Todo: 100% understand this vanilla code block & rename variables - int ac = Mth.floor(this.getX()); - int ad = Mth.floor(this.getZ()); - if (ac != startPos.getX() || ad != startPos.getZ()) { - momentum = this.getDeltaMovement(); - horizontalMomentum = momentum.horizontalDistance(); - this.setDeltaMovement( - horizontalMomentum * Mth.clamp(ac - startPos.getX(), -1.0D, 1.0D), - momentum.y, - horizontalMomentum * Mth.clamp(ad - startPos.getZ(), -1.0D, 1.0D)); - } - - - // Give speedup or kickstart when standing at block + powered rail - if (onPoweredRail) { - momentum = this.getDeltaMovement(); - horizontalMomentum = momentum.horizontalDistance(); - final double basisAccelerationPerTick = 0.021D; - if (horizontalMomentum > 0.01D) { - - if (this.isVehicle()) { - // TODO: Rewrite the comment/naming so it makes more sense (very confusing since TPS is 20 and we can only skip 1 block with current speeds) - - // Based on a 10 ticks per second basis spent per powered block we calculate a fair acceleration per tick - // due to spending less ticks per powered block on higher speeds (and even skipping blocks) - final double basisTicksPerSecond = 10.0D; - // Tps = Ticks per second - final double tickMovementForBasisTps = 1.0D / basisTicksPerSecond; - final double maxSkippedBlocksToConsider = 3.0D; - - - double acceleration = basisAccelerationPerTick; - final double distanceMovedHorizontally = movement.horizontalDistance(); - - if (distanceMovedHorizontally > tickMovementForBasisTps) { - acceleration *= Math.min((1.0D + maxSkippedBlocksToConsider) * basisTicksPerSecond, distanceMovedHorizontally / tickMovementForBasisTps); - - // Add progressively slower (or faster) acceleration for higher speeds; - double highspeedFactor = 1.0D + Mth.clamp(-0.45D * (distanceMovedHorizontally / tickMovementForBasisTps / basisTicksPerSecond), -0.7D, 2.0D); - acceleration *= highspeedFactor; - } - this.setDeltaMovement(momentum.add(acceleration * (momentum.x / horizontalMomentum), 0.0D, acceleration * (momentum.z / horizontalMomentum))); - } - else { - this.setDeltaMovement(momentum.add(momentum.x / horizontalMomentum * 0.06D, 0.0D, momentum.z / horizontalMomentum * 0.06D)); - } - - - } else { - momentum = this.getDeltaMovement(); - double ah = momentum.x; - double ai = momentum.z; - final double railStopperAcceleration = basisAccelerationPerTick * 16.0D; - if (railShape == RailShape.EAST_WEST) { - if (this.isRedstoneConductor(startPos.west())) { - ah = railStopperAcceleration; - } else if (this.isRedstoneConductor(startPos.east())) { - ah = -railStopperAcceleration; - } - } else { - if (railShape != RailShape.NORTH_SOUTH) { - return; - } - - if (this.isRedstoneConductor(startPos.north())) { - ai = railStopperAcceleration; - } else if (this.isRedstoneConductor(startPos.south())) { - ai = -railStopperAcceleration; - } - } - - this.setDeltaMovement(ah, momentum.y, ai); - } - } - - // TODO: Falling is still inconsistent, is it a vanilla inconsistency? -// if (exitIsAir) { -// momentum = this.getDeltaMovement(); -// horizontalMomentum = momentum.horizontalDistance(); -// if (horizontalMomentum > vanillaMaxSpeed) { -// double ratioToSlowdown = vanillaMaxSpeed / horizontalMomentum; -// this.setDeltaMovement(momentum.multiply(ratioToSlowdown, 1., ratioToSlowdown)); -// } -// } - } -} diff --git a/src/main/java/audaki/cart_engine/mixin/AbstractMinecartMixin.java b/src/main/java/audaki/cart_engine/mixin/AbstractMinecartMixin.java new file mode 100644 index 0000000..0c6bb07 --- /dev/null +++ b/src/main/java/audaki/cart_engine/mixin/AbstractMinecartMixin.java @@ -0,0 +1,56 @@ +package audaki.cart_engine.mixin; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.*; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(AbstractMinecart.class) +public abstract class AbstractMinecartMixin extends VehicleEntity { + + @Shadow + public abstract boolean isRideable(); + + @Shadow + public abstract boolean isFurnace(); + + @Shadow + private boolean onRails; + + @Mutable + @Final + @Shadow + private MinecartBehavior behavior; + + public AbstractMinecartMixin(EntityType type, Level level) { + super(type, level); + } + + @Unique + protected void juiceUpBehavior() { + if (this.behavior instanceof OldMinecartBehavior) { + AbstractMinecart instance = (AbstractMinecart) (Object) this; + this.behavior = new NewMinecartBehavior(instance); + } + } + + @Inject(at = @At("HEAD"), method = "setInitialPos") + public void _setInitialPos(double d, double e, double f, CallbackInfo ci) { + this.juiceUpBehavior(); + } + + @Inject(at = @At("HEAD"), method = "tick") + public void _tick(CallbackInfo ci) { + this.juiceUpBehavior(); + } + + @Inject(at = @At("HEAD"), method = "useExperimentalMovement", cancellable = true) + private static void _useExperimentalMovement(Level level, CallbackInfoReturnable cir) { + cir.setReturnValue(true); + cir.cancel(); + } +} diff --git a/src/main/java/audaki/cart_engine/mixin/NewMinecartBehaviorMixin.java b/src/main/java/audaki/cart_engine/mixin/NewMinecartBehaviorMixin.java new file mode 100644 index 0000000..4ba8f3d --- /dev/null +++ b/src/main/java/audaki/cart_engine/mixin/NewMinecartBehaviorMixin.java @@ -0,0 +1,29 @@ +package audaki.cart_engine.mixin; + +import audaki.cart_engine.AceGameRules; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.MinecartBehavior; +import net.minecraft.world.entity.vehicle.NewMinecartBehavior; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(NewMinecartBehavior.class) +public abstract class NewMinecartBehaviorMixin extends MinecartBehavior { + + protected NewMinecartBehaviorMixin(AbstractMinecart abstractMinecart) { + super(abstractMinecart); + } + + @Inject(at = @At("HEAD"), method = "getMaxSpeed", cancellable = true) + public void _getMaxSpeed(ServerLevel level, CallbackInfoReturnable cir) { + int speedBlocksPerSecond = 8; + if (minecart.isRideable()) { + speedBlocksPerSecond = level.getGameRules().getInt(AceGameRules.ACE_CART_SPEED);; + } + cir.setReturnValue(speedBlocksPerSecond * (this.minecart.isInWater() ? 0.5 : 1.0) / 20.0); + cir.cancel(); + } +} diff --git a/src/main/resources/audaki_cart_engine.mixins.json b/src/main/resources/audaki_cart_engine.mixins.json index e64af9d..3bd35ba 100644 --- a/src/main/resources/audaki_cart_engine.mixins.json +++ b/src/main/resources/audaki_cart_engine.mixins.json @@ -1,10 +1,11 @@ { "required": true, - "minVersion": "0.8", + "minVersion": "0.8.5", "package": "audaki.cart_engine.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "AbstractMinecartEntityMixin" + "AbstractMinecartMixin", + "NewMinecartBehaviorMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6222f22..0b135f6 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,12 +24,17 @@ "icon": "assets/audaki_cart_engine/icon.png", "environment": "*", + "entrypoints": { + "main": [ + "audaki.cart_engine.AceMod" + ] + }, "mixins": [ "audaki_cart_engine.mixins.json" ], "depends": { "fabricloader": "*", - "minecraft": ">=1.20 <=1.21.99", + "minecraft": ">=1.21.3 <=1.21.99", "java": ">=17" }, "suggests": {