diff --git a/.github/workflows/build-on-pr.yml b/.github/workflows/build-on-pr.yml index ad8e9989..fbc04aa2 100644 --- a/.github/workflows/build-on-pr.yml +++ b/.github/workflows/build-on-pr.yml @@ -7,13 +7,12 @@ on: [pull_request] jobs: Build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 21 @@ -22,7 +21,7 @@ jobs: run: chmod +x gradlew - name: Build with Gradle run: ./gradlew build - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: "Compiled artifacts for Pull Request #${{github.event.number}}" path: build/libs diff --git a/.github/workflows/devbuild.yml b/.github/workflows/devbuild.yml index 15dbeaf7..379e74c8 100644 --- a/.github/workflows/devbuild.yml +++ b/.github/workflows/devbuild.yml @@ -11,9 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 21 @@ -22,7 +22,7 @@ jobs: run: chmod +x gradlew - name: Build with Gradle run: ./gradlew build - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: Compiled artifacts for ${{ github.sha }} path: build/libs diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 68720486..ab90c42e 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -16,7 +16,7 @@ jobs: extra-branch-curse-version: ${{ steps.properties.outputs.release-extra-curse-version }} steps: - name: Checkout the sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Determine release type id: type run: | @@ -41,7 +41,7 @@ jobs: if ! ${{ steps.properties.outputs.release-extra-branch }}; then echo "matrix-to-exclude=Snapshots" >> $GITHUB_OUTPUT fi - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 env: READ_VERSION: ${{ steps.properties.outputs.mod_version }} with: @@ -78,11 +78,11 @@ jobs: echo "curse-versions=${{ needs.Get-Properties.outputs.curse-versions }}" >> $GITHUB_OUTPUT fi - name: Checkout the sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ steps.getbranchinfo.outputs.branchname }} - name: Set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 21 @@ -97,7 +97,7 @@ jobs: output="$(find build/libs/ ! -name "*-dev.jar" ! -name "*-sources.jar" -type f -printf "%f\n")" echo "jarname=$output" >> $GITHUB_OUTPUT - name: Save build artifacts in the action - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Artifacts for ${{ matrix.branch }} path: build/libs @@ -111,7 +111,7 @@ jobs: asset_name: ${{ steps.findjar.outputs.jarname }} asset_content_type: application/java-archive - name: Upload to Curseforge - uses: itsmeow/curseforge-upload@v3 + uses: itsmeow/curseforge-upload@v3.1.2 with: token: ${{ secrets.CF_API_TOKEN }} project_id: 349239 @@ -125,7 +125,7 @@ jobs: - name: Ask Gradle to publish run: ./gradlew publish - name: Save publish folder in action's artifacts # Remove when automated - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Maven publishing artifacts for ${{ matrix.branch }} path: publish/carpet/fabric-carpet/ @@ -149,7 +149,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: master - name: Merge docs @@ -166,15 +166,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Carpet sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 21 cache: 'gradle' - name: Checkout wiki - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{github.repository}}.wiki path: wiki diff --git a/README-ES.md b/README-ES.md new file mode 100644 index 00000000..ab7559a6 --- /dev/null +++ b/README-ES.md @@ -0,0 +1,66 @@ + + +# Fabric Carpet + +[![Development Builds](https://github.com/gnembon/fabric-carpet/actions/workflows/devbuild.yml/badge.svg)](https://github.com/gnembon/fabric-carpet/actions/workflows/devbuild.yml) +[![CurseForge downloads](http://cf.way2muchnoise.eu/full_349239_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/carpet) +[![Modrinth downloads](https://img.shields.io/modrinth/dt/carpet?label=Modrinth%20downloads&logo=modrinth)](https://modrinth.com/mod/carpet) +[![GitHub downloads](https://img.shields.io/github/downloads/gnembon/fabric-carpet/total?label=Github%20downloads&logo=github)](https://github.com/gnembon/fabric-carpet/releases) +[![GitHub contributors](https://img.shields.io/github/contributors/gnembon/fabric-carpet?label=Contributors&logo=github)](https://github.com/gnembon/fabric-carpet/graphs/contributors) +[![Discord](https://badgen.net/discord/online-members/gn99m4QRY4?icon=discord&label=Discord&list=what)](https://discord.gg/gn99m4QRY4) + +English version of this [docs](https://github.com/gnembon/fabric-carpet/blob/master/README.md) + +Cause all carpets are made of fabric? + +Esto es la [Fabric](https://fabricmc.net/) version del Carpet Mod, para Minecraft 1.14.X, 1.15.X, 1.16.X y siguientes. + +Carpet Mod es un mod para Minecraft Vanilla que permite tener un control total de lo que importa desde la perspectiva tecnica del juego. + +* Prueba tus granjas durante varias horas en tan solo unos minutos con el comando [`/tick warp`](https://github.com/gnembon/fabric-carpet/wiki/Commands#usage-tick-warp-ticks-cmd), tan rapido como tu computadora pueda +* ...da un informe detallado de los items producido usando el comando [`/hopperCounters`](https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings#hoppercounters) +* Ve la mobcap del server, TPS, etc. con actualizaciones en vivo con [`/log`](https://github.com/gnembon/fabric-carpet/wiki/Commands#log) +* Permite a los pistones mover entidades (por ejemplo. cofres) con [`/movableBlockEntities`](https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings#movableblockentities) +* [Arregla](https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings#leadfix) [muchas](https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings#portalsuffocationfix) [cosas](https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings#unloadedentityfix) + +# ecosistema carpet + +Para funcionalidades del ecosistema de carpet este el lugar correcto. Ve las descargas disponibles en [pagina de descargas](https://github.com/gnembon/fabric-carpet/releases) + + + + +## carpet-extra + +Mira [carpet-extra](https://github.com/gnembon/carpet-extra/) mod para mas locas y divertidas funcionalidades, incluyendo mesas de crafteo automaticas, dispensers que ponen bloques, hasta trasquilado de pollos! + +## mesa de crafteo automatica + +Debido a problemas de compatibildias con vanilla y otros mods, descarga [mesa de crafteo automatica](https://github.com/gnembon/carpet-autoCraftingTable/releases) por Skyrising como un addon separado para carpet + +## scarpet app store + +Si quieres buscar o contribuir a las app store de scarpet mira las aplicaciones disponibles, ve [aqui](https://github.com/gnembon/scarpet), es gratis! + +## quick-carpet + +Tienes problemas con las snapshots recientes recientes o alguien necesita la version base de carpet?, pero necesita algunas funcionalidades bases de carpet?, checkea la version minima de [quick-carpet](https://github.com/gnembon/quick-carpet/releases). Va a funcionar bien, no vas a poder agregar extensiones o usar apps de scarpet en este por cierto. + +## Otras extensiones hechas por la comunidad para carpet + +Aqui hay una [lista de otras extensiones de carpet](https://github.com/gnembon/fabric-carpet/wiki/List-of-Carpet-extensions) creadas por la comunidad. + +Cualquiera puede crear sus propias opciones de carpeta o extender el lenguaje scarpet con una nueva API, creando una extension de carpet usando esto [extension de carpet plantilla](https://github.com/gnembon/fabric-carpet-extension-example-mod). + +# Como? Que? + +Mira las instrucciones para los mods de carpeta https://fabricmc.net/use/ y pon [carpet...jar](https://github.com/gnembon/fabric-carpet/releases) en la carpeta `mods` junto a los otros mods compatibles. + +Mira la [demostracion de mods](https://www.youtube.com/watch?v=Lt-ooRGpLz4) en youtube para la explicación de cada uno de las opciones y comandos, y checkea la lista de todas las opciones disponibles en la wiki por una lista actualizada de cada opcion. + +# Carpet Mod Settings +Mira la lista [Lista de todas las configuraciones disponibles][settings] en la wiki + +[settings]: https://github.com/gnembon/fabric-carpet/wiki/Current-Available-Settings + +Para versiones anteriores de Minecraft: 1.13 checkea [gnembon/carpetmod](https://github.com/gnembon/carpetmod) y para 1.12 checkea [gnembon/carpetmod112](https://github.com/gnembon/carpetmod112). diff --git a/README.md b/README.md index e4a03ab8..0b835290 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ [![GitHub contributors](https://img.shields.io/github/contributors/gnembon/fabric-carpet?label=Contributors&logo=github)](https://github.com/gnembon/fabric-carpet/graphs/contributors) [![Discord](https://badgen.net/discord/online-members/gn99m4QRY4?icon=discord&label=Discord&list=what)](https://discord.gg/gn99m4QRY4) +Version en español de esta [documentacion](https://github.com/gnembon/fabric-carpet/blob/master/README-ES.md) + Cause all carpets are made of fabric? This is the [Fabric](https://fabricmc.net/) version of Carpet Mod, for Minecraft 1.14.X, 1.15.X, 1.16.X and above. diff --git a/build.gradle b/build.gradle index f788b207..66610675 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' id 'io.github.juuxel.loom-quiltflower' version '1.7.3' id 'maven-publish' } diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 3c70c645..e59a94f0 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2954,7 +2954,7 @@ It returns a `map` with a report indicating how many chunks were affected, and h Adds a chunk ticket at a position, which makes the game to keep the designated area centered around `pos` with radius of `radius` loaded for a predefined amount of ticks, defined by `type`. Allowed types -are `portal`: 300 ticks, `teleport`: 5 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. +are `portal`: 300 ticks, `teleport`: 40 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. This function is tentative - will likely change when chunk ticket API is properly fleshed out. @@ -4301,8 +4301,8 @@ Recipe type can take one of the following options: * `'smithing'` - smithing table (1.16+) The return value is a list of available recipes (even if there is only one recipe available). Each recipe contains of - an item triple of the crafting result, list of ingredients, each containing a list of possible variants of the - ingredients in this slot, as item triples, or `null` if its a shaped recipe and a given slot in the patterns is left + an item triple of the crafting results as a list of item stacks, list of ingredients, each containing a list of possible variants of the + ingredients in this slot, as item ids, or `null` if it is a shaped recipe and a given slot in the patterns is left empty, and recipe specification as another list. Possible recipe specs is: * `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3. * `['shapeless']` - shapeless crafting @@ -4310,10 +4310,6 @@ Recipe type can take one of the following options: * `['cutting']` - stonecutter recipe * `['special']` - special crafting recipe, typically not present in the crafting menu * `['custom']` - other recipe types - -Note that ingredients are specified as tripes, with count and nbt information. Currently all recipes require always one -of the ingredients, and for some recipes, even if the nbt data for the ingredient is specified (e.g. `dispenser`), it -can accept items of any tags. Also note that some recipes leave some products in the crafting window, and these can be determined using `crafting_remaining_item()` function @@ -4328,7 +4324,7 @@ Also note that some recipes leave some products in the crafting window, and thes ### `crafting_remaining_item(item)` returns `null` if the item has no remaining item in the crafting window when used as a crafting ingredient, or an -item name that serves as a replacement after crafting is done. Currently it can only be buckets and glass bottles. +item tuple that serves as a replacement after crafting is done. Currently, it can only be buckets and glass bottles. ### `inventory_size(inventory)` @@ -5347,7 +5343,7 @@ clients will actually be able to receive (they may have more available via resou Renders a cloud of particles `name` centered around `pos` position, by default `count` 10 of them, default `speed` of 0, and to all players nearby, but these options can be changed via optional arguments. Follow vanilla `/particle` command on details on those options. Valid particle names are -for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`. +for example `'angry_villager', 'item diamond', 'block stone', 'dust{"scale": 4, "color": [0.8, 0.1, 0.1]}'`. Used with no arguments, return the list of available particle names. Note that some of the names do not correspond to a valid particle that can be fed to `particle(...)` function due to a fact that some particles need more configuration @@ -5735,11 +5731,21 @@ Runs a vanilla command from the string result of the `expr` and returns a triple intercepted list of output messages, and error message if the command resulted in a failure. Successful commands return `null` as their error. +The command return `null` if the command was not run immediately, but was scheduled for later execution +due to being requested while command was executed. This happens most commonly +when running `run` from a `/script run/invoke` command since that always results in piling up command to run while `script` is being executed. + +The mitigation for this is to use `run` in a separate scheduled function, or use `run` in a `tick` event, or literally in +any other way than directly from a `/script` command, which will ensure that the command runs immediately. +
-run('fill 1 1 1 10 10 10 air') -> [0, ["Successfully filled 123 blocks"], null]
-run('give @s stone 4') -> [0, ["Gave 4 [Stone] to gnembon"], null]
-run('seed') -> [0, ["Seed: [4031384495743822299]"], null]
-run('sed') -> [0, [], "sed<--[HERE]"] // wrong command
+run('fill 1 1 1 10 10 10 air') -> [123, ["Successfully filled 123 blocks"], null]
+run('give @s stone 4') -> [1, ["Gave 4 [Stone] to gnembon"], null]
+run('seed') -> [-170661413, [Seed: [4031384495743822299]], null]
+run('sed') -> [-1, [], "sed<--[HERE]"] // wrong command
+
+/script run run('setblock 0 0 0 stone') -> null
+/script run schedule(0, _() -> print(run('setblock 0 0 0 stone'))) -> [1, [Changed the block at 0, 0, 0], null]
 
### `save()` diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 8427523e..59d4cb12 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -22,7 +22,7 @@ clients will actually be able to receive (they may have more available via resou Renders a cloud of particles `name` centered around `pos` position, by default `count` 10 of them, default `speed` of 0, and to all players nearby, but these options can be changed via optional arguments. Follow vanilla `/particle` command on details on those options. Valid particle names are -for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`. +for example `'angry_villager', 'item diamond', 'block stone', 'dust{"scale": 4, "color": [0.8, 0.1, 0.1]}'`. Used with no arguments, return the list of available particle names. Note that some of the names do not correspond to a valid particle that can be fed to `particle(...)` function due to a fact that some particles need more configuration @@ -410,11 +410,21 @@ Runs a vanilla command from the string result of the `expr` and returns a triple intercepted list of output messages, and error message if the command resulted in a failure. Successful commands return `null` as their error. +The command return `null` if the command was not run immediately, but was scheduled for later execution +due to being requested while command was executed. This happens most commonly +when running `run` from a `/script run/invoke` command since that always results in piling up command to run while `script` is being executed. + +The mitigation for this is to use `run` in a separate scheduled function, or use `run` in a `tick` event, or literally in +any other way than directly from a `/script` command, which will ensure that the command runs immediately. +
-run('fill 1 1 1 10 10 10 air') -> [0, ["Successfully filled 123 blocks"], null]
-run('give @s stone 4') -> [0, ["Gave 4 [Stone] to gnembon"], null]
-run('seed') -> [0, ["Seed: [4031384495743822299]"], null]
-run('sed') -> [0, [], "sed<--[HERE]"] // wrong command
+run('fill 1 1 1 10 10 10 air') -> [123, ["Successfully filled 123 blocks"], null]
+run('give @s stone 4') -> [1, ["Gave 4 [Stone] to gnembon"], null]
+run('seed') -> [-170661413, [Seed: [4031384495743822299]], null]
+run('sed') -> [-1, [], "sed<--[HERE]"] // wrong command
+
+/script run run('setblock 0 0 0 stone') -> null
+/script run schedule(0, _() -> print(run('setblock 0 0 0 stone'))) -> [1, [Changed the block at 0, 0, 0], null]
 
### `save()` diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index d3f3c10a..a2715a57 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -625,7 +625,7 @@ It returns a `map` with a report indicating how many chunks were affected, and h Adds a chunk ticket at a position, which makes the game to keep the designated area centered around `pos` with radius of `radius` loaded for a predefined amount of ticks, defined by `type`. Allowed types -are `portal`: 300 ticks, `teleport`: 5 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. +are `portal`: 300 ticks, `teleport`: 40 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. This function is tentative - will likely change when chunk ticket API is properly fleshed out. diff --git a/docs/scarpet/api/Inventories.md b/docs/scarpet/api/Inventories.md index 23d07352..f6f6561d 100644 --- a/docs/scarpet/api/Inventories.md +++ b/docs/scarpet/api/Inventories.md @@ -70,8 +70,8 @@ Recipe type can take one of the following options: * `'smithing'` - smithing table (1.16+) The return value is a list of available recipes (even if there is only one recipe available). Each recipe contains of - an item triple of the crafting result, list of ingredients, each containing a list of possible variants of the - ingredients in this slot, as item triples, or `null` if its a shaped recipe and a given slot in the patterns is left + an item triple of the crafting results as a list of item stacks, list of ingredients, each containing a list of possible variants of the + ingredients in this slot, as item ids, or `null` if it is a shaped recipe and a given slot in the patterns is left empty, and recipe specification as another list. Possible recipe specs is: * `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3. * `['shapeless']` - shapeless crafting @@ -79,10 +79,6 @@ Recipe type can take one of the following options: * `['cutting']` - stonecutter recipe * `['special']` - special crafting recipe, typically not present in the crafting menu * `['custom']` - other recipe types - -Note that ingredients are specified as tripes, with count and nbt information. Currently all recipes require always one -of the ingredients, and for some recipes, even if the nbt data for the ingredient is specified (e.g. `dispenser`), it -can accept items of any tags. Also note that some recipes leave some products in the crafting window, and these can be determined using `crafting_remaining_item()` function @@ -97,7 +93,7 @@ Also note that some recipes leave some products in the crafting window, and thes ### `crafting_remaining_item(item)` returns `null` if the item has no remaining item in the crafting window when used as a crafting ingredient, or an -item name that serves as a replacement after crafting is done. Currently it can only be buckets and glass bottles. +item tuple that serves as a replacement after crafting is done. Currently, it can only be buckets and glass bottles. ### `inventory_size(inventory)` diff --git a/gradle.properties b/gradle.properties index d4f14a65..ac006952 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,13 +3,13 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check https://fabricmc.net/develop/ - minecraft_version=1.21.1 - loader_version=0.15.11 + minecraft_version=1.21.8 + loader_version=0.16.14 jsr305_version=3.0.2 - fabric_version=0.99.2+1.21 + fabric_version=0.119.5+1.21.5 # Mod Properties - mod_version = 1.4.147 + mod_version = 1.4.177 maven_group = carpet archives_base_name = fabric-carpet @@ -17,7 +17,7 @@ org.gradle.jvmargs=-Xmx1G # The Curseforge versions "names" or ids for the main branch (comma separated: 1.16.4,1.16.5) # This is needed because CF uses too vague names for prereleases and release candidates # Can also be the version ID directly coming from https://minecraft.curseforge.com/api/game/versions?token=[API_TOKEN] - release-curse-versions = Minecraft 1.21.1:1.21.1 + release-curse-versions = Minecraft 1.21:1.21.7 # Whether or not to build another branch on release release-extra-branch = false # The name of the second branch to release @@ -25,4 +25,4 @@ org.gradle.jvmargs=-Xmx1G # The "name" or id of the Curseforge version for the secondary branch # This is needed because CF uses too vague names for snapshots # Can also be the version ID directly coming from https://minecraft.curseforge.com/api/game/versions?token=[API_TOKEN] - release-extra-curse-version = Minecraft 1.20:1.20.4-Snapshot \ No newline at end of file + release-extra-curse-version = Minecraft 1.20:1.20.4-Snapshot diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 509c4a29..21d5e095 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.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index ac102ace..65ffb8ad 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -40,6 +40,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.commands.PerfCommand; import net.minecraft.server.level.ServerPlayer; +import javax.annotation.Nullable; + public class CarpetServer // static for now - easier to handle all around the code, its one anyways { public static MinecraftServer minecraft_server; @@ -172,7 +174,7 @@ public class CarpetServer // static for now - easier to handle all around the co scriptServer = null; } - public static void onServerClosed(MinecraftServer server) + public static void onServerClosed(@Nullable MinecraftServer server) { // this for whatever reason gets called multiple times even when joining on SP // so we allow to pass multiple times gating it only on existing server ref @@ -180,7 +182,7 @@ public class CarpetServer // static for now - easier to handle all around the co { if (scriptServer != null) scriptServer.onClose(); // this is a mess, will cleanip onlly when global reference is gone - if (!Vanilla.MinecraftServer_getScriptServer(server).stopAll) { + if (server != null && !Vanilla.MinecraftServer_getScriptServer(server).stopAll) { Vanilla.MinecraftServer_getScriptServer(server).onClose(); } diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 61253d59..338d1e0b 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -73,7 +73,7 @@ public class CarpetSettings @Rule( desc = "Sets the language for Carpet", category = FEATURE, - options = {"en_us", "fr_fr", "pt_br", "zh_cn", "zh_tw"}, + options = {"en_us", "fr_fr", "es_ar","pt_br", "zh_cn", "zh_tw"}, strict = true, // the current system doesn't handle fallbacks and other, not defined languages would make unreadable mess. Change later validate = LanguageValidator.class ) @@ -908,7 +908,7 @@ public class CarpetSettings @Override public String validate(CommandSourceStack source, CarpetRule currentRule, String newValue, String string) { if (source == null) return newValue; // closing or sync - Optional ignoredBlock = source.registryAccess().registryOrThrow(Registries.BLOCK).getOptional(ResourceLocation.tryParse(newValue)); + Optional ignoredBlock = source.registryAccess().lookupOrThrow(Registries.BLOCK).getOptional(ResourceLocation.tryParse(newValue)); if (!ignoredBlock.isPresent()) { Messenger.m(source, "r Unknown block '" + newValue + "'."); return null; diff --git a/src/main/java/carpet/api/settings/SettingsManager.java b/src/main/java/carpet/api/settings/SettingsManager.java index b8a0430f..2b4f341b 100644 --- a/src/main/java/carpet/api/settings/SettingsManager.java +++ b/src/main/java/carpet/api/settings/SettingsManager.java @@ -25,6 +25,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import carpet.script.Expression; import com.google.common.collect.Sets; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; @@ -304,7 +305,7 @@ public class SettingsManager { /** * Calling this method is not supported. */ - public void inspectClientsideCommand(CommandSourceStack source, String string) + public void inspectClientsideCommand(String string) { if (string.startsWith("/" + identifier + " ")) { @@ -316,9 +317,9 @@ public class SettingsManager { if (rules.containsKey(rule) && rules.get(rule).canBeToggledClientSide()) { try { - rules.get(rule).set(source, strOption); + rules.get(rule).set(null, strOption); } catch (InvalidRuleValueException e) { - e.notifySource(rule, source); + //e.notifySource(rule, source); } } } @@ -331,7 +332,7 @@ public class SettingsManager { { if (RuleHelper.getBooleanValue(rule) || (rule.type() == String.class && !rule.value().equals("false"))) { - CarpetServer.scriptServer.addScriptHost(source, rule.scarpetApp, s -> CommandHelper.canUseCommand(s, rule.value()), false, false, true, null); + CarpetServer.scriptServer.addScriptHost(source, rule.scarpetApp, s -> CommandHelper.canUseCommand(s, rule.value()), false, false, true, null, Expression.LoadOverride.DEFAULT); } else { CarpetServer.scriptServer.removeScriptHost(source, rule.scarpetApp, false, true); } diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 17fddef9..3b5f3f79 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -241,7 +241,7 @@ public class DrawCommand } if (CarpetSettings.fillUpdates) { - list.forEach(blockpos1 -> world.blockUpdated(blockpos1, world.getBlockState(blockpos1).getBlock())); + list.forEach(blockpos1 -> world.updateNeighborsAt(blockpos1, world.getBlockState(blockpos1).getBlock())); } Messenger.m(ctx.getSource(), "gi Filled " + affected + " blocks"); return affected; @@ -291,7 +291,7 @@ public class DrawCommand if (CarpetSettings.fillUpdates) { - list.forEach(p -> world.blockUpdated(p, world.getBlockState(p).getBlock())); + list.forEach(p -> world.updateNeighborsAt(p, world.getBlockState(p).getBlock())); } Messenger.m(source, "gi Filled " + affected + " blocks"); @@ -390,7 +390,7 @@ public class DrawCommand for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); - world.blockUpdated(blockpos1, blokc); + world.updateNeighborsAt(blockpos1, blokc); } } @@ -441,7 +441,7 @@ public class DrawCommand for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); - world.blockUpdated(blockpos1, blokc); + world.updateNeighborsAt(blockpos1, blokc); } } diff --git a/src/main/java/carpet/commands/PerimeterInfoCommand.java b/src/main/java/carpet/commands/PerimeterInfoCommand.java index 4bb82f91..d409926f 100644 --- a/src/main/java/carpet/commands/PerimeterInfoCommand.java +++ b/src/main/java/carpet/commands/PerimeterInfoCommand.java @@ -15,6 +15,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; @@ -39,7 +40,7 @@ public class PerimeterInfoCommand BlockPosArgument.getSpawnablePos(c, "center position"), null)). then(argument("mob", resource(commandBuildContext, Registries.ENTITY_TYPE)). - suggests(SuggestionProviders.SUMMONABLE_ENTITIES). + suggests(SuggestionProviders.cast(SuggestionProviders.SUMMONABLE_ENTITIES)). executes( (c) -> perimeterDiagnose( c.getSource(), BlockPosArgument.getSpawnablePos(c, "center position"), @@ -55,8 +56,8 @@ public class PerimeterInfoCommand if (mobId != null) { nbttagcompound.putString("id", mobId); - Entity baseEntity = EntityType.loadEntityRecursive(nbttagcompound, source.getLevel(), (entity_1x) -> { - entity_1x.moveTo(new BlockPos(pos.getX(), source.getLevel().getMinBuildHeight()-10, pos.getZ()), entity_1x.getYRot(), entity_1x. getXRot()); + Entity baseEntity = EntityType.loadEntityRecursive(nbttagcompound, source.getLevel(), EntitySpawnReason.COMMAND, (entity_1x) -> { + entity_1x.snapTo(new BlockPos(pos.getX(), source.getLevel().getMinY()-10, pos.getZ()), entity_1x.getYRot(), entity_1x. getXRot()); return !source.getLevel().addWithUUID(entity_1x) ? null : entity_1x; }); if (!(baseEntity instanceof Mob)) diff --git a/src/main/java/carpet/commands/PlayerCommand.java b/src/main/java/carpet/commands/PlayerCommand.java index fd5ddf00..7284f33d 100644 --- a/src/main/java/carpet/commands/PlayerCommand.java +++ b/src/main/java/carpet/commands/PlayerCommand.java @@ -181,7 +181,13 @@ public class PlayerCommand { MinecraftServer server = context.getSource().getServer(); PlayerList manager = server.getPlayerList(); - if (manager.getPlayerByName(playerName) != null) { + if (EntityPlayerMPFake.isSpawningPlayer(playerName)) + { + Messenger.m(context.getSource(), "r Player ", "rb " + playerName, "r is currently logging on"); + return true; + } + if (manager.getPlayerByName(playerName) != null) + { Messenger.m(context.getSource(), "r Player ", "rb " + playerName, "r is already logged on"); return true; } @@ -215,7 +221,8 @@ public class PlayerCommand { private static int kill(CommandContext context) { if (cantReMove(context)) return 0; - getPlayer(context).kill(); + ServerPlayer player = getPlayer(context); + player.kill(player.level()); return 1; } @@ -314,7 +321,7 @@ public class PlayerCommand { return 0; } - EntityPlayerMPFake.createShadow(player.server, player); + EntityPlayerMPFake.createShadow(player.getServer(), player); return 1; } } diff --git a/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java b/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java deleted file mode 100644 index 2a01ed8c..00000000 --- a/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -package carpet.fakes; - -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.Ticket; -import net.minecraft.util.SortedArraySet; -import net.minecraft.world.level.ChunkPos; - -public interface ChunkTicketManagerInterface -{ - void changeSpawnChunks(ChunkPos pos, int distance); - - Long2ObjectOpenHashMap>> getTicketsByPosition(); - - void replaceHolder(ChunkHolder oldHolder, ChunkHolder newHolder); -} diff --git a/src/main/java/carpet/fakes/DefaultRedstoneWireEvaluatorInferface.java b/src/main/java/carpet/fakes/DefaultRedstoneWireEvaluatorInferface.java new file mode 100644 index 00000000..b394aaf7 --- /dev/null +++ b/src/main/java/carpet/fakes/DefaultRedstoneWireEvaluatorInferface.java @@ -0,0 +1,10 @@ +package carpet.fakes; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + + +public interface DefaultRedstoneWireEvaluatorInferface +{ + int calculateTargetStrengthCM(final Level level, final BlockPos pos); +} diff --git a/src/main/java/carpet/fakes/FoodDataInterface.java b/src/main/java/carpet/fakes/FoodDataInterface.java new file mode 100644 index 00000000..82dafee8 --- /dev/null +++ b/src/main/java/carpet/fakes/FoodDataInterface.java @@ -0,0 +1,8 @@ +package carpet.fakes; + +public interface FoodDataInterface +{ + float getCMExhaustionLevel(); + + void setExhaustion(float aFloat); +} diff --git a/src/main/java/carpet/fakes/IngredientInterface.java b/src/main/java/carpet/fakes/IngredientInterface.java index f6d93854..22ef94e3 100644 --- a/src/main/java/carpet/fakes/IngredientInterface.java +++ b/src/main/java/carpet/fakes/IngredientInterface.java @@ -10,5 +10,5 @@ public interface IngredientInterface * Gets all the stacks of the ingredients for a given item recipe. Also used for {@link carpet.helpers.HopperCounter#guessColor} * to guess the colour of an item to display it prettily */ - List> getRecipeStacks(); + //List> getRecipeStacks(); } diff --git a/src/main/java/carpet/fakes/RecipeManagerInterface.java b/src/main/java/carpet/fakes/RecipeManagerInterface.java deleted file mode 100644 index 78cfe428..00000000 --- a/src/main/java/carpet/fakes/RecipeManagerInterface.java +++ /dev/null @@ -1,17 +0,0 @@ -package carpet.fakes; - -import java.util.List; - -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; - -public interface RecipeManagerInterface -{ - /** - * Gets all the recipes for a given item. Also used for {@link carpet.helpers.HopperCounter#guessColor} to guess the - * colour of an item to display it prettily - */ - List> getAllMatching(final RecipeType type, final ResourceLocation itemId, final RegistryAccess registryAccess); -} diff --git a/src/main/java/carpet/fakes/TicketsFetcherInterface.java b/src/main/java/carpet/fakes/TicketsFetcherInterface.java new file mode 100644 index 00000000..7bc6055a --- /dev/null +++ b/src/main/java/carpet/fakes/TicketsFetcherInterface.java @@ -0,0 +1,11 @@ +package carpet.fakes; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.Ticket; + +import java.util.List; + +public interface TicketsFetcherInterface +{ + Long2ObjectOpenHashMap> getTicketsByPosition(); +} diff --git a/src/main/java/carpet/fakes/WorldChunkInterface.java b/src/main/java/carpet/fakes/WorldChunkInterface.java index d93b0a1d..22a8c1db 100644 --- a/src/main/java/carpet/fakes/WorldChunkInterface.java +++ b/src/main/java/carpet/fakes/WorldChunkInterface.java @@ -6,5 +6,5 @@ import net.minecraft.world.level.block.state.BlockState; public interface WorldChunkInterface { - BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, boolean boolean1); + BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, int flags); } diff --git a/src/main/java/carpet/helpers/BlockRotator.java b/src/main/java/carpet/helpers/BlockRotator.java index a815c8da..8584148f 100644 --- a/src/main/java/carpet/helpers/BlockRotator.java +++ b/src/main/java/carpet/helpers/BlockRotator.java @@ -100,7 +100,7 @@ public class BlockRotator } } // Send block update to the block that just have been rotated. - world.neighborChanged(blockpos, block, source.pos()); + world.neighborChanged(blockpos, block, null); return stack; } diff --git a/src/main/java/carpet/helpers/EntityPlayerActionPack.java b/src/main/java/carpet/helpers/EntityPlayerActionPack.java index e0601ea2..dc73346f 100644 --- a/src/main/java/carpet/helpers/EntityPlayerActionPack.java +++ b/src/main/java/carpet/helpers/EntityPlayerActionPack.java @@ -11,7 +11,7 @@ import carpet.script.utils.Tracer; import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; +import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -274,15 +274,15 @@ public class EntityPlayerActionPack else // one slot { if (selectedSlot == -1) - selectedSlot = inv.selected; + selectedSlot = inv.getSelectedSlot(); dropItemFromSlot(selectedSlot, dropAll); } } public void setSlot(int slot) { - player.getInventory().selected = slot-1; - player.connection.send(new ClientboundSetCarriedItemPacket(slot-1)); + player.getInventory().setSelectedSlot(slot-1); + player.connection.send(new ClientboundSetHeldSlotPacket(slot-1)); } public enum ActionType @@ -310,16 +310,16 @@ public class EntityPlayerActionPack case BLOCK: { player.resetLastActionTime(); - ServerLevel world = player.serverLevel(); + ServerLevel world = player.level(); BlockHitResult blockHit = (BlockHitResult) hit; BlockPos pos = blockHit.getBlockPos(); Direction side = blockHit.getDirection(); - if (pos.getY() < player.level().getMaxBuildHeight() - (side == Direction.UP ? 1 : 0) && world.mayInteract(player, pos)) + if (pos.getY() < player.level().getMaxY() - (side == Direction.UP ? 1 : 0) && world.mayInteract(player, pos)) { InteractionResult result = player.gameMode.useItemOn(player, world, player.getItemInHand(hand), hand, blockHit); - if (result.consumesAction()) + if (result instanceof InteractionResult.Success success) { - if (result.shouldSwing()) player.swing(hand); + if (success.swingSource() == InteractionResult.SwingSource.SERVER) player.swing(hand); ap.itemUseCooldown = 3; return true; } @@ -402,7 +402,7 @@ public class EntityPlayerActionPack boolean blockBroken = false; if (player.gameMode.getGameModeForPlayer().isCreative()) { - player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, side, player.level().getMaxBuildHeight(), -1); + player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, side, player.level().getMaxY(), -1); ap.blockHitDelay = 5; blockBroken = true; } @@ -410,9 +410,9 @@ public class EntityPlayerActionPack { if (ap.currentBlock != null) { - player.gameMode.handleBlockBreakAction(ap.currentBlock, ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, side, player.level().getMaxBuildHeight(), -1); + player.gameMode.handleBlockBreakAction(ap.currentBlock, ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, side, player.level().getMaxY(), -1); } - player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, side, player.level().getMaxBuildHeight(), -1); + player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, side, player.level().getMaxY(), -1); boolean notAir = !state.isAir(); if (notAir && ap.curBlockDamageMP == 0) { @@ -435,7 +435,7 @@ public class EntityPlayerActionPack ap.curBlockDamageMP += state.getDestroyProgress(player, player.level(), pos); if (ap.curBlockDamageMP >= 1) { - player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, side, player.level().getMaxBuildHeight(), -1); + player.gameMode.handleBlockBreakAction(pos, ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, side, player.level().getMaxY(), -1); ap.currentBlock = null; ap.blockHitDelay = 5; blockBroken = true; @@ -457,7 +457,7 @@ public class EntityPlayerActionPack EntityPlayerActionPack ap = ((ServerPlayerInterface) player).getActionPack(); if (ap.currentBlock == null) return; player.level().destroyBlockProgress(-1, ap.currentBlock, -1); - player.gameMode.handleBlockBreakAction(ap.currentBlock, ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, Direction.DOWN, player.level().getMaxBuildHeight(), -1); + player.gameMode.handleBlockBreakAction(ap.currentBlock, ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, Direction.DOWN, player.level().getMaxY(), -1); ap.currentBlock = null; } }, diff --git a/src/main/java/carpet/helpers/FertilizableCoral.java b/src/main/java/carpet/helpers/FertilizableCoral.java index 9c8bd43d..3f7447fe 100644 --- a/src/main/java/carpet/helpers/FertilizableCoral.java +++ b/src/main/java/carpet/helpers/FertilizableCoral.java @@ -58,7 +58,7 @@ public interface FertilizableCoral extends BonemealableBlock { MapColor color = blockUnder.getMapColor(worldIn, pos); BlockState properBlock = blockUnder; - HolderSet.Named coralBlocks = worldIn.registryAccess().registryOrThrow(Registries.BLOCK).getTag(BlockTags.CORAL_BLOCKS).orElseThrow(); + HolderSet.Named coralBlocks = worldIn.registryAccess().lookupOrThrow(Registries.BLOCK).get(BlockTags.CORAL_BLOCKS).orElseThrow(); for (Holder block: coralBlocks) { properBlock = block.value().defaultBlockState(); diff --git a/src/main/java/carpet/helpers/HopperCounter.java b/src/main/java/carpet/helpers/HopperCounter.java index 3e419e83..3fc8ca68 100644 --- a/src/main/java/carpet/helpers/HopperCounter.java +++ b/src/main/java/carpet/helpers/HopperCounter.java @@ -1,12 +1,12 @@ package carpet.helpers; import carpet.CarpetServer; -import carpet.fakes.IngredientInterface; -import carpet.fakes.RecipeManagerInterface; +import carpet.script.utils.RecipeHelper; import carpet.utils.Messenger; import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; import net.minecraft.ChatFormatting; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; @@ -24,7 +24,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.AbstractBannerBlock; import net.minecraft.world.level.block.BeaconBeamBlock; import net.minecraft.world.level.block.Block; @@ -32,12 +32,12 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.material.MapColor; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static java.util.Map.entry; @@ -102,7 +102,9 @@ public class HopperCounter this.color = color; String hexColor = Integer.toHexString(color.getTextColor()); if (hexColor.length() < 6) + { hexColor = "0".repeat(6 - hexColor.length()) + hexColor; + } this.coloredName = '#' + hexColor + ' ' + color.getName(); } @@ -136,6 +138,7 @@ public class HopperCounter /** * Resets all counters, clearing their items. + * * @param fresh Whether or not to start the clocks going immediately or later. */ public static void resetAll(MinecraftServer server, boolean fresh) @@ -143,7 +146,10 @@ public class HopperCounter for (HopperCounter counter : COUNTERS.values()) { counter.reset(server); - if (fresh) counter.startTick = -1; + if (fresh) + { + counter.startTick = -1; + } } } @@ -159,7 +165,10 @@ public class HopperCounter List temp = counter.format(server, realtime, false); if (temp.size() > 1) { - if (!text.isEmpty()) text.add(Messenger.s("")); + if (!text.isEmpty()) + { + text.add(Messenger.s("")); + } text.addAll(temp); } } @@ -181,7 +190,7 @@ public class HopperCounter { if (brief) { - return Collections.singletonList(Messenger.c("b"+coloredName,"w : ","gi -, -/h, - min ")); + return Collections.singletonList(Messenger.c("b" + coloredName, "w : ", "gi -, -/h, - min ")); } return Collections.singletonList(Messenger.c(coloredName, "w hasn't started counting yet")); } @@ -190,36 +199,36 @@ public class HopperCounter { if (brief) { - return Collections.singletonList(Messenger.c("b"+coloredName,"w : ","wb 0","w , ","wb 0","w /h, ", String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min")); + return Collections.singletonList(Messenger.c("b" + coloredName, "w : ", "wb 0", "w , ", "wb 0", "w /h, ", String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min")); } return Collections.singletonList(Messenger.c("w No items for ", coloredName, String.format("w yet (%.2f min.%s)", - ticks / (20.0 * 60.0), (realTime ? " - real time" : "")), - "nb [X]", "^g reset", "!/counter " + color.getName() +" reset")); + ticks / (20.0 * 60.0), (realTime ? " - real time" : "")), + "nb [X]", "^g reset", "!/counter " + color.getName() + " reset")); } if (brief) { - return Collections.singletonList(Messenger.c("b"+coloredName,"w : ", - "wb "+total,"w , ", - "wb "+(total * (20 * 60 * 60) / ticks),"w /h, ", + return Collections.singletonList(Messenger.c("b" + coloredName, "w : ", + "wb " + total, "w , ", + "wb " + (total * (20 * 60 * 60) / ticks), "w /h, ", String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min" )); } List items = new ArrayList<>(); items.add(Messenger.c("w Items for ", coloredName, - "w (",String.format("wb %.2f", ticks*1.0/(20*60)), "w min"+(realTime?" - real time":"")+"), ", - "w total: ", "wb "+total, "w , (",String.format("wb %.1f",total*1.0*(20*60*60)/ticks),"w /h):", - "nb [X]", "^g reset", "!/counter "+color+" reset" + "w (", String.format("wb %.2f", ticks * 1.0 / (20 * 60)), "w min" + (realTime ? " - real time" : "") + "), ", + "w total: ", "wb " + total, "w , (", String.format("wb %.1f", total * 1.0 * (20 * 60 * 60) / ticks), "w /h):", + "nb [X]", "^g reset", "!/counter " + color + " reset" )); items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(e -> { Item item = e.getKey(); MutableComponent itemName = Component.translatable(item.getDescriptionId()); Style itemStyle = itemName.getStyle(); - TextColor color = guessColor(item, server.registryAccess()); + TextColor color = guessColor(item, server.overworld()); itemName.setStyle((color != null) ? itemStyle.withColor(color) : itemStyle.withItalic(true)); long count = e.getLongValue(); return Messenger.c("g - ", itemName, - "g : ","wb "+count,"g , ", + "g : ", "wb " + count, "g , ", String.format("wb %.1f", count * (20.0 * 60.0 * 60.0) / ticks), "w /h" ); }).collect(Collectors.toList())); @@ -232,13 +241,25 @@ public class HopperCounter */ public static int appropriateColor(int color) { - if (color == 0) return MapColor.SNOW.col; + if (color == 0) + { + return MapColor.SNOW.col; + } int r = (color >> 16 & 255); int g = (color >> 8 & 255); int b = (color & 255); - if (r < 70) r = 70; - if (g < 70) g = 70; - if (b < 70) b = 70; + if (r < 70) + { + r = 70; + } + if (g < 70) + { + g = 70; + } + if (b < 70) + { + b = 70; + } return (r << 16) + (g << 8) + b; } @@ -272,65 +293,65 @@ public class HopperCounter entry(Items.ROSE_BUSH, Blocks.RED_WOOL), entry(Items.PEONY, Blocks.PINK_WOOL), entry(Items.CARROT, Blocks.ORANGE_WOOL), - entry(Items.APPLE,Blocks.RED_WOOL), - entry(Items.WHEAT,Blocks.HAY_BLOCK), + entry(Items.APPLE, Blocks.RED_WOOL), + entry(Items.WHEAT, Blocks.HAY_BLOCK), entry(Items.PORKCHOP, Blocks.PINK_WOOL), - entry(Items.RABBIT,Blocks.PINK_WOOL), - entry(Items.CHICKEN,Blocks.WHITE_TERRACOTTA), - entry(Items.BEEF,Blocks.NETHERRACK), - entry(Items.ENCHANTED_GOLDEN_APPLE,Blocks.GOLD_BLOCK), - entry(Items.COD,Blocks.WHITE_TERRACOTTA), - entry(Items.SALMON,Blocks.ACACIA_PLANKS), - entry(Items.ROTTEN_FLESH,Blocks.BROWN_WOOL), - entry(Items.PUFFERFISH,Blocks.YELLOW_TERRACOTTA), - entry(Items.TROPICAL_FISH,Blocks.ORANGE_WOOL), - entry(Items.POTATO,Blocks.WHITE_TERRACOTTA), + entry(Items.RABBIT, Blocks.PINK_WOOL), + entry(Items.CHICKEN, Blocks.WHITE_TERRACOTTA), + entry(Items.BEEF, Blocks.NETHERRACK), + entry(Items.ENCHANTED_GOLDEN_APPLE, Blocks.GOLD_BLOCK), + entry(Items.COD, Blocks.WHITE_TERRACOTTA), + entry(Items.SALMON, Blocks.ACACIA_PLANKS), + entry(Items.ROTTEN_FLESH, Blocks.BROWN_WOOL), + entry(Items.PUFFERFISH, Blocks.YELLOW_TERRACOTTA), + entry(Items.TROPICAL_FISH, Blocks.ORANGE_WOOL), + entry(Items.POTATO, Blocks.WHITE_TERRACOTTA), entry(Items.MUTTON, Blocks.RED_WOOL), - entry(Items.BEETROOT,Blocks.NETHERRACK), - entry(Items.MELON_SLICE,Blocks.MELON), - entry(Items.POISONOUS_POTATO,Blocks.SLIME_BLOCK), - entry(Items.SPIDER_EYE,Blocks.NETHERRACK), - entry(Items.GUNPOWDER,Blocks.GRAY_WOOL), - entry(Items.TURTLE_SCUTE,Blocks.LIME_WOOL), - entry(Items.ARMADILLO_SCUTE,Blocks.ANCIENT_DEBRIS), - entry(Items.FEATHER,Blocks.WHITE_WOOL), - entry(Items.FLINT,Blocks.BLACK_WOOL), - entry(Items.LEATHER,Blocks.SPRUCE_PLANKS), - entry(Items.GLOWSTONE_DUST,Blocks.GLOWSTONE), - entry(Items.PAPER,Blocks.WHITE_WOOL), - entry(Items.BRICK,Blocks.BRICKS), - entry(Items.INK_SAC,Blocks.BLACK_WOOL), - entry(Items.SNOWBALL,Blocks.SNOW_BLOCK), - entry(Items.WATER_BUCKET,Blocks.WATER), - entry(Items.LAVA_BUCKET,Blocks.LAVA), - entry(Items.MILK_BUCKET,Blocks.WHITE_WOOL), + entry(Items.BEETROOT, Blocks.NETHERRACK), + entry(Items.MELON_SLICE, Blocks.MELON), + entry(Items.POISONOUS_POTATO, Blocks.SLIME_BLOCK), + entry(Items.SPIDER_EYE, Blocks.NETHERRACK), + entry(Items.GUNPOWDER, Blocks.GRAY_WOOL), + entry(Items.TURTLE_SCUTE, Blocks.LIME_WOOL), + entry(Items.ARMADILLO_SCUTE, Blocks.ANCIENT_DEBRIS), + entry(Items.FEATHER, Blocks.WHITE_WOOL), + entry(Items.FLINT, Blocks.BLACK_WOOL), + entry(Items.LEATHER, Blocks.SPRUCE_PLANKS), + entry(Items.GLOWSTONE_DUST, Blocks.GLOWSTONE), + entry(Items.PAPER, Blocks.WHITE_WOOL), + entry(Items.BRICK, Blocks.BRICKS), + entry(Items.INK_SAC, Blocks.BLACK_WOOL), + entry(Items.SNOWBALL, Blocks.SNOW_BLOCK), + entry(Items.WATER_BUCKET, Blocks.WATER), + entry(Items.LAVA_BUCKET, Blocks.LAVA), + entry(Items.MILK_BUCKET, Blocks.WHITE_WOOL), entry(Items.CLAY_BALL, Blocks.CLAY), - entry(Items.COCOA_BEANS,Blocks.COCOA), - entry(Items.BONE,Blocks.BONE_BLOCK), - entry(Items.COD_BUCKET,Blocks.BROWN_TERRACOTTA), - entry(Items.PUFFERFISH_BUCKET,Blocks.YELLOW_TERRACOTTA), - entry(Items.SALMON_BUCKET,Blocks.PINK_TERRACOTTA), - entry(Items.TROPICAL_FISH_BUCKET,Blocks.ORANGE_TERRACOTTA), - entry(Items.SUGAR,Blocks.WHITE_WOOL), - entry(Items.BLAZE_POWDER,Blocks.GOLD_BLOCK), - entry(Items.ENDER_PEARL,Blocks.WARPED_PLANKS), - entry(Items.NETHER_STAR,Blocks.DIAMOND_BLOCK), - entry(Items.PRISMARINE_CRYSTALS,Blocks.SEA_LANTERN), - entry(Items.PRISMARINE_SHARD,Blocks.PRISMARINE), - entry(Items.RABBIT_HIDE,Blocks.OAK_PLANKS), - entry(Items.CHORUS_FRUIT,Blocks.PURPUR_BLOCK), - entry(Items.SHULKER_SHELL,Blocks.SHULKER_BOX), - entry(Items.NAUTILUS_SHELL,Blocks.BONE_BLOCK), - entry(Items.HEART_OF_THE_SEA,Blocks.CONDUIT), - entry(Items.HONEYCOMB,Blocks.HONEYCOMB_BLOCK), - entry(Items.NAME_TAG,Blocks.BONE_BLOCK), - entry(Items.TOTEM_OF_UNDYING,Blocks.YELLOW_TERRACOTTA), - entry(Items.TRIDENT,Blocks.PRISMARINE), - entry(Items.GHAST_TEAR,Blocks.WHITE_WOOL), - entry(Items.PHANTOM_MEMBRANE,Blocks.BONE_BLOCK), - entry(Items.EGG,Blocks.BONE_BLOCK), + entry(Items.COCOA_BEANS, Blocks.COCOA), + entry(Items.BONE, Blocks.BONE_BLOCK), + entry(Items.COD_BUCKET, Blocks.BROWN_TERRACOTTA), + entry(Items.PUFFERFISH_BUCKET, Blocks.YELLOW_TERRACOTTA), + entry(Items.SALMON_BUCKET, Blocks.PINK_TERRACOTTA), + entry(Items.TROPICAL_FISH_BUCKET, Blocks.ORANGE_TERRACOTTA), + entry(Items.SUGAR, Blocks.WHITE_WOOL), + entry(Items.BLAZE_POWDER, Blocks.GOLD_BLOCK), + entry(Items.ENDER_PEARL, Blocks.WARPED_PLANKS), + entry(Items.NETHER_STAR, Blocks.DIAMOND_BLOCK), + entry(Items.PRISMARINE_CRYSTALS, Blocks.SEA_LANTERN), + entry(Items.PRISMARINE_SHARD, Blocks.PRISMARINE), + entry(Items.RABBIT_HIDE, Blocks.OAK_PLANKS), + entry(Items.CHORUS_FRUIT, Blocks.PURPUR_BLOCK), + entry(Items.SHULKER_SHELL, Blocks.SHULKER_BOX), + entry(Items.NAUTILUS_SHELL, Blocks.BONE_BLOCK), + entry(Items.HEART_OF_THE_SEA, Blocks.CONDUIT), + entry(Items.HONEYCOMB, Blocks.HONEYCOMB_BLOCK), + entry(Items.NAME_TAG, Blocks.BONE_BLOCK), + entry(Items.TOTEM_OF_UNDYING, Blocks.YELLOW_TERRACOTTA), + entry(Items.TRIDENT, Blocks.PRISMARINE), + entry(Items.GHAST_TEAR, Blocks.WHITE_WOOL), + entry(Items.PHANTOM_MEMBRANE, Blocks.BONE_BLOCK), + entry(Items.EGG, Blocks.BONE_BLOCK), //entry(Items.,Blocks.), - entry(Items.COPPER_INGOT,Blocks.COPPER_BLOCK), + entry(Items.COPPER_INGOT, Blocks.COPPER_BLOCK), entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK)); /** @@ -338,11 +359,17 @@ public class HopperCounter */ public static TextColor fromItem(Item item, RegistryAccess registryAccess) { - if (DEFAULTS.containsKey(item)) return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col)); - if (item instanceof DyeItem dye) return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col)); + if (DEFAULTS.containsKey(item)) + { + return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col)); + } + if (item instanceof DyeItem dye) + { + return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col)); + } Block block = null; - final Registry itemRegistry = registryAccess.registryOrThrow(Registries.ITEM); - final Registry blockRegistry = registryAccess.registryOrThrow(Registries.BLOCK); + final Registry itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM); + final Registry blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK); ResourceLocation id = itemRegistry.getKey(item); if (item instanceof BlockItem blockItem) { @@ -350,13 +377,19 @@ public class HopperCounter } else if (blockRegistry.getOptional(id).isPresent()) { - block = blockRegistry.get(id); + block = blockRegistry.getValue(id); } if (block != null) { - if (block instanceof AbstractBannerBlock) return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col)); - if (block instanceof BeaconBeamBlock) return TextColor.fromRgb(appropriateColor( ((BeaconBeamBlock) block).getColor().getMapColor().col)); - return TextColor.fromRgb(appropriateColor( block.defaultMapColor().col)); + if (block instanceof AbstractBannerBlock) + { + return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col)); + } + if (block instanceof BeaconBeamBlock) + { + return TextColor.fromRgb(appropriateColor(((BeaconBeamBlock) block).getColor().getMapColor().col)); + } + return TextColor.fromRgb(appropriateColor(block.defaultMapColor().col)); } return null; } @@ -365,38 +398,45 @@ public class HopperCounter * Guesses the item's colour from the item itself. It first calls {@link HopperCounter#fromItem} to see if it has a * valid colour there, if not just makes a guess, and if that fails just returns null */ - public static TextColor guessColor(Item item, RegistryAccess registryAccess) + public static TextColor guessColor(Item item, Level level) { + RegistryAccess registryAccess = level.registryAccess(); TextColor direct = fromItem(item, registryAccess); - if (direct != null) return direct; - if (CarpetServer.minecraft_server == null) return WHITE; - - ResourceLocation id = registryAccess.registryOrThrow(Registries.ITEM).getKey(item); - for (RecipeType type: registryAccess.registryOrThrow(Registries.RECIPE_TYPE)) + if (direct != null) { - for (Recipe r: ((RecipeManagerInterface) CarpetServer.minecraft_server.getRecipeManager()).getAllMatching(type, id, registryAccess)) + return direct; + } + if (CarpetServer.minecraft_server == null) + { + return WHITE; + } + + ResourceLocation id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item); + if (id == null) + { + return null; + } + + for (Recipe r : RecipeHelper.getRecipesForOutput(CarpetServer.minecraft_server.getRecipeManager(), id, level)) + { + for (Ingredient ingredient : r.placementInfo().ingredients()) { - for (Ingredient ingredient: r.getIngredients()) + Optional> match = ingredient.items().filter(stack -> fromItem(stack.value(), registryAccess) != null).findFirst(); + if (match.isPresent()) { - for (Collection stacks : ((IngredientInterface) (Object) ingredient).getRecipeStacks()) - { - for (ItemStack iStak : stacks) - { - TextColor cand = fromItem(iStak.getItem(), registryAccess); - if (cand != null) - return cand; - } - } + return fromItem(match.get().value(), registryAccess); } } } + return null; } /** * Returns the hopper counter for the given color */ - public static HopperCounter getCounter(DyeColor color) { + public static HopperCounter getCounter(DyeColor color) + { return COUNTERS.get(color); } @@ -421,6 +461,6 @@ public class HopperCounter */ public long getTotalItems() { - return counter.isEmpty()?0:counter.values().longStream().sum(); + return counter.isEmpty() ? 0 : counter.values().longStream().sum(); } } diff --git a/src/main/java/carpet/helpers/OptimizedExplosion.java b/src/main/java/carpet/helpers/OptimizedExplosion.java index 63bc00b9..f35b6027 100644 --- a/src/main/java/carpet/helpers/OptimizedExplosion.java +++ b/src/main/java/carpet/helpers/OptimizedExplosion.java @@ -1,80 +1,39 @@ package carpet.helpers; //Author: masa -import java.math.RoundingMode; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import carpet.logging.logHelpers.ExplosionLogHelper; import carpet.mixins.ExplosionAccessor; import carpet.CarpetSettings; -import carpet.utils.Messenger; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; -import static carpet.script.CarpetEventServer.Event.EXPLOSION_OUTCOME; - public class OptimizedExplosion { - private static List entitylist; - private static Vec3 vec3dmem; - private static long tickmem; - // For disabling the explosion particles and sound - public static int explosionSound = 0; - // masa's optimizations private static Object2DoubleOpenHashMap> densityCache = new Object2DoubleOpenHashMap<>(); - private static MutablePair pairMutable = new MutablePair<>(); private static Object2ObjectOpenHashMap stateCache = new Object2ObjectOpenHashMap<>(); private static Object2ObjectOpenHashMap fluidCache = new Object2ObjectOpenHashMap<>(); private static BlockPos.MutableBlockPos posMutable = new BlockPos.MutableBlockPos(0, 0, 0); private static ObjectOpenHashSet affectedBlockPositionsSet = new ObjectOpenHashSet<>(); private static boolean firstRay; private static boolean rayCalcDone; - private static ArrayList chances = new ArrayList<>(); - private static BlockPos blastChanceLocation; - // Creating entity list for scarpet event - private static List entityList = new ArrayList<>(); - - public static void doExplosionA(Explosion e, ExplosionLogHelper eLogger) { + public static List doExplosionA(Explosion e, ExplosionLogHelper eLogger) { ExplosionAccessor eAccess = (ExplosionAccessor) e; - - entityList.clear(); - boolean eventNeeded = EXPLOSION_OUTCOME.isNeeded() && !eAccess.getLevel().isClientSide(); - blastCalc(e); + + List toBlow; if (!CarpetSettings.explosionNoBlockDamage && eAccess.getDamageSource() != null) { rayCalcDone = false; @@ -88,291 +47,14 @@ public class OptimizedExplosion stateCache.clear(); fluidCache.clear(); - e.getToBlow().addAll(affectedBlockPositionsSet); + toBlow = new ArrayList<>(affectedBlockPositionsSet); affectedBlockPositionsSet.clear(); + } else { + toBlow = Collections.emptyList(); } - - float f3 = eAccess.getRadius() * 2.0F; - int k1 = Mth.floor(eAccess.getX() - (double) f3 - 1.0D); - int l1 = Mth.floor(eAccess.getX() + (double) f3 + 1.0D); - int i2 = Mth.floor(eAccess.getY() - (double) f3 - 1.0D); - int i1 = Mth.floor(eAccess.getY() + (double) f3 + 1.0D); - int j2 = Mth.floor(eAccess.getZ() - (double) f3 - 1.0D); - int j1 = Mth.floor(eAccess.getZ() + (double) f3 + 1.0D); - Vec3 vec3d = new Vec3(eAccess.getX(), eAccess.getY(), eAccess.getZ()); - - if (vec3dmem == null || !vec3dmem.equals(vec3d) || tickmem != eAccess.getLevel().getGameTime()) { - vec3dmem = vec3d; - tickmem = eAccess.getLevel().getGameTime(); - entitylist = eAccess.getLevel().getEntities(null, new AABB(k1, i2, j2, l1, i1, j1)); - explosionSound = 0; - } - - explosionSound++; - - Entity explodingEntity = eAccess.getSource(); - for (int k2 = 0; k2 < entitylist.size(); ++k2) { - Entity entity = entitylist.get(k2); - - - if (entity == explodingEntity) { - // entitylist.remove(k2); - removeFast(entitylist, k2); - k2--; - continue; - } - - if (entity instanceof PrimedTnt && explodingEntity != null && - entity.getX() == explodingEntity.getX() && - entity.getY() == explodingEntity.getY() && - entity.getZ() == explodingEntity.getZ()) { - if (eLogger != null) { - eLogger.onEntityImpacted(entity, new Vec3(0,-0.9923437498509884d, 0)); - } - continue; - } - - if (!entity.ignoreExplosion(e)) { - double d12 = Math.sqrt(entity.distanceToSqr(eAccess.getX(), eAccess.getY(), eAccess.getZ())) / (double) f3; - - if (d12 <= 1.0D) { - double d5 = entity.getX() - eAccess.getX(); - // Change in 1.16 snapshots to fix a bug with TNT jumping - double d7 = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - eAccess.getY(); - double d9 = entity.getZ() - eAccess.getZ(); - double d13 = (double) Math.sqrt(d5 * d5 + d7 * d7 + d9 * d9); - - if (d13 != 0.0D) { - d5 = d5 / d13; - d7 = d7 / d13; - d9 = d9 / d13; - double density; - - pairMutable.setLeft(vec3d); - pairMutable.setRight(entity.getBoundingBox()); - density = densityCache.getOrDefault(pairMutable, Double.MAX_VALUE); - - if (density == Double.MAX_VALUE) - { - Pair pair = Pair.of(vec3d, entity.getBoundingBox()); - density = Explosion.getSeenPercent(vec3d, entity); - densityCache.put(pair, density); - } - - // If it is needed, it saves the entity - if (eventNeeded) { - entityList.add(entity); - } - - double d10 = (1.0D - d12) * density; - if (eAccess.getDamageSource() != null) - { - entity.hurt(eAccess.getDamageSource(), - (float) ((int) ((d10 * d10 + d10) / 2.0D * 7.0D * (double) f3 + 1.0D))); - } - double d11 = d10; - - if (entity instanceof LivingEntity lev) { - d11 = d10 * Mth.clamp(1.0 - lev.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE), 0.0, 1.0); - } - - if (eLogger != null) { - eLogger.onEntityImpacted(entity, new Vec3(d5 * d11, d7 * d11, d9 * d11)); - } - - entity.setDeltaMovement(entity.getDeltaMovement().add(d5 * d11, d7 * d11, d9 * d11)); - - if (entity instanceof Player player) { - - if (!player.isSpectator() - && (!player.isCreative() || !player.getAbilities().flying)) { //getAbilities - e.getHitPlayers().put(player, new Vec3(d5 * d10, d7 * d10, d9 * d10)); - } - } - } - } - } - } - densityCache.clear(); - } - public static void doExplosionB(Explosion e, boolean spawnParticles) - { - ExplosionAccessor eAccess = (ExplosionAccessor) e; - Level world = eAccess.getLevel(); - double posX = eAccess.getX(); - double posY = eAccess.getY(); - double posZ = eAccess.getZ(); - - // If it is needed, calls scarpet event - if (EXPLOSION_OUTCOME.isNeeded() && !world.isClientSide()) { - EXPLOSION_OUTCOME.onExplosion((ServerLevel) world, eAccess.getSource(), e::getIndirectSourceEntity, eAccess.getX(), eAccess.getY(), eAccess.getZ(), eAccess.getRadius(), eAccess.isFire(), e.getToBlow(), entityList, eAccess.getBlockInteraction()); - } - - boolean damagesTerrain = eAccess.getBlockInteraction() != Explosion.BlockInteraction.KEEP; - - // explosionSound incremented till disabling the explosion particles and sound - if (explosionSound < 100 || explosionSound % 100 == 0) - { - world.playSound(null, posX, posY, posZ, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.BLOCKS, 4.0F, - (1.0F + (world.random.nextFloat() - world.random.nextFloat()) * 0.2F) * 0.7F); - - if (spawnParticles) - { - if (eAccess.getRadius() >= 2.0F && damagesTerrain) - { - world.addParticle(ParticleTypes.EXPLOSION_EMITTER, posX, posY, posZ, 1.0D, 0.0D, 0.0D); - } - else - { - world.addParticle(ParticleTypes.EXPLOSION, posX, posY, posZ, 1.0D, 0.0D, 0.0D); - } - } - } - - if (damagesTerrain) - { - ObjectArrayList> objectArrayList = new ObjectArrayList<>(); - Util.shuffle((ObjectArrayList) e.getToBlow(), world.random); - - boolean dropFromExplosions = CarpetSettings.xpFromExplosions || e.getIndirectSourceEntity() instanceof Player; - - for (BlockPos blockpos : e.getToBlow()) - { - BlockState state = world.getBlockState(blockpos); - Block block = state.getBlock(); - - if (!state.isAir()) - { - if (block.dropFromExplosion(e) && world instanceof ServerLevel serverLevel) - { - BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(blockpos) : null; //hasBlockEntity() - - LootParams.Builder lootBuilder = (new LootParams.Builder((ServerLevel)eAccess.getLevel())) - .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)) - .withParameter(LootContextParams.TOOL, ItemStack.EMPTY) - .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity) - .withOptionalParameter(LootContextParams.THIS_ENTITY, eAccess.getSource()); - - if (eAccess.getBlockInteraction() == Explosion.BlockInteraction.DESTROY_WITH_DECAY) - lootBuilder.withParameter(LootContextParams.EXPLOSION_RADIUS, eAccess.getRadius()); - - state.spawnAfterBreak(serverLevel, blockpos, ItemStack.EMPTY, dropFromExplosions); - - state.getDrops(lootBuilder).forEach((itemStackx) -> { - method_24023(objectArrayList, itemStackx, blockpos.immutable()); - }); - } - - world.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); - block.wasExploded(world, blockpos, e); - } - } - objectArrayList.forEach(p -> Block.popResource(world, p.getRight(), p.getLeft())); - - } - - if (eAccess.isFire()) - { - for (BlockPos blockpos1 : e.getToBlow()) - { - // Use the same Chunk reference because the positions are in the same xz-column - ChunkAccess chunk = world.getChunk(blockpos1.getX() >> 4, blockpos1.getZ() >> 4); - - BlockPos down = blockpos1.below(1); - if (eAccess.getRandom().nextInt(3) == 0 && - chunk.getBlockState(blockpos1).isAir() && - chunk.getBlockState(down).isSolidRender(world, down) - ) - { - world.setBlockAndUpdate(blockpos1, Blocks.FIRE.defaultBlockState()); - } - } - } - } - - // copied from Explosion, need to move the code to the explosion code anyways and use shadows for - // simplicity, its not jarmodding anyways - private static void method_24023(ObjectArrayList> objectArrayList, ItemStack itemStack, BlockPos blockPos) { - int i = objectArrayList.size(); - - for(int j = 0; j < i; ++j) { - Pair pair = objectArrayList.get(j); - ItemStack itemStack2 = pair.getLeft(); - if (ItemEntity.areMergable(itemStack2, itemStack)) { - ItemStack itemStack3 = ItemEntity.merge(itemStack2, itemStack, 16); - objectArrayList.set(j, Pair.of(itemStack3, pair.getRight())); - if (itemStack.isEmpty()) { - return; - } - } - } - - objectArrayList.add(Pair.of(itemStack, blockPos)); - } - - private static void removeFast(List lst, int index) { - if (index < lst.size() - 1) - lst.set(index, lst.get(lst.size() - 1)); - lst.remove(lst.size() - 1); - } - - private static void rayCalcs(Explosion e) { - ExplosionAccessor eAccess = (ExplosionAccessor) e; - boolean first = true; - - for (int j = 0; j < 16; ++j) { - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - if (j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15) { - double d0 = (double) ((float) j / 15.0F * 2.0F - 1.0F); - double d1 = (double) ((float) k / 15.0F * 2.0F - 1.0F); - double d2 = (double) ((float) l / 15.0F * 2.0F - 1.0F); - double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); - d0 = d0 / d3; - d1 = d1 / d3; - d2 = d2 / d3; - float rand = eAccess.getLevel().random.nextFloat(); - if (CarpetSettings.tntRandomRange >= 0) { - rand = (float) CarpetSettings.tntRandomRange; - } - float f = eAccess.getRadius() * (0.7F + rand * 0.6F); - double d4 = eAccess.getX(); - double d6 = eAccess.getY(); - double d8 = eAccess.getZ(); - - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPos blockpos = BlockPos.containing(d4, d6, d8); - BlockState state = eAccess.getLevel().getBlockState(blockpos); - FluidState fluidState = eAccess.getLevel().getFluidState(blockpos); - - if (!state.isAir()) { - float f2 = Math.max(state.getBlock().getExplosionResistance(), fluidState.getExplosionResistance()); - if (eAccess.getSource() != null) - f2 = eAccess.getSource().getBlockExplosionResistance(e, eAccess.getLevel(), blockpos, state, fluidState, f2); - f -= (f2 + 0.3F) * 0.3F; - } - - if (f > 0.0F && (eAccess.getSource() == null || - eAccess.getSource().shouldBlockExplode(e, eAccess.getLevel(), blockpos, state, f))) - { - affectedBlockPositionsSet.add(blockpos); - } - else if (first) { - return; - } - - first = false; - - d4 += d0 * 0.30000001192092896D; - d6 += d1 * 0.30000001192092896D; - d8 += d2 * 0.30000001192092896D; - } - } - } - } - } + return toBlow; } private static void getAffectedPositionsOnPlaneX(Explosion e, int x, int yStart, int yEnd, int zStart, int zEnd) @@ -454,9 +136,10 @@ public class OptimizedExplosion float rand = eAccess.getLevel().random.nextFloat(); float sizeRand = (CarpetSettings.tntRandomRange >= 0 ? (float) CarpetSettings.tntRandomRange : rand); float size = eAccess.getRadius() * (0.7F + sizeRand * 0.6F); - double posX = eAccess.getX(); - double posY = eAccess.getY(); - double posZ = eAccess.getZ(); + Vec3 vec3 = eAccess.getCenter(); + double posX = vec3.x; + double posY = vec3.y; + double posZ = vec3.z; for (float f1 = 0.3F; size > 0.0F; size -= 0.22500001F) { @@ -508,112 +191,4 @@ public class OptimizedExplosion return false; } - - public static void setBlastChanceLocation(BlockPos p){ - blastChanceLocation = p; - } - - private static void blastCalc(Explosion e){ - ExplosionAccessor eAccess = (ExplosionAccessor) e; - if(blastChanceLocation == null || blastChanceLocation.distToLowCornerSqr(eAccess.getX(), eAccess.getY(), eAccess.getZ()) > 200) return; - chances.clear(); - for (int j = 0; j < 16; ++j) { - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - if (j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15) { - double d0 = (double) ((float) j / 15.0F * 2.0F - 1.0F); - double d1 = (double) ((float) k / 15.0F * 2.0F - 1.0F); - double d2 = (double) ((float) l / 15.0F * 2.0F - 1.0F); - double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); - d0 = d0 / d3; - d1 = d1 / d3; - d2 = d2 / d3; - float f = eAccess.getRadius() * (0.7F + 0.6F); - double d4 = eAccess.getX(); - double d6 = eAccess.getY(); - double d8 = eAccess.getZ(); - boolean found = false; - - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPos blockpos = BlockPos.containing(d4, d6, d8); - BlockState state = eAccess.getLevel().getBlockState(blockpos); - FluidState fluidState = eAccess.getLevel().getFluidState(blockpos); - - if (!state.isAir()) { - float f2 = Math.max(state.getBlock().getExplosionResistance(), fluidState.getExplosionResistance()); - if (eAccess.getSource() != null) - f2 = eAccess.getSource().getBlockExplosionResistance(e, eAccess.getLevel(), blockpos, state, fluidState, f2); - f -= (f2 + 0.3F) * 0.3F; - } - - if (f > 0.0F && (eAccess.getSource() == null || - eAccess.getSource().shouldBlockExplode(e, eAccess.getLevel(), blockpos, state, f))) { - if(!found && blockpos.equals(blastChanceLocation)){ - chances.add(f); - found = true; - } - } - - d4 += d0 * 0.30000001192092896D; - d6 += d1 * 0.30000001192092896D; - d8 += d2 * 0.30000001192092896D; - } - } - } - } - } - - //showTNTblastChance(e); - } - - private static void showTNTblastChance(Explosion e){ - ExplosionAccessor eAccess = (ExplosionAccessor) e; - double randMax = 0.6F * eAccess.getRadius(); - double total = 0; - boolean fullyBlownUp = false; - boolean first = true; - int rays = 0; - for(float f3 : chances){ - rays++; - double calc = f3 - randMax; - if(calc > 0) fullyBlownUp = true; - double chancePerRay = (Math.abs(calc) / randMax); - if(!fullyBlownUp){ - if(first){ - first = false; - total = chancePerRay; - }else { - total = total * chancePerRay; - } - } - } - if(fullyBlownUp) total = 0; - double chance = 1 - total; - NumberFormat nf = NumberFormat.getNumberInstance(); - nf.setRoundingMode (RoundingMode.DOWN); - nf.setMaximumFractionDigits(2); - for(Player player : eAccess.getLevel().players()){ - Messenger.m(player,"w Pop: ", - "c " + nf.format(chance) + " ", - "^w Chance for the block to be destroyed by the blast: " + chance, - "?" + chance, - "w Remain: ", - String.format("c %.2f ", total), - "^w Chance the block survives the blast: " + total, - "?" + total, - "w Rays: ", - String.format("c %d ", rays), - "^w TNT blast rays going through the block", - "?" + rays, - "w Size: ", - String.format("c %.1f ", eAccess.getRadius()), - "^w TNT blast size", - "?" + eAccess.getRadius(), - "w @: ", - String.format("c [%.1f %.1f %.1f] ", eAccess.getX(), eAccess.getY(), eAccess.getZ()), - "^w TNT blast location X:" + eAccess.getX() + " Y:" + eAccess.getY() + " Z:" + eAccess.getZ(), - "?" + eAccess.getX() + " " + eAccess.getY() + " " + eAccess.getZ() - ); - } - } } diff --git a/src/main/java/carpet/helpers/ParticleDisplay.java b/src/main/java/carpet/helpers/ParticleDisplay.java index 0184375c..d6f2ee61 100644 --- a/src/main/java/carpet/helpers/ParticleDisplay.java +++ b/src/main/java/carpet/helpers/ParticleDisplay.java @@ -1,24 +1,18 @@ package carpet.helpers; -import carpet.script.utils.ParticleParser; -import net.minecraft.core.HolderLookup; import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.core.registries.Registries; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.phys.Vec3; public class ParticleDisplay { - public static void drawParticleLine(ServerPlayer player, Vec3 from, Vec3 to, String main, String accent, int count, double spread) + public static void drawParticleLine(ServerPlayer player, Vec3 from, Vec3 to, ParticleOptions mainParticle, ParticleOptions accentParticle, int count, double spread) { - ParticleOptions accentParticle = ParticleParser.getEffect(accent, player.server.registryAccess()); - ParticleOptions mainParticle = ParticleParser.getEffect(main, player.server.registryAccess()); - if (accentParticle != null) player.serverLevel().sendParticles( + if (accentParticle != null) player.level().sendParticles( player, accentParticle, - true, + true, true, to.x, to.y, to.z, count, spread, spread, spread, 0.0); @@ -30,10 +24,10 @@ public class ParticleDisplay delta.lengthSqr() < lineLengthSq; delta = delta.add(incvec.scale(player.level().random.nextFloat()))) { - player.serverLevel().sendParticles( + player.level().sendParticles( player, mainParticle, - true, + true, true, delta.x+from.x, delta.y+from.y, delta.z+from.z, 1, 0.0, 0.0, 0.0, 0.0); } diff --git a/src/main/java/carpet/helpers/RedstoneWireTurbo.java b/src/main/java/carpet/helpers/RedstoneWireTurbo.java index 30a1c37d..57015ed0 100644 --- a/src/main/java/carpet/helpers/RedstoneWireTurbo.java +++ b/src/main/java/carpet/helpers/RedstoneWireTurbo.java @@ -676,7 +676,7 @@ public class RedstoneWireTurbo // call BlockStateBase#neighborChanged directly. This change mostly // restores old behavior, at the cost of bypassing the // max-chained-neighbor-updates server property. - worldIn.getBlockState(upd.self).handleNeighborChanged(worldIn, upd.self, wire, upd.parent, false); + worldIn.getBlockState(upd.self).handleNeighborChanged(worldIn, upd.self, wire, null, false); } } @@ -951,7 +951,7 @@ public class RedstoneWireTurbo BlockPos neighborPos = pos.relative(dir); BlockState neighborState = level.getBlockState(neighborPos); - BlockState newState = neighborState.updateShape(dir.getOpposite(), state, level, neighborPos, pos); + BlockState newState = neighborState.updateShape(level, level, neighborPos, dir.getOpposite(), pos, state, level.getRandom()); Block.updateOrDestroy(neighborState, newState, level, neighborPos, Block.UPDATE_CLIENTS); } } diff --git a/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java index 972ec1a5..7ac25d51 100644 --- a/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java +++ b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java @@ -80,7 +80,7 @@ public class ExplosionLogHelper messages.add(c((k.pos.equals(pos))?"r - TNT":"w - ", Messenger.dblt((k.pos.equals(pos))?"r":"y", k.pos.x, k.pos.y, k.pos.z), "w dV", Messenger.dblt("d", k.accel.x, k.accel.y, k.accel.z), - "w "+ regs.registryOrThrow(Registries.ENTITY_TYPE).getKey(k.type).getPath(), (v>1)?"l ("+v+")":"" + "w "+ regs.lookupOrThrow(Registries.ENTITY_TYPE).getKey(k.type).getPath(), (v>1)?"l ("+v+")":"" )); }); } diff --git a/src/main/java/carpet/logging/logHelpers/PathfindingVisualizer.java b/src/main/java/carpet/logging/logHelpers/PathfindingVisualizer.java index ff66ee3c..987af8d5 100644 --- a/src/main/java/carpet/logging/logHelpers/PathfindingVisualizer.java +++ b/src/main/java/carpet/logging/logHelpers/PathfindingVisualizer.java @@ -2,6 +2,9 @@ package carpet.logging.logHelpers; import carpet.helpers.ParticleDisplay; import carpet.logging.LoggerRegistry; +import net.minecraft.core.particles.DustParticleOptions; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; @@ -31,8 +34,8 @@ public class PathfindingVisualizer if (minDuration < 1) minDuration = 1; - String accent = successful ? "happy_villager" : "angry_villager"; - String color = (miliseconds/minDuration < 2)? "dust 1 1 0 1" : ((miliseconds/minDuration < 4)?"dust 1 0.5 0 1":"dust 1 0 0 1"); + ParticleOptions accent = successful ? ParticleTypes.HAPPY_VILLAGER : ParticleTypes.ANGRY_VILLAGER; + ParticleOptions color = (miliseconds/minDuration < 2)? new DustParticleOptions(0xffffff00, 1) : ((miliseconds/minDuration < 4)?new DustParticleOptions(0xFFFF7700, 1): new DustParticleOptions(0xFFFF0000, 1)); ParticleDisplay.drawParticleLine((ServerPlayer) player, entity.position(), target, color, accent, 5, 0.5); return null; }); diff --git a/src/main/java/carpet/mixins/AbstractCauldronBlock_stackableSBoxesMixin.java b/src/main/java/carpet/mixins/AbstractCauldronBlock_stackableSBoxesMixin.java deleted file mode 100644 index 95cc0dbc..00000000 --- a/src/main/java/carpet/mixins/AbstractCauldronBlock_stackableSBoxesMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -package carpet.mixins; - -import carpet.CarpetSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.cauldron.CauldronInteraction; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.AbstractCauldronBlock; -import net.minecraft.world.level.block.ShulkerBoxBlock; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(AbstractCauldronBlock.class) -public class AbstractCauldronBlock_stackableSBoxesMixin -{ - @Redirect(method = "useItemOn", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/core/cauldron/CauldronInteraction;interact(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/ItemInteractionResult;" - )) - private ItemInteractionResult wrapInteractor(final CauldronInteraction cauldronBehavior, final BlockState blockState, final Level world, final BlockPos blockPos, final Player playerEntity, final InteractionHand hand, final ItemStack itemStack) - { - int count = -1; - if (CarpetSettings.shulkerBoxStackSize > 1 && itemStack.getItem() instanceof BlockItem && ((BlockItem)itemStack.getItem()).getBlock() instanceof ShulkerBoxBlock) - count = itemStack.getCount(); - ItemInteractionResult result = cauldronBehavior.interact(blockState, world, blockPos, playerEntity, hand, itemStack); - if (count > 0 && result.consumesAction()) - { - ItemStack current = playerEntity.getItemInHand(hand); - if (current.getItem() instanceof BlockItem && ((BlockItem)itemStack.getItem()).getBlock() instanceof ShulkerBoxBlock) - current.setCount(count); - } - return result; - } -} diff --git a/src/main/java/carpet/mixins/AbstractCraftingMenu_scarpetMixin.java b/src/main/java/carpet/mixins/AbstractCraftingMenu_scarpetMixin.java new file mode 100644 index 00000000..a2b09aa0 --- /dev/null +++ b/src/main/java/carpet/mixins/AbstractCraftingMenu_scarpetMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.fakes.AbstractContainerMenuInterface; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractCraftingMenu; +import net.minecraft.world.inventory.RecipeBookMenu; +import net.minecraft.world.item.crafting.RecipeHolder; +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(AbstractCraftingMenu.class) +public class AbstractCraftingMenu_scarpetMixin +{ + @Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true) + private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder recipe, ServerLevel serverLevel, Inventory player, CallbackInfoReturnable cir) { + if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll)) + cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING); + } +} diff --git a/src/main/java/carpet/mixins/RecipeBookMenu_scarpetMixin.java b/src/main/java/carpet/mixins/AbstractFurnaceMenu_scarpetMixin.java similarity index 50% rename from src/main/java/carpet/mixins/RecipeBookMenu_scarpetMixin.java rename to src/main/java/carpet/mixins/AbstractFurnaceMenu_scarpetMixin.java index e28072b1..5f91dc5b 100644 --- a/src/main/java/carpet/mixins/RecipeBookMenu_scarpetMixin.java +++ b/src/main/java/carpet/mixins/AbstractFurnaceMenu_scarpetMixin.java @@ -1,19 +1,23 @@ package carpet.mixins; import carpet.fakes.AbstractContainerMenuInterface; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractFurnaceMenu; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.RecipeHolder; 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.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(RecipeBookMenu.class) -public class RecipeBookMenu_scarpetMixin { +@Mixin(AbstractFurnaceMenu.class) +public class AbstractFurnaceMenu_scarpetMixin +{ @Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true) - private void selectRecipeCallback(boolean craftAll, RecipeHolder recipe, ServerPlayer player, CallbackInfo ci) { - if(((AbstractContainerMenuInterface) this).callSelectRecipeListener(player,recipe,craftAll)) - ci.cancel(); + private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder recipe, ServerLevel level, Inventory player, CallbackInfoReturnable cir) { + if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll)) + cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING); } } diff --git a/src/main/java/carpet/mixins/BarrierBlock_updateSuppressionBlockMixin.java b/src/main/java/carpet/mixins/BarrierBlock_updateSuppressionBlockMixin.java index a4f2cc52..81017c3b 100644 --- a/src/main/java/carpet/mixins/BarrierBlock_updateSuppressionBlockMixin.java +++ b/src/main/java/carpet/mixins/BarrierBlock_updateSuppressionBlockMixin.java @@ -4,6 +4,7 @@ import carpet.CarpetSettings; import carpet.fakes.LevelInterface; import net.minecraft.world.level.redstone.NeighborUpdater; import net.minecraft.util.RandomSource; +import net.minecraft.world.level.redstone.Orientation; import org.spongepowered.asm.mixin.Mixin; import net.minecraft.core.BlockPos; @@ -29,10 +30,10 @@ public class BarrierBlock_updateSuppressionBlockMixin extends Block { } @Override - public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, Orientation fromPos, boolean notify) { if (CarpetSettings.updateSuppressionBlock != -1) { - if (fromPos.equals(pos.above())) { - BlockState stateAbove = level.getBlockState(fromPos); + if (true/*fromPos.equals(pos.above())*/) { // todo neighbour updates don't have source + BlockState stateAbove = level.getBlockState(pos.above()); if (stateAbove.is(Blocks.ACTIVATOR_RAIL) && !stateAbove.getValue(PoweredRailBlock.POWERED)) { level.scheduleTick(pos, this, 1); NeighborUpdater updater = ((LevelInterface)level).getNeighborUpdater(); diff --git a/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java b/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java index e18b5e54..f1adfc67 100644 --- a/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java +++ b/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java @@ -3,10 +3,10 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; +import net.minecraft.tags.ItemTags; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.PickaxeItem; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; @@ -14,12 +14,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.BuddingAmethystBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; import org.jetbrains.annotations.Nullable; 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(BuddingAmethystBlock.class) public class BuddingAmethystBlock_movableAmethystMixin extends Block { @@ -33,8 +29,8 @@ public class BuddingAmethystBlock_movableAmethystMixin extends Block { // doing it here rather than though loottables since loottables are loaded on reload // drawback - not controlled via loottables, but hey if (CarpetSettings.movableAmethyst && - stack.getItem() instanceof PickaxeItem && - EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).getHolderOrThrow(Enchantments.SILK_TOUCH), stack) > 0 + stack.is(ItemTags.PICKAXES) && + EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH), stack) > 0 ) popResource(world, pos, Items.BUDDING_AMETHYST.getDefaultInstance()); } diff --git a/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java b/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java index 06868170..71f9b48d 100644 --- a/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java +++ b/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.utils.SpawnOverrides; import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.core.Holder; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.levelgen.structure.Structure; import org.spongepowered.asm.mixin.Mixin; @@ -11,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.core.BlockPos; -import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.MobSpawnSettings; @@ -31,10 +31,10 @@ public abstract class ChunkGenerator_customMobSpawnsMixin target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;" ), cancellable = true) private void checkCMSpawns(Holder holder, StructureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos, - CallbackInfoReturnable> cir, + CallbackInfoReturnable> cir, Map map, Iterator var6, Map.Entry entry) { - WeightedRandomList res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos); + WeightedList res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos); if (res != null) { cir.setReturnValue(res); diff --git a/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java index fc300dbb..a66e8167 100644 --- a/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java @@ -23,7 +23,7 @@ import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap.DistanceManager; import net.minecraft.server.level.ChunkResult; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; +//import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.TicketType; @@ -46,7 +46,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import carpet.fakes.ChunkHolderInterface; -import carpet.fakes.ChunkTicketManagerInterface; import carpet.fakes.ServerLightingProviderInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.script.utils.WorldTools; @@ -76,9 +75,9 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi @Final private ThreadedLevelLightEngine lightEngine; - @Shadow - @Final - private ChunkTaskPriorityQueueSorter queueSorter; + //@Shadow + //@Final + //private ChunkTaskPriorityQueueSorter queueSorter; @Shadow @Final @@ -165,7 +164,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi this.world.getServer().execute(() -> CHUNK_LOADED.onChunkEvent(this.world, chpos, generated)); } } - */ @Unique private void addTicket(ChunkPos pos, ChunkStatus status) @@ -180,7 +178,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi } - /* @Unique private void addRelightTicket(ChunkPos pos) { @@ -195,7 +192,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi () -> "release relight ticket " + pos )); } - */ + @Unique private void tickTicketManager() { @@ -220,7 +217,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi } - /* + @Unique private Set loadExistingChunksFromDisk(Set requestedChunks) { diff --git a/src/main/java/carpet/mixins/ClientPacketListener_clientCommandMixin.java b/src/main/java/carpet/mixins/ClientPacketListener_clientCommandMixin.java index 6690ea49..d894c38d 100644 --- a/src/main/java/carpet/mixins/ClientPacketListener_clientCommandMixin.java +++ b/src/main/java/carpet/mixins/ClientPacketListener_clientCommandMixin.java @@ -35,7 +35,7 @@ public abstract class ClientPacketListener_clientCommandMixin extends ClientComm if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet() && minecraft.player != null) { LocalPlayer playerSource = minecraft.player; - CarpetServer.forEachManager(sm -> sm.inspectClientsideCommand(playerSource.createCommandSourceStack(), "/" + string)); + CarpetServer.forEachManager(sm -> sm.inspectClientsideCommand("/" + string)); } } } diff --git a/src/main/java/carpet/mixins/ClientPacketListener_explosionMixin.java b/src/main/java/carpet/mixins/ClientPacketListener_explosionMixin.java new file mode 100644 index 00000000..5d50a15e --- /dev/null +++ b/src/main/java/carpet/mixins/ClientPacketListener_explosionMixin.java @@ -0,0 +1,49 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.CommonListenerCookie; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; +import net.minecraft.world.phys.Vec3; +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.CallbackInfo; + +@Mixin(ClientPacketListener.class) +public abstract class ClientPacketListener_explosionMixin extends ClientCommonPacketListenerImpl +{ + + private static Vec3 vec3dmem; + private static long tickmem; + // For disabling the explosion particles and sounds if explosions are stacking up + + protected ClientPacketListener_explosionMixin(final Minecraft minecraft, final Connection connection, final CommonListenerCookie commonListenerCookie) + { + super(minecraft, connection, commonListenerCookie); + } + + + @Inject(method = "handleExplosion", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/multiplayer/ClientLevel;playLocalSound(DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FFZ)V" + ), cancellable = true) + private void onHandleExplosion(final ClientboundExplodePacket clientboundExplodePacket, final CallbackInfo ci) + { + + if (CarpetSettings.optimizedTNT) + { + Vec3 vec3d = clientboundExplodePacket.center(); + long tick = minecraft.level.getGameTime(); + if (vec3dmem == null || !vec3dmem.equals(vec3d) || tickmem != tick) { + vec3dmem = vec3d; + tickmem = tick; + } else { + ci.cancel(); + } + } + } +} diff --git a/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java b/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java index 7a172441..1951e915 100644 --- a/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java @@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.commands.CloneCommands; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -14,10 +15,10 @@ public abstract class CloneCommands_fillUpdatesMixin { @Redirect(method = "clone", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighboursOnBlockSet(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V" )) - private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) + private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, BlockState block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighboursOnBlockSet(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/Connection_packetCounterMixin.java b/src/main/java/carpet/mixins/Connection_packetCounterMixin.java index c7159e73..3be41624 100644 --- a/src/main/java/carpet/mixins/Connection_packetCounterMixin.java +++ b/src/main/java/carpet/mixins/Connection_packetCounterMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.fakes.ClientConnectionInterface; import carpet.logging.logHelpers.PacketCounter; import io.netty.channel.Channel; +import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; @@ -28,7 +29,7 @@ public abstract class Connection_packetCounterMixin implements ClientConnectionI // Add to the packet counter whenever a packet is sent. @Inject(method = "sendPacket", at = @At("HEAD")) - private void packetOutCount(final Packet packet, final PacketSendListener packetSendListener, final boolean bl, final CallbackInfo ci) + private void packetOutCount(Packet packet, ChannelFutureListener channelFutureListener, boolean bl, CallbackInfo ci) { PacketCounter.totalOut++; } diff --git a/src/main/java/carpet/mixins/DefaultRedstoneWireEvaluator_redstoneMixin.java b/src/main/java/carpet/mixins/DefaultRedstoneWireEvaluator_redstoneMixin.java new file mode 100644 index 00000000..b9be2e28 --- /dev/null +++ b/src/main/java/carpet/mixins/DefaultRedstoneWireEvaluator_redstoneMixin.java @@ -0,0 +1,20 @@ +package carpet.mixins; + +import carpet.fakes.DefaultRedstoneWireEvaluatorInferface; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.redstone.DefaultRedstoneWireEvaluator; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(DefaultRedstoneWireEvaluator.class) +public abstract class DefaultRedstoneWireEvaluator_redstoneMixin implements DefaultRedstoneWireEvaluatorInferface +{ + @Shadow protected abstract int calculateTargetStrength(final Level level, final BlockPos blockPos); + + @Override + public int calculateTargetStrengthCM(final Level level, final BlockPos pos) + { + return calculateTargetStrength(level, pos); + } +} diff --git a/src/main/java/carpet/mixins/DispenserBlock_qcMixin.java b/src/main/java/carpet/mixins/DispenserBlock_qcMixin.java index 6444c1a6..958548af 100644 --- a/src/main/java/carpet/mixins/DispenserBlock_qcMixin.java +++ b/src/main/java/carpet/mixins/DispenserBlock_qcMixin.java @@ -1,5 +1,6 @@ package carpet.mixins; +import net.minecraft.world.level.redstone.Orientation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -23,7 +24,7 @@ public class DispenserBlock_qcMixin { target = "Lnet/minecraft/world/level/Level;hasNeighborSignal(Lnet/minecraft/core/BlockPos;)Z" ) ) - private boolean carpet_hasQuasiSignal(Level _level, BlockPos above, BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + private boolean carpet_hasQuasiSignal(Level _level, BlockPos above, BlockState state, Level level, BlockPos pos, Block neighborBlock, Orientation neighborPos, boolean movedByPiston) { return QuasiConnectivity.hasQuasiSignal(level, pos); } } diff --git a/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java deleted file mode 100644 index 694aed49..00000000 --- a/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package carpet.mixins; - -import java.util.Set; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.DistanceManager; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import carpet.fakes.ChunkTicketManagerInterface; - -@Mixin(DistanceManager.class) -public abstract class DistanceManager_scarpetChunkCreationMixin implements ChunkTicketManagerInterface -{ - @Shadow - @Final - private Set chunksToUpdateFutures; - - @Override - public void replaceHolder(final ChunkHolder oldHolder, final ChunkHolder newHolder) - { - this.chunksToUpdateFutures.remove(oldHolder); - this.chunksToUpdateFutures.add(newHolder); - } -} diff --git a/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java b/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java index 120f1f4a..8cd13ce5 100644 --- a/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java +++ b/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java @@ -1,23 +1,25 @@ package carpet.mixins; -import carpet.fakes.ChunkTicketManagerInterface; +import carpet.fakes.TicketsFetcherInterface; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.Ticket; -import net.minecraft.util.SortedArraySet; +import net.minecraft.world.level.TicketStorage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import java.util.List; + @Mixin(DistanceManager.class) -public abstract class DistanceManager_scarpetMixin implements ChunkTicketManagerInterface +public abstract class DistanceManager_scarpetMixin implements TicketsFetcherInterface { - @Shadow @Final private Long2ObjectOpenHashMap>> tickets; + @Shadow @Final private TicketStorage ticketStorage; @Override - public Long2ObjectOpenHashMap>> getTicketsByPosition() + public Long2ObjectOpenHashMap> getTicketsByPosition() { - return tickets; + return ((TicketsFetcherInterface)ticketStorage).getTicketsByPosition(); } } diff --git a/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java b/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java deleted file mode 100644 index e4a24c65..00000000 --- a/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -package carpet.mixins; - -import carpet.fakes.ChunkTicketManagerInterface; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import net.minecraft.server.level.DistanceManager; -import net.minecraft.server.level.Ticket; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.SortedArraySet; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Iterator; - -@Mixin(DistanceManager.class) -public abstract class DistanceManager_spawnChunksMixin implements ChunkTicketManagerInterface -{ - @Shadow @Final private Long2ObjectOpenHashMap>> tickets; - - @Shadow protected abstract void removeTicket(long pos, Ticket ticket); - - @Shadow public abstract void addRegionTicket(TicketType type, ChunkPos pos, int radius, T argument); - - @Override - public void changeSpawnChunks(ChunkPos chunkPos, int distance) - { - long pos = chunkPos.toLong(); - SortedArraySet> set = tickets.get(pos); - Ticket existingTicket = null; - if (set != null) - { - Iterator> iter = set.iterator(); - while(iter.hasNext()) - { - Ticket ticket = iter.next(); - if (ticket.getType() == TicketType.START) - { - existingTicket = ticket; - iter.remove(); - } - } - set.add(existingTicket); - } - // the reason we are removing the ticket this way is that there are sideeffects of removal - if (existingTicket != null) - { - removeTicket(pos, existingTicket); - } - // set optionally new spawn ticket - if (distance > 0) - addRegionTicket(TicketType.START, chunkPos, distance, Unit.INSTANCE); - } -} diff --git a/src/main/java/carpet/mixins/EntityMixin.java b/src/main/java/carpet/mixins/EntityMixin.java index 6c2223ad..589f5111 100644 --- a/src/main/java/carpet/mixins/EntityMixin.java +++ b/src/main/java/carpet/mixins/EntityMixin.java @@ -32,7 +32,7 @@ public abstract class EntityMixin implements EntityInterface return partialTicks == 1.0F ? this.yRot : Mth.lerp(partialTicks, this.yRotO, this.yRot); } - @Inject(method = "isControlledByLocalInstance", at = @At("HEAD"), cancellable = true) + @Inject(method = "isLocalInstanceAuthoritative", at = @At("HEAD"), cancellable = true) private void isFakePlayer(CallbackInfoReturnable cir) { if (getControllingPassenger() instanceof EntityPlayerMPFake) cir.setReturnValue(!level.isClientSide); diff --git a/src/main/java/carpet/mixins/ExperienceOrb_xpNoCooldownMixin.java b/src/main/java/carpet/mixins/ExperienceOrb_xpNoCooldownMixin.java index 0b04c22b..7c590b6e 100644 --- a/src/main/java/carpet/mixins/ExperienceOrb_xpNoCooldownMixin.java +++ b/src/main/java/carpet/mixins/ExperienceOrb_xpNoCooldownMixin.java @@ -19,9 +19,6 @@ public abstract class ExperienceOrb_xpNoCooldownMixin extends Entity @Shadow private int count; - @Shadow - private int value; - public ExperienceOrb_xpNoCooldownMixin(EntityType type, Level world) { super(type, world); @@ -30,13 +27,15 @@ public abstract class ExperienceOrb_xpNoCooldownMixin extends Entity @Shadow protected abstract int repairPlayerItems(ServerPlayer player, int amount); + @Shadow public abstract int getValue(); + @Inject(method = "playerTouch", at = @At("HEAD")) private void addXP(Player player, CallbackInfo ci) { if (CarpetSettings.xpNoCooldown && !level().isClientSide) { player.takeXpDelay = 0; // reducing the count to 1 and leaving vanilla to deal with it while (this.count > 1) { - int remainder = this.repairPlayerItems((ServerPlayer) player, this.value); + int remainder = this.repairPlayerItems((ServerPlayer) player, this.getValue()); if (remainder > 0) { player.giveExperiencePoints(remainder); } diff --git a/src/main/java/carpet/mixins/ExplosionAccessor.java b/src/main/java/carpet/mixins/ExplosionAccessor.java index 5b0875ba..e204b241 100644 --- a/src/main/java/carpet/mixins/ExplosionAccessor.java +++ b/src/main/java/carpet/mixins/ExplosionAccessor.java @@ -1,37 +1,22 @@ package carpet.mixins; -import net.minecraft.util.RandomSource; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -@Mixin(Explosion.class) +@Mixin(ServerExplosion.class) public interface ExplosionAccessor { @Accessor - boolean isFire(); + ServerLevel getLevel(); @Accessor - Explosion.BlockInteraction getBlockInteraction(); - - @Accessor - Level getLevel(); - - @Accessor - RandomSource getRandom(); - - @Accessor - double getX(); - - @Accessor - double getY(); - - @Accessor - double getZ(); + Vec3 getCenter(); @Accessor float getRadius(); diff --git a/src/main/java/carpet/mixins/Explosion_optimizedTntMixin.java b/src/main/java/carpet/mixins/Explosion_optimizedTntMixin.java index 3cf32d6c..43d38cb1 100644 --- a/src/main/java/carpet/mixins/Explosion_optimizedTntMixin.java +++ b/src/main/java/carpet/mixins/Explosion_optimizedTntMixin.java @@ -4,11 +4,12 @@ import carpet.helpers.OptimizedExplosion; import carpet.CarpetSettings; import carpet.logging.LoggerRegistry; import carpet.logging.logHelpers.ExplosionLogHelper; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.core.Holder; -import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.monster.breeze.Breeze; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.level.material.FluidState; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -23,81 +24,74 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(value = Explosion.class) +import java.util.List; +import java.util.Optional; + +@Mixin(value = ServerExplosion.class) public abstract class Explosion_optimizedTntMixin { - @Shadow - @Final - private ObjectArrayList toBlow; - - @Shadow @Final private Level level; + @Shadow @Final private ServerLevel level; @Shadow @Nullable public abstract LivingEntity getIndirectSourceEntity(); private ExplosionLogHelper eLogger; - @Inject(method = "explode", at = @At("HEAD"), + @Inject(method = "calculateExplodedPositions", at = @At("HEAD"), cancellable = true) - private void onExplosionA(CallbackInfo ci) + private void calculateExplodedPositionsCM(final CallbackInfoReturnable> cir) { if (CarpetSettings.optimizedTNT && !level.isClientSide && !(getIndirectSourceEntity() instanceof Breeze)) { - OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger); - ci.cancel(); + cir.setReturnValue(OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger)); } } - @Inject(method = "finalizeExplosion", at = @At("HEAD"), - cancellable = true) - private void onExplosionB(boolean spawnParticles, CallbackInfo ci) + @Inject(method = "interactWithBlocks", at = @At("HEAD")) + private void interactWithBlocksCM(final List list, final CallbackInfo ci) { if (eLogger != null) { - eLogger.setAffectBlocks( ! toBlow.isEmpty()); + eLogger.setAffectBlocks( ! list.isEmpty()); eLogger.onExplosionDone(this.level.getGameTime()); } if (CarpetSettings.explosionNoBlockDamage) { - toBlow.clear(); + list.clear(); } - if (CarpetSettings.optimizedTNT && !level.isClientSide && !(getIndirectSourceEntity() instanceof Breeze)) - { - OptimizedExplosion.doExplosionB((Explosion) (Object) this, spawnParticles); - ci.cancel(); - } - } - //optional due to Overwrite in Lithium - //should kill most checks if no block damage is requested - @Redirect(method = "explode", require = 0, at = @At(value = "INVOKE", - target ="Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) - private BlockState noBlockCalcsWithNoBLockDamage(Level world, BlockPos pos) - { - if (CarpetSettings.explosionNoBlockDamage) return Blocks.BEDROCK.defaultBlockState(); - return world.getBlockState(pos); } - @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)V", + //optional due to Overwrite in Lithium + //should kill most checks if no block damage is requested + @Redirect(method = "calculateExplodedPositions", require = 0, at = @At(value = "INVOKE", + target ="Lnet/minecraft/world/level/ExplosionDamageCalculator;getBlockExplosionResistance(Lnet/minecraft/world/level/Explosion;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/material/FluidState;)Ljava/util/Optional;")) + private Optional noBlockCalcsWithNoBLockDamage(final ExplosionDamageCalculator instance, final Explosion explosion, final BlockGetter blockGetter, final BlockPos blockPos, final BlockState blockState, final FluidState fluidState) + { + if (CarpetSettings.explosionNoBlockDamage) return Optional.of(Blocks.BEDROCK.getExplosionResistance()); + return instance.getBlockExplosionResistance(explosion, blockGetter, blockPos, blockState, fluidState); + } + + @Inject(method = "", at = @At(value = "RETURN")) - private void onExplosionCreated(Level world, Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionBehavior, double x, double y, double z, float power, boolean createFire, Explosion.BlockInteraction destructionType, ParticleOptions particleOptions, ParticleOptions particleOptions2, Holder soundEvent, CallbackInfo ci) + private void onExplostion(ServerLevel world, Entity entity, DamageSource damageSource, final ExplosionDamageCalculator explosionBehavior, final Vec3 vec3, final float power, final boolean createFire, final Explosion.BlockInteraction destructionType, final CallbackInfo ci) { if (LoggerRegistry.__explosions && ! world.isClientSide) { - eLogger = new ExplosionLogHelper(x, y, z, power, createFire, destructionType, level.registryAccess()); + eLogger = new ExplosionLogHelper(vec3.x, vec3.y, vec3.z, power, createFire, destructionType, level.registryAccess()); } } - @Redirect(method = "explode", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) + @Redirect(method = "hurtEntities", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(Lnet/minecraft/world/phys/Vec3;)V")) private void setVelocityAndUpdateLogging(Entity entity, Vec3 velocity) { if (eLogger != null) { eLogger.onEntityImpacted(entity, velocity.subtract(entity.getDeltaMovement())); } - entity.setDeltaMovement(velocity); + entity.push(velocity); } } diff --git a/src/main/java/carpet/mixins/Explosion_scarpetEventMixin.java b/src/main/java/carpet/mixins/Explosion_scarpetEventMixin.java index 12e9bf2b..5985a526 100644 --- a/src/main/java/carpet/mixins/Explosion_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/Explosion_scarpetEventMixin.java @@ -1,8 +1,6 @@ package carpet.mixins; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.core.Holder; -import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.world.level.ServerExplosion; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -14,66 +12,48 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.ArrayList; import java.util.List; -import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import static carpet.script.CarpetEventServer.Event.EXPLOSION_OUTCOME; -@Mixin(value = Explosion.class, priority = 990) +@Mixin(value = ServerExplosion.class, priority = 990) public abstract class Explosion_scarpetEventMixin { - @Shadow @Final private Level level; - @Shadow @Final private double x; - @Shadow @Final private double y; - @Shadow @Final private double z; + @Shadow @Final private ServerLevel level; + @Shadow @Final private Vec3 center; @Shadow @Final private float radius; @Shadow @Final private boolean fire; - @Shadow @Final private ObjectArrayList toBlow; @Shadow @Final private Explosion.BlockInteraction blockInteraction; @Shadow @Final private @Nullable Entity source; @Shadow /*@Nullable*/ public abstract /*@Nullable*/ LivingEntity getIndirectSourceEntity(); - @Shadow public static float getSeenPercent(Vec3 source, Entity entity) {return 0.0f;} + private List affectedEntities = new ArrayList<>(); - private List affectedEntities; - - @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)V", - at = @At(value = "RETURN")) - private void onExplosionCreated(Level world, Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionBehavior, double x, double y, double z, float power, boolean createFire, Explosion.BlockInteraction destructionType, ParticleOptions particleOptions, ParticleOptions particleOptions2, Holder soundEvent, CallbackInfo ci) + @Inject(method = "explode", at = @At("HEAD")) + private void explodeCM(CallbackInfo ci) { - if (EXPLOSION_OUTCOME.isNeeded() && !world.isClientSide()) - { - affectedEntities = new ArrayList<>(); - } + affectedEntities.clear(); } - @Redirect(method = "explode", at=@At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Explosion;getSeenPercent(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/Entity;)F") - ) - private float onExplosion(Vec3 source, Entity entity) + @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;onExplosionHit(Lnet/minecraft/world/entity/Entity;)V")) + private void onEntityHit(Entity instance, Entity entity) { - if (affectedEntities != null) - { - affectedEntities.add(entity); - } - return getSeenPercent(source, entity); + affectedEntities.add(instance); + instance.onExplosionHit(entity); } - @Inject(method = "finalizeExplosion", at = @At("HEAD")) - private void onExplosion(boolean spawnParticles, CallbackInfo ci) + @Inject(method = "explode", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;hurtEntities()V", shift = At.Shift.AFTER)) + private void onExplosionDone(CallbackInfo ci, List list) { if (EXPLOSION_OUTCOME.isNeeded() && !level.isClientSide()) { - EXPLOSION_OUTCOME.onExplosion((ServerLevel) level, source, this::getIndirectSourceEntity, x, y, z, radius, fire, toBlow, affectedEntities, blockInteraction); + EXPLOSION_OUTCOME.onExplosion((ServerLevel) level, source, this::getIndirectSourceEntity, center, radius, fire, list, affectedEntities, blockInteraction); } } } diff --git a/src/main/java/carpet/mixins/FillCommandMixin.java b/src/main/java/carpet/mixins/FillCommandMixin.java index 344f5ff3..936bb00a 100644 --- a/src/main/java/carpet/mixins/FillCommandMixin.java +++ b/src/main/java/carpet/mixins/FillCommandMixin.java @@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.commands.FillCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -14,10 +15,10 @@ public abstract class FillCommandMixin { @Redirect(method = "fillBlocks", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighboursOnBlockSet(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V" )) - private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) + private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, BlockState block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighboursOnBlockSet(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/FlowingFluid_liquidDamageDisabledMixin.java b/src/main/java/carpet/mixins/FlowingFluid_liquidDamageDisabledMixin.java index 933e0980..1990e719 100644 --- a/src/main/java/carpet/mixins/FlowingFluid_liquidDamageDisabledMixin.java +++ b/src/main/java/carpet/mixins/FlowingFluid_liquidDamageDisabledMixin.java @@ -16,14 +16,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class FlowingFluid_liquidDamageDisabledMixin { @Inject( - method = "canHoldFluid", + method = "canHoldAnyFluid", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;blocksMotion()Z" ), cancellable = true ) - private void stopBreakingBlock(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid, CallbackInfoReturnable cir) + private static void stopBreakingBlock(final BlockState state, final CallbackInfoReturnable cir) { if (CarpetSettings.liquidDamageDisabled) { diff --git a/src/main/java/carpet/mixins/FoodData_scarpetMixin.java b/src/main/java/carpet/mixins/FoodData_scarpetMixin.java new file mode 100644 index 00000000..40b3cf4d --- /dev/null +++ b/src/main/java/carpet/mixins/FoodData_scarpetMixin.java @@ -0,0 +1,24 @@ +package carpet.mixins; + +import carpet.fakes.FoodDataInterface; +import net.minecraft.world.food.FoodData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(FoodData.class) +public class FoodData_scarpetMixin implements FoodDataInterface +{ + @Shadow private float exhaustionLevel; + + @Override + public float getCMExhaustionLevel() + { + return exhaustionLevel; + } + + @Override + public void setExhaustion(float aFloat) + { + exhaustionLevel = aFloat; + } +} diff --git a/src/main/java/carpet/mixins/Guardian_renewableSpongesMixin.java b/src/main/java/carpet/mixins/Guardian_renewableSpongesMixin.java index 42f5fdad..d2fc84d3 100644 --- a/src/main/java/carpet/mixins/Guardian_renewableSpongesMixin.java +++ b/src/main/java/carpet/mixins/Guardian_renewableSpongesMixin.java @@ -1,12 +1,10 @@ package carpet.mixins; import carpet.CarpetSettings; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LightningBolt; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.SpawnGroupData; import net.minecraft.world.entity.monster.ElderGuardian; import net.minecraft.world.entity.monster.Guardian; import net.minecraft.world.entity.monster.Monster; @@ -27,8 +25,8 @@ public abstract class Guardian_renewableSpongesMixin extends Monster if (!this.level().isClientSide && !this.isRemoved() && CarpetSettings.renewableSponges && !((Object)this instanceof ElderGuardian)) { ElderGuardian elderGuardian = new ElderGuardian(EntityType.ELDER_GUARDIAN ,this.level()); - elderGuardian.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); - elderGuardian.finalizeSpawn(serverWorld ,this.level().getCurrentDifficultyAt(elderGuardian.blockPosition()), MobSpawnType.CONVERSION, null); + elderGuardian.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + elderGuardian.finalizeSpawn(serverWorld ,this.level().getCurrentDifficultyAt(elderGuardian.blockPosition()), EntitySpawnReason.CONVERSION, null); elderGuardian.setNoAi(this.isNoAi()); if (this.hasCustomName()) diff --git a/src/main/java/carpet/mixins/Ingredient_scarpetMixin.java b/src/main/java/carpet/mixins/Ingredient_scarpetMixin.java index 4d33697e..e59c04c5 100644 --- a/src/main/java/carpet/mixins/Ingredient_scarpetMixin.java +++ b/src/main/java/carpet/mixins/Ingredient_scarpetMixin.java @@ -1,24 +1,11 @@ package carpet.mixins; -import carpet.fakes.IngredientInterface; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; @Mixin(Ingredient.class) -public class Ingredient_scarpetMixin implements IngredientInterface +public class Ingredient_scarpetMixin// implements IngredientInterface { - @Shadow @Final private Ingredient.Value[] values; - @Override - public List> getRecipeStacks() - { - return Arrays.stream(values).map(Ingredient.Value::getItems).toList(); - } } diff --git a/src/main/java/carpet/mixins/Item_missingToolsMixin.java b/src/main/java/carpet/mixins/Item_missingToolsMixin.java new file mode 100644 index 00000000..90445ad7 --- /dev/null +++ b/src/main/java/carpet/mixins/Item_missingToolsMixin.java @@ -0,0 +1,30 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.core.component.DataComponents; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.Tool; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +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(Item.class) +public class Item_missingToolsMixin +{ + @Inject(method = "getDestroySpeed", at = @At("HEAD"), cancellable = true) + public void getDestroySpeed(ItemStack itemStack, BlockState blockState, CallbackInfoReturnable cir) { + if (CarpetSettings.missingTools && blockState.getSoundType() == SoundType.GLASS && itemStack.is(ItemTags.PICKAXES)) + { + Tool tool = itemStack.get(DataComponents.TOOL); + if (tool != null) { + cir.setReturnValue(tool.getMiningSpeed(Blocks.STONE.defaultBlockState())); + } + } + } +} diff --git a/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java b/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java index 52b345a8..7b5458ef 100644 --- a/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java @@ -2,7 +2,9 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import org.spongepowered.asm.mixin.Mixin; @@ -25,20 +27,25 @@ public class LevelChunk_fillUpdatesMixin @Redirect(method = "setBlockState", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;onRemove(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Z)V" + target = "Lnet/minecraft/world/level/block/entity/BlockEntity;preRemoveSideEffects(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V" )) - private void onRemovedBlock(BlockState blockState, Level world, BlockPos pos, BlockState state, boolean moved) + private void onPreRemoveSideEffects(BlockEntity blockEntity, BlockPos blockPos_1, BlockState blockState_1) { - if (CarpetSettings.impendingFillSkipUpdates.get()) // doing due dilligence from AbstractBlock onStateReplaced + if (!CarpetSettings.impendingFillSkipUpdates.get()) { - if (blockState.hasBlockEntity() && !blockState.is(state.getBlock())) - { - world.removeBlockEntity(pos); - } + blockEntity.preRemoveSideEffects(blockPos_1, blockState_1); } - else + } + + @Redirect(method = "setBlockState", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/state/BlockState;affectNeighborsAfterRemoval(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Z)V" + )) + private void onAffectNeighborsAfterRemoval(final BlockState instance, final ServerLevel serverLevel, final BlockPos blockPos, final boolean b) + { + if (!CarpetSettings.impendingFillSkipUpdates.get()) { - blockState.onRemove(world, pos, state, moved); + instance.affectNeighborsAfterRemoval(serverLevel, blockPos, b); } } } diff --git a/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java b/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java index 9ea44301..6aa9b979 100644 --- a/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java +++ b/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java @@ -4,10 +4,15 @@ import carpet.CarpetSettings; import carpet.fakes.WorldChunkInterface; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.BaseRailBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -19,6 +24,7 @@ import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.blending.BlendingData; +import net.minecraft.world.level.lighting.LightEngine; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -72,91 +78,119 @@ public abstract class LevelChunk_movableBEMixin extends ChunkAccess implements W */ /* @Nullable */ // todo update me to the new version + @Override public BlockState setBlockStateWithBlockEntity(BlockPos blockPos_1, BlockState newBlockState, BlockEntity newBlockEntity, - boolean boolean_1) + int flags) { - int x = blockPos_1.getX() & 15; + int y = blockPos_1.getY(); - int z = blockPos_1.getZ() & 15; + LevelChunkSection chunkSection = this.getSection(this.getSectionIndex(y)); - if (chunkSection.hasOnlyAir()) + + boolean hadOnlyAir = chunkSection.hasOnlyAir(); + + if (hadOnlyAir && newBlockState.isAir()) { - if (newBlockState.isAir()) - { - return null; - } + return null; } - - boolean boolean_2 = chunkSection.hasOnlyAir(); - BlockState oldBlockState = chunkSection.setBlockState(x, y & 15, z, newBlockState); + + int x = blockPos_1.getX() & 15; + int chunkY = blockPos_1.getY() & 15; + int z = blockPos_1.getZ() & 15; + BlockState oldBlockState = chunkSection.setBlockState(x, chunkY, z, newBlockState); if (oldBlockState == newBlockState) { return null; } - else + Block newBlock = newBlockState.getBlock(); + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(x, y, z, newBlockState); + boolean hasOnlyAir = chunkSection.hasOnlyAir(); + if (hadOnlyAir != hasOnlyAir) { - Block newBlock = newBlockState.getBlock(); - Block oldBlock = oldBlockState.getBlock(); - ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(x, y, z, newBlockState); - boolean boolean_3 = chunkSection.hasOnlyAir(); - if (boolean_2 != boolean_3) - { - this.level.getChunkSource().getLightEngine().updateSectionStatus(blockPos_1, boolean_3); + this.level.getChunkSource().getLightEngine().updateSectionStatus(blockPos_1, hasOnlyAir); + this.level.getChunkSource().onSectionEmptinessChanged(chunkPos.x, SectionPos.blockToSectionCoord(y), chunkPos.z, hasOnlyAir); + } + + if (LightEngine.hasDifferentLightProperties(oldBlockState, newBlockState)) { + ProfilerFiller profiler = Profiler.get(); + profiler.push("updateSkyLightSources"); + skyLightSources.update(this, x, chunkY, z); + profiler.popPush("queueCheckLight"); + level.getChunkSource().getLightEngine().checkBlock(blockPos_1); + profiler.pop(); + } + + boolean blockChanged = !oldBlockState.is(newBlock); + boolean boolean_1 = (flags & 64) != 0; // moved by pistons + boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0; + + if (blockChanged && oldBlockState.hasBlockEntity()) { + if (level instanceof ServerLevel serverLevel && !(oldBlockState.getBlock() instanceof MovingPistonBlock)) { + if (sideEffects) { + BlockEntity blockEntity = level.getBlockEntity(blockPos_1); + if (blockEntity != null) { + blockEntity.preRemoveSideEffects(blockPos_1, oldBlockState); + } + } } - - if (!this.level.isClientSide) + removeBlockEntity(blockPos_1); + } + + if (blockChanged || newBlock instanceof BaseRailBlock) + { + if (level instanceof ServerLevel serverLevel && !(oldBlockState.getBlock() instanceof MovingPistonBlock)) { - if (!(oldBlock instanceof MovingPistonBlock))//this is a movableTE special case, if condition wasn't there it would remove the blockentity that was carried for some reason - oldBlockState.onRemove(this.level, blockPos_1, newBlockState, boolean_1);//this kills it + if ((flags & Block.UPDATE_NEIGHBORS) != 0 || boolean_1) + { + oldBlockState.affectNeighborsAfterRemoval(serverLevel, blockPos_1, boolean_1); + } } - else if (oldBlock != newBlock && oldBlock instanceof EntityBlock) + } + + + if (chunkSection.getBlockState(x, chunkY, z).getBlock() != newBlock) + { + return null; + } + + if (!level.isClientSide && sideEffects) { + // this updates stuff, schedule ticks - do we want that since its only be called from MovingPistonBlock really? + newBlockState.onPlace(level, blockPos_1, oldBlockState, boolean_1); + } + + BlockEntity oldBlockEntity = null; + if (oldBlockState.hasBlockEntity()) + { + oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK); + if (oldBlockEntity != null && !oldBlockEntity.isValidBlockState(oldBlockState)) { - this.level.removeBlockEntity(blockPos_1); - } - - if (chunkSection.getBlockState(x, y & 15, z).getBlock() != newBlock) - { - return null; + oldBlockEntity.setBlockState(oldBlockState); + updateBlockEntityTicker(oldBlockEntity); } else { - BlockEntity oldBlockEntity = null; - if (oldBlockState.hasBlockEntity()) + if (newBlockEntity == null) { - oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK); - if (oldBlockEntity != null) + newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState); + if (newBlockEntity != null) { - oldBlockEntity.setBlockState(oldBlockState); - updateBlockEntityTicker(oldBlockEntity); + addAndRegisterBlockEntity(newBlockEntity); } } - - if (oldBlockState.hasBlockEntity()) + if (newBlockEntity != oldBlockEntity && newBlockEntity != null) { - if (newBlockEntity == null) - { - newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState); - } - if (newBlockEntity != oldBlockEntity && newBlockEntity != null) - { - newBlockEntity.clearRemoved(); - this.level.setBlockEntity(newBlockEntity); - newBlockEntity.setBlockState(newBlockState); - updateBlockEntityTicker(newBlockEntity); - } + newBlockEntity.clearRemoved(); + this.level.setBlockEntity(newBlockEntity); + newBlockEntity.setBlockState(newBlockState); + updateBlockEntityTicker(newBlockEntity); } - - if (!this.level.isClientSide) - { - newBlockState.onPlace(this.level, blockPos_1, oldBlockState, boolean_1); //This can call setblockstate! (e.g. hopper does) - } - - this.unsaved = true; // shouldSave - return oldBlockState; } } + + markUnsaved(); + return oldBlockState; } } diff --git a/src/main/java/carpet/mixins/LevelRenderer_scarpetRenderMixin.java b/src/main/java/carpet/mixins/LevelRenderer_scarpetRenderMixin.java index f2a71f2b..2a63219a 100644 --- a/src/main/java/carpet/mixins/LevelRenderer_scarpetRenderMixin.java +++ b/src/main/java/carpet/mixins/LevelRenderer_scarpetRenderMixin.java @@ -2,18 +2,20 @@ package carpet.mixins; import carpet.network.CarpetClient; import carpet.script.utils.ShapesRenderer; -import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.framegraph.FrameGraphBuilder; +import com.mojang.blaze3d.framegraph.FramePass; import net.minecraft.client.Camera; -import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.LevelTargetBundle; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Final; 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; @@ -21,30 +23,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LevelRenderer.class) public class LevelRenderer_scarpetRenderMixin { + @Shadow @Final private LevelTargetBundle targets; + @Inject(method = "", at = @At("RETURN")) private void addRenderers(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) { CarpetClient.shapes = new ShapesRenderer(minecraft); } - @Inject(method = "renderLevel", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/Sheets;translucentCullBlockSheet()Lnet/minecraft/client/renderer/RenderType;", shift = At.Shift.BEFORE - //target = "Lnet/minecraft/client/render/RenderLayer;getWaterMask()Lnet/minecraft/client/render/RenderLayer;", shift = At.Shift.AFTER - //target = "Lnet/minecraft/client/render/BufferBuilderStorage;getEffectVertexConsumers()Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;", shift = At.Shift.BEFORE - //target = "Lnet/minecraft/client/render/WorldRenderer;renderChunkDebugInfo(Lnet/minecraft/client/render/Camera;)V", shift = At.Shift.AFTER - //target = "Lnet/minecraft/client/render/BackgroundRenderer;method_23792()V", shift = At.Shift.AFTER - //target = "Lnet/minecraft/client/render/BufferBuilderStorage;getEntityVertexConsumers()Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;", shift = At.Shift.AFTER - //target = "Lnet/minecraft/client/render/WorldRenderer;renderChunkDebugInfo(Lnet/minecraft/client/render/Camera;)V", shift = At.Shift.AFTER // before return - )) - private void renderScarpetThings(final DeltaTracker deltaTracker, final boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightmapTextureManager, Matrix4f modelViewMatrix, Matrix4f matrix4f, CallbackInfo ci) + @Inject(method = "addParticlesPass", at = @At("RETURN")) + private void renderScarpetThingsLate(FrameGraphBuilder frameGraphBuilder, Camera camera, float f, GpuBufferSlice fogParameters, CallbackInfo ci) { // in normal circumstances we want to render shapes at the very end so it appears correctly behind stuff. // we might actually not need to play with render hooks here. //if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null ) if (CarpetClient.shapes != null) { - CarpetClient.shapes.render(modelViewMatrix, camera, deltaTracker.getGameTimeDeltaPartialTick(false)); + FramePass pass = frameGraphBuilder.addPass("scarpet_shapes"); + targets.main = pass.readsAndWrites(targets.main); + pass.executes(() -> CarpetClient.shapes.render(null, camera, f)); } } } diff --git a/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java b/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java index cb050c7a..0b141729 100644 --- a/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java @@ -23,11 +23,11 @@ public abstract class Level_fillUpdatesMixin @Redirect(method = "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;II)Z", at = @At( //setBlockState main value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/world/level/Level;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private void updateNeighborsMaybe(Level world, BlockPos blockPos, Block block) { - if (!CarpetSettings.impendingFillSkipUpdates.get()) world.blockUpdated(blockPos, block); + if (!CarpetSettings.impendingFillSkipUpdates.get()) world.updateNeighborsAt(blockPos, block); } } diff --git a/src/main/java/carpet/mixins/Level_getOtherEntitiesLimited.java b/src/main/java/carpet/mixins/Level_getOtherEntitiesLimited.java index 4a6b4a75..aeb60732 100644 --- a/src/main/java/carpet/mixins/Level_getOtherEntitiesLimited.java +++ b/src/main/java/carpet/mixins/Level_getOtherEntitiesLimited.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.fakes.LevelInterface; import com.google.common.collect.Lists; +import net.minecraft.util.profiling.Profiler; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -9,7 +10,6 @@ import org.spongepowered.asm.mixin.Shadow; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; -import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; @@ -24,7 +24,7 @@ public abstract class Level_getOtherEntitiesLimited implements LevelInterface { @Override public List getOtherEntitiesLimited(@Nullable Entity except, AABB box, Predicate predicate, int limit) { - this.getProfiler().incrementCounter("getEntities"); // visit + Profiler.get().incrementCounter("getEntities"); // visit AtomicInteger checkedEntities = new AtomicInteger(); List list = Lists.newArrayList(); try { @@ -55,9 +55,6 @@ public abstract class Level_getOtherEntitiesLimited implements LevelInterface { return list; } - @Shadow - public abstract ProfilerFiller getProfiler(); - @Shadow protected abstract LevelEntityGetter getEntities(); } diff --git a/src/main/java/carpet/mixins/Level_movableBEMixin.java b/src/main/java/carpet/mixins/Level_movableBEMixin.java index d5820368..d774f158 100644 --- a/src/main/java/carpet/mixins/Level_movableBEMixin.java +++ b/src/main/java/carpet/mixins/Level_movableBEMixin.java @@ -4,8 +4,8 @@ import carpet.fakes.WorldChunkInterface; import carpet.fakes.LevelInterface; import net.minecraft.core.BlockPos; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; @@ -28,32 +28,18 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces @Shadow public abstract LevelChunk getChunkAt(BlockPos blockPos_1); - @Shadow - public abstract BlockState getBlockState(BlockPos blockPos_1); - - //@Shadow - //public abstract ChunkManager getChunkManager(); - @Shadow public abstract void setBlocksDirty(BlockPos blockPos_1, BlockState s1, BlockState s2); @Shadow public abstract void sendBlockUpdated(BlockPos var1, BlockState var2, BlockState var3, int var4); - - @Shadow - public abstract void updateNeighborsAt(BlockPos blockPos_1, Block block_1); - - @Shadow - public abstract void onBlockStateChange(BlockPos blockPos_1, BlockState blockState_1, BlockState blockState_2); - - @Shadow public abstract ProfilerFiller getProfiler(); @Shadow public abstract void updateNeighbourForOutputSignal(BlockPos pos, Block block); - //@Shadow public abstract boolean setBlockState(BlockPos pos, BlockState state, int flags); - @Shadow public abstract boolean isDebug(); + @Shadow public abstract void updatePOIOnBlockStateChange(final BlockPos blockPos, final BlockState blockState, final BlockState blockState2); + /** * @author 2No2Name */ @@ -67,7 +53,7 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces BlockState blockState_2; if (newBlockEntity != null && block_1 instanceof EntityBlock) { - blockState_2 = ((WorldChunkInterface) worldChunk_1).setBlockStateWithBlockEntity(blockPos_1, blockState_1, newBlockEntity, (int_1 & 64) != 0); + blockState_2 = ((WorldChunkInterface) worldChunk_1).setBlockStateWithBlockEntity(blockPos_1, blockState_1, newBlockEntity, int_1); if (newBlockEntity instanceof LidBlockEntity) { scheduleTick(blockPos_1, block_1, 5); @@ -75,56 +61,46 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces } else { - blockState_2 = worldChunk_1.setBlockState(blockPos_1, blockState_1, (int_1 & 64) != 0); + blockState_2 = worldChunk_1.setBlockState(blockPos_1, blockState_1, int_1); } if (blockState_2 == null) { return false; } - else + + BlockState blockState_3 = this.getBlockState(blockPos_1); + + if (blockState_3 == blockState_1) { - BlockState blockState_3 = this.getBlockState(blockPos_1); - - if (blockState_3 != blockState_2 && (blockState_3.getLightBlock((BlockGetter) this, blockPos_1) != blockState_2.getLightBlock((BlockGetter) this, blockPos_1) || blockState_3.getLightEmission() != blockState_2.getLightEmission() || blockState_3.useShapeForLightOcclusion() || blockState_2.useShapeForLightOcclusion())) + if (blockState_2 != blockState_3) { - ProfilerFiller profiler = getProfiler(); - profiler.push("queueCheckLight"); - this.getChunkSource().getLightEngine().checkBlock(blockPos_1); - profiler.pop(); + this.setBlocksDirty(blockPos_1, blockState_2, blockState_3); } - if (blockState_3 == blockState_1) + if ((int_1 & 2) != 0 && (!this.isClientSide || (int_1 & 4) == 0) && (this.isClientSide || worldChunk_1.getFullStatus() != null && worldChunk_1.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { - if (blockState_2 != blockState_3) - { - this.setBlocksDirty(blockPos_1, blockState_2, blockState_3); - } - - if ((int_1 & 2) != 0 && (!this.isClientSide || (int_1 & 4) == 0) && (this.isClientSide || worldChunk_1.getFullStatus() != null && worldChunk_1.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) - { - this.sendBlockUpdated(blockPos_1, blockState_2, blockState_1, int_1); - } - - if (!this.isClientSide && (int_1 & 1) != 0) - { - this.updateNeighborsAt(blockPos_1, blockState_2.getBlock()); - if (blockState_1.hasAnalogOutputSignal()) - { - updateNeighbourForOutputSignal(blockPos_1, block_1); - } - } - - if ((int_1 & 16) == 0) - { - int int_2 = int_1 & -34; - blockState_2.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare - blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours - blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare - } - this.onBlockStateChange(blockPos_1, blockState_2, blockState_3); + this.sendBlockUpdated(blockPos_1, blockState_2, blockState_1, int_1); } - return true; + + if (!this.isClientSide && (int_1 & 1) != 0) + { + this.updateNeighborsAt(blockPos_1, blockState_2.getBlock()); + if (blockState_1.hasAnalogOutputSignal()) + { + updateNeighbourForOutputSignal(blockPos_1, block_1); + } + } + + if ((int_1 & 16) == 0) + { + int int_2 = int_1 & -34; + blockState_2.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare + blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours + blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare + } + updatePOIOnBlockStateChange(blockPos_1, blockState_2, blockState_3); } + return true; } } diff --git a/src/main/java/carpet/mixins/LivingEntity_cleanLogsMixin.java b/src/main/java/carpet/mixins/LivingEntity_cleanLogsMixin.java index 525d918f..16b5306f 100644 --- a/src/main/java/carpet/mixins/LivingEntity_cleanLogsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_cleanLogsMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.CarpetSettings; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; @@ -22,6 +23,6 @@ public abstract class LivingEntity_cleanLogsMixin extends Entity @Redirect(method = "die", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hasCustomName()Z")) private boolean shouldLogDeaths(LivingEntity livingEntity) { - return livingEntity.hasCustomName() && CarpetSettings.cleanLogs && level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); + return livingEntity.hasCustomName() && CarpetSettings.cleanLogs && livingEntity.getServer().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); } } diff --git a/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java index 5b22f42f..24771951 100644 --- a/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java @@ -25,8 +25,8 @@ public abstract class LivingEntity_creativeFlyMixin extends Entity super(type, world); } - @ModifyConstant(method = "travel", constant = @Constant(floatValue = 0.91F), expect = 2) - private float drag(float original) + @ModifyConstant(method = "travelInAir", constant = @Constant(floatValue = 0.91F), expect = 1) + private float dragAir(float original) { if (CarpetSettings.creativeFlyDrag != 0.09 && (Object)this instanceof Player) { @@ -37,7 +37,6 @@ public abstract class LivingEntity_creativeFlyMixin extends Entity return original; } - @Inject(method = "getFrictionInfluencedSpeed(F)F", at = @At("HEAD"), cancellable = true) private void flyingAltSpeed(float slipperiness, CallbackInfoReturnable cir) { diff --git a/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java b/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java index f7168f9a..90474f0e 100644 --- a/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.CarpetSettings; import carpet.fakes.LevelInterface; +import net.minecraft.server.level.ServerLevel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -33,12 +34,18 @@ public abstract class LivingEntity_maxCollisionsMixin extends Entity { return; } + + if (!(this.level() instanceof ServerLevel serverLevel)) + { + return; + } + List entities; int maxEntityCramming =-1; if (CarpetSettings.maxEntityCollisions > 0) { - maxEntityCramming = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); - entities = ((LevelInterface) this.level()).getOtherEntitiesLimited( + maxEntityCramming = serverLevel.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); + entities = ((LevelInterface) serverLevel).getOtherEntitiesLimited( this, this.getBoundingBox(), EntitySelector.pushableBy(this), @@ -46,11 +53,11 @@ public abstract class LivingEntity_maxCollisionsMixin extends Entity } else { - entities = this.level().getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + entities = serverLevel.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); } if (!entities.isEmpty()) { - if (maxEntityCramming < 0) maxEntityCramming = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); + if (maxEntityCramming < 0) maxEntityCramming = serverLevel.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); if (maxEntityCramming > 0 && entities.size() > maxEntityCramming - 1 && this.random.nextInt(4) == 0) { int candidates = 0; diff --git a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java index fe461420..0c5b8e9d 100644 --- a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.fakes.EntityInterface; import carpet.fakes.LivingEntityInterface; import carpet.script.EntityEventsGroup; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -42,7 +43,7 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity implements target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F", shift = At.Shift.BEFORE )) - private void entityTakingDamage(DamageSource source, float amount, CallbackInfo ci) + private void entityTakingDamage(ServerLevel serverLevel, DamageSource source, float amount, CallbackInfo ci) { ((EntityInterface)this).getEventContainer().onEvent(EntityEventsGroup.Event.ON_DAMAGE, amount, source); // this is not applicable since its not a playr for sure diff --git a/src/main/java/carpet/mixins/MinecraftMixin.java b/src/main/java/carpet/mixins/MinecraftMixin.java index ffe95fb8..613d220e 100644 --- a/src/main/java/carpet/mixins/MinecraftMixin.java +++ b/src/main/java/carpet/mixins/MinecraftMixin.java @@ -15,8 +15,8 @@ public class MinecraftMixin { @Shadow public ClientLevel level; - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD")) - private void onCloseGame(Screen screen, CallbackInfo ci) + @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;Z)V", at = @At("HEAD")) + private void onCloseGame(Screen screen, boolean b, CallbackInfo ci) { CarpetClient.disconnect(); } diff --git a/src/main/java/carpet/mixins/MinecraftServer_pingPlayerSampleLimit.java b/src/main/java/carpet/mixins/MinecraftServer_pingPlayerSampleLimit.java index e53249c1..f70925e7 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_pingPlayerSampleLimit.java +++ b/src/main/java/carpet/mixins/MinecraftServer_pingPlayerSampleLimit.java @@ -11,7 +11,7 @@ import net.minecraft.server.MinecraftServer; public abstract class MinecraftServer_pingPlayerSampleLimit { - @ModifyConstant(method = "tickServer", constant = @Constant(intValue = 12), require = 0, allow = 1) + @ModifyConstant(method = "buildPlayerStatus", constant = @Constant(intValue = 12), require = 1) private int modifyPlayerSampleLimit(int value) { return CarpetSettings.pingPlayerListLimit; diff --git a/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java b/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java index a52d55a0..d92513c9 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java @@ -102,7 +102,7 @@ public abstract class MinecraftServer_scarpetMixin extends ReentrantBlockableEve @Override public void reloadAfterReload(RegistryAccess newRegs) { - resources.managers().updateRegistryTags(); + resources.managers().updateStaticRegistryTags(); getPlayerList().saveAll(); getPlayerList().reloadResources(); functionManager.replaceLibrary(this.resources.managers().getFunctionLibrary()); diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index 27fde78c..aba7780b 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -10,8 +10,6 @@ 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.function.BooleanSupplier; - @Mixin(value = MinecraftServer.class, priority = Integer.MAX_VALUE - 10) public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableEventLoop implements MinecraftServerInterface { @@ -26,7 +24,7 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE // could possibly just inject that mspt selection at the beginning of the loop, but then adding all mspt's to // replace 50L will be a hassle @Inject(method = "runServer", at = @At(value = "INVOKE", shift = At.Shift.AFTER, - target = "Lnet/minecraft/server/MinecraftServer;startMetricsRecordingTick()V")) + target = "Lnet/minecraft/util/profiling/Profiler;get()Lnet/minecraft/util/profiling/ProfilerFiller;")) private void modifiedRunLoop(CallbackInfo ci) { if (CarpetProfiler.tick_health_requested != 0L) @@ -36,42 +34,34 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE } - @Inject(method = "tickServer", at = @At( + @Inject(method = "autoSave", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;saveEverything(ZZZ)Z", // save shift = At.Shift.BEFORE )) - private void startAutosave(BooleanSupplier booleanSupplier_1, CallbackInfo ci) + private void startAutosave(final CallbackInfo ci) { currentSection = CarpetProfiler.start_section(null, "Autosave", CarpetProfiler.TYPE.GENERAL); } - @Inject(method = "tickServer", at = @At( + @Inject(method = "autoSave", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;saveEverything(ZZZ)Z", shift = At.Shift.AFTER )) - private void finishAutosave(BooleanSupplier booleanSupplier_1, CallbackInfo ci) + private void finishAutosave(final CallbackInfo ci) { CarpetProfiler.end_current_section(currentSection); } - @Inject(method = "tickChildren", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/MinecraftServer;getConnection()Lnet/minecraft/server/network/ServerConnectionListener;", - shift = At.Shift.BEFORE - )) - private void startNetwork(BooleanSupplier booleanSupplier_1, CallbackInfo ci) + @Inject(method = "tickConnection", at = @At("HEAD")) + private void startNetwork(final CallbackInfo ci) { currentSection = CarpetProfiler.start_section(null, "Network", CarpetProfiler.TYPE.GENERAL); } - @Inject(method = "tickChildren", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/players/PlayerList;tick()V", - shift = At.Shift.AFTER - )) - private void finishNetwork(BooleanSupplier booleanSupplier_1, CallbackInfo ci) + @Inject(method = "tickConnection", at = @At("RETURN")) + private void finishNetwork(final CallbackInfo ci) { CarpetProfiler.end_current_section(currentSection); } @@ -94,6 +84,4 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE CarpetProfiler.end_tick_profiling((MinecraftServer) (Object)this); } } - - } diff --git a/src/main/java/carpet/mixins/NaturalSpawnerMixin.java b/src/main/java/carpet/mixins/NaturalSpawnerMixin.java index 8cd2f826..7ab4f6f5 100644 --- a/src/main/java/carpet/mixins/NaturalSpawnerMixin.java +++ b/src/main/java/carpet/mixins/NaturalSpawnerMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.CarpetSettings; import carpet.fakes.LevelInterface; import carpet.utils.SpawnReporter; +import net.minecraft.world.entity.EntitySpawnReason; import org.apache.commons.lang3.tuple.Pair; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -12,9 +13,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; import java.util.Map; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.BlockTags; @@ -24,7 +25,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnGroupData; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -133,9 +133,9 @@ public class NaturalSpawnerMixin @Redirect(method = "getMobForSpawn", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/world/level/Level;)Lnet/minecraft/world/entity/Entity;" + target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/EntitySpawnReason;)Lnet/minecraft/world/entity/Entity;" )) - private static Entity create(EntityType entityType, Level world_1) + private static Entity create(final EntityType entityType, final Level world_1, final EntitySpawnReason entitySpawnReason) { if (CarpetSettings.lagFreeSpawning) { @@ -143,11 +143,11 @@ public class NaturalSpawnerMixin if (precookedMobs.containsKey(entityType)) //this mob has been 's but not used yet return precookedMobs.get(entityType); - Entity e = entityType.create(world_1); + Entity e = entityType.create(world_1, entitySpawnReason); precookedMobs.put(entityType, e); return e; } - return entityType.create(world_1); + return entityType.create(world_1, entitySpawnReason); } @Redirect(method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V", at = @At( @@ -176,9 +176,9 @@ public class NaturalSpawnerMixin @Redirect(method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/Mob;finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;" + target = "Lnet/minecraft/world/entity/Mob;finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;" )) - private static SpawnGroupData spawnEntity(Mob mobEntity, ServerLevelAccessor serverWorldAccess, DifficultyInstance difficulty, MobSpawnType spawnReason, SpawnGroupData entityData) + private static SpawnGroupData spawnEntity(Mob mobEntity, ServerLevelAccessor serverWorldAccess, DifficultyInstance difficulty, EntitySpawnReason spawnReason, SpawnGroupData entityData) { if (!SpawnReporter.mockSpawns) // WorldAccess return mobEntity.finalizeSpawn(serverWorldAccess, difficulty, spawnReason, entityData); @@ -271,17 +271,13 @@ public class NaturalSpawnerMixin @Inject(method = "spawnForChunk", at = @At("HEAD")) // allows to change mobcaps and captures each category try per dimension before it fails due to full mobcaps. private static void checkSpawns(ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnState info, - boolean spawnAnimals, boolean spawnMonsters, boolean shouldSpawnAnimals, CallbackInfo ci) + List list, CallbackInfo ci) { if (SpawnReporter.trackingSpawns()) { - MobCategory[] var6 = SPAWNING_CATEGORIES; - int var7 = var6.length; + for (MobCategory entityCategory: list) + { - for(int var8 = 0; var8 < var7; ++var8) { - MobCategory entityCategory = var6[var8]; - if ((spawnAnimals || !entityCategory.isFriendly()) && (spawnMonsters || entityCategory.isFriendly()) && (shouldSpawnAnimals || !entityCategory.isPersistent()) ) - { ResourceKey dim = world.dimension(); // getDimensionType; int newCap = entityCategory.getMaxInstancesPerChunk(); //(int) ((double)entityCategory.getCapacity()*(Math.pow(2.0,(SpawnReporter.mobcap_exponent/4)))); int int_2 = SpawnReporter.chunkCounts.get(dim); // eligible chunks for spawning @@ -311,7 +307,6 @@ public class NaturalSpawnerMixin //else //full mobcaps - and key in local_spawns will be missing } - } } } } diff --git a/src/main/java/carpet/mixins/PerfCommand_permissionMixin.java b/src/main/java/carpet/mixins/PerfCommand_permissionMixin.java index a07fdd4d..d0c9f58f 100644 --- a/src/main/java/carpet/mixins/PerfCommand_permissionMixin.java +++ b/src/main/java/carpet/mixins/PerfCommand_permissionMixin.java @@ -1,20 +1,24 @@ package carpet.mixins; import carpet.CarpetSettings; -import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.PermissionSource; import net.minecraft.server.commands.PerfCommand; +import net.minecraft.server.commands.PermissionCheck; 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; +import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(PerfCommand.class) public class PerfCommand_permissionMixin { - @Inject(method = "method_37340", at = @At("HEAD"), cancellable = true, remap = false) - private static void canRun(CommandSourceStack source, CallbackInfoReturnable cir) + @Redirect(method = "register", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/commands/Commands;hasPermission(I)Lnet/minecraft/server/commands/PermissionCheck;" + )) + private static PermissionCheck canRun(int i) { - cir.setReturnValue(source.hasPermission(CarpetSettings.perfPermissionLevel)); + return Commands.hasPermission(CarpetSettings.perfPermissionLevel); } } diff --git a/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java b/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java deleted file mode 100644 index a8e9a3f4..00000000 --- a/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package carpet.mixins; - -import carpet.CarpetSettings; -import net.minecraft.core.component.DataComponents; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.DiggerItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.PickaxeItem; -import net.minecraft.world.item.Tier; -import net.minecraft.world.item.component.Tool; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(PickaxeItem.class) -public class PickaxeItem_missingToolsMixin extends DiggerItem -{ - - protected PickaxeItem_missingToolsMixin(Tier material, TagKey tag, Properties settings) { - super(material, tag, settings); - } - - @Override - public float getDestroySpeed(ItemStack stack, BlockState state) { - if (CarpetSettings.missingTools && state.getSoundType() == SoundType.GLASS) - { - final Tool tool = stack.get(DataComponents.TOOL); - return tool != null ? tool.getMiningSpeed(Blocks.STONE.defaultBlockState()) : super.getDestroySpeed(stack, state); - } - return super.getDestroySpeed(stack, state); - } -} diff --git a/src/main/java/carpet/mixins/PistonBaseBlock_movableBEMixin.java b/src/main/java/carpet/mixins/PistonBaseBlock_movableBEMixin.java index ef1a2d3e..5cc5ba95 100644 --- a/src/main/java/carpet/mixins/PistonBaseBlock_movableBEMixin.java +++ b/src/main/java/carpet/mixins/PistonBaseBlock_movableBEMixin.java @@ -3,6 +3,12 @@ package carpet.mixins; import carpet.CarpetSettings; import carpet.fakes.PistonBlockEntityInterface; import com.google.common.collect.Lists; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; + import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; @@ -11,7 +17,6 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.CommandBlock; import net.minecraft.world.level.block.DirectionalBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.piston.MovingPistonBlock; import net.minecraft.world.level.block.piston.PistonBaseBlock; import net.minecraft.world.level.block.piston.PistonStructureResolver; import net.minecraft.world.level.block.state.BlockState; @@ -33,8 +38,6 @@ public abstract class PistonBaseBlock_movableBEMixin extends DirectionalBlock { super(block$Settings_1); } - - private ThreadLocal> list1_BlockEntities = new ThreadLocal<>(); //Unneccessary ThreadLocal if client and server use different PistonBlock instances @Inject(method = "isPushable", cancellable = true, at = @At(value = "RETURN", ordinal = 3, shift = At.Shift.BEFORE)) private static void movableCMD(BlockState blockState_1, Level world_1, BlockPos blockPos_1, @@ -53,7 +56,8 @@ public abstract class PistonBaseBlock_movableBEMixin extends DirectionalBlock //Making PISTON_EXTENSION (BlockPistonMoving) pushable would not work as its createNewTileEntity()-method returns null return block != Blocks.ENDER_CHEST && block != Blocks.ENCHANTING_TABLE && block != Blocks.END_GATEWAY && block != Blocks.END_PORTAL && block != Blocks.MOVING_PISTON && - block != Blocks.SPAWNER; + block != Blocks.SPAWNER + && block != Blocks.SCULK_SENSOR && block != Blocks.CALIBRATED_SCULK_SENSOR; // these have weird behaviour and crashes, #1473, also #1885 } @Redirect(method = "isPushable", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;hasBlockEntity()Z")) @@ -84,17 +88,17 @@ public abstract class PistonBaseBlock_movableBEMixin extends DirectionalBlock private void onMove(Level world_1, BlockPos blockPos_1, Direction direction_1, boolean boolean_1, CallbackInfoReturnable cir, BlockPos blockPos_2, PistonStructureResolver pistonHandler_1, Map map_1, List list_1, List list_2, List list_3, BlockState[] blockStates_1, - Direction direction_2, int int_2) + Direction direction_2, int int_2, @Share("blockEntities") LocalRef> blockEntities) { //Get the blockEntities and remove them from the world before any magic starts to happen if (CarpetSettings.movableBlockEntities) { - list1_BlockEntities.set(Lists.newArrayList()); + blockEntities.set(Lists.newArrayList()); for (int i = 0; i < list_1.size(); ++i) { BlockPos blockpos = list_1.get(i); BlockEntity blockEntity = (list_2.get(i).hasBlockEntity()) ? world_1.getBlockEntity(blockpos) : null; - list1_BlockEntities.get().add(blockEntity); + blockEntities.get().add(blockEntity); if (blockEntity != null) { //hopefully this call won't have any side effects in the future, such as dropping all the BlockEntity's items @@ -105,35 +109,15 @@ public abstract class PistonBaseBlock_movableBEMixin extends DirectionalBlock } } } - - @Inject(method = "moveBlocks", at = @At(value = "INVOKE", shift = At.Shift.BEFORE, - target = "Lnet/minecraft/world/level/Level;setBlockEntity(Lnet/minecraft/world/level/block/entity/BlockEntity;)V", ordinal = 0), - locals = LocalCapture.CAPTURE_FAILHARD) - private void setBlockEntityWithCarried(Level world_1, BlockPos blockPos_1, Direction direction_1, boolean boolean_1, - CallbackInfoReturnable cir, BlockPos blockPos_2, PistonStructureResolver pistonHandler_1, Map map_1, List list_1, - List list_2, List list_3, BlockState[] blockStates_1, Direction direction_2, int int_2, - int int_3, BlockPos blockPos_4, BlockState blockState9, BlockState blockState4) - { - BlockEntity blockEntityPiston = MovingPistonBlock.newMovingBlockEntity(blockPos_4, blockState4, list_2.get(int_3), - direction_1, boolean_1, false); - if (CarpetSettings.movableBlockEntities) - ((PistonBlockEntityInterface) blockEntityPiston).setCarriedBlockEntity(list1_BlockEntities.get().get(int_3)); - world_1.setBlockEntity(blockEntityPiston); - //world_1.setBlockEntity(blockPos_4, blockEntityPiston); - } - - @Redirect(method = "moveBlocks", at = @At(value = "INVOKE", + + @WrapOperation(method = "moveBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockEntity(Lnet/minecraft/world/level/block/entity/BlockEntity;)V", ordinal = 0)) - private void dontDoAnything(Level world, BlockEntity blockEntity) + private void setCarriedOnMove(Level instance, BlockEntity blockEntity, Operation original, + @Local(ordinal = 1) int index, @Share("blockEntities") LocalRef> blockEntities) { - } - - @Redirect(method = "moveBlocks", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/MovingPistonBlock;newMovingBlockEntity(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;ZZ)Lnet/minecraft/world/level/block/entity/BlockEntity;", - ordinal = 0)) - private BlockEntity returnNull(BlockPos blockPos, BlockState blockState, BlockState blockState2, Direction direction, boolean bl, boolean bl2) - { - return null; + if (CarpetSettings.movableBlockEntities) + ((PistonBlockEntityInterface) blockEntity).setCarriedBlockEntity(blockEntities.get().get(index)); + original.call(instance, blockEntity); } } diff --git a/src/main/java/carpet/mixins/PistonHeadRenderer_movableBEMixin.java b/src/main/java/carpet/mixins/PistonHeadRenderer_movableBEMixin.java index 87df4e34..3a8b0e14 100644 --- a/src/main/java/carpet/mixins/PistonHeadRenderer_movableBEMixin.java +++ b/src/main/java/carpet/mixins/PistonHeadRenderer_movableBEMixin.java @@ -10,6 +10,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.PistonHeadRenderer; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -27,8 +28,9 @@ public abstract class PistonHeadRenderer_movableBEMixin implements BlockEntityRe } @Inject(method = "render", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/blockentity/PistonHeadRenderer;renderBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/level/Level;ZI)V", ordinal = 3)) - private void updateRenderBool(PistonMovingBlockEntity pistonBlockEntity_1, float float_1, PoseStack matrixStack_1, MultiBufferSource layeredVertexConsumerStorage_1, int int_1, int int_2, CallbackInfo ci) + target = "Lnet/minecraft/client/renderer/blockentity/PistonHeadRenderer;renderBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/level/Level;ZI)V", + ordinal = 3)) + private void updateRenderBool(PistonMovingBlockEntity pistonBlockEntity_1, float float_1, PoseStack matrixStack_1, MultiBufferSource layeredVertexConsumerStorage_1, int int_1, int int_2, Vec3 cameraPos, CallbackInfo ci) //private void updateRenderBool(PistonBlockEntity pistonBlockEntity_1, double double_1, double double_2, double double_3, float float_1, class_4587 class_4587_1, class_4597 class_4597_1, int int_1, CallbackInfo ci) { if (!((PistonBlockEntityInterface) pistonBlockEntity_1).isRenderModeSet()) @@ -37,7 +39,7 @@ public abstract class PistonHeadRenderer_movableBEMixin implements BlockEntityRe @Inject(method = "render", at = @At("RETURN"), locals = LocalCapture.NO_CAPTURE) - private void endMethod3576(PistonMovingBlockEntity pistonBlockEntity_1, float partialTicks, PoseStack matrixStack_1, MultiBufferSource layeredVertexConsumerStorage_1, int int_1, int init_2, CallbackInfo ci) + private void endMethod3576(PistonMovingBlockEntity pistonBlockEntity_1, float partialTicks, PoseStack matrixStack_1, MultiBufferSource layeredVertexConsumerStorage_1, int int_1, int init_2, Vec3 cameraPos, CallbackInfo ci) { if (((PistonBlockEntityInterface) pistonBlockEntity_1).getRenderCarriedBlockEntity()) { diff --git a/src/main/java/carpet/mixins/PistonMovingBlockEntity_movableBEMixin.java b/src/main/java/carpet/mixins/PistonMovingBlockEntity_movableBEMixin.java index b7d01d79..5323f670 100644 --- a/src/main/java/carpet/mixins/PistonMovingBlockEntity_movableBEMixin.java +++ b/src/main/java/carpet/mixins/PistonMovingBlockEntity_movableBEMixin.java @@ -15,6 +15,10 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -134,25 +138,25 @@ public abstract class PistonMovingBlockEntity_movableBEMixin extends BlockEntity } @Inject(method = "loadAdditional", at = @At(value = "TAIL")) - private void onFromTag(CompoundTag NbtCompound_1, HolderLookup.Provider registries, CallbackInfo ci) + private void onFromTag(ValueInput valueInput, CallbackInfo ci) { - if (CarpetSettings.movableBlockEntities && NbtCompound_1.contains("carriedTileEntityCM", 10)) - { - if (this.movedState.getBlock() instanceof EntityBlock) - this.carriedBlockEntity = ((EntityBlock) (this.movedState.getBlock())).newBlockEntity(worldPosition, movedState);// this.world); - if (carriedBlockEntity != null) //Can actually be null, as BlockPistonMoving.createNewTileEntity(...) returns null - this.carriedBlockEntity.loadWithComponents(NbtCompound_1.getCompound("carriedTileEntityCM"), registries); - setCarriedBlockEntity(carriedBlockEntity); - } + if (CarpetSettings.movableBlockEntities) + valueInput.child("carriedTileEntityCM").ifPresent(tag -> { + if (this.movedState.getBlock() instanceof EntityBlock) + this.carriedBlockEntity = ((EntityBlock) (this.movedState.getBlock())).newBlockEntity(worldPosition, movedState);// this.world); + if (carriedBlockEntity != null) //Can actually be null, as BlockPistonMoving.createNewTileEntity(...) returns null + this.carriedBlockEntity.loadWithComponents(tag); + setCarriedBlockEntity(carriedBlockEntity); + }); } @Inject(method = "saveAdditional", at = @At(value = "RETURN", shift = At.Shift.BEFORE)) - private void onToTag(CompoundTag NbtCompound_1, HolderLookup.Provider registries, CallbackInfo ci) + private void onToTag(ValueOutput valueOutput, CallbackInfo ci) { - if (CarpetSettings.movableBlockEntities && this.carriedBlockEntity != null) + if (CarpetSettings.movableBlockEntities && this.carriedBlockEntity != null && valueOutput instanceof TagValueOutput output) { //Leave name "carriedTileEntityCM" instead of "carriedBlockEntityCM" for upgrade compatibility with 1.13.2 movable TE - NbtCompound_1.put("carriedTileEntityCM", this.carriedBlockEntity.saveWithoutMetadata(registries)); + this.carriedBlockEntity.saveWithoutMetadata(output.child("carriedTileEntityCM")); } } } diff --git a/src/main/java/carpet/mixins/PlayerList_fakePlayersMixin.java b/src/main/java/carpet/mixins/PlayerList_fakePlayersMixin.java index 3cd54ed3..2d8dc9b5 100644 --- a/src/main/java/carpet/mixins/PlayerList_fakePlayersMixin.java +++ b/src/main/java/carpet/mixins/PlayerList_fakePlayersMixin.java @@ -10,6 +10,8 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.CommonListenerCookie; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.PlayerList; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.storage.ValueInput; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -20,6 +22,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import carpet.patches.NetHandlerPlayServerFake; import carpet.patches.EntityPlayerMPFake; +import java.util.Optional; + @Mixin(PlayerList.class) public abstract class PlayerList_fakePlayersMixin { @@ -28,11 +32,11 @@ public abstract class PlayerList_fakePlayersMixin private MinecraftServer server; @Inject(method = "load", at = @At(value = "RETURN", shift = At.Shift.BEFORE)) - private void fixStartingPos(ServerPlayer serverPlayerEntity_1, CallbackInfoReturnable cir) + private void fixStartingPos(ServerPlayer serverPlayer, ProblemReporter problemReporter, CallbackInfoReturnable> cir) { - if (serverPlayerEntity_1 instanceof EntityPlayerMPFake) + if (serverPlayer instanceof EntityPlayerMPFake) { - ((EntityPlayerMPFake) serverPlayerEntity_1).fixStartingPosition.run(); + ((EntityPlayerMPFake) serverPlayer).fixStartingPosition.run(); } } diff --git a/src/main/java/carpet/mixins/Player_antiCheatDisabledMixin.java b/src/main/java/carpet/mixins/Player_antiCheatDisabledMixin.java index 8a9625dc..2a4b6ed0 100644 --- a/src/main/java/carpet/mixins/Player_antiCheatDisabledMixin.java +++ b/src/main/java/carpet/mixins/Player_antiCheatDisabledMixin.java @@ -2,11 +2,15 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ElytraItem; +//import net.minecraft.world.item.ElytraItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -14,19 +18,24 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Player.class) -public abstract class Player_antiCheatDisabledMixin +public abstract class Player_antiCheatDisabledMixin extends LivingEntity { - @Shadow public abstract ItemStack getItemBySlot(EquipmentSlot equipmentSlot_1); + protected Player_antiCheatDisabledMixin(final EntityType entityType, final Level level) + { + super(entityType, level); + } @Shadow public abstract void startFallFlying(); + @Shadow public abstract Inventory getInventory(); + @Inject(method = "tryToStartFallFlying", at = @At("HEAD"), cancellable = true) private void allowDeploys(CallbackInfoReturnable cir) { if (CarpetSettings.antiCheatDisabled && (Object)this instanceof ServerPlayer sp && sp.getServer().isDedicatedServer()) { - ItemStack itemStack_1 = getItemBySlot(EquipmentSlot.CHEST); - if (itemStack_1.getItem() == Items.ELYTRA && ElytraItem.isFlyEnabled(itemStack_1)) { + ItemStack itemStack_1 = equipment.get(EquipmentSlot.CHEST); + if (itemStack_1.getItem() == Items.ELYTRA && !itemStack_1.nextDamageWillBreak()) { startFallFlying(); cir.setReturnValue(true); } diff --git a/src/main/java/carpet/mixins/Player_parrotMixin.java b/src/main/java/carpet/mixins/Player_parrotMixin.java index bc29fc66..b7d32283 100644 --- a/src/main/java/carpet/mixins/Player_parrotMixin.java +++ b/src/main/java/carpet/mixins/Player_parrotMixin.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; @@ -57,7 +58,7 @@ public abstract class Player_parrotMixin extends LivingEntity } } - @Redirect(method = "hurt", at = @At(value = "INVOKE", + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;removeEntitiesOnShoulder()V")) private void cancelDropShoulderEntities2(Player playerEntity) { @@ -76,9 +77,9 @@ public abstract class Player_parrotMixin extends LivingEntity this.setShoulderEntityRight(new CompoundTag()); } - @Inject(method = "hurt", at = @At(value = "INVOKE", shift = At.Shift.BEFORE, + @Inject(method = "hurtServer", at = @At(value = "INVOKE", shift = At.Shift.BEFORE, target = "Lnet/minecraft/world/entity/player/Player;removeEntitiesOnShoulder()V")) - private void onDamage(DamageSource damageSource_1, float float_1, CallbackInfoReturnable cir) + private void onDamage(ServerLevel serverLevel, DamageSource damageSource_1, float float_1, CallbackInfoReturnable cir) { if (CarpetSettings.persistentParrots && !this.isShiftKeyDown()) { diff --git a/src/main/java/carpet/mixins/Player_scarpetEventsMixin.java b/src/main/java/carpet/mixins/Player_scarpetEventsMixin.java index 31720265..44411d5a 100644 --- a/src/main/java/carpet/mixins/Player_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/Player_scarpetEventsMixin.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.fakes.EntityInterface; import carpet.script.EntityEventsGroup; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -36,7 +37,7 @@ public abstract class Player_scarpetEventsMixin extends LivingEntity value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F" )) - private void playerTakingDamage(DamageSource source, float amount, CallbackInfo ci) + private void playerTakingDamage(ServerLevel serverLevel, DamageSource source, float amount, CallbackInfo ci) { // version of LivingEntity_scarpetEventsMixin::entityTakingDamage ((EntityInterface)this).getEventContainer().onEvent(EntityEventsGroup.Event.ON_DAMAGE, amount, source); diff --git a/src/main/java/carpet/mixins/RecipeManager_scarpetMixin.java b/src/main/java/carpet/mixins/RecipeManager_scarpetMixin.java deleted file mode 100644 index d95593e4..00000000 --- a/src/main/java/carpet/mixins/RecipeManager_scarpetMixin.java +++ /dev/null @@ -1,50 +0,0 @@ -package carpet.mixins; - -import carpet.fakes.RecipeManagerInterface; -import com.google.common.collect.Multimap; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.world.item.Item; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.world.item.crafting.RecipeType; - -@Mixin(RecipeManager.class) -public class RecipeManager_scarpetMixin implements RecipeManagerInterface -{ - @Shadow private Multimap, RecipeHolder> byType; - - @Shadow private Map> byName; - - @Override - public List> getAllMatching(RecipeType type, ResourceLocation itemId, RegistryAccess registryAccess) - { - // quiq cheq - RecipeHolder recipe = byName.get(itemId); - if (recipe != null && recipe.value().getType().equals(type)) - { - return List.of(recipe.value()); - } - if (!byType.containsKey(type)) - { - // happens when mods add recipe to the registry without updating recipe manager - return List.of(); - } - Collection> typeRecipes = byType.get(type); - Registry regs = registryAccess.registryOrThrow(Registries.ITEM); - Item item = regs.get(itemId); - return typeRecipes.stream() - .>map(RecipeHolder::value) - .filter(r -> r.getResultItem(registryAccess).getItem() == item) - .toList(); - } -} diff --git a/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java b/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java index 0ac25bd1..5cdceb9a 100644 --- a/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java +++ b/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java @@ -1,9 +1,13 @@ package carpet.mixins; import carpet.CarpetSettings; +import carpet.fakes.DefaultRedstoneWireEvaluatorInferface; import carpet.fakes.RedstoneWireBlockInterface; import carpet.helpers.RedstoneWireTurbo; import com.google.common.collect.Sets; +import net.minecraft.world.level.redstone.DefaultRedstoneWireEvaluator; +import net.minecraft.world.level.redstone.Orientation; +import net.minecraft.world.level.redstone.RedstoneWireEvaluator; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; @@ -21,16 +25,15 @@ import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; +import javax.annotation.Nullable; + import static net.minecraft.world.level.block.RedStoneWireBlock.POWER; @Mixin(RedStoneWireBlock.class) public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockInterface { @Shadow - private void updatePowerStrength(Level world_1, BlockPos blockPos_1, BlockState blockState_1) { } - - @Shadow - private int calculateTargetStrength(Level world, BlockPos pos) { return 0; } + private void updatePowerStrength(Level world_1, BlockPos blockPos_1, BlockState blockState_1, @Nullable final Orientation orientation, boolean sup) { } @Override @Accessor("shouldSignal") @@ -40,6 +43,8 @@ public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockIn @Accessor("shouldSignal") public abstract boolean getWiresGivePower(); + private RedstoneWireEvaluator legacy = new DefaultRedstoneWireEvaluator((RedStoneWireBlock)(Object) this); + // = private RedstoneWireTurbo wireTurbo = null; @@ -52,20 +57,22 @@ public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockIn // = - public void fastUpdate(Level world, BlockPos pos, BlockState state, BlockPos source) { + public void fastUpdate(Level world, BlockPos pos, BlockState state, Orientation o, boolean sup) { // [CM] fastRedstoneDust -- update based on carpet rule if (CarpetSettings.fastRedstoneDust) { + BlockPos source = null; // todo this probably removes all improvements from the original method + // so needs to be evaluated if its worth keeping wireTurbo.updateSurroundingRedstone(world, pos, state, source); return; } - updatePowerStrength(world, pos, state); + updatePowerStrength(world, pos, state, o, sup); } /** * @author theosib, soykaf, gnembon */ @Inject(method = "updatePowerStrength", at = @At("HEAD"), cancellable = true) - private void updateLogicAlternative(Level world, BlockPos pos, BlockState state, CallbackInfo cir) { + private void updateLogicAlternative(Level world, BlockPos pos, BlockState state, Orientation orientation, boolean sup, CallbackInfo cir) { if (CarpetSettings.fastRedstoneDust) { updateLogicPublic(world, pos, state); cir.cancel(); @@ -74,7 +81,7 @@ public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockIn @Override public BlockState updateLogicPublic(Level world_1, BlockPos blockPos_1, BlockState blockState_1) { - int i = this.calculateTargetStrength(world_1, blockPos_1); + int i = ((DefaultRedstoneWireEvaluatorInferface)legacy).calculateTargetStrengthCM(world_1, blockPos_1); BlockState blockState = blockState_1; if (blockState_1.getValue(POWER) != i) { blockState_1 = blockState_1.setValue(POWER, i); @@ -107,28 +114,37 @@ public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockIn // = - @Redirect(method = "onPlace", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) - private void redirectOnBlockAddedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1) { - fastUpdate(world_1, blockPos_1, blockState_1, null); + @Redirect(method = "onPlace", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;Z)V")) + private void redirectOnBlockAddedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1, Orientation o, boolean sup) { + fastUpdate(world_1, blockPos_1, blockState_1, o, sup); } - @Redirect(method = "onRemove", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) - private void redirectOnStateReplacedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1) { - fastUpdate(world_1, blockPos_1, blockState_1, null); + @Redirect(method = "affectNeighborsAfterRemoval", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;Z)V")) + private void redirectOnStateReplacedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1, Orientation o, boolean sup) { + fastUpdate(world_1, blockPos_1, blockState_1, o, sup); } - @Redirect(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) + @Redirect(method = "neighborChanged", at = @At(value = "INVOKE", target = + "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;Z)V" + //"Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;)V" + )) + //private void red(final RedStoneWireBlock instance, final Level level, + // final BlockPos blockPos, final BlockState blockState, final Orientation orientation) private void redirectNeighborUpdateUpdate( RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1, + Orientation o, + boolean sup, BlockState blockState_2, Level world_2, BlockPos blockPos_2, Block block_1, - BlockPos blockPos_3, - boolean boolean_1) { - fastUpdate(world_1, blockPos_1, blockState_1, blockPos_3); + Orientation o2, + boolean b + ) + { + fastUpdate(world_1, blockPos_1, blockState_1, o, sup); } } diff --git a/src/main/java/carpet/mixins/ServerChunkCacheMixin.java b/src/main/java/carpet/mixins/ServerChunkCacheMixin.java index 815ed551..ce5c0107 100644 --- a/src/main/java/carpet/mixins/ServerChunkCacheMixin.java +++ b/src/main/java/carpet/mixins/ServerChunkCacheMixin.java @@ -27,7 +27,7 @@ public abstract class ServerChunkCacheMixin @Shadow @Final private DistanceManager distanceManager; - @Redirect(method = "tickChunks", at = @At( + @Redirect(method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/level/DistanceManager;getNaturalSpawnChunkCount()I" )) @@ -54,7 +54,7 @@ public abstract class ServerChunkCacheMixin } - @Inject(method = "tickChunks", at = @At("RETURN")) + @Inject(method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", at = @At("RETURN")) private void onFinishSpawnWorldCycle(CallbackInfo ci) { LevelData levelData = this.level.getLevelData(); // levelProperies class diff --git a/src/main/java/carpet/mixins/ServerChunkCache_profilerMixin.java b/src/main/java/carpet/mixins/ServerChunkCache_profilerMixin.java index 6dabe407..23d4c904 100644 --- a/src/main/java/carpet/mixins/ServerChunkCache_profilerMixin.java +++ b/src/main/java/carpet/mixins/ServerChunkCache_profilerMixin.java @@ -19,36 +19,13 @@ public abstract class ServerChunkCache_profilerMixin CarpetProfiler.ProfilerToken currentSection; - @Inject(method = "tickChunks", at = @At("HEAD")) + @Inject(method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", at = @At("HEAD")) private void startSpawningSection(CallbackInfo ci) { currentSection = CarpetProfiler.start_section(level, "Spawning", CarpetProfiler.TYPE.GENERAL); } - @Inject(method = "tickChunks", at = @At( - value = "FIELD", - target = "net/minecraft/server/level/ServerChunkCache.level:Lnet/minecraft/server/level/ServerLevel;", - ordinal = 10 - )) - private void skipChunkTicking(CallbackInfo ci) - { - if (currentSection != null) - { - CarpetProfiler.end_current_section(currentSection); - } - } - - @Inject(method = "tickChunks", at = @At( - value = "INVOKE", - target = "net/minecraft/server/level/ServerLevel.tickChunk(Lnet/minecraft/world/level/chunk/LevelChunk;I)V", - shift = At.Shift.AFTER - )) - private void resumeSpawningSection(CallbackInfo ci) - { - currentSection = CarpetProfiler.start_section(level, "Spawning", CarpetProfiler.TYPE.GENERAL); - } - - @Inject(method = "tickChunks", at = @At("RETURN")) + @Inject(method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", at = @At("RETURN")) private void stopSpawningSection(CallbackInfo ci) { if (currentSection != null) @@ -56,18 +33,4 @@ public abstract class ServerChunkCache_profilerMixin CarpetProfiler.end_current_section(currentSection); } } - - //@Redirect(method = "tick", at = @At( - // value = "INVOKE", - // target = "Lnet/minecraft/server/level/DistanceManager;purgeStaleTickets()V" - //)) - //private void pauseTicketSystem(DistanceManager distanceManager) - //{ - // pausing expiry of tickets - // that will prevent also chunks from unloading, so require a deep frozen state - //ServerTickRateManager trm = ((MinecraftServerInterface) level.getServer()).getTickRateManager(); - //if (!trm.runsNormally() && trm.deeplyFrozen()) return; - //distanceManager.purgeStaleTickets(); - //} - } diff --git a/src/main/java/carpet/mixins/ServerGamePacketListenerImpl_scarpetEventsMixin.java b/src/main/java/carpet/mixins/ServerGamePacketListenerImpl_scarpetEventsMixin.java index 55011635..f14d6385 100644 --- a/src/main/java/carpet/mixins/ServerGamePacketListenerImpl_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/ServerGamePacketListenerImpl_scarpetEventsMixin.java @@ -1,6 +1,9 @@ package carpet.mixins; +import carpet.fakes.EntityInterface; import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraft.world.entity.player.Input; +import net.minecraft.world.item.crafting.RecipeManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -51,12 +54,19 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin { @Shadow public ServerPlayer player; - @Inject(method = "handlePlayerInput", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setPlayerInput(FFZZ)V")) + @Inject(method = "handlePlayerInput", at = @At("HEAD")) private void checkMoves(ServerboundPlayerInputPacket p, CallbackInfo ci) { - if (PLAYER_RIDES.isNeeded() && (p.getXxa() != 0.0F || p.getZza() != 0.0F || p.isJumping() || p.isShiftKeyDown())) + // todo this may not ride on the right thread moment, so needs to be checked + + Input input = p.input(); + + if (player.getVehicle() != null && !((EntityInterface)player.getVehicle()).isPermanentVehicle()) // won't since that method makes sure its not null + player.setShiftKeyDown(p.input().shift()); + + if (PLAYER_RIDES.isNeeded() && (input.jump() || input.shift() || input.forward() || input.backward() || input.left() || input.right())) { - PLAYER_RIDES.onMountControls(player, p.getXxa(), p.getZza(), p.isJumping(), p.isShiftKeyDown()); + PLAYER_RIDES.onMountControls(player, input.left() == input.right() ? 0 : (input.left() ? -1 : 1 ), input.forward() == input.backward() ? 0 : (input.forward() ? 1 : -1), input.jump(), input.shift()); } } @@ -170,24 +180,25 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin } } - @Inject(method = "handlePlayerCommand", at = @At( + @Inject(method = "handlePlayerInput", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;setShiftKeyDown(Z)V", - ordinal = 0 + target = "Lnet/minecraft/server/level/ServerPlayer;setLastClientInput(Lnet/minecraft/world/entity/player/Input;)V" )) - private void onStartSneaking(ServerboundPlayerCommandPacket clientCommandC2SPacket_1, CallbackInfo ci) + private void onStartSneaking(ServerboundPlayerInputPacket serverboundPlayerInputPacket, CallbackInfo ci) { - PLAYER_STARTS_SNEAKING.onPlayerEvent(player); - } - - @Inject(method = "handlePlayerCommand", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;setShiftKeyDown(Z)V", - ordinal = 1 - )) - private void onStopSneaking(ServerboundPlayerCommandPacket clientCommandC2SPacket_1, CallbackInfo ci) - { - PLAYER_STOPS_SNEAKING.onPlayerEvent(player); + boolean wasDown = player.isShiftKeyDown(); + boolean isDown = serverboundPlayerInputPacket.input().shift(); + if (wasDown != isDown) + { + if (isDown) + { + PLAYER_STARTS_SNEAKING.onPlayerEvent(player); + } + else + { + PLAYER_STOPS_SNEAKING.onPlayerEvent(player); + } + } } @Inject(method = "handlePlayerCommand", at = @At( @@ -246,7 +257,11 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin { if (PLAYER_CHOOSES_RECIPE.isNeeded()) { - if(PLAYER_CHOOSES_RECIPE.onRecipeSelected(player, packet.getRecipe(), packet.isShiftDown())) ci.cancel(); + RecipeManager.ServerDisplayInfo displayInfo = player.getServer().getRecipeManager().getRecipeFromDisplay(packet.recipe()); + if (displayInfo == null) { + return; + } + if(PLAYER_CHOOSES_RECIPE.onRecipeSelected(player, displayInfo.parent().id().location(), packet.useMaxItems())) ci.cancel(); } } @@ -255,7 +270,7 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin { if (PLAYER_SWITCHES_SLOT.isNeeded() && player.getServer() != null && player.getServer().isSameThread()) { - PLAYER_SWITCHES_SLOT.onSlotSwitch(player, player.getInventory().selected, packet.getSlot()); + PLAYER_SWITCHES_SLOT.onSlotSwitch(player, player.getInventory().getSelectedSlot(), packet.getSlot()); } } diff --git a/src/main/java/carpet/mixins/ServerGamePacketListenerimpl_connectionMixin.java b/src/main/java/carpet/mixins/ServerGamePacketListenerimpl_connectionMixin.java index 1811168e..386472cd 100644 --- a/src/main/java/carpet/mixins/ServerGamePacketListenerimpl_connectionMixin.java +++ b/src/main/java/carpet/mixins/ServerGamePacketListenerimpl_connectionMixin.java @@ -26,7 +26,7 @@ public class ServerGamePacketListenerimpl_connectionMixin // We should force onto the main thread here // ServerNetworkHandler.handleData can possibly mutate data that isn't // thread safe, and also allows for client commands to be executed - PacketUtils.ensureRunningOnSameThread(serverboundCustomPayloadPacket, (ServerGamePacketListener) this, player.serverLevel()); + PacketUtils.ensureRunningOnSameThread(serverboundCustomPayloadPacket, (ServerGamePacketListener) this, player.level()); ServerNetworkHandler.onClientData(player, cpp.data()); ci.cancel(); } diff --git a/src/main/java/carpet/mixins/ServerLevel_scarpetMixin.java b/src/main/java/carpet/mixins/ServerLevel_scarpetMixin.java index b9b870b3..81929187 100644 --- a/src/main/java/carpet/mixins/ServerLevel_scarpetMixin.java +++ b/src/main/java/carpet/mixins/ServerLevel_scarpetMixin.java @@ -24,6 +24,7 @@ import net.minecraft.world.level.entity.LevelEntityGetter; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WritableLevelData; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -31,7 +32,6 @@ import org.spongepowered.asm.mixin.Unique; 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; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.function.Supplier; @@ -43,18 +43,21 @@ import static carpet.script.CarpetEventServer.Event.CHUNK_UNLOADED; @Mixin(ServerLevel.class) public abstract class ServerLevel_scarpetMixin extends Level implements ServerWorldInterface { - protected ServerLevel_scarpetMixin(WritableLevelData writableLevelData, ResourceKey resourceKey, RegistryAccess registryAccess, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) + + @Shadow public abstract GameRules getGameRules(); + + protected ServerLevel_scarpetMixin(WritableLevelData writableLevelData, ResourceKey resourceKey, RegistryAccess registryAccess, Holder holder, boolean bl, boolean bl2, long l, int i) { - super(writableLevelData, resourceKey, registryAccess, holder, supplier, bl, bl2, l, i); + super(writableLevelData, resourceKey, registryAccess, holder, bl, bl2, l, i); } - @Inject(method = "tickChunk", locals = LocalCapture.CAPTURE_FAILHARD, at = @At( + @Inject(method = "tickThunder", locals = LocalCapture.CAPTURE_FAILHARD, at = @At( value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.BEFORE, ordinal = 1 )) - private void onNaturalLightinig(LevelChunk chunk, int randomTickSpeed, CallbackInfo ci, + private void onNaturalLightinig(LevelChunk chunk, CallbackInfo ci, //ChunkPos chunkPos, boolean bl, int i, int j, Profiler profiler, BlockPos blockPos, boolean bl2) ChunkPos chunkPos, boolean bl, int i, int j, ProfilerFiller profiler, BlockPos blockPos, DifficultyInstance localDifficulty, boolean bl2, LightningBolt lightningEntity) { @@ -65,8 +68,8 @@ public abstract class ServerLevel_scarpetMixin extends Level implements ServerWo return getGameRules().getBoolean(rule) ? Explosion.BlockInteraction.DESTROY_WITH_DECAY : Explosion.BlockInteraction.DESTROY; } - @Inject(method = "explode", at = @At("HEAD")) - private void handleExplosion(/*@Nullable*/ Entity entity, /*@Nullable*/ DamageSource damageSource, /*@Nullable*/ ExplosionDamageCalculator explosionBehavior, double d, double e, double f, float g, boolean bl, ExplosionInteraction explosionInteraction, ParticleOptions particleOptions, ParticleOptions particleOptions2, Holder soundEvent, CallbackInfoReturnable cir) + @Inject(method = "explode", at = @At("HEAD"), cancellable = true) + private void handleExplosion(final Entity entity, final DamageSource damageSource, final ExplosionDamageCalculator explosionDamageCalculator, final double x, final double y, final double z, final float g, final boolean bl, final ExplosionInteraction explosionInteraction, final ParticleOptions particleOptions, final ParticleOptions particleOptions2, final Holder holder, final CallbackInfo ci) { if (EXPLOSION.isNeeded()) { Explosion.BlockInteraction var10000 = switch (explosionInteraction) { @@ -74,10 +77,11 @@ public abstract class ServerLevel_scarpetMixin extends Level implements ServerWo case BLOCK -> this.getCMDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY); case MOB -> this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getCMDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.BlockInteraction.KEEP; case TNT -> this.getCMDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY); - default -> throw new IncompatibleClassChangeError(); + case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK; }; - EXPLOSION.onExplosion((ServerLevel) (Object) this, entity, null, d, e, f, g, bl, null, null, var10000); + boolean cancelled = EXPLOSION.onExplosion((ServerLevel) (Object) this, entity, null, new Vec3(x, y, z), g, bl, null, null, var10000); + if (cancelled) ci.cancel(); } } diff --git a/src/main/java/carpet/mixins/ServerLevel_tickMixin.java b/src/main/java/carpet/mixins/ServerLevel_tickMixin.java index 38a19e69..4f3a166a 100644 --- a/src/main/java/carpet/mixins/ServerLevel_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerLevel_tickMixin.java @@ -21,9 +21,9 @@ import net.minecraft.world.level.storage.WritableLevelData; @Mixin(ServerLevel.class) public abstract class ServerLevel_tickMixin extends Level implements LevelInterface { - protected ServerLevel_tickMixin(final WritableLevelData writableLevelData, final ResourceKey resourceKey, final RegistryAccess registryAccess, final Holder holder, final Supplier supplier, final boolean bl, final boolean bl2, final long l, final int i) + protected ServerLevel_tickMixin(final WritableLevelData writableLevelData, final ResourceKey resourceKey, final RegistryAccess registryAccess, final Holder holder, final boolean bl, final boolean bl2, final long l, final int i) { - super(writableLevelData, resourceKey, registryAccess, holder, supplier, bl, bl2, l, i); + super(writableLevelData, resourceKey, registryAccess, holder, bl, bl2, l, i); } private CarpetProfiler.ProfilerToken currentSection; diff --git a/src/main/java/carpet/mixins/ServerPlayerGameMode_cactusMixin.java b/src/main/java/carpet/mixins/ServerPlayerGameMode_cactusMixin.java index d4cb5763..70784fcd 100644 --- a/src/main/java/carpet/mixins/ServerPlayerGameMode_cactusMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayerGameMode_cactusMixin.java @@ -3,7 +3,7 @@ package carpet.mixins; import carpet.helpers.BlockRotator; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -19,13 +19,13 @@ public class ServerPlayerGameMode_cactusMixin @Redirect(method = "useItemOn", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;useItemOn(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/ItemInteractionResult;" + target = "Lnet/minecraft/world/level/block/state/BlockState;useItemOn(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;" )) - private ItemInteractionResult activateWithOptionalCactus(final BlockState blockState, final ItemStack itemStack, final Level world_1, final Player playerEntity_1, final InteractionHand hand_1, final BlockHitResult blockHitResult_1) + private InteractionResult activateWithOptionalCactus(final BlockState blockState, final ItemStack itemStack, final Level world_1, final Player playerEntity_1, final InteractionHand hand_1, final BlockHitResult blockHitResult_1) { boolean flipped = BlockRotator.flipBlockWithCactus(blockState, world_1, playerEntity_1, hand_1, blockHitResult_1); if (flipped) - return ItemInteractionResult.SUCCESS; + return InteractionResult.SUCCESS; return blockState.useItemOn(itemStack, world_1, playerEntity_1, hand_1, blockHitResult_1); } diff --git a/src/main/java/carpet/mixins/ServerPlayer_scarpetEventMixin.java b/src/main/java/carpet/mixins/ServerPlayer_scarpetEventMixin.java index 15531f17..372a01b0 100644 --- a/src/main/java/carpet/mixins/ServerPlayer_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayer_scarpetEventMixin.java @@ -14,7 +14,7 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -38,8 +38,8 @@ public abstract class ServerPlayer_scarpetEventMixin extends Player implements S @Unique private boolean isInvalidReference = false; - public ServerPlayer_scarpetEventMixin(Level level, BlockPos blockPos, float f, GameProfile gameProfile) { - super(level, blockPos, f, gameProfile); + public ServerPlayer_scarpetEventMixin(Level level, GameProfile gameProfile) { + super(level, gameProfile); } //@Shadow protected abstract void completeUsingItem(); @@ -83,33 +83,23 @@ public abstract class ServerPlayer_scarpetEventMixin extends Player implements S } } - @Redirect(method = "setPlayerInput", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;setShiftKeyDown(Z)V" - )) - private void setSneakingConditionally(ServerPlayer serverPlayerEntity, boolean sneaking) - { - if (!((EntityInterface)serverPlayerEntity.getVehicle()).isPermanentVehicle()) // won't since that method makes sure its not null - serverPlayerEntity.setShiftKeyDown(sneaking); - } - private Vec3 previousLocation; private ResourceKey previousDimension; - @Inject(method = "changeDimension", at = @At("HEAD")) - private void logPreviousCoordinates(DimensionTransition serverWorld, CallbackInfoReturnable cir) + @Inject(method = "teleport", at = @At("HEAD")) + private void logPreviousCoordinates(TeleportTransition serverWorld, CallbackInfoReturnable cir) { previousLocation = position(); previousDimension = level().dimension(); //dimension type } - @Inject(method = "changeDimension", at = @At("RETURN")) - private void atChangeDimension(DimensionTransition destinationP, CallbackInfoReturnable cir) + @Inject(method = "teleport", at = @At("RETURN")) + private void atChangeDimension(TeleportTransition destinationP, CallbackInfoReturnable cir) { if (PLAYER_CHANGES_DIMENSION.isNeeded()) { ServerPlayer player = (ServerPlayer) (Object)this; - DimensionTransition destinationTransition = destinationP; + TeleportTransition destinationTransition = destinationP; ServerLevel destination = destinationTransition.newLevel(); Vec3 to = null; if (!wonGame || previousDimension != Level.END || destination.dimension() != Level.OVERWORLD) diff --git a/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java b/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java index 95df92ef..b3780ec4 100644 --- a/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java @@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.commands.SetBlockCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -14,10 +15,10 @@ public class SetBlockCommand_fillUpdatesMixin { @Redirect(method = "setBlock", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighboursOnBlockSet(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V" )) - private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) + private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, BlockState block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighboursOnBlockSet(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/ShulkerBoxAccessMixin.java b/src/main/java/carpet/mixins/ShulkerBoxAccessMixin.java index a0d59a4e..7d766a47 100644 --- a/src/main/java/carpet/mixins/ShulkerBoxAccessMixin.java +++ b/src/main/java/carpet/mixins/ShulkerBoxAccessMixin.java @@ -1,11 +1,6 @@ package carpet.mixins; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.model.ShulkerModel; @Mixin(net.minecraft.client.renderer.blockentity.ShulkerBoxRenderer.class) public interface ShulkerBoxAccessMixin { - @Accessor("model") - ShulkerModel getModel(); } \ No newline at end of file diff --git a/src/main/java/carpet/mixins/StructureBlockEntity_limitsMixin.java b/src/main/java/carpet/mixins/StructureBlockEntity_limitsMixin.java index f0c758bb..cf47efba 100644 --- a/src/main/java/carpet/mixins/StructureBlockEntity_limitsMixin.java +++ b/src/main/java/carpet/mixins/StructureBlockEntity_limitsMixin.java @@ -9,6 +9,9 @@ import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyConstant; +import java.util.List; +import java.util.stream.Stream; + @Mixin(StructureBlockEntity.class) public abstract class StructureBlockEntity_limitsMixin { @@ -29,14 +32,16 @@ public abstract class StructureBlockEntity_limitsMixin } @ModifyArg( - method = "saveStructure(Z)Z", + method = "saveStructure(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Vec3i;ZLjava/lang/String;ZLjava/util/List;)Z", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate;fillFromWorld(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Vec3i;ZLnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate;fillFromWorld(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Vec3i;ZLjava/util/List;)V" ), index = 4 ) - private Block ignoredBlock(Block original) { - return CarpetSettings.structureBlockIgnoredBlock; + private static List ignoredBlock(List original) { + if (original.contains(CarpetSettings.structureBlockIgnoredBlock)) + return original; + return Stream.concat(original.stream(), Stream.of(CarpetSettings.structureBlockIgnoredBlock)).toList(); } } diff --git a/src/main/java/carpet/mixins/StructureBlockRenderer_mixin.java b/src/main/java/carpet/mixins/StructureBlockRenderer_mixin.java index 56bd7974..9fddba60 100644 --- a/src/main/java/carpet/mixins/StructureBlockRenderer_mixin.java +++ b/src/main/java/carpet/mixins/StructureBlockRenderer_mixin.java @@ -2,14 +2,14 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.StructureBlockRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityWithBoundingBoxRenderer; import net.minecraft.world.level.block.entity.StructureBlockEntity; 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(StructureBlockRenderer.class) +@Mixin(BlockEntityWithBoundingBoxRenderer.class) public abstract class StructureBlockRenderer_mixin implements BlockEntityRenderer { @Inject(method = "getViewDistance", at = @At("HEAD"), cancellable = true) diff --git a/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java b/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java index bd9cbb44..8d2938b7 100644 --- a/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java @@ -15,12 +15,12 @@ public class StructureTemplate_fillUpdatesMixin { @Redirect( method = "placeInWorld", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/ServerLevelAccessor;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/world/level/ServerLevelAccessor;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private void skipUpdateNeighbours(ServerLevelAccessor serverWorldAccess, BlockPos pos, Block block) { if (!CarpetSettings.impendingFillSkipUpdates.get()) - serverWorldAccess.blockUpdated(pos, block); + serverWorldAccess.updateNeighborsAt(pos, block); } @Redirect(method = "placeInWorld", at = @At( diff --git a/src/main/java/carpet/mixins/SummonCommand_lightningMixin.java b/src/main/java/carpet/mixins/SummonCommand_lightningMixin.java index 97c4d450..9dee70b4 100644 --- a/src/main/java/carpet/mixins/SummonCommand_lightningMixin.java +++ b/src/main/java/carpet/mixins/SummonCommand_lightningMixin.java @@ -6,6 +6,7 @@ import net.minecraft.server.commands.SummonCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.animal.horse.SkeletonHorse; @@ -24,14 +25,14 @@ public class SummonCommand_lightningMixin private static BlockPos addRiders(Entity entity) { // [CM] SummonNaturalLightning - if statement around - if (CarpetSettings.summonNaturalLightning && entity instanceof LightningBolt && !entity.getCommandSenderWorld().isClientSide) + if (CarpetSettings.summonNaturalLightning && entity instanceof LightningBolt && !entity.level().isClientSide) { - ServerLevel world = (ServerLevel) entity.getCommandSenderWorld(); + ServerLevel world = (ServerLevel) entity.level(); BlockPos at = entity.blockPosition(); DifficultyInstance localDifficulty_1 = world.getCurrentDifficultyAt(at); boolean boolean_2 = world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && world.random.nextDouble() < (double)localDifficulty_1.getEffectiveDifficulty() * 0.01D; if (boolean_2) { - SkeletonHorse skeletonHorseEntity_1 = EntityType.SKELETON_HORSE.create(world); + SkeletonHorse skeletonHorseEntity_1 = EntityType.SKELETON_HORSE.create(world, EntitySpawnReason.EVENT); skeletonHorseEntity_1.setTrap(true); skeletonHorseEntity_1.setAge(0); skeletonHorseEntity_1.setPos(entity.getX(), entity.getY(), entity.getZ()); diff --git a/src/main/java/carpet/mixins/ThreadedLevelLightEngine_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedLevelLightEngine_scarpetChunkCreationMixin.java index 9e792756..61aa4008 100644 --- a/src/main/java/carpet/mixins/ThreadedLevelLightEngine_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedLevelLightEngine_scarpetChunkCreationMixin.java @@ -61,8 +61,8 @@ public abstract class ThreadedLevelLightEngine_scarpetChunkCreationMixin extends this.addTask(pos.x, pos.z, () -> 0, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> { super.propagateLightSources(pos); - int minY = chunk.getMinBuildHeight(); - int maxY = chunk.getMaxBuildHeight(); + int minY = chunk.getMinY(); + int maxY = chunk.getMaxY(); int minX = pos.getMinBlockX(); int minZ = pos.getMinBlockZ(); BlockPos.MutableBlockPos poss = new BlockPos.MutableBlockPos(); diff --git a/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java b/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java new file mode 100644 index 00000000..08cd3d0d --- /dev/null +++ b/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.fakes.TicketsFetcherInterface; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.Ticket; +import net.minecraft.world.level.TicketStorage; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(TicketStorage.class) +public class TicketStorage_scarpetMixin implements TicketsFetcherInterface +{ + @Shadow @Final private Long2ObjectOpenHashMap> tickets; + + @Override + public Long2ObjectOpenHashMap> getTicketsByPosition() + { + return tickets; + } +} diff --git a/src/main/java/carpet/mixins/Villager_aiMixin.java b/src/main/java/carpet/mixins/Villager_aiMixin.java index 359fbcf6..2829f9ac 100644 --- a/src/main/java/carpet/mixins/Villager_aiMixin.java +++ b/src/main/java/carpet/mixins/Villager_aiMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.helpers.ParticleDisplay; import carpet.utils.Messenger; import carpet.utils.MobAI; +import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.world.entity.ai.village.poi.PoiTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -126,12 +127,12 @@ public abstract class Villager_aiMixin extends AbstractVillager if (bedPos == null || bedPos.dimension() != level().dimension()) // get Dimension { setUnhappy(); - ((ServerLevel) getCommandSenderWorld()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), getX(), getY() + getEyeHeight() + 1, getZ(), 1, 0.1, 0.1, 0.1, 0.0); + ((ServerLevel) level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), getX(), getY() + getEyeHeight() + 1, getZ(), 1, 0.1, 0.1, 0.1, 0.0); } else { - ParticleDisplay.drawParticleLine((ServerPlayer) playerEntity_1, position(), Vec3.atCenterOf(bedPos.pos()), "dust 0 0 0 1", "happy_villager", 100, 0.2); // pos+0.5v + ParticleDisplay.drawParticleLine((ServerPlayer) playerEntity_1, position(), Vec3.atCenterOf(bedPos.pos()), new DustParticleOptions(0xff000000, 1), ParticleTypes.HAPPY_VILLAGER, 100, 0.2); // pos+0.5v } } else if (itemStack_1.getItem() == Items.ROTTEN_FLESH) @@ -141,7 +142,7 @@ public abstract class Villager_aiMixin extends AbstractVillager } else if (itemStack_1.getItem() instanceof BedItem) { - List list_1 = ((ServerLevel) getCommandSenderWorld()).getPoiManager().getInRange( + List list_1 = ((ServerLevel) level()).getPoiManager().getInRange( type -> type.is(PoiTypes.HOME), blockPosition(), 48, PoiManager.Occupancy.ANY).toList(); @@ -150,16 +151,16 @@ public abstract class Villager_aiMixin extends AbstractVillager Vec3 pv = Vec3.atCenterOf(poi.getPos()); if (!poi.hasSpace()) { - ((ServerLevel) getCommandSenderWorld()).sendParticles(ParticleTypes.HAPPY_VILLAGER, + ((ServerLevel) level()).sendParticles(ParticleTypes.HAPPY_VILLAGER, pv.x, pv.y+1.5, pv.z, 50, 0.1, 0.3, 0.1, 0.0); } else if (canReachHome((Villager)(Object)this, poi.getPos(), poi)) - ((ServerLevel) getCommandSenderWorld()).sendParticles(ParticleTypes.END_ROD, + ((ServerLevel) level()).sendParticles(ParticleTypes.END_ROD, pv.x, pv.y+1, pv.z, 50, 0.1, 0.3, 0.1, 0.0); else - ((ServerLevel) getCommandSenderWorld()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), + ((ServerLevel) level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), pv.x, pv.y+1, pv.z, 1, 0.1, 0.1, 0.1, 0.0); } @@ -185,7 +186,7 @@ public abstract class Villager_aiMixin extends AbstractVillager { if (MobAI.isTracking(this, MobAI.TrackingType.IRON_GOLEM_SPAWNING)) { - ((ServerLevel) getCommandSenderWorld()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), getX(), getY()+3, getZ(), 1, 0.1, 0.1, 0.1, 0.0); + ((ServerLevel) level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK_MARKER, Blocks.BARRIER.defaultBlockState()), getX(), getY()+3, getZ(), 1, 0.1, 0.1, 0.1, 0.0); } } diff --git a/src/main/java/carpet/mixins/WoolCarpetBlock_placeMixin.java b/src/main/java/carpet/mixins/WoolCarpetBlock_placeMixin.java index e5a3239c..0cbe55bf 100644 --- a/src/main/java/carpet/mixins/WoolCarpetBlock_placeMixin.java +++ b/src/main/java/carpet/mixins/WoolCarpetBlock_placeMixin.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.utils.WoolTool; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.WoolCarpetBlock; @@ -17,12 +18,13 @@ public abstract class WoolCarpetBlock_placeMixin extends Block super(block$Settings_1); } + @Override public BlockState getStateForPlacement(BlockPlaceContext context) { BlockState state = super.getStateForPlacement(context); if (context.getPlayer() != null && !context.getLevel().isClientSide) { // getColor() - WoolTool.carpetPlacedAction(((WoolCarpetBlock)(Object)this).getColor(), context.getPlayer(), context.getClickedPos(), (ServerLevel) context.getLevel()); + WoolTool.carpetPlacedAction(((WoolCarpetBlock)(Object)this).getColor(), (ServerPlayer) context.getPlayer(), context.getClickedPos(), (ServerLevel) context.getLevel()); } return state; } diff --git a/src/main/java/carpet/network/CarpetClient.java b/src/main/java/carpet/network/CarpetClient.java index 91622bd5..a2e83ee2 100644 --- a/src/main/java/carpet/network/CarpetClient.java +++ b/src/main/java/carpet/network/CarpetClient.java @@ -106,7 +106,7 @@ public class CarpetClient ListTag outputTag = (ListTag) tag.get("output"); for (int i = 0; i < outputTag.size(); i++) { - CarpetSettings.LOG.info(" - response: " + Component.Serializer.fromJson(outputTag.getString(i), clientPlayer.registryAccess()).getString()); + CarpetSettings.LOG.info(" - response: " + outputTag.getString(i).orElseThrow()); } } } diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 9e463700..2e33e045 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -23,18 +23,18 @@ public class ClientNetworkHandler static { - dataHandlers.put(CarpetClient.HI, (p, t) -> onHi(t.getAsString())); + dataHandlers.put(CarpetClient.HI, (p, t) -> onHi(t.asString().orElseThrow())); dataHandlers.put("Rules", (p, t) -> { CompoundTag ruleset = (CompoundTag) t; - for (String ruleKey : ruleset.getAllKeys()) + for (String ruleKey : ruleset.keySet()) { CompoundTag ruleNBT = (CompoundTag) ruleset.get(ruleKey); SettingsManager manager = null; String ruleName; if (ruleNBT.contains("Manager")) { - ruleName = ruleNBT.getString("Rule"); - String managerName = ruleNBT.getString("Manager"); + ruleName = ruleNBT.getString("Rule").orElseThrow(); + String managerName = ruleNBT.getString("Manager").orElseThrow(); if (managerName.equals("carpet")) { manager = CarpetServer.settingsManager; @@ -60,7 +60,7 @@ public class ClientNetworkHandler CarpetRule rule = (manager != null) ? manager.getCarpetRule(ruleName) : null; if (rule != null) { - String value = ruleNBT.getString("Value"); + String value = ruleNBT.getString("Value").orElseThrow(); try { rule.set(null, value); @@ -116,7 +116,7 @@ public class ClientNetworkHandler public static void onServerData(CompoundTag compound, LocalPlayer player) { - for (String key : compound.getAllKeys()) + for (String key : compound.keySet()) { if (dataHandlers.containsKey(key)) { diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index 771bbaaa..ed394c99 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -31,7 +31,7 @@ public class ServerNetworkHandler private static final Set validCarpetPlayers = new HashSet<>(); private static final Map> dataHandlers = Map.of( - CarpetClient.HELLO, (p, t) -> onHello(p, t.getAsString()), + CarpetClient.HELLO, (p, t) -> onHello(p, t.asString().orElseThrow()), "clientCommand", (p, t) -> handleClientCommand(p, (CompoundTag) t) ); @@ -61,7 +61,7 @@ public class ServerNetworkHandler { CarpetSettings.LOG.warn("Player " + playerEntity.getName().getString() + " joined with another carpet version: " + version); } - DataBuilder data = DataBuilder.create(playerEntity.server); // tickrate related settings are sent on world change + DataBuilder data = DataBuilder.create(playerEntity.getServer()); // tickrate related settings are sent on world change CarpetServer.forEachManager(sm -> sm.getCarpetRules().forEach(data::withRule)); playerEntity.connection.send(data.build()); } @@ -79,10 +79,11 @@ public class ServerNetworkHandler private static void handleClientCommand(ServerPlayer player, CompoundTag commandData) { - String command = commandData.getString("command"); - String id = commandData.getString("id"); + String command = commandData.getString("command").orElseThrow(); + String id = commandData.getString("id").orElseThrow(); List output = new ArrayList<>(); Component[] error = {null}; + int[] returnValue = {0}; if (player.getServer() == null) { error[0] = Component.literal("No Server"); @@ -90,7 +91,7 @@ public class ServerNetworkHandler else { player.getServer().getCommands().performPrefixedCommand( - new SnoopyCommandSource(player, error, output), command + new SnoopyCommandSource(player, error, output, returnValue), command ); } CompoundTag result = new CompoundTag(); @@ -99,22 +100,23 @@ public class ServerNetworkHandler { result.putString("error", error[0].getContents().toString()); } + result.putInt("return", returnValue[0]); ListTag outputResult = new ListTag(); for (Component line : output) { - outputResult.add(StringTag.valueOf(Component.Serializer.toJson(line, player.registryAccess()))); + outputResult.add(StringTag.valueOf(line.getString())); } if (!output.isEmpty()) { result.put("output", outputResult); } - player.connection.send(DataBuilder.create(player.server).withCustomNbt("clientCommand", result).build()); + player.connection.send(DataBuilder.create(player.getServer()).withCustomNbt("clientCommand", result).build()); // run command plug to command output, } public static void onClientData(ServerPlayer player, CompoundTag compound) { - for (String key : compound.getAllKeys()) + for (String key : compound.keySet()) { if (dataHandlers.containsKey(key)) { @@ -135,7 +137,7 @@ public class ServerNetworkHandler } for (ServerPlayer player : remoteCarpetPlayers.keySet()) { - player.connection.send(DataBuilder.create(player.server).withRule(rule).build()); + player.connection.send(DataBuilder.create(player.getServer()).withRule(rule).build()); } } @@ -147,7 +149,7 @@ public class ServerNetworkHandler } for (ServerPlayer player : validCarpetPlayers) { - player.connection.send(DataBuilder.create(player.server).withCustomNbt(command, data).build()); + player.connection.send(DataBuilder.create(player.getServer()).withCustomNbt(command, data).build()); } } @@ -155,7 +157,7 @@ public class ServerNetworkHandler { if (isValidCarpetPlayer(player)) { - player.connection.send(DataBuilder.create(player.server).withCustomNbt(command, data).build()); + player.connection.send(DataBuilder.create(player.getServer()).withCustomNbt(command, data).build()); } } diff --git a/src/main/java/carpet/patches/EntityPlayerMPFake.java b/src/main/java/carpet/patches/EntityPlayerMPFake.java index 981e46bf..b0f979f7 100644 --- a/src/main/java/carpet/patches/EntityPlayerMPFake.java +++ b/src/main/java/carpet/patches/EntityPlayerMPFake.java @@ -8,9 +8,9 @@ import net.minecraft.network.DisconnectionDetails; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.network.protocol.PacketFlow; +import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; -import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; import net.minecraft.network.protocol.game.ServerboundClientCommandPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; @@ -31,17 +31,21 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.SkullBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.phys.Vec3; import carpet.fakes.ServerPlayerInterface; import carpet.utils.Messenger; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletableFuture; @SuppressWarnings("EntityConstructor") public class EntityPlayerMPFake extends ServerPlayer { + private static final Set spawning = new HashSet<>(); + public Runnable fixStartingPosition = () -> {}; public boolean isAShadow; @@ -70,22 +74,36 @@ public class EntityPlayerMPFake extends ServerPlayer } } GameProfile finalGP = gameprofile; - fetchGameProfile(gameprofile.getName()).thenAcceptAsync(p -> { + + // We need to mark this player as spawning so that we do not + // try to spawn another player with the name while the profile + // is being fetched - preventing multiple players spawning + String name = gameprofile.getName(); + spawning.add(name); + + fetchGameProfile(name).whenCompleteAsync((p, t) -> { + // Always remove the name, even if exception occurs + spawning.remove(name); + if (t != null) + { + return; + } + GameProfile current = finalGP; if (p.isPresent()) { current = p.get(); } EntityPlayerMPFake instance = new EntityPlayerMPFake(server, worldIn, current, ClientInformation.createDefault(), false); - instance.fixStartingPosition = () -> instance.moveTo(pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + instance.fixStartingPosition = () -> instance.snapTo(pos.x, pos.y, pos.z, (float) yaw, (float) pitch); server.getPlayerList().placeNewPlayer(new FakeClientConnection(PacketFlow.SERVERBOUND), instance, new CommonListenerCookie(current, 0, instance.clientInformation(), false)); - instance.teleportTo(worldIn, pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + instance.teleportTo(worldIn, pos.x, pos.y, pos.z, Set.of(), (float) yaw, (float) pitch, true); instance.setHealth(20.0F); instance.unsetRemoved(); instance.getAttribute(Attributes.STEP_HEIGHT).setBaseValue(0.6F); instance.gameMode.changeGameModeForPlayer(gamemode); server.getPlayerList().broadcastAll(new ClientboundRotateHeadPacket(instance, (byte) (instance.yHeadRot * 256 / 360)), dimensionId);//instance.dimension); - server.getPlayerList().broadcastAll(new ClientboundTeleportEntityPacket(instance), dimensionId);//instance.dimension); + server.getPlayerList().broadcastAll(ClientboundEntityPositionSyncPacket.of(instance), dimensionId);//instance.dimension); //instance.world.getChunkManager(). updatePosition(instance); instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f); // show all model layers (incl. capes) instance.getAbilities().flying = flying; @@ -104,7 +122,7 @@ public class EntityPlayerMPFake extends ServerPlayer { player.getServer().getPlayerList().remove(player); player.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); - ServerLevel worldIn = player.serverLevel();//.getWorld(player.dimension); + ServerLevel worldIn = player.level();//.getWorld(player.dimension); GameProfile gameprofile = player.getGameProfile(); EntityPlayerMPFake playerShadow = new EntityPlayerMPFake(server, worldIn, gameprofile, player.clientInformation(), true); playerShadow.setChatSession(player.getChatSession()); @@ -131,6 +149,11 @@ public class EntityPlayerMPFake extends ServerPlayer return new EntityPlayerMPFake(server, level, profile, cli, false); } + public static boolean isSpawningPlayer(String username) + { + return spawning.contains(username); + } + private EntityPlayerMPFake(MinecraftServer server, ServerLevel worldIn, GameProfile profile, ClientInformation cli, boolean shadow) { super(server, worldIn, profile, cli); @@ -144,7 +167,7 @@ public class EntityPlayerMPFake extends ServerPlayer } @Override - public void kill() + public void kill(ServerLevel level) { kill(Messenger.s("Killed")); } @@ -156,7 +179,7 @@ public class EntityPlayerMPFake extends ServerPlayer if (reason.getContents() instanceof TranslatableContents text && text.getKey().equals("multiplayer.disconnect.duplicate_login")) { this.connection.onDisconnect(new DisconnectionDetails(reason)); } else { - this.server.tell(new TickTask(this.server.getTickCount(), () -> { + this.getServer().schedule(new TickTask(this.getServer().getTickCount(), () -> { this.connection.onDisconnect(new DisconnectionDetails(reason)); })); } @@ -168,7 +191,7 @@ public class EntityPlayerMPFake extends ServerPlayer if (this.getServer().getTickCount() % 10 == 0) { this.connection.resetPosition(); - this.serverLevel().getChunkSource().move(this); + this.level().getChunkSource().move(this); } try { @@ -220,9 +243,9 @@ public class EntityPlayerMPFake extends ServerPlayer } @Override - public Entity changeDimension(DimensionTransition serverLevel) + public ServerPlayer teleport(TeleportTransition serverLevel) { - super.changeDimension(serverLevel); + super.teleport(serverLevel); if (wonGame) { ServerboundClientCommandPacket p = new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN); connection.handleClientCommand(p); diff --git a/src/main/java/carpet/patches/NetHandlerPlayServerFake.java b/src/main/java/carpet/patches/NetHandlerPlayServerFake.java index bfdd7f45..143e7ad0 100644 --- a/src/main/java/carpet/patches/NetHandlerPlayServerFake.java +++ b/src/main/java/carpet/patches/NetHandlerPlayServerFake.java @@ -8,7 +8,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.CommonListenerCookie; import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.entity.Relative; import java.util.Set; public class NetHandlerPlayServerFake extends ServerGamePacketListenerImpl @@ -33,12 +34,12 @@ public class NetHandlerPlayServerFake extends ServerGamePacketListenerImpl } @Override - public void teleport(double d, double e, double f, float g, float h, Set set) + public void teleport(PositionMoveRotation positionMoveRotation, Set set) { - super.teleport(d, e, f, g, h, set); - if (player.serverLevel().getPlayerByUUID(player.getUUID()) != null) { + super.teleport(positionMoveRotation, set); + if (player.level().getPlayerByUUID(player.getUUID()) != null) { resetPosition(); - player.serverLevel().getChunkSource().move(player); + player.level().getChunkSource().move(player); } } diff --git a/src/main/java/carpet/script/CarpetContext.java b/src/main/java/carpet/script/CarpetContext.java index b428c925..e1206aa2 100644 --- a/src/main/java/carpet/script/CarpetContext.java +++ b/src/main/java/carpet/script/CarpetContext.java @@ -62,7 +62,7 @@ public class CarpetContext extends Context public Registry registry(ResourceKey> resourceKey) { - return registryAccess().registryOrThrow(resourceKey); + return registryAccess().lookupOrThrow(resourceKey); } public CommandSourceStack source() diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 24de93ac..6aa33dd3 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -502,6 +502,7 @@ public class CarpetEventServer ); } }; + // fixme public static final Event CHUNK_GENERATED = new Event("chunk_generated", 2, true) { @Override @@ -513,6 +514,7 @@ public class CarpetEventServer ); } }; + // fixme public static final Event CHUNK_LOADED = new Event("chunk_loaded", 2, true) { @Override @@ -604,7 +606,7 @@ public class CarpetEventServer return handler.call(() -> Arrays.asList( new EntityValue(player), - new BlockValue(null, player.serverLevel(), blockpos), + new BlockValue(null, player.level(), blockpos), StringValue.of(facing.getName()) ), player::createCommandSourceStack); } @@ -624,7 +626,7 @@ public class CarpetEventServer new EntityValue(player), ValueConversions.of(itemstack, player.level().registryAccess()), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), - new BlockValue(null, player.serverLevel(), blockpos), + new BlockValue(null, player.level(), blockpos), StringValue.of(enumfacing.getName()), ListValue.of( new NumericValue(vec3d.x), @@ -648,7 +650,7 @@ public class CarpetEventServer return Arrays.asList( new EntityValue(player), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), - new BlockValue(null, player.serverLevel(), blockpos), + new BlockValue(null, player.level(), blockpos), StringValue.of(enumfacing.getName()), ListValue.of( new NumericValue(vec3d.x), @@ -669,7 +671,7 @@ public class CarpetEventServer new EntityValue(player), ValueConversions.of(itemstack, player.level().registryAccess()), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), - new BlockValue(null, player.serverLevel(), pos) + new BlockValue(null, player.level(), pos) ), player::createCommandSourceStack); } }; @@ -682,7 +684,7 @@ public class CarpetEventServer new EntityValue(player), ValueConversions.of(itemstack, player.level().registryAccess()), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), - new BlockValue(null, player.serverLevel(), pos) + new BlockValue(null, player.level(), pos) ), player::createCommandSourceStack); return false; } @@ -693,7 +695,7 @@ public class CarpetEventServer public boolean onBlockBroken(ServerPlayer player, BlockPos pos, BlockState previousBS) { return handler.call( - () -> Arrays.asList(new EntityValue(player), new BlockValue(previousBS, player.serverLevel(), pos)), + () -> Arrays.asList(new EntityValue(player), new BlockValue(previousBS, player.level(), pos)), player::createCommandSourceStack ); } @@ -884,7 +886,7 @@ public class CarpetEventServer new NumericValue(amount), StringValue.of(source.getMsgId()), source.getEntity() == null ? Value.NULL : new EntityValue(source.getEntity()) - ), target::createCommandSourceStack); + ), () -> target.getServer().createCommandSourceStack()); } }; public static final Event PLAYER_DEALS_DAMAGE = new Event("player_deals_damage", 3, false) @@ -894,7 +896,7 @@ public class CarpetEventServer { return handler.call(() -> Arrays.asList(new EntityValue(source.getEntity()), new NumericValue(amount), new EntityValue(target)), - () -> source.getEntity().createCommandSourceStack() + () -> source.getEntity().getServer().createCommandSourceStack() ); } }; @@ -999,7 +1001,7 @@ public class CarpetEventServer { return; } - Registry> registry = player.level().registryAccess().registryOrThrow(Registries.STAT_TYPE); + Registry> registry = player.level().registryAccess().lookupOrThrow(Registries.STAT_TYPE); handler.call(() -> Arrays.asList( new EntityValue(player), NBTSerializableValue.nameFromRegistryId(registry.getKey(stat.getType())), @@ -1051,11 +1053,11 @@ public class CarpetEventServer public static final Event EXPLOSION_OUTCOME = new Event("explosion_outcome", 8, true) { @Override - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) + public boolean onExplosion(ServerLevel world, Entity e, Supplier attacker, Vec3 center, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) { handler.call( () -> Arrays.asList( - ListValue.fromTriple(x, y, z), + ValueConversions.of(center), NumericValue.of(power), EntityValue.of(e), EntityValue.of(attacker != null ? attacker.get() : Event.getExplosionCausingEntity(e)), @@ -1067,6 +1069,7 @@ public class CarpetEventServer ListValue.wrap(affectedEntities.stream().map(EntityValue::of)) ), () -> world.getServer().createCommandSourceStack().withLevel(world) ); + return false; } }; @@ -1074,11 +1077,11 @@ public class CarpetEventServer public static final Event EXPLOSION = new Event("explosion", 6, true) { @Override - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) + public boolean onExplosion(ServerLevel world, Entity e, Supplier attacker, Vec3 center, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) { - handler.call( + return handler.call( () -> Arrays.asList( - ListValue.fromTriple(x, y, z), + ValueConversions.of(center), NumericValue.of(power), EntityValue.of(e), EntityValue.of(attacker != null ? attacker.get() : Event.getExplosionCausingEntity(e)), @@ -1306,8 +1309,9 @@ public class CarpetEventServer { } - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) + public boolean onExplosion(ServerLevel world, Entity e, Supplier attacker, Vec3 center, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) { + return false; } public void onWorldEvent(ServerLevel world, BlockPos pos) @@ -1334,7 +1338,7 @@ public class CarpetEventServer valArgs.add(EntityValue.of(player)); for (Object o : args) { - valArgs.add(ValueConversions.guess(player.serverLevel(), o)); + valArgs.add(ValueConversions.guess(player.level(), o)); } return valArgs; }, player::createCommandSourceStack diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 8535812a..9ca41018 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -12,6 +12,7 @@ import carpet.script.api.WorldAccess; import carpet.script.exception.CarpetExpressionException; import carpet.script.exception.ExpressionException; import carpet.script.external.Carpet; +import carpet.script.external.Vanilla; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.NumericValue; @@ -19,6 +20,10 @@ import carpet.script.value.Value; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import java.util.List; public class CarpetExpression { @@ -42,7 +47,7 @@ public class CarpetExpression return origin; } - public CarpetExpression(Module module, String expression, CommandSourceStack source, BlockPos origin) + public CarpetExpression(@Nullable Module module, String expression, CommandSourceStack source, BlockPos origin) { this.origin = origin; this.source = source; @@ -86,7 +91,12 @@ public class CarpetExpression Value playerValue = new EntityValue(e).bindTo("p"); context.with("p", (cc, tt) -> playerValue); } - return scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.eval(context).getBoolean()); + return scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.executeAndEvaluate( + context, + Vanilla.ScriptServer_scriptOptimizations(scriptServer.server), + host.loadOverrides, + Vanilla.ScriptServer_scriptDebugging(scriptServer.server) ? CarpetScriptServer.LOG::info : null + ).getLeft().getBoolean()); } catch (ExpressionException e) { @@ -102,7 +112,7 @@ public class CarpetExpression } } - public Value scriptRunCommand(ScriptHost host, BlockPos pos) + public Pair scriptRunCommand(ScriptHost host, BlockPos pos) { CarpetScriptServer scriptServer = (CarpetScriptServer) host.scriptServer(); if (scriptServer.stopAll) @@ -126,7 +136,48 @@ public class CarpetExpression Value playerValue = new EntityValue(e).bindTo("p"); context.with("p", (cc, tt) -> playerValue); } - return scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.eval(context)); + return scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.executeAndEvaluate( + context, + Vanilla.ScriptServer_scriptOptimizations(scriptServer.server), + host.loadOverrides, + Vanilla.ScriptServer_scriptDebugging(scriptServer.server) ? CarpetScriptServer.LOG::info : null + )); + } + catch (ExpressionException e) + { + throw new CarpetExpressionException(e.getMessage(), e.stack); + } + catch (ArithmeticException ae) + { + throw new CarpetExpressionException("Math doesn't compute... " + ae.getMessage(), null); + } + catch (StackOverflowError soe) + { + throw new CarpetExpressionException("Your thoughts are too deep", null); + } + } + + public List explain(ScriptHost host, @Nullable String code, @Nullable String method, @Nullable String style, BlockPos pos) + { + CarpetScriptServer scriptServer = (CarpetScriptServer) host.scriptServer(); + try + { + Context context = new CarpetContext(host, source, origin). + with("x", (c, t) -> new NumericValue(pos.getX() - origin.getX()).bindTo("x")). + with("y", (c, t) -> new NumericValue(pos.getY() - origin.getY()).bindTo("y")). + with("z", (c, t) -> new NumericValue(pos.getZ() - origin.getZ()).bindTo("z")); + Entity e = source.getEntity(); + if (e == null) + { + Value nullPlayer = Value.NULL.reboundedTo("p"); + context.with("p", (cc, tt) -> nullPlayer); + } + else + { + Value playerValue = new EntityValue(e).bindTo("p"); + context.with("p", (cc, tt) -> playerValue); + } + return scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.explain(context, code, method, style)); } catch (ExpressionException e) { diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 7a8d8412..c9c0314d 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -78,9 +78,9 @@ public class CarpetScriptHost extends ScriptHost public AppStoreManager.StoreNode storeSource; boolean hasCommand; - private CarpetScriptHost(CarpetScriptServer server, @Nullable Module code, boolean perUser, ScriptHost parent, Map config, Map argTypes, Predicate commandValidator, boolean isRuleApp) + private CarpetScriptHost(CarpetScriptServer server, @Nullable Module code, boolean perUser, ScriptHost parent, Map config, Map argTypes, Predicate commandValidator, boolean isRuleApp, Expression.LoadOverride override) { - super(code, server, perUser, parent); + super(code, server, perUser, parent, override); this.saveTimeout = 0; persistenceRequired = true; if (parent == null && code != null) // app, not a global host @@ -99,9 +99,9 @@ public class CarpetScriptHost extends ScriptHost storeSource = null; } - public static CarpetScriptHost create(CarpetScriptServer scriptServer, @Nullable Module module, boolean perPlayer, CommandSourceStack source, Predicate commandValidator, boolean isRuleApp, AppStoreManager.StoreNode storeSource) + public static CarpetScriptHost create(CarpetScriptServer scriptServer, @Nullable Module module, boolean perPlayer, CommandSourceStack source, Predicate commandValidator, boolean isRuleApp, AppStoreManager.StoreNode storeSource, Expression.LoadOverride override) { - CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp); + CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp, override); // parse code and convert to expression if (module != null) { @@ -111,7 +111,7 @@ public class CarpetScriptHost extends ScriptHost CarpetExpression ex = new CarpetExpression(host.main, module.code(), source, new BlockPos(0, 0, 0)); ex.getExpr().asATextSource(); host.storeSource = storeSource; - ex.scriptRunCommand(host, BlockPos.containing(source.getPosition())); + host.root = ex.scriptRunCommand(host, BlockPos.containing(source.getPosition())).getRight(); } catch (CarpetExpressionException e) { @@ -132,6 +132,10 @@ public class CarpetScriptHost extends ScriptHost host.storeSource = null; } } + else + { + host.root = Expression.ExpressionNode.ofConstant(Value.NULL, new Token()); + } return host; } @@ -253,7 +257,7 @@ public class CarpetScriptHost extends ScriptHost @Override protected ScriptHost duplicate() { - return new CarpetScriptHost(scriptServer(), main, false, this, appConfig, appArgTypes, commandValidator, isRuleApp); + return new CarpetScriptHost(scriptServer(), main, false, this, appConfig, appArgTypes, commandValidator, isRuleApp, loadOverrides); } @Override @@ -754,7 +758,7 @@ public class CarpetScriptHost extends ScriptHost } } String sign = ""; - for (Tokenizer.Token tok : Tokenizer.simplepass(arg)) + for (Token tok : Tokenizer.simple(arg).parseTokens()) { switch (tok.type) { @@ -829,7 +833,7 @@ public class CarpetScriptHost extends ScriptHost // TODO: this is just for now - invoke would be able to invoke other hosts scripts assertAppIntegrity(function.getModule()); Context context = new CarpetContext(this, source); - return scriptServer().events.handleEvents.getWhileDisabled(() -> function.getExpression().evalValue( + return scriptServer().events.handleEvents.getWhileDisabled(() -> function.getExpression().evaluatePartial( () -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv), context, Context.VOID @@ -862,7 +866,7 @@ public class CarpetScriptHost extends ScriptHost { assertAppIntegrity(function.getModule()); Context context = new CarpetContext(this, source); - return function.getExpression().evalValue( + return function.getExpression().evaluatePartial( () -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv, null), context, Context.VOID @@ -899,7 +903,7 @@ public class CarpetScriptHost extends ScriptHost { assertAppIntegrity(fun.getModule()); Context context = new CarpetContext(this, source, origin); - return fun.getExpression().evalValue( + return fun.getExpression().evaluatePartial( () -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv, null), context, Context.VOID); diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 5345ceae..6b79c557 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -121,7 +121,7 @@ public class CarpetScriptServer extends ScriptServer tickStart = 0L; stopAll = false; holyMoly = server.getCommands().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet()); - globalHost = CarpetScriptHost.create(this, null, false, null, p -> true, false, null); + globalHost = CarpetScriptHost.create(this, null, false, null, p -> true, false, null, Expression.LoadOverride.DEFAULT); } public void initializeForWorld() @@ -130,7 +130,7 @@ public class CarpetScriptServer extends ScriptServer { for (String moduleName : listAvailableModules(false)) { - addScriptHost(server.createCommandSourceStack(), moduleName, null, true, true, false, null); + addScriptHost(server.createCommandSourceStack(), moduleName, null, true, true, false, null, Expression.LoadOverride.DEFAULT); } } CarpetEventServer.Event.START.onTick(server); @@ -232,8 +232,8 @@ public class CarpetScriptServer extends ScriptServer return name == null ? globalHost : modules.get(name); } - public boolean addScriptHost(CommandSourceStack source, String name, @Nullable Predicate commandValidator, - boolean perPlayer, boolean autoload, boolean isRuleApp, AppStoreManager.StoreNode installer) + public int addScriptHost(CommandSourceStack source, String name, @Nullable Predicate commandValidator, + boolean perPlayer, boolean autoload, boolean isRuleApp, AppStoreManager.StoreNode installer, Expression.LoadOverride override) { Runnable token = Carpet.startProfilerSection("Scarpet load"); if (commandValidator == null) @@ -247,7 +247,7 @@ public class CarpetScriptServer extends ScriptServer { if (isRuleApp) { - return false; + return 0; } removeScriptHost(source, name, false, isRuleApp); reload = true; @@ -256,17 +256,17 @@ public class CarpetScriptServer extends ScriptServer if (module == null) { Carpet.Messenger_message(source, "r Failed to add " + name + " app: App not found"); - return false; + return 0; } CarpetScriptHost newHost; try { - newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer); + newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer, override); } catch (LoadException e) { Carpet.Messenger_message(source, "r Failed to add " + name + " app" + (e.getMessage() == null ? "" : ": " + e.getMessage())); - return false; + return 0; } modules.put(name, newHost); @@ -278,7 +278,7 @@ public class CarpetScriptServer extends ScriptServer if (autoload && !newHost.persistenceRequired) { removeScriptHost(source, name, false, false); - return false; + return 0; } String action = (installer != null) ? (reload ? "reinstalled" : "installed") : (reload ? "reloaded" : "loaded"); @@ -292,7 +292,7 @@ public class CarpetScriptServer extends ScriptServer if (isCommandAdded == null) // error should be dispatched { removeScriptHost(source, name, false, isRuleApp); - return false; + return 0; } else if (isCommandAdded) { @@ -330,7 +330,7 @@ public class CarpetScriptServer extends ScriptServer token.run(); long end = System.nanoTime(); LOG.info("App " + name + " loaded in " + (end - start) / 1000000 + " ms"); - return true; + return 1; } public boolean isInvalidCommandRoot(String appName) @@ -458,11 +458,11 @@ public class CarpetScriptServer extends ScriptServer } private record TransferData(boolean perUser, Predicate commandValidator, - boolean isRuleApp) + boolean isRuleApp, Expression.LoadOverride override) { private TransferData(CarpetScriptHost host) { - this(host.perUser, host.commandValidator, host.isRuleApp); + this(host.perUser, host.commandValidator, host.isRuleApp, host.loadOverrides); } } @@ -473,7 +473,7 @@ public class CarpetScriptServer extends ScriptServer apps.keySet().forEach(s -> removeScriptHost(server.createCommandSourceStack(), s, false, false)); CarpetEventServer.Event.clearAllBuiltinEvents(); init(); - apps.forEach((s, data) -> addScriptHost(server.createCommandSourceStack(), s, data.commandValidator, data.perUser, false, data.isRuleApp, null)); + apps.forEach((s, data) -> addScriptHost(server.createCommandSourceStack(), s, data.commandValidator, data.perUser, false, data.isRuleApp, null, data.override)); } public void reAddCommands() diff --git a/src/main/java/carpet/script/EntityEventsGroup.java b/src/main/java/carpet/script/EntityEventsGroup.java index 7f59f210..6eaf9fc5 100644 --- a/src/main/java/carpet/script/EntityEventsGroup.java +++ b/src/main/java/carpet/script/EntityEventsGroup.java @@ -16,8 +16,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; public class EntityEventsGroup @@ -167,7 +170,7 @@ public class EntityEventsGroup public CarpetEventServer.CallbackResult call(CarpetEventServer.Callback tickCall, Entity entity, Object... args) { assert args.length == argcount - 1; - return tickCall.execute(entity.createCommandSourceStack(), makeArgs(entity, args)); + return tickCall.execute((entity instanceof ServerPlayer player ? player.createCommandSourceStack() : entity.getServer().createCommandSourceStack()), makeArgs(entity, args)); } protected List makeArgs(Entity entity, Object... args) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 7f427a40..3105d295 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -19,7 +19,6 @@ import carpet.script.exception.IntegrityException; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ResolvedException; import carpet.script.exception.ReturnStatement; -import carpet.script.external.Vanilla; import carpet.script.language.Arithmetic; import carpet.script.language.ControlFlow; import carpet.script.language.DataStructures; @@ -36,7 +35,10 @@ import it.unimi.dsi.fastutil.Stack; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import javax.annotation.Nullable; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; @@ -45,6 +47,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.DoubleBinaryOperator; import java.util.function.DoubleToLongFunction; import java.util.function.DoubleUnaryOperator; @@ -68,6 +71,7 @@ public class Expression private boolean allowNewlineSubstitutions = true; private boolean allowComments = false; + @Nullable public Module module = null; public String getModuleName() @@ -81,7 +85,7 @@ public class Expression allowComments = true; } - public void asAModule(Module mi) + public void asAModule(@Nullable Module mi) { module = mi; } @@ -89,8 +93,12 @@ public class Expression /** * Cached AST (Abstract Syntax Tree) (root) of the expression */ + @Nullable private LazyValue ast = null; + @Nullable + private ExpressionNode root = null; + /** * script specific operatos and built-in functions */ @@ -109,12 +117,20 @@ public class Expression } private final Map functionalEquivalence = new Object2ObjectOpenHashMap<>(); + private final Map functionalAliases = new Object2ObjectOpenHashMap<>(); - public void addFunctionalEquivalence(String operator, String function) + private void addFunctionalEquivalence(String operator, String function) { assert operators.containsKey(operator); assert functions.containsKey(function); functionalEquivalence.put(operator, function); + functionalAliases.put(operator, function); + } + private void addFunctionalAlias(String operator, String function) + { + assert operators.containsKey(operator); + assert functions.containsKey(function); + functionalAliases.put(operator, function); } private final Map constants = Map.of( @@ -130,7 +146,7 @@ public class Expression return constants.get(surface); } - public List getExpressionSnippet(Tokenizer.Token token) + public List getExpressionSnippet(Token token) { String code = this.getCodeString(); List output = new ArrayList<>(getExpressionSnippetLeftContext(token, code, 1)); @@ -140,7 +156,7 @@ public class Expression return output; } - private static List getExpressionSnippetLeftContext(Tokenizer.Token token, String expr, int contextsize) + private static List getExpressionSnippetLeftContext(Token token, String expr, int contextsize) { List output = new ArrayList<>(); String[] lines = expr.split("\n"); @@ -156,7 +172,7 @@ public class Expression return output; } - private static List getExpressionSnippetContext(Tokenizer.Token token, String expr) + private static List getExpressionSnippetContext(Token token, String expr) { List output = new ArrayList<>(); String[] lines = expr.split("\n"); @@ -173,7 +189,7 @@ public class Expression return output; } - private static List getExpressionSnippetRightContext(Tokenizer.Token token, String expr, int contextsize) + private static List getExpressionSnippetRightContext(Token token, String expr, int contextsize) { List output = new ArrayList<>(); String[] lines = expr.split("\n"); @@ -189,7 +205,7 @@ public class Expression } - public void addLazyUnaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function staticTyper, + public void addLazyUnaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function staticTyper, TriFunction lazyfun) { operators.put(surface + "u", new AbstractLazyOperator(precedence, leftAssoc) @@ -213,7 +229,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v, LazyValue v2) + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, LazyValue v, LazyValue v2) { try { @@ -225,11 +241,46 @@ public class Expression } } }); + + functions.put(function, new AbstractLazyFunction(1, function) + { + @Override + public boolean pure() + { + return pure; + } + + @Override + public boolean transitive() + { + return false; + } + + @Override + public Context.Type staticType(Context.Type outerType) + { + return staticTyper.apply(outerType); + } + + @Override + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List v) + { + try + { + return lazyfun.apply(c, t, v.get(0)); + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + addFunctionalAlias(surface + "u", function); } - public void addLazyBinaryOperatorWithDelegation(String surface, int precedence, boolean leftAssoc, boolean pure, - SexFunction lazyfun) + public void addLazyBinaryOperatorWithDelegation(String surface, String function, int precedence, boolean leftAssoc, boolean pure, + SexFunction lazyfun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) { @@ -246,7 +297,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, LazyValue v1, LazyValue v2) { try { @@ -258,6 +309,36 @@ public class Expression } } }); + + functions.put(function, new AbstractLazyFunction(2, function) + { + @Override + public boolean pure() + { + return pure; + } + + @Override + public boolean transitive() + { + return false; + } + + @Override + public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, List v) + { + try + { + return lazyfun.apply(c, type, e, t, v.get(0), v.get(1)); + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + + addFunctionalAlias(surface, function); } public void addCustomFunction(String name, ILazyFunction fun) @@ -266,7 +347,7 @@ public class Expression } public void addLazyFunctionWithDelegation(String name, int numpar, boolean pure, boolean transitive, - QuinnFunction, LazyValue> lazyfun) + QuinnFunction, LazyValue> lazyfun) { functions.put(name, new AbstractLazyFunction(numpar, name) { @@ -283,7 +364,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lv) + public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, List lv) { ILazyFunction.checkInterrupts(); try @@ -299,7 +380,7 @@ public class Expression } public void addFunctionWithDelegation(String name, int numpar, boolean pure, boolean transitive, - QuinnFunction, Value> fun) + QuinnFunction, Value> fun) { functions.put(name, new AbstractLazyFunction(numpar, name) { @@ -316,7 +397,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lv) + public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, List lv) { try { @@ -331,7 +412,84 @@ public class Expression }); } - public void addLazyBinaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function typer, + public void addLazyBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function typer, + QuadFunction lazyfun, TriFunction, LazyValue> multiFun) + { + operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) + { + + @Override + public boolean pure() + { + return pure; + } + + @Override + public boolean transitive() + { + return false; + } + + @Override + public Context.Type staticType(Context.Type outerType) + { + return typer.apply(outerType); + } + + @Override + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, LazyValue v1, LazyValue v2) + { + ILazyFunction.checkInterrupts(); + try + { + return lazyfun.apply(c, t, v1, v2); + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + + functions.put(function, new AbstractLazyFunction(-1, function) + { + @Override + public boolean pure() + { + return true; + } + + @Override + public boolean transitive() + { + return false; + } + + @Override + public Context.Type staticType(Context.Type outerType) + { + return typer.apply(outerType); + } + + @Override + public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List lazyParams) + { + ILazyFunction.checkInterrupts(); + try + { + return multiFun.apply(c, i, lazyParams); + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + + addFunctionalEquivalence(surface, function); + } + + public void addLazyBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function typer, QuadFunction lazyfun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) @@ -356,7 +514,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, LazyValue v1, LazyValue v2) { ILazyFunction.checkInterrupts(); try @@ -369,9 +527,45 @@ public class Expression } } }); + + functions.put(function, new AbstractLazyFunction(2, function) + { + @Override + public boolean pure() + { + return pure; + } + + @Override + public boolean transitive() + { + return false; + } + + @Override + public Context.Type staticType(Context.Type outerType) + { + return typer.apply(outerType); + } + + @Override + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List v) + { + try + { + return lazyfun.apply(c, t, v.get(0), v.get(1)); + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + + addFunctionalAlias(surface, function); } - public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc, boolean pure, boolean transitive, + public void addBinaryContextOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, boolean transitive, QuadFunction fun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) @@ -389,7 +583,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, LazyValue v1, LazyValue v2) { try { @@ -402,9 +596,40 @@ public class Expression } } }); + + functions.put(function, new AbstractLazyFunction(2, function) + { + @Override + public boolean pure() + { + return pure; + } + + @Override + public boolean transitive() + { + return transitive; + } + + @Override + public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List v) + { + try + { + Value ret = fun.apply(c, t, v.get(0).evalValue(c, Context.NONE), v.get(1).evalValue(c, Context.NONE)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + + addFunctionalAlias(surface, function); } - public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Tokenizer.Token token) + public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Token token) { if (exc instanceof ExitStatement) { @@ -431,7 +656,7 @@ public class Expression return new ExpressionException(c, e, token, "Internal error (please report this issue to Carpet) while evaluating: " + exc); } - public void addUnaryOperator(String surface, boolean leftAssoc, Function fun) + public void addUnaryOperator(String surface, String function, boolean leftAssoc, Function fun) { operators.put(surface + "u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc) { @@ -441,18 +666,57 @@ public class Expression return fun.apply(v1); } }); + functions.put(function, new AbstractFunction(1, function) + { + @Override + public Value eval(List v1) + { + return fun.apply(v1.get(0)); + } + }); + addFunctionalAlias(surface + "u", function); } - public void addBinaryOperator(String surface, int precedence, boolean leftAssoc, BiFunction fun) + public void addBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, BiFunction fun, Function, Value> multiFun) { operators.put(surface, new AbstractOperator(precedence, leftAssoc) { @Override - public Value eval(Value v1, Value v2) - { + public Value eval(Value v1, Value v2) { return fun.apply(v1, v2); } }); + + functions.put(function, new AbstractFunction(-1, function) + { + @Override + public Value eval(List parameters) + { + return multiFun.apply(parameters); + } + }); + addFunctionalEquivalence(surface, function); + } + + public void addBinaryOperator(String surface, String name, int precedence, boolean leftAssoc, BiFunction fun) + { + operators.put(surface, new AbstractOperator(precedence, leftAssoc) + { + @Override + public Value eval(Value v1, Value v2) { + return fun.apply(v1, v2); + } + }); + functions.put(name, new AbstractFunction(2, name) + { + @Override + public Value eval(List parameters) + { + return fun.apply(parameters.get(0), parameters.get(1)); + } + }); + + addFunctionalAlias(surface, name); } @@ -568,7 +832,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List lazyParams) { ILazyFunction.checkInterrupts(); if (numParams >= 0 && lazyParams.size() != numParams) @@ -606,45 +870,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) - { - ILazyFunction.checkInterrupts(); - try - { - return fun.apply(c, i, lazyParams); - } - catch (RuntimeException exc) - { - throw handleCodeException(c, exc, e, t); - } - } - }); - } - - public void addPureLazyFunction(String name, int num_params, Function typer, TriFunction, LazyValue> fun) - { - functions.put(name, new AbstractLazyFunction(num_params, name) - { - @Override - public boolean pure() - { - return true; - } - - @Override - public boolean transitive() - { - return false; - } - - @Override - public Context.Type staticType(Context.Type outerType) - { - return typer.apply(outerType); - } - - @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List lazyParams) { ILazyFunction.checkInterrupts(); try @@ -676,7 +902,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List lazyParams) { ILazyFunction.checkInterrupts(); try @@ -715,7 +941,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List lazyParams) { try { @@ -730,7 +956,7 @@ public class Expression }); } - public FunctionValue createUserDefinedFunction(Context context, String name, Expression expr, Tokenizer.Token token, List arguments, String varArgs, List outers, LazyValue code) + public FunctionValue createUserDefinedFunction(Context context, String name, Expression expr, Token token, List arguments, String varArgs, List outers, LazyValue code) { if (functions.containsKey(name)) { @@ -799,7 +1025,7 @@ public class Expression } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression expr, Tokenizer.Token token, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type type, Expression expr, Token token, List lazyParams) { c.host.issueDeprecation(copy + "(...)"); return originalFunction.lazyEval(c, type, expr, token, lazyParams); @@ -848,7 +1074,7 @@ public class Expression */ public Expression(String expression) { - this.expression = expression.stripTrailing().replaceAll("\\r\\n?", "\n").replaceAll("\\t", " "); + this.expression = stripExpression(expression); Operators.apply(this); ControlFlow.apply(this); Functions.apply(this); @@ -857,21 +1083,24 @@ public class Expression Threading.apply(this); Loops.apply(this); DataStructures.apply(this); + for(String op : operators.keySet()) { + assert functionalAliases.containsKey(op) : "Missing function for operator " + op; + } + } + + private String stripExpression(String expression) + { + return expression.stripTrailing().replaceAll("\\r\\n?", "\n").replaceAll("\\t", " "); } - private List shuntingYard(Context c) + private List shuntingYard(Context c, List tokens) { - List outputQueue = new ArrayList<>(); - Stack stack = new ObjectArrayList<>(); - - Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions); - // stripping lousy but acceptable semicolons - List cleanedTokens = tokenizer.postProcess(); - - Tokenizer.Token lastFunction = null; - Tokenizer.Token previousToken = null; - for (Tokenizer.Token token : cleanedTokens) + List outputQueue = new ArrayList<>(); + Stack stack = new ObjectArrayList<>(); + Token lastFunction = null; + Token previousToken = null; + for (Token token : tokens) { switch (token.type) { @@ -880,9 +1109,9 @@ public class Expression //break; case LITERAL, HEX_LITERAL: if (previousToken != null && ( - previousToken.type == Tokenizer.Token.TokenType.LITERAL || - previousToken.type == Tokenizer.Token.TokenType.HEX_LITERAL || - previousToken.type == Tokenizer.Token.TokenType.STRINGPARAM)) + previousToken.type == Token.TokenType.LITERAL || + previousToken.type == Token.TokenType.HEX_LITERAL || + previousToken.type == Token.TokenType.STRINGPARAM)) { throw new ExpressionException(c, this, token, "Missing operator"); } @@ -896,11 +1125,11 @@ public class Expression lastFunction = token; break; case COMMA: - if (previousToken != null && previousToken.type == Tokenizer.Token.TokenType.OPERATOR) + if (previousToken != null && previousToken.type == Token.TokenType.OPERATOR) { throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator "); } - while (!stack.isEmpty() && stack.top().type != Tokenizer.Token.TokenType.OPEN_PAREN) + while (!stack.isEmpty() && stack.top().type != Token.TokenType.OPEN_PAREN) { outputQueue.add(stack.pop()); } @@ -919,7 +1148,7 @@ public class Expression case OPERATOR: { if (previousToken != null - && (previousToken.type == Tokenizer.Token.TokenType.COMMA || previousToken.type == Tokenizer.Token.TokenType.OPEN_PAREN)) + && (previousToken.type == Token.TokenType.COMMA || previousToken.type == Token.TokenType.OPEN_PAREN)) { throw new ExpressionException(c, this, token, "Missing parameter(s) for operator '" + token + "'"); } @@ -935,8 +1164,8 @@ public class Expression } case UNARY_OPERATOR: { - if (previousToken != null && previousToken.type != Tokenizer.Token.TokenType.OPERATOR - && previousToken.type != Tokenizer.Token.TokenType.COMMA && previousToken.type != Tokenizer.Token.TokenType.OPEN_PAREN) + if (previousToken != null && previousToken.type != Token.TokenType.OPERATOR + && previousToken.type != Token.TokenType.COMMA && previousToken.type != Token.TokenType.OPEN_PAREN) { throw new ExpressionException(c, this, token, "Invalid position for unary operator " + token); } @@ -952,18 +1181,18 @@ public class Expression } case OPEN_PAREN: // removed implicit multiplication in this missing code block - if (previousToken != null && previousToken.type == Tokenizer.Token.TokenType.FUNCTION) + if (previousToken != null && previousToken.type == Token.TokenType.FUNCTION) { outputQueue.add(token); } stack.push(token); break; case CLOSE_PAREN: - if (previousToken != null && previousToken.type == Tokenizer.Token.TokenType.OPERATOR) + if (previousToken != null && previousToken.type == Token.TokenType.OPERATOR) { throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator " + previousToken); } - while (!stack.isEmpty() && stack.top().type != Tokenizer.Token.TokenType.OPEN_PAREN) + while (!stack.isEmpty() && stack.top().type != Token.TokenType.OPEN_PAREN) { outputQueue.add(stack.pop()); } @@ -972,7 +1201,7 @@ public class Expression throw new ExpressionException(c, this, "Mismatched parentheses"); } stack.pop(); - if (!stack.isEmpty() && stack.top().type == Tokenizer.Token.TokenType.FUNCTION) + if (!stack.isEmpty() && stack.top().type == Token.TokenType.FUNCTION) { outputQueue.add(stack.pop()); } @@ -986,7 +1215,7 @@ public class Expression } break; } - if (token.type != Tokenizer.Token.TokenType.MARKER) + if (token.type != Token.TokenType.MARKER) { previousToken = token; } @@ -994,8 +1223,8 @@ public class Expression while (!stack.isEmpty()) { - Tokenizer.Token element = stack.pop(); - if (element.type == Tokenizer.Token.TokenType.OPEN_PAREN || element.type == Tokenizer.Token.TokenType.CLOSE_PAREN) + Token element = stack.pop(); + if (element.type == Token.TokenType.OPEN_PAREN || element.type == Token.TokenType.CLOSE_PAREN) { throw new ExpressionException(c, this, element, "Mismatched parentheses"); } @@ -1004,12 +1233,12 @@ public class Expression return outputQueue; } - private void shuntOperators(List outputQueue, Stack stack, ILazyOperator o1) + private void shuntOperators(List outputQueue, Stack stack, ILazyOperator o1) { - Tokenizer.Token nextToken = stack.isEmpty() ? null : stack.top(); + Token nextToken = stack.isEmpty() ? null : stack.top(); while (nextToken != null - && (nextToken.type == Tokenizer.Token.TokenType.OPERATOR - || nextToken.type == Tokenizer.Token.TokenType.UNARY_OPERATOR) + && (nextToken.type == Token.TokenType.OPERATOR + || nextToken.type == Token.TokenType.UNARY_OPERATOR) && ((o1.isLeftAssoc() && o1.getPrecedence() <= operators.get(nextToken.surface).getPrecedence()) || (o1.getPrecedence() < operators.get(nextToken.surface).getPrecedence()))) { @@ -1018,16 +1247,32 @@ public class Expression } } - public Value eval(Context c) + public enum LoadOverride { + DEFAULT("clean"), CANONICAL("canonical"), OPTIMIZED("optimized"), FUNCTIONAL("functional"), FUNCTIONAL_OPTIMIZED("functional_optimized"); + public String equivalent; + LoadOverride(String equivalent) { + this.equivalent = equivalent; + } + } + + public Pair executeAndEvaluate(Context c, boolean optimize, LoadOverride override, @Nullable Consumer logger) { if (ast == null) { - ast = getAST(c); + boolean functions = false; + if (override != LoadOverride.DEFAULT) { + optimize = override == LoadOverride.OPTIMIZED || override == LoadOverride.FUNCTIONAL_OPTIMIZED; + functions = override == LoadOverride.FUNCTIONAL || override == LoadOverride.FUNCTIONAL_OPTIMIZED; + } + + Pair ret = getAST(c, optimize, functions, logger); + ast = ret.getRight(); + root = ret.getLeft(); } - return evalValue(() -> ast, c, Context.Type.NONE); + return Pair.of(evaluatePartial(() -> ast, c, Context.Type.NONE), root); } - public Value evalValue(Supplier exprProvider, Context c, Context.Type expectedType) + public Value evaluatePartial(Supplier exprProvider, Context c, Context.Type expectedType) { try { @@ -1059,15 +1304,15 @@ public class Expression { public LazyValue op; public List args; - public Tokenizer.Token token; - public List range; + public Token token; + public List range; /** * The Value representation of the left parenthesis, used for parsing * varying numbers of function parameters. */ - public static final ExpressionNode PARAMS_START = new ExpressionNode(null, null, Tokenizer.Token.NONE); + public static final ExpressionNode PARAMS_START = new ExpressionNode(null, null, Token.NONE); - public ExpressionNode(LazyValue op, List args, Tokenizer.Token token) + public ExpressionNode(LazyValue op, List args, Token token) { this.op = op; this.args = args; @@ -1076,40 +1321,125 @@ public class Expression range.add(token); } - public static ExpressionNode ofConstant(Value val, Tokenizer.Token token) + public static ExpressionNode ofConstant(Value val, Token token) { return new ExpressionNode(new LazyValue.Constant(val), Collections.emptyList(), token); } + + public List tokensRecursive(Expression expression, List reference, Map, List> referencePointers){ + List tokens = new ArrayList<>(); + switch (token.type) { + case FUNCTION -> { + tokens.add(token); + tokens.add(findToken(token, Token.TokenType.OPEN_PAREN, "(", reference, referencePointers)); + if (!args.isEmpty()) { + for (ExpressionNode arg : args) { + List argTokens = arg.tokensRecursive(expression, reference, referencePointers); + tokens.addAll(argTokens); + tokens.add(findToken(argTokens.getLast(), Token.TokenType.COMMA, ",", reference, referencePointers).disguiseAs(", ", null)); + } + tokens.removeLast(); + } + tokens.add(findToken(tokens.getLast(), Token.TokenType.CLOSE_PAREN, ")", reference, referencePointers)); + } + case OPERATOR -> { + tokens.addAll(createOperatorArgumentTokens(expression, args.get(0), reference, referencePointers)); + tokens.add(token.disguiseAs(token.surface.equals(";") ? (token.surface+" ") : (" "+token.surface+" "), null)); + tokens.addAll(createOperatorArgumentTokens(expression, args.get(1), reference, referencePointers)); + } + case UNARY_OPERATOR -> { + tokens.add(token.disguiseAs(" "+StringUtils.chop(token.surface),null)); + tokens.addAll(createOperatorArgumentTokens(expression, args.get(0), reference, referencePointers)); + } + case VARIABLE, LITERAL, HEX_LITERAL, CONSTANT -> tokens.add(token); + case STRINGPARAM -> tokens.add(token.disguiseAs("'"+token.surface+"'", null)); + // these should be parsed out already, but .... + //case LITERAL, STRINGPARAM, HEX_LITERAL, OPEN_PAREN, CLOSE_PAREN, MARKER -> tokens.add(token.morphedInto(token.type, token.surface+"?")); + // CONSTANT ?? + default -> tokens.add(token.disguiseAs("?"+token.surface+"?", null)); + } + return tokens; + } + + public Token findToken(Token previous, Token.TokenType type, String expectedSurface, List reference, Map, List> referencePointers) + { + List indices = referencePointers.get(Pair.of(previous.lineno, previous.linepos)); + if (indices == null) + { + return previous.morphedInto(type, expectedSurface); + } + for (int index : indices) + { + if (index + 1 == reference.size()) + { + continue; + } + Token token = reference.get(index + 1); + if (token.type == type) + { + return token.morphedInto(type, expectedSurface); + } + } + return previous.morphedInto(type, expectedSurface); + } + + public List createOperatorArgumentTokens(Expression expression, ExpressionNode operand, List reference, Map, List> referencePointers) { + boolean needsBrackets = false; + var operators = expression.operators; + if (operators.containsKey(operand.token.surface) && operators.containsKey(token.surface)) { + if (operators.get(operand.token.surface).getPrecedence() < operators.get(token.surface).getPrecedence()) { + needsBrackets = true; + } + } + List argumentTokens = operand.tokensRecursive(expression, reference, referencePointers); + if (!needsBrackets) { + return argumentTokens; + } + List bracketed = new ArrayList<>(); + bracketed.add(findToken(argumentTokens.getFirst(), Token.TokenType.OPEN_PAREN, "(", reference, referencePointers)); + bracketed.get(0).swapPlace(argumentTokens.getFirst()); + bracketed.addAll(argumentTokens); + bracketed.add(findToken(argumentTokens.getLast(), Token.TokenType.CLOSE_PAREN, ")", reference, referencePointers)); + return bracketed; + } } - private ExpressionNode RPNToParseTree(List tokens, Context context) + private ExpressionNode RPNToParseTree(List tokens, Context context) { Stack nodeStack = new ObjectArrayList<>(); - for (Tokenizer.Token token : tokens) + for (Token token : tokens) { switch (token.type) { case UNARY_OPERATOR -> { ExpressionNode node = nodeStack.pop(); LazyValue result = (c, t) -> operators.get(token.surface).lazyEval(c, t, this, token, node.op, null).evalValue(c, t); - nodeStack.push(new ExpressionNode(result, Collections.singletonList(node), token)); + ExpressionNode newNode = new ExpressionNode(result, Collections.singletonList(node), token); + token.node = newNode; + nodeStack.push(newNode); } case OPERATOR -> { ExpressionNode v1 = nodeStack.pop(); ExpressionNode v2 = nodeStack.pop(); LazyValue result = (c, t) -> operators.get(token.surface).lazyEval(c, t, this, token, v2.op, v1.op).evalValue(c, t); - nodeStack.push(new ExpressionNode(result, List.of(v2, v1), token)); + ExpressionNode newNode = new ExpressionNode(result, List.of(v2, v1), token); + token.node = newNode; + nodeStack.push(newNode); } case VARIABLE -> { Value constant = getConstantFor(token.surface); if (constant != null) { - token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); - nodeStack.push(new ExpressionNode(LazyValue.ofConstant(constant), Collections.emptyList(), token)); + token.morph(Token.TokenType.CONSTANT, token.surface); + ExpressionNode newNode = new ExpressionNode(LazyValue.ofConstant(constant), Collections.emptyList(), token); + token.node = newNode; + nodeStack.push(newNode); } else { - nodeStack.push(new ExpressionNode(((c, t) -> getOrSetAnyVariable(c, token.surface).evalValue(c, t)), Collections.emptyList(), token)); + ExpressionNode newNode = new ExpressionNode(((c, t) -> getOrSetAnyVariable(c, token.surface).evalValue(c, t)), Collections.emptyList(), token); + token.node = newNode; + nodeStack.push(newNode); } } case FUNCTION -> { @@ -1135,8 +1465,8 @@ public class Expression } if (!isKnown) { - p.add(ExpressionNode.ofConstant(new StringValue(name), token.morphedInto(Tokenizer.Token.TokenType.STRINGPARAM, token.surface))); - token.morph(Tokenizer.Token.TokenType.FUNCTION, "call"); + p.add(ExpressionNode.ofConstant(new StringValue(name), token.morphedInto(Token.TokenType.STRINGPARAM, token.surface))); + token.morph(Token.TokenType.FUNCTION, "call"); } Collections.reverse(p); if (nodeStack.top() == ExpressionNode.PARAMS_START) @@ -1144,12 +1474,17 @@ public class Expression nodeStack.pop(); } List params = p.stream().map(n -> n.op).collect(Collectors.toList()); - nodeStack.push(new ExpressionNode( + ExpressionNode newNode = new ExpressionNode( (c, t) -> f.lazyEval(c, t, this, token, params).evalValue(c, t), p, token - )); + ); + token.node = newNode; + nodeStack.push(newNode); + } + case OPEN_PAREN -> { + token.node = ExpressionNode.PARAMS_START; + nodeStack.push(ExpressionNode.PARAMS_START); } - case OPEN_PAREN -> nodeStack.push(ExpressionNode.PARAMS_START); case LITERAL -> { Value number; try @@ -1160,12 +1495,16 @@ public class Expression { throw new ExpressionException(context, this, token, "Not a number"); } - token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); - nodeStack.push(ExpressionNode.ofConstant(number, token)); + //token.morph(Token.TokenType.CONSTANT, token.surface); + ExpressionNode newNode = ExpressionNode.ofConstant(number, token); + token.node = newNode; + nodeStack.push(newNode); } case STRINGPARAM -> { - token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); - nodeStack.push(ExpressionNode.ofConstant(new StringValue(token.surface), token)); + //token.morph(Token.TokenType.CONSTANT, token.surface); + ExpressionNode newNode = ExpressionNode.ofConstant(new StringValue(token.surface), token); + token.node = newNode; + nodeStack.push(newNode); } case HEX_LITERAL -> { Value hexNumber; @@ -1177,8 +1516,10 @@ public class Expression { throw new ExpressionException(context, this, token, "Not a number"); } - token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); - nodeStack.push(ExpressionNode.ofConstant(hexNumber, token)); + //token.morph(Token.TokenType.CONSTANT, token.surface); + ExpressionNode newNode = ExpressionNode.ofConstant(hexNumber, token); + token.node = newNode; + nodeStack.push(newNode); } default -> throw new ExpressionException(context, this, token, "Unexpected token '" + token.surface + "'"); } @@ -1186,21 +1527,34 @@ public class Expression return nodeStack.pop(); } - private LazyValue getAST(Context context) + private Pair getAST(Context context, boolean optimize, boolean functional, @Nullable Consumer logger) { - List rpn = shuntingYard(context); + Tokenizer tokenizer = new Tokenizer(context, this, expression, allowComments, allowNewlineSubstitutions); + // stripping lousy but acceptable semicolons + List cleanedTokens = Tokenizer.postProcess(tokenizer.parseTokens()); + + List rpn = shuntingYard(context, cleanedTokens); validate(context, rpn); ExpressionNode root = RPNToParseTree(rpn, context); - if (!Vanilla.ScriptServer_scriptOptimizations(((CarpetScriptServer)context.scriptServer()).server)) + if (!optimize && !functional) { - return root.op; + return Pair.of(root, root.op); } Context optimizeOnlyContext = new Context.ContextForErrorReporting(context); - boolean scriptsDebugging = Vanilla.ScriptServer_scriptDebugging(((CarpetScriptServer)context.scriptServer()).server); - if (scriptsDebugging) + // flipping to full functional representation makes it little underperforming, might be related + // to the fact that operators are running from a bigger pool or function execution is slower + optimizeTree(root, optimizeOnlyContext, logger, optimize, functional); + if (!optimize) { + return Pair.of(root, root.op); + } + return Pair.of(root, extractOp(optimizeOnlyContext, root, Context.Type.NONE)); + } + + private void optimizeTree(ExpressionNode root, Context optimizeOnlyContext, @Nullable Consumer logger, boolean optimize, boolean toFunctional) { + if (logger != null) { - CarpetScriptServer.LOG.info("Input code size for " + getModuleName() + ": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep"); + logger.accept("Input code size for " + getModuleName() + ": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep"); } // Defined out here to not need to conditionally assign them with debugging disabled @@ -1213,42 +1567,116 @@ public class Expression changed = false; while (true) { - if (scriptsDebugging) + if (logger != null) { prevTreeSize = treeSize(root); prevTreeDepth = treeDepth(root); } - boolean optimized = compactTree(root, Context.Type.NONE, 0, scriptsDebugging); + boolean optimized = compactTree(root, Context.Type.NONE, 0, logger, optimize, toFunctional); if (!optimized) { break; } changed = true; - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info("Compacted from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); + logger.accept("Compacted from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); } } - while (true) + while (optimize) { - if (scriptsDebugging) + if (logger != null) { prevTreeSize = treeSize(root); prevTreeDepth = treeDepth(root); } - boolean optimized = optimizeTree(optimizeOnlyContext, root, Context.Type.NONE, 0, scriptsDebugging); + boolean optimized = optimizeConstantsAndPureFunctions(optimizeOnlyContext, root, Context.Type.NONE, 0, logger); if (!optimized) { break; } changed = true; - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info("Optimized from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); + logger.accept("Optimized from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); } } } - return extractOp(optimizeOnlyContext, root, Context.Type.NONE); + } + + public List explain(Context context, @Nullable String code, @Nullable String method, @Nullable String style) + { + if (code == null) + { + ExpressionNode node; + if (method != null) + { + FunctionValue function = context.host.getFunction(method); + if (function == null) { + throw new ExpressionException(context, this, "Unknown function " + method); + } + node = function.getToken().node; + if (node == null) { + throw new ExpressionException(context, this, "Function " + method + " is not a compiled function"); + } + } else + { + node = context.host.root; + } + if (node == null || node.token.type == null) { + throw new ExpressionException(context, this, "No code to explain"); + } + + // grab source reference + Tokenizer tokenizer = new Tokenizer(context, this, context.host.main == null ? "" : stripExpression(context.host.main.code()) , true, true); + List input = tokenizer.parseTokens(); + List cleanedTokens = Tokenizer.postProcess(input); + + Map, List> tokenPointers = new HashMap<>(); + for (int i = 0; i < cleanedTokens.size(); i++) { + Token token = cleanedTokens.get(i); + tokenPointers.computeIfAbsent(Pair.of(token.lineno, token.linepos), k -> new ArrayList<>()).add(i); + } + + return node.tokensRecursive(this, cleanedTokens, tokenPointers); + } + if (style == null) { + style = context.host.loadOverrides.equivalent; + } + + //todo convert to explain + Tokenizer tokenizer = new Tokenizer(context, this, stripExpression(code), true, true); + // stripping lousy but acceptable semicolons + List input = tokenizer.parseTokens(); + if (style.equalsIgnoreCase("raw")) { + return input; + } + List cleanedTokens = Tokenizer.postProcess(input); + if (style.equalsIgnoreCase("clean")) { + return cleanedTokens; + } + + List rpn = shuntingYard(context, cleanedTokens); + validate(context, rpn); + ExpressionNode root = RPNToParseTree(rpn, context); + + Map, List> tokenPointers = new HashMap<>(); + for (int i = 0; i < cleanedTokens.size(); i++) { + Token token = cleanedTokens.get(i); + tokenPointers.computeIfAbsent(Pair.of(token.lineno, token.linepos), k -> new ArrayList<>()).add(i); + } + + List parsedTokens = root.tokensRecursive(this, cleanedTokens, tokenPointers); + if (style.equalsIgnoreCase("canonical")) { + return parsedTokens; + } + + Context optimizeOnlyContext = new Context.ContextForErrorReporting(context); + // pure functional + optimizeTree(root, optimizeOnlyContext, null, style.contains("optimized"), style.contains("functional")); + List compileTimeOptimized = root.tokensRecursive(this, cleanedTokens, tokenPointers); + + return compileTimeOptimized; } private int treeSize(ExpressionNode node) @@ -1262,11 +1690,11 @@ public class Expression } - private boolean compactTree(ExpressionNode node, Context.Type expectedType, int indent, boolean scriptsDebugging) + private boolean compactTree(ExpressionNode node, Context.Type expectedType, int indent, @Nullable Consumer logger, boolean optimize, boolean toFunctional) { // ctx is just to report errors, not values evaluation boolean optimized = false; - Tokenizer.Token.TokenType token = node.token.type; + Token.TokenType token = node.token.type; if (!token.isFunctional()) { return false; @@ -1278,17 +1706,17 @@ public class Expression } // function or operator String symbol = node.token.surface; - Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); + Fluff.EvalNode operation = ((token == Token.TokenType.FUNCTION) ? functions : operators).get(symbol); Context.Type requestedType = operation.staticType(expectedType); for (ExpressionNode arg : node.args) { - if (compactTree(arg, requestedType, indent + 1, scriptsDebugging)) + if (compactTree(arg, requestedType, indent + 1, logger, optimize, toFunctional)) { optimized = true; } } - if (expectedType != Context.Type.MAPDEF && symbol.equals("->") && node.args.size() == 2) + if (optimize && expectedType != Context.Type.MAPDEF && (symbol.equals("->") || symbol.equals("define") ) && node.args.size() == 2) { String rop = node.args.get(1).token.surface; ExpressionNode returnNode = null; @@ -1312,19 +1740,19 @@ public class Expression returnNode.token = returnNode.args.get(0).token; returnNode.range = returnNode.args.get(0).range; returnNode.args = returnNode.args.get(0).args; - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info(" - Removed unnecessary tail return of " + returnNode.token.surface + " from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); + logger.accept(" - Removed unnecessary tail return of " + returnNode.token.surface + " from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); } } else { returnNode.op = LazyValue.ofConstant(Value.NULL); - returnNode.token.morph(Tokenizer.Token.TokenType.CONSTANT, ""); + returnNode.token.morph(Token.TokenType.CONSTANT, "null"); returnNode.args = Collections.emptyList(); - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info(" - Removed unnecessary tail return from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); + logger.accept(" - Removed unnecessary tail return from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); } } @@ -1334,14 +1762,13 @@ public class Expression { String operator = pair.getKey(); String function = pair.getValue(); - if ((symbol.equals(operator) || symbol.equals(function)) && node.args.size() > 0) + if (optimize && (symbol.equals(operator) || symbol.equals(function)) && !node.args.isEmpty()) { boolean leftOptimizable = operators.get(operator).isLeftAssoc(); ExpressionNode optimizedChild = node.args.get(leftOptimizable ? 0 : (node.args.size() - 1)); String type = optimizedChild.token.surface; if ((type.equals(operator) || type.equals(function)) && (!(optimizedChild.op instanceof LazyValue.ContextFreeLazyValue))) { - optimized = true; List newargs = new ArrayList<>(); if (leftOptimizable) { @@ -1360,23 +1787,31 @@ public class Expression newargs.addAll(optimizedChild.args); } - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info(" - " + symbol + "(" + node.args.size() + ") => " + function + "(" + newargs.size() + ") at line " + (node.token.lineno + 1) + ", node depth " + indent); + logger.accept(" - " + symbol + "(" + node.args.size() + ") => " + function + "(" + newargs.size() + ") at line " + (node.token.lineno + 1) + ", node depth " + indent); } - node.token.morph(Tokenizer.Token.TokenType.FUNCTION, function); + node.token.morph(Token.TokenType.FUNCTION, function); node.args = newargs; + return true; } } } + + if (toFunctional && functionalAliases.containsKey(symbol) && !node.args.isEmpty()) + { + optimized = true; + node.token.morph(Token.TokenType.FUNCTION, functionalAliases.get(symbol)); + } + return optimized; } - private boolean optimizeTree(Context ctx, ExpressionNode node, Context.Type expectedType, int indent, boolean scriptsDebugging) + private boolean optimizeConstantsAndPureFunctions(Context ctx, ExpressionNode node, Context.Type expectedType, int indent, @Nullable Consumer logger) { // ctx is just to report errors, not values evaluation boolean optimized = false; - Tokenizer.Token.TokenType token = node.token.type; + Token.TokenType token = node.token.type; if (!token.isFunctional()) { return false; @@ -1390,11 +1825,11 @@ public class Expression } // function or operator - Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); + Fluff.EvalNode operation = ((token == Token.TokenType.FUNCTION) ? functions : operators).get(symbol); Context.Type requestedType = operation.staticType(expectedType); for (ExpressionNode arg : node.args) { - if (optimizeTree(ctx, arg, requestedType, indent + 1, scriptsDebugging)) + if (optimizeConstantsAndPureFunctions(ctx, arg, requestedType, indent + 1, logger)) { optimized = true; } @@ -1415,7 +1850,7 @@ public class Expression // a few exceptions which we don't implement in the framework for simplicity for now if (!operation.pure()) { - if (!symbol.equals("->") || expectedType != Context.Type.MAPDEF) + if (!(symbol.equals("->") || symbol.equals("define")) || expectedType != Context.Type.MAPDEF) { return optimized; } @@ -1460,10 +1895,11 @@ public class Expression { result = ((ILazyOperator) operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), args.get(1)).evalValue(null, expectedType); } + node.token.disguiseAs(null, "=> "+result.getString()); node.op = LazyValue.ofConstant(result); - if (scriptsDebugging) + if (logger != null) { - CarpetScriptServer.LOG.info(" - " + symbol + "(" + args.stream().map(a -> a.evalValue(null, requestedType).getString()).collect(Collectors.joining(", ")) + ") => " + result.getString() + " at line " + (node.token.lineno + 1) + ", node depth " + indent); + logger.accept(" - " + symbol + "(" + args.stream().map(a -> a.evalValue(null, requestedType).getString()).collect(Collectors.joining(", ")) + ") => " + result.getString() + " at line " + (node.token.lineno + 1) + ", node depth " + indent); } return true; } @@ -1485,7 +1921,7 @@ public class Expression Value ret = ((LazyValue.ContextFreeLazyValue) node.op).evalType(expectedType); return (c, t) -> ret; } - Tokenizer.Token token = node.token; + Token token = node.token; switch (token.type) { case UNARY_OPERATOR: @@ -1520,7 +1956,7 @@ public class Expression } } - private void validate(Context c, List rpn) + private void validate(Context c, List rpn) { /*- * Thanks to Norman Ramsey: @@ -1535,7 +1971,7 @@ public class Expression // push the 'global' scope stack.push(0); - for (Tokenizer.Token token : rpn) + for (Token token : rpn) { switch (token.type) { diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index 0ab2e11d..04286062 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -70,7 +70,7 @@ public abstract class Fluff boolean numParamsVaries(); - LazyValue lazyEval(Context c, Context.Type type, Expression expr, Tokenizer.Token token, List lazyParams); + LazyValue lazyEval(Context c, Context.Type type, Expression expr, Token token, List lazyParams); static void checkInterrupts() { @@ -93,7 +93,7 @@ public abstract class Fluff boolean isLeftAssoc(); - LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, LazyValue v1, LazyValue v2); + LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, LazyValue v1, LazyValue v2); } public interface IOperator extends ILazyOperator @@ -187,7 +187,7 @@ public abstract class Fluff } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Token t, List lazyParams) { return new LazyValue() @@ -273,7 +273,7 @@ public abstract class Fluff } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Token t, LazyValue v1, LazyValue v2) { return (c, typeIgnored) -> { try @@ -308,7 +308,7 @@ public abstract class Fluff } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Token t, LazyValue v1, LazyValue v2) { if (v2 != null) { diff --git a/src/main/java/carpet/script/ScriptCommand.java b/src/main/java/carpet/script/ScriptCommand.java index e8bc716a..8383849a 100644 --- a/src/main/java/carpet/script/ScriptCommand.java +++ b/src/main/java/carpet/script/ScriptCommand.java @@ -5,6 +5,7 @@ import carpet.script.external.Vanilla; import carpet.script.utils.AppStoreManager; import carpet.script.exception.CarpetExpressionException; import carpet.script.value.FunctionValue; +import carpet.script.value.NumericValue; import carpet.script.value.Value; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; @@ -14,14 +15,20 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.commands.CommandBuildContext; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.GameRules; import org.apache.commons.lang3.StringUtils; import java.io.IOException; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CompletableFuture; @@ -36,12 +43,12 @@ import net.minecraft.commands.arguments.blocks.BlockStateArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.Clearable; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.pattern.BlockInWorld; import net.minecraft.world.level.levelgen.structure.BoundingBox; +import javax.annotation.Nullable; + import static net.minecraft.commands.Commands.argument; import static net.minecraft.commands.Commands.literal; import static net.minecraft.commands.SharedSuggestionProvider.suggest; @@ -288,18 +295,18 @@ public class ScriptCommand LiteralArgumentBuilder a = literal("load").requires(Vanilla::ServerPlayer_canScriptACE). then(argument("app", StringArgumentType.word()). suggests((cc, bb) -> suggest(ss(cc).listAvailableModules(true), bb)). - executes((cc) -> - { - boolean success = ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null); - return success ? 1 : 0; - }). + executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null, Expression.LoadOverride.DEFAULT)). + //then(literal("canonical").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null, Expression.LoadOverride.CANONICAL))). + //then(literal("optimized").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null, Expression.LoadOverride.OPTIMIZED))). + //then(literal("functional").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null, Expression.LoadOverride.FUNCTIONAL))). + //then(literal("functional_optimized").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false, null, Expression.LoadOverride.FUNCTIONAL_OPTIMIZED))). then(literal("global"). - executes((cc) -> - { - boolean success = ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null); - return success ? 1 : 0; - } - ) + executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null, Expression.LoadOverride.DEFAULT)) + //. + //then(literal("canonical").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null, Expression.LoadOverride.CANONICAL))). + //then(literal("optimized").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null, Expression.LoadOverride.OPTIMIZED))). + //then(literal("functional").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null, Expression.LoadOverride.FUNCTIONAL))). + //then(literal("functional_optimized").executes((cc) -> ss(cc).addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false, null, Expression.LoadOverride.FUNCTIONAL_OPTIMIZED))) ) ); LiteralArgumentBuilder f = literal("unload").requires(Vanilla::ServerPlayer_canScriptACE). @@ -359,6 +366,26 @@ public class ScriptCommand return success ? 1 : 0; })); + LiteralArgumentBuilder x = literal("explain").requires(Vanilla::ServerPlayer_canScriptACE). + executes((cc) -> explain(cc, null, null, null)). + then(literal("expression"). + then(argument("style", StringArgumentType.word()).suggests((cc, bb) -> suggest(List.of("raw", "clean", "functional", "canonical", "optimized", "functional_optimized"), bb)). + then(argument("expr", StringArgumentType.greedyString()).suggests(ScriptCommand::suggestCode). + executes((cc) -> explain(cc, StringArgumentType.getString(cc, "expr"), null, StringArgumentType.getString(cc, "style"))) + ) + ) + ). + then(literal("invoke"). + then(argument("call", StringArgumentType.word()).suggests((cc, bb) -> suggest(suggestFunctionCalls(cc), bb)). + executes((cc) -> explain(cc, null, StringArgumentType.getString(cc, "call"), null)) + ) + ). + then(literal("source"). + then(argument("style", StringArgumentType.word()).suggests((cc, bb) -> suggest(List.of("raw", "clean", "functional", "canonical", "optimized", "functional_optimized"), bb)). + executes((cc) -> explain(cc, null, null, StringArgumentType.getString(cc, "style"))) + ) + ); + dispatcher.register(literal("script"). requires(Vanilla::ServerPlayer_canScriptGeneral). then(b).then(u).then(o).then(l).then(s).then(c).then(h).then(i).then(e).then(t).then(a).then(f).then(q).then(d).then(r)); @@ -431,7 +458,7 @@ public class ScriptCommand return; } Expression expr = fun.getExpression(); - Tokenizer.Token tok = fun.getToken(); + Token tok = fun.getToken(); List snippet = expr.getExpressionSnippet(tok); Carpet.Messenger_message(source, "wb " + fun.fullName(), "t defined at: line " + (tok.lineno + 1) + " pos " + (tok.linepos + 1)); for (String snippetLine : snippet) @@ -532,10 +559,106 @@ public class ScriptCommand CarpetScriptHost host = getHost(context); return handleCall(source, host, () -> { CarpetExpression ex = new CarpetExpression(host.main, expr, source, new BlockPos(0, 0, 0)); - return ex.scriptRunCommand(host, BlockPos.containing(source.getPosition())); + return ex.scriptRunCommand(host, BlockPos.containing(source.getPosition())).getLeft(); }); } + private static int explain(CommandContext context, @Nullable String expr, @Nullable String method, @Nullable String style) throws CommandSyntaxException + { + CommandSourceStack source = context.getSource(); + CarpetScriptHost host = getHost(context); + return handleCall(source, host, () -> { + // expression is irrelevant as we pass approprirate strings for parsing directly + // we only really need access to operators and functions? + CarpetExpression ex = new CarpetExpression(host.main, "", source, BlockPos.ZERO); + List results = ex.explain(host, expr != null ? expr : (style != null? (host.main != null ? host.main.code() : "") :null), method, style, BlockPos.containing(source.getPosition())); + prettyPrintTokens(source, results); + return NumericValue.of(results.size()); + }); + } + + private static void prettyPrintTokens(CommandSourceStack source, List tokens) + { + Map indents = new HashMap<>(); + for (Token token : tokens) + { + indents.put(token.lineno, Math.min(indents.getOrDefault(token.lineno, token.linepos), token.linepos)); + } + List lines = new ArrayList<>(indents.keySet()); + Collections.sort(lines); + int lineMax = String.valueOf(lines.getLast()).length(); + Deque indentsStack = new ArrayDeque<>(lines); + + List elements = new ArrayList<>(); + for (int i = 0; i < tokens.size(); i++) + { + Token token = tokens.get(i); + if (!indentsStack.isEmpty() && token.lineno == indentsStack.peekFirst()) + { + flushElements(source, elements); + indentsStack.pollFirst(); + // remove all elements of intendStack that don't have any more tokens + outer: while (!indentsStack.isEmpty()) + { + int nextLineNo = indentsStack.peekFirst(); + for (int j = i + 1; j < tokens.size(); j++) + { + if (tokens.get(j).lineno == nextLineNo) + { + break outer; + } + } + indentsStack.pollFirst(); + } + + int lastPos = indents.getOrDefault(token.lineno, 0); + elements.add(Carpet.Messenger_compose("fi " + " ".repeat(lineMax - String.valueOf(token.lineno).length()) + token.lineno)); + elements.add(Carpet.Messenger_compose("g | " + " ".repeat(lastPos))); + } + elements.add(tokenToComponent(token)); + } + flushElements(source, elements); + } + + private static Component tokenToComponent(Token token) + { + String surface = token.surface; + if (!token.display.isEmpty()) + { + surface = token.display; + } + if (token.comment.isEmpty()) + { + return Carpet.Messenger_compose(styleForToken(token) + " " + surface);//, "^gi " + String.format("%s: line %s, pos %s", token.surface, token.lineno, token.linepos)); + } + return Carpet.Messenger_compose(styleForToken(token)+"u " + surface, "^gi " + token.comment); + } + + private static String styleForToken(Token token) + { + return switch (token.type) { + case Token.TokenType.LITERAL -> "l"; + case Token.TokenType.HEX_LITERAL -> "m"; + case Token.TokenType.CONSTANT -> "q"; + case Token.TokenType.OPEN_PAREN, Token.TokenType.CLOSE_PAREN, Token.TokenType.COMMA, + Token.TokenType.OPERATOR, Token.TokenType.UNARY_OPERATOR -> "w"; + case Token.TokenType.FUNCTION -> "d"; + case Token.TokenType.VARIABLE -> "y"; + case Token.TokenType.STRINGPARAM -> "c"; + default -> // marker + "r"; + }; + } + + private static void flushElements(CommandSourceStack source, List elements) + { + if (!elements.isEmpty()) + { + Carpet.Messenger_message(source, (Object []) elements.toArray(new Component[0])); + elements.clear(); + } + } + private static int scriptScan(CommandContext context, BlockPos origin, BlockPos a, BlockPos b, String expr) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); @@ -543,7 +666,7 @@ public class ScriptCommand BoundingBox area = BoundingBox.fromCorners(a, b); CarpetExpression cexpr = new CarpetExpression(host.main, expr, source, origin); int int_1 = area.getXSpan() * area.getYSpan() * area.getZSpan(); // X Y Z - if (int_1 > Vanilla.MinecraftServer_getFillLimit(source.getServer()) ) + if (int_1 > source.getServer().getGameRules().getInt(GameRules.RULE_COMMAND_MODIFICATION_BLOCK_LIMIT)) { Carpet.Messenger_message(source, "r too many blocks to evaluate: " + int_1); return 1; @@ -595,7 +718,7 @@ public class ScriptCommand BoundingBox area = BoundingBox.fromCorners(a, b); CarpetExpression cexpr = new CarpetExpression(host.main, expr, source, origin); int int_1 = area.getXSpan() * area.getYSpan() * area.getZSpan(); - if (int_1 > Vanilla.MinecraftServer_getFillLimit(source.getServer())) + if (int_1 > source.getServer().getGameRules().getInt(GameRules.RULE_COMMAND_MODIFICATION_BLOCK_LIMIT)) { Carpet.Messenger_message(source, "r too many blocks to evaluate: " + int_1); return 1; @@ -675,10 +798,7 @@ public class ScriptCommand if (replacement == null || replacement.test( new BlockInWorld(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - Clearable.tryClear(tileentity); - - if (block.place(world, mbpos, 2)) + if (block.place(world, mbpos, 2 & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS)) { ++affected; } @@ -701,7 +821,7 @@ public class ScriptCommand { mbpos.set(x + area.minX(), y + area.minY(), z + area.minZ()); Block blokc = world.getBlockState(mbpos).getBlock(); - world.blockUpdated(mbpos, blokc); + world.updateNeighborsAt(mbpos, blokc); } } } diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index 29cd5233..4dd06d5f 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -37,6 +37,9 @@ public abstract class ScriptHost private final ScriptServer scriptServer; protected boolean inTermination = false; public boolean strict; + public Expression.LoadOverride loadOverrides; + @Nullable + public Expression.ExpressionNode root; private final Set deprecations = new HashSet<>(); @@ -138,18 +141,19 @@ public abstract class ScriptHost @FunctionalInterface public interface ErrorSnooper { - List apply(Expression expression, Tokenizer.Token token, Context context, String message); + List apply(Expression expression, Token token, Context context, String message); } public ErrorSnooper errorSnooper = null; - protected ScriptHost(@Nullable Module code, ScriptServer scriptServer, boolean perUser, ScriptHost parent) + protected ScriptHost(@Nullable Module code, ScriptServer scriptServer, boolean perUser, ScriptHost parent, Expression.LoadOverride loadOverrides) { this.parent = parent; this.main = code; this.perUser = perUser; this.user = null; this.strict = false; + this.loadOverrides = loadOverrides; this.scriptServer = scriptServer; ModuleData moduleData = new ModuleData(code); initializeModuleGlobals(moduleData); @@ -231,6 +235,7 @@ public abstract class ScriptHost protected abstract void runModuleCode(Context c, Module module); // this should be shell out in the executor + @Nullable public FunctionValue getFunction(String name) { return getFunction(main, name); @@ -253,6 +258,7 @@ public abstract class ScriptHost return ret; } + @Nullable private FunctionValue getFunction(Module module, String name) { ModuleData local = getModuleData(module); @@ -286,6 +292,7 @@ public abstract class ScriptHost return target.globalFunctions.get(name); } + @Nullable private ModuleData findModuleDataFromFunctionImports(String name, ModuleData source, int ttl) { if (ttl > 64) @@ -460,6 +467,7 @@ public abstract class ScriptHost this.moduleData.forEach((key, value) -> host.moduleData.put(key, new ModuleData(key, value))); // fixing imports host.moduleData.forEach((module, data) -> data.setImportsBasedOn(host, this.moduleData.get(data.parent))); + host.root = this.root; } public synchronized void handleExpressionException(String msg, ExpressionException exc) diff --git a/src/main/java/carpet/script/Token.java b/src/main/java/carpet/script/Token.java new file mode 100644 index 00000000..c0fa53e8 --- /dev/null +++ b/src/main/java/carpet/script/Token.java @@ -0,0 +1,113 @@ +package carpet.script; + +import javax.annotation.Nullable; + +public class Token implements Comparable { + + enum TokenType { + FUNCTION(true, false), OPERATOR(true, false), UNARY_OPERATOR(true, false), + VARIABLE(false, false), CONSTANT(false, true), + LITERAL(false, true), HEX_LITERAL(false, true), STRINGPARAM(false, true), + OPEN_PAREN(false, true), COMMA(false, true), CLOSE_PAREN(false, true), MARKER(false, true); + + final boolean functional; + final boolean constant; + + TokenType(boolean functional, boolean constant) { + this.functional = functional; + this.constant = constant; + } + + public boolean isFunctional() { + return functional; + } + + public boolean isConstant() { + return constant; + } + } + + public String surface = ""; + public String display = ""; + public String comment = ""; + public TokenType type; + public int pos; + public int ordinal = 0; + public int linepos; + public int lineno; + + @Nullable + public Expression.ExpressionNode node = null; + + public static final Token NONE = new Token(); + + public Token morphedInto(TokenType newType, String newSurface) { + Token created = new Token(); + created.surface = newSurface; + created.type = newType; + created.pos = pos; + created.linepos = linepos; + created.lineno = lineno; + created.node = node; + created.ordinal = ordinal + 1; + return created; + } + + public void swapPlace(Token other) { + int order = other.ordinal; + other.ordinal = ordinal; + ordinal = order; + } + + public void morph(TokenType type, String s) { + this.type = type; + this.surface = s; + this.display = ""; + this.comment = ""; + } + + public Token disguiseAs(@Nullable String s, @Nullable String s1) { + if (s != null) { + display = s; + } + if (s1 != null) { + comment = s1; + } + return this; + } + + public void append(char c) { + surface += c; + } + + public void append(String s) { + surface += s; + } + + public char charAt(int pos) { + return surface.charAt(pos); + } + + public int length() { + return surface.length(); + } + + @Override + public String toString() { + return surface; + } + + @Override + public int compareTo(Token o) { + // compare by lineno, then by linepos, then by ordinal + if (lineno != o.lineno) + { + return lineno - o.lineno; + } + if (linepos != o.linepos) + { + return linepos - o.linepos; + } + return ordinal - o.ordinal; + } +} diff --git a/src/main/java/carpet/script/Tokenizer.java b/src/main/java/carpet/script/Tokenizer.java index 90994f00..75fd2646 100644 --- a/src/main/java/carpet/script/Tokenizer.java +++ b/src/main/java/carpet/script/Tokenizer.java @@ -1,20 +1,16 @@ package carpet.script; import carpet.script.exception.ExpressionException; -import carpet.script.exception.InternalExpressionException; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; /** * Expression tokenizer that allows to iterate over a {@link String} * expression token by token. Blank characters will be skipped. */ -public class Tokenizer implements Iterator +public class Tokenizer { /** * What character to use for decimal separators. @@ -53,15 +49,18 @@ public class Tokenizer implements Iterator this.newLinesMarkers = allowNewLineMakers; } - public List postProcess() + public static Tokenizer simple(String input) + { + return new Tokenizer(null, null, input, false, false); + } + + public static List postProcess(List originalTokens) { - Iterable iterable = () -> this; - List originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); List cleanedTokens = new ArrayList<>(); Token last = null; - while (!originalTokens.isEmpty()) + for (int i = originalTokens.size() - 1; i >= 0; i--) { - Token current = originalTokens.remove(originalTokens.size() - 1); + Token current = originalTokens.get(i); if (current.type == Token.TokenType.MARKER && current.surface.startsWith("//")) { continue; @@ -104,7 +103,16 @@ public class Tokenizer implements Iterator return cleanedTokens; } - @Override + public List parseTokens() + { + List tokens = new ArrayList<>(); + while (hasNext()) + { + tokens.add(next()); + } + return tokens; + } + public boolean hasNext() { return (pos < input.length()); @@ -132,18 +140,6 @@ public class Tokenizer implements Iterator || (tok.type == Token.TokenType.UNARY_OPERATOR && tok.surface.equals(";u")); } - public static List simplepass(String input) - { - Tokenizer tok = new Tokenizer(null, null, input, false, false); - List res = new ArrayList<>(); - while (tok.hasNext()) - { - res.add(tok.next()); - } - return res; - } - - @Override public Token next() { Token token = new Token(); @@ -259,6 +255,7 @@ public class Tokenizer implements Iterator } pos++; linepos++; + token.disguiseAs("'"+token.surface+"'", null); } else if (Character.isLetter(ch) || "_".indexOf(ch) >= 0) @@ -302,6 +299,7 @@ public class Tokenizer implements Iterator else if (ch == ',') { token.type = Token.TokenType.COMMA; + token.disguiseAs(", ", null); } else { @@ -383,12 +381,15 @@ public class Tokenizer implements Iterator || (previousToken.type == Token.TokenType.MARKER && (previousToken.surface.equals("{") || previousToken.surface.equals("["))) ) { + token.disguiseAs(token.surface, null); token.surface += "u"; token.type = Token.TokenType.UNARY_OPERATOR; } else { token.type = Token.TokenType.OPERATOR; + token.disguiseAs(token.surface.equals(";") ? (token.surface + " ") : (" " + token.surface + " "), null); + } } if (expression != null && context != null && previousToken != null && @@ -414,90 +415,4 @@ public class Tokenizer implements Iterator } return previousToken = token; } - - @Override - public void remove() - { - throw new InternalExpressionException("remove() not supported"); - } - - public static class Token - { - enum TokenType - { - FUNCTION(true, false), OPERATOR(true, false), UNARY_OPERATOR(true, false), - VARIABLE(false, false), CONSTANT(false, true), - LITERAL(false, true), HEX_LITERAL(false, true), STRINGPARAM(false, true), - OPEN_PAREN(false, true), COMMA(false, true), CLOSE_PAREN(false, true), MARKER(false, true); - - final boolean functional; - final boolean constant; - - TokenType(boolean functional, boolean constant) - { - this.functional = functional; - this.constant = constant; - } - - public boolean isFunctional() - { - return functional; - } - - public boolean isConstant() - { - return constant; - } - } - - public String surface = ""; - public TokenType type; - public int pos; - public int linepos; - public int lineno; - public static final Token NONE = new Token(); - - public Token morphedInto(TokenType newType, String newSurface) - { - Token created = new Token(); - created.surface = newSurface; - created.type = newType; - created.pos = pos; - created.linepos = linepos; - created.lineno = lineno; - return created; - } - - public void morph(TokenType type, String s) - { - this.type = type; - this.surface = s; - } - - public void append(char c) - { - surface += c; - } - - public void append(String s) - { - surface += s; - } - - public char charAt(int pos) - { - return surface.charAt(pos); - } - - public int length() - { - return surface.length(); - } - - @Override - public String toString() - { - return surface; - } - } } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index ca3c22b4..108bc030 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -97,6 +97,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.OptionalLong; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -131,7 +132,7 @@ public class Auxiliary CarpetContext cc = (CarpetContext) c; if (lv.isEmpty()) { - return ListValue.wrap(cc.registry(Registries.SOUND_EVENT).holders().map(soundEventReference -> ValueConversions.of(soundEventReference.key().location()))); + return ListValue.wrap(cc.registry(Registries.SOUND_EVENT).listElements().map(soundEventReference -> ValueConversions.of(soundEventReference.key().location()))); } String rawString = lv.get(0).getString(); ResourceLocation soundName = InputValidator.identifierOf(rawString); @@ -176,7 +177,7 @@ public class Auxiliary CarpetContext cc = (CarpetContext) c; if (lv.isEmpty()) { - return ListValue.wrap(cc.registry(Registries.PARTICLE_TYPE).holders().map(particleTypeReference -> ValueConversions.of(particleTypeReference.key().location()))); + return ListValue.wrap(cc.registry(Registries.PARTICLE_TYPE).listElements().map(particleTypeReference -> ValueConversions.of(particleTypeReference.key().location()))); } MinecraftServer ms = cc.server(); ServerLevel world = cc.level(); @@ -208,14 +209,14 @@ public class Auxiliary { for (ServerPlayer p : (world.players())) { - world.sendParticles(p, particle, true, vec.x, vec.y, vec.z, count, + world.sendParticles(p, particle, true, true, vec.x, vec.y, vec.z, count, spread, spread, spread, speed); } } else { world.sendParticles(player, - particle, true, vec.x, vec.y, vec.z, count, + particle, true, true, vec.x, vec.y, vec.z, count, spread, spread, spread, speed); } @@ -401,7 +402,7 @@ public class Auxiliary yoffset = -armorstand.getBbHeight() + 0.3; } } - armorstand.moveTo( + armorstand.snapTo( pointLocator.vec.x, //pointLocator.vec.y - ((!interactable && targetBlock == null)?0.41f:((targetBlock==null)?(armorstand.getHeight()+0.41):(armorstand.getHeight()-0.3))), pointLocator.vec.y + yoffset, @@ -684,12 +685,17 @@ public class Auxiliary try { Component[] error = {null}; + OptionalLong[] returnValue = {OptionalLong.empty()}; List output = new ArrayList<>(); s.getServer().getCommands().performPrefixedCommand( - new SnoopyCommandSource(s, error, output), + new SnoopyCommandSource(s, error, output, returnValue), lv.get(0).getString()); + if (returnValue[0].isEmpty()) + { + return Value.NULL; + } return ListValue.of( - NumericValue.ZERO, + NumericValue.of(returnValue[0].getAsLong()), ListValue.wrap(output.stream().map(FormattedTextValue::new)), FormattedTextValue.of(error[0]) ); @@ -1062,7 +1068,7 @@ public class Auxiliary ResourceLocation statName; category = InputValidator.identifierOf(lv.get(1).getString()); statName = InputValidator.identifierOf(lv.get(2).getString()); - StatType type = cc.registry(Registries.STAT_TYPE).get(category); + StatType type = cc.registry(Registries.STAT_TYPE).getValue(category); if (type == null) { return Value.NULL; @@ -1189,7 +1195,7 @@ public class Auxiliary Path zipRoot = zipfs.getPath("/"); zipValueToJson(zipRoot.resolve("pack.mcmeta"), MapValue.wrap( Map.of(StringValue.of("pack"), MapValue.wrap(Map.of( - StringValue.of("pack_format"), new NumericValue(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA)), + StringValue.of("pack_format"), new NumericValue(SharedConstants.getCurrentVersion().packVersion(PackType.SERVER_DATA)), StringValue.of("description"), StringValue.of(name), StringValue.of("source"), StringValue.of("scarpet") ))) @@ -1382,7 +1388,7 @@ public class Auxiliary @Nullable private static Stat getStat(StatType type, ResourceLocation id) { - T key = type.getRegistry().get(id); + T key = type.getRegistry().getValue(id); if (key == null || !type.contains(key)) { return null; diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index 744f8c43..9c478d4b 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -33,9 +33,9 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySelector; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -142,17 +142,17 @@ public class Entities Vec3 vec3d = position.vec; ServerLevel serverWorld = cc.level(); - Entity entity = EntityType.loadEntityRecursive(tag, serverWorld, e -> { - e.moveTo(vec3d.x, vec3d.y, vec3d.z, e.getYRot(), e.getXRot()); + Entity entity = EntityType.loadEntityRecursive(tag, serverWorld, EntitySpawnReason.COMMAND, e -> { + e.snapTo(vec3d.x, vec3d.y, vec3d.z, e.getYRot(), e.getXRot()); return e; }); if (entity == null) { return Value.NULL; } - if (!hasTag && entity instanceof final Mob mob) + if (!hasTag && entity instanceof Mob mob) { - mob.finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, null); + mob.finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.COMMAND, null); } if (!serverWorld.tryAddFreshEntityWithPassengers(entity)) { diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index 11bab7e7..e7b45930 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -6,8 +6,8 @@ import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ThrowStatement; import carpet.script.exception.Throwables; -import carpet.script.external.Vanilla; import carpet.script.utils.InputValidator; +import carpet.script.utils.RecipeHelper; import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; @@ -21,7 +21,6 @@ import carpet.script.value.Value; import carpet.script.value.ValueConversions; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -37,6 +36,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; +import net.minecraft.util.context.ContextMap; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; @@ -44,11 +44,14 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.PlacementInfo; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.item.crafting.SingleItemRecipe; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; import net.minecraft.world.phys.Vec3; public class Inventories @@ -69,10 +72,10 @@ public class Inventories Registry items = cc.registry(Registries.ITEM); if (lv.isEmpty()) { - return ListValue.wrap(items.holders().map(itemReference -> ValueConversions.of(itemReference.key().location()))); + return ListValue.wrap(items.listElements().map(itemReference -> ValueConversions.of(itemReference.key().location()))); } String tag = lv.get(0).getString(); - Optional> itemTag = items.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); + Optional> itemTag = items.get(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); return itemTag.isEmpty() ? Value.NULL : ListValue.wrap(itemTag.get().stream().map(b -> items.getKey(b.value())).filter(Objects::nonNull).map(ValueConversions::of)); }); @@ -83,15 +86,15 @@ public class Inventories Registry blocks = cc.registry(Registries.ITEM); if (lv.isEmpty()) { - return ListValue.wrap(blocks.getTagNames().map(ValueConversions::of)); + return ListValue.wrap(blocks.getTags().map(ValueConversions::of)); } Item item = NBTSerializableValue.parseItem(lv.get(0).getString(), cc.registryAccess()).getItem(); if (lv.size() == 1) { - return ListValue.wrap(blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == item))).map(e -> ValueConversions.of(e.getFirst()))); + return ListValue.wrap(blocks.getTags().filter(e -> e.stream().anyMatch(h -> (h.value() == item))).map(ValueConversions::of)); } String tag = lv.get(1).getString(); - Optional> tagSet = blocks.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); + Optional> tagSet = blocks.get(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item)); }); @@ -103,43 +106,54 @@ public class Inventories throw new InternalExpressionException("'recipe_data' requires at least one argument"); } String recipeName = lv.get(0).getString(); - RecipeType type = RecipeType.CRAFTING; + RecipeType> type = RecipeType.CRAFTING; if (lv.size() > 1) { String recipeType = lv.get(1).getString(); - type = cc.registry(Registries.RECIPE_TYPE).get(InputValidator.identifierOf(recipeType)); + type = cc.registry(Registries.RECIPE_TYPE).getValue(InputValidator.identifierOf(recipeType)); if (type == null) { throw new InternalExpressionException("Unknown recipe type: " + recipeType); } } - List> recipes = Vanilla.RecipeManager_getAllMatching(cc.server().getRecipeManager(), type, InputValidator.identifierOf(recipeName), cc.registryAccess()); + List> recipes = RecipeHelper.getRecipesForOutput(cc.server().getRecipeManager(), type, InputValidator.identifierOf(recipeName), cc.level()); if (recipes.isEmpty()) { return Value.NULL; } List recipesOutput = new ArrayList<>(); RegistryAccess regs = cc.registryAccess(); + ContextMap context = SlotDisplayContext.fromLevel(cc.level()); for (Recipe recipe : recipes) { - ItemStack result = recipe.getResultItem(regs); + List results = new ArrayList<>(); + //ItemStack result = recipe.display().forEach(); getResultItem(regs); + recipe.display().forEach(rd -> rd.result().resolveForStacks(context).forEach(is -> results.add(ValueConversions.of(is, regs)))); + + List ingredientValue = new ArrayList<>(); - recipe.getIngredients().forEach(ingredient -> { - // I am flattening ingredient lists per slot. - // consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference - // in depths of lists. - List> stacks = Vanilla.Ingredient_getRecipeStacks(ingredient); - if (stacks.isEmpty()) + for (int info : recipe.placementInfo().slotsToIngredientIndex()) + { + if (info == PlacementInfo.EMPTY_SLOT) + { + ingredientValue.add(Value.NULL); + continue; + } + int ingredientIndex = info; + + List alternatives = new ArrayList<>(); + recipe.placementInfo().ingredients().get(ingredientIndex).items().forEach(item -> alternatives.add(ValueConversions.of(item.value(), regs))); + if (alternatives.isEmpty()) { ingredientValue.add(Value.NULL); } else { - List alternatives = new ArrayList<>(); - stacks.forEach(col -> col.stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add)); ingredientValue.add(ListValue.wrap(alternatives)); } - }); + } + + Value recipeSpec; if (recipe instanceof ShapedRecipe shapedRecipe) { @@ -157,8 +171,8 @@ public class Inventories { recipeSpec = ListValue.of( new StringValue("smelting"), - new NumericValue(abstractCookingRecipe.getCookingTime()), - new NumericValue(abstractCookingRecipe.getExperience()) + new NumericValue(abstractCookingRecipe.cookingTime()), + new NumericValue(abstractCookingRecipe.experience()) ); } else if (recipe instanceof SingleItemRecipe) @@ -174,7 +188,7 @@ public class Inventories recipeSpec = ListValue.of(new StringValue("custom")); } - recipesOutput.add(ListValue.of(ValueConversions.of(result, regs), ListValue.wrap(ingredientValue), recipeSpec)); + recipesOutput.add(ListValue.of(ListValue.wrap(results), ListValue.wrap(ingredientValue), recipeSpec)); } return ListValue.wrap(recipesOutput); }); @@ -183,10 +197,11 @@ public class Inventories { String itemStr = v.get(0).getString(); ResourceLocation id = InputValidator.identifierOf(itemStr); - Registry registry = ((CarpetContext) c).registry(Registries.ITEM); + CarpetContext cc = (CarpetContext) c; + Registry registry = cc.registry(Registries.ITEM); Item item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM)); - Item reminder = item.getCraftingRemainingItem(); - return reminder == null ? Value.NULL : NBTSerializableValue.nameFromRegistryId(registry.getKey(reminder)); + ItemStack reminder = item.getCraftingRemainder(); + return reminder.isEmpty() ? Value.NULL : ValueConversions.of(reminder, cc.registryAccess()); }); expression.addContextFunction("inventory_size", -1, (c, t, lv) -> diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index cd282d7e..f903eb0a 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -26,6 +26,7 @@ import net.minecraft.server.ServerScoreboard; import net.minecraft.server.bossevents.CustomBossEvent; import net.minecraft.server.bossevents.CustomBossEvents; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.StringRepresentable; import net.minecraft.world.BossEvent; import net.minecraft.world.scores.DisplaySlot; import net.minecraft.world.scores.Objective; @@ -35,6 +36,7 @@ import net.minecraft.world.scores.ScoreHolder; import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Team; import net.minecraft.world.scores.criteria.ObjectiveCriteria; +import org.jetbrains.annotations.Nullable; public class Scoreboards { @@ -420,7 +422,7 @@ public class Scoreboards { throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); } - Team.CollisionRule collisionRule = Team.CollisionRule.byName(settingVal.getString()); + Team.CollisionRule collisionRule = getCollisionRule(settingVal); if (collisionRule == null) { throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); @@ -452,7 +454,7 @@ public class Scoreboards { throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); } - Team.Visibility deathMessageVisibility = Team.Visibility.byName(settingVal.getString()); + Team.Visibility deathMessageVisibility = getVisibility(settingVal); if (deathMessageVisibility == null) { throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); @@ -490,7 +492,7 @@ public class Scoreboards { throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); } - Team.Visibility nametagVisibility = Team.Visibility.byName(settingVal.getString()); + Team.Visibility nametagVisibility = getVisibility(settingVal); if (nametagVisibility == null) { throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); @@ -578,12 +580,12 @@ public class Scoreboards BossEvent.BossBarColor color = (bossBar).getColor(); return color == null ? Value.NULL : StringValue.of(color.getName()); } - BossEvent.BossBarColor color = BossEvent.BossBarColor.byName(propertyValue.getString()); + BossEvent.BossBarColor color = ((StringRepresentable.EnumCodec)BossEvent.BossBarColor.CODEC).byName(propertyValue.getString()); if (color == null) { return Value.NULL; } - bossBar.setColor(BossEvent.BossBarColor.byName(propertyValue.getString())); + bossBar.setColor(color); return Value.TRUE; } case "max" -> { @@ -661,7 +663,7 @@ public class Scoreboards { return StringValue.of(bossBar.getOverlay().getName()); } - BossEvent.BossBarOverlay style = BossEvent.BossBarOverlay.byName(propertyValue.getString()); + BossEvent.BossBarOverlay style = ((StringRepresentable.EnumCodec)BossEvent.BossBarOverlay.CODEC).byName(propertyValue.getString()); if (style == null) { throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property); @@ -697,5 +699,35 @@ public class Scoreboards } }); } + + @Nullable + private static Team.CollisionRule getCollisionRule(Value settingVal) + { + + final String string = settingVal.getString(); + for (Team.CollisionRule rule : Team.CollisionRule.values()) + { + if (rule.getSerializedName().equalsIgnoreCase(string)) + { + return rule; + } + } + return null; + } + + @Nullable + private static Team.Visibility getVisibility(Value settingVal) + { + + final String string = settingVal.getString(); + for (Team.Visibility rule : Team.Visibility.values()) + { + if (rule.getSerializedName().equalsIgnoreCase(string)) + { + return rule; + } + } + return null; + } } diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index ae60ed0d..2794a875 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -39,9 +39,11 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.QuartPos; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.NbtOps; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.ServerLevel; @@ -49,7 +51,10 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.Ticket; import net.minecraft.server.level.TicketType; import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.status.ChunkStatus; @@ -60,6 +65,7 @@ import net.minecraft.world.level.levelgen.NoiseRouter; import net.minecraft.world.level.levelgen.RandomState; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.storage.TagValueInput; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.tuple.Pair; @@ -97,12 +103,10 @@ import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.DiggerItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.ShearsItem; -import net.minecraft.world.item.SwordItem; import net.minecraft.world.item.TridentItem; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; @@ -147,9 +151,9 @@ public class WorldAccess DIRECTION_MAP.put("x", Direction.EAST); } - private static final Map> ticketTypes = Map.of( + private static final Map ticketTypes = Map.of( "portal", TicketType.PORTAL, - "teleport", TicketType.POST_TELEPORT, + "teleport", TicketType.ENDER_PEARL, "unknown", TicketType.UNKNOWN ); // dummy entity for dummy requirements in the loot tables (see snowball) @@ -401,7 +405,7 @@ public class WorldAccess Registry poiReg = cc.registry(Registries.POINT_OF_INTEREST_TYPE); PoiType type = poiReg.getOptional(resource) .orElseThrow(() -> new ThrowStatement(poiTypeString, Throwables.UNKNOWN_POI)); - Holder holder = poiReg.getHolderOrThrow(ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, resource)); + Holder holder = poiReg.getOrThrow(ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, resource)); int occupancy = 0; if (locator.offset + 1 < lv.size()) @@ -644,7 +648,7 @@ public class WorldAccess { ServerLevel world = ((CarpetContext) c).level(); DistanceManager foo = world.getChunkSource().chunkMap.getDistanceManager(); - Long2ObjectOpenHashMap>> levelTickets = Vanilla.ChunkTicketManager_getTicketsByPosition(foo); + Long2ObjectOpenHashMap> levelTickets = Vanilla.ChunkTicketManager_getTicketsByPosition(foo); List res = new ArrayList<>(); if (lv.isEmpty()) @@ -652,7 +656,7 @@ public class WorldAccess for (long key : levelTickets.keySet()) { ChunkPos chpos = new ChunkPos(key); - for (Ticket ticket : levelTickets.get(key)) + for (Ticket ticket : levelTickets.get(key)) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -667,10 +671,10 @@ public class WorldAccess { BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockPos pos = blockArgument.block.getPos(); - SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); + List tickets = levelTickets.get(new ChunkPos(pos).toLong()); if (tickets != null) { - for (Ticket ticket : tickets) + for (Ticket ticket : tickets) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -695,7 +699,7 @@ public class WorldAccess expression.addContextFunction("update", -1, (c, t, lv) -> booleanStateTest(c, "update", lv, (s, p) -> { - ((CarpetContext) c).level().neighborChanged(p, s.getBlock(), p); + ((CarpetContext) c).level().neighborChanged(p, s.getBlock(), null); return true; })); @@ -817,8 +821,7 @@ public class WorldAccess Boolean[] result = new Boolean[]{true}; cc.server().executeBlocking(() -> { - Clearable.tryClear(world.getBlockEntity(targetPos)); - boolean success = world.setBlock(targetPos, finalSourceBlockState, 2); + boolean success = world.setBlock(targetPos, finalSourceBlockState, Block.UPDATE_CLIENTS | Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS ); if (finalData != null) { BlockEntity be = world.getBlockEntity(targetPos); @@ -828,7 +831,9 @@ public class WorldAccess destTag.putInt("x", targetPos.getX()); destTag.putInt("y", targetPos.getY()); destTag.putInt("z", targetPos.getZ()); - be.loadWithComponents(destTag, world.registryAccess()); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(be.problemPath(), CarpetScriptServer.LOG)) { + be.loadWithComponents(TagValueInput.create(reporter, world.registryAccess(), destTag)); + } be.setChanged(); success = true; } @@ -887,7 +892,7 @@ public class WorldAccess ItemStack tool; if (tag != null) { - tool = ItemStack.parseOptional(regs, tag); + tool = ItemStack.CODEC.parse(regs.createSerializationContext(NbtOps.INSTANCE), tag).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s)); } else { @@ -912,11 +917,11 @@ public class WorldAccess //postMine() durability from item classes float hardness = state.getDestroySpeed(world, where); int damageAmount = 0; - if ((item instanceof DiggerItem && hardness > 0.0) || item instanceof ShearsItem) + if ((tool.is(ItemTags.PICKAXES) && hardness > 0.0) || item instanceof ShearsItem) { damageAmount = 1; } - else if (item instanceof TridentItem || item instanceof SwordItem) + else if (item instanceof TridentItem || tool.is(ItemTags.SWORDS)) { damageAmount = 2; } @@ -930,7 +935,7 @@ public class WorldAccess if (dropLoot) { - if (how < 0 || (tag != null && EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).getHolderOrThrow(Enchantments.SILK_TOUCH), tool) > 0)) + if (how < 0 || (tag != null && EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH), tool) > 0)) { Block.popResource(world, where, new ItemStack(state.getBlock())); } @@ -938,7 +943,7 @@ public class WorldAccess { if (how > 0) { - tool.enchant(world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).getHolderOrThrow(Enchantments.FORTUNE), (int) how); + tool.enchant(world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.FORTUNE), (int) how); } if (DUMMY_ENTITY == null) { @@ -955,7 +960,7 @@ public class WorldAccess { return Value.NULL; } - return new NBTSerializableValue(() -> tool.saveOptional(regs)); + return new NBTSerializableValue(() -> ItemStack.CODEC.encodeStart(regs.createSerializationContext(NbtOps.INSTANCE), tool).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s))); }); @@ -1071,10 +1076,9 @@ public class WorldAccess } } LivingEntity theAttacker = attacker; - float thePowah = powah; // copy of ServerWorld.createExplosion #TRACK# - Explosion explosion = new Explosion(cc.level(), source, null, null, pos.x, pos.y, pos.z, powah, createFire, mode, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE) + ServerExplosion explosion = new ServerExplosion(cc.level(), source, null, null, pos, powah, createFire, mode) { @Override @Nullable @@ -1085,16 +1089,11 @@ public class WorldAccess } }; explosion.explode(); - explosion.finalizeExplosion(false); - if (mode == Explosion.BlockInteraction.KEEP) - { - explosion.clearToBlow(); - } - Explosion.BlockInteraction finalMode = mode; + ParticleOptions explosionParticle = explosion.isSmall() ? ParticleTypes.EXPLOSION : ParticleTypes.EXPLOSION_EMITTER; cc.level().players().forEach(spe -> { if (spe.distanceToSqr(pos) < 4096.0D) { - spe.connection.send(new ClientboundExplodePacket(pos.x, pos.y, pos.z, thePowah, explosion.getToBlow(), explosion.getHitPlayers().get(spe), finalMode, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE)); + spe.connection.send(new ClientboundExplodePacket(pos, Optional.ofNullable(explosion.getHitPlayers().get(spe)), explosionParticle, SoundEvents.GENERIC_EXPLODE)); } }); return Value.TRUE; @@ -1226,10 +1225,10 @@ public class WorldAccess Registry blocks = cc.registry(Registries.BLOCK); if (lv.isEmpty()) { - return ListValue.wrap(blocks.holders().map(blockReference -> ValueConversions.of(blockReference.key().location()))); + return ListValue.wrap(blocks.listElements().map(blockReference -> ValueConversions.of(blockReference.key().location()))); } ResourceLocation tag = InputValidator.identifierOf(lv.get(0).getString()); - Optional> tagset = blocks.getTag(TagKey.create(Registries.BLOCK, tag)); + Optional> tagset = blocks.get(TagKey.create(Registries.BLOCK, tag)); return tagset.isEmpty() ? Value.NULL : ListValue.wrap(tagset.get().stream().map(b -> ValueConversions.of(blocks.getKey(b.value())))); }); @@ -1239,16 +1238,16 @@ public class WorldAccess Registry blocks = cc.registry(Registries.BLOCK); if (lv.isEmpty()) { - return ListValue.wrap(blocks.getTagNames().map(ValueConversions::of)); + return ListValue.wrap(blocks.getTags().map(ValueConversions::of)); } BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); if (blockLocator.offset == lv.size()) { Block target = blockLocator.block.getBlockState().getBlock(); - return ListValue.wrap(blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == target))).map(e -> ValueConversions.of(e.getFirst()))); + return ListValue.wrap(blocks.getTags().filter(e -> e.stream().anyMatch(h -> (h.value() == target))).map(ValueConversions::of)); } String tag = lv.get(blockLocator.offset).getString(); - Optional> tagSet = blocks.getTag(TagKey.create(Registries.BLOCK, InputValidator.identifierOf(tag))); + Optional> tagSet = blocks.get(TagKey.create(Registries.BLOCK, InputValidator.identifierOf(tag))); return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(blockLocator.block.getBlockState().is(tagSet.get())); }); @@ -1257,7 +1256,7 @@ public class WorldAccess ServerLevel world = cc.level(); if (lv.isEmpty()) { - return ListValue.wrap(cc.registry(Registries.BIOME).holders().map(biomeReference -> ValueConversions.of(biomeReference.key().location()))); + return ListValue.wrap(cc.registry(Registries.BIOME).listElements().map(biomeReference -> ValueConversions.of(biomeReference.key().location()))); } Biome biome; @@ -1302,7 +1301,7 @@ public class WorldAccess if (locator.replacement != null) { - biome = world.registryAccess().registryOrThrow(Registries.BIOME).get(InputValidator.identifierOf(locator.replacement)); + biome = world.registryAccess().lookupOrThrow(Registries.BIOME).getValue(InputValidator.identifierOf(locator.replacement)); if (biome == null) { throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME); @@ -1337,7 +1336,7 @@ public class WorldAccess } String biomeName = lv.get(locator.offset).getString(); // from locatebiome command code - Holder biome = cc.registry(Registries.BIOME).getHolder(ResourceKey.create(Registries.BIOME, InputValidator.identifierOf(biomeName))) + Holder biome = cc.registry(Registries.BIOME).get(ResourceKey.create(Registries.BIOME, InputValidator.identifierOf(biomeName))) .orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME)); boolean doImmediateUpdate = true; if (lv.size() > locator.offset + 1) @@ -1352,7 +1351,7 @@ public class WorldAccess int biomeZ = QuartPos.fromBlock(pos.getZ()); try { - int i = QuartPos.fromBlock(chunk.getMinBuildHeight()); + int i = QuartPos.fromBlock(chunk.getMinY()); int j = i + QuartPos.fromBlock(chunk.getHeight()) - 1; int k = Mth.clamp(biomeY, i, j); int l = chunk.getSectionIndex(QuartPos.toBlock(k)); @@ -1367,7 +1366,7 @@ public class WorldAccess { WorldTools.forceChunkUpdate(pos, world); } - chunk.setUnsaved(true); + chunk.markUnsaved(); return Value.TRUE; }); @@ -1394,7 +1393,7 @@ public class WorldAccess ); } String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); - Structure structureName = reg.get(InputValidator.identifierOf(simpleStructureName)); + Structure structureName = reg.getValue(InputValidator.identifierOf(simpleStructureName)); if (structureName == null) { return Value.NULL; @@ -1432,7 +1431,7 @@ public class WorldAccess { String reqString = requested.getString(); ResourceLocation id = InputValidator.identifierOf(reqString); - Structure requestedStructure = reg.get(id); + Structure requestedStructure = reg.getValue(id); if (requestedStructure != null) { singleOutput = true; @@ -1440,7 +1439,7 @@ public class WorldAccess } else { - StructureType sss = cc.registry(Registries.STRUCTURE_TYPE).get(id); + StructureType sss = cc.registry(Registries.STRUCTURE_TYPE).getValue(id); reg.entrySet().stream().filter(e -> e.getValue().type() == sss).forEach(e -> structure.add(e.getValue())); } if (structure.isEmpty()) @@ -1519,7 +1518,7 @@ public class WorldAccess return MapValue.wrap(structureList); } String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); - return ValueConversions.of(structures.get(reg.get(InputValidator.identifierOf(structureName))), cc.registryAccess()); + return ValueConversions.of(structures.get(reg.getValue(InputValidator.identifierOf(structureName))), cc.registryAccess()); }); expression.addContextFunction("set_structure", -1, (c, t, lv) -> @@ -1682,7 +1681,7 @@ public class WorldAccess throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); } String type = lv.get(locator.offset).getString(); - TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); + TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); if (ticket == null) { throw new InternalExpressionException("Unknown ticket type: " + type); @@ -1696,15 +1695,15 @@ public class WorldAccess ChunkPos target = new ChunkPos(pos); if (ticket == TicketType.PORTAL) // portal { - cc.level().getChunkSource().addRegionTicket(TicketType.PORTAL, target, radius, pos); + cc.level().getChunkSource().addTicketWithRadius(TicketType.PORTAL, target, radius); } - else if (ticket == TicketType.POST_TELEPORT) // post teleport + else if (ticket == TicketType.ENDER_PEARL) // post teleport { - cc.level().getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, target, radius, 1); + cc.level().getChunkSource().addTicketWithRadius(TicketType.ENDER_PEARL, target, radius); } else { - cc.level().getChunkSource().addRegionTicket(TicketType.UNKNOWN, target, radius, target); + cc.level().getChunkSource().addTicketWithRadius(TicketType.UNKNOWN, target, radius); } return new NumericValue(ticket.timeout()); }); @@ -1763,7 +1762,7 @@ public class WorldAccess if (generator instanceof final NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Registry densityFunctionRegistry = level.registryAccess().registryOrThrow(Registries.DENSITY_FUNCTION); + Registry densityFunctionRegistry = level.registryAccess().lookupOrThrow(Registries.DENSITY_FUNCTION); NoiseRouter router = noiseBasedChunkGenerator.generatorSettings().value().noiseRouter(); DensityFunction densityFunction = switch (densityFunctionQuery) { @@ -1783,7 +1782,7 @@ public class WorldAccess case "vein_ridged" -> router.veinRidged(); case "vein_gap" -> router.veinGap(); default -> { - DensityFunction result = densityFunctionRegistry.get(InputValidator.identifierOf(densityFunctionQuery)); + DensityFunction result = densityFunctionRegistry.getValue(InputValidator.identifierOf(densityFunctionQuery)); if (result == null) { throw new InternalExpressionException("Density function '" + densityFunctionQuery + "' is not defined in the registies."); diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java index 5d0fbabe..78310667 100644 --- a/src/main/java/carpet/script/command/CommandArgument.java +++ b/src/main/java/carpet/script/command/CommandArgument.java @@ -55,7 +55,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import net.minecraft.ChatFormatting; -import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; @@ -163,7 +162,7 @@ public abstract class CommandArgument (c, p) -> StringValue.of(EntityAnchorArgument.getAnchor(c, p).name()), false ), new VanillaUnconfigurableArgument("entitytype", c -> ResourceArgument.resource(c, Registries.ENTITY_TYPE), - (c, p) -> ValueConversions.of(ResourceArgument.getSummonableEntityType(c, p).key()), SuggestionProviders.SUMMONABLE_ENTITIES + (c, p) -> ValueConversions.of(ResourceArgument.getSummonableEntityType(c, p).key()), SuggestionProviders.cast(SuggestionProviders.SUMMONABLE_ENTITIES) ), new VanillaUnconfigurableArgument("floatrange", RangeArgument::floatRange, (c, p) -> ValueConversions.of(c.getArgument(p, MinMaxBounds.Doubles.class)), true @@ -199,23 +198,15 @@ public abstract class CommandArgument ), // operation // not sure if we need it, you have scarpet for that new VanillaUnconfigurableArgument("particle", ParticleArgument::particle, - (c, p) -> ValueConversions.of(ParticleArgument.getParticle(c, p), c.getSource().registryAccess()), (c, b) -> SharedSuggestionProvider.suggestResource(c.getSource().getServer().registryAccess().registryOrThrow(Registries.PARTICLE_TYPE).keySet(), b) + (c, p) -> ValueConversions.of(ParticleArgument.getParticle(c, p), c.getSource().registryAccess()), (c, b) -> SharedSuggestionProvider.suggestResource(c.getSource().getServer().registryAccess().lookupOrThrow(Registries.PARTICLE_TYPE).keySet(), b) ), // resource / identifier section - new VanillaUnconfigurableArgument("recipe", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of(ResourceLocationArgument.getRecipe(c, p).id()), SuggestionProviders.ALL_RECIPES - ), - new VanillaUnconfigurableArgument("advancement", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of(ResourceLocationArgument.getAdvancement(c, p).id()), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getAdvancements().getAllAdvancements().stream().map(AdvancementHolder::id), builder) - ), - new VanillaUnconfigurableArgument("lootcondition", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().reloadableRegistries().getKeys(Registries.LOOT_CONDITION_TYPE), builder) - ), - new VanillaUnconfigurableArgument("loottable", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), LootCommand.SUGGEST_LOOT_TABLE - ), + new VanillaUnconfigurableArgument("recipe", Registries.RECIPE), + new VanillaUnconfigurableArgument("advancement", Registries.ADVANCEMENT), + new VanillaUnconfigurableArgument("lootcondition", Registries.LOOT_CONDITION_TYPE), + new VanillaUnconfigurableArgument("loottable", Registries.LOOT_TABLE), new VanillaUnconfigurableArgument("attribute", Registries.ATTRIBUTE), new VanillaUnconfigurableArgument("boss", ResourceLocationArgument::id, @@ -235,10 +226,10 @@ public abstract class CommandArgument return ValueConversions.of(res.right().get().key()); } return Value.NULL; - }, (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().registryAccess().registryOrThrow(Registries.BIOME).keySet(), builder) + }, (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().registryAccess().lookupOrThrow(Registries.BIOME).keySet(), builder) ), new VanillaUnconfigurableArgument("sound", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_SOUNDS + (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), SuggestionProviders.cast(SuggestionProviders.AVAILABLE_SOUNDS) ), new VanillaUnconfigurableArgument("storekey", ResourceLocationArgument::id, (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getCommandStorage().keys(), builder) @@ -1278,7 +1269,7 @@ public abstract class CommandArgument suffix, c -> ResourceArgument.resource(c, registry), (c, p) -> ValueConversions.of(ResourceArgument.getResource(c, p, registry).key()), - (c, b) -> SharedSuggestionProvider.suggestResource(c.getSource().getServer().registryAccess().registryOrThrow(registry).keySet(), b) + (c, b) -> SharedSuggestionProvider.suggestResource(c.getSource().getServer().registryAccess().lookupOrThrow(registry).keySet(), b) ); } diff --git a/src/main/java/carpet/script/exception/ExpressionException.java b/src/main/java/carpet/script/exception/ExpressionException.java index d0ab1650..a2cdd1f0 100644 --- a/src/main/java/carpet/script/exception/ExpressionException.java +++ b/src/main/java/carpet/script/exception/ExpressionException.java @@ -2,7 +2,7 @@ package carpet.script.exception; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.Tokenizer; +import carpet.script.Token; import carpet.script.external.Carpet; import carpet.script.value.FunctionValue; @@ -16,7 +16,7 @@ import java.util.function.Supplier; public class ExpressionException extends StacklessRuntimeException implements ResolvedException { public final Context context; - public final Tokenizer.Token token; + public final Token token; public final List stack = new ArrayList<>(); private final Supplier lazyMessage; private String cachedMessage = null; @@ -28,15 +28,15 @@ public class ExpressionException extends StacklessRuntimeException implements Re public ExpressionException(Context c, Expression e, String message) { - this(c, e, Tokenizer.Token.NONE, message); + this(c, e, Token.NONE, message); } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message) + public ExpressionException(Context c, Expression e, Token t, String message) { this(c, e, t, message, Collections.emptyList()); } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message, List stack) + public ExpressionException(Context c, Expression e, Token t, String message, List stack) { super("Error"); this.stack.addAll(stack); @@ -45,7 +45,7 @@ public class ExpressionException extends StacklessRuntimeException implements Re context = c; } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, Supplier messageSupplier, List stack) + public ExpressionException(Context c, Expression e, Token t, Supplier messageSupplier, List stack) { super("Error"); this.stack.addAll(stack); @@ -54,7 +54,7 @@ public class ExpressionException extends StacklessRuntimeException implements Re context = c; } - private static List makeError(Expression expr, @Nullable Tokenizer.Token token, String errmessage) + private static List makeError(Expression expr, @Nullable Token token, String errmessage) { List errMsg = new ArrayList<>(); errmessage += expr.getModuleName() == null ? "" : (" in " + expr.getModuleName()); @@ -76,7 +76,7 @@ public class ExpressionException extends StacklessRuntimeException implements Re return errMsg; } - static synchronized String makeMessage(Context c, Expression e, Tokenizer.Token t, String message) throws ExpressionException + static synchronized String makeMessage(Context c, Expression e, Token t, String message) throws ExpressionException { if (c.getErrorSnooper() != null) { diff --git a/src/main/java/carpet/script/exception/InternalExpressionException.java b/src/main/java/carpet/script/exception/InternalExpressionException.java index ef850ed1..c37acde7 100644 --- a/src/main/java/carpet/script/exception/InternalExpressionException.java +++ b/src/main/java/carpet/script/exception/InternalExpressionException.java @@ -2,7 +2,7 @@ package carpet.script.exception; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.Tokenizer; +import carpet.script.Token; import carpet.script.value.FunctionValue; import java.util.ArrayList; @@ -30,7 +30,7 @@ public class InternalExpressionException extends StacklessRuntimeException * @return The new {@link ExpressionException} (or {@link ProcessedThrowStatement}), * depending on the implementation. */ - public ExpressionException promote(Context c, Expression e, Tokenizer.Token token) + public ExpressionException promote(Context c, Expression e, Token token) { return new ExpressionException(c, e, token, getMessage(), stack); } diff --git a/src/main/java/carpet/script/exception/ProcessedThrowStatement.java b/src/main/java/carpet/script/exception/ProcessedThrowStatement.java index 3768550b..7d5cc7fc 100644 --- a/src/main/java/carpet/script/exception/ProcessedThrowStatement.java +++ b/src/main/java/carpet/script/exception/ProcessedThrowStatement.java @@ -4,7 +4,7 @@ import java.util.List; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.Tokenizer.Token; +import carpet.script.Token; import carpet.script.value.FunctionValue; import carpet.script.value.Value; diff --git a/src/main/java/carpet/script/exception/ThrowStatement.java b/src/main/java/carpet/script/exception/ThrowStatement.java index 40cf10b9..67abccb0 100644 --- a/src/main/java/carpet/script/exception/ThrowStatement.java +++ b/src/main/java/carpet/script/exception/ThrowStatement.java @@ -2,7 +2,7 @@ package carpet.script.exception; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.Tokenizer.Token; +import carpet.script.Token; import carpet.script.value.StringValue; import carpet.script.value.Value; diff --git a/src/main/java/carpet/script/external/Carpet.java b/src/main/java/carpet/script/external/Carpet.java index a6fdc1c6..223fc98b 100644 --- a/src/main/java/carpet/script/external/Carpet.java +++ b/src/main/java/carpet/script/external/Carpet.java @@ -85,6 +85,7 @@ public class Carpet return () -> CarpetProfiler.end_current_section(token); } + // not needed in vanilla public static void MinecraftServer_addScriptServer(MinecraftServer server, CarpetScriptServer scriptServer) { ((MinecraftServerInterface) server).addScriptServer(scriptServer); diff --git a/src/main/java/carpet/script/external/Vanilla.java b/src/main/java/carpet/script/external/Vanilla.java index f046ae62..942157b6 100644 --- a/src/main/java/carpet/script/external/Vanilla.java +++ b/src/main/java/carpet/script/external/Vanilla.java @@ -1,26 +1,7 @@ package carpet.script.external; import carpet.CarpetSettings; -import carpet.fakes.BiomeInterface; -import carpet.fakes.BlockPredicateInterface; -import carpet.fakes.BlockStateArgumentInterface; -import carpet.fakes.ChunkTicketManagerInterface; -import carpet.fakes.CommandDispatcherInterface; -import carpet.fakes.EntityInterface; -import carpet.fakes.IngredientInterface; -import carpet.fakes.InventoryBearerInterface; -import carpet.fakes.ItemEntityInterface; -import carpet.fakes.LivingEntityInterface; -import carpet.fakes.MinecraftServerInterface; -import carpet.fakes.MobEntityInterface; -import carpet.fakes.RandomStateVisitorAccessor; -import carpet.fakes.RecipeManagerInterface; -import carpet.fakes.AbstractContainerMenuInterface; -import carpet.fakes.ServerPlayerInterface; -import carpet.fakes.ServerPlayerInteractionManagerInterface; -import carpet.fakes.ServerWorldInterface; -import carpet.fakes.SpawnHelperInnerInterface; -import carpet.fakes.ThreadedAnvilChunkStorageInterface; +import carpet.fakes.*; import carpet.mixins.Objective_scarpetMixin; import carpet.mixins.PoiRecord_scarpetMixin; import carpet.mixins.Scoreboard_scarpetMixin; @@ -39,10 +20,8 @@ import net.fabricmc.loader.api.ModContainer; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.blocks.BlockInput; import net.minecraft.core.BlockPos; -import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.DistanceManager; @@ -51,7 +30,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.server.level.Ticket; import net.minecraft.tags.TagKey; -import net.minecraft.util.SortedArraySet; import net.minecraft.world.Container; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -61,15 +39,10 @@ import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.food.FoodData; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.NaturalSpawner; import net.minecraft.world.level.PotentialCalculator; import net.minecraft.world.level.biome.Biome; @@ -84,7 +57,6 @@ import net.minecraft.world.scores.Objective; import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.criteria.ObjectiveCriteria; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -108,16 +80,6 @@ public class Vanilla return Map.of(); //return ((ThreadedAnvilChunkStorageInterface) chunkMap).regenerateChunkRegion(requestedChunks); } - public static List> Ingredient_getRecipeStacks(Ingredient ingredient) - { - return ((IngredientInterface) (Object) ingredient).getRecipeStacks(); - } - - public static List> RecipeManager_getAllMatching(RecipeManager recipeManager, RecipeType type, ResourceLocation output, RegistryAccess registryAccess) - { - return ((RecipeManagerInterface) recipeManager).getAllMatching(type, output, registryAccess); - } - public static int NaturalSpawner_MAGIC_NUMBER() { return SpawnReporter.MAGIC_NUMBER; @@ -143,9 +105,9 @@ public class Vanilla return ((ServerWorldInterface) world).getWorldPropertiesCM(); } - public static Long2ObjectOpenHashMap>> ChunkTicketManager_getTicketsByPosition(DistanceManager ticketManager) + public static Long2ObjectOpenHashMap> ChunkTicketManager_getTicketsByPosition(DistanceManager ticketManager) { - return ((ChunkTicketManagerInterface) ticketManager).getTicketsByPosition(); + return ((TicketsFetcherInterface) ticketManager).getTicketsByPosition(); } public static DensityFunction.Visitor RandomState_getVisitor(RandomState randomState) @@ -228,11 +190,6 @@ public class Vanilla return ((ServerPlayerInterface) player).isInvalidEntityObject(); } - public static String ServerPlayer_getLanguage(ServerPlayer player) - { - return player.clientInformation().language(); - } - public static GoalSelector Mob_getAI(Mob mob, boolean target) { return ((MobEntityInterface) mob).getAI(target); @@ -343,11 +300,6 @@ public class Vanilla return CommandHelper.canUseCommand(player, CarpetSettings.commandScript); } - public static int MinecraftServer_getFillLimit(MinecraftServer server) - { - return server.getGameRules().getInt(GameRules.RULE_COMMAND_MODIFICATION_BLOCK_LIMIT); - } - public static int PoiRecord_getFreeTickets(PoiRecord record) { return ((PoiRecord_scarpetMixin) record).getFreeTickets(); @@ -358,6 +310,14 @@ public class Vanilla ((PoiRecord_scarpetMixin) record).callAcquireTicket(); } + public static double FoodData_getExhaustion(FoodData foodData) { + return ((FoodDataInterface)foodData).getCMExhaustionLevel(); + } + + public static void FoodData_setExhaustion(FoodData foodData, float exhaustion) { + ((FoodDataInterface)foodData).setExhaustion(exhaustion); + } + public record BlockPredicatePayload(BlockState state, TagKey tagKey, Map properties, CompoundTag tag) { public static BlockPredicatePayload of(Predicate blockPredicate) { diff --git a/src/main/java/carpet/script/external/VanillaClient.java b/src/main/java/carpet/script/external/VanillaClient.java deleted file mode 100644 index 874d15fc..00000000 --- a/src/main/java/carpet/script/external/VanillaClient.java +++ /dev/null @@ -1,13 +0,0 @@ -package carpet.script.external; - -import carpet.mixins.ShulkerBoxAccessMixin; -import net.minecraft.client.model.ShulkerModel; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; - -public class VanillaClient -{ - public static ShulkerModel ShulkerBoxRenderer_model(BlockEntityRenderer shulkerBoxRenderer) { - return ((ShulkerBoxAccessMixin)shulkerBoxRenderer).getModel(); - } -} diff --git a/src/main/java/carpet/script/language/ControlFlow.java b/src/main/java/carpet/script/language/ControlFlow.java index d96d1209..978938aa 100644 --- a/src/main/java/carpet/script/language/ControlFlow.java +++ b/src/main/java/carpet/script/language/ControlFlow.java @@ -22,14 +22,12 @@ public class ControlFlow public static void apply(Expression expression) // public just to get the javadoc right { // needs to be lazy cause of custom contextualization - expression.addLazyBinaryOperator(";", Operators.precedence.get("nextop;"), true, true, t -> Context.Type.VOID, (c, t, lv1, lv2) -> + expression.addLazyBinaryOperator(";", "then", Operators.precedence.get("nextop;"), true, true, t -> Context.Type.VOID, (c, t, lv1, lv2) -> { lv1.evalValue(c, Context.VOID); Value v2 = lv2.evalValue(c, t); return (cc, tt) -> v2; - }); - - expression.addPureLazyFunction("then", -1, t -> Context.Type.VOID, (c, t, lv) -> { + }, (c, t, lv) -> { int imax = lv.size() - 1; for (int i = 0; i < imax; i++) { @@ -38,7 +36,6 @@ public class ControlFlow Value v = lv.get(imax).evalValue(c, t); return (cc, tt) -> v; }); - expression.addFunctionalEquivalence(";", "then"); // obvious lazy due to conditional evaluation of arguments diff --git a/src/main/java/carpet/script/language/DataStructures.java b/src/main/java/carpet/script/language/DataStructures.java index 24adb642..01fa6c80 100644 --- a/src/main/java/carpet/script/language/DataStructures.java +++ b/src/main/java/carpet/script/language/DataStructures.java @@ -188,7 +188,7 @@ public class DataStructures ? ListValue.wrap(map.getMap().entrySet().stream().map(p -> ListValue.of(p.getKey(), p.getValue()))) : Value.NULL); - expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"), true, true, false, (ctx, t, container, address) -> + expression.addBinaryContextOperator(":", "element", Operators.precedence.get("attribute~:"), true, true, false, (ctx, t, container, address) -> { if (container instanceof final LContainerValue lcv) { diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 8bc29712..2c544be3 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -4,7 +4,7 @@ import carpet.script.Context; import carpet.script.Expression; import carpet.script.Fluff; import carpet.script.LazyValue; -import carpet.script.Tokenizer; +import carpet.script.Token; import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; @@ -45,7 +45,7 @@ public class Functions expression.addCustomFunction("call", new Fluff.AbstractLazyFunction(-1, "call") { @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression expr, Tokenizer.Token tok, List lv) + public LazyValue lazyEval(Context c, Context.Type t, Expression expr, Token tok, List lv) { if (lv.isEmpty()) { @@ -126,7 +126,7 @@ public class Functions //assigns const procedure to the lhs, returning its previous value // must be lazy due to RHS being an expression to save to execute - expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->"), false, false, (c, type, e, t, lv1, lv2) -> + expression.addLazyBinaryOperatorWithDelegation("->", "define", Operators.precedence.get("def->"), false, false, (c, type, e, t, lv1, lv2) -> { if (type == Context.MAPDEF) { diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index a1c2d1a2..f097ae8d 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -41,8 +41,7 @@ public class Operators public static void apply(Expression expression) { - expression.addBinaryOperator("+", precedence.get("addition+-"), true, Value::add); - expression.addFunction("sum", lv -> { + expression.addBinaryOperator("+", "sum", precedence.get("addition+-"), true, Value::add, lv -> { int size = lv.size(); if (size == 0) { @@ -55,10 +54,8 @@ public class Operators } return accumulator; }); - expression.addFunctionalEquivalence("+", "sum"); - expression.addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract); - expression.addFunction("difference", lv -> { + expression.addBinaryOperator("-", "difference", precedence.get("addition+-"), true, Value::subtract, lv -> { int size = lv.size(); if (size == 0) { @@ -71,10 +68,8 @@ public class Operators } return accumulator; }); - expression.addFunctionalEquivalence("-", "difference"); - expression.addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply); - expression.addFunction("product", lv -> { + expression.addBinaryOperator("*", "product", precedence.get("multiplication*/%"), true, Value::multiply, lv -> { int size = lv.size(); if (size == 0) { @@ -87,10 +82,8 @@ public class Operators } return accumulator; }); - expression.addFunctionalEquivalence("*", "product"); - expression.addBinaryOperator("/", precedence.get("multiplication*/%"), true, Value::divide); - expression.addFunction("quotient", lv -> { + expression.addBinaryOperator("/", "quotient", precedence.get("multiplication*/%"), true, Value::divide, lv -> { int size = lv.size(); if (size == 0) { @@ -103,11 +96,11 @@ public class Operators } return accumulator; }); - expression.addFunctionalEquivalence("/", "quotient"); - expression.addBinaryOperator("%", precedence.get("multiplication*/%"), true, (v1, v2) -> + expression.addBinaryOperator("%", "modulo", precedence.get("multiplication*/%"), true, (v1, v2) -> NumericValue.asNumber(v1).mod(NumericValue.asNumber(v2))); - expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) -> + + expression.addBinaryOperator("^", "exponent", precedence.get("exponent^"), false, (v1, v2) -> new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble()))); expression.addFunction("bitwise_and", lv -> { @@ -153,13 +146,11 @@ public class Operators }); // lazy cause RHS is only conditional - expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> + expression.addLazyBinaryOperator("&&", "and", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> { // todo check how is optimizations going Value v1 = lv1.evalValue(c, Context.BOOLEAN); return v1.getBoolean() ? lv2 : ((cc, tt) -> v1); - }); - - expression.addPureLazyFunction("and", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> { + }, (c, t, lv) -> { int last = lv.size() - 1; if (last == -1) { @@ -168,7 +159,7 @@ public class Operators for (LazyValue l : lv.subList(0, last)) { Value val = l.evalValue(c, Context.Type.BOOLEAN); - if (val instanceof final FunctionUnpackedArgumentsValue fuav) + if (val instanceof FunctionUnpackedArgumentsValue fuav) { for (Value it : fuav) { @@ -188,16 +179,13 @@ public class Operators } return lv.get(last); }); - expression.addFunctionalEquivalence("&&", "and"); // lazy cause RHS is only conditional - expression.addLazyBinaryOperator("||", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> + expression.addLazyBinaryOperator("||", "or", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.BOOLEAN); return v1.getBoolean() ? ((cc, tt) -> v1) : lv2; - }); - - expression.addPureLazyFunction("or", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> { + }, (c, t, lv) -> { int last = lv.size() - 1; if (last == -1) { @@ -226,13 +214,10 @@ public class Operators } return lv.get(last); }); - expression.addFunctionalEquivalence("||", "or"); - expression.addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in); + expression.addBinaryOperator("~", "match", precedence.get("attribute~:"), true, Value::in); - expression.addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) -> - BooleanValue.of(v1.compareTo(v2) > 0)); - expression.addFunction("decreasing", lv -> { + expression.addBinaryOperator(">", "decreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) > 0), lv -> { int size = lv.size(); if (size < 2) { @@ -249,11 +234,8 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence(">", "decreasing"); - expression.addBinaryOperator(">=", precedence.get("compare>=><=<"), false, (v1, v2) -> - BooleanValue.of(v1.compareTo(v2) >= 0)); - expression.addFunction("nonincreasing", lv -> { + expression.addBinaryOperator(">=", "nonincreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) >= 0), lv -> { int size = lv.size(); if (size < 2) { @@ -270,11 +252,8 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence(">=", "nonincreasing"); - expression.addBinaryOperator("<", precedence.get("compare>=><=<"), false, (v1, v2) -> - BooleanValue.of(v1.compareTo(v2) < 0)); - expression.addFunction("increasing", lv -> { + expression.addBinaryOperator("<", "increasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) < 0), lv -> { int size = lv.size(); if (size < 2) { @@ -291,11 +270,8 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence("<", "increasing"); - expression.addBinaryOperator("<=", precedence.get("compare>=><=<"), false, (v1, v2) -> - BooleanValue.of(v1.compareTo(v2) <= 0)); - expression.addFunction("nondecreasing", lv -> { + expression.addBinaryOperator("<=", "nondecreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) <= 0), lv -> { int size = lv.size(); if (size < 2) { @@ -312,7 +288,7 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence("<=", "nondecreasing"); + expression.addMathematicalBinaryIntFunction("bitwise_shift_left", (num, amount) -> num << amount); expression.addMathematicalBinaryIntFunction("bitwise_shift_right", (num, amount) -> num >>> amount); expression.addMathematicalBinaryIntFunction("bitwise_arithmetic_shift_right", (num, amount) -> num >> amount); @@ -326,9 +302,7 @@ public class Operators expression.addMathematicalUnaryIntFunction("double_to_long_bits", Double::doubleToLongBits); expression.addUnaryFunction("long_to_double_bits", v -> new NumericValue(Double.longBitsToDouble(NumericValue.asNumber(v).getLong()))); - expression.addBinaryOperator("==", precedence.get("equal==!="), false, (v1, v2) -> - v1.equals(v2) ? Value.TRUE : Value.FALSE); - expression.addFunction("equal", lv -> { + expression.addBinaryOperator("==", "equal", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.TRUE : Value.FALSE, lv -> { int size = lv.size(); if (size < 2) { @@ -345,10 +319,8 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence("==", "equal"); - expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) -> - v1.equals(v2) ? Value.FALSE : Value.TRUE); - expression.addFunction("unique", lv -> { + + expression.addBinaryOperator("!=", "unique", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.FALSE : Value.TRUE, lv -> { int size = lv.size(); if (size < 2) { @@ -367,10 +339,9 @@ public class Operators } return Value.TRUE; }); - expression.addFunctionalEquivalence("!=", "unique"); // lazy cause of assignment which is non-trivial - expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> + expression.addLazyBinaryOperator("=", "assign", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); Value v2 = lv2.evalValue(c); @@ -423,7 +394,7 @@ public class Operators }); // lazy due to assignment - expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> + expression.addLazyBinaryOperator("+=", "append", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); Value v2 = lv2.evalValue(c); @@ -492,7 +463,7 @@ public class Operators return boundedLHS; }); - expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) -> + expression.addBinaryContextOperator("<>", "swap", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) -> { if (v1 instanceof final ListValue.ListConstructorValue lcv1 && v2 instanceof final ListValue.ListConstructorValue lcv2) { @@ -540,17 +511,17 @@ public class Operators return lval; }); - expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite()); + expression.addUnaryOperator("-", "opposite", false, v -> NumericValue.asNumber(v).opposite()); - expression.addUnaryOperator("+", false, NumericValue::asNumber); + expression.addUnaryOperator("+", "identity", false, NumericValue::asNumber); // could be non-lazy, but who cares - its a small one. - expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, true, x -> Context.Type.BOOLEAN, (c, t, lv) -> + expression.addLazyUnaryOperator("!", "not", precedence.get("unary+-!..."), false, true, x -> Context.Type.BOOLEAN, (c, t, lv) -> lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt) -> Value.FALSE : (cc, tt) -> Value.TRUE ); // might need context boolean // lazy because of typed evaluation of the argument - expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, true, t -> t == Context.Type.LOCALIZATION ? Context.NONE : t, (c, t, lv) -> + expression.addLazyUnaryOperator("...", "unpack", Operators.precedence.get("unary+-!..."), false, true, t -> t == Context.Type.LOCALIZATION ? Context.NONE : t, (c, t, lv) -> { if (t == Context.LOCALIZATION) { diff --git a/src/main/java/carpet/script/utils/AppStoreManager.java b/src/main/java/carpet/script/utils/AppStoreManager.java index 963cd549..f7536faa 100644 --- a/src/main/java/carpet/script/utils/AppStoreManager.java +++ b/src/main/java/carpet/script/utils/AppStoreManager.java @@ -2,6 +2,7 @@ package carpet.script.utils; import carpet.script.CarpetScriptHost; import carpet.script.CarpetScriptServer; +import carpet.script.Expression; import carpet.script.exception.InternalExpressionException; import carpet.script.external.Carpet; import carpet.script.external.Vanilla; @@ -283,8 +284,7 @@ public class AppStoreManager { return 0; } - boolean success = Vanilla.MinecraftServer_getScriptServer(source.getServer()).addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source()); - return success ? 1 : 0; + return Vanilla.MinecraftServer_getScriptServer(source.getServer()).addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source(), Expression.LoadOverride.DEFAULT); } /** diff --git a/src/main/java/carpet/script/utils/BiomeInfo.java b/src/main/java/carpet/script/utils/BiomeInfo.java index 4cd07760..aa8c39cd 100644 --- a/src/main/java/carpet/script/utils/BiomeInfo.java +++ b/src/main/java/carpet/script/utils/BiomeInfo.java @@ -23,7 +23,7 @@ public class BiomeInfo { public static final Map> biomeFeatures = new HashMap<>() {{ - put("tags", (w, b) -> ListValue.wrap(w.registryAccess().registryOrThrow(Registries.BIOME).getTags().filter(p -> p.getSecond().stream().anyMatch(h -> h.value() == b)).map(p -> p.getFirst().location()).map(ValueConversions::of))); + put("tags", (w, b) -> ListValue.wrap(w.registryAccess().lookupOrThrow(Registries.BIOME).getTags().filter(p -> p.stream().anyMatch(h -> h.value() == b)).map(ValueConversions::of))); put("temperature", (w, b) -> NumericValue.of(b.getBaseTemperature())); put("fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFogColor())); put("foliage_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFoliageColorOverride().orElse(4764952))); // client Biome.getDefaultFoliageColor @@ -31,9 +31,9 @@ public class BiomeInfo put("water_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getWaterColor())); put("water_fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getWaterFogColor())); put("humidity", (w, b) -> NumericValue.of(Vanilla.Biome_getClimateSettings(b).downfall())); - put("precipitation", (w, b) -> StringValue.of(b.getPrecipitationAt(new BlockPos(0, w.getSeaLevel(), 0)).name().toLowerCase(Locale.ROOT))); + put("precipitation", (w, b) -> StringValue.of(b.getPrecipitationAt(new BlockPos(0, w.getSeaLevel(), 0), w.getSeaLevel()).name().toLowerCase(Locale.ROOT))); put("features", (w, b) -> { - Registry> registry = w.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); + Registry> registry = w.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE); return ListValue.wrap( b.getGenerationSettings().features().stream().map(step -> ListValue.wrap(step.stream().map(cfp -> diff --git a/src/main/java/carpet/script/utils/EntityTools.java b/src/main/java/carpet/script/utils/EntityTools.java index 5849e50a..0b7e1cb6 100644 --- a/src/main/java/carpet/script/utils/EntityTools.java +++ b/src/main/java/carpet/script/utils/EntityTools.java @@ -12,7 +12,7 @@ public class EntityTools */ public static void genericJump(Entity e) { - if (!e.onGround() && !e.isInWaterOrBubble() && !e.isInLava()) + if (!e.onGround() && !e.isInLiquid()) { return; } diff --git a/src/main/java/carpet/script/utils/FeatureGenerator.java b/src/main/java/carpet/script/utils/FeatureGenerator.java index 32f84a32..79a5e766 100644 --- a/src/main/java/carpet/script/utils/FeatureGenerator.java +++ b/src/main/java/carpet/script/utils/FeatureGenerator.java @@ -76,13 +76,13 @@ public class FeatureGenerator return custom.apply(world).plop(world, pos); } ResourceLocation id = ResourceLocation.parse(featureName); - Structure structure = world.registryAccess().registryOrThrow(Registries.STRUCTURE).get(id); + Structure structure = world.registryAccess().lookupOrThrow(Registries.STRUCTURE).getValue(id); if (structure != null) { return plopAnywhere(structure, world, pos, world.getChunkSource().getGenerator(), false); } - ConfiguredFeature configuredFeature = world.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).get(id); + ConfiguredFeature configuredFeature = world.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(id); if (configuredFeature != null) { ThreadLocal checks = Vanilla.skipGenerationChecks(world); @@ -96,7 +96,7 @@ public class FeatureGenerator checks.set(false); } } - Optional> structureType = world.registryAccess().registryOrThrow(Registries.STRUCTURE_TYPE).getOptional(id); + Optional> structureType = world.registryAccess().lookupOrThrow(Registries.STRUCTURE_TYPE).getOptional(id); if (structureType.isPresent()) { Structure configuredStandard = getDefaultFeature(structureType.get(), world, pos); @@ -105,7 +105,7 @@ public class FeatureGenerator return plopAnywhere(configuredStandard, world, pos, world.getChunkSource().getGenerator(), false); } } - Feature feature = world.registryAccess().registryOrThrow(Registries.FEATURE).get(id); + Feature feature = world.registryAccess().lookupOrThrow(Registries.FEATURE).getValue(id); if (feature != null) { ConfiguredFeature configuredStandard = getDefaultFeature(feature, world, pos, true); @@ -130,12 +130,12 @@ public class FeatureGenerator public static Structure resolveConfiguredStructure(String name, ServerLevel world, BlockPos pos) { ResourceLocation id = ResourceLocation.parse(name); - Structure configuredStructureFeature = world.registryAccess().registryOrThrow(Registries.STRUCTURE).get(id); + Structure configuredStructureFeature = world.registryAccess().lookupOrThrow(Registries.STRUCTURE).getValue(id); if (configuredStructureFeature != null) { return configuredStructureFeature; } - StructureType structureFeature = world.registryAccess().registryOrThrow(Registries.STRUCTURE_TYPE).get(id); + StructureType structureFeature = world.registryAccess().lookupOrThrow(Registries.STRUCTURE_TYPE).getValue(id); if (structureFeature == null) { return null; @@ -197,7 +197,7 @@ public class FeatureGenerator // TODO allow old types, like vaillage, or bastion Holder existingBiome = world.getBiome(pos); Structure result = null; - for (Structure confstr : world.registryAccess().registryOrThrow(Registries.STRUCTURE).entrySet().stream(). + for (Structure confstr : world.registryAccess().lookupOrThrow(Registries.STRUCTURE).entrySet().stream(). filter(cS -> cS.getValue().type() == structure).map(Map.Entry::getValue).toList()) { result = confstr; @@ -226,7 +226,7 @@ public class FeatureGenerator { return null; } - return world.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).entrySet().stream(). + return world.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).entrySet().stream(). filter(cS -> cS.getValue().feature() == feature). findFirst().map(Map.Entry::getValue).orElse(null); } @@ -261,7 +261,7 @@ public class FeatureGenerator } else { - StructureStart filledStructure = structure.generate( + StructureStart filledStructure = structure.generate(Holder.direct(structure), world.dimension(), world.registryAccess(), generator, generator.getBiomeSource(), seed, world.getStructureManager(), world.getSeed(), chunkPos, 0, world, structureBiomes::contains); if (filledStructure != null && filledStructure.isValid()) @@ -304,8 +304,7 @@ public class FeatureGenerator return spawnCustomStructure( - new JigsawStructure(new Structure.StructureSettings( - l.registryAccess().registryOrThrow(Registries.BIOME).getOrCreateTag(BiomeTags.HAS_BASTION_REMNANT), + new JigsawStructure(new Structure.StructureSettings(l.registryAccess().lookup(Registries.BIOME).orElseThrow().getOrThrow(BiomeTags.HAS_BASTION_REMNANT), Map.of(), GenerationStep.Decoration.SURFACE_STRUCTURES, TerrainAdjustment.NONE @@ -334,7 +333,7 @@ public class FeatureGenerator return spawnCustomStructure( new JigsawStructure(new Structure.StructureSettings( - l.registryAccess().registryOrThrow(Registries.BIOME).getOrCreateTag(BiomeTags.HAS_BASTION_REMNANT), + l.registryAccess().lookup(Registries.BIOME).orElseThrow().getOrThrow(BiomeTags.HAS_BASTION_REMNANT), Map.of(), GenerationStep.Decoration.SURFACE_STRUCTURES, TerrainAdjustment.NONE @@ -363,7 +362,7 @@ public class FeatureGenerator return spawnCustomStructure( new JigsawStructure(new Structure.StructureSettings( - l.registryAccess().registryOrThrow(Registries.BIOME).getOrCreateTag(BiomeTags.HAS_BASTION_REMNANT), + l.registryAccess().lookup(Registries.BIOME).orElseThrow().getOrThrow(BiomeTags.HAS_BASTION_REMNANT), Map.of(), GenerationStep.Decoration.SURFACE_STRUCTURES, TerrainAdjustment.NONE @@ -392,7 +391,7 @@ public class FeatureGenerator return spawnCustomStructure( new JigsawStructure(new Structure.StructureSettings( - l.registryAccess().registryOrThrow(Registries.BIOME).getOrCreateTag(BiomeTags.HAS_BASTION_REMNANT), + l.registryAccess().lookup(Registries.BIOME).orElseThrow().getOrThrow(BiomeTags.HAS_BASTION_REMNANT), Map.of(), GenerationStep.Decoration.SURFACE_STRUCTURES, TerrainAdjustment.NONE @@ -419,7 +418,7 @@ public class FeatureGenerator checks.set(true); try { - StructureStart start = structure.generate(world.registryAccess(), generator, generator.getBiomeSource(), world.getChunkSource().randomState(), world.getStructureManager(), world.getSeed(), new ChunkPos(pos), 0, world, b -> true); + StructureStart start = structure.generate(Holder.direct(structure), world.dimension(), world.registryAccess(), generator, generator.getBiomeSource(), world.getChunkSource().randomState(), world.getStructureManager(), world.getSeed(), new ChunkPos(pos), 0, world, b -> true); if (start == StructureStart.INVALID_START) { return false; @@ -435,7 +434,7 @@ public class FeatureGenerator if (!wireOnly) { - Registry registry3 = world.registryAccess().registryOrThrow(Registries.STRUCTURE); + Registry registry3 = world.registryAccess().lookupOrThrow(Registries.STRUCTURE); world.setCurrentlyGenerating(() -> { Objects.requireNonNull(structure); return registry3.getResourceKey(structure).map(Object::toString).orElseGet(structure::toString); diff --git a/src/main/java/carpet/script/utils/RecipeHelper.java b/src/main/java/carpet/script/utils/RecipeHelper.java new file mode 100644 index 00000000..94c484d0 --- /dev/null +++ b/src/main/java/carpet/script/utils/RecipeHelper.java @@ -0,0 +1,61 @@ +package carpet.script.utils; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.context.ContextMap; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; +import net.minecraft.world.level.Level; + +import java.util.ArrayList; +import java.util.List; + +public class RecipeHelper +{ + public static List> getRecipesForOutput(RecipeManager recipeManager, RecipeType type, ResourceLocation id, Level level) + { + List> results = new ArrayList<>(); + + + ContextMap context = SlotDisplayContext.fromLevel(level); + recipeManager.getRecipes().forEach(r -> { + if (r.value().getType() == type) + { + for (RecipeDisplay recipeDisplay : r.value().display()) + { + recipeDisplay.result().resolveForStacks(context).forEach(stack -> { + if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id)) + { + results.add(r.value()); + } + }); + } + } + }); + return results; + } + + public static List> getRecipesForOutput(RecipeManager recipeManager, ResourceLocation id, Level level) + { + List> results = new ArrayList<>(); + + ContextMap context = SlotDisplayContext.fromLevel(level); + recipeManager.getRecipes().forEach(r -> { + for (RecipeDisplay recipeDisplay : r.value().display()) + { + recipeDisplay.result().resolveForStacks(context).forEach(stack -> { + if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id)) + { + results.add(r.value()); + } + }); + } + + }); + return results; + } +} diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index ab622bd4..d37ae3f8 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.ByteTag; @@ -34,16 +35,19 @@ import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.nbt.NumericTag; import net.minecraft.network.chat.Component; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; @@ -236,7 +240,7 @@ public class ShapeDispatcher public static ExpiringShape fromTag(CompoundTag tag, Level level) { Map options = new HashMap<>(); - for (String key : tag.getAllKeys()) + for (String key : tag.keySet()) { Param decoder = Param.of.get(key); if (decoder == null) @@ -250,7 +254,7 @@ public class ShapeDispatcher Value shapeValue = options.get("shape"); if (shapeValue == null) { - CarpetScriptServer.LOG.info("Shape id missing in " + String.join(", ", tag.getAllKeys())); + CarpetScriptServer.LOG.info("Shape id missing in " + String.join(", ", tag.keySet())); return null; } BiFunction, RegistryAccess, ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); @@ -433,10 +437,8 @@ public class ShapeDispatcher protected ParticleOptions replacementParticle(RegistryAccess regs) { - String particleName = fa == 0 ? - String.format(Locale.ROOT, "dust %.1f %.1f %.1f 1.0", r, g, b) : - String.format(Locale.ROOT, "dust %.1f %.1f %.1f 1.0", fr, fg, fb); - return getParticleData(particleName, regs); + boolean bg = fa == 0; + return new DustParticleOptions(ARGB.colorFromFloat(1.0f, (bg ?r:fr), (bg ?r:fr), (bg ?r:fr)), 1); } @@ -724,7 +726,7 @@ public class ShapeDispatcher } else { - this.item = ItemStack.parseOptional(regs, ((NBTSerializableValue) options.get("item")).getCompoundTag()); + this.item = ItemStack.CODEC.parse(regs.createSerializationContext(NbtOps.INSTANCE), ((NBTSerializableValue) options.get("item")).getCompoundTag() ).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s)); } blockLight = NumericValue.asNumber(options.getOrDefault("blocklight", optional.get("blocklight"))).getInt(); if (blockLight > 15) @@ -760,7 +762,7 @@ public class ShapeDispatcher { return p -> { ParticleOptions particle; - Registry blocks = p.getServer().registryAccess().registryOrThrow(Registries.BLOCK); + Registry blocks = p.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); if (this.isitem) { if (Block.byItem(this.item.getItem()).defaultBlockState().isAir()) @@ -775,7 +777,7 @@ public class ShapeDispatcher } Vec3 v = relativiseRender(p.level(), this.pos, 0); - p.serverLevel().sendParticles(p, particle, true, v.x, v.y, v.z, 1, 0.0, 0.0, 0.0, 0.0); + p.level().sendParticles(p, particle, true, true, v.x, v.y, v.z, 1, 0.0, 0.0, 0.0, 0.0); }; } @@ -1067,10 +1069,10 @@ public class ShapeDispatcher } if (fa > 0.0f) { - ParticleOptions locparticledata = getParticleData(String.format(Locale.ROOT, "dust %.1f %.1f %.1f %.1f", fr, fg, fb, fa), p.level().registryAccess()); + ParticleOptions locparticledata = new DustParticleOptions(ARGB.colorFromFloat(1.0f, fr, fg, fb), 1); for (Vec3 v : getAlterPoint(p)) { - p.serverLevel().sendParticles(p, locparticledata, true, + p.level().sendParticles(p, locparticledata, true, true, v.x, v.y, v.z, 1, 0.0, 0.0, 0.0, 0.0); } @@ -1280,7 +1282,7 @@ public class ShapeDispatcher { int partno = Math.min(1000, 20 * subdivisions); RandomSource rand = p.level().getRandom(); - ServerLevel world = p.serverLevel(); + ServerLevel world = p.level(); ParticleOptions particle = replacementParticle(world.registryAccess()); Vec3 ccenter = relativiseRender(world, center, 0); @@ -1297,7 +1299,7 @@ public class ShapeDispatcher double x = radius * Mth.cos(theta) * Mth.cos(phi); double y = radius * Mth.cos(theta) * Mth.sin(phi); double z = radius * Mth.sin(theta); - world.sendParticles(p, particle, true, + world.sendParticles(p, particle, true, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); } @@ -1377,7 +1379,7 @@ public class ShapeDispatcher { int partno = (int) Math.min(1000, Math.sqrt(20 * subdivisions * (1 + height))); RandomSource rand = p.level().getRandom(); - ServerLevel world = p.serverLevel(); + ServerLevel world = p.level(); ParticleOptions particle = replacementParticle(world.registryAccess()); Vec3 ccenter = relativiseRender(world, center, 0); @@ -1395,7 +1397,7 @@ public class ShapeDispatcher double x = radius * Mth.cos(phi); double y = d; double z = radius * Mth.sin(phi); - world.sendParticles(p, particle, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); + world.sendParticles(p, particle, true, true,x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); } } else if (axis == Direction.Axis.X) @@ -1407,7 +1409,7 @@ public class ShapeDispatcher double x = d; double y = radius * Mth.cos(phi); double z = radius * Mth.sin(phi); - world.sendParticles(p, particle, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); + world.sendParticles(p, particle, true, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); } } else // Z @@ -1419,7 +1421,7 @@ public class ShapeDispatcher double x = radius * Mth.sin(phi); double y = radius * Mth.cos(phi); double z = d; - world.sendParticles(p, particle, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); + world.sendParticles(p, particle, true, true, x + ccx, y + ccy, z + ccz, 1, 0.0, 0.0, 0.0, 0.0); } } }; @@ -1557,11 +1559,11 @@ public class ShapeDispatcher { if (tag instanceof final ListTag list) { - return ListValue.wrap(list.stream().map(x -> BooleanValue.of(((NumericTag) x).getAsNumber().doubleValue() != 0))); + return ListValue.wrap(list.stream().map(x -> BooleanValue.of(((NumericTag) x).doubleValue() != 0))); } if (tag instanceof final ByteTag booltag) { - return BooleanValue.of(booltag.getAsByte() != 0); + return BooleanValue.of(booltag.byteValue() != 0); } return Value.NULL; } @@ -1597,7 +1599,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new StringValue(tag.getAsString()); + return new StringValue(tag.asString().get()); } } @@ -1641,9 +1643,9 @@ public class ShapeDispatcher { BlockState bs = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), (CompoundTag) tag); CompoundTag compoundTag2 = null; - if (((CompoundTag) tag).contains("TileEntityData", 10)) + if (((CompoundTag) tag).contains("TileEntityData")) { - compoundTag2 = ((CompoundTag) tag).getCompound("TileEntityData"); + compoundTag2 = ((CompoundTag) tag).getCompound("TileEntityData").get(); } return new BlockValue(bs, compoundTag2); } @@ -1661,7 +1663,7 @@ public class ShapeDispatcher public Value validate(Map options, MinecraftServer server, Value value) { ItemStack item = ValueConversions.getItemStackFromValue(value, true, server.registryAccess()); - return new NBTSerializableValue(item.saveOptional(server.registryAccess())); + return new NBTSerializableValue(ItemStack.CODEC.encodeStart(server.registryAccess().createSerializationContext(NbtOps.INSTANCE), item).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s))); } @Override @@ -1716,13 +1718,13 @@ public class ShapeDispatcher { value = new FormattedTextValue(Component.literal(value.getString())); } - return StringTag.valueOf(((FormattedTextValue) value).serialize(regs)); + return ((FormattedTextValue) value).serialize(regs); } @Override public Value decode(Tag tag, Level level) { - return FormattedTextValue.deserialize(tag.getAsString(), level.registryAccess()); + return FormattedTextValue.deserialize(tag, level.registryAccess()); } } @@ -1816,7 +1818,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return BooleanValue.of(((ByteTag) tag).getAsByte() > 0); + return BooleanValue.of(((ByteTag) tag).byteValue() > 0); } } @@ -1830,7 +1832,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((FloatTag) tag).getAsFloat()); + return new NumericValue(((FloatTag) tag).floatValue()); } @Override @@ -1869,7 +1871,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((FloatTag) tag).getAsFloat()); + return new NumericValue(((FloatTag) tag).floatValue()); } @Override @@ -1890,7 +1892,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((IntTag) tag).getAsInt()); + return new NumericValue(((IntTag) tag).intValue()); } @Override @@ -1911,7 +1913,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((IntTag) tag).getAsInt()); + return new NumericValue(((IntTag) tag).intValue()); } @Override @@ -1942,7 +1944,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((FloatTag) tag).getAsFloat()); + return new NumericValue(((FloatTag) tag).floatValue()); } @Override @@ -2034,9 +2036,9 @@ public class ShapeDispatcher { ListTag ctag = (ListTag) tag; return ListValue.of( - new NumericValue(ctag.getDouble(0)), - new NumericValue(ctag.getDouble(1)), - new NumericValue(ctag.getDouble(2)) + new NumericValue(ctag.getDouble(0).orElseThrow()), + new NumericValue(ctag.getDouble(1).orElseThrow()), + new NumericValue(ctag.getDouble(2).orElseThrow()) ); } @@ -2081,11 +2083,11 @@ public class ShapeDispatcher List points = new ArrayList<>(); for (int i = 0, ll = ltag.size(); i < ll; i++) { - ListTag ptag = ltag.getList(i); + ListTag ptag = ltag.getList(i).orElseThrow(); points.add(ListValue.of( - new NumericValue(ptag.getDouble(0)), - new NumericValue(ptag.getDouble(1)), - new NumericValue(ptag.getDouble(2)) + new NumericValue(ptag.getDouble(0).orElseThrow()), + new NumericValue(ptag.getDouble(1).orElseThrow()), + new NumericValue(ptag.getDouble(2).orElseThrow()) )); } return ListValue.wrap(points); @@ -2120,7 +2122,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((IntTag) tag).getAsInt()); + return new NumericValue(((IntTag) tag).intValue()); } @Override @@ -2162,7 +2164,7 @@ public class ShapeDispatcher @Override public Value decode(Tag tag, Level level) { - return new NumericValue(((IntTag) tag).getAsInt()); + return new NumericValue(((IntTag) tag).intValue()); } } @@ -2183,13 +2185,13 @@ public class ShapeDispatcher int parts = 0; for (ServerPlayer player : playerList) { - ServerLevel world = player.serverLevel(); - world.sendParticles(player, particle, true, + ServerLevel world = player.level(); + world.sendParticles(player, particle, true, true, (towards.x) / 2 + from.x, (towards.y) / 2 + from.y, (towards.z) / 2 + from.z, particles / 3, towards.x / 6, towards.y / 6, towards.z / 6, 0.0); - world.sendParticles(player, particle, true, + world.sendParticles(player, particle, true, true, from.x, from.y, from.z, 1, 0.0, 0.0, 0.0, 0.0); - world.sendParticles(player, particle, true, + world.sendParticles(player, particle, true, true, to.x, to.y, to.z, 1, 0.0, 0.0, 0.0, 0.0); parts += particles / 3 + 2; } @@ -2200,11 +2202,11 @@ public class ShapeDispatcher int dev = 2 * divider; for (ServerPlayer player : playerList) { - ServerLevel world = player.serverLevel(); - world.sendParticles(player, particle, true, + ServerLevel world = player.level(); + world.sendParticles(player, particle, true, true, (towards.x) / center + from.x, (towards.y) / center + from.y, (towards.z) / center + from.z, particles / divider, towards.x / dev, towards.y / dev, towards.z / dev, 0.0); - world.sendParticles(player, particle, true, + world.sendParticles(player, particle, true, true, (towards.x) * (1.0 - 1.0 / center) + from.x, (towards.y) * (1.0 - 1.0 / center) + from.y, (towards.z) * (1.0 - 1.0 / center) + from.z, particles / divider, towards.x / dev, towards.y / dev, towards.z / dev, 0.0); } @@ -2232,7 +2234,7 @@ public class ShapeDispatcher Vec3 at = from.add(towards.scale(rand.nextDouble())); for (ServerPlayer player : players) { - player.serverLevel().sendParticles(player, particle, true, + player.level().sendParticles(player, particle, true, true, at.x, at.y, at.z, 1, 0.0, 0.0, 0.0, 0.0); pcount++; @@ -2253,7 +2255,7 @@ public class ShapeDispatcher { for (ServerPlayer player : players) { - player.serverLevel().sendParticles(player, particle, true, + player.level().sendParticles(player, particle, true, true, delta.x + from.x, delta.y + from.y, delta.z + from.z, 1, 0.0, 0.0, 0.0, 0.0); pcount++; diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 7d6edd6f..53892aab 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -2,17 +2,16 @@ package carpet.script.utils; import carpet.script.CarpetScriptServer; import carpet.script.external.Carpet; -import carpet.script.external.VanillaClient; import carpet.script.utils.shapes.ShapeDirection; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.BufferUploader; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexConsumer; +//import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat.Mode; import com.mojang.math.Axis; @@ -26,35 +25,29 @@ import java.util.function.BiFunction; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.model.ShulkerModel; -import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.resources.model.Material; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.resources.ResourceKey; import net.minecraft.util.Mth; -import net.minecraft.world.item.DyeColor; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueInput; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.joml.Matrix4fStack; @@ -129,18 +122,18 @@ public class ShapesRenderer return; } long currentTime = client.level.getGameTime(); - RenderSystem.enableDepthTest(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); - RenderSystem.depthFunc(515); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); + ////RenderSystem.enableDepthTest(); + //RenderSystem.setShader(CoreShaders.POSITION_COLOR); + ////RenderSystem.depthFunc(515); + ////RenderSystem.enableBlend(); + ////RenderSystem.defaultBlendFunc(); // too bright //RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO); // meh //RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.disableCull(); - RenderSystem.depthMask(false); + ////RenderSystem.disableCull(); + ////RenderSystem.depthMask(false); //RenderSystem.polygonOffset(-3f, -3f); //RenderSystem.enablePolygonOffset(); @@ -160,7 +153,6 @@ public class ShapesRenderer Matrix4fStack matrixStack = RenderSystem.getModelViewStack(); matrixStack.pushMatrix(); matrixStack.mul(matrices.last().pose()); - RenderSystem.applyModelViewMatrix(); // lines RenderSystem.lineWidth(0.5F); @@ -180,7 +172,6 @@ public class ShapesRenderer }); RenderSystem.lineWidth(1.0F); matrixStack.popMatrix(); - RenderSystem.applyModelViewMatrix(); } if (!labels.isEmpty()) @@ -195,10 +186,10 @@ public class ShapesRenderer } }); } - RenderSystem.enableCull(); - RenderSystem.depthMask(true); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); + ////RenderSystem.enableCull(); + ////RenderSystem.depthMask(true); + ////RenderSystem.enableBlend(); + ////RenderSystem.defaultBlendFunc(); token.run(); } @@ -207,7 +198,7 @@ public class ShapesRenderer Runnable token = Carpet.startProfilerSection("Scarpet client"); for (int i = 0, count = tag.size(); i < count; i++) { - addShape(tag.getCompound(i)); + addShape(tag.getCompound(i).orElseThrow()); } token.run(); } @@ -220,7 +211,7 @@ public class ShapesRenderer return; } BiFunction> shapeFactory; - shapeFactory = renderedShapes.get(tag.getString("shape")); + shapeFactory = renderedShapes.get(tag.getString("shape").orElseThrow()); if (shapeFactory == null) { CarpetScriptServer.LOG.info("Unrecognized shape: " + tag.getString("shape")); @@ -384,9 +375,9 @@ public class ShapesRenderer matrices.mulPose(Axis.YP.rotationDegrees(180)); } - RenderSystem.depthMask(true); - RenderSystem.enableCull(); - RenderSystem.enableDepthTest(); + ////RenderSystem.depthMask(true); + ////RenderSystem.enableCull(); + ////RenderSystem.enableDepthTest(); blockPos = BlockPos.containing(v1); int light = 0; @@ -418,9 +409,9 @@ public class ShapesRenderer if (blockState.getBlock() instanceof LeavesBlock && !Minecraft.useFancyGraphics()) { type = RenderType.solid(); } else { - type = ItemBlockRenderTypes.getRenderType(blockState, false); + type = ItemBlockRenderTypes.getRenderType(blockState); } - client.getBlockRenderer().getModelRenderer().renderModel(matrices.last(), immediate.getBuffer(type), blockState, bakedModel, red, green, blue, light, OverlayTexture.NO_OVERLAY); + client.getBlockRenderer().getModelRenderer().renderModel(matrices.last(), immediate.getBuffer(type), bakedModel, red, green, blue, light, OverlayTexture.NO_OVERLAY); } // draw the block`s entity part @@ -434,28 +425,22 @@ public class ShapesRenderer BlockEntity.setLevel(client.level); if (shape.blockEntity != null) { - BlockEntity.loadWithComponents(shape.blockEntity, client.level.registryAccess()); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(BlockEntity.problemPath(), CarpetScriptServer.LOG)) { + BlockEntity.loadWithComponents(TagValueInput.create(reporter, client.level.registryAccess(), shape.blockEntity)); + } } } } } - if (BlockEntity instanceof ShulkerBoxBlockEntity sbBlockEntity) + if (BlockEntity != null) { - sbrender(sbBlockEntity, partialTick, - matrices, immediate, light, OverlayTexture.NO_OVERLAY); - } - else - { - if (BlockEntity != null) - { BlockEntityRenderer blockEntityRenderer = client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity); if (blockEntityRenderer != null) { blockEntityRenderer.render(BlockEntity, partialTick, - matrices, immediate, light, OverlayTexture.NO_OVERLAY); + matrices, immediate, light, OverlayTexture.NO_OVERLAY, camera1.getPosition()); } - } } } else @@ -469,9 +454,9 @@ public class ShapesRenderer } matrices.popPose(); immediate.endBatch(); - RenderSystem.disableCull(); - RenderSystem.disableDepthTest(); - RenderSystem.depthMask(false); + ////RenderSystem.disableCull(); + ////RenderSystem.disableDepthTest(); + ////RenderSystem.depthMask(false); } @@ -480,44 +465,6 @@ public class ShapesRenderer { return true; } - - // copy and modifiy a bit from net.minecraft.client.renderer.blockentity.ShulkerBoxRenderer.render - public void sbrender(ShulkerBoxBlockEntity shulkerBoxBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j) - { - Direction direction = Direction.UP; - if (shulkerBoxBlockEntity.hasLevel()) - { - BlockState blockState = shulkerBoxBlockEntity.getBlockState(); - if (blockState.getBlock() instanceof ShulkerBoxBlock) - { - direction = blockState.getValue(ShulkerBoxBlock.FACING); - } - } - DyeColor dyeColor = shulkerBoxBlockEntity.getColor(); - Material material; - if (dyeColor == null) - { - material = Sheets.DEFAULT_SHULKER_TEXTURE_LOCATION; - } - else - { - material = Sheets.SHULKER_TEXTURE_LOCATION.get(dyeColor.getId()); - } - - poseStack.pushPose(); - poseStack.translate(0.5, 0.5, 0.5); - poseStack.scale(0.9995F, 0.9995F, 0.9995F); - poseStack.mulPose(direction.getRotation()); - poseStack.scale(1.0F, -1.0F, -1.0F); - poseStack.translate(0.0, -1.0, 0.0); - ShulkerModel model = VanillaClient.ShulkerBoxRenderer_model(client.getBlockEntityRenderDispatcher().getRenderer(shulkerBoxBlockEntity)); - ModelPart modelPart = model.getLid(); - modelPart.setPos(0.0F, 24.0F - shulkerBoxBlockEntity.getProgress(f) * 0.5F * 16.0F, 0.0F); - modelPart.yRot = 270.0F * shulkerBoxBlockEntity.getProgress(f) * (float) (Math.PI / 180.0); - VertexConsumer vertexConsumer = material.buffer(multiBufferSource, RenderType::entityCutoutNoCull); - model.renderToBuffer(poseStack, vertexConsumer, i, j, 0xffffffff); - poseStack.popPose(); - } } @@ -541,11 +488,11 @@ public class ShapesRenderer Font textRenderer = client.font; if (shape.doublesided) { - RenderSystem.disableCull(); + //// RenderSystem.disableCull(); TODO culling } else { - RenderSystem.enableCull(); + //// RenderSystem.enableCull(); } matrices.pushPose(); matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz); @@ -581,10 +528,12 @@ public class ShapesRenderer text_x = (float) (-textRenderer.width(shape.value.getString())); } MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(new ByteBufferBuilder(RenderType.TRANSIENT_BUFFER_SIZE)); - textRenderer.drawInBatch(shape.value, text_x, 0.0F, shape.textcolor, false, matrices.last().pose(), immediate, Font.DisplayMode.NORMAL, shape.textbck, 15728880); + // text doesn't appear if backgroud is set + ///script run draw_shape('label', 100, 'pos', [200, 100, 200], 'text', 'Hewwo World!', 'color', 0xffffffff, 'fill', 0x33333333) + textRenderer.drawInBatch(shape.value, text_x, 0.0F, shape.textcolor, false, matrices.last().pose(), immediate, Font.DisplayMode.SEE_THROUGH, shape.textbck, 15728880); immediate.endBatch(); matrices.popPose(); - RenderSystem.enableCull(); + ////RenderSystem.enableCull(); } @Override @@ -673,11 +622,32 @@ public class ShapesRenderer } } + private static void drawWithShader(MeshData mesh, RenderType type) { + type.draw(mesh); + //VertexBuffer buffre = mesh.drawState().format().getImmediateDrawVertexBuffer(); + //buffre.bind(); + //buffre.upload(mesh); + //buffre.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderType. RenderSystem.getShader()); + } + + public static class RenderedPolyface extends RenderedShape { + // mode now can only be 4, 5, or 6 private static final VertexFormat.Mode[] faceIndices = new VertexFormat.Mode[]{ Mode.LINES, Mode.LINE_STRIP, Mode.DEBUG_LINES, Mode.DEBUG_LINE_STRIP, Mode.TRIANGLES, Mode.TRIANGLE_STRIP, Mode.TRIANGLE_FAN, Mode.QUADS}; + private static final RenderType [] renderTypes = new RenderType[] { + RenderType.debugLineStrip(1), + RenderType.debugLineStrip(1), + RenderType.debugLineStrip(1), + RenderType.debugLineStrip(1), + RenderType.debugTriangleFan(), // TODO wrong + RenderType.debugTriangleFan(), // TODO wrong + RenderType.debugTriangleFan(), + RenderType.debugQuads() + }; + public RenderedPolyface(Minecraft client, ShapeDispatcher.ExpiringShape shape) { super(client, (ShapeDispatcher.Polyface) shape); @@ -693,11 +663,11 @@ public class ShapesRenderer if (shape.doublesided) { - RenderSystem.disableCull(); + ////RenderSystem.disableCull(); // todo culling } else { - RenderSystem.enableCull(); + ////RenderSystem.enableCull(); } BufferBuilder builder = tesselator.begin(faceIndices[shape.mode], DefaultVertexFormat.POSITION_COLOR); @@ -710,10 +680,10 @@ public class ShapesRenderer } builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.fr, shape.fg, shape.fb, shape.fa); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), renderTypes[shape.mode]); - RenderSystem.disableCull(); - RenderSystem.depthMask(false); + ////RenderSystem.disableCull(); + ////RenderSystem.depthMask(false); //RenderSystem.enableDepthTest(); @@ -746,10 +716,10 @@ public class ShapesRenderer builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); } builder.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); if (shape.inneredges) { - BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + BufferBuilder builderr = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); for (int i = 1; i < shape.vertexList.size() - 1; i++) { Vec3 vec = shape.vertexList.get(i); @@ -757,11 +727,11 @@ public class ShapesRenderer { vec = shape.relativiseRender(client.level, vec, partialTick); } - + builderr.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); builderr.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); builderr.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); } - BufferUploader.drawWithShader(builderr.buildOrThrow()); + drawWithShader(builderr.buildOrThrow(), RenderType.debugLineStrip(1)); } return; } @@ -806,14 +776,15 @@ public class ShapesRenderer builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); } } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); return; } if (shape.mode == 4) { - BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + // for (int i = 0; i < shape.vertexList.size(); i++) { + BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); Vec3 vecA = shape.vertexList.get(i); if (shape.relative.get(i)) { @@ -834,13 +805,15 @@ public class ShapesRenderer builder.addVertex((float) (vecA.x() - cx), (float) (vecA.y() - cy), (float) (vecA.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); builder.addVertex((float) (vecB.x() - cx), (float) (vecB.y() - cy), (float) (vecB.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); - builder.addVertex((float) (vecB.x() - cx), (float) (vecB.y() - cy), (float) (vecB.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); + //builder.addVertex((float) (vecB.x() - cx), (float) (vecB.y() - cy), (float) (vecB.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); builder.addVertex((float) (vecC.x() - cx), (float) (vecC.y() - cy), (float) (vecC.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); - builder.addVertex((float) (vecC.x() - cx), (float) (vecC.y() - cy), (float) (vecC.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); + //builder.addVertex((float) (vecC.x() - cx), (float) (vecC.y() - cy), (float) (vecC.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); builder.addVertex((float) (vecA.x() - cx), (float) (vecA.y() - cy), (float) (vecA.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a); + + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + //drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } } } @@ -900,7 +873,7 @@ public class ShapesRenderer drawCylinderWireframe(tesselator, (float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon), (float) (shape.radius + renderEpsilon), (float) (shape.height + 2 * dir * renderEpsilon), shape.axis, - shape.subdivisions, shape.radius == 0, + shape.subdivisions, shape.height == 0, shape.r, shape.g, shape.b, shape.a); } @@ -926,10 +899,10 @@ public class ShapesRenderer public static void drawLine(Tesselator tesselator, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { - BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); builder.addVertex(x1, y1, z1).setColor(red1, grn1, blu1, alpha); builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha); - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } public static void drawBoxWireGLLines( @@ -939,7 +912,8 @@ public class ShapesRenderer boolean xthick, boolean ythick, boolean zthick, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { - BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); + /* old lines not using strip if (xthick) { builder.addVertex(x1, y1, z1).setColor(red1, grn2, blu2, alpha); @@ -982,7 +956,52 @@ public class ShapesRenderer builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha); builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + */ + + if (xthick) + + { + builder.addVertex(x1, y1, z1).setColor(red1, grn2, blu2, alpha); + builder.addVertex(x2, y1, z1).setColor(red1, grn2, blu2, alpha); + + builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha); + } + if (ythick) + { + builder.addVertex(x1, y1, z1).setColor(red2, grn1, blu2, alpha); + builder.addVertex(x1, y2, z1).setColor(red2, grn1, blu2, alpha); + + builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha); + } + if (zthick) + { + builder.addVertex(x1, y1, z1).setColor(red2, grn2, blu1, alpha); + builder.addVertex(x1, y1, z2).setColor(red2, grn2, blu1, alpha); + + builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha); + + builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha); + builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha); + } + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } public static void drawBoxFaces( @@ -1043,7 +1062,7 @@ public class ShapesRenderer builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha); } } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugQuads()); } public static void drawCylinderWireframe(Tesselator tesselator, @@ -1076,7 +1095,7 @@ public class ShapesRenderer float z = r * Mth.sin(theta); builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } if (!isFlat) @@ -1094,10 +1113,10 @@ public class ShapesRenderer builder.addVertex(cx + x, cy + h, cz - z).setColor(red, grn, blu, alpha); builder.addVertex(cx - x, cy + h, cz + z).setColor(red, grn, blu, alpha); builder.addVertex(cx - x, cy + 0, cz + z).setColor(red, grn, blu, alpha); - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } } - else + /* else { BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); for (int i = 0; i <= num_steps180; i++) @@ -1108,8 +1127,8 @@ public class ShapesRenderer builder.addVertex(cx - x, cy, cz + z).setColor(red, grn, blu, alpha); builder.addVertex(cx + x, cy, cz - z).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); - } + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); + }*/ } else if (axis == Direction.Axis.X) @@ -1126,7 +1145,7 @@ public class ShapesRenderer float y = r * Mth.sin(theta); builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } if (!isFlat) @@ -1143,22 +1162,22 @@ public class ShapesRenderer builder.addVertex(cx + 0, cy + y, cz - z).setColor(red, grn, blu, alpha); builder.addVertex(cx + h, cy + y, cz - z).setColor(red, grn, blu, alpha); builder.addVertex(cx + h, cy - y, cz + z).setColor(red, grn, blu, alpha); - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } } - else + /*else { - BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); - for (int i = 0; i <= num_steps180; i++) + BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); + for (int i = 0; i <= num_steps360+1; i++) { float theta = step * i; float y = r * Mth.cos(theta); float z = r * Mth.sin(theta); - builder.addVertex(cx, cy - y, cz + z).setColor(red, grn, blu, alpha); - builder.addVertex(cx, cy + y, cz - z).setColor(red, grn, blu, alpha); + builder.addVertex(cx, cy + y, cz + z).setColor(red, grn, blu, alpha); + //builder.addVertex(cx, cy + y, cz - z).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); - } + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); + }*/ } else if (axis == Direction.Axis.Z) { @@ -1174,7 +1193,7 @@ public class ShapesRenderer float x = r * Mth.sin(theta); builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } if (!isFlat) { @@ -1190,10 +1209,10 @@ public class ShapesRenderer builder.addVertex(cx - x, cy + y, cz + 0).setColor(red, grn, blu, alpha); builder.addVertex(cx - x, cy + y, cz + h).setColor(red, grn, blu, alpha); builder.addVertex(cx + x, cy - y, cz + h).setColor(red, grn, blu, alpha); - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } } - else + /*else { BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); for (int i = 0; i <= num_steps180; i++) @@ -1204,9 +1223,8 @@ public class ShapesRenderer builder.addVertex(cx + x, cy - y, cz).setColor(red, grn, blu, alpha); builder.addVertex(cx - x, cy + y, cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); - } - + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); + }*/ } } @@ -1231,7 +1249,7 @@ public class ShapesRenderer float z = r * Mth.sin(theta); builder.addVertex(x + cx, cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan()); if (!isFlat) { BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); @@ -1243,7 +1261,7 @@ public class ShapesRenderer float z = r * Mth.sin(theta); builderr.addVertex(x + cx, cy + h, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builderr.buildOrThrow()); + drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan()); BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads float xp = r * 1; @@ -1260,7 +1278,7 @@ public class ShapesRenderer xp = x; zp = z; } - BufferUploader.drawWithShader(builderrr.buildOrThrow()); + drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads()); } } @@ -1275,7 +1293,7 @@ public class ShapesRenderer float z = r * Mth.sin(theta); builder.addVertex(cx, cy + y, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan()); if (!isFlat) { BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); @@ -1287,7 +1305,7 @@ public class ShapesRenderer float z = r * Mth.sin(theta); builderr.addVertex(cx + h, cy + y, cz + z).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builderr.buildOrThrow()); + drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan()); BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads float yp = r * 1; @@ -1304,7 +1322,7 @@ public class ShapesRenderer yp = y; zp = z; } - BufferUploader.drawWithShader(builderrr.buildOrThrow()); + drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads()); } } else if (axis == Direction.Axis.Z) @@ -1318,7 +1336,7 @@ public class ShapesRenderer float y = r * Mth.sin(theta); builder.addVertex(x + cx, cy + y, cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan()); if (!isFlat) { BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); @@ -1330,7 +1348,7 @@ public class ShapesRenderer float y = r * Mth.sin(theta); builderr.addVertex(x + cx, cy + y, cz + h).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builderr.buildOrThrow()); + drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan()); BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads float xp = r; @@ -1347,7 +1365,7 @@ public class ShapesRenderer xp = x; yp = y; } - BufferUploader.drawWithShader(builderrr.buildOrThrow()); + drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads()); } } } @@ -1372,7 +1390,7 @@ public class ShapesRenderer float y = r * Mth.cos(phi); builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } for (int j = 0; j <= num_steps180; j++) { @@ -1387,7 +1405,7 @@ public class ShapesRenderer float y = r * Mth.cos(phi); builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha); } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1)); } } @@ -1429,7 +1447,7 @@ public class ShapesRenderer zbp = zp; yp = y; } - BufferUploader.drawWithShader(builder.buildOrThrow()); + drawWithShader(builder.buildOrThrow(), RenderType.debugQuads()); } } } diff --git a/src/main/java/carpet/script/utils/SnoopyCommandSource.java b/src/main/java/carpet/script/utils/SnoopyCommandSource.java index 39d582e2..71e10508 100644 --- a/src/main/java/carpet/script/utils/SnoopyCommandSource.java +++ b/src/main/java/carpet/script/utils/SnoopyCommandSource.java @@ -19,6 +19,7 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.OptionalLong; import java.util.function.BinaryOperator; import java.util.function.Supplier; @@ -43,11 +44,11 @@ public class SnoopyCommandSource extends CommandSourceStack private final TaskChainer taskChainer; - public SnoopyCommandSource(CommandSourceStack original, Component[] error, List chatOutput) + public SnoopyCommandSource(CommandSourceStack original, Component[] error, List chatOutput, OptionalLong[] returnValue) { super(CommandSource.NULL, original.getPosition(), original.getRotation(), original.getLevel(), Vanilla.MinecraftServer_getRunPermissionLevel(original.getServer()), original.getTextName(), original.getDisplayName(), original.getServer(), original.getEntity(), false, - CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer())); + (b, i) -> returnValue[0] = OptionalLong.of(i), EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer())); this.output = CommandSource.NULL; this.position = original.getPosition(); this.world = original.getLevel(); @@ -56,7 +57,7 @@ public class SnoopyCommandSource extends CommandSourceStack this.name = original.getDisplayName(); this.server = original.getServer(); this.entity = original.getEntity(); - this.resultConsumer = CommandResultCallback.EMPTY; + this.resultConsumer = (b, i) -> returnValue[0] = OptionalLong.of(i); this.entityAnchor = original.getAnchor(); this.rotation = original.getRotation(); this.error = error; @@ -65,27 +66,27 @@ public class SnoopyCommandSource extends CommandSourceStack this.taskChainer = TaskChainer.immediate(original.getServer()); } - public SnoopyCommandSource(ServerPlayer player, Component[] error, List output) + public SnoopyCommandSource(ServerPlayer player, Component[] error, List output, int [] result) { - super(player, player.position(), player.getRotationVector(), + super(player.commandSource(), player.position(), player.getRotationVector(), player.level() instanceof final ServerLevel serverLevel ? serverLevel : null, - player.server.getProfilePermissions(player.getGameProfile()), player.getName().getString(), player.getDisplayName(), + player.getServer().getProfilePermissions(player.getGameProfile()), player.getName().getString(), player.getDisplayName(), player.level().getServer(), player); - this.output = player; + this.output = player.commandSource(); this.position = player.position(); this.world = player.level() instanceof final ServerLevel serverLevel ? serverLevel : null; - this.level = player.server.getProfilePermissions(player.getGameProfile()); + this.level = player.getServer().getProfilePermissions(player.getGameProfile()); this.simpleName = player.getName().getString(); this.name = player.getDisplayName(); this.server = player.level().getServer(); this.entity = player; - this.resultConsumer = CommandResultCallback.EMPTY; + this.resultConsumer = (b, i) -> result[0] = i; this.entityAnchor = EntityAnchorArgument.Anchor.FEET; this.rotation = player.getRotationVector(); // not a client call really this.error = error; this.chatOutput = output; this.signingContext = CommandSigningContext.ANONYMOUS; - this.taskChainer = TaskChainer.immediate(player.server); + this.taskChainer = TaskChainer.immediate(player.getServer()); } private SnoopyCommandSource(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity, CommandResultCallback consumer, EntityAnchorArgument.Anchor entityAnchor, CommandSigningContext context, TaskChainer chainer, @@ -203,5 +204,4 @@ public class SnoopyCommandSource extends CommandSourceStack { chatOutput.add(message.get()); } - } diff --git a/src/main/java/carpet/script/utils/SystemInfo.java b/src/main/java/carpet/script/utils/SystemInfo.java index 0174d904..d655f142 100644 --- a/src/main/java/carpet/script/utils/SystemInfo.java +++ b/src/main/java/carpet/script/utils/SystemInfo.java @@ -61,9 +61,9 @@ public class SystemInfo put("world_dimensions", c -> ListValue.wrap(c.server().levelKeys().stream().map(k -> ValueConversions.of(k.location())))); put("world_spawn_point", c -> ValueConversions.of(c.server().overworld().getLevelData().getSpawnPos())); - put("world_bottom", c -> new NumericValue(c.level().getMinBuildHeight())); + put("world_bottom", c -> new NumericValue(c.level().getMinY())); - put("world_top", c -> new NumericValue(c.level().getMaxBuildHeight())); + put("world_top", c -> new NumericValue(c.level().getMaxY())); put("world_center", c -> { WorldBorder worldBorder = c.level().getWorldBorder(); @@ -90,9 +90,9 @@ public class SystemInfo put("game_protocol", c -> NumericValue.of(SharedConstants.getProtocolVersion())); put("game_major_target", c -> NumericValue.of(Vanilla.MinecraftServer_getReleaseTarget(c.server())[0])); put("game_minor_target", c -> NumericValue.of(Vanilla.MinecraftServer_getReleaseTarget(c.server())[1])); - put("game_stable", c -> BooleanValue.of(SharedConstants.getCurrentVersion().isStable())); - put("game_data_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion())); - put("game_pack_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA))); + put("game_stable", c -> BooleanValue.of(SharedConstants.getCurrentVersion().stable())); + put("game_data_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().dataVersion().version())); + put("game_pack_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().packVersion(PackType.SERVER_DATA))); put("server_ip", c -> StringValue.of(c.server().getLocalIp())); put("server_whitelisted", c -> BooleanValue.of(c.server().isEnforceWhitelist())); @@ -165,7 +165,7 @@ public class SystemInfo put("world_gamerules", c -> { Map rules = new HashMap<>(); GameRules gameRules = c.level().getGameRules(); - GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() + gameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { @Override public > void visit(GameRules.Key key, GameRules.Type type) diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index 77fef2f7..13a8c101 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -199,7 +199,7 @@ public class BlockValue extends Value @Override public String getString() { - Registry blockRegistry = world.registryAccess().registryOrThrow(Registries.BLOCK); + Registry blockRegistry = world.registryAccess().lookupOrThrow(Registries.BLOCK); return nameFromResource(blockRegistry.getKey(getBlockState().getBlock())); } @@ -250,7 +250,7 @@ public class BlockValue extends Value CompoundTag tag = new CompoundTag(); CompoundTag state = new CompoundTag(); BlockState s = getBlockState(); - state.put("Name", StringTag.valueOf(world.registryAccess().registryOrThrow(Registries.BLOCK).getKey(s.getBlock()).toString())); + state.put("Name", StringTag.valueOf(world.registryAccess().lookupOrThrow(Registries.BLOCK).getKey(s.getBlock()).toString())); Collection> properties = s.getProperties(); if (!properties.isEmpty()) { diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index f3dcc1cc..f6188f45 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -25,10 +25,10 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StringTag; -import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; +import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket; import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; +import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; -import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -37,6 +37,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.EntityTypeTags; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.InteractionHand; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; @@ -49,7 +50,6 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeMap; @@ -69,6 +69,8 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; @@ -77,7 +79,6 @@ import net.minecraft.world.phys.Vec3; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; -import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -239,8 +240,8 @@ public class EntityValue extends Value who = who.substring(1); } String booWho = who; - HolderSet.Named> eTagValue = server.registryAccess().registryOrThrow(Registries.ENTITY_TYPE) - .getTag(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(who))) + HolderSet.Named> eTagValue = server.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE) + .get(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(who))) .orElseThrow(() -> new InternalExpressionException(booWho + " is not a valid entity descriptor")); Set> eTag = eTagValue.stream().map(Holder::value).collect(Collectors.toUnmodifiableSet()); if (positive) @@ -257,7 +258,7 @@ public class EntityValue extends Value } else { - return new EntityClassDescriptor(ANY, e -> !eTag.contains(e.getType()) && e.isAlive(), server.registryAccess().registryOrThrow(Registries.ENTITY_TYPE).stream().filter(et -> !eTag.contains(et))); + return new EntityClassDescriptor(ANY, e -> !eTag.contains(e.getType()) && e.isAlive(), server.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).stream().filter(et -> !eTag.contains(et))); } } return eDesc; @@ -285,7 +286,7 @@ public class EntityValue extends Value public Value listValue(RegistryAccess regs) { - Registry> entityRegs = regs.registryOrThrow(Registries.ENTITY_TYPE); + Registry> entityRegs = regs.lookupOrThrow(Registries.ENTITY_TYPE); return ListValue.wrap(types.stream().map(et -> nameFromRegistryId(entityRegs.getKey(et)))); } @@ -297,15 +298,15 @@ public class EntityValue extends Value EntityType.ARROW, EntityType.DRAGON_FIREBALL, EntityType.FIREWORK_ROCKET, EntityType.FIREBALL, EntityType.LLAMA_SPIT, EntityType.SMALL_FIREBALL, EntityType.SNOWBALL, EntityType.SPECTRAL_ARROW, EntityType.EGG, - EntityType.ENDER_PEARL, EntityType.EXPERIENCE_BOTTLE, EntityType.POTION, + EntityType.ENDER_PEARL, EntityType.EXPERIENCE_BOTTLE, EntityType.SPLASH_POTION, EntityType.LINGERING_POTION, EntityType.TRIDENT, EntityType.WITHER_SKULL, EntityType.FISHING_BOBBER, EntityType.SHULKER_BULLET ); Set> deads = Set.of( - EntityType.AREA_EFFECT_CLOUD, EntityType.MARKER, EntityType.BOAT, EntityType.END_CRYSTAL, + EntityType.AREA_EFFECT_CLOUD, EntityType.MARKER, EntityType.END_CRYSTAL, EntityType.EVOKER_FANGS, EntityType.EXPERIENCE_ORB, EntityType.EYE_OF_ENDER, EntityType.FALLING_BLOCK, EntityType.ITEM, EntityType.ITEM_FRAME, EntityType.GLOW_ITEM_FRAME, EntityType.LEASH_KNOT, EntityType.LIGHTNING_BOLT, EntityType.PAINTING, - EntityType.TNT, EntityType.ARMOR_STAND, EntityType.CHEST_BOAT + EntityType.TNT, EntityType.ARMOR_STAND ); Set> minecarts = Set.of( @@ -335,7 +336,7 @@ public class EntityValue extends Value ); Set> living = allTypes.stream().filter(et -> - !deads.contains(et) && !projectiles.contains(et) && !minecarts.contains(et) + !deads.contains(et) && !projectiles.contains(et) && !minecarts.contains(et) && !et.is(EntityTypeTags.BOAT) ).collect(Collectors.toSet()); Set> regular = allTypes.stream().filter(et -> @@ -382,7 +383,7 @@ public class EntityValue extends Value for (ResourceLocation typeId : BuiltInRegistries.ENTITY_TYPE.keySet()) { - EntityType type = BuiltInRegistries.ENTITY_TYPE.get(typeId); + EntityType type = BuiltInRegistries.ENTITY_TYPE.getValue(typeId); String mobType = ValueConversions.simplify(typeId); put(mobType, new EntityClassDescriptor(type, net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, Stream.of(type))); put("!" + mobType, new EntityClassDescriptor(ANY, (e) -> e.getType() != type && e.isAlive(), allTypes.stream().filter(et -> et != type))); @@ -445,7 +446,7 @@ public class EntityValue extends Value put("display_name", (e, a) -> new FormattedTextValue(e.getDisplayName())); put("command_name", (e, a) -> new StringValue(e.getScoreboardName())); put("custom_name", (e, a) -> e.hasCustomName() ? new StringValue(e.getCustomName().getString()) : Value.NULL); - put("type", (e, a) -> nameFromRegistryId(e.level().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getKey(e.getType()))); + put("type", (e, a) -> nameFromRegistryId(e.level().registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).getKey(e.getType()))); put("is_riding", (e, a) -> BooleanValue.of(e.isPassenger())); put("is_ridden", (e, a) -> BooleanValue.of(e.isVehicle())); put("passengers", (e, a) -> ListValue.wrap(e.getPassengers().stream().map(EntityValue::new))); @@ -457,14 +458,14 @@ public class EntityValue extends Value put("scoreboard_tags", (e, a) -> ListValue.wrap(e.getTags().stream().map(StringValue::new))); put("entity_tags", (e, a) -> { EntityType type = e.getType(); - return ListValue.wrap(e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTags().filter(entry -> entry.getSecond().stream().anyMatch(h -> h.value() == type)).map(entry -> ValueConversions.of(entry.getFirst()))); + return ListValue.wrap(e.getServer().registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).getTags().filter(entry -> entry.stream().anyMatch(h -> h.value() == type)).map(entry -> ValueConversions.of(entry))); }); // deprecated put("has_tag", (e, a) -> BooleanValue.of(e.getTags().contains(a.getString()))); put("has_scoreboard_tag", (e, a) -> BooleanValue.of(e.getTags().contains(a.getString()))); put("has_entity_tag", (e, a) -> { - Optional>> tag = e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTag(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(a.getString()))); + Optional>> tag = e.getServer().registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).get(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(a.getString()))); if (tag.isEmpty()) { return Value.NULL; @@ -494,7 +495,7 @@ public class EntityValue extends Value put("immune_to_fire", (e, a) -> BooleanValue.of(e.fireImmune())); put("immune_to_frost", (e, a) -> BooleanValue.of(!e.canFreeze())); - put("invulnerable", (e, a) -> BooleanValue.of(e.isInvulnerable())); + put("invulnerable", (e, a) -> BooleanValue.of(e instanceof Player player ? player.getAbilities().invulnerable : e.isInvulnerable())); put("dimension", (e, a) -> nameFromRegistryId(e.level().dimension().location())); // getDimId put("height", (e, a) -> new NumericValue(e.getDimensions(Pose.STANDING).height())); put("width", (e, a) -> new NumericValue(e.getDimensions(Pose.STANDING).width())); @@ -522,19 +523,20 @@ public class EntityValue extends Value } return Value.NULL; }); - put("home", (e, a) -> e instanceof Mob mob ? (mob.getRestrictRadius() > 0) ? new BlockValue(null, (ServerLevel) e.level(), mob.getRestrictCenter()) : Value.FALSE : Value.NULL); + put("home", (e, a) -> e instanceof Mob mob ? (mob.getHomeRadius() > 0) ? new BlockValue(null, (ServerLevel) e.level(), mob.getHomePosition()) : Value.FALSE : Value.NULL); put("spawn_point", (e, a) -> { if (e instanceof ServerPlayer spe) { - if (spe.getRespawnPosition() == null) + if (spe.getRespawnConfig() == null) { return Value.FALSE; } + ServerPlayer.RespawnConfig spec = spe.getRespawnConfig(); return ListValue.of( - ValueConversions.of(spe.getRespawnPosition()), - ValueConversions.of(spe.getRespawnDimension()), - new NumericValue(spe.getRespawnAngle()), - BooleanValue.of(spe.isRespawnForced()) + ValueConversions.of(spec.pos()), + ValueConversions.of(spec.dimension()), + new NumericValue(spec.angle()), + BooleanValue.of(spec.forced()) ); } return Value.NULL; @@ -545,11 +547,11 @@ public class EntityValue extends Value put("swimming", (e, a) -> e.isSwimming() ? Value.TRUE : Value.FALSE); put("swinging", (e, a) -> e instanceof LivingEntity le ? BooleanValue.of(le.swinging) : Value.NULL); put("air", (e, a) -> new NumericValue(e.getAirSupply())); - put("language", (e, a) -> !(e instanceof ServerPlayer p) ? NULL : StringValue.of(Vanilla.ServerPlayer_getLanguage(p))); + put("language", (e, a) -> !(e instanceof ServerPlayer p) ? NULL : StringValue.of(p.clientInformation().language())); put("persistence", (e, a) -> e instanceof Mob mob ? BooleanValue.of(mob.isPersistenceRequired()) : Value.NULL); put("hunger", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getFoodLevel()) : Value.NULL); put("saturation", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getSaturationLevel()) : Value.NULL); - put("exhaustion", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getExhaustionLevel()) : Value.NULL); + put("exhaustion", (e, a) -> e instanceof Player player ? new NumericValue(Vanilla.FoodData_getExhaustion(player.getFoodData())) : Value.NULL); put("absorption", (e, a) -> e instanceof Player player ? new NumericValue(player.getAbsorptionAmount()) : Value.NULL); put("xp", (e, a) -> e instanceof Player player ? new NumericValue(player.totalExperience) : Value.NULL); put("xp_level", (e, a) -> e instanceof Player player ? new NumericValue(player.experienceLevel) : Value.NULL); @@ -565,14 +567,14 @@ public class EntityValue extends Value { return Value.NULL; } - return ValueConversions.fromPath((ServerLevel) e.getCommandSenderWorld(), path); + return ValueConversions.fromPath((ServerLevel) e.level(), path); } return Value.NULL; }); put("brain", (e, a) -> { String module = a.getString(); - MemoryModuleType moduleType = e.level().registryAccess().registryOrThrow(Registries.MEMORY_MODULE_TYPE).get(InputValidator.identifierOf(module)); + MemoryModuleType moduleType = e.level().registryAccess().lookupOrThrow(Registries.MEMORY_MODULE_TYPE).getValue(InputValidator.identifierOf(module)); if (moduleType == MemoryModuleType.DUMMY) { return Value.NULL; @@ -616,7 +618,7 @@ public class EntityValue extends Value { return StringValue.of(moddedType); } - MinecraftServer server = p.getCommandSenderWorld().getServer(); + MinecraftServer server = p.level().getServer(); if (server.isDedicatedServer()) { return new StringValue("multiplayer"); @@ -663,7 +665,7 @@ public class EntityValue extends Value return ListValue.wrap(effects); } String effectName = a.getString(); - Holder potion = BuiltInRegistries.MOB_EFFECT.getHolder(ResourceKey.create(Registries.MOB_EFFECT, InputValidator.identifierOf(effectName))).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); + Holder potion = BuiltInRegistries.MOB_EFFECT.get(ResourceKey.create(Registries.MOB_EFFECT, InputValidator.identifierOf(effectName))).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); if (!le.hasEffect(potion)) { return Value.NULL; @@ -696,7 +698,7 @@ public class EntityValue extends Value return Value.NULL; }); - put("selected_slot", (e, a) -> e instanceof Player p ? new NumericValue(p.getInventory().selected) : Value.NULL); + put("selected_slot", (e, a) -> e instanceof Player p ? new NumericValue(p.getInventory().getSelectedSlot()) : Value.NULL); put("active_block", (e, a) -> { if (e instanceof ServerPlayer sp) @@ -706,7 +708,7 @@ public class EntityValue extends Value { return Value.NULL; } - return new BlockValue(null, sp.serverLevel(), pos); + return new BlockValue(null, sp.level(), pos); } return Value.NULL; }); @@ -821,7 +823,7 @@ public class EntityValue extends Value case MISS: return Value.NULL; case BLOCK: - return new BlockValue((ServerLevel) e.getCommandSenderWorld(), ((BlockHitResult) hitres).getBlockPos()); + return new BlockValue((ServerLevel) e.level(), ((BlockHitResult) hitres).getBlockPos()); case ENTITY: return new EntityValue(((EntityHitResult) hitres).getEntity()); } @@ -833,14 +835,14 @@ public class EntityValue extends Value { return Value.NULL; } - Registry attributes = e.level().registryAccess().registryOrThrow(Registries.ATTRIBUTE); + Registry attributes = e.level().registryAccess().lookupOrThrow(Registries.ATTRIBUTE); if (a == null) { AttributeMap container = el.getAttributes(); - return MapValue.wrap(attributes.holders().filter(container::hasAttribute).collect(Collectors.toMap(aa -> ValueConversions.of(aa.key()), aa -> NumericValue.of(container.getValue(aa))))); + return MapValue.wrap(attributes.listElements().filter(container::hasAttribute).collect(Collectors.toMap(aa -> ValueConversions.of(aa.key()), aa -> NumericValue.of(container.getValue(aa))))); } ResourceLocation id = InputValidator.identifierOf(a.getString()); - Holder attrib = attributes.getHolder(id).orElseThrow( + Holder attrib = attributes.get(id).orElseThrow( () -> new InternalExpressionException("Unknown attribute: " + a.getString()) ); if (!el.getAttributes().hasAttribute(attrib)) @@ -851,12 +853,16 @@ public class EntityValue extends Value }); put("nbt", (e, a) -> { - CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); - if (a == null) - { - return new NBTSerializableValue(nbttagcompound); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(e.problemPath(), CarpetScriptServer.LOG)) { + final TagValueOutput output = TagValueOutput.createWithContext(reporter, e.registryAccess()); + e.saveWithoutId(output); + CompoundTag nbttagcompound = output.buildResult(); + if (a == null) + { + return new NBTSerializableValue(nbttagcompound); + } + return new NBTSerializableValue(nbttagcompound).get(a); } - return new NBTSerializableValue(nbttagcompound).get(a); }); put("category", (e, a) -> { @@ -898,15 +904,11 @@ public class EntityValue extends Value } if (e instanceof ServerPlayer sp) { - // this forces position but doesn't angles for some reason. Need both in the API in the future. - EnumSet set = EnumSet.noneOf(RelativeMovement.class); - set.add(RelativeMovement.X_ROT); - set.add(RelativeMovement.Y_ROT); - sp.connection.teleport(x, y, z, yaw, pitch, set); + sp.connection.teleport(x, y, z, yaw, pitch); } else { - e.moveTo(x, y, z, yaw, pitch); + e.snapTo(x, y, z, yaw, pitch); // we were sending to players for not-living entites, that were untracked. Living entities should be tracked. //((ServerWorld) e.getEntityWorld()).getChunkManager().sendToNearbyPlayers(e, new EntityS2CPacket.(e)); if (e instanceof LivingEntity le) @@ -919,7 +921,7 @@ public class EntityValue extends Value } else { - ((ServerLevel) e.getCommandSenderWorld()).getChunkSource().broadcastAndSend(e, new ClientboundTeleportEntityPacket(e)); + ((ServerLevel) e.level()).getChunkSource().broadcastAndSend(e, ClientboundEntityPositionSyncPacket.of(e)); } } } @@ -1019,7 +1021,7 @@ public class EntityValue extends Value if (e instanceof ServerPlayer player) { int slot = NumericValue.asNumber(v).getInt(); - player.connection.send(new ClientboundSetCarriedItemPacket(slot)); + player.connection.send(new ClientboundSetHeldSlotPacket(slot)); } }); @@ -1038,7 +1040,7 @@ public class EntityValue extends Value } });*/ - put("kill", (e, v) -> e.kill()); + put("kill", (e, v) -> e.kill((ServerLevel) e.level())); put("location", (e, v) -> { if (!(v instanceof ListValue lv)) @@ -1311,7 +1313,7 @@ public class EntityValue extends Value } if (v.isNull()) { - ec.restrictTo(BlockPos.ZERO, -1); + ec.setHomeTo(BlockPos.ZERO, -1); Map tasks = Vanilla.Mob_getTemporaryTasks(ec); Vanilla.Mob_getAI(ec, false).removeGoal(tasks.get("home")); tasks.remove("home"); @@ -1344,7 +1346,7 @@ public class EntityValue extends Value throw new InternalExpressionException("'home' requires at least one position argument, and optional distance"); } - ec.restrictTo(pos, distance); + ec.setHomeTo(pos, distance); Map tasks = Vanilla.Mob_getTemporaryTasks(ec); if (!tasks.containsKey("home")) { @@ -1361,14 +1363,14 @@ public class EntityValue extends Value } if (a == null) { - spe.setRespawnPosition(null, null, 0, false, false); + spe.setRespawnPosition(null, false); } else if (a instanceof ListValue lv) { List params = lv.getItems(); Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false); BlockPos pos = BlockPos.containing(blockLocator.vec); - ResourceKey world = spe.getCommandSenderWorld().dimension(); + ResourceKey world = spe.level().dimension(); float angle = spe.getYHeadRot(); boolean forced = false; if (params.size() > blockLocator.offset) @@ -1384,7 +1386,7 @@ public class EntityValue extends Value } } } - spe.setRespawnPosition(world, pos, angle, forced, false); + spe.setRespawnPosition(new ServerPlayer.RespawnConfig(world, pos, angle, forced), false); } else if (a instanceof BlockValue bv) { @@ -1392,11 +1394,11 @@ public class EntityValue extends Value { throw new InternalExpressionException("block for spawn modification should be localised in the world"); } - spe.setRespawnPosition(bv.getWorld().dimension(), bv.getPos(), e.getYRot(), true, false); // yaw + spe.setRespawnPosition(new ServerPlayer.RespawnConfig(bv.getWorld().dimension(), bv.getPos(), e.getYRot(), true), false); // yaw } else if (a.isNull()) { - spe.setRespawnPosition(null, null, 0, false, false); + spe.setRespawnPosition(null, false); } else { @@ -1474,7 +1476,7 @@ public class EntityValue extends Value if (list.size() >= 1 && list.size() <= 6) { String effectName = list.get(0).getString(); - Holder effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); + Holder effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); if (list.size() == 1) { le.removeEffect(effect); @@ -1517,7 +1519,7 @@ public class EntityValue extends Value else { String effectName = v.getString(); - Holder effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); + Holder effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName)); le.removeEffect(effect); return; } @@ -1603,7 +1605,10 @@ public class EntityValue extends Value put("exhaustion", (e, v) -> { if (e instanceof Player p) { - p.getFoodData().setExhaustion(NumericValue.asNumber(v).getFloat()); + Vanilla.FoodData_setExhaustion( + p.getFoodData(), + NumericValue.asNumber(v, "exhaustion").getFloat() + ); } }); @@ -1674,7 +1679,9 @@ public class EntityValue extends Value Value tagValue = NBTSerializableValue.fromValue(v); if (tagValue instanceof NBTSerializableValue nbtsv) { - e.load(nbtsv.getCompoundTag()); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(e.problemPath(), CarpetScriptServer.LOG)) { + e.load(TagValueInput.create(reporter, e.registryAccess(), nbtsv.getCompoundTag())); + } e.setUUID(uUID); } } @@ -1686,9 +1693,16 @@ public class EntityValue extends Value Value tagValue = NBTSerializableValue.fromValue(v); if (tagValue instanceof NBTSerializableValue nbtsv) { - CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); + CompoundTag nbttagcompound; + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(e.problemPath(), CarpetScriptServer.LOG)) { + final TagValueOutput output = TagValueOutput.createWithContext(reporter, e.registryAccess()); + e.saveWithoutId(output); + nbttagcompound = output.buildResult(); + } nbttagcompound.merge(nbtsv.getCompoundTag()); - e.load(nbttagcompound); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(e.problemPath(), CarpetScriptServer.LOG)) { + e.load(TagValueInput.create(reporter, e.registryAccess(), nbttagcompound)); + } e.setUUID(uUID); } } @@ -1742,9 +1756,14 @@ public class EntityValue extends Value throw new NBTSerializableValue.IncompatibleTypeException(this); } CompoundTag tag = new CompoundTag(); - tag.put("Data", getEntity().saveWithoutId(new CompoundTag())); - Registry> reg = getEntity().level().registryAccess().registryOrThrow(Registries.ENTITY_TYPE); - tag.put("Name", StringTag.valueOf(reg.getKey(getEntity().getType()).toString())); + Entity entity = getEntity(); + try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(entity.problemPath(), CarpetScriptServer.LOG)) { + final TagValueOutput output = TagValueOutput.createWithContext(reporter, entity.registryAccess()); + entity.save(output); + tag.put("Data", output.buildResult()); + } + Registry> reg = entity.level().registryAccess().lookupOrThrow(Registries.ENTITY_TYPE); + tag.put("Name", StringTag.valueOf(reg.getKey(entity.getType()).toString())); return tag; } } diff --git a/src/main/java/carpet/script/value/FormattedTextValue.java b/src/main/java/carpet/script/value/FormattedTextValue.java index b08e0942..3a8c5ee0 100644 --- a/src/main/java/carpet/script/value/FormattedTextValue.java +++ b/src/main/java/carpet/script/value/FormattedTextValue.java @@ -1,9 +1,13 @@ package carpet.script.value; +import carpet.script.exception.InternalExpressionException; +import com.mojang.serialization.DynamicOps; import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.chat.MutableComponent; public class FormattedTextValue extends StringValue @@ -86,7 +90,7 @@ public class FormattedTextValue extends StringValue { throw new NBTSerializableValue.IncompatibleTypeException(this); } - return StringTag.valueOf(Component.Serializer.toJson(text, regs)); + return serialize(regs); } @Override @@ -95,14 +99,14 @@ public class FormattedTextValue extends StringValue return combine(this, o); } - public String serialize(RegistryAccess regs) + public Tag serialize(RegistryAccess regs) { - return Component.Serializer.toJson(text, regs); + return ComponentSerialization.CODEC.encodeStart(regs.createSerializationContext(NbtOps.INSTANCE), text).getOrThrow(InternalExpressionException::new);// text.getContents() Component.Serializer.toJson(text, regs); } - public static FormattedTextValue deserialize(String serialized, RegistryAccess regs) + public static FormattedTextValue deserialize(Tag tag, RegistryAccess regs) { - return new FormattedTextValue(Component.Serializer.fromJson(serialized, regs)); + return new FormattedTextValue(ComponentSerialization.CODEC.decode(regs.createSerializationContext(NbtOps.INSTANCE), tag).getOrThrow(InternalExpressionException::new).getFirst()); } public static Component getTextByValue(Value value) diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index 1cc7f449..db54f1aa 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -6,7 +6,7 @@ import carpet.script.Expression; import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.Module; -import carpet.script.Tokenizer; +import carpet.script.Token; import carpet.script.exception.BreakStatement; import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExpressionException; @@ -28,7 +28,7 @@ import javax.annotation.Nullable; public class FunctionValue extends Value implements Fluff.ILazyFunction { private final Expression expression; - private final Tokenizer.Token token; + private final Token token; private final String name; private final LazyValue body; private Map outerState; @@ -37,7 +37,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction private static long variantCounter = 1; private long variant; - private FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List args, String varArgs) + private FunctionValue(Expression expression, Token token, String name, LazyValue body, List args, String varArgs) { this.expression = expression; this.token = token; @@ -49,7 +49,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction variant = 0L; } - public FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List args, String varArgs, Map outerState) + public FunctionValue(Expression expression, Token token, String name, LazyValue body, List args, String varArgs, Map outerState) { this.expression = expression; this.token = token; @@ -214,13 +214,13 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, List lazyParams) { List resolvedParams = unpackArgs(lazyParams, c); return execute(c, type, e, t, resolvedParams, null); } - public LazyValue execute(Context c, Context.Type type, Expression e, Tokenizer.Token t, List params, @Nullable ThreadValue freshNewCallingThread) + public LazyValue execute(Context c, Context.Type type, Expression e, Token t, List params, @Nullable ThreadValue freshNewCallingThread) { assertArgsOk(params, fixedArgs -> { if (fixedArgs) // wrong number of args for fixed args @@ -288,7 +288,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return expression; } - public Tokenizer.Token getToken() + public Token getToken() { return token; } diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index 99ae419c..1e2d183b 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -56,7 +56,7 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public String getString() { - return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); + return String.format(Locale.ROOT, "<%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); } }; } @@ -104,7 +104,7 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public String getString() { - return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); + return String.format(Locale.ROOT, "<%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); } }; } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index dfea2253..0d770809 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -587,13 +587,13 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf { throw new NBTSerializableValue.IncompatibleTypeException(this); } - tags.forEach(t -> tag.add(StringTag.valueOf(t.getAsString()))); + tags.forEach(t -> tag.add(StringTag.valueOf(t.asString().orElseThrow()))); return tag; } // only numbers / mixed types tags.forEach(cases.contains(TagTypeCompat.DBL) - ? (t -> tag.add(DoubleTag.valueOf(((NumericTag) t).getAsDouble()))) - : (t -> tag.add(LongTag.valueOf(((NumericTag) t).getAsLong())))); + ? (t -> tag.add(DoubleTag.valueOf(((NumericTag) t).doubleValue()))) + : (t -> tag.add(LongTag.valueOf(((NumericTag) t).longValue())))); return tag; } diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index f6df234c..ecb9e7d9 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -32,6 +32,7 @@ import net.minecraft.nbt.EndTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.LongTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NumericTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -63,6 +64,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa private Tag nbtTag = null; private Supplier nbtSupplier = null; private boolean owned = false; + private static TagParser tagParser = TagParser.create(NbtOps.INSTANCE); private NBTSerializableValue() { @@ -74,7 +76,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { try { - return (new TagParser(new StringReader(nbtString))).readValue(); + return tagParser.parseAsArgument( new StringReader(nbtString)); } catch (CommandSyntaxException e) { @@ -107,7 +109,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public static Value fromStack(ItemStack stack, RegistryAccess regs) { NBTSerializableValue value = new NBTSerializableValue(); - value.nbtSupplier = () -> stack.saveOptional(regs); + value.nbtSupplier = () -> ItemStack.CODEC.encodeStart(regs.createSerializationContext(NbtOps.INSTANCE), stack).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s)); return value; } @@ -127,7 +129,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { try { - Tag tag = (new TagParser(new StringReader(nbtString))).readValue(); + Tag tag = tagParser.parseAsArgument(new StringReader(nbtString)); NBTSerializableValue value = new NBTSerializableValue(tag); value.nbtString = null; return value; @@ -345,7 +347,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public static ItemStack parseItem(String itemString, @Nullable CompoundTag customTag, RegistryAccess regs) { if (customTag != null) { - return ItemStack.parseOptional(regs, customTag); + return ItemStack.CODEC.parse(regs.createSerializationContext(NbtOps.INSTANCE), customTag).getOrThrow(s -> new InternalExpressionException("Failed to parse item stack data: " + s)); } try { @@ -385,11 +387,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa if (t instanceof final NumericTag number) { // short and byte will never exceed float's precision, even int won't - return t instanceof LongTag || t instanceof IntTag ? NumericValue.of(number.getAsLong()) : NumericValue.of(number.getAsNumber()); + return t instanceof LongTag || t instanceof IntTag ? NumericValue.of(number.longValue()) : NumericValue.of(number.asNumber().orElseThrow()); } - if (t instanceof StringTag) + if (t instanceof StringTag stringTag) { - return StringValue.of(t.getAsString()); + return StringValue.of(stringTag.value()); } if (t instanceof EndTag) { @@ -408,13 +410,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa if (t instanceof final CompoundTag ctag) { Map pairs = new HashMap<>(); - for (String key : ctag.getAllKeys()) + for (String key : ctag.keySet()) { pairs.put(new StringValue(key), decodeTagDeep(ctag.get(key))); } return MapValue.wrap(pairs); } - if (t instanceof final CollectionTag ltag) + if (t instanceof final CollectionTag ltag) { List elems = new ArrayList<>(); for (Tag elem : ltag) @@ -477,17 +479,17 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { return !(ctag).isEmpty(); } - if (tag instanceof final CollectionTag ltag) + if (tag instanceof final CollectionTag ltag) { return !(ltag).isEmpty(); } if (tag instanceof final NumericTag number) { - return number.getAsDouble() != 0.0; + return number.doubleValue() != 0.0; } - if (tag instanceof StringTag) + if (tag instanceof StringTag st) { - return !tag.getAsString().isEmpty(); + return !st.value().isEmpty(); } return true; } @@ -569,7 +571,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa boolean modified = false; for (Tag target : targets) { - if (!(target instanceof final CollectionTag targetList)) + if (!(target instanceof final CollectionTag targetList)) { continue; } diff --git a/src/main/java/carpet/script/value/ScreenValue.java b/src/main/java/carpet/script/value/ScreenValue.java index a3c154ff..9f436eab 100644 --- a/src/main/java/carpet/script/value/ScreenValue.java +++ b/src/main/java/carpet/script/value/ScreenValue.java @@ -20,6 +20,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -199,7 +200,7 @@ public class ScreenValue extends Value this.screenHandler = null; return false; } - int runPermissionLevel = Vanilla.MinecraftServer_getRunPermissionLevel(player.server); + int runPermissionLevel = Vanilla.MinecraftServer_getRunPermissionLevel(player.getServer()); CommandSourceStack source = player.createCommandSourceStack().withPermission(runPermissionLevel); CarpetScriptHost executingHost = appHost.retrieveForExecution(source, player); try @@ -391,7 +392,7 @@ public class ScreenValue extends Value } else { - nbtList.add(itemStack.save(regs)); + nbtList.add(ItemStack.CODEC.encodeStart(regs.createSerializationContext(NbtOps.INSTANCE), itemStack).getOrThrow(InternalExpressionException::new)); } } return nbtList; diff --git a/src/main/java/carpet/script/value/ThreadValue.java b/src/main/java/carpet/script/value/ThreadValue.java index e5665557..793a2d5f 100644 --- a/src/main/java/carpet/script/value/ThreadValue.java +++ b/src/main/java/carpet/script/value/ThreadValue.java @@ -2,7 +2,7 @@ package carpet.script.value; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.Tokenizer; +import carpet.script.Token; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; @@ -28,7 +28,7 @@ public class ThreadValue extends LazyListValue private final AtomicReference coLock = new AtomicReference<>(Value.EOL); public final boolean isCoroutine; - public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List args) + public ThreadValue(Value pool, FunctionValue function, Expression expr, Token token, Context ctx, List args) { this.id = sequence++; this.isCoroutine = ctx.host.canSynchronouslyExecute(); @@ -37,7 +37,7 @@ public class ThreadValue extends LazyListValue Thread.yield(); } - public CompletableFuture getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List args) + public CompletableFuture getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Token token, Context ctx, List args) { ExecutorService executor = ctx.host.getExecutor(pool); ThreadValue callingThread = isCoroutine ? this : null; diff --git a/src/main/java/carpet/script/value/ValueConversions.java b/src/main/java/carpet/script/value/ValueConversions.java index 8bf58f1d..f9622974 100644 --- a/src/main/java/carpet/script/value/ValueConversions.java +++ b/src/main/java/carpet/script/value/ValueConversions.java @@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; +import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.Vec3i; @@ -30,6 +31,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.behavior.PositionTracker; import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; import net.minecraft.world.entity.ai.memory.WalkTarget; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -98,12 +100,17 @@ public class ValueConversions public static Value of(ItemStack stack, RegistryAccess regs) { return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of( - of(regs.registryOrThrow(Registries.ITEM).getKey(stack.getItem())), + of(stack.getItem(), regs), new NumericValue(stack.getCount()), NBTSerializableValue.fromStack(stack, regs) ); } + public static Value of(Item item, RegistryAccess regs) + { + return of(regs.lookupOrThrow(Registries.ITEM).getKey(item)); + } + public static Value of(Objective objective) { return ListValue.of( @@ -137,7 +144,7 @@ public class ValueConversions { if (dimensionValue instanceof EntityValue) { - return ((EntityValue) dimensionValue).getEntity().getCommandSenderWorld(); + return ((EntityValue) dimensionValue).getEntity().level(); } else if (dimensionValue instanceof BlockValue bv) { @@ -189,6 +196,11 @@ public class ValueConversions return of(tagKey.location()); } + public static Value of(HolderSet.Named tagKey) + { + return of(tagKey.key().location()); + } + public static Value of(@Nullable ResourceLocation id) { if (id == null) // should be Value.NULL @@ -253,7 +265,7 @@ public class ValueConversions } if (v instanceof final BlockPos pos) { - return new BlockValue(null, (ServerLevel) e.getCommandSenderWorld(), pos); + return new BlockValue(null, (ServerLevel) e.level(), pos); } if (v instanceof final Number number) { @@ -265,7 +277,7 @@ public class ValueConversions } if (v instanceof final UUID uuid) { - return ofUUID((ServerLevel) e.getCommandSenderWorld(), uuid); + return ofUUID((ServerLevel) e.level(), uuid); } if (v instanceof final DamageSource source) { @@ -276,16 +288,16 @@ public class ValueConversions } if (v instanceof final Path path) { - return fromPath((ServerLevel) e.getCommandSenderWorld(), path); + return fromPath((ServerLevel) e.level(), path); } if (v instanceof final PositionTracker tracker) { - return new BlockValue(null, (ServerLevel) e.getCommandSenderWorld(), tracker.currentBlockPosition()); + return new BlockValue(null, (ServerLevel) e.level(), tracker.currentBlockPosition()); } if (v instanceof final WalkTarget target) { return ListValue.of( - new BlockValue(null, (ServerLevel) e.getCommandSenderWorld(), target.getTarget().currentBlockPosition()), + new BlockValue(null, (ServerLevel) e.level(), target.getTarget().currentBlockPosition()), new NumericValue(target.getSpeedModifier()), new NumericValue(target.getCloseEnoughDist()) ); @@ -362,7 +374,7 @@ public class ValueConversions if (box.maxX() >= box.minX() && box.maxY() >= box.minY() && box.maxZ() >= box.minZ()) { pieces.add(ListValue.of( - NBTSerializableValue.nameFromRegistryId(regs.registryOrThrow(Registries.STRUCTURE_PIECE).getKey(piece.getType())), + NBTSerializableValue.nameFromRegistryId(regs.lookupOrThrow(Registries.STRUCTURE_PIECE).getKey(piece.getType())), (piece.getOrientation() == null) ? Value.NULL : new StringValue(piece.getOrientation().getName()), ListValue.fromTriple(box.minX(), box.minY(), box.minZ()), ListValue.fromTriple(box.maxX(), box.maxY(), box.maxZ()) @@ -451,10 +463,10 @@ public class ValueConversions public static Value ofBlockPredicate(RegistryAccess registryAccess, Predicate blockPredicate) { Vanilla.BlockPredicatePayload payload = Vanilla.BlockPredicatePayload.of(blockPredicate); - Registry blocks = registryAccess.registryOrThrow(Registries.BLOCK); + Registry blocks = registryAccess.lookupOrThrow(Registries.BLOCK); return ListValue.of( payload.state() == null ? Value.NULL : of(blocks.getKey(payload.state().getBlock())), - payload.tagKey() == null ? Value.NULL : of(blocks.getTag(payload.tagKey()).get().key()), + payload.tagKey() == null ? Value.NULL : of(blocks.get(payload.tagKey()).get().key()), MapValue.wrap(payload.properties()), payload.tag() == null ? Value.NULL : new NBTSerializableValue(payload.tag()) ); diff --git a/src/main/java/carpet/utils/BlockInfo.java b/src/main/java/carpet/utils/BlockInfo.java index e1519e85..ba41f635 100644 --- a/src/main/java/carpet/utils/BlockInfo.java +++ b/src/main/java/carpet/utils/BlockInfo.java @@ -9,8 +9,8 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.ai.goal.RandomStrollGoal; import net.minecraft.world.entity.ai.util.DefaultRandomPos; @@ -29,7 +29,7 @@ public class BlockInfo BlockState state = world.getBlockState(pos); Block block = state.getBlock(); String metastring = ""; - final Registry blocks = world.registryAccess().registryOrThrow(Registries.BLOCK); + final Registry blocks = world.registryAccess().lookupOrThrow(Registries.BLOCK); for (net.minecraft.world.level.block.state.properties.Property iproperty : state.getProperties()) { metastring += ", "+iproperty.getName() + '='+state.getValue(iproperty); @@ -75,8 +75,8 @@ public class BlockInfo private static Component wander_chances(BlockPos pos, ServerLevel worldIn) { PathfinderMob creature = new ZombifiedPiglin(EntityType.ZOMBIFIED_PIGLIN, worldIn); - creature.finalizeSpawn(worldIn, worldIn.getCurrentDifficultyAt(pos), MobSpawnType.NATURAL, null); - creature.moveTo(pos, 0.0F, 0.0F); + creature.finalizeSpawn(worldIn, worldIn.getCurrentDifficultyAt(pos), EntitySpawnReason.NATURAL, null); + creature.snapTo(pos, 0.0F, 0.0F); RandomStrollGoal wander = new RandomStrollGoal(creature, 0.8D); int success = 0; for (int i=0; i<1000; i++) diff --git a/src/main/java/carpet/utils/CarpetProfiler.java b/src/main/java/carpet/utils/CarpetProfiler.java index a4a02067..dbd0cde2 100644 --- a/src/main/java/carpet/utils/CarpetProfiler.java +++ b/src/main/java/carpet/utils/CarpetProfiler.java @@ -279,11 +279,11 @@ public class CarpetProfiler final RegistryAccess regs = section.getKey().registryAccess(); if (section.getValue() instanceof EntityType) { - id = regs.registryOrThrow(Registries.ENTITY_TYPE).getKey((EntityType) section.getValue()); + id = regs.lookupOrThrow(Registries.ENTITY_TYPE).getKey((EntityType) section.getValue()); } else { - id = regs.registryOrThrow(Registries.BLOCK_ENTITY_TYPE).getKey((BlockEntityType) section.getValue()); + id = regs.lookupOrThrow(Registries.BLOCK_ENTITY_TYPE).getKey((BlockEntityType) section.getValue()); } String name = "minecraft".equals(id.getNamespace())?id.getPath():id.toString(); if (section.getKey().isClientSide) diff --git a/src/main/java/carpet/utils/CommandHelper.java b/src/main/java/carpet/utils/CommandHelper.java index d6825a91..9b97f652 100644 --- a/src/main/java/carpet/utils/CommandHelper.java +++ b/src/main/java/carpet/utils/CommandHelper.java @@ -23,7 +23,7 @@ public final class CommandHelper { { return; } - server.tell(new TickTask(server.getTickCount(), () -> + server.schedule(new TickTask(server.getTickCount(), () -> { try { for (ServerPlayer player : server.getPlayerList().getPlayers()) { diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index 36af4c17..18dabb68 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -10,12 +10,14 @@ import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -146,11 +148,11 @@ public class Messenger Style previousStyle = previousMessage.getStyle(); MutableComponent ret = previousMessage; previousMessage.setStyle(switch (desc.charAt(0)) { - case '?' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message.substring(1))); - case '!' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, message.substring(1))); - case '^' -> previousStyle.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, c(message.substring(1)))); - case '@' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, message.substring(1))); - case '&' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, message.substring(1))); + case '?' -> previousStyle.withClickEvent(new ClickEvent.SuggestCommand(message.substring(1))); + case '!' -> previousStyle.withClickEvent(new ClickEvent.RunCommand(message.substring(1))); + case '^' -> previousStyle.withHoverEvent(new HoverEvent.ShowText(c(message.substring(1)))); + case '@' -> previousStyle.withClickEvent(new ClickEvent.OpenUrl(URI.create(message.substring(1)))); + case '&' -> previousStyle.withClickEvent(new ClickEvent.CopyToClipboard(message.substring(1))); default -> { // Create a new component ret = Component.literal(str); ret.setStyle(parseStyle(desc)); @@ -243,7 +245,7 @@ public class Messenger } public static void m(Player player, Object ... fields) { - player.sendSystemMessage(Messenger.c(fields)); + ((ServerPlayer)player).sendSystemMessage(Messenger.c(fields)); } /* @@ -287,7 +289,7 @@ public class Messenger public static void send(Player player, Collection lines) { - lines.forEach(message -> player.sendSystemMessage(message)); + lines.forEach(message -> ((ServerPlayer)player).sendSystemMessage(message)); } public static void send(CommandSourceStack source, Collection lines) { @@ -301,7 +303,7 @@ public class Messenger LOG.error("Message not delivered: "+message); server.sendSystemMessage(Component.literal(message)); Component txt = c("gi "+message); - for (Player entityplayer : server.getPlayerList().getPlayers()) + for (ServerPlayer entityplayer : server.getPlayerList().getPlayers()) { entityplayer.sendSystemMessage(txt); } @@ -311,7 +313,7 @@ public class Messenger if (server == null) LOG.error("Message not delivered: "+message.getString()); server.sendSystemMessage(message); - for (Player entityplayer : server.getPlayerList().getPlayers()) + for (ServerPlayer entityplayer : server.getPlayerList().getPlayers()) { entityplayer.sendSystemMessage(message); } diff --git a/src/main/java/carpet/utils/MobAI.java b/src/main/java/carpet/utils/MobAI.java index 454d234b..193b1565 100644 --- a/src/main/java/carpet/utils/MobAI.java +++ b/src/main/java/carpet/utils/MobAI.java @@ -30,7 +30,7 @@ public class MobAI public static boolean isTracking(Entity e, TrackingType type) { - if (e.getCommandSenderWorld().isClientSide()) + if (e.level().isClientSide()) return false; Set currentTrackers = aiTrackers.get(e.getType()); if (currentTrackers == null) @@ -64,7 +64,7 @@ public class MobAI { types.addAll(type.types); } - return types.stream().map(t -> source.registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getKey(t).getPath()); + return types.stream().map(t -> source.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).getKey(t).getPath()); } public static Stream availableFor(EntityType entityType) diff --git a/src/main/java/carpet/utils/PerimeterDiagnostics.java b/src/main/java/carpet/utils/PerimeterDiagnostics.java index 0b7be1b6..439f505a 100644 --- a/src/main/java/carpet/utils/PerimeterDiagnostics.java +++ b/src/main/java/carpet/utils/PerimeterDiagnostics.java @@ -5,11 +5,12 @@ import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.FluidTags; +import net.minecraft.util.random.Weighted; import net.minecraft.world.entity.AgeableMob; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnPlacements; import net.minecraft.world.entity.ambient.AmbientCreature; import net.minecraft.world.entity.animal.WaterAnimal; @@ -87,8 +88,8 @@ public class PerimeterDiagnostics PerimeterDiagnostics diagnostic = new PerimeterDiagnostics(worldserver,ctype,el); EntityType type = EntityType.ZOMBIE; if (el != null) type = el.getType(); - int minY = worldserver.getMinBuildHeight(); - int maxY = worldserver.getMaxBuildHeight(); + int minY = worldserver.getMinY(); + int maxY = worldserver.getMaxY(); for (int x = -128; x <= 128; ++x) { for (int z = -128; z <= 128; ++z) @@ -162,9 +163,10 @@ public class PerimeterDiagnostics if (sle == null || !worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap().contains(sle)) { sle = null; - for (MobSpawnSettings.SpawnerData sle: worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap()) + for (Weighted wsle: worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap()) { - if (el.getType() == sle.type) + MobSpawnSettings.SpawnerData sle = wsle.value(); + if (el.getType() == sle.type()) { this.sle = sle; break; @@ -176,11 +178,11 @@ public class PerimeterDiagnostics } } - if (SpawnPlacements.isSpawnPositionOk(sle.type, worldServer, pos)) + if (SpawnPlacements.isSpawnPositionOk(sle.type(), worldServer, pos)) { - el.moveTo(pos.getX() + 0.5F, pos.getY(), pos.getZ()+0.5F, 0.0F, 0.0F); - return el.checkSpawnObstruction(worldServer) && el.checkSpawnRules(worldServer, MobSpawnType.NATURAL) && - SpawnPlacements.checkSpawnRules(el.getType(),(ServerLevel)el.getCommandSenderWorld(), MobSpawnType.NATURAL, el.blockPosition(), el.getCommandSenderWorld().random) && + el.snapTo(pos.getX() + 0.5F, pos.getY(), pos.getZ()+0.5F, 0.0F, 0.0F); + return el.checkSpawnObstruction(worldServer) && el.checkSpawnRules(worldServer, EntitySpawnReason.NATURAL) && + SpawnPlacements.checkSpawnRules(el.getType(),(ServerLevel)el.level(), EntitySpawnReason.NATURAL, el.blockPosition(), el.level().random) && worldServer.noCollision(el); // check collision rules once they stop fiddling with them after 1.14.1 } return false; diff --git a/src/main/java/carpet/utils/SpawnOverrides.java b/src/main/java/carpet/utils/SpawnOverrides.java index 575b491d..d4c05f40 100644 --- a/src/main/java/carpet/utils/SpawnOverrides.java +++ b/src/main/java/carpet/utils/SpawnOverrides.java @@ -8,7 +8,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.StructureManager; @@ -32,29 +32,29 @@ public class SpawnOverrides { static { addOverride(() -> CarpetSettings.huskSpawningInTemples, MobCategory.MONSTER, BuiltinStructures.DESERT_PYRAMID, StructureSpawnOverride.BoundingBoxType.STRUCTURE, - WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1, 1)) + WeightedList.of(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1)) ); addOverride(() -> CarpetSettings.shulkerSpawningInEndCities, MobCategory.MONSTER, BuiltinStructures.END_CITY, StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 10, 4, 4)) + WeightedList.of(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 4, 4)) ); addOverride(() -> CarpetSettings.piglinsSpawningInBastions, MobCategory.MONSTER, BuiltinStructures.BASTION_REMNANT, StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create( - new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE, 5, 1, 2), - new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 10, 2, 4), - new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 2, 1, 2) - ) + WeightedList.builder() + .add(new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE,1, 2), 5) + .add(new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 2, 4), 10) + .add(new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 1, 2), 2) + .build() ); } public static void addOverride(BooleanSupplier when, MobCategory cat, ResourceKey poo, - StructureSpawnOverride.BoundingBoxType type, WeightedRandomList spawns) { + StructureSpawnOverride.BoundingBoxType type, WeightedList spawns) { carpetOverrides.put(Pair.of(cat, poo), Pair.of(when, new StructureSpawnOverride(type, spawns))); } - public static WeightedRandomList test(StructureManager structureFeatureManager, LongSet foo, - MobCategory cat, Structure confExisting, BlockPos where) { - ResourceLocation resource = structureFeatureManager.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(confExisting); + public static WeightedList test(StructureManager structureFeatureManager, LongSet foo, + MobCategory cat, Structure confExisting, BlockPos where) { + ResourceLocation resource = structureFeatureManager.registryAccess().lookupOrThrow(Registries.STRUCTURE).getKey(confExisting); ResourceKey key = ResourceKey.create(Registries.STRUCTURE, resource); final Pair spawnData = carpetOverrides.get(Pair.of(cat, key)); if (spawnData == null || !spawnData.getKey().getAsBoolean()) return null; @@ -76,7 +76,7 @@ public class SpawnOverrides { public static boolean isStructureAtPosition(ServerLevel level, ResourceKey structureKey, BlockPos pos) { - final Structure fortressFeature = level.registryAccess().registryOrThrow(Registries.STRUCTURE).get(structureKey); + final Structure fortressFeature = level.registryAccess().lookupOrThrow(Registries.STRUCTURE).getValue(structureKey); if (fortressFeature == null) { return false; } diff --git a/src/main/java/carpet/utils/SpawnReporter.java b/src/main/java/carpet/utils/SpawnReporter.java index 512431c9..3c086e4f 100644 --- a/src/main/java/carpet/utils/SpawnReporter.java +++ b/src/main/java/carpet/utils/SpawnReporter.java @@ -12,12 +12,14 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; +import net.minecraft.util.random.Weighted; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnPlacements; import net.minecraft.world.entity.animal.Ocelot; import net.minecraft.world.item.DyeColor; @@ -380,7 +382,7 @@ public class SpawnReporter } if (entity instanceof Ocelot) { - for (Entity e: entity.getCommandSenderWorld().getEntities(entity, entity.getBoundingBox())) + for (Entity e: entity.level().getEntities(entity, entity.getBoundingBox())) { e.discard(); } @@ -389,8 +391,8 @@ public class SpawnReporter } // yeeted from NaturalSpawner - temporary access fix - private static List getSpawnEntries(ServerLevel serverLevel, StructureManager structureManager, ChunkGenerator chunkGenerator, MobCategory mobCategory, BlockPos blockPos, @Nullable Holder holder) { - return NaturalSpawner.isInNetherFortressBounds(blockPos, serverLevel, mobCategory, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES.unwrap() : chunkGenerator.getMobsAt(holder != null ? holder : serverLevel.getBiome(blockPos), structureManager, mobCategory, blockPos).unwrap(); + private static WeightedList getSpawnEntries(ServerLevel serverLevel, StructureManager structureManager, ChunkGenerator chunkGenerator, MobCategory mobCategory, BlockPos blockPos, @Nullable Holder holder) { + return NaturalSpawner.isInNetherFortressBounds(blockPos, serverLevel, mobCategory, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES : chunkGenerator.getMobsAt(holder != null ? holder : serverLevel.getBiome(blockPos), structureManager, mobCategory, blockPos); } public static List report(BlockPos pos, ServerLevel worldIn) @@ -407,21 +409,22 @@ public class SpawnReporter for (MobCategory category : cachedMobCategories()) { String categoryCode = String.valueOf(category).substring(0, 3); - List lst = getSpawnEntries(worldIn, worldIn.structureManager(), worldIn.getChunkSource().getGenerator(), category, pos, worldIn.getBiome(pos)); + WeightedList lst = getSpawnEntries(worldIn, worldIn.structureManager(), worldIn.getChunkSource().getGenerator(), category, pos, worldIn.getBiome(pos)); if (lst != null && !lst.isEmpty()) { - for (MobSpawnSettings.SpawnerData spawnEntry : lst) + for (Weighted wspawnEntry : lst.unwrap()) { - if (SpawnPlacements.getPlacementType(spawnEntry.type) == null) + MobSpawnSettings.SpawnerData spawnEntry = wspawnEntry.value(); + if (SpawnPlacements.getPlacementType(spawnEntry.type()) == null) continue; // vanilla bug - boolean canSpawn = SpawnPlacements.isSpawnPositionOk(spawnEntry.type, worldIn, pos); + boolean canSpawn = SpawnPlacements.isSpawnPositionOk(spawnEntry.type(), worldIn, pos); int willSpawn = -1; boolean fits = false; Mob mob; try { - mob = (Mob) spawnEntry.type.create(worldIn); + mob = (Mob) spawnEntry.type().create(worldIn, EntitySpawnReason.NATURAL); } catch (Exception e) { @@ -436,16 +439,16 @@ public class SpawnReporter { float f = x + 0.5F; float f1 = z + 0.5F; - mob.moveTo(f, y, f1, worldIn.random.nextFloat() * 360.0F, 0.0F); + mob.snapTo(f, y, f1, worldIn.random.nextFloat() * 360.0F, 0.0F); fits = worldIn.noCollision(mob); EntityType etype = mob.getType(); for (int i = 0; i < 20; ++i) { if ( - SpawnPlacements.checkSpawnRules(etype,worldIn, MobSpawnType.NATURAL, pos, worldIn.random) && + SpawnPlacements.checkSpawnRules(etype,worldIn, EntitySpawnReason.NATURAL, pos, worldIn.random) && SpawnPlacements.isSpawnPositionOk(etype, worldIn, pos) && - mob.checkSpawnRules(worldIn, MobSpawnType.NATURAL) + mob.checkSpawnRules(worldIn, EntitySpawnReason.NATURAL) // && mob.canSpawn(worldIn) // entity collisions // mostly - except ocelots ) { @@ -459,7 +462,7 @@ public class SpawnReporter willSpawn += 1; } } - mob.finalizeSpawn(worldIn, worldIn.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.NATURAL, null); + mob.finalizeSpawn(worldIn, worldIn.getCurrentDifficultyAt(mob.blockPosition()), EntitySpawnReason.NATURAL, null); // the code invokes onInitialSpawn after getCanSpawHere fits = fits && worldIn.noCollision(mob); @@ -467,7 +470,7 @@ public class SpawnReporter try { - mob = (Mob) spawnEntry.type.create(worldIn); + mob = (Mob) spawnEntry.type().create(worldIn, EntitySpawnReason.NATURAL); } catch (Exception e) { @@ -479,12 +482,12 @@ public class SpawnReporter String mobTypeName = mob.getType().getDescription().getString(); //String pack_size = Integer.toString(mob.getMaxSpawnClusterSize());//String.format("%d-%d", animal.minGroupCount, animal.maxGroupCount); - int weight = spawnEntry.getWeight().asInt(); + int weight = wspawnEntry.weight(); if (canSpawn) { String color = (fits && willSpawn > 0) ? "e" : "gi"; rep.add(Messenger.c( - String.format("%s %s: %s (%d:%d-%d/%d), can: ", color, categoryCode, mobTypeName, weight, spawnEntry.minCount, spawnEntry.maxCount, mob.getMaxSpawnClusterSize()), + String.format("%s %s: %s (%d:%d-%d/%d), can: ", color, categoryCode, mobTypeName, weight, spawnEntry.minCount(), spawnEntry.maxCount(), mob.getMaxSpawnClusterSize()), "l YES", color + " , fit: ", (fits ? "l YES" : "r NO"), @@ -494,7 +497,7 @@ public class SpawnReporter } else { - rep.add(Messenger.c(String.format("gi %s: %s (%d:%d-%d/%d), can: ", categoryCode, mobTypeName, weight, spawnEntry.minCount, spawnEntry.maxCount, mob.getMaxSpawnClusterSize()), "n NO")); + rep.add(Messenger.c(String.format("gi %s: %s (%d:%d-%d/%d), can: ", categoryCode, mobTypeName, weight, spawnEntry.minCount(), spawnEntry.maxCount(), mob.getMaxSpawnClusterSize()), "n NO")); } killEntity(mob); } diff --git a/src/main/java/carpet/utils/WoolTool.java b/src/main/java/carpet/utils/WoolTool.java index 7d3fa7fa..c8ba39a0 100644 --- a/src/main/java/carpet/utils/WoolTool.java +++ b/src/main/java/carpet/utils/WoolTool.java @@ -10,6 +10,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DyeColor; @@ -60,7 +61,7 @@ public class WoolTool *
  • Green - Prints the contents of the counter of the colour of wool underneath the carpet
  • * */ - public static void carpetPlacedAction(DyeColor color, Player placer, BlockPos pos, ServerLevel worldIn) + public static void carpetPlacedAction(DyeColor color, ServerPlayer placer, BlockPos pos, ServerLevel worldIn) { if (!CarpetSettings.carpets) { diff --git a/src/main/resources/assets/carpet/lang/es_ar.json b/src/main/resources/assets/carpet/lang/es_ar.json new file mode 100644 index 00000000..28abc299 --- /dev/null +++ b/src/main/resources/assets/carpet/lang/es_ar.json @@ -0,0 +1,432 @@ +{ + // Settings command UI elements + + "carpet.settings.command.browse_categories": "Buscar categorias", + "carpet.settings.command.version": "Version", + "carpet.settings.command.list_all_category": "Lista de todas las configuraciones de %s", + "carpet.settings.command.current_settings_header": "Configuraciones actuales de %s", + "carpet.settings.command.switch_to": "Alternar a %s", + "carpet.settings.command.unknown_rule": "Regla desconocida", + "carpet.settings.command.current_from_file_header": "Configuraciones de inicio actual de %s de %s", + "carpet.settings.command.mod_settings_matching": "%s configuraciones correspondientes \"%s\" ", + "carpet.settings.command.all_mod_settings": "Todas las configuraciones de %s", + "carpet.settings.command.tags": "Tags", + "carpet.settings.command.change_permanently": "Cambiar permanentemente", + "carpet.settings.command.change_permanently_tooltip": "Haz click para mantener las configuraciones en %s para que sea permanente.", + "carpet.settings.command.default_set": "La regla %s ahora se establecerá como %s ", + "carpet.settings.command.default_removed": "La regla %s ya no se establecerá al inicio", + "carpet.settings.command.current_value": "Valor actual", + + // Categories + + "carpet.category.bugfix": "Arreglo de Bugs", + "carpet.category.survival": "Supervivencia", + "carpet.category.creative": "Creativo", + "carpet.category.experimental": "Experimental", + "carpet.category.optimization": "Optimizacion", + "carpet.category.feature": "Caracteristicas", + "carpet.category.command": "Comandos", + "carpet.category.tnt": "TNT", + "carpet.category.dispenser": "Dispensandor", + "carpet.category.scarpet": "Scarpet", + "carpet.category.client": "Cliente", + + // Rules + + // allowSpawningOfflinePlayers + "carpet.rule.allowSpawningOfflinePlayers.desc": "Permite aparecer jugadores en modo offline", + + // antiCheatDisabled + "carpet.rule.antiCheatDisabled.desc": "Evita que los jugadores se bugeen al moverse muy rapido", + + "carpet.rule.antiCheatDisabled.extra.0": "... fue expulsado por 'volar'", + "carpet.rule.antiCheatDisabled.extra.1": "Coloca mas confianza en el posicionamiento de los clientes", + "carpet.rule.antiCheatDisabled.extra.2": "Aumenta la distancia de minería permitida por el jugador a 32 bloques", + + // carpetCommandPermissionLevel + "carpet.rule.carpetCommandPermissionLevel.desc": "Nivel de permiso del comando de carpet. Tambien puede ser definido con el archivo .conf", + + // carpets + "carpet.rule.carpets.desc": "Colocar carpets puede causar problemas con carpet para usuarios sin OP", + + // chainStone + "carpet.rule.chainStone.desc": "Las cadenas se van a adherir a otras en los extremos", + + "carpet.rule.chainStone.extra.0": "y se van a adherir a bloques conectados directamente en ellas.", + "carpet.rule.chainStone.extra.1": "con stick_to_all: se van a adherir si no estan visualmente conectadas.", + + // cleanLogs + "carpet.rule.cleanLogs.desc": "Remueve mensajes innecesarios de los logs", + + "carpet.rule.cleanLogs.extra.0": "No muestra 'Maximum sound pool size 247 reached'", + "carpet.rule.cleanLogs.extra.1": "Que es normal con granjas decentes y mecanismos", + + // commandDistance + "carpet.rule.commandDistance.desc": "Habilita el comando /distance para medir la distancia entre puntos en el juego.", + + "carpet.rule.commandDistance.extra.0": "Habilita la accion de poner brown carpets si la rule 'carpets' esta habilitada.", + + // commandDraw + "carpet.rule.commandDraw.desc": "Habilita el comando /draw", + + "carpet.rule.commandDraw.extra.0": "... permite dibujar formas simples o", + "carpet.rule.commandDraw.extra.1": "otras formas que son dificiles de hacer de forma normal.", + + // commandInfo + "carpet.rule.commandInfo.desc": "Habilita el comando /info para bloques", + + "carpet.rule.commandInfo.extra.0": "Habilita tambien la accion de colocar gray carpets", + "carpet.rule.commandInfo.extra.1": "si la regla 'carpets' esta habilitada tambien.", + + // commandLog + "carpet.rule.commandLog.desc": "Habilita el comando /log para monitorear eventos en el chat o overlays", + + // commandPerimeterInfo + "carpet.rule.commandPerimeterInfo.desc": "Habilita el comando /perimeterinfo", + + "carpet.rule.commandPerimeterInfo.extra.0": "... que scanea la zona alrededor para ver las zonas de spawn", + + // commandPlayer + "carpet.rule.commandPlayer.desc": "Habilita el comando /player para controlar/spawnear jugadores.", + + // commandProfile + "carpet.rule.commandProfile.desc": "Habilita el comando /profile para monitorear el rendimiento del juego", + + "carpet.rule.commandProfile.extra.0": "habilita los comandos de /tick ", + + // commandScript + "carpet.rule.commandScript.desc": "Habilita el comando /script", + + "carpet.rule.commandScript.extra.0": "Es un IN-Game Scripting API para el lenguaje de programación Scarpet", + + // commandScriptACE + "carpet.rule.commandScriptACE.desc": "Habilita restricciones para el codigo arbitrario ejecutado por Scarpet", + + "carpet.rule.commandScriptACE.extra.0": "Usuarios que no tienen los permisos necesarios.", + "carpet.rule.commandScriptACE.extra.1": "no van a poder cargar comandos o scripts con scarpet.", + "carpet.rule.commandScriptACE.extra.2": "tambien van a ser los permisos que van a tener", + "carpet.rule.commandScriptACE.extra.3": "cuando corran comandos con run()", + + // commandSpawn + "carpet.rule.commandSpawn.desc": "Habilita el comando /spawn para analizar el spawneo", + + // commandTick + "carpet.rule.commandTick.desc": "Habilita el comando /tick para controlar el reloj interno del juego", + + // commandTrackAI + "carpet.rule.commandTrackAI.desc": "Permite localizar mobs con IA mediante el comando /track", + + // creativeFlyDrag + "carpet.rule.creativeFlyDrag.desc": "Resistencia del Aire en Creativo", + + "carpet.rule.creativeFlyDrag.extra.0": "Incrementar la resistencia va a bajar la velocidad de vuelo", + "carpet.rule.creativeFlyDrag.extra.1": "Asi que hay que ajustar la velocidad acorde", + "carpet.rule.creativeFlyDrag.extra.2": "Con 1.0 de resistencia, usando velocidad de 11 coincide con las velocidades vanilla.", + "carpet.rule.creativeFlyDrag.extra.3": "Configuración puramente del lado del cliente, eso significa", + "carpet.rule.creativeFlyDrag.extra.4": "tenerlo activado en servers dedicados no va a tener ningun efecto", + "carpet.rule.creativeFlyDrag.extra.5": "pero tambien signfica que va a funcionar en servidores vanilla", + + // creativeFlySpeed + "carpet.rule.creativeFlySpeed.desc": "Multiplicador de Velocidad del Modo Creativo", + + "carpet.rule.creativeFlySpeed.extra.0": "Configuración puramente del lado del cliente, eso significa", + "carpet.rule.creativeFlySpeed.extra.1": "que de tenerla no tendra efecto del lado del servidor", + "carpet.rule.creativeFlySpeed.extra.2": "pero tambien significa que funcionaria en servidores vanilla.", + + // creativeNoClip + "carpet.rule.creativeNoClip.desc": "No Clip en Creativo", + + "carpet.rule.creativeNoClip.extra.0": "En servidores tiene que ser puestos en ambos ", + "carpet.rule.creativeNoClip.extra.1": "server y cliente para funcionar correctamente.", + "carpet.rule.creativeNoClip.extra.2": "No tiene efecto si es solo en el server.", + "carpet.rule.creativeNoClip.extra.3": "Puede permitir atravesar paredes", + "carpet.rule.creativeNoClip.extra.4": "Si solo es puesto en carpet del lado del cliente", + "carpet.rule.creativeNoClip.extra.5": "pero requiere alguna para magia para", + "carpet.rule.creativeNoClip.extra.6": "permitir a los jugadores entrar a bloques.", + + // creativePlayersLoadChunks + "carpet.rule.creativePlayersLoadChunks.desc": "Jugadores en Creativo cargan chunks, o no! como los espectadores!", + + "carpet.rule.creativePlayersLoadChunks.extra.0": "alterna el compartamiento si el jugador esta en modo espectador y cambia el gamerule 'spectatorsGenerateChunks.'", + + // ctrlQCraftingFix + "carpet.rule.ctrlQCraftingFix.desc": "Dropear el stack entero tambien funciona desde la UI de Crafteo", + + // customMOTD + "carpet.rule.customMOTD.desc": "Setea un mensaje de MOTD distinto en el cliente cuando quiere conectarse al server", + + "carpet.rule.customMOTD.extra.0": "usa '_' para usar al inicio en server.properties", + + // defaultLoggers + "carpet.rule.defaultLoggers.desc": "Setea unos loggers en su configuracion default para todos los jugadores nuevos", + + "carpet.rule.defaultLoggers.extra.0": "usa csv, como 'tps,mobcaps' para multiples loggers, none para ninguno", + + // desertShrubs + "carpet.rule.desertShrubs.desc": "Los saplings se convierten en Shrubs del desierto si no tienen agua y estan en climas calidos", + + // explosionNoBlockDamage + "carpet.rule.explosionNoBlockDamage.desc": "Explosiones no destruyen bloques", + + // fastRedstoneDust + "carpet.rule.fastRedstoneDust.desc": "Optimizaciones de lag de restone", + + "carpet.rule.fastRedstoneDust.extra.0": "Hecha por Theosib", + "carpet.rule.fastRedstoneDust.extra.1": ".. tambien agrega algunos compartamientos normales y el bug MC-11193", + "carpet.rule.fastRedstoneDust.extra.2": "el uso de los mecanismos como en vanilla no esta asegurado.", + + // fillLimit + "carpet.rule.fillLimit.desc": "[Deprecado] Customizable fill/fillbiome/clone limite de volumen", + + "carpet.rule.fillLimit.extra.0": "Usa la gamerule vanilla. Esta opcion sera removida en la 1.20.0", + + // fillUpdates + "carpet.rule.fillUpdates.desc": "fill/clone/setblock and structure blocks cause block updates", + + // flippinCactus + "carpet.rule.flippinCactus.desc": "Players can flip and rotate blocks when holding cactus", + + "carpet.rule.flippinCactus.extra.0": "No se actualizan los bloques cuando se rotan/voltean", + "carpet.rule.flippinCactus.extra.1": "Se aplica a los pistones, observers, droppers, repetidores, escaleras, glazed terracotta etc...", + + // fogOff + "carpet.rule.fogOff.desc": "Remueve el fog en el nether y en el end", + + "carpet.rule.fogOff.extra.0": "Mejora la visibilidad, pero se ve raro", + + // forceloadLimit + "carpet.rule.forceloadLimit.desc": "Limite customizable de la carga forzada de chunks", + + // hardcodeTNTangle + "carpet.rule.hardcodeTNTangle.desc": "Setea el angulo horizontal aleatorio de la TNT para analizar los mecanismos de TNT", + + "carpet.rule.hardcodeTNTangle.extra.0": "Ponlo en -1 para compartamiento normal", + + // hopperCounters + "carpet.rule.hopperCounters.desc": "hoppers apuntando a lana va a contar items pasando atraves de el", + + "carpet.rule.hopperCounters.extra.0": "Habilita el commando /counter, y las acciones mientras pones alfombras rojas y verdes en lana", + "carpet.rule.hopperCounters.extra.1": "Usa /counter reset para resetear el contador, y /counter para consultar", + "carpet.rule.hopperCounters.extra.2": "En survival, pon una alfombra verde del mismo color lana para consultar, roja para resetear los contadores", + "carpet.rule.hopperCounters.extra.3": "Los contadores son globales y compartidos entre jugadores, 16 canales disponibles", + "carpet.rule.hopperCounters.extra.4": "Los items contados son destruidos, cuenta hasta un stack por tick por hopper", + + // huskSpawningInTemples + "carpet.rule.huskSpawningInTemples.desc": "Los husk solo pueden spawnear en templos", + + // interactionUpdates + "carpet.rule.interactionUpdates.desc": "poner bloques causa block updates ", + + // lagFreeSpawning + "carpet.rule.lagFreeSpawning.desc": "Spawnear requiere mucho menos CPU Y Memoria", + + // language + "carpet.rule.language.desc": "Setea el lenguaje en Carpet", + + // lightEngineMaxBatchSize + "carpet.rule.lightEngineMaxBatchSize.desc": "Cambia el tamaño máximo del lote de tareas ligeras", + + "carpet.rule.lightEngineMaxBatchSize.extra.0": "Permite por una tolerancia de limite mayor de light supression", + "carpet.rule.lightEngineMaxBatchSize.extra.1": "Ponerlo en 5 - Limite default definido por el juego", + + // lightningKillsDropsFix + "carpet.rule.lightningKillsDropsFix.desc": "Los rayos no matan los drops de un mob muerto por un rayo", + + "carpet.rule.lightningKillsDropsFix.extra.0": "Activarlo en true hace que los rayos no borren los drops de los mobs", + "carpet.rule.lightningKillsDropsFix.extra.1": "Arregla [MC-206922](https://bugs.mojang.com/browse/MC-206922).", + + // liquidDamageDisabled + "carpet.rule.liquidDamageDisabled.desc": "Deshabilita romper bloques por liquidos fluyendo", + + // maxEntityCollisions + "carpet.rule.maxEntityCollisions.desc": "Customizable limite de colisiones de entidad, 0 para no tener limites", + + // mergeTNT + "carpet.rule.mergeTNT.desc": "Fusiona entidades TNT fijas activadas", + + // missingTools + "carpet.rule.missingTools.desc": "El vidrio puede ser roto mas rapido con el pico", + + // moreBlueSkulls + "carpet.rule.moreBlueSkulls.desc": "Incrementa las cabezas disparadas por el wither", + + // movableAmethyst + "carpet.rule.movableAmethyst.desc": "Permite los bloques spawneables de amatista moverse", + + "carpet.rule.movableAmethyst.extra.0": "Permite moverlos con pistones", + "carpet.rule.movableAmethyst.extra.1": "tambien añade un drop extra cuand se pica con toque de seda", + + // movableBlockEntities + "carpet.rule.movableBlockEntities.desc": "Pistones pueden mover block entities, como hoppers, cofres etc.", + + // optimizedTNT + "carpet.rule.optimizedTNT.desc": "TNT causa menos lag cuando explota en el mismo lugar y en liquidos", + + // perfPermissionLevel + "carpet.rule.perfPermissionLevel.desc": "Se necesitan permisos para el comando /perf", + + // persistentParrots + "carpet.rule.persistentParrots.desc": "Loros no salen de tus codos hasta que no recibas el daño necesario", + + // piglinsSpawningInBastions + "carpet.rule.piglinsSpawningInBastions.desc": "Piglins van a respawnear en los remenantes de bastions", + + "carpet.rule.piglinsSpawningInBastions.extra.0": "Incluye piglins, brutes, y unos hoglins", + + // pingPlayerListLimit + "carpet.rule.pingPlayerListLimit.desc": "Customizable ping del servidor (menu Multiplayer) lista de jugadores limite", + + // placementRotationFix + "carpet.rule.placementRotationFix.desc": "arregla problema de posicionamiento del bloque cuando el jugador gira rapidamente mientras pone bloques", + + // portalCreativeDelay + "carpet.rule.portalCreativeDelay.desc": "Tiempo necesario en ticks para usar un portal del nether en creativo", + + // portalSurvivalDelay + "carpet.rule.portalSurvivalDelay.desc": "Tiempo necesario en ticks para usar un portal del nether en survival", + + // pushLimit + "carpet.rule.pushLimit.desc": "Limite Customizable de bloques movibles por los Pistones", + + // quasiConnectivity + "carpet.rule.quasiConnectivity.desc": "Pistones, droppers, y dispensers checkean por poder en los bloque(s) sobre ellos.", + + "carpet.rule.quasiConnectivity.extra.0": "Define el rango en que los pistones, droppers, y dispensers checkean por 'quasi power'.", + + // railPowerLimit + "carpet.rule.railPowerLimit.desc": "Rango personalizado de poder de los Railes activables", + + // renewableBlackstone + "carpet.rule.renewableBlackstone.desc": "Generador de Basalto en el nether sin soul sand abajo ", + + "carpet.rule.renewableBlackstone.extra.0": " .. se va a convertir en blackstone ", + + // renewableCoral + "carpet.rule.renewableCoral.desc": "Estructuras de Coral structures van a crecer con polvo de hueso con plantas de coral", + + "carpet.rule.renewableCoral.extra.0": "La ampliación también permite el cultivo a partir de abanicos de coral para una agricultura sostenible fuera de los océanos cálidos.", + + // renewableDeepslate + "carpet.rule.renewableDeepslate.desc": "Lava y agua generan deepslate y cobbled deepslate en la capa Y0", + + // renewableSponges + "carpet.rule.renewableSponges.desc": "Guardianes se convierten en Elder Guardian cuando son alcanzados por un rayo", + + // rotatorBlock + "carpet.rule.rotatorBlock.desc": "Cactus en dispensers rota bloques.", + + "carpet.rule.rotatorBlock.extra.0": "Rota bloques contrario a las agujas del reloj si es posible", + + // scriptsAppStore + "carpet.rule.scriptsAppStore.desc": "Localizacion del repositorio online de las de scarpet", + + "carpet.rule.scriptsAppStore.extra.0": "ponlo en 'none' para deshabilitar.", + "carpet.rule.scriptsAppStore.extra.1": "Apunta a cualquier repositorio de github con apps de scarpet", + "carpet.rule.scriptsAppStore.extra.2": "usando //contents/", + + // scriptsAutoload + "carpet.rule.scriptsAutoload.desc": "Los scripts de Scarpet se autocargan al entrar al mundo", + + "carpet.rule.scriptsAutoload.extra.0": "Si /script esta habilitado", + + // scriptsDebugging + "carpet.rule.scriptsDebugging.desc": "Habilita mensajes de debug en los logs del sistema", + + // scriptsOptimization + "carpet.rule.scriptsOptimization.desc": "Habilita la optimización de scripts", + + // sculkSensorRange + "carpet.rule.sculkSensorRange.desc": "Rango customizable del Sculk Sensor", + + // shulkerSpawningInEndCities + "carpet.rule.shulkerSpawningInEndCities.desc": "Shulkers respawnean en las end cities", + + // silverFishDropGravel + "carpet.rule.silverFishDropGravel.desc": "Silverfish dropea grava cuando se rompe un bloque", + + // simulationDistance + "carpet.rule.simulationDistance.desc": "Cambia la distancia de simulacion del server.", + + "carpet.rule.simulationDistance.extra.0": "Ponlo en 0 para no sustituir las configuraciones del server.", + + // smoothClientAnimations + "carpet.rule.smoothClientAnimations.desc": "Animaciones Fluidas con bajos tps", + + "carpet.rule.smoothClientAnimations.extra.0": "Funciona solo en singleplayer, y va a hacer mas lentos a los jugadores", + + // spawnChunksSize + "carpet.rule.spawnChunksSize.desc": "Cambia el tamaño de los spawn chunks", + + "carpet.rule.spawnChunksSize.extra.0": "Define el nuevo radio", + "carpet.rule.spawnChunksSize.extra.1": "Cambiarlo a 0 - deshabilita los spawn chunks", + + // stackableShulkerBoxes + "carpet.rule.stackableShulkerBoxes.desc": "Las shulker boxes vacias se pueden stackear cuando son tiradas al suelo.", + + "carpet.rule.stackableShulkerBoxes.extra.0": ".. o cuando son manipuladas en el inventario.", + + // structureBlockIgnored + "carpet.rule.structureBlockIgnored.desc": "Cambia el bloque ignorado por el Structure Block", + + // structureBlockLimit + "carpet.rule.structureBlockLimit.desc": "Limite customizable del structure block", + + "carpet.rule.structureBlockLimit.extra.0": "ALERTA: Necesita ser permamente para correcta carga.", + "carpet.rule.structureBlockLimit.extra.1": "Opcion 'structureBlockIgnored' a aire Es recommendado", + "carpet.rule.structureBlockLimit.extra.2": "cuando guardas grandes estructuras.", + "carpet.rule.structureBlockLimit.extra.3": "Requerido en el cliente del jugando editando el bloque de estructura.", + "carpet.rule.structureBlockLimit.extra.4": "'structureBlockOutlineDistance' es requerido por", + "carpet.rule.structureBlockLimit.extra.5": "correcta renderizacion de grandes estructuras", + + // structureBlockOutlineDistance + "carpet.rule.structureBlockOutlineDistance.desc": "Distancia de renderizado del Structure Block de estructura personalizable", + + "carpet.rule.structureBlockOutlineDistance.extra.0": "Necesaria en el cliente para funcionar correctamente.", + + // summonNaturalLightning + "carpet.rule.summonNaturalLightning.desc": "spawnear un rayo tiene los mismo efectos que un rayo natural.", + + // superSecretSetting + "carpet.rule.superSecretSetting.desc": "AKLÑSDLKÑASLJKD REGLA ULTRA SECRETA QUE TIRABA!!! - nachitodev", + + // thickFungusGrowth + "carpet.rule.thickFungusGrowth.desc": "Permite crecer arboles fungi del nether con una base de 3x3", + + "carpet.rule.thickFungusGrowth.extra.0": "Ponerlo en 'all' va a hacer que todos los arboles fungi del nether crezcan en arboles 3x3", + "carpet.rule.thickFungusGrowth.extra.1": "Ponerlo en 'random' will make 6% of all nether fungi grow into 3x3 trees", + "carpet.rule.thickFungusGrowth.extra.2": "(esto siendo consistente con la generación del mundo)", + + // tickSyncedWorldBorders + "carpet.rule.tickSyncedWorldBorders.desc": "hace que los world borders se muevan basados en el tiempo en el juego en vez del tiempo de la vida real", + + "carpet.rule.tickSyncedWorldBorders.extra.0": "Esto tiene efecto cuando el tick rate cambia la velocidad del world border tambien cambia proporcionalmente a el", + + // tntDoNotUpdate + "carpet.rule.tntDoNotUpdate.desc": "la TNT no se actualiza cuando se pone junto a un bloque lo actualize", + + // tntPrimerMomentumRemoved + "carpet.rule.tntPrimerMomentumRemoved.desc": "Remueve el TNT momentum random cuando se prende", + + // tntRandomRange + "carpet.rule.tntRandomRange.desc": "Pone el rango de la explosion de la TNT en un rango especifico", + + "carpet.rule.tntRandomRange.extra.0": "Ponlo a -1 para el compartamiento normal", + + // updateSuppressionBlock + "carpet.rule.updateSuppressionBlock.desc": "Poner un rail activador arriba de un bloque barrier llena a los vecinos updater cuando el stack de rail se apaga.", + + "carpet.rule.updateSuppressionBlock.extra.0": "El numero ingresado es la cantidad de actualizaciones que van a haber en el stack izquierdo", + "carpet.rule.updateSuppressionBlock.extra.1": "-1 lo apaga.", + + // viewDistance + "carpet.rule.viewDistance.desc": "Cambia la distancia de vision del servidor.", + + "carpet.rule.viewDistance.extra.0": "Pon a 0 para no sustituir los valores del server.", + + // xpFromExplosions + "carpet.rule.xpFromExplosions.desc": "La experiencia va a caer con cualquier tipo de explosion", + + // xpNoCooldown + "carpet.rule.xpNoCooldown.desc": "Los jugadores absorben la XP automaticamente sin delay." + +} \ No newline at end of file diff --git a/src/main/resources/assets/carpet/scripts/camera.sc b/src/main/resources/assets/carpet/scripts/camera.sc index 63cc6c46..f0bfdb96 100644 --- a/src/main/resources/assets/carpet/scripts/camera.sc +++ b/src/main/resources/assets/carpet/scripts/camera.sc @@ -127,8 +127,9 @@ _start_with(points_supplier) -> global_dimension = p~'dimension'; code = abs(hash_code(str(p))-123456); - global_color_a = str('dust %.1f %.1f %.1f 1',(code%10)/10,(((code/10)%10)/10), (((code/100)%10)/10) ); // 'dust 0.1 0.9 0.1 1', - global_color_b = str('dust %.1f %.1f %.1f 1',(((code/1000)%10)/10),(((code/10000)%10)/10), (((code/100000)%10)/10) );// 'dust 0.6 0.6 0.6 1' + + global_color_a = str('dust{"scale": 1, "color": [%.1f, %.1f, %.1f]}',(code%10)/10,(((code/10)%10)/10), (((code/100)%10)/10) ); // 'dust 0.1 0.9 0.1 1', + global_color_b = str('dust{"scale": 1, "color": [%.1f, %.1f, %.1f]}',(((code/1000)%10)/10),(((code/10000)%10)/10), (((code/100000)%10)/10) );// 'dust 0.6 0.6 0.6 1' global_points = call(points_supplier); global_selected_point = null; diff --git a/src/main/resources/carpet.accesswidener b/src/main/resources/carpet.accesswidener index 8aa2dafe..fda730bd 100644 --- a/src/main/resources/carpet.accesswidener +++ b/src/main/resources/carpet.accesswidener @@ -2,7 +2,6 @@ accessWidener v1 named accessible class net/minecraft/server/level/ChunkMap$DistanceManager accessible class net/minecraft/server/level/ThreadedLevelLightEngine$TaskType -accessible class net/minecraft/world/item/crafting/Ingredient$Value accessible class net/minecraft/world/level/lighting/BlockLightSectionStorage$BlockDataLayerStorageMap accessible class net/minecraft/world/level/border/WorldBorder$BorderExtent accessible class net/minecraft/world/level/border/WorldBorder$StaticBorderExtent @@ -12,8 +11,8 @@ accessible class net/minecraft/world/level/block/entity/SculkSensorBlockEntity$V #TODO fields and methods should be fetched via interfaces unless there is a good reason not to accessible method net/minecraft/world/level/border/WorldBorder getListeners ()Ljava/util/List; +accessible method net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator calculateTargetStrength (Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)I -accessible method net/minecraft/server/level/DistanceManager purgeStaleTickets ()V #cause I don't want to deal with the interfaces until stuff is stable accessible method net/minecraft/world/level/block/entity/SkullBlockEntity fetchGameProfile (Ljava/lang/String;)Ljava/util/concurrent/CompletableFuture; diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 6b68dcff..366ebf76 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -42,11 +42,9 @@ "ChunkHolder_scarpetChunkCreationMixin", "ThreadedLevelLightEngine_scarpetMixin", "DynamicGraphMinFixedPoint_resetChunkInterface", - "DistanceManager_scarpetChunkCreationMixin", "LevelLightEngine_scarpetChunkCreationMixin", "LayerLightEngine_scarpetChunkCreationMixin", "LayerLightSectionStorage_scarpetChunkCreationMixin", - "DistanceManager_spawnChunksMixin", "ThreadedLevelLightEngine_scarpetChunkCreationMixin", "LivingEntity_cleanLogsMixin", "MobMixin", @@ -100,7 +98,6 @@ "HopperBlockEntity_counterMixin", "AbstractContainerMenu_ctrlQCraftingMixin", "Connection_packetCounterMixin", - "AbstractCauldronBlock_stackableSBoxesMixin", "ItemStack_stackableShulkerBoxesMixin", "ItemEntityMixin", "TntBlock_noUpdateMixin", @@ -117,8 +114,7 @@ "InfestedBlock_gravelMixin", "PistonBaseBlock_qcMixin", "DispenserBlock_qcMixin", - - "PickaxeItem_missingToolsMixin", + "Item_missingToolsMixin", "WitherBoss_moreBlueMixin", "ArmorStand_scarpetMarkerMixin", "Entity_scarpetEventsMixin", @@ -139,8 +135,10 @@ "MerchantResultSlot_scarpetEventMixin", "AbstractContainerMenu_scarpetMixin", "AbstractContainerMenuSubclasses_scarpetMixin", - "RecipeBookMenu_scarpetMixin", + "AbstractCraftingMenu_scarpetMixin", + "AbstractFurnaceMenu_scarpetMixin", "DistanceManager_scarpetMixin", + "TicketStorage_scarpetMixin", "PoiRecord_scarpetMixin", "ServerLevel_scarpetMixin", "PersistentEntitySectionManager_scarpetMixin", @@ -148,9 +146,8 @@ "SystemReport_addScarpetAppsMixin", "CommandNode_scarpetCommandsMixin", "CommandDispatcher_scarpetCommandsMixin", + "FoodData_scarpetMixin", - "RecipeManager_scarpetMixin", - "Ingredient_scarpetMixin", "BlockInput_scarpetMixin", "BlockPredicate_scarpetMixin", "TagPredicate_scarpetMixin", @@ -180,19 +177,21 @@ "ChestBlock_customStickyMixin", "PistonStructureResolver_customStickyMixin", + "DefaultRedstoneWireEvaluator_redstoneMixin", + "CustomPacketPayload_networkStuffMixin", "ServerGamePacketListenerimpl_connectionMixin" ], "client": [ "Minecraft_tickMixin", - "ShulkerBoxAccessMixin", "MinecraftMixin", "Gui_tablistMixin", "PlayerTabOverlayMixin", "PistonHeadRenderer_movableBEMixin", "StructureBlockRenderer_mixin", "ClientPacketListener_clientCommandMixin", + "ClientPacketListener_explosionMixin", "LevelRenderer_fogOffMixin", "LevelRenderer_creativeNoClipMixin", "ClientPacketListener_customPacketsMixin", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index bc051461..95673982 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -33,8 +33,8 @@ "accessWidener" : "carpet.accesswidener", "depends": { - "minecraft": ">1.20.1", - "fabricloader": ">=0.14.18", + "minecraft": ">=1.21.4", + "fabricloader": ">=0.16.10", "java": ">=21" } }