merge upstream 26.2

This commit is contained in:
iceBear67 committed 2026-07-17 17:22:31 +08:00
commit 72f3a09f6d
264 files changed
+4908 -3959

No files matched your search

+6 -7
View File
@@ -7,22 +7,21 @@ on: [pull_request]
jobs: jobs:
Build: Build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up JDK 21 - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: microsoft
java-version: 21 java-version: 25
cache: 'gradle' cache: 'gradle'
- name: Grant execute permission to gradlew - name: Grant execute permission to gradlew
run: chmod +x gradlew run: chmod +x gradlew
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build run: ./gradlew build
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: "Compiled artifacts for Pull Request #${{github.event.number}}" name: "Compiled artifacts for Pull Request #${{github.event.number}}"
path: build/libs path: build/libs
+6 -6
View File
@@ -11,18 +11,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up JDK 21 - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: microsoft
java-version: 21 java-version: 25
cache: 'gradle' cache: 'gradle'
- name: Grant execute permission to gradlew - name: Grant execute permission to gradlew
run: chmod +x gradlew run: chmod +x gradlew
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build run: ./gradlew build
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: Compiled artifacts for ${{ github.sha }} name: Compiled artifacts for ${{ github.sha }}
path: build/libs path: build/libs
+18 -18
View File
@@ -16,7 +16,7 @@ jobs:
extra-branch-curse-version: ${{ steps.properties.outputs.release-extra-curse-version }} extra-branch-curse-version: ${{ steps.properties.outputs.release-extra-curse-version }}
steps: steps:
- name: Checkout the sources - name: Checkout the sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Determine release type - name: Determine release type
id: type id: type
run: | run: |
@@ -41,7 +41,7 @@ jobs:
if ! ${{ steps.properties.outputs.release-extra-branch }}; then if ! ${{ steps.properties.outputs.release-extra-branch }}; then
echo "matrix-to-exclude=Snapshots" >> $GITHUB_OUTPUT echo "matrix-to-exclude=Snapshots" >> $GITHUB_OUTPUT
fi fi
- uses: actions/github-script@v6 - uses: actions/github-script@v7
env: env:
READ_VERSION: ${{ steps.properties.outputs.mod_version }} READ_VERSION: ${{ steps.properties.outputs.mod_version }}
with: with:
@@ -54,7 +54,7 @@ jobs:
})).data; })).data;
console.log('Previous release was: ' + releases[1].name); console.log('Previous release was: ' + releases[1].name);
for (let release of releases.slice(1)) { for (let release of releases.slice(1)) {
if (release.name.includes(READ_VERSION)) if (release.name.includes(' ' + READ_VERSION + ' '))
core.setFailed('Version number is the same as a previous release!') core.setFailed('Version number is the same as a previous release!')
} }
Build-And-Publish: Build-And-Publish:
@@ -78,14 +78,14 @@ jobs:
echo "curse-versions=${{ needs.Get-Properties.outputs.curse-versions }}" >> $GITHUB_OUTPUT echo "curse-versions=${{ needs.Get-Properties.outputs.curse-versions }}" >> $GITHUB_OUTPUT
fi fi
- name: Checkout the sources - name: Checkout the sources
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
ref: ${{ steps.getbranchinfo.outputs.branchname }} ref: ${{ steps.getbranchinfo.outputs.branchname }}
- name: Set up JDK 21 - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: microsoft
java-version: 21 java-version: 25
cache: 'gradle' cache: 'gradle'
- name: Grant execute permission to gradlew - name: Grant execute permission to gradlew
run: chmod +x gradlew run: chmod +x gradlew
@@ -97,7 +97,7 @@ jobs:
output="$(find build/libs/ ! -name "*-dev.jar" ! -name "*-sources.jar" -type f -printf "%f\n")" output="$(find build/libs/ ! -name "*-dev.jar" ! -name "*-sources.jar" -type f -printf "%f\n")"
echo "jarname=$output" >> $GITHUB_OUTPUT echo "jarname=$output" >> $GITHUB_OUTPUT
- name: Save build artifacts in the action - name: Save build artifacts in the action
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: Artifacts for ${{ matrix.branch }} name: Artifacts for ${{ matrix.branch }}
path: build/libs path: build/libs
@@ -111,7 +111,7 @@ jobs:
asset_name: ${{ steps.findjar.outputs.jarname }} asset_name: ${{ steps.findjar.outputs.jarname }}
asset_content_type: application/java-archive asset_content_type: application/java-archive
- name: Upload to Curseforge - name: Upload to Curseforge
uses: itsmeow/curseforge-upload@v3 uses: itsmeow/curseforge-upload@v3.1.2
with: with:
token: ${{ secrets.CF_API_TOKEN }} token: ${{ secrets.CF_API_TOKEN }}
project_id: 349239 project_id: 349239
@@ -125,7 +125,7 @@ jobs:
- name: Ask Gradle to publish - name: Ask Gradle to publish
run: ./gradlew publish run: ./gradlew publish
- name: Save publish folder in action's artifacts # Remove when automated - name: Save publish folder in action's artifacts # Remove when automated
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: Maven publishing artifacts for ${{ matrix.branch }} name: Maven publishing artifacts for ${{ matrix.branch }}
path: publish/carpet/fabric-carpet/ path: publish/carpet/fabric-carpet/
@@ -149,7 +149,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout the sources - name: Checkout the sources
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
ref: master ref: master
- name: Merge docs - name: Merge docs
@@ -166,15 +166,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Carpet sources - name: Checkout Carpet sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up JDK 21 - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: microsoft
java-version: 21 java-version: 25
cache: 'gradle' cache: 'gradle'
- name: Checkout wiki - name: Checkout wiki
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
repository: ${{github.repository}}.wiki repository: ${{github.repository}}.wiki
path: wiki path: wiki
+66
View File
@@ -0,0 +1,66 @@
<img src="./src/main/resources/assets/carpet/icon.png" align="right" width="128px"/>
# 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)
<img src="https://raw.githubusercontent.com/gnembon/carpet-extra/master/src/main/resources/assets/carpet-extra/icon.png" align="right" width="128px"/>
## 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).
+2
View File
@@ -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) [![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) [![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? 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. This is the [Fabric](https://fabricmc.net/) version of Carpet Mod, for Minecraft 1.14.X, 1.15.X, 1.16.X and above.
+16 -20
View File
@@ -1,14 +1,13 @@
plugins { plugins {
id 'fabric-loom' version '1.6-SNAPSHOT' id 'net.fabricmc.fabric-loom' version "${loom_version}"
id 'io.github.juuxel.loom-quiltflower' version '1.7.3'
id 'maven-publish' id 'maven-publish'
} }
sourceCompatibility = JavaVersion.VERSION_21 base {
targetCompatibility = JavaVersion.VERSION_21 archivesName = project.archives_base_name
}
archivesBaseName = project.archives_base_name version = project.mod_version+'+v'+new Date().format('yyMMdd')
version = project.minecraft_version+'-'+project.mod_version+'+v'+new Date().format('yyMMdd')
group = project.maven_group group = project.maven_group
loom { loom {
@@ -19,25 +18,19 @@ loom {
dependencies { dependencies {
// To change the versions see the gradle.properties file // To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}" minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.officialMojangMappings() implementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.
//modImplementation "net.fabricmc:fabric:${project.fabric_version}" //modImplementation "net.fabricmc:fabric:${project.fabric_version}"
//modCompileOnly fabricApi.module("fabric-rendering-v1", project.fabric_version) //modCompileOnly fabricApi.module("fabric-rendering-v1", project.fabric_version)
implementation 'me.lucko:fabric-permissions-api:0.7.0'
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them.
compileOnly "com.google.code.findbugs:jsr305:${project.jsr305_version}"
modImplementation 'me.lucko:fabric-permissions-api:0.3.1'
} }
processResources { processResources {
inputs.property "version", project.version+'+v'+new Date().format('yyMMdd') inputs.property "version", project.version
print("\nBuilding version: " + project.version + "\n")
filesMatching("fabric.mod.json") { filesMatching("fabric.mod.json") {
expand "version": project.mod_version+'+v'+new Date().format('yyMMdd') expand "version": project.version
} }
} }
@@ -50,7 +43,7 @@ tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8" it.options.encoding = "UTF-8"
// Minecraft 1.20.5 upwards uses Java 21. // Minecraft 1.20.5 upwards uses Java 21.
it.options.release = 21 it.options.release = 25
} }
java { java {
@@ -58,11 +51,14 @@ java {
// if it is present. // if it is present.
// If you remove this line, sources will not be generated. // If you remove this line, sources will not be generated.
withSourcesJar() withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
} }
jar { jar {
from("LICENSE") { from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"} rename { "${it}_${project.archives_base_name}"}
} }
} }
@@ -79,7 +75,7 @@ publishing {
repositories { repositories {
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
maven { maven {
url "$projectDir/publish" url = "$projectDir/publish"
} }
} }
} }
+26 -19
View File
@@ -2869,7 +2869,7 @@ On top of that, scarpet provides the following list of noises sampled directly f
`'barrier_noise'`, `'fluid_level_floodedness_noise'`, `'fluid_level_spread_noise'`, `'lava_noise'`, `'barrier_noise'`, `'fluid_level_floodedness_noise'`, `'fluid_level_spread_noise'`, `'lava_noise'`,
`'temperature'`, `'vegetation'`, `'continents'`, `'erosion'`, `'depth'`, `'ridges'`, `'temperature'`, `'vegetation'`, `'continents'`, `'erosion'`, `'depth'`, `'ridges'`,
`'initial_density_without_jaggedness'`, `'final_density'`, `'vein_toggle'`, `'vein_ridged'` and `'vein_gap'` `'preliminary_surface_level'`, `'final_density'`, `'vein_toggle'`, `'vein_ridged'` and `'vein_gap'`
<pre> <pre>
// requesting single value // requesting single value
@@ -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 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 `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. This function is tentative - will likely change when chunk ticket API is properly fleshed out.
@@ -3433,7 +3433,7 @@ Entity that `e` rides.
### `query(e, 'unmountable')` ### `query(e, 'unmountable')`
Boolean, true if the entity cannot be mounted. Boolean, true if the entity cannot be unmounted.
### `(deprecated) query(e, 'tags')` ### `(deprecated) query(e, 'tags')`
@@ -3956,7 +3956,7 @@ Mounts the entity to the `other`.
### `modify(e, 'unmountable', boolean)` ### `modify(e, 'unmountable', boolean)`
Denies or allows an entity to be mounted. Denies or allows an entity to be unmounted.
### `modify(e, 'drop_passengers')` ### `modify(e, 'drop_passengers')`
@@ -4301,8 +4301,8 @@ Recipe type can take one of the following options:
* `'smithing'` - smithing table (1.16+) * `'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 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 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 triples, or `null` if its a shaped recipe and a given slot in the patterns is left 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: 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. * `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
* `['shapeless']` - shapeless crafting * `['shapeless']` - shapeless crafting
@@ -4311,10 +4311,6 @@ Recipe type can take one of the following options:
* `['special']` - special crafting recipe, typically not present in the crafting menu * `['special']` - special crafting recipe, typically not present in the crafting menu
* `['custom']` - other recipe types * `['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 Also note that some recipes leave some products in the crafting window, and these can be determined using
`crafting_remaining_item()` function `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)` ### `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 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)` ### `inventory_size(inventory)`
@@ -5016,11 +5012,11 @@ Triggered when a player sends a disconnect package or is forcefully disconnected
### `__on_player_message(player, message)` ### `__on_player_message(player, message)`
Triggered when a player sends a chat message. Triggered when a player sends a chat message.
This event can be cancelled by returning `'cancel'`, which prevents the message from being sent.
### `__on_player_command(player, command)` ### `__on_player_command(player, command)`
Triggered when a player runs a command. Command value is returned without the / in front. Triggered when a player runs a command. Command value is returned without the / in front.
This event can be cancelled by returning `'cancel'`, which prevents the message from being sent.
### `__on_statistic(player, category, event, value)` ### `__on_statistic(player, category, event, value)`
Triggered when a player statistic changes. Doesn't notify on periodic an rhythmic events, i.e. Triggered when a player statistic changes. Doesn't notify on periodic an rhythmic events, i.e.
`time_since_death`, `time_since_rest`, and `played_one_minute` since these are triggered every tick. Event `time_since_death`, `time_since_rest`, and `played_one_minute` since these are triggered every tick. Event
@@ -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` 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` 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 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 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 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. intercepted list of output messages, and error message if the command resulted in a failure.
Successful commands return `null` as their error. 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.
<pre> <pre>
run('fill 1 1 1 10 10 10 air') -> [0, ["Successfully filled 123 blocks"], null] run('fill 1 1 1 10 10 10 air') -> [123, ["Successfully filled 123 blocks"], null]
run('give @s stone 4') -> [0, ["Gave 4 [Stone] to gnembon"], null] run('give @s stone 4') -> [1, ["Gave 4 [Stone] to gnembon"], null]
run('seed') -> [0, ["Seed: [4031384495743822299]"], null] run('seed') -> [-170661413, [Seed: [4031384495743822299]], null]
run('sed') -> [0, [], "sed<--[HERE]"] // wrong command 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]
</pre> </pre>
### `save()` ### `save()`
@@ -6093,7 +6099,8 @@ system calls. In all circumstances, these are only provided as read-only.
* `game_major_target` - major release target. For 1.12.2, that would be 12 * `game_major_target` - major release target. For 1.12.2, that would be 12
* `game_minor_release` - minor release target. For 1.12.2, that would be 2 * `game_minor_release` - minor release target. For 1.12.2, that would be 2
* `game_protocol` - protocol version number * `game_protocol` - protocol version number
* `game_pack_version` - datapack version number * `game_pack_version` - datapack version number as a version string
* `game_pack_minor_version` - datapack format minor version number
* `game_data_version` - data version of the game. Returns an integer, so it can be compared. * `game_data_version` - data version of the game. Returns an integer, so it can be compared.
* `game_stable` - indicating if its a production release or a snapshot * `game_stable` - indicating if its a production release or a snapshot
+17 -6
View File
@@ -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` 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` 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 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 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 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. intercepted list of output messages, and error message if the command resulted in a failure.
Successful commands return `null` as their error. 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.
<pre> <pre>
run('fill 1 1 1 10 10 10 air') -> [0, ["Successfully filled 123 blocks"], null] run('fill 1 1 1 10 10 10 air') -> [123, ["Successfully filled 123 blocks"], null]
run('give @s stone 4') -> [0, ["Gave 4 [Stone] to gnembon"], null] run('give @s stone 4') -> [1, ["Gave 4 [Stone] to gnembon"], null]
run('seed') -> [0, ["Seed: [4031384495743822299]"], null] run('seed') -> [-170661413, [Seed: [4031384495743822299]], null]
run('sed') -> [0, [], "sed<--[HERE]"] // wrong command 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]
</pre> </pre>
### `save()` ### `save()`
@@ -768,7 +778,8 @@ system calls. In all circumstances, these are only provided as read-only.
* `game_major_target` - major release target. For 1.12.2, that would be 12 * `game_major_target` - major release target. For 1.12.2, that would be 12
* `game_minor_release` - minor release target. For 1.12.2, that would be 2 * `game_minor_release` - minor release target. For 1.12.2, that would be 2
* `game_protocol` - protocol version number * `game_protocol` - protocol version number
* `game_pack_version` - datapack version number * `game_pack_version` - datapack version number as a version string
* `game_pack_minor_version` - datapack format minor version number
* `game_data_version` - data version of the game. Returns an integer, so it can be compared. * `game_data_version` - data version of the game. Returns an integer, so it can be compared.
* `game_stable` - indicating if its a production release or a snapshot * `game_stable` - indicating if its a production release or a snapshot
+2 -2
View File
@@ -540,7 +540,7 @@ On top of that, scarpet provides the following list of noises sampled directly f
`'barrier_noise'`, `'fluid_level_floodedness_noise'`, `'fluid_level_spread_noise'`, `'lava_noise'`, `'barrier_noise'`, `'fluid_level_floodedness_noise'`, `'fluid_level_spread_noise'`, `'lava_noise'`,
`'temperature'`, `'vegetation'`, `'continents'`, `'erosion'`, `'depth'`, `'ridges'`, `'temperature'`, `'vegetation'`, `'continents'`, `'erosion'`, `'depth'`, `'ridges'`,
`'initial_density_without_jaggedness'`, `'final_density'`, `'vein_toggle'`, `'vein_ridged'` and `'vein_gap'` `'preliminary_surface_level'`, `'final_density'`, `'vein_toggle'`, `'vein_ridged'` and `'vein_gap'`
<pre> <pre>
// requesting single value // requesting single value
@@ -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 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 `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. This function is tentative - will likely change when chunk ticket API is properly fleshed out.
+2 -2
View File
@@ -204,7 +204,7 @@ Entity that `e` rides.
### `query(e, 'unmountable')` ### `query(e, 'unmountable')`
Boolean, true if the entity cannot be mounted. Boolean, true if the entity cannot be unmounted.
### `(deprecated) query(e, 'tags')` ### `(deprecated) query(e, 'tags')`
@@ -727,7 +727,7 @@ Mounts the entity to the `other`.
### `modify(e, 'unmountable', boolean)` ### `modify(e, 'unmountable', boolean)`
Denies or allows an entity to be mounted. Denies or allows an entity to be unmounted.
### `modify(e, 'drop_passengers')` ### `modify(e, 'drop_passengers')`
+2 -2
View File
@@ -318,11 +318,11 @@ Triggered when a player sends a disconnect package or is forcefully disconnected
### `__on_player_message(player, message)` ### `__on_player_message(player, message)`
Triggered when a player sends a chat message. Triggered when a player sends a chat message.
This event can be cancelled by returning `'cancel'`, which prevents the message from being sent.
### `__on_player_command(player, command)` ### `__on_player_command(player, command)`
Triggered when a player runs a command. Command value is returned without the / in front. Triggered when a player runs a command. Command value is returned without the / in front.
This event can be cancelled by returning `'cancel'`, which prevents the message from being sent.
### `__on_statistic(player, category, event, value)` ### `__on_statistic(player, category, event, value)`
Triggered when a player statistic changes. Doesn't notify on periodic an rhythmic events, i.e. Triggered when a player statistic changes. Doesn't notify on periodic an rhythmic events, i.e.
`time_since_death`, `time_since_rest`, and `played_one_minute` since these are triggered every tick. Event `time_since_death`, `time_since_rest`, and `played_one_minute` since these are triggered every tick. Event
+3 -7
View File
@@ -70,8 +70,8 @@ Recipe type can take one of the following options:
* `'smithing'` - smithing table (1.16+) * `'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 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 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 triples, or `null` if its a shaped recipe and a given slot in the patterns is left 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: 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. * `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
* `['shapeless']` - shapeless crafting * `['shapeless']` - shapeless crafting
@@ -80,10 +80,6 @@ Recipe type can take one of the following options:
* `['special']` - special crafting recipe, typically not present in the crafting menu * `['special']` - special crafting recipe, typically not present in the crafting menu
* `['custom']` - other recipe types * `['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 Also note that some recipes leave some products in the crafting window, and these can be determined using
`crafting_remaining_item()` function `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)` ### `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 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)` ### `inventory_size(inventory)`
+11 -8
View File
@@ -1,15 +1,18 @@
# Done to increase the memory available to gradle. # Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check https://fabricmc.net/develop/ # check https://fabricmc.net/develop/
minecraft_version=1.21.1 minecraft_version=26.2
loader_version=0.15.11 loader_version=0.19.3
jsr305_version=3.0.2 loom_version=1.15-SNAPSHOT
fabric_version=0.99.2+1.21
# Mod Properties # Mod Properties
mod_version = 1.4.147 mod_version = 26.2
maven_group = carpet maven_group = carpet
archives_base_name = fabric-carpet archives_base_name = fabric-carpet
@@ -17,12 +20,12 @@ org.gradle.jvmargs=-Xmx1G
# The Curseforge versions "names" or ids for the main branch (comma separated: 1.16.4,1.16.5) # 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 # 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] # 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 26:26.2
# Whether or not to build another branch on release # Whether or not to build another branch on release
release-extra-branch = false release-extra-branch = false
# The name of the second branch to release # The name of the second branch to release
release-extra-branch-name = 1.20.4 release-extra-branch-name = 1.21.10
# The "name" or id of the Curseforge version for the secondary branch # The "name" or id of the Curseforge version for the secondary branch
# This is needed because CF uses too vague names for snapshots # 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] # 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 release-extra-curse-version = Minecraft 1.21:1.21.10-Snapshot
Binary file not shown.
+2 -1
View File
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+22 -18
View File
@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@@ -83,10 +85,8 @@ done
# This is normally unused # This is normally unused
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@@ -114,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -133,10 +132,13 @@ location of your Java installation."
fi fi
else else
JAVACMD=java JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
@@ -144,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045 # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
@@ -152,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045 # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@@ -169,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" ) JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -197,16 +198,19 @@ if "$cygwin" || "$msys" ; then
done done
fi fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
# shell script including quotes and variable substitutions, so put them in DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded. # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.
Vendored
+13 -12
View File
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
@@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
+2 -2
View File
@@ -1,3 +1,3 @@
before_install: before_install:
- sdk install java 21.0.2-open - sdk install java 25.0.1-ms
- sdk use java 21.0.2-open - sdk use java 25.0.1-ms
+1 -13
View File
@@ -70,12 +70,6 @@ public interface CarpetExtension
registerCommands(dispatcher); registerCommands(dispatcher);
} }
/**
* @deprecated Implement {@link #extensionSettingsManager()} instead
*/
@Deprecated(forRemoval = true)
default carpet.settings.SettingsManager customSettingsManager() {return null;}
/** /**
* Provide your own custom settings manager managed in the same way as base /carpet * Provide your own custom settings manager managed in the same way as base /carpet
* command, but separated to its own command as defined in SettingsManager. * command, but separated to its own command as defined in SettingsManager.
@@ -84,13 +78,7 @@ public interface CarpetExtension
* *
*/ */
default SettingsManager extensionSettingsManager() { default SettingsManager extensionSettingsManager() {
// Warn extensions overriding the other (deprecated) method, go ahead and override this if you want to provide a custom SettingsManager return null;
SettingsManager deprecatedManager = customSettingsManager();
if (deprecatedManager != null) {
// Extension is providing a manager via the old method (and also hasn't overriden this)
CarpetServer.warnOutdatedManager(this);
}
return customSettingsManager();
} }
/** /**
+5 -12
View File
@@ -40,6 +40,8 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.commands.PerfCommand; import net.minecraft.server.commands.PerfCommand;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import org.jspecify.annotations.Nullable;
public class CarpetServer // static for now - easier to handle all around the code, its one anyways public class CarpetServer // static for now - easier to handle all around the code, its one anyways
{ {
public static MinecraftServer minecraft_server; public static MinecraftServer minecraft_server;
@@ -160,7 +162,7 @@ public class CarpetServer // static for now - easier to handle all around the co
LoggerRegistry.playerDisconnected(player); LoggerRegistry.playerDisconnected(player);
extensions.forEach(e -> e.onPlayerLoggedOut(player)); extensions.forEach(e -> e.onPlayerLoggedOut(player));
// first case client, second case server // first case client, second case server
CarpetScriptServer runningScriptServer = (player.getServer() == null) ? scriptServer : Vanilla.MinecraftServer_getScriptServer(player.getServer()); CarpetScriptServer runningScriptServer = (player.level().getServer() == null) ? scriptServer : Vanilla.MinecraftServer_getScriptServer(player.level().getServer());
if (runningScriptServer != null && !runningScriptServer.stopAll) { if (runningScriptServer != null && !runningScriptServer.stopAll) {
runningScriptServer.onPlayerLoggedOut(player, reason); runningScriptServer.onPlayerLoggedOut(player, reason);
} }
@@ -172,7 +174,7 @@ public class CarpetServer // static for now - easier to handle all around the co
scriptServer = null; 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 // 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 // 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(); if (scriptServer != null) scriptServer.onClose();
// this is a mess, will cleanip onlly when global reference is gone // 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(); Vanilla.MinecraftServer_getScriptServer(server).onClose();
} }
@@ -224,14 +226,5 @@ public class CarpetServer // static for now - easier to handle all around the co
scriptServer.reload(server); scriptServer.reload(server);
extensions.forEach(e -> e.onReload(server)); extensions.forEach(e -> e.onReload(server));
} }
private static final Set<CarpetExtension> warnedOutdatedManagerProviders = new HashSet<>();
static void warnOutdatedManager(CarpetExtension ext)
{
if (warnedOutdatedManagerProviders.add(ext))
CarpetSettings.LOG.warn("""
%s is providing a SettingsManager from an outdated method in CarpetExtension!
This behaviour will not work in later Carpet versions and the manager won't be registered!""".formatted(ext.getClass().getName()));
}
} }
+45 -60
View File
@@ -12,12 +12,16 @@ import carpet.utils.Messenger;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.SemanticVersion; import net.fabricmc.loader.api.SemanticVersion;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerInterface; import net.minecraft.server.ServerInterface;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.permissions.LevelBasedPermissionSet;
import net.minecraft.server.permissions.PermissionCheck;
import net.minecraft.server.permissions.PermissionSet;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@@ -56,7 +60,7 @@ public class CarpetSettings
public static final Logger LOG = LoggerFactory.getLogger("carpet"); public static final Logger LOG = LoggerFactory.getLogger("carpet");
public static final ThreadLocal<Boolean> skipGenerationChecks = ThreadLocal.withInitial(() -> false); public static final ThreadLocal<Boolean> skipGenerationChecks = ThreadLocal.withInitial(() -> false);
public static final ThreadLocal<Boolean> impendingFillSkipUpdates = ThreadLocal.withInitial(() -> false); public static final ThreadLocal<Boolean> impendingFillSkipUpdates = ThreadLocal.withInitial(() -> false);
public static int runPermissionLevel = 2; public static PermissionSet runPermissionLevel = LevelBasedPermissionSet.GAMEMASTER;
public static Block structureBlockIgnoredBlock = Blocks.STRUCTURE_VOID; public static Block structureBlockIgnoredBlock = Blocks.STRUCTURE_VOID;
private static class LanguageValidator extends Validator<String> { private static class LanguageValidator extends Validator<String> {
@Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) { @Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) {
@@ -73,7 +77,7 @@ public class CarpetSettings
@Rule( @Rule(
desc = "Sets the language for Carpet", desc = "Sets the language for Carpet",
category = FEATURE, 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 strict = true, // the current system doesn't handle fallbacks and other, not defined languages would make unreadable mess. Change later
validate = LanguageValidator.class validate = LanguageValidator.class
) )
@@ -129,7 +133,7 @@ public class CarpetSettings
private static class CarpetPermissionLevel extends Validator<String> { private static class CarpetPermissionLevel extends Validator<String> {
@Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) { @Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) {
if (source == null || source.hasPermission(4)) if (source == null || Commands.LEVEL_OWNERS.check(source.permissions()))
return newValue; return newValue;
return null; return null;
} }
@@ -152,9 +156,6 @@ public class CarpetSettings
@Rule(desc = "Gbhs sgnf sadsgras fhskdpri!!!", category = EXPERIMENTAL) @Rule(desc = "Gbhs sgnf sadsgras fhskdpri!!!", category = EXPERIMENTAL)
public static boolean superSecretSetting = false; public static boolean superSecretSetting = false;
@Rule(desc = "Dropping entire stacks works also from on the crafting UI result slot", category = {RuleCategory.BUGFIX, SURVIVAL})
public static boolean ctrlQCraftingFix = false;
@Rule(desc = "Parrots don't get of your shoulders until you receive proper damage", category = {SURVIVAL, FEATURE}) @Rule(desc = "Parrots don't get of your shoulders until you receive proper damage", category = {SURVIVAL, FEATURE})
public static boolean persistentParrots = false; public static boolean persistentParrots = false;
@@ -423,10 +424,32 @@ public class CarpetSettings
@Rule( @Rule(
desc = "Required permission level for /perf command", desc = "Required permission level for /perf command",
options = {"2", "4"}, options = {"2", "4"},
category = CREATIVE category = CREATIVE,
validate = PermissionValidator.class
) )
public static int perfPermissionLevel = 4; public static int perfPermissionLevel = 4;
public static class PermissionValidator extends Validator<Integer> {
@Override
public Integer validate(CommandSourceStack source, CarpetRule<Integer> currentRule, Integer newValue, String string) {
if (newValue == 2) {
perfPermissionCheck = Commands.LEVEL_GAMEMASTERS;
} else if (newValue == 4) {
perfPermissionCheck = Commands.LEVEL_OWNERS;
}
return newValue;
}
@Override
public String description() {
return "You must have the permission level you are trying to set";
}
}
public static PermissionCheck perfPermissionCheck = Commands.LEVEL_OWNERS;
@Rule(desc = "Enables /log command to monitor events via chat and overlays", category = COMMAND) @Rule(desc = "Enables /log command to monitor events via chat and overlays", category = COMMAND)
public static String commandLog = "true"; public static String commandLog = "true";
@@ -476,17 +499,21 @@ public class CarpetSettings
private static class ModulePermissionLevel extends Validator<String> { private static class ModulePermissionLevel extends Validator<String> {
@Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) { @Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) {
int permissionLevel = switch (newValue) { PermissionCheck permissionLevel = switch (newValue) {
case "false" -> 0; case "0", "false" -> Commands.LEVEL_ALL;
case "true", "ops" -> 2; case "1" -> Commands.LEVEL_MODERATORS;
case "0", "1", "2", "3", "4" -> Integer.parseInt(newValue); case "2", "true", "ops" -> Commands.LEVEL_GAMEMASTERS;
case "3" -> Commands.LEVEL_ADMINS;
case "4" -> Commands.LEVEL_OWNERS;
default -> throw new IllegalArgumentException(); // already checked by previous validator default -> throw new IllegalArgumentException(); // already checked by previous validator
}; };
if (source != null && !source.hasPermission(permissionLevel)) if (source != null && !permissionLevel.check(source.permissions()))
return null; return null;
CarpetSettings.runPermissionLevel = permissionLevel; CarpetSettings.runPermissionLevel = LevelBasedPermissionSet.GAMEMASTER;
if (source != null) if (source != null) {
CommandHelper.notifyPlayersCommandsChanged(source.getServer()); CommandHelper.notifyPlayersCommandsChanged(source.getServer());
CarpetSettings.runPermissionLevel =source.permissions();
}
return newValue; return newValue;
} }
@Override @Override
@@ -708,7 +735,7 @@ public class CarpetSettings
if (server.isDedicatedServer()) if (server.isDedicatedServer())
{ {
int vd = (newValue >= 2)?newValue:((ServerInterface) server).getProperties().viewDistance; int vd = (newValue >= 2)?newValue:((ServerInterface) server).getProperties().viewDistance.get();
if (vd != server.getPlayerList().getViewDistance()) if (vd != server.getPlayerList().getViewDistance())
server.getPlayerList().setViewDistance(vd); server.getPlayerList().setViewDistance(vd);
return newValue; return newValue;
@@ -749,7 +776,7 @@ public class CarpetSettings
if (server.isDedicatedServer()) if (server.isDedicatedServer())
{ {
int vd = (newValue >= 2)?newValue:((DedicatedServer) server).getProperties().simulationDistance; int vd = (newValue >= 2)?newValue:((DedicatedServer) server).getProperties().simulationDistance.get();
if (vd != server.getPlayerList().getSimulationDistance()) if (vd != server.getPlayerList().getSimulationDistance())
server.getPlayerList().setSimulationDistance(vd); server.getPlayerList().setSimulationDistance(vd);
return newValue; return newValue;
@@ -908,7 +935,7 @@ public class CarpetSettings
@Override @Override
public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) { public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String string) {
if (source == null) return newValue; // closing or sync if (source == null) return newValue; // closing or sync
Optional<Block> ignoredBlock = source.registryAccess().registryOrThrow(Registries.BLOCK).getOptional(ResourceLocation.tryParse(newValue)); Optional<Block> ignoredBlock = source.registryAccess().lookupOrThrow(Registries.BLOCK).getOptional(Identifier.tryParse(newValue));
if (!ignoredBlock.isPresent()) { if (!ignoredBlock.isPresent()) {
Messenger.m(source, "r Unknown block '" + newValue + "'."); Messenger.m(source, "r Unknown block '" + newValue + "'.");
return null; return null;
@@ -981,48 +1008,6 @@ public class CarpetSettings
) )
public static int sculkSensorRange = 8; public static int sculkSensorRange = 8;
/**
* Listener, we need to update world borders to change whether
* they are currently moving in real time or in game time.
*/
private static class WorldBorderValidator extends Validator<Boolean>
{
@Override
public Boolean validate(CommandSourceStack source, CarpetRule<Boolean> changingRule, Boolean newValue, String userInput)
{
if (changingRule.value() ^ newValue)
{
// Needed for the update
tickSyncedWorldBorders = newValue;
MinecraftServer server = CarpetServer.minecraft_server;
if (server == null)
{
return newValue;
}
for (ServerLevel level : server.getAllLevels())
{
WorldBorder worldBorder = level.getWorldBorder();
if (worldBorder.getStatus() != BorderStatus.STATIONARY)
{
double from = worldBorder.getSize();
double to = worldBorder.getLerpTarget();
long time = worldBorder.getLerpRemainingTime();
worldBorder.lerpSizeBetween(from, to, time);
}
}
}
return newValue;
}
}
@Rule(
desc = "Makes world borders move based on in game time instead of real time",
extra = "This has the effect that when the tick rate changes the world border speed also changes proportional to it",
category = FEATURE,
validate = WorldBorderValidator.class
)
public static boolean tickSyncedWorldBorders = false;
public enum FungusGrowthMode { public enum FungusGrowthMode {
FALSE, RANDOM, ALL; FALSE, RANDOM, ALL;
} }
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import carpet.script.Expression;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
@@ -304,7 +305,7 @@ public class SettingsManager {
/** /**
* Calling this method is not supported. * Calling this method is not supported.
*/ */
public void inspectClientsideCommand(CommandSourceStack source, String string) public void inspectClientsideCommand(String string)
{ {
if (string.startsWith("/" + identifier + " ")) if (string.startsWith("/" + identifier + " "))
{ {
@@ -316,9 +317,9 @@ public class SettingsManager {
if (rules.containsKey(rule) && rules.get(rule).canBeToggledClientSide()) if (rules.containsKey(rule) && rules.get(rule).canBeToggledClientSide())
{ {
try { try {
rules.get(rule).set(source, strOption); rules.get(rule).set(null, strOption);
} catch (InvalidRuleValueException e) { } 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"))) 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 { } else {
CarpetServer.scriptServer.removeScriptHost(source, rule.scarpetApp, false, true); CarpetServer.scriptServer.removeScriptHost(source, rule.scarpetApp, false, true);
} }
@@ -694,16 +695,16 @@ public class SettingsManager {
{ {
if (locked()) return 0; if (locked()) return 0;
if (!rules.containsKey(rule.name())) return 0; if (!rules.containsKey(rule.name())) return 0;
ConfigReadResult conf = readSettingsFromConf(getFile());
conf.ruleMap().put(rule.name(), stringValue);
writeSettingsToConf(conf); // this may feels weird, but if conf
// is locked, it will never reach this point.
try { try {
rule.set(source, stringValue); rule.set(source, stringValue);
Messenger.m(source ,"gi "+String.format(tr(TranslationKeys.DEFAULT_SET), RuleHelper.translatedName(rule), stringValue)); Messenger.m(source ,"gi "+String.format(tr(TranslationKeys.DEFAULT_SET), RuleHelper.translatedName(rule), stringValue));
} catch (InvalidRuleValueException e) { } catch (InvalidRuleValueException e) {
e.notifySource(rule.name(), source); e.notifySource(rule.name(), source);
return 0;
} }
ConfigReadResult conf = readSettingsFromConf(getFile());
conf.ruleMap().put(rule.name(), stringValue);
writeSettingsToConf(conf);
return 1; return 1;
} }
// removes overrides of the default values in the file // removes overrides of the default values in the file
@@ -241,7 +241,7 @@ public class DrawCommand
} }
if (CarpetSettings.fillUpdates) 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"); Messenger.m(ctx.getSource(), "gi Filled " + affected + " blocks");
return affected; return affected;
@@ -291,7 +291,7 @@ public class DrawCommand
if (CarpetSettings.fillUpdates) 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"); Messenger.m(source, "gi Filled " + affected + " blocks");
@@ -390,7 +390,7 @@ public class DrawCommand
for (BlockPos blockpos1 : list) { for (BlockPos blockpos1 : list) {
Block blokc = world.getBlockState(blockpos1).getBlock(); 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) { for (BlockPos blockpos1 : list) {
Block blokc = world.getBlockState(blockpos1).getBlock(); Block blokc = world.getBlockState(blockpos1).getBlock();
world.blockUpdated(blockpos1, blokc); world.updateNeighborsAt(blockpos1, blokc);
} }
} }
@@ -69,7 +69,7 @@ public class InfoCommand
private static int infoBlock(CommandSourceStack source, BlockPos pos, String grep) private static int infoBlock(CommandSourceStack source, BlockPos pos, String grep)
{ {
if (!source.hasPermission(Commands.LEVEL_GAMEMASTERS)) { if (!Commands.LEVEL_GAMEMASTERS.check(source.permissions())) {
//check id pos is loaded //check id pos is loaded
if (!source.getLevel().hasChunkAt(pos)) { if (!source.getLevel().hasChunkAt(pos)) {
Messenger.m(source, "r Chunk is not loaded"); Messenger.m(source, "r Chunk is not loaded");
@@ -15,6 +15,8 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntitySpawnRequest;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
@@ -39,11 +41,11 @@ public class PerimeterInfoCommand
BlockPosArgument.getSpawnablePos(c, "center position"), BlockPosArgument.getSpawnablePos(c, "center position"),
null)). null)).
then(argument("mob", resource(commandBuildContext, Registries.ENTITY_TYPE)). then(argument("mob", resource(commandBuildContext, Registries.ENTITY_TYPE)).
suggests(SuggestionProviders.SUMMONABLE_ENTITIES). suggests(SuggestionProviders.cast(SuggestionProviders.SUMMONABLE_ENTITIES)).
executes( (c) -> perimeterDiagnose( executes( (c) -> perimeterDiagnose(
c.getSource(), c.getSource(),
BlockPosArgument.getSpawnablePos(c, "center position"), BlockPosArgument.getSpawnablePos(c, "center position"),
getSummonableEntityType(c, "mob").key().location().toString() getSummonableEntityType(c, "mob").key().identifier().toString()
)))); ))));
dispatcher.register(command); dispatcher.register(command);
} }
@@ -55,8 +57,8 @@ public class PerimeterInfoCommand
if (mobId != null) if (mobId != null)
{ {
nbttagcompound.putString("id", mobId); nbttagcompound.putString("id", mobId);
Entity baseEntity = EntityType.loadEntityRecursive(nbttagcompound, source.getLevel(), (entity_1x) -> { Entity baseEntity = EntityType.loadEntityRecursive(nbttagcompound, source.getLevel(), new EntitySpawnRequest(EntitySpawnReason.COMMAND, true), (entity_1x) -> {
entity_1x.moveTo(new BlockPos(pos.getX(), source.getLevel().getMinBuildHeight()-10, pos.getZ()), entity_1x.getYRot(), entity_1x. getXRot()); 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; return !source.getLevel().addWithUUID(entity_1x) ? null : entity_1x;
}); });
if (!(baseEntity instanceof Mob)) if (!(baseEntity instanceof Mob))
+108 -55
View File
@@ -20,6 +20,7 @@ import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.SharedConstants; import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.DimensionArgument;
import net.minecraft.commands.arguments.GameModeArgument; import net.minecraft.commands.arguments.GameModeArgument;
import net.minecraft.commands.arguments.coordinates.RotationArgument; import net.minecraft.commands.arguments.coordinates.RotationArgument;
@@ -30,6 +31,8 @@ import net.minecraft.core.UUIDUtil;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.NameAndId;
import net.minecraft.server.players.OldUsersConverter;
import net.minecraft.server.players.PlayerList; import net.minecraft.server.players.PlayerList;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.GameType; import net.minecraft.world.level.GameType;
@@ -37,19 +40,18 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import java.util.Collection; import java.util.*;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import static net.minecraft.commands.Commands.argument; import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal; import static net.minecraft.commands.Commands.literal;
import static net.minecraft.commands.SharedSuggestionProvider.suggest; import static net.minecraft.commands.SharedSuggestionProvider.suggest;
public class PlayerCommand { public class PlayerCommand
{
// TODO: allow any order like execute // TODO: allow any order like execute
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandBuildContext) { public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandBuildContext)
{
LiteralArgumentBuilder<CommandSourceStack> command = literal("player") LiteralArgumentBuilder<CommandSourceStack> command = literal("player")
.requires((player) -> Permissions.check(player, "carpet.command.player", CommandHelper.canUseCommand(player, CarpetSettings.commandPlayer))) .requires((player) -> Permissions.check(player, "carpet.command.player", CommandHelper.canUseCommand(player, CarpetSettings.commandPlayer)))
.then(argument("player", StringArgumentType.word()) .then(argument("player", StringArgumentType.word())
@@ -67,7 +69,7 @@ public class PlayerCommand {
.then(argument("slot", IntegerArgumentType.integer(1, 9)) .then(argument("slot", IntegerArgumentType.integer(1, 9))
.executes(c -> manipulate(c, ap -> ap.setSlot(IntegerArgumentType.getInteger(c, "slot")))))) .executes(c -> manipulate(c, ap -> ap.setSlot(IntegerArgumentType.getInteger(c, "slot"))))))
.then(literal("kill").executes(PlayerCommand::kill)) .then(literal("kill").executes(PlayerCommand::kill))
.then(literal("shadow").executes(PlayerCommand::shadow)) .then(literal("shadow"). executes(PlayerCommand::shadow))
.then(literal("mount").executes(manipulation(ap -> ap.mount(true))) .then(literal("mount").executes(manipulation(ap -> ap.mount(true)))
.then(literal("anything").executes(manipulation(ap -> ap.mount(false))))) .then(literal("anything").executes(manipulation(ap -> ap.mount(false)))))
.then(literal("dismount").executes(manipulation(EntityPlayerActionPack::dismount))) .then(literal("dismount").executes(manipulation(EntityPlayerActionPack::dismount)))
@@ -98,15 +100,16 @@ public class PlayerCommand {
.then(literal("left").executes(manipulation(ap -> ap.setStrafing(1)))) .then(literal("left").executes(manipulation(ap -> ap.setStrafing(1))))
.then(literal("right").executes(manipulation(ap -> ap.setStrafing(-1)))) .then(literal("right").executes(manipulation(ap -> ap.setStrafing(-1))))
).then(literal("spawn").executes(PlayerCommand::spawn) ).then(literal("spawn").executes(PlayerCommand::spawn)
.then(literal("in").requires((player) -> Permissions.check(player, "carpet.command.player.gamemode", player.hasPermission(2))) .then(literal("in").requires((player) -> Permissions.check(player, "carpet.command.player.gamemode", Commands.LEVEL_GAMEMASTERS.check(player.permissions())))
.then(argument("gamemode", GameModeArgument.gameMode()) .then(argument("gamemode", GameModeArgument.gameMode())
.executes(PlayerCommand::spawn))) .executes(PlayerCommand::spawn)))
.then(literal("at").then(argument("position", Vec3Argument.vec3()).executes(PlayerCommand::spawn) .then(literal("at").then(argument("position", Vec3Argument.vec3()).executes(PlayerCommand::spawn)
.then(literal("facing").then(argument("direction", RotationArgument.rotation()).executes(PlayerCommand::spawn) .then(literal("facing").then(argument("direction", RotationArgument.rotation()).executes(PlayerCommand::spawn)
.then(literal("in") .then(literal("in")
.requires((player) -> Permissions.check(player,"carpet.command.player.dimension",player.hasPermission(4))) .then(argument("dimension", DimensionArgument.dimension())
.then(argument("dimension", DimensionArgument.dimension()).executes(PlayerCommand::spawn) .requires((player) -> Permissions.check(player,"carpet.command.player.dimension",Commands.LEVEL_GAMEMASTERS.check(player.permissions())))
.then(literal("in").requires((player) -> player.hasPermission(2)) .executes(PlayerCommand::spawn)
.then(literal("in")
.then(argument("gamemode", GameModeArgument.gameMode()) .then(argument("gamemode", GameModeArgument.gameMode())
.executes(PlayerCommand::spawn) .executes(PlayerCommand::spawn)
))) )))
@@ -117,7 +120,8 @@ public class PlayerCommand {
dispatcher.register(command); dispatcher.register(command);
} }
private static LiteralArgumentBuilder<CommandSourceStack> makeActionCommand(String actionName, ActionType type) { private static LiteralArgumentBuilder<CommandSourceStack> makeActionCommand(String actionName, ActionType type)
{
return literal(actionName) return literal(actionName)
.executes(manipulation(ap -> ap.start(type, Action.once()))) .executes(manipulation(ap -> ap.start(type, Action.once())))
.then(literal("once").executes(manipulation(ap -> ap.start(type, Action.once())))) .then(literal("once").executes(manipulation(ap -> ap.start(type, Action.once()))))
@@ -126,7 +130,8 @@ public class PlayerCommand {
.executes(c -> manipulate(c, ap -> ap.start(type, Action.interval(IntegerArgumentType.getInteger(c, "ticks"))))))); .executes(c -> manipulate(c, ap -> ap.start(type, Action.interval(IntegerArgumentType.getInteger(c, "ticks")))))));
} }
private static LiteralArgumentBuilder<CommandSourceStack> makeDropCommand(String actionName, boolean dropAll) { private static LiteralArgumentBuilder<CommandSourceStack> makeDropCommand(String actionName, boolean dropAll)
{
return literal(actionName) return literal(actionName)
.then(literal("all").executes(manipulation(ap -> ap.drop(-2, dropAll)))) .then(literal("all").executes(manipulation(ap -> ap.drop(-2, dropAll))))
.then(literal("mainhand").executes(manipulation(ap -> ap.drop(-1, dropAll)))) .then(literal("mainhand").executes(manipulation(ap -> ap.drop(-1, dropAll))))
@@ -135,32 +140,39 @@ public class PlayerCommand {
executes(c -> manipulate(c, ap -> ap.drop(IntegerArgumentType.getInteger(c, "slot"), dropAll)))); executes(c -> manipulate(c, ap -> ap.drop(IntegerArgumentType.getInteger(c, "slot"), dropAll))));
} }
private static Collection<String> getPlayerSuggestions(CommandSourceStack source) { private static Collection<String> getPlayerSuggestions(CommandSourceStack source)
Set<String> players = new LinkedHashSet<>(List.of("Steve.bot", "Alex.bot")); {
Set<String> players = new LinkedHashSet<>(List.of("Steve", "Alex"));
players.addAll(source.getOnlinePlayerNames()); players.addAll(source.getOnlinePlayerNames());
return players; return players;
} }
private static ServerPlayer getPlayer(CommandContext<CommandSourceStack> context) { private static ServerPlayer getPlayer(CommandContext<CommandSourceStack> context)
{
String playerName = StringArgumentType.getString(context, "player"); String playerName = StringArgumentType.getString(context, "player");
MinecraftServer server = context.getSource().getServer(); MinecraftServer server = context.getSource().getServer();
return server.getPlayerList().getPlayerByName(playerName); return server.getPlayerList().getPlayerByName(playerName);
} }
private static boolean cantManipulate(CommandContext<CommandSourceStack> context) { private static boolean cantManipulate(CommandContext<CommandSourceStack> context)
{
Player player = getPlayer(context); Player player = getPlayer(context);
CommandSourceStack source = context.getSource(); CommandSourceStack source = context.getSource();
if (player == null) { if (player == null)
{
Messenger.m(source, "r Can only manipulate existing players"); Messenger.m(source, "r Can only manipulate existing players");
return true; return true;
} }
Player sender = source.getPlayer(); Player sender = source.getPlayer();
if (sender == null) { if (sender == null)
{
return false; return false;
} }
if (!source.getServer().getPlayerList().isOp(sender.getGameProfile())) { if (!source.getServer().getPlayerList().isOp(sender.nameAndId()))
if (sender != player && !(player instanceof EntityPlayerMPFake)) { {
if (sender != player && !(player instanceof EntityPlayerMPFake))
{
Messenger.m(source, "r Non OP players can't control other real players"); Messenger.m(source, "r Non OP players can't control other real players");
return true; return true;
} }
@@ -168,7 +180,8 @@ public class PlayerCommand {
return false; return false;
} }
private static boolean cantReMove(CommandContext<CommandSourceStack> context) { private static boolean cantReMove(CommandContext<CommandSourceStack> context)
{
if (cantManipulate(context)) return true; if (cantManipulate(context)) return true;
Player player = getPlayer(context); Player player = getPlayer(context);
if (player instanceof EntityPlayerMPFake) return false; if (player instanceof EntityPlayerMPFake) return false;
@@ -176,63 +189,95 @@ public class PlayerCommand {
return true; return true;
} }
private static boolean cantSpawn(CommandContext<CommandSourceStack> context) { private static boolean cantSpawn(CommandContext<CommandSourceStack> context)
{
String playerName = StringArgumentType.getString(context, "player"); String playerName = StringArgumentType.getString(context, "player");
MinecraftServer server = context.getSource().getServer(); MinecraftServer server = context.getSource().getServer();
PlayerList manager = server.getPlayerList(); 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"); Messenger.m(context.getSource(), "r Player ", "rb " + playerName, "r is already logged on");
return true; return true;
} }
var sender = context.getSource().getPlayer(); var sender = context.getSource().getPlayer();
if(!playerName.endsWith(".bot") && sender != null && !Permissions.check(sender,"carpet.command.player.name",sender.hasPermissions(4))){ if(!playerName.endsWith(".bot") && sender != null && !Permissions.check(sender,"carpet.command.player.name",Commands.LEVEL_GAMEMASTERS.check(sender.permissions()))){
Messenger.m(sender,"r You can't spawn a player whose name isn't ends with `.bot` suffix."); Messenger.m(sender,"r You can't spawn a player whose name isn't ends with `.bot` suffix.");
Messenger.m(sender,"r Try this: /player "+playerName+".bot spawn ..."); Messenger.m(sender,"r Try this: /player "+playerName+".bot spawn ...");
return true; return true;
} }
GameProfile profile = server.getProfileCache().get(playerName).orElse(null); UUID uuid = OldUsersConverter.convertMobOwnerIfNecessary(server, playerName);
if (profile == null) { if (uuid == null)
if (!CarpetSettings.allowSpawningOfflinePlayers) { {
Messenger.m(context.getSource(), "r Player " + playerName + " is either banned by Mojang, or auth servers are down. " + if (!CarpetSettings.allowSpawningOfflinePlayers)
{
Messenger.m(context.getSource(), "r Player "+playerName+" is either banned by Mojang, or auth servers are down. " +
"Banned players can only be summoned in Singleplayer and in servers in off-line mode."); "Banned players can only be summoned in Singleplayer and in servers in off-line mode.");
return true; return true;
} else { } else {
profile = new GameProfile(UUIDUtil.createOfflinePlayerUUID(playerName), playerName); uuid = UUIDUtil.createOfflinePlayerUUID(playerName);
} }
} }
if (manager.getBans().isBanned(profile)) { //GameProfile profile = new GameProfile(uuid, playerName);
NameAndId profile = server.services().nameToIdCache().get(uuid).orElse(null);
if (profile == null)
{
if (!CarpetSettings.allowSpawningOfflinePlayers)
{
Messenger.m(context.getSource(), "r Player "+playerName+" is either banned by Mojang, or auth servers are down. " +
"Banned players can only be summoned in Singleplayer and in servers in off-line mode.");
return true;
} else {
profile = new NameAndId(UUIDUtil.createOfflinePlayerUUID(playerName), playerName);
}
}
if (manager.getBans().isBanned(profile))
{
Messenger.m(context.getSource(), "r Player ", "rb " + playerName, "r is banned on this server"); Messenger.m(context.getSource(), "r Player ", "rb " + playerName, "r is banned on this server");
return true; return true;
} }
if (manager.isUsingWhitelist() && manager.isWhiteListed(profile) && !context.getSource().hasPermission(2)) { if (manager.isUsingWhitelist() && manager.isWhiteListed(profile) && !Commands.LEVEL_GAMEMASTERS.check(context.getSource().permissions()))
{
Messenger.m(context.getSource(), "r Whitelisted players can only be spawned by operators"); Messenger.m(context.getSource(), "r Whitelisted players can only be spawned by operators");
return true; return true;
} }
return false; return false;
} }
private static int kill(CommandContext<CommandSourceStack> context) { private static int kill(CommandContext<CommandSourceStack> context)
{
if (cantReMove(context)) return 0; if (cantReMove(context)) return 0;
getPlayer(context).kill(); ServerPlayer player = getPlayer(context);
player.kill(player.level());
return 1; return 1;
} }
@FunctionalInterface @FunctionalInterface
interface SupplierWithCSE<T> { interface SupplierWithCSE<T>
{
T get() throws CommandSyntaxException; T get() throws CommandSyntaxException;
} }
private static <T> T getArgOrDefault(SupplierWithCSE<T> getter, T defaultValue) throws CommandSyntaxException { private static <T> T getArgOrDefault(SupplierWithCSE<T> getter, T defaultValue) throws CommandSyntaxException
try { {
try
{
return getter.get(); return getter.get();
} catch (IllegalArgumentException e) { }
catch (IllegalArgumentException e)
{
return defaultValue; return defaultValue;
} }
} }
private static int spawn(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int spawn(CommandContext<CommandSourceStack> context) throws CommandSyntaxException
{
if (cantSpawn(context)) return 0; if (cantSpawn(context)) return 0;
CommandSourceStack source = context.getSource(); CommandSourceStack source = context.getSource();
@@ -250,29 +295,33 @@ public class PlayerCommand {
); );
GameType mode = GameType.CREATIVE; GameType mode = GameType.CREATIVE;
boolean flying = false; boolean flying = false;
if (source.getEntity() instanceof ServerPlayer sender) { if (source.getEntity() instanceof ServerPlayer sender)
{
mode = sender.gameMode.getGameModeForPlayer(); mode = sender.gameMode.getGameModeForPlayer();
flying = sender.getAbilities().flying; flying = sender.getAbilities().flying;
} }
try { try {
mode = GameModeArgument.getGameMode(context, "gamemode"); mode = GameModeArgument.getGameMode(context, "gamemode");
} catch (IllegalArgumentException notPresent) { } catch (IllegalArgumentException notPresent) {}
}
if (mode == GameType.SPECTATOR) { if (mode == GameType.SPECTATOR)
{
// Force override flying to true for spectator players, or they will fell out of the world. // Force override flying to true for spectator players, or they will fell out of the world.
flying = true; flying = true;
} else if (mode.isSurvival()) { } else if (mode.isSurvival())
{
// Force override flying to false for survival-like players, or they will fly too // Force override flying to false for survival-like players, or they will fly too
flying = false; flying = false;
} }
String playerName = StringArgumentType.getString(context, "player"); String playerName = StringArgumentType.getString(context, "player");
if (playerName.length() > maxNameLength(source.getServer())) { if (playerName.length() > maxNameLength(source.getServer()))
{
Messenger.m(source, "rb Player name: " + playerName + " is too long"); Messenger.m(source, "rb Player name: " + playerName + " is too long");
return 0; return 0;
} }
if (!Level.isInSpawnableBounds(BlockPos.containing(pos))) { if (!Level.isInSpawnableBounds(BlockPos.containing(pos)))
{
Messenger.m(source, "rb Player " + playerName + " cannot be placed outside of the world"); Messenger.m(source, "rb Player " + playerName + " cannot be placed outside of the world");
return 0; return 0;
} }
@@ -281,40 +330,44 @@ public class PlayerCommand {
Messenger.m(source, "rb Player " + playerName + " doesn't exist and cannot spawn in online mode. " + Messenger.m(source, "rb Player " + playerName + " doesn't exist and cannot spawn in online mode. " +
"Turn the server offline or the allowSpawningOfflinePlayers on to spawn non-existing players"); "Turn the server offline or the allowSpawningOfflinePlayers on to spawn non-existing players");
return 0; return 0;
} };
;
return 1; return 1;
} }
private static int maxNameLength(MinecraftServer server) { private static int maxNameLength(MinecraftServer server)
{
return server.getPort() >= 0 ? SharedConstants.MAX_PLAYER_NAME_LENGTH : 40; return server.getPort() >= 0 ? SharedConstants.MAX_PLAYER_NAME_LENGTH : 40;
} }
private static int manipulate(CommandContext<CommandSourceStack> context, Consumer<EntityPlayerActionPack> action) { private static int manipulate(CommandContext<CommandSourceStack> context, Consumer<EntityPlayerActionPack> action)
{
if (cantManipulate(context)) return 0; if (cantManipulate(context)) return 0;
ServerPlayer player = getPlayer(context); ServerPlayer player = getPlayer(context);
action.accept(((ServerPlayerInterface) player).getActionPack()); action.accept(((ServerPlayerInterface) player).getActionPack());
return 1; return 1;
} }
private static Command<CommandSourceStack> manipulation(Consumer<EntityPlayerActionPack> action) { private static Command<CommandSourceStack> manipulation(Consumer<EntityPlayerActionPack> action)
{
return c -> manipulate(c, action); return c -> manipulate(c, action);
} }
private static int shadow(CommandContext<CommandSourceStack> context) { private static int shadow(CommandContext<CommandSourceStack> context)
{
if (cantManipulate(context)) return 0; if (cantManipulate(context)) return 0;
ServerPlayer player = getPlayer(context); ServerPlayer player = getPlayer(context);
if (player instanceof EntityPlayerMPFake) { if (player instanceof EntityPlayerMPFake)
{
Messenger.m(context.getSource(), "r Cannot shadow fake players"); Messenger.m(context.getSource(), "r Cannot shadow fake players");
return 0; return 0;
} }
if (player.getServer().isSingleplayerOwner(player.getGameProfile())) { if (player.level().getServer().isSingleplayerOwner(player.nameAndId())) {
Messenger.m(context.getSource(), "r Cannot shadow single-player server owner"); Messenger.m(context.getSource(), "r Cannot shadow single-player server owner");
return 0; return 0;
} }
EntityPlayerMPFake.createShadow(player.server, player); EntityPlayerMPFake.createShadow(player.level().getServer(), player);
return 1; return 1;
} }
} }
@@ -0,0 +1,10 @@
package carpet.fakes;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemorySlot;
import java.util.Map;
public interface BrainInterface {
Map<MemoryModuleType<?>, MemorySlot<?>> getMemoriesCM();
}
@@ -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<SortedArraySet<Ticket<?>>> getTicketsByPosition();
void replaceHolder(ChunkHolder oldHolder, ChunkHolder newHolder);
}
@@ -0,0 +1,10 @@
package carpet.fakes;
import net.minecraft.commands.CommandResultCallback;
import net.minecraft.commands.CommandSigningContext;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.util.TaskChainer;
public interface CommandSourceStackInterface {
void setupPrivates(boolean bl, CommandResultCallback commandResultCallback, EntityAnchorArgument.Anchor anchor, CommandSigningContext commandSigningContext, TaskChainer taskChainer);
}
@@ -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);
}
@@ -1,6 +1,9 @@
package carpet.fakes; package carpet.fakes;
import java.util.stream.Stream;
import carpet.script.EntityEventsGroup; import carpet.script.EntityEventsGroup;
import net.minecraft.world.entity.Entity;
public interface EntityInterface public interface EntityInterface
{ {
@@ -19,4 +22,5 @@ public interface EntityInterface
int getPublicNetherPortalCooldown(); int getPublicNetherPortalCooldown();
void setPublicNetherPortalCooldown(int what); void setPublicNetherPortalCooldown(int what);
Stream<Entity> cm$getIndirectPassengersStream();
} }
@@ -0,0 +1,8 @@
package carpet.fakes;
public interface FoodDataInterface
{
float getCMExhaustionLevel();
void setExhaustion(float aFloat);
}
@@ -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} * 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 * to guess the colour of an item to display it prettily
*/ */
List<Collection<ItemStack>> getRecipeStacks(); //List<Collection<ItemStack>> getRecipeStacks();
} }
@@ -1,5 +1,6 @@
package carpet.fakes; package carpet.fakes;
import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
import net.minecraft.world.level.redstone.NeighborUpdater; import net.minecraft.world.level.redstone.NeighborUpdater;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -21,5 +22,5 @@ public interface LevelInterface
List<Entity> getOtherEntitiesLimited(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate, int limit); List<Entity> getOtherEntitiesLimited(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate, int limit);
NeighborUpdater getNeighborUpdater(); CollectingNeighborUpdater getNeighborUpdater();
} }
@@ -0,0 +1,8 @@
package carpet.fakes;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
public interface PistonHeadRenderStateInterface {
public BlockEntityRenderState getMovedBERenderState();
public void setMovedBERenderState(BlockEntityRenderState state);
}
@@ -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<Recipe<?>> getAllMatching(final RecipeType<?> type, final ResourceLocation itemId, final RegistryAccess registryAccess);
}
@@ -1,10 +0,0 @@
package carpet.fakes;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.entity.LevelEntityGetter;
import net.minecraft.world.level.storage.ServerLevelData;
public interface ServerWorldInterface {
ServerLevelData getWorldPropertiesCM();
LevelEntityGetter<Entity> getEntityLookupCMPublic();
}
@@ -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<List<Ticket>> getTicketsByPosition();
}
@@ -6,5 +6,5 @@ import net.minecraft.world.level.block.state.BlockState;
public interface WorldChunkInterface public interface WorldChunkInterface
{ {
BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, boolean boolean1); BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, int flags);
} }
@@ -100,7 +100,7 @@ public class BlockRotator
} }
} }
// Send block update to the block that just have been rotated. // Send block update to the block that just have been rotated.
world.neighborChanged(blockpos, block, source.pos()); world.neighborChanged(blockpos, block, null);
return stack; return stack;
} }
@@ -11,7 +11,7 @@ import carpet.script.utils.Tracer;
import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; 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.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
@@ -19,11 +19,11 @@ import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.animal.equine.AbstractHorse;
import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.entity.vehicle.boat.Boat;
import net.minecraft.world.entity.vehicle.Minecart; import net.minecraft.world.entity.vehicle.minecart.Minecart;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@@ -201,7 +201,7 @@ public class EntityPlayerActionPack
if (closest instanceof AbstractHorse && onlyRideables) if (closest instanceof AbstractHorse && onlyRideables)
((AbstractHorse) closest).mobInteract(player, InteractionHand.MAIN_HAND); ((AbstractHorse) closest).mobInteract(player, InteractionHand.MAIN_HAND);
else else
player.startRiding(closest,true); player.startRiding(closest,true, true);
return this; return this;
} }
public EntityPlayerActionPack dismount() public EntityPlayerActionPack dismount()
@@ -274,15 +274,15 @@ public class EntityPlayerActionPack
else // one slot else // one slot
{ {
if (selectedSlot == -1) if (selectedSlot == -1)
selectedSlot = inv.selected; selectedSlot = inv.getSelectedSlot();
dropItemFromSlot(selectedSlot, dropAll); dropItemFromSlot(selectedSlot, dropAll);
} }
} }
public void setSlot(int slot) public void setSlot(int slot)
{ {
player.getInventory().selected = slot-1; player.getInventory().setSelectedSlot(slot-1);
player.connection.send(new ClientboundSetCarriedItemPacket(slot-1)); player.connection.send(new ClientboundSetHeldSlotPacket(slot-1));
} }
public enum ActionType public enum ActionType
@@ -310,16 +310,16 @@ public class EntityPlayerActionPack
case BLOCK: case BLOCK:
{ {
player.resetLastActionTime(); player.resetLastActionTime();
ServerLevel world = player.serverLevel(); ServerLevel world = player.level();
BlockHitResult blockHit = (BlockHitResult) hit; BlockHitResult blockHit = (BlockHitResult) hit;
BlockPos pos = blockHit.getBlockPos(); BlockPos pos = blockHit.getBlockPos();
Direction side = blockHit.getDirection(); 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); 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; ap.itemUseCooldown = 3;
return true; return true;
} }
@@ -334,13 +334,13 @@ public class EntityPlayerActionPack
boolean handWasEmpty = player.getItemInHand(hand).isEmpty(); boolean handWasEmpty = player.getItemInHand(hand).isEmpty();
boolean itemFrameEmpty = (entity instanceof ItemFrame) && ((ItemFrame) entity).getItem().isEmpty(); boolean itemFrameEmpty = (entity instanceof ItemFrame) && ((ItemFrame) entity).getItem().isEmpty();
Vec3 relativeHitPos = entityHit.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ()); Vec3 relativeHitPos = entityHit.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
if (entity.interactAt(player, relativeHitPos, hand).consumesAction()) if (entity.interact(player, hand, relativeHitPos).consumesAction())
{ {
ap.itemUseCooldown = 3; ap.itemUseCooldown = 3;
return true; return true;
} }
// fix for SS itemframe always returns CONSUME even if no action is performed // fix for SS itemframe always returns CONSUME even if no action is performed
if (player.interactOn(entity, hand).consumesAction() && !(handWasEmpty && itemFrameEmpty)) if (player.interactOn(entity, hand, relativeHitPos).consumesAction() && !(handWasEmpty && itemFrameEmpty))
{ {
ap.itemUseCooldown = 3; ap.itemUseCooldown = 3;
return true; return true;
@@ -402,7 +402,7 @@ public class EntityPlayerActionPack
boolean blockBroken = false; boolean blockBroken = false;
if (player.gameMode.getGameModeForPlayer().isCreative()) 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; ap.blockHitDelay = 5;
blockBroken = true; blockBroken = true;
} }
@@ -410,9 +410,9 @@ public class EntityPlayerActionPack
{ {
if (ap.currentBlock != null) 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(); boolean notAir = !state.isAir();
if (notAir && ap.curBlockDamageMP == 0) if (notAir && ap.curBlockDamageMP == 0)
{ {
@@ -435,7 +435,7 @@ public class EntityPlayerActionPack
ap.curBlockDamageMP += state.getDestroyProgress(player, player.level(), pos); ap.curBlockDamageMP += state.getDestroyProgress(player, player.level(), pos);
if (ap.curBlockDamageMP >= 1) 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.currentBlock = null;
ap.blockHitDelay = 5; ap.blockHitDelay = 5;
blockBroken = true; blockBroken = true;
@@ -457,7 +457,7 @@ public class EntityPlayerActionPack
EntityPlayerActionPack ap = ((ServerPlayerInterface) player).getActionPack(); EntityPlayerActionPack ap = ((ServerPlayerInterface) player).getActionPack();
if (ap.currentBlock == null) return; if (ap.currentBlock == null) return;
player.level().destroyBlockProgress(-1, ap.currentBlock, -1); 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; ap.currentBlock = null;
} }
}, },
@@ -468,7 +468,8 @@ public class EntityPlayerActionPack
{ {
if (action.limit == 1) if (action.limit == 1)
{ {
if (player.onGround()) player.jumpFromGround(); // onGround if (player.onGround()) player.jumpFromGround();
else if (!player.onClimbable()) player.tryToStartFallFlying();
} }
else else
{ {
@@ -58,7 +58,7 @@ public interface FertilizableCoral extends BonemealableBlock {
MapColor color = blockUnder.getMapColor(worldIn, pos); MapColor color = blockUnder.getMapColor(worldIn, pos);
BlockState properBlock = blockUnder; BlockState properBlock = blockUnder;
HolderSet.Named<Block> coralBlocks = worldIn.registryAccess().registryOrThrow(Registries.BLOCK).getTag(BlockTags.CORAL_BLOCKS).orElseThrow(); HolderSet.Named<Block> coralBlocks = worldIn.registryAccess().lookupOrThrow(Registries.BLOCK).get(BlockTags.CORAL_BLOCKS).orElseThrow();
for (Holder<Block> block: coralBlocks) for (Holder<Block> block: coralBlocks)
{ {
properBlock = block.value().defaultBlockState(); properBlock = block.value().defaultBlockState();
@@ -75,10 +75,10 @@ public interface FertilizableCoral extends BonemealableBlock {
} }
else else
{ {
if (worldIn.random.nextInt(10) == 0) if (worldIn.getRandom().nextInt(10) == 0)
{ {
BlockPos randomPos = pos.offset(worldIn.random.nextInt(16) - 8, worldIn.random.nextInt(8), worldIn.random.nextInt(16) - 8); BlockPos randomPos = pos.offset(worldIn.getRandom().nextInt(16) - 8, worldIn.getRandom().nextInt(8), worldIn.getRandom().nextInt(16) - 8);
if (coralBlocks.contains(worldIn.getBlockState(randomPos).getBlockHolder())) if (worldIn.getBlockState(randomPos).is(BlockTags.CORAL_BLOCKS))
{ {
worldIn.setBlock(randomPos, Blocks.WET_SPONGE.defaultBlockState(), Block.UPDATE_ALL); worldIn.setBlock(randomPos, Blocks.WET_SPONGE.defaultBlockState(), Block.UPDATE_ALL);
} }
+162 -121
View File
@@ -1,20 +1,21 @@
package carpet.helpers; package carpet.helpers;
import carpet.CarpetServer; import carpet.CarpetServer;
import carpet.fakes.IngredientInterface; import carpet.script.utils.RecipeHelper;
import carpet.fakes.RecipeManagerInterface;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongMap;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor; import net.minecraft.network.chat.TextColor;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeColor;
@@ -24,7 +25,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe; 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.AbstractBannerBlock;
import net.minecraft.world.level.block.BeaconBeamBlock; import net.minecraft.world.level.block.BeaconBeamBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -32,12 +33,12 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.material.MapColor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Map.entry; import static java.util.Map.entry;
@@ -100,9 +101,11 @@ public class HopperCounter
{ {
startTick = -1; startTick = -1;
this.color = color; this.color = color;
String hexColor = Integer.toHexString(color.getTextColor()); String hexColor = Integer.toHexString(color.getTextColor() & 0xFFFFFF); // don't get alpha
if (hexColor.length() < 6) if (hexColor.length() < 6)
{
hexColor = "0".repeat(6 - hexColor.length()) + hexColor; hexColor = "0".repeat(6 - hexColor.length()) + hexColor;
}
this.coloredName = '#' + hexColor + ' ' + color.getName(); this.coloredName = '#' + hexColor + ' ' + color.getName();
} }
@@ -136,6 +139,7 @@ public class HopperCounter
/** /**
* Resets all counters, clearing their items. * Resets all counters, clearing their items.
*
* @param fresh Whether or not to start the clocks going immediately or later. * @param fresh Whether or not to start the clocks going immediately or later.
*/ */
public static void resetAll(MinecraftServer server, boolean fresh) public static void resetAll(MinecraftServer server, boolean fresh)
@@ -143,7 +147,10 @@ public class HopperCounter
for (HopperCounter counter : COUNTERS.values()) for (HopperCounter counter : COUNTERS.values())
{ {
counter.reset(server); counter.reset(server);
if (fresh) counter.startTick = -1; if (fresh)
{
counter.startTick = -1;
}
} }
} }
@@ -159,7 +166,10 @@ public class HopperCounter
List<Component> temp = counter.format(server, realtime, false); List<Component> temp = counter.format(server, realtime, false);
if (temp.size() > 1) if (temp.size() > 1)
{ {
if (!text.isEmpty()) text.add(Messenger.s("")); if (!text.isEmpty())
{
text.add(Messenger.s(""));
}
text.addAll(temp); text.addAll(temp);
} }
} }
@@ -181,7 +191,7 @@ public class HopperCounter
{ {
if (brief) 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")); return Collections.singletonList(Messenger.c(coloredName, "w hasn't started counting yet"));
} }
@@ -190,36 +200,36 @@ public class HopperCounter
{ {
if (brief) 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)", 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" : "")), ticks / (20.0 * 60.0), (realTime ? " - real time" : "")),
"nb [X]", "^g reset", "!/counter " + color.getName() +" reset")); "nb [X]", "^g reset", "!/counter " + color.getName() + " reset"));
} }
if (brief) if (brief)
{ {
return Collections.singletonList(Messenger.c("b"+coloredName,"w : ", return Collections.singletonList(Messenger.c("b" + coloredName, "w : ",
"wb "+total,"w , ", "wb " + total, "w , ",
"wb "+(total * (20 * 60 * 60) / ticks),"w /h, ", "wb " + (total * (20 * 60 * 60) / ticks), "w /h, ",
String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min" String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min"
)); ));
} }
List<Component> items = new ArrayList<>(); List<Component> items = new ArrayList<>();
items.add(Messenger.c("w Items for ", coloredName, items.add(Messenger.c("w Items for ", coloredName,
"w (",String.format("wb %.2f", ticks*1.0/(20*60)), "w min"+(realTime?" - real time":"")+"), ", "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):", "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" "nb [X]", "^g reset", "!/counter " + color + " reset"
)); ));
items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(e -> items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(e ->
{ {
Item item = e.getKey(); Item item = e.getKey();
MutableComponent itemName = Component.translatable(item.getDescriptionId()); MutableComponent itemName = Component.translatable(item.getDescriptionId());
Style itemStyle = itemName.getStyle(); 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)); itemName.setStyle((color != null) ? itemStyle.withColor(color) : itemStyle.withItalic(true));
long count = e.getLongValue(); long count = e.getLongValue();
return Messenger.c("g - ", itemName, 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" String.format("wb %.1f", count * (20.0 * 60.0 * 60.0) / ticks), "w /h"
); );
}).collect(Collectors.toList())); }).collect(Collectors.toList()));
@@ -232,13 +242,25 @@ public class HopperCounter
*/ */
public static int appropriateColor(int color) 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 r = (color >> 16 & 255);
int g = (color >> 8 & 255); int g = (color >> 8 & 255);
int b = (color & 255); int b = (color & 255);
if (r < 70) r = 70; if (r < 70)
if (g < 70) g = 70; {
if (b < 70) b = 70; r = 70;
}
if (g < 70)
{
g = 70;
}
if (b < 70)
{
b = 70;
}
return (r << 16) + (g << 8) + b; return (r << 16) + (g << 8) + b;
} }
@@ -247,19 +269,19 @@ public class HopperCounter
* {@link Block#defaultMapColor()} method as these items have those same colours. * {@link Block#defaultMapColor()} method as these items have those same colours.
*/ */
private static final Map<Item, Block> DEFAULTS = Map.ofEntries( private static final Map<Item, Block> DEFAULTS = Map.ofEntries(
entry(Items.DANDELION, Blocks.YELLOW_WOOL), entry(Items.DANDELION, Blocks.WOOL.yellow()),
entry(Items.POPPY, Blocks.RED_WOOL), entry(Items.POPPY, Blocks.WOOL.red()),
entry(Items.BLUE_ORCHID, Blocks.LIGHT_BLUE_WOOL), entry(Items.BLUE_ORCHID, Blocks.WOOL.lightBlue()),
entry(Items.ALLIUM, Blocks.MAGENTA_WOOL), entry(Items.ALLIUM, Blocks.WOOL.magenta()),
entry(Items.AZURE_BLUET, Blocks.SNOW_BLOCK), entry(Items.AZURE_BLUET, Blocks.SNOW_BLOCK),
entry(Items.RED_TULIP, Blocks.RED_WOOL), entry(Items.RED_TULIP, Blocks.WOOL.red()),
entry(Items.ORANGE_TULIP, Blocks.ORANGE_WOOL), entry(Items.ORANGE_TULIP, Blocks.WOOL.orange()),
entry(Items.WHITE_TULIP, Blocks.SNOW_BLOCK), entry(Items.WHITE_TULIP, Blocks.SNOW_BLOCK),
entry(Items.PINK_TULIP, Blocks.PINK_WOOL), entry(Items.PINK_TULIP, Blocks.WOOL.pink()),
entry(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK), entry(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK),
entry(Items.CORNFLOWER, Blocks.BLUE_WOOL), entry(Items.CORNFLOWER, Blocks.WOOL.blue()),
entry(Items.WITHER_ROSE, Blocks.BLACK_WOOL), entry(Items.WITHER_ROSE, Blocks.WOOL.black()),
entry(Items.LILY_OF_THE_VALLEY, Blocks.WHITE_WOOL), entry(Items.LILY_OF_THE_VALLEY, Blocks.WOOL.white()),
entry(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK), entry(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK),
entry(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK), entry(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK),
entry(Items.STICK, Blocks.OAK_PLANKS), entry(Items.STICK, Blocks.OAK_PLANKS),
@@ -267,70 +289,70 @@ public class HopperCounter
entry(Items.IRON_INGOT, Blocks.IRON_BLOCK), entry(Items.IRON_INGOT, Blocks.IRON_BLOCK),
entry(Items.DIAMOND, Blocks.DIAMOND_BLOCK), entry(Items.DIAMOND, Blocks.DIAMOND_BLOCK),
entry(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK), entry(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK),
entry(Items.SUNFLOWER, Blocks.YELLOW_WOOL), entry(Items.SUNFLOWER, Blocks.WOOL.yellow()),
entry(Items.LILAC, Blocks.MAGENTA_WOOL), entry(Items.LILAC, Blocks.WOOL.magenta()),
entry(Items.ROSE_BUSH, Blocks.RED_WOOL), entry(Items.ROSE_BUSH, Blocks.WOOL.red()),
entry(Items.PEONY, Blocks.PINK_WOOL), entry(Items.PEONY, Blocks.WOOL.pink()),
entry(Items.CARROT, Blocks.ORANGE_WOOL), entry(Items.CARROT, Blocks.WOOL.orange()),
entry(Items.APPLE,Blocks.RED_WOOL), entry(Items.APPLE, Blocks.WOOL.red()),
entry(Items.WHEAT,Blocks.HAY_BLOCK), entry(Items.WHEAT, Blocks.HAY_BLOCK),
entry(Items.PORKCHOP, Blocks.PINK_WOOL), entry(Items.PORKCHOP, Blocks.WOOL.pink()),
entry(Items.RABBIT,Blocks.PINK_WOOL), entry(Items.RABBIT, Blocks.WOOL.pink()),
entry(Items.CHICKEN,Blocks.WHITE_TERRACOTTA), entry(Items.CHICKEN, Blocks.DYED_TERRACOTTA.white()),
entry(Items.BEEF,Blocks.NETHERRACK), entry(Items.BEEF, Blocks.NETHERRACK),
entry(Items.ENCHANTED_GOLDEN_APPLE,Blocks.GOLD_BLOCK), entry(Items.ENCHANTED_GOLDEN_APPLE, Blocks.GOLD_BLOCK),
entry(Items.COD,Blocks.WHITE_TERRACOTTA), entry(Items.COD, Blocks.DYED_TERRACOTTA.white()),
entry(Items.SALMON,Blocks.ACACIA_PLANKS), entry(Items.SALMON, Blocks.ACACIA_PLANKS),
entry(Items.ROTTEN_FLESH,Blocks.BROWN_WOOL), entry(Items.ROTTEN_FLESH, Blocks.WOOL.brown()),
entry(Items.PUFFERFISH,Blocks.YELLOW_TERRACOTTA), entry(Items.PUFFERFISH, Blocks.DYED_TERRACOTTA.orange()),
entry(Items.TROPICAL_FISH,Blocks.ORANGE_WOOL), entry(Items.TROPICAL_FISH, Blocks.WOOL.orange()),
entry(Items.POTATO,Blocks.WHITE_TERRACOTTA), entry(Items.POTATO, Blocks.DYED_TERRACOTTA.white()),
entry(Items.MUTTON, Blocks.RED_WOOL), entry(Items.MUTTON, Blocks.WOOL.red()),
entry(Items.BEETROOT,Blocks.NETHERRACK), entry(Items.BEETROOT, Blocks.NETHERRACK),
entry(Items.MELON_SLICE,Blocks.MELON), entry(Items.MELON_SLICE, Blocks.MELON),
entry(Items.POISONOUS_POTATO,Blocks.SLIME_BLOCK), entry(Items.POISONOUS_POTATO, Blocks.SLIME_BLOCK),
entry(Items.SPIDER_EYE,Blocks.NETHERRACK), entry(Items.SPIDER_EYE, Blocks.NETHERRACK),
entry(Items.GUNPOWDER,Blocks.GRAY_WOOL), entry(Items.GUNPOWDER, Blocks.WOOL.gray()),
entry(Items.TURTLE_SCUTE,Blocks.LIME_WOOL), entry(Items.TURTLE_SCUTE, Blocks.WOOL.lime()),
entry(Items.ARMADILLO_SCUTE,Blocks.ANCIENT_DEBRIS), entry(Items.ARMADILLO_SCUTE, Blocks.ANCIENT_DEBRIS),
entry(Items.FEATHER,Blocks.WHITE_WOOL), entry(Items.FEATHER, Blocks.WOOL.white()),
entry(Items.FLINT,Blocks.BLACK_WOOL), entry(Items.FLINT, Blocks.WOOL.black()),
entry(Items.LEATHER,Blocks.SPRUCE_PLANKS), entry(Items.LEATHER, Blocks.SPRUCE_PLANKS),
entry(Items.GLOWSTONE_DUST,Blocks.GLOWSTONE), entry(Items.GLOWSTONE_DUST, Blocks.GLOWSTONE),
entry(Items.PAPER,Blocks.WHITE_WOOL), entry(Items.PAPER, Blocks.WOOL.white()),
entry(Items.BRICK,Blocks.BRICKS), entry(Items.BRICK, Blocks.BRICKS),
entry(Items.INK_SAC,Blocks.BLACK_WOOL), entry(Items.INK_SAC, Blocks.WOOL.black()),
entry(Items.SNOWBALL,Blocks.SNOW_BLOCK), entry(Items.SNOWBALL, Blocks.SNOW_BLOCK),
entry(Items.WATER_BUCKET,Blocks.WATER), entry(Items.WATER_BUCKET, Blocks.WATER),
entry(Items.LAVA_BUCKET,Blocks.LAVA), entry(Items.LAVA_BUCKET, Blocks.LAVA),
entry(Items.MILK_BUCKET,Blocks.WHITE_WOOL), entry(Items.MILK_BUCKET, Blocks.WOOL.white()),
entry(Items.CLAY_BALL, Blocks.CLAY), entry(Items.CLAY_BALL, Blocks.CLAY),
entry(Items.COCOA_BEANS,Blocks.COCOA), entry(Items.COCOA_BEANS, Blocks.COCOA),
entry(Items.BONE,Blocks.BONE_BLOCK), entry(Items.BONE, Blocks.BONE_BLOCK),
entry(Items.COD_BUCKET,Blocks.BROWN_TERRACOTTA), entry(Items.COD_BUCKET, Blocks.DYED_TERRACOTTA.brown()),
entry(Items.PUFFERFISH_BUCKET,Blocks.YELLOW_TERRACOTTA), entry(Items.PUFFERFISH_BUCKET, Blocks.DYED_TERRACOTTA.yellow()),
entry(Items.SALMON_BUCKET,Blocks.PINK_TERRACOTTA), entry(Items.SALMON_BUCKET, Blocks.DYED_TERRACOTTA.pink()),
entry(Items.TROPICAL_FISH_BUCKET,Blocks.ORANGE_TERRACOTTA), entry(Items.TROPICAL_FISH_BUCKET, Blocks.DYED_TERRACOTTA.orange()),
entry(Items.SUGAR,Blocks.WHITE_WOOL), entry(Items.SUGAR, Blocks.WOOL.white()),
entry(Items.BLAZE_POWDER,Blocks.GOLD_BLOCK), entry(Items.BLAZE_POWDER, Blocks.GOLD_BLOCK),
entry(Items.ENDER_PEARL,Blocks.WARPED_PLANKS), entry(Items.ENDER_PEARL, Blocks.WARPED_PLANKS),
entry(Items.NETHER_STAR,Blocks.DIAMOND_BLOCK), entry(Items.NETHER_STAR, Blocks.DIAMOND_BLOCK),
entry(Items.PRISMARINE_CRYSTALS,Blocks.SEA_LANTERN), entry(Items.PRISMARINE_CRYSTALS, Blocks.SEA_LANTERN),
entry(Items.PRISMARINE_SHARD,Blocks.PRISMARINE), entry(Items.PRISMARINE_SHARD, Blocks.PRISMARINE),
entry(Items.RABBIT_HIDE,Blocks.OAK_PLANKS), entry(Items.RABBIT_HIDE, Blocks.OAK_PLANKS),
entry(Items.CHORUS_FRUIT,Blocks.PURPUR_BLOCK), entry(Items.CHORUS_FRUIT, Blocks.PURPUR_BLOCK),
entry(Items.SHULKER_SHELL,Blocks.SHULKER_BOX), entry(Items.SHULKER_SHELL, Blocks.SHULKER_BOX),
entry(Items.NAUTILUS_SHELL,Blocks.BONE_BLOCK), entry(Items.NAUTILUS_SHELL, Blocks.BONE_BLOCK),
entry(Items.HEART_OF_THE_SEA,Blocks.CONDUIT), entry(Items.HEART_OF_THE_SEA, Blocks.CONDUIT),
entry(Items.HONEYCOMB,Blocks.HONEYCOMB_BLOCK), entry(Items.HONEYCOMB, Blocks.HONEYCOMB_BLOCK),
entry(Items.NAME_TAG,Blocks.BONE_BLOCK), entry(Items.NAME_TAG, Blocks.BONE_BLOCK),
entry(Items.TOTEM_OF_UNDYING,Blocks.YELLOW_TERRACOTTA), entry(Items.TOTEM_OF_UNDYING, Blocks.DYED_TERRACOTTA.yellow()),
entry(Items.TRIDENT,Blocks.PRISMARINE), entry(Items.TRIDENT, Blocks.PRISMARINE),
entry(Items.GHAST_TEAR,Blocks.WHITE_WOOL), entry(Items.GHAST_TEAR, Blocks.WOOL.white()),
entry(Items.PHANTOM_MEMBRANE,Blocks.BONE_BLOCK), entry(Items.PHANTOM_MEMBRANE, Blocks.BONE_BLOCK),
entry(Items.EGG,Blocks.BONE_BLOCK), entry(Items.EGG, Blocks.BONE_BLOCK),
//entry(Items.,Blocks.), //entry(Items.,Blocks.),
entry(Items.COPPER_INGOT,Blocks.COPPER_BLOCK), entry(Items.COPPER_INGOT, Blocks.COPPER_BLOCK.weathering().unaffected()),
entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK)); entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK));
/** /**
@@ -338,25 +360,37 @@ public class HopperCounter
*/ */
public static TextColor fromItem(Item item, RegistryAccess registryAccess) public static TextColor fromItem(Item item, RegistryAccess registryAccess)
{ {
if (DEFAULTS.containsKey(item)) return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col)); if (DEFAULTS.containsKey(item))
if (item instanceof DyeItem dye) return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col)); {
return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col));
}
if (item instanceof DyeItem dye)
{
return TextColor.fromRgb(appropriateColor(Optional.ofNullable(dye.getDefaultInstance().get(DataComponents.DYE)).orElse(DyeColor.WHITE).getMapColor().col));
}
Block block = null; Block block = null;
final Registry<Item> itemRegistry = registryAccess.registryOrThrow(Registries.ITEM); final Registry<Item> itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM);
final Registry<Block> blockRegistry = registryAccess.registryOrThrow(Registries.BLOCK); final Registry<Block> blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK);
ResourceLocation id = itemRegistry.getKey(item); Identifier id = itemRegistry.getKey(item);
if (item instanceof BlockItem blockItem) if (item instanceof BlockItem blockItem)
{ {
block = blockItem.getBlock(); block = blockItem.getBlock();
} }
else if (blockRegistry.getOptional(id).isPresent()) else if (blockRegistry.getOptional(id).isPresent())
{ {
block = blockRegistry.get(id); block = blockRegistry.getValue(id);
} }
if (block != null) if (block != null)
{ {
if (block instanceof AbstractBannerBlock) return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col)); if (block instanceof AbstractBannerBlock)
if (block instanceof BeaconBeamBlock) return TextColor.fromRgb(appropriateColor( ((BeaconBeamBlock) block).getColor().getMapColor().col)); {
return TextColor.fromRgb(appropriateColor( block.defaultMapColor().col)); 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; return null;
} }
@@ -365,38 +399,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 * 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 * 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); TextColor direct = fromItem(item, registryAccess);
if (direct != null) return direct; if (direct != null)
if (CarpetServer.minecraft_server == null) return WHITE; {
return direct;
}
if (CarpetServer.minecraft_server == null)
{
return WHITE;
}
ResourceLocation id = registryAccess.registryOrThrow(Registries.ITEM).getKey(item); Identifier id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item);
for (RecipeType<?> type: registryAccess.registryOrThrow(Registries.RECIPE_TYPE)) if (id == null)
{ {
for (Recipe<?> r: ((RecipeManagerInterface) CarpetServer.minecraft_server.getRecipeManager()).getAllMatching(type, id, registryAccess)) return null;
}
for (Recipe<?> r : RecipeHelper.getRecipesForOutput(CarpetServer.minecraft_server.getRecipeManager(), id, level))
{ {
for (Ingredient ingredient: r.getIngredients()) for (Ingredient ingredient : r.placementInfo().ingredients())
{ {
for (Collection<ItemStack> stacks : ((IngredientInterface) (Object) ingredient).getRecipeStacks()) Optional<Holder<Item>> match = ingredient.items().filter(stack -> fromItem(stack.value(), registryAccess) != null).findFirst();
if (match.isPresent())
{ {
for (ItemStack iStak : stacks) return fromItem(match.get().value(), registryAccess);
{
TextColor cand = fromItem(iStak.getItem(), registryAccess);
if (cand != null)
return cand;
}
}
} }
} }
} }
return null; return null;
} }
/** /**
* Returns the hopper counter for the given color * Returns the hopper counter for the given color
*/ */
public static HopperCounter getCounter(DyeColor color) { public static HopperCounter getCounter(DyeColor color)
{
return COUNTERS.get(color); return COUNTERS.get(color);
} }
@@ -421,6 +462,6 @@ public class HopperCounter
*/ */
public long getTotalItems() public long getTotalItems()
{ {
return counter.isEmpty()?0:counter.values().longStream().sum(); return counter.isEmpty() ? 0 : counter.values().longStream().sum();
} }
} }
@@ -1,80 +1,39 @@
package carpet.helpers; package carpet.helpers;
//Author: masa //Author: masa
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.minecraft.Util;
import net.minecraft.core.BlockPos; 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.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.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.material.FluidState; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import carpet.logging.logHelpers.ExplosionLogHelper; import carpet.logging.logHelpers.ExplosionLogHelper;
import carpet.mixins.ExplosionAccessor; import carpet.mixins.ExplosionAccessor;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.utils.Messenger;
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import static carpet.script.CarpetEventServer.Event.EXPLOSION_OUTCOME;
public class OptimizedExplosion public class OptimizedExplosion
{ {
private static List<Entity> entitylist;
private static Vec3 vec3dmem;
private static long tickmem;
// For disabling the explosion particles and sound
public static int explosionSound = 0;
// masa's optimizations // masa's optimizations
private static Object2DoubleOpenHashMap<Pair<Vec3, AABB>> densityCache = new Object2DoubleOpenHashMap<>(); private static Object2DoubleOpenHashMap<Pair<Vec3, AABB>> densityCache = new Object2DoubleOpenHashMap<>();
private static MutablePair<Vec3, AABB> pairMutable = new MutablePair<>();
private static Object2ObjectOpenHashMap<BlockPos, BlockState> stateCache = new Object2ObjectOpenHashMap<>(); private static Object2ObjectOpenHashMap<BlockPos, BlockState> stateCache = new Object2ObjectOpenHashMap<>();
private static Object2ObjectOpenHashMap<BlockPos, FluidState> fluidCache = new Object2ObjectOpenHashMap<>(); private static Object2ObjectOpenHashMap<BlockPos, FluidState> fluidCache = new Object2ObjectOpenHashMap<>();
private static BlockPos.MutableBlockPos posMutable = new BlockPos.MutableBlockPos(0, 0, 0); private static BlockPos.MutableBlockPos posMutable = new BlockPos.MutableBlockPos(0, 0, 0);
private static ObjectOpenHashSet<BlockPos> affectedBlockPositionsSet = new ObjectOpenHashSet<>(); private static ObjectOpenHashSet<BlockPos> affectedBlockPositionsSet = new ObjectOpenHashSet<>();
private static boolean firstRay; private static boolean firstRay;
private static boolean rayCalcDone; private static boolean rayCalcDone;
private static ArrayList<Float> chances = new ArrayList<>();
private static BlockPos blastChanceLocation;
// Creating entity list for scarpet event public static List<BlockPos> doExplosionA(Explosion e, ExplosionLogHelper eLogger) {
private static List<Entity> entityList = new ArrayList<>();
public static void doExplosionA(Explosion e, ExplosionLogHelper eLogger) {
ExplosionAccessor eAccess = (ExplosionAccessor) e; ExplosionAccessor eAccess = (ExplosionAccessor) e;
entityList.clear(); List<BlockPos> toBlow;
boolean eventNeeded = EXPLOSION_OUTCOME.isNeeded() && !eAccess.getLevel().isClientSide();
blastCalc(e);
if (!CarpetSettings.explosionNoBlockDamage && eAccess.getDamageSource() != null) { if (!CarpetSettings.explosionNoBlockDamage && eAccess.getDamageSource() != null) {
rayCalcDone = false; rayCalcDone = false;
@@ -88,291 +47,14 @@ public class OptimizedExplosion
stateCache.clear(); stateCache.clear();
fluidCache.clear(); fluidCache.clear();
e.getToBlow().addAll(affectedBlockPositionsSet); toBlow = new ArrayList<>(affectedBlockPositionsSet);
affectedBlockPositionsSet.clear(); 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<Vec3, AABB> 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(); densityCache.clear();
}
public static void doExplosionB(Explosion e, boolean spawnParticles) return toBlow;
{
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<Pair<ItemStack, BlockPos>> objectArrayList = new ObjectArrayList<>();
Util.shuffle((ObjectArrayList<BlockPos>) 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<Pair<ItemStack, BlockPos>> objectArrayList, ItemStack itemStack, BlockPos blockPos) {
int i = objectArrayList.size();
for(int j = 0; j < i; ++j) {
Pair<ItemStack, BlockPos> 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<Entity> 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;
}
}
}
}
}
} }
private static void getAffectedPositionsOnPlaneX(Explosion e, int x, int yStart, int yEnd, int zStart, int zEnd) private static void getAffectedPositionsOnPlaneX(Explosion e, int x, int yStart, int yEnd, int zStart, int zEnd)
@@ -451,12 +133,13 @@ public class OptimizedExplosion
double xInc = (xRel / len) * 0.3; double xInc = (xRel / len) * 0.3;
double yInc = (yRel / len) * 0.3; double yInc = (yRel / len) * 0.3;
double zInc = (zRel / len) * 0.3; double zInc = (zRel / len) * 0.3;
float rand = eAccess.getLevel().random.nextFloat(); float rand = eAccess.getLevel().getRandom().nextFloat();
float sizeRand = (CarpetSettings.tntRandomRange >= 0 ? (float) CarpetSettings.tntRandomRange : rand); float sizeRand = (CarpetSettings.tntRandomRange >= 0 ? (float) CarpetSettings.tntRandomRange : rand);
float size = eAccess.getRadius() * (0.7F + sizeRand * 0.6F); float size = eAccess.getRadius() * (0.7F + sizeRand * 0.6F);
double posX = eAccess.getX(); Vec3 vec3 = eAccess.getCenter();
double posY = eAccess.getY(); double posX = vec3.x;
double posZ = eAccess.getZ(); double posY = vec3.y;
double posZ = vec3.z;
for (float f1 = 0.3F; size > 0.0F; size -= 0.22500001F) for (float f1 = 0.3F; size > 0.0F; size -= 0.22500001F)
{ {
@@ -508,112 +191,4 @@ public class OptimizedExplosion
return false; 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()
);
}
}
} }
@@ -1,24 +1,18 @@
package carpet.helpers; package carpet.helpers;
import carpet.script.utils.ParticleParser;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.particles.ParticleOptions; 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.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public class ParticleDisplay 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, player,
accentParticle, accentParticle,
true, true, true,
to.x, to.y, to.z, count, to.x, to.y, to.z, count,
spread, spread, spread, 0.0); spread, spread, spread, 0.0);
@@ -28,12 +22,12 @@ public class ParticleDisplay
Vec3 incvec = to.subtract(from).normalize();// multiply(50/sqrt(lineLengthSq)); Vec3 incvec = to.subtract(from).normalize();// multiply(50/sqrt(lineLengthSq));
for (Vec3 delta = new Vec3(0.0,0.0,0.0); for (Vec3 delta = new Vec3(0.0,0.0,0.0);
delta.lengthSqr() < lineLengthSq; delta.lengthSqr() < lineLengthSq;
delta = delta.add(incvec.scale(player.level().random.nextFloat()))) delta = delta.add(incvec.scale(player.level().getRandom().nextFloat())))
{ {
player.serverLevel().sendParticles( player.level().sendParticles(
player, player,
mainParticle, mainParticle,
true, true, true,
delta.x+from.x, delta.y+from.y, delta.z+from.z, 1, delta.x+from.x, delta.y+from.y, delta.z+from.z, 1,
0.0, 0.0, 0.0, 0.0); 0.0, 0.0, 0.0, 0.0);
} }
@@ -676,7 +676,7 @@ public class RedstoneWireTurbo
// call BlockStateBase#neighborChanged directly. This change mostly // call BlockStateBase#neighborChanged directly. This change mostly
// restores old behavior, at the cost of bypassing the // restores old behavior, at the cost of bypassing the
// max-chained-neighbor-updates server property. // 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); BlockPos neighborPos = pos.relative(dir);
BlockState neighborState = level.getBlockState(neighborPos); 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); Block.updateOrDestroy(neighborState, newState, level, neighborPos, Block.UPDATE_CLIENTS);
} }
} }
+1 -1
View File
@@ -9,7 +9,7 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.Util; import net.minecraft.util.Util;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@@ -80,7 +80,7 @@ public class ExplosionLogHelper
messages.add(c((k.pos.equals(pos))?"r - TNT":"w - ", 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((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), 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+")":""
)); ));
}); });
} }
@@ -2,6 +2,9 @@ package carpet.logging.logHelpers;
import carpet.helpers.ParticleDisplay; import carpet.helpers.ParticleDisplay;
import carpet.logging.LoggerRegistry; 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.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -31,8 +34,8 @@ public class PathfindingVisualizer
if (minDuration < 1) if (minDuration < 1)
minDuration = 1; minDuration = 1;
String accent = successful ? "happy_villager" : "angry_villager"; ParticleOptions accent = successful ? ParticleTypes.HAPPY_VILLAGER : ParticleTypes.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 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); ParticleDisplay.drawParticleLine((ServerPlayer) player, entity.position(), target, color, accent, 5, 0.5);
return null; return null;
}); });
@@ -4,7 +4,7 @@ import carpet.logging.LoggerRegistry;
import carpet.logging.logHelpers.TrajectoryLogHelper; import carpet.logging.logHelpers.TrajectoryLogHelper;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.arrow.AbstractArrow;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@@ -23,7 +23,7 @@ public abstract class AbstractArrowMixin extends Entity
@Inject(method = "<init>(Lnet/minecraft/world/entity/EntityType;DDDLnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V", at = @At("RETURN")) @Inject(method = "<init>(Lnet/minecraft/world/entity/EntityType;DDDLnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V", at = @At("RETURN"))
private void addLogger(final EntityType entityType, final double x, final double y, final double z, final Level level, final ItemStack itemStack, final ItemStack weapon, final CallbackInfo ci) private void addLogger(final EntityType entityType, final double x, final double y, final double z, final Level level, final ItemStack itemStack, final ItemStack weapon, final CallbackInfo ci)
{ {
if (LoggerRegistry.__projectiles && !level.isClientSide) if (LoggerRegistry.__projectiles && !level.isClientSide())
logHelper = new TrajectoryLogHelper("projectiles"); logHelper = new TrajectoryLogHelper("projectiles");
} }
@@ -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;
}
}
@@ -1,55 +0,0 @@
package carpet.mixins;
import carpet.CarpetSettings;
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;
import net.minecraft.core.NonNullList;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@Mixin(AbstractContainerMenu.class)
public abstract class AbstractContainerMenu_ctrlQCraftingMixin
{
@Shadow public abstract void clicked(int int_1, int int_2, ClickType slotActionType_1, Player playerEntity_1);
@Shadow public abstract void broadcastChanges();
@Shadow @Final public NonNullList<Slot> slots;
@Shadow protected abstract void resetQuickCraft();
@Shadow public abstract ItemStack getCarried();
@Inject( method = "doClick", at = @At(value = "HEAD"), cancellable = true)
private void onThrowClick(int slotId, int clickData, ClickType actionType, Player playerEntity, CallbackInfo ci)
{
if (actionType == ClickType.THROW && CarpetSettings.ctrlQCraftingFix && this.getCarried().isEmpty() && slotId >= 0)
{
Slot slot_4 = slots.get(slotId);
if (/*slot_4 != null && */slot_4.hasItem() && slot_4.mayPickup(playerEntity))
{
if(slotId == 0 && clickData == 1)
{
Item craftedItem = slot_4.getItem().getItem();
while(slot_4.hasItem() && slot_4.getItem().getItem() == craftedItem)
{
this.clicked(slotId, 0, ClickType.THROW, playerEntity);
}
this.broadcastChanges();
this.resetQuickCraft();
ci.cancel();
}
}
}
}
}
@@ -14,7 +14,7 @@ import java.util.List;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.ContainerInput;
import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.inventory.DataSlot;
@@ -26,7 +26,7 @@ public abstract class AbstractContainerMenu_scarpetMixin implements AbstractCont
@Shadow @Final private List<DataSlot> dataSlots; @Shadow @Final private List<DataSlot> dataSlots;
@Inject(method = "doClick", at = @At("HEAD"), cancellable = true) @Inject(method = "doClick", at = @At("HEAD"), cancellable = true)
private void callSlotClickListener(int slotIndex, int button, ClickType actionType, Player player, CallbackInfo ci) { private void callSlotClickListener(int slotIndex, int button, ContainerInput actionType, Player player, CallbackInfo ci) {
if(!(player instanceof ServerPlayer serverPlayerEntity)) return; if(!(player instanceof ServerPlayer serverPlayerEntity)) return;
for(ContainerListener screenHandlerListener : this.containerListeners) { for(ContainerListener screenHandlerListener : this.containerListeners) {
if(screenHandlerListener instanceof ScreenValue.ScarpetScreenHandlerListener scarpetScreenHandlerListener) { if(screenHandlerListener instanceof ScreenValue.ScarpetScreenHandlerListener scarpetScreenHandlerListener) {
@@ -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<RecipeBookMenu.PostPlaceAction> cir) {
if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING);
}
}
@@ -1,19 +1,23 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.AbstractContainerMenuInterface; import carpet.fakes.AbstractContainerMenuInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; 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.inventory.RecipeBookMenu;
import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeHolder;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; 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) @Mixin(AbstractFurnaceMenu.class)
public class RecipeBookMenu_scarpetMixin { public class AbstractFurnaceMenu_scarpetMixin
{
@Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true) @Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true)
private void selectRecipeCallback(boolean craftAll, RecipeHolder<?> recipe, ServerPlayer player, CallbackInfo ci) { private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder<?> recipe, ServerLevel level, Inventory player, CallbackInfoReturnable<RecipeBookMenu.PostPlaceAction> cir) {
if(((AbstractContainerMenuInterface) this).callSelectRecipeListener(player,recipe,craftAll)) if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
ci.cancel(); cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING);
} }
} }
@@ -4,7 +4,7 @@ import carpet.fakes.EntityInterface;
import carpet.script.EntityEventsGroup; import carpet.script.EntityEventsGroup;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -29,12 +29,12 @@ public abstract class ArmorStand_scarpetMarkerMixin extends LivingEntity
@Inject(method = "readAdditionalSaveData", at = @At("HEAD")) @Inject(method = "readAdditionalSaveData", at = @At("HEAD"))
private void checkScarpetMarkerUnloaded(CallbackInfo ci) private void checkScarpetMarkerUnloaded(CallbackInfo ci)
{ {
if (!level().isClientSide) if (!level().isClientSide())
{ {
if (getTags().contains(Auxiliary.MARKER_STRING)) if (entityTags().contains(Auxiliary.MARKER_STRING))
{ {
String prefix = Auxiliary.MARKER_STRING+"_"; String prefix = Auxiliary.MARKER_STRING+"_";
Optional<String> owner = getTags().stream().filter(s -> s.startsWith(prefix)).findFirst(); Optional<String> owner = entityTags().stream().filter(s -> s.startsWith(prefix)).findFirst();
if (owner.isPresent()) if (owner.isPresent())
{ {
String hostName = StringUtils.removeStart(owner.get(),prefix); String hostName = StringUtils.removeStart(owner.get(),prefix);
@@ -2,8 +2,9 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.fakes.LevelInterface; import carpet.fakes.LevelInterface;
import net.minecraft.world.level.redstone.NeighborUpdater; import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.level.redstone.Orientation;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -29,13 +30,13 @@ public class BarrierBlock_updateSuppressionBlockMixin extends Block {
} }
@Override @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 (CarpetSettings.updateSuppressionBlock != -1) {
if (fromPos.equals(pos.above())) { if (true/*fromPos.equals(pos.above())*/) { // todo neighbour updates don't have source
BlockState stateAbove = level.getBlockState(fromPos); BlockState stateAbove = level.getBlockState(pos.above());
if (stateAbove.is(Blocks.ACTIVATOR_RAIL) && !stateAbove.getValue(PoweredRailBlock.POWERED)) { if (stateAbove.is(Blocks.ACTIVATOR_RAIL) && !stateAbove.getValue(PoweredRailBlock.POWERED)) {
level.scheduleTick(pos, this, 1); level.scheduleTick(pos, this, 1);
NeighborUpdater updater = ((LevelInterface)level).getNeighborUpdater(); CollectingNeighborUpdater updater = ((LevelInterface)level).getNeighborUpdater();
if (updater instanceof CollectingNeighborUpdaterAccessor cnua) if (updater instanceof CollectingNeighborUpdaterAccessor cnua)
cnua.setCount(cnua.getMaxChainedNeighborUpdates()-CarpetSettings.updateSuppressionBlock); cnua.setCount(cnua.getMaxChainedNeighborUpdates()-CarpetSettings.updateSuppressionBlock);
} }
@@ -0,0 +1,22 @@
package carpet.mixins;
import carpet.fakes.BrainInterface;
import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemorySlot;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Map;
@Mixin(Brain.class)
public class Brain_scarpetMixin implements BrainInterface {
@Shadow @Final
private Map<MemoryModuleType<?>, MemorySlot<?>> memories;
@Override
public Map<MemoryModuleType<?>, MemorySlot<?>> getMemoriesCM() {
return memories;
}
}
@@ -3,10 +3,10 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; 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.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level; 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.BuddingAmethystBlock;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; 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) @Mixin(BuddingAmethystBlock.class)
public class BuddingAmethystBlock_movableAmethystMixin extends Block { 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 // doing it here rather than though loottables since loottables are loaded on reload
// drawback - not controlled via loottables, but hey // drawback - not controlled via loottables, but hey
if (CarpetSettings.movableAmethyst && if (CarpetSettings.movableAmethyst &&
stack.getItem() instanceof PickaxeItem && stack.is(ItemTags.PICKAXES) &&
EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).getHolderOrThrow(Enchantments.SILK_TOUCH), stack) > 0 EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH), stack) > 0
) )
popResource(world, pos, Items.BUDDING_AMETHYST.getDefaultInstance()); popResource(world, pos, Items.BUDDING_AMETHYST.getDefaultInstance());
} }
@@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class ChunkAccess_warningsMixin public abstract class ChunkAccess_warningsMixin
{ {
// failed to mixin into interface. need to mixin in two places that uses it // failed to mixin into interface. need to mixin in two places that uses it
@Inject(method = "markPosForPostprocessing(Lnet/minecraft/core/BlockPos;)V", @Inject(method = "markPosForPostProcessing(Lnet/minecraft/core/BlockPos;)V",
at =@At("HEAD"), cancellable = true) at =@At("HEAD"), cancellable = true)
private void squashWarnings(BlockPos blockPos_1, CallbackInfo ci) private void squashWarnings(BlockPos blockPos_1, CallbackInfo ci)
{ {
@@ -3,6 +3,7 @@ package carpet.mixins;
import carpet.utils.SpawnOverrides; import carpet.utils.SpawnOverrides;
import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.util.random.WeightedList;
import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.Structure;
import org.spongepowered.asm.mixin.Mixin; 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.MobSpawnSettings; 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;" target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;"
), cancellable = true) ), cancellable = true)
private void checkCMSpawns(Holder<Biome> holder, StructureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos, private void checkCMSpawns(Holder<Biome> holder, StructureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos,
CallbackInfoReturnable<WeightedRandomList<MobSpawnSettings.SpawnerData>> cir, CallbackInfoReturnable<WeightedList<MobSpawnSettings.SpawnerData>> cir,
Map<Structure, LongSet> map, Iterator<?> var6, Map.Entry<Structure, LongSet> entry) Map<Structure, LongSet> map, Iterator<?> var6, Map.Entry<Structure, LongSet> entry)
{ {
WeightedRandomList<MobSpawnSettings.SpawnerData> res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos); WeightedList<MobSpawnSettings.SpawnerData> res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos);
if (res != null) if (res != null)
{ {
cir.setReturnValue(res); cir.setReturnValue(res);
@@ -9,12 +9,12 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.IntFunction; import java.util.function.IntFunction;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import carpet.fakes.SimpleEntityLookupInterface; import carpet.fakes.SimpleEntityLookupInterface;
import carpet.fakes.ServerWorldInterface; import net.minecraft.util.Util;
import net.minecraft.Util;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.TickTask; import net.minecraft.server.TickTask;
@@ -23,11 +23,11 @@ import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkMap.DistanceManager; import net.minecraft.server.level.ChunkMap.DistanceManager;
import net.minecraft.server.level.ChunkResult; 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.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@@ -46,7 +46,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import carpet.fakes.ChunkHolderInterface; import carpet.fakes.ChunkHolderInterface;
import carpet.fakes.ChunkTicketManagerInterface;
import carpet.fakes.ServerLightingProviderInterface; import carpet.fakes.ServerLightingProviderInterface;
import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface;
import carpet.script.utils.WorldTools; import carpet.script.utils.WorldTools;
@@ -76,17 +75,17 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
@Final @Final
private ThreadedLevelLightEngine lightEngine; private ThreadedLevelLightEngine lightEngine;
@Shadow //@Shadow
@Final //@Final
private ChunkTaskPriorityQueueSorter queueSorter; //private ChunkTaskPriorityQueueSorter queueSorter;
@Shadow @Shadow
@Final @Final
private BlockableEventLoop<Runnable> mainThreadExecutor; private BlockableEventLoop<Runnable> mainThreadExecutor;
@Shadow //@Shadow
@Final //@Final
private ChunkProgressListener progressListener; //private ChunkProgressListener progressListener;
@Shadow @Shadow
@Final @Final
@@ -95,8 +94,8 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
@Shadow @Shadow
protected abstract boolean promoteChunkMap(); protected abstract boolean promoteChunkMap();
@Shadow //@Shadow
protected abstract Iterable<ChunkHolder> getChunks(); //protected abstract void forEachReadyToSendChunk(Consumer<LevelChunk> consumer); // for getChunks()
@Shadow @Shadow
@@ -165,7 +164,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
this.world.getServer().execute(() -> CHUNK_LOADED.onChunkEvent(this.world, chpos, generated)); this.world.getServer().execute(() -> CHUNK_LOADED.onChunkEvent(this.world, chpos, generated));
} }
} }
*/
@Unique @Unique
private void addTicket(ChunkPos pos, ChunkStatus status) private void addTicket(ChunkPos pos, ChunkStatus status)
@@ -180,7 +178,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
} }
/*
@Unique @Unique
private void addRelightTicket(ChunkPos pos) private void addRelightTicket(ChunkPos pos)
{ {
@@ -195,7 +192,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
() -> "release relight ticket " + pos () -> "release relight ticket " + pos
)); ));
} }
*/
@Unique @Unique
private void tickTicketManager() private void tickTicketManager()
{ {
@@ -220,7 +217,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
} }
/*
@Unique @Unique
private Set<ChunkPos> loadExistingChunksFromDisk(Set<ChunkPos> requestedChunks) private Set<ChunkPos> loadExistingChunksFromDisk(Set<ChunkPos> requestedChunks)
{ {
@@ -35,7 +35,7 @@ public abstract class ClientPacketListener_clientCommandMixin extends ClientComm
if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet() && minecraft.player != null) if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet() && minecraft.player != null)
{ {
LocalPlayer playerSource = minecraft.player; LocalPlayer playerSource = minecraft.player;
CarpetServer.forEachManager(sm -> sm.inspectClientsideCommand(playerSource.createCommandSourceStack(), "/" + string)); CarpetServer.forEachManager(sm -> sm.inspectClientsideCommand("/" + string));
} }
} }
} }
@@ -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();
}
}
}
}
@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.server.commands.CloneCommands; import net.minecraft.server.commands.CloneCommands;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@@ -14,10 +15,10 @@ public abstract class CloneCommands_fillUpdatesMixin
{ {
@Redirect(method = "clone", at = @At( @Redirect(method = "clone", at = @At(
value = "INVOKE", 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);
} }
} }
@@ -0,0 +1,29 @@
package carpet.mixins;
import carpet.fakes.CommandSourceStackInterface;
import net.minecraft.commands.CommandResultCallback;
import net.minecraft.commands.CommandSigningContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.util.TaskChainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(CommandSourceStack.class)
public class CommandSourceStack_scarpetMixin implements CommandSourceStackInterface {
@Mutable @Shadow private boolean silent;
@Mutable @Shadow private CommandResultCallback resultCallback;
@Mutable @Shadow private EntityAnchorArgument.Anchor anchor;
@Mutable @Shadow private CommandSigningContext signingContext;
@Mutable @Shadow private TaskChainer chatMessageChainer;
@Override
public void setupPrivates(boolean bl, CommandResultCallback commandResultCallback, EntityAnchorArgument.Anchor anchor, CommandSigningContext commandSigningContext, TaskChainer taskChainer) {
this.silent = bl;
this.resultCallback = commandResultCallback;
this.anchor = anchor;
this.signingContext = commandSigningContext;
this.chatMessageChainer = taskChainer;
}
}
@@ -3,6 +3,7 @@ package carpet.mixins;
import carpet.fakes.ClientConnectionInterface; import carpet.fakes.ClientConnectionInterface;
import carpet.logging.logHelpers.PacketCounter; import carpet.logging.logHelpers.PacketCounter;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener; 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. // Add to the packet counter whenever a packet is sent.
@Inject(method = "sendPacket", at = @At("HEAD")) @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++; PacketCounter.totalOut++;
} }
@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(DebugRenderer.class) @Mixin(DebugRenderer.class)
public class DebugRenderer_scarpetRenderMixin public class DebugRenderer_scarpetRenderMixin
{ {
@Inject(method = "clear", at = @At("HEAD")) @Inject(method = "refreshRendererList", at = @At("HEAD"))
private void resetScarpetRenderes(CallbackInfo ci) private void resetScarpetRenderes(CallbackInfo ci)
{ {
if (CarpetClient.shapes != null) if (CarpetClient.shapes != null)
@@ -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);
}
}
@@ -1,5 +1,6 @@
package carpet.mixins; package carpet.mixins;
import net.minecraft.world.level.redstone.Orientation;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; 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" 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); return QuasiConnectivity.hasQuasiSignal(level, pos);
} }
} }
@@ -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<ChunkHolder> chunksToUpdateFutures;
@Override
public void replaceHolder(final ChunkHolder oldHolder, final ChunkHolder newHolder)
{
this.chunksToUpdateFutures.remove(oldHolder);
this.chunksToUpdateFutures.add(newHolder);
}
}
@@ -1,23 +1,25 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.ChunkTicketManagerInterface; import carpet.fakes.TicketsFetcherInterface;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.Ticket; 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.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import java.util.List;
@Mixin(DistanceManager.class) @Mixin(DistanceManager.class)
public abstract class DistanceManager_scarpetMixin implements ChunkTicketManagerInterface public abstract class DistanceManager_scarpetMixin implements TicketsFetcherInterface
{ {
@Shadow @Final private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets; @Shadow @Final private TicketStorage ticketStorage;
@Override @Override
public Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> getTicketsByPosition() public Long2ObjectOpenHashMap<List<Ticket>> getTicketsByPosition()
{ {
return tickets; return ((TicketsFetcherInterface)ticketStorage).getTicketsByPosition();
} }
} }
@@ -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<SortedArraySet<Ticket<?>>> tickets;
@Shadow protected abstract void removeTicket(long pos, Ticket<?> ticket);
@Shadow public abstract <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int radius, T argument);
@Override
public void changeSpawnChunks(ChunkPos chunkPos, int distance)
{
long pos = chunkPos.toLong();
SortedArraySet<Ticket<?>> set = tickets.get(pos);
Ticket<?> existingTicket = null;
if (set != null)
{
Iterator<Ticket<?>> 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);
}
}
+15 -2
View File
@@ -6,6 +6,9 @@ import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -32,9 +35,19 @@ public abstract class EntityMixin implements EntityInterface
return partialTicks == 1.0F ? this.yRot : Mth.lerp(partialTicks, this.yRotO, this.yRot); 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<Boolean> cir) private void isFakePlayer(CallbackInfoReturnable<Boolean> cir)
{ {
if (getControllingPassenger() instanceof EntityPlayerMPFake) cir.setReturnValue(!level.isClientSide); // getControllingPassenger() does not return the EntityPlayerMPFake if there are no passengers involved with it
if ((Object) this instanceof EntityPlayerMPFake || getControllingPassenger() instanceof EntityPlayerMPFake) cir.setReturnValue(!level.isClientSide());
}
@Shadow
protected abstract Stream<Entity> getIndirectPassengersStream();
@Override
public Stream<Entity> cm$getIndirectPassengersStream()
{
return this.getIndirectPassengersStream();
} }
} }
@@ -19,9 +19,6 @@ public abstract class ExperienceOrb_xpNoCooldownMixin extends Entity
@Shadow @Shadow
private int count; private int count;
@Shadow
private int value;
public ExperienceOrb_xpNoCooldownMixin(EntityType<?> type, Level world) public ExperienceOrb_xpNoCooldownMixin(EntityType<?> type, Level world)
{ {
super(type, world); super(type, world);
@@ -30,13 +27,15 @@ public abstract class ExperienceOrb_xpNoCooldownMixin extends Entity
@Shadow @Shadow
protected abstract int repairPlayerItems(ServerPlayer player, int amount); protected abstract int repairPlayerItems(ServerPlayer player, int amount);
@Shadow public abstract int getValue();
@Inject(method = "playerTouch", at = @At("HEAD")) @Inject(method = "playerTouch", at = @At("HEAD"))
private void addXP(Player player, CallbackInfo ci) { private void addXP(Player player, CallbackInfo ci) {
if (CarpetSettings.xpNoCooldown && !level().isClientSide) { if (CarpetSettings.xpNoCooldown && !level().isClientSide()) {
player.takeXpDelay = 0; player.takeXpDelay = 0;
// reducing the count to 1 and leaving vanilla to deal with it // reducing the count to 1 and leaving vanilla to deal with it
while (this.count > 1) { while (this.count > 1) {
int remainder = this.repairPlayerItems((ServerPlayer) player, this.value); int remainder = this.repairPlayerItems((ServerPlayer) player, this.getValue());
if (remainder > 0) { if (remainder > 0) {
player.giveExperiencePoints(remainder); player.giveExperiencePoints(remainder);
} }
@@ -1,37 +1,22 @@
package carpet.mixins; package carpet.mixins;
import net.minecraft.util.RandomSource; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource; 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.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.world.entity.Entity; 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 { public interface ExplosionAccessor {
@Accessor @Accessor
boolean isFire(); ServerLevel getLevel();
@Accessor @Accessor
Explosion.BlockInteraction getBlockInteraction(); Vec3 getCenter();
@Accessor
Level getLevel();
@Accessor
RandomSource getRandom();
@Accessor
double getX();
@Accessor
double getY();
@Accessor
double getZ();
@Accessor @Accessor
float getRadius(); float getRadius();
@@ -4,11 +4,12 @@ import carpet.helpers.OptimizedExplosion;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.logging.LoggerRegistry; import carpet.logging.LoggerRegistry;
import carpet.logging.logHelpers.ExplosionLogHelper; import carpet.logging.logHelpers.ExplosionLogHelper;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.breeze.Breeze; 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.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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.entity.Entity;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator; 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.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; 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 public abstract class Explosion_optimizedTntMixin
{ {
@Shadow @Shadow @Final private ServerLevel level;
@Final
private ObjectArrayList<BlockPos> toBlow;
@Shadow @Final private Level level;
@Shadow @Nullable public abstract LivingEntity getIndirectSourceEntity(); @Shadow @Nullable public abstract LivingEntity getIndirectSourceEntity();
private ExplosionLogHelper eLogger; private ExplosionLogHelper eLogger;
@Inject(method = "explode", at = @At("HEAD"), @Inject(method = "calculateExplodedPositions", at = @At("HEAD"),
cancellable = true) cancellable = true)
private void onExplosionA(CallbackInfo ci) private void calculateExplodedPositionsCM(final CallbackInfoReturnable<List<BlockPos>> cir)
{ {
if (CarpetSettings.optimizedTNT && !level.isClientSide && !(getIndirectSourceEntity() instanceof Breeze)) if (CarpetSettings.optimizedTNT && !level.isClientSide() && !(getIndirectSourceEntity() instanceof Breeze))
{ {
OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger); cir.setReturnValue(OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger));
ci.cancel();
} }
} }
@Inject(method = "finalizeExplosion", at = @At("HEAD"), @Inject(method = "interactWithBlocks", at = @At("HEAD"))
cancellable = true) private void interactWithBlocksCM(final List<BlockPos> list, final CallbackInfo ci)
private void onExplosionB(boolean spawnParticles, CallbackInfo ci)
{ {
if (eLogger != null) if (eLogger != null)
{ {
eLogger.setAffectBlocks( ! toBlow.isEmpty()); eLogger.setAffectBlocks( ! list.isEmpty());
eLogger.onExplosionDone(this.level.getGameTime()); eLogger.onExplosionDone(this.level.getGameTime());
} }
if (CarpetSettings.explosionNoBlockDamage) 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 //optional due to Overwrite in Lithium
//should kill most checks if no block damage is requested //should kill most checks if no block damage is requested
@Redirect(method = "explode", require = 0, at = @At(value = "INVOKE", @Redirect(method = "calculateExplodedPositions", require = 0, at = @At(value = "INVOKE",
target ="Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) 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 BlockState noBlockCalcsWithNoBLockDamage(Level world, BlockPos pos) private Optional<Float> noBlockCalcsWithNoBLockDamage(final ExplosionDamageCalculator instance, final Explosion explosion, final BlockGetter blockGetter, final BlockPos blockPos, final BlockState blockState, final FluidState fluidState)
{ {
if (CarpetSettings.explosionNoBlockDamage) return Blocks.BEDROCK.defaultBlockState(); if (CarpetSettings.explosionNoBlockDamage) return Optional.of(Blocks.BEDROCK.getExplosionResistance());
return world.getBlockState(pos); return instance.getBlockExplosionResistance(explosion, blockGetter, blockPos, blockState, fluidState);
} }
@Inject(method = "<init>(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", @Inject(method = "<init>",
at = @At(value = "RETURN")) 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) 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", @Redirect(method = "hurtEntities",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(Lnet/minecraft/world/phys/Vec3;)V"))
private void setVelocityAndUpdateLogging(Entity entity, Vec3 velocity) private void setVelocityAndUpdateLogging(Entity entity, Vec3 velocity)
{ {
if (eLogger != null) { if (eLogger != null) {
eLogger.onEntityImpacted(entity, velocity.subtract(entity.getDeltaMovement())); eLogger.onEntityImpacted(entity, velocity.subtract(entity.getDeltaMovement()));
} }
entity.setDeltaMovement(velocity); entity.push(velocity);
} }
} }
@@ -1,8 +1,6 @@
package carpet.mixins; package carpet.mixins;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.world.level.ServerExplosion;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.ParticleOptions;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -10,70 +8,52 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Explosion; 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 net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import static carpet.script.CarpetEventServer.Event.EXPLOSION_OUTCOME; 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 public abstract class Explosion_scarpetEventMixin
{ {
@Shadow @Final private Level level; @Shadow @Final private ServerLevel level;
@Shadow @Final private double x; @Shadow @Final private Vec3 center;
@Shadow @Final private double y;
@Shadow @Final private double z;
@Shadow @Final private float radius; @Shadow @Final private float radius;
@Shadow @Final private boolean fire; @Shadow @Final private boolean fire;
@Shadow @Final private ObjectArrayList<BlockPos> toBlow;
@Shadow @Final private Explosion.BlockInteraction blockInteraction; @Shadow @Final private Explosion.BlockInteraction blockInteraction;
@Shadow @Final private @Nullable Entity source; @Shadow @Final private @Nullable Entity source;
@Shadow /*@Nullable*/ public abstract /*@Nullable*/ LivingEntity getIndirectSourceEntity(); @Shadow /*@Nullable*/ public abstract /*@Nullable*/ LivingEntity getIndirectSourceEntity();
@Shadow public static float getSeenPercent(Vec3 source, Entity entity) {return 0.0f;} private List<Entity> affectedEntities = new ArrayList<>();
private List<Entity> affectedEntities; @Inject(method = "explode", at = @At("HEAD"))
private void explodeCM(CallbackInfoReturnable<Integer> cir)
@Inject(method = "<init>(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)
{ {
if (EXPLOSION_OUTCOME.isNeeded() && !world.isClientSide()) affectedEntities.clear();
{
affectedEntities = new ArrayList<>();
}
} }
@Redirect(method = "explode", at=@At( @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;onExplosionHit(Lnet/minecraft/world/entity/Entity;)V"))
value = "INVOKE", private void onEntityHit(Entity instance, Entity entity)
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)
{ {
if (affectedEntities != null) affectedEntities.add(instance);
{ instance.onExplosionHit(entity);
affectedEntities.add(entity);
}
return getSeenPercent(source, entity);
} }
@Inject(method = "finalizeExplosion", at = @At("HEAD")) @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 onExplosion(boolean spawnParticles, CallbackInfo ci) private void onExplosionDone(CallbackInfoReturnable<Integer> cir, List list)
{ {
if (EXPLOSION_OUTCOME.isNeeded() && !level.isClientSide()) 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);
} }
} }
} }
@@ -21,7 +21,7 @@ public abstract class FallingBlockEntityMixin extends Entity
@Inject(method = "<init>(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V", at = @At("RETURN")) @Inject(method = "<init>(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V", at = @At("RETURN"))
private void addLogger(EntityType<? extends Projectile> entityType_1, Level world_1, CallbackInfo ci) private void addLogger(EntityType<? extends Projectile> entityType_1, Level world_1, CallbackInfo ci)
{ {
if (LoggerRegistry.__fallingBlocks && !world_1.isClientSide) if (LoggerRegistry.__fallingBlocks && !world_1.isClientSide())
logHelper = new TrajectoryLogHelper("fallingBlocks"); logHelper = new TrajectoryLogHelper("fallingBlocks");
} }
@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.server.commands.FillCommand; import net.minecraft.server.commands.FillCommand;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@@ -14,10 +15,10 @@ public abstract class FillCommandMixin
{ {
@Redirect(method = "fillBlocks", at = @At( @Redirect(method = "fillBlocks", at = @At(
value = "INVOKE", 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);
} }
} }
@@ -16,14 +16,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class FlowingFluid_liquidDamageDisabledMixin public class FlowingFluid_liquidDamageDisabledMixin
{ {
@Inject( @Inject(
method = "canHoldFluid", method = "canHoldAnyFluid",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;blocksMotion()Z" target = "Lnet/minecraft/world/level/block/state/BlockState;blocksMotion()Z"
), ),
cancellable = true cancellable = true
) )
private void stopBreakingBlock(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid, CallbackInfoReturnable<Boolean> cir) private static void stopBreakingBlock(final BlockState state, final CallbackInfoReturnable<Boolean> cir)
{ {
if (CarpetSettings.liquidDamageDisabled) if (CarpetSettings.liquidDamageDisabled)
{ {
@@ -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;
}
}
@@ -1,12 +1,11 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.LightningBolt; 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.ElderGuardian;
import net.minecraft.world.entity.monster.Guardian; import net.minecraft.world.entity.monster.Guardian;
import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.monster.Monster;
@@ -24,11 +23,11 @@ public abstract class Guardian_renewableSpongesMixin extends Monster
@Override @Override
public void thunderHit(ServerLevel serverWorld, LightningBolt lightningEntity) public void thunderHit(ServerLevel serverWorld, LightningBolt lightningEntity)
{ // isRemoved() { // isRemoved()
if (!this.level().isClientSide && !this.isRemoved() && CarpetSettings.renewableSponges && !((Object)this instanceof ElderGuardian)) if (!this.level().isClientSide() && !this.isRemoved() && CarpetSettings.renewableSponges && !((Object)this instanceof ElderGuardian))
{ {
ElderGuardian elderGuardian = new ElderGuardian(EntityType.ELDER_GUARDIAN ,this.level()); ElderGuardian elderGuardian = new ElderGuardian(EntityTypes.ELDER_GUARDIAN ,this.level());
elderGuardian.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); elderGuardian.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
elderGuardian.finalizeSpawn(serverWorld ,this.level().getCurrentDifficultyAt(elderGuardian.blockPosition()), MobSpawnType.CONVERSION, null); elderGuardian.finalizeSpawn(serverWorld ,serverWorld.getCurrentDifficultyAt(elderGuardian.blockPosition()), EntitySpawnReason.CONVERSION, null);
elderGuardian.setNoAi(this.isNoAi()); elderGuardian.setNoAi(this.isNoAi());
if (this.hasCustomName()) if (this.hasCustomName())
@@ -3,6 +3,7 @@ package carpet.mixins;
import carpet.fakes.PlayerListHudInterface; import carpet.fakes.PlayerListHudInterface;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.Hud;
import net.minecraft.client.gui.components.PlayerTabOverlay; import net.minecraft.client.gui.components.PlayerTabOverlay;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -10,7 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Gui.class) @Mixin(Hud.class)
public abstract class Gui_tablistMixin public abstract class Gui_tablistMixin
{ {
@Shadow @Shadow
@@ -19,7 +20,7 @@ public abstract class Gui_tablistMixin
@Shadow @Final private PlayerTabOverlay tabList; @Shadow @Final private PlayerTabOverlay tabList;
@Redirect(method = "renderTabList", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;isLocalServer()Z")) @Redirect(method = "extractTabList", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;isLocalServer()Z"))
private boolean onDraw(Minecraft minecraftClient) private boolean onDraw(Minecraft minecraftClient)
{ {
return this.minecraft.isLocalServer() && !((PlayerListHudInterface) tabList).hasFooterOrHeader(); return this.minecraft.isLocalServer() && !((PlayerListHudInterface) tabList).hasFooterOrHeader();
@@ -3,7 +3,7 @@ package carpet.mixins;
import carpet.fakes.InventoryBearerInterface; import carpet.fakes.InventoryBearerInterface;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer; import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.animal.equine.AbstractHorse;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -1,23 +0,0 @@
package carpet.mixins;
import carpet.CarpetSettings;
import carpet.utils.SpawnOverrides;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.monster.Husk;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Husk.class)
public class Husk_templesMixin
{
@Redirect(method = "checkHuskSpawnRules", at = @At(value = "INVOKE", target="Lnet/minecraft/world/level/ServerLevelAccessor;canSeeSky(Lnet/minecraft/core/BlockPos;)Z"))
private static boolean isSkylightOrTempleVisible(ServerLevelAccessor serverWorldAccess, BlockPos pos)
{
return serverWorldAccess.canSeeSky(pos) ||
(CarpetSettings.huskSpawningInTemples && SpawnOverrides.isStructureAtPosition((ServerLevel)serverWorldAccess, BuiltinStructures.DESERT_PYRAMID, pos));
}
}
@@ -1,24 +1,11 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.IngredientInterface;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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; import net.minecraft.world.item.crafting.Ingredient;
@Mixin(Ingredient.class) @Mixin(Ingredient.class)
public class Ingredient_scarpetMixin implements IngredientInterface public class Ingredient_scarpetMixin// implements IngredientInterface
{ {
@Shadow @Final private Ingredient.Value[] values;
@Override
public List<Collection<ItemStack>> getRecipeStacks()
{
return Arrays.stream(values).map(Ingredient.Value::getItems).toList();
}
} }
@@ -3,6 +3,7 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemInstance;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemContainerContents;
import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraft.world.level.block.ShulkerBoxBlock;
@@ -11,16 +12,17 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ItemStack.class) @Mixin(ItemInstance.class)
public class ItemStack_stackableShulkerBoxesMixin public interface ItemStack_stackableShulkerBoxesMixin
{ {
@Inject(method = "getMaxStackSize", at = @At("HEAD"), cancellable = true) @Inject(method = "getMaxStackSize", at = @At("HEAD"), cancellable = true)
private void getCMMAxStackSize(CallbackInfoReturnable<Integer> cir) private void getCMMAxStackSize(CallbackInfoReturnable<Integer> cir)
{ {
if (CarpetSettings.shulkerBoxStackSize > 1 if (CarpetSettings.shulkerBoxStackSize > 1
&& ((ItemStack)((Object)this)).getItem() instanceof BlockItem blockItem && ((ItemInstance)((Object)this)) instanceof final ItemStack itemStack
&& itemStack.getItem() instanceof BlockItem blockItem
&& blockItem.getBlock() instanceof ShulkerBoxBlock && blockItem.getBlock() instanceof ShulkerBoxBlock
&& ((ItemStack) ((Object) this)).getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty() && ((ItemStack) ((Object) this)).getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).allItemsCopyStream().findAny().isEmpty()
) { ) {
cir.setReturnValue(CarpetSettings.shulkerBoxStackSize); cir.setReturnValue(CarpetSettings.shulkerBoxStackSize);
} }
@@ -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<Float> 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()));
}
}
}
}
@@ -2,7 +2,9 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level; 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.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -25,20 +27,25 @@ public class LevelChunk_fillUpdatesMixin
@Redirect(method = "setBlockState", at = @At( @Redirect(method = "setBlockState", at = @At(
value = "INVOKE", 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())) blockEntity.preRemoveSideEffects(blockPos_1, blockState_1);
{
world.removeBlockEntity(pos);
} }
} }
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)
{ {
blockState.onRemove(world, pos, state, moved); if (!CarpetSettings.impendingFillSkipUpdates.get())
{
instance.affectNeighborsAfterRemoval(serverLevel, blockPos, b);
} }
} }
} }
@@ -4,21 +4,24 @@ import carpet.CarpetSettings;
import carpet.fakes.WorldChunkInterface; import carpet.fakes.WorldChunkInterface;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; 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.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.biome.Biome; 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.Block;
import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.piston.MovingPistonBlock; import net.minecraft.world.level.block.piston.MovingPistonBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.*;
import net.minecraft.world.level.chunk.LevelChunk;
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.Heightmap;
import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.lighting.LightEngine;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -33,8 +36,8 @@ public abstract class LevelChunk_movableBEMixin extends ChunkAccess implements W
@Final @Final
Level level; Level level;
public LevelChunk_movableBEMixin(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biome, long inhabitedTime, @Nullable LevelChunkSection[] sectionArrayInitializer, @Nullable BlendingData blendingData) { public LevelChunk_movableBEMixin(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, PalettedContainerFactory palettedContainerFactory, long l, @Nullable LevelChunkSection[] levelChunkSections, @Nullable BlendingData blendingData) {
super(pos, upgradeData, heightLimitView, biome, inhabitedTime, sectionArrayInitializer, blendingData); super(chunkPos, upgradeData, levelHeightAccessor, palettedContainerFactory, l, levelChunkSections, blendingData);
} }
@Shadow @Shadow
@@ -72,73 +75,110 @@ public abstract class LevelChunk_movableBEMixin extends ChunkAccess implements W
*/ */
/* @Nullable */ /* @Nullable */
// todo update me to the new version // todo update me to the new version
@Override
public BlockState setBlockStateWithBlockEntity(BlockPos blockPos_1, BlockState newBlockState, BlockEntity newBlockEntity, 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 y = blockPos_1.getY();
int z = blockPos_1.getZ() & 15;
LevelChunkSection chunkSection = this.getSection(this.getSectionIndex(y)); LevelChunkSection chunkSection = this.getSection(this.getSectionIndex(y));
if (chunkSection.hasOnlyAir())
{ boolean hadOnlyAir = chunkSection.hasOnlyAir();
if (newBlockState.isAir())
if (hadOnlyAir && newBlockState.isAir())
{ {
return null; return null;
} }
}
boolean boolean_2 = chunkSection.hasOnlyAir(); int x = blockPos_1.getX() & 15;
BlockState oldBlockState = chunkSection.setBlockState(x, y & 15, z, newBlockState); int chunkY = blockPos_1.getY() & 15;
int z = blockPos_1.getZ() & 15;
BlockState oldBlockState = chunkSection.setBlockState(x, chunkY, z, newBlockState);
if (oldBlockState == newBlockState) if (oldBlockState == newBlockState)
{ {
return null; return null;
} }
else
{
Block newBlock = newBlockState.getBlock(); Block newBlock = newBlockState.getBlock();
Block oldBlock = oldBlockState.getBlock(); this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(x, y, z, newBlockState);
((Heightmap) 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);
((Heightmap) 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);
((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(x, y, z, newBlockState); this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(x, y, z, newBlockState);
((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(x, y, z, newBlockState); boolean hasOnlyAir = chunkSection.hasOnlyAir();
boolean boolean_3 = chunkSection.hasOnlyAir(); if (hadOnlyAir != 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 (!this.level.isClientSide) if (LightEngine.hasDifferentLightProperties(oldBlockState, newBlockState)) {
ProfilerFiller profiler = Profiler.get();
profiler.push("updateSkyLightSources");
if (skyLightSources != null) // compat with ScalableLux aka Starlight port
{ {
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 skyLightSources.update(this, x, chunkY, z);
oldBlockState.onRemove(this.level, blockPos_1, newBlockState, boolean_1);//this kills it
} }
else if (oldBlock != newBlock && oldBlock instanceof EntityBlock) profiler.popPush("queueCheckLight");
{ level.getChunkSource().getLightEngine().checkBlock(blockPos_1);
this.level.removeBlockEntity(blockPos_1); profiler.pop();
} }
if (chunkSection.getBlockState(x, y & 15, z).getBlock() != newBlock) boolean blockChanged = !oldBlockState.is(newBlock);
boolean movedByPiston = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0; // moved by pistons
boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
if (blockChanged && oldBlockState.hasBlockEntity()) {
if (level instanceof ServerLevel && !(oldBlockState.getBlock() instanceof MovingPistonBlock)) {
if (sideEffects) {
BlockEntity blockEntity = level.getBlockEntity(blockPos_1);
if (blockEntity != null) {
blockEntity.preRemoveSideEffects(blockPos_1, oldBlockState);
}
}
}
removeBlockEntity(blockPos_1);
}
if (blockChanged || newBlock instanceof BaseRailBlock)
{
if (level instanceof ServerLevel serverLevel && !(oldBlockState.getBlock() instanceof MovingPistonBlock))
{
if ((flags & Block.UPDATE_NEIGHBORS) != 0 || movedByPiston)
{
oldBlockState.affectNeighborsAfterRemoval(serverLevel, blockPos_1, movedByPiston);
}
}
}
if (chunkSection.getBlockState(x, chunkY, z).getBlock() != newBlock)
{ {
return null; return null;
} }
else
{ 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, movedByPiston);
}
BlockEntity oldBlockEntity = null; BlockEntity oldBlockEntity = null;
if (oldBlockState.hasBlockEntity()) if (oldBlockState.hasBlockEntity())
{ {
oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK); oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK);
if (oldBlockEntity != null) if (oldBlockEntity != null && !oldBlockEntity.isValidBlockState(oldBlockState))
{ {
oldBlockEntity.setBlockState(oldBlockState); oldBlockEntity.setBlockState(oldBlockState);
updateBlockEntityTicker(oldBlockEntity); updateBlockEntityTicker(oldBlockEntity);
} }
} else
if (oldBlockState.hasBlockEntity())
{ {
if (newBlockEntity == null) if (newBlockEntity == null)
{ {
newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState); newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState);
if (newBlockEntity != null)
{
addAndRegisterBlockEntity(newBlockEntity);
}
} }
if (newBlockEntity != oldBlockEntity && newBlockEntity != null) if (newBlockEntity != oldBlockEntity && newBlockEntity != null)
{ {
@@ -148,15 +188,9 @@ public abstract class LevelChunk_movableBEMixin extends ChunkAccess implements W
updateBlockEntityTicker(newBlockEntity); 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 markUnsaved();
return oldBlockState; return oldBlockState;
} }
}
}
} }
@@ -21,7 +21,7 @@ public class LevelEntityGetterAdapter_scarpetMixin<T extends EntityAccess> imple
@Override @Override
public List<T> getChunkEntities(ChunkPos chpos) { public List<T> getChunkEntities(ChunkPos chpos) {
return this.sectionStorage.getExistingSectionsInChunk(chpos.toLong()).flatMap(EntitySection::getEntities).collect(Collectors.toList()); return this.sectionStorage.getExistingSectionsInChunk(chpos.pack()).flatMap(EntitySection::getEntities).collect(Collectors.toList());
} }
} }
@@ -1,16 +1,16 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.client.Camera;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.LevelRenderer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LevelRenderer.class) @Mixin(Camera.class)
public class LevelRenderer_creativeNoClipMixin public class LevelRenderer_creativeNoClipMixin
{ {
@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z")) @Redirect(method = "extractRenderState", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z"))
private boolean canSeeWorld(LocalPlayer clientPlayerEntity) private boolean canSeeWorld(LocalPlayer clientPlayerEntity)
{ {
return clientPlayerEntity.isSpectator() || (CarpetSettings.creativeNoClip && clientPlayerEntity.isCreative()); return clientPlayerEntity.isSpectator() || (CarpetSettings.creativeNoClip && clientPlayerEntity.isCreative());
@@ -1,24 +1,24 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.client.renderer.fog.environment.AtmosphericFogEnvironment;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.world.attribute.EnvironmentAttribute;
//import net.minecraft.world.dimension.Dimension; import net.minecraft.world.attribute.EnvironmentAttributeProbe;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = LevelRenderer.class, priority = 69420) @Mixin(value = AtmosphericFogEnvironment.class, priority = 69420)
public class LevelRenderer_fogOffMixin public class LevelRenderer_fogOffMixin
{ {
@Redirect(method = "renderLevel", require = 0, expect = 0, at = @At( @Redirect(method = "setupFog", require = 0, expect = 0, at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/client/renderer/DimensionSpecialEffects;isFoggyAt(II)Z" target = "Lnet/minecraft/world/attribute/EnvironmentAttributeProbe;getValue(Lnet/minecraft/world/attribute/EnvironmentAttribute;F)Ljava/lang/Object;"
)) ))
private boolean isReallyThick(DimensionSpecialEffects skyProperties, int x, int z) private <Value> Value isReallyThick(EnvironmentAttributeProbe instance, EnvironmentAttribute<Value> environmentAttribute, float f)
{ {
if (CarpetSettings.fogOff) return false; if (CarpetSettings.fogOff) return environmentAttribute.defaultValue();
return skyProperties.isFoggyAt(x, z); return instance.getValue(environmentAttribute, f);
} }
} }
@@ -2,18 +2,35 @@ package carpet.mixins;
import carpet.network.CarpetClient; import carpet.network.CarpetClient;
import carpet.script.utils.ShapesRenderer; import carpet.script.utils.ShapesRenderer;
import com.mojang.blaze3d.vertex.PoseStack; import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.Camera; import com.mojang.blaze3d.buffers.GpuBufferSlice;
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
import com.mojang.blaze3d.framegraph.FramePass;
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import net.minecraft.client.DeltaTracker; import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.ShaderManager;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.SubmitNodeStorage;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import org.joml.Matrix4f; import net.minecraft.client.renderer.feature.FeatureRenderDispatcher;
import net.minecraft.client.renderer.state.GameRenderState;
import net.minecraft.client.renderer.state.level.CameraRenderState;
import net.minecraft.client.renderer.state.level.LevelRenderState;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.sprite.AtlasManager;
import org.joml.Matrix4fc;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -21,30 +38,45 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LevelRenderer.class) @Mixin(LevelRenderer.class)
public class LevelRenderer_scarpetRenderMixin public class LevelRenderer_scarpetRenderMixin
{ {
@Shadow @Final private LevelTargetBundle targets;
@Shadow @Final private FeatureRenderDispatcher featureRenderDispatcher;
@Shadow @Final private RenderBuffers renderBuffers;
@Shadow @Final private LevelRenderState levelRenderState;
@Shadow @Final private SubmitNodeStorage submitNodeStorage;
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
private void addRenderers(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) private void addRenderers(EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, ModelManager modelManager, TextureManager textureManager, AtlasManager atlasManager, ShaderManager shaderManager, GameRenderer gameRenderer, int width, int height, CallbackInfo ci)
{ {
CarpetClient.shapes = new ShapesRenderer(minecraft); CarpetClient.shapes = new ShapesRenderer(Minecraft.getInstance());
} }
@Inject(method = "renderLevel", at = @At( @Inject(method = "render", at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Sheets;translucentCullBlockSheet()Lnet/minecraft/client/renderer/RenderType;", shift = At.Shift.BEFORE target = "Lnet/minecraft/client/renderer/LevelRenderer;addMainPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher$PreparedFrame;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lnet/minecraft/client/renderer/state/level/LevelRenderState;Lnet/minecraft/util/profiling/ProfilerFiller;Lnet/minecraft/client/renderer/chunk/ChunkSectionsToRender;)V",
//target = "Lnet/minecraft/client/render/RenderLayer;getWaterMask()Lnet/minecraft/client/render/RenderLayer;", shift = At.Shift.AFTER //target = "Lnet/minecraft/client/renderer/LevelRenderer;addAlwaysOnTopPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;)V",
//target = "Lnet/minecraft/client/render/BufferBuilderStorage;getEffectVertexConsumers()Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;", shift = At.Shift.BEFORE //target = "Lnet/minecraft/client/renderer/LevelRenderer;submitFeatures(Lnet/minecraft/client/renderer/state/level/LevelRenderState;Lnet/minecraft/client/renderer/SubmitNodeCollector;Z)V",
//target = "Lnet/minecraft/client/render/WorldRenderer;renderChunkDebugInfo(Lnet/minecraft/client/render/Camera;)V", shift = At.Shift.AFTER //target = "Lnet/minecraft/client/renderer/LevelRenderer;addMainPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lnet/minecraft/client/renderer/state/level/LevelRenderState;Lnet/minecraft/util/profiling/ProfilerFiller;Lnet/minecraft/client/renderer/chunk/ChunkSectionsToRender;)V",
//target = "Lnet/minecraft/client/render/BackgroundRenderer;method_23792()V", shift = At.Shift.AFTER //target = "Lnet/minecraft/client/renderer/LevelRenderer;addLateDebugPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/state/level/CameraRenderState;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Matrix4fc;)V",
//target = "Lnet/minecraft/client/render/BufferBuilderStorage;getEntityVertexConsumers()Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;", shift = At.Shift.AFTER 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) private void renderScarpetThingsLate(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, @Local FrameGraphBuilder frameGraphBuilder)
//private void renderScarpetThinsLate(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, @Local FrameGraphBuilder frameGraphBuilder)
{ {
// in normal circumstances we want to render shapes at the very end so it appears correctly behind stuff. // 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. // we might actually not need to play with render hooks here.
//if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null ) //if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null )
if (CarpetClient.shapes != null) if (CarpetClient.shapes != null)
{ {
CarpetClient.shapes.render(modelViewMatrix, camera, deltaTracker.getGameTimeDeltaPartialTick(false)); final float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(false);
FramePass pass = frameGraphBuilder.addPass("scarpet_shapes");
targets.main = pass.readsAndWrites(targets.main);
pass.executes(() -> CarpetClient.shapes.render(submitNodeStorage, levelRenderState, modelViewMatrix, deltaPartialTick));
//featureRenderDispatcher.renderAllFeatures(submitNodeStorage);
//renderBuffers.bufferSource().uploadAndDraw();
} }
} }
} }
@@ -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 @Redirect(method = "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;II)Z", at = @At( //setBlockState main
value = "INVOKE", 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) 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);
} }
} }
@@ -2,6 +2,7 @@ package carpet.mixins;
import carpet.fakes.LevelInterface; import carpet.fakes.LevelInterface;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.minecraft.util.profiling.Profiler;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -9,9 +10,8 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.LevelEntityGetter; import net.minecraft.world.level.entity.LevelEntityGetter;
@@ -24,7 +24,7 @@ public abstract class Level_getOtherEntitiesLimited implements LevelInterface {
@Override @Override
public List<Entity> getOtherEntitiesLimited(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate, int limit) { public List<Entity> getOtherEntitiesLimited(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate, int limit) {
this.getProfiler().incrementCounter("getEntities"); // visit Profiler.get().incrementCounter("getEntities"); // visit
AtomicInteger checkedEntities = new AtomicInteger(); AtomicInteger checkedEntities = new AtomicInteger();
List<Entity> list = Lists.newArrayList(); List<Entity> list = Lists.newArrayList();
try { try {
@@ -55,9 +55,6 @@ public abstract class Level_getOtherEntitiesLimited implements LevelInterface {
return list; return list;
} }
@Shadow
public abstract ProfilerFiller getProfiler();
@Shadow @Shadow
protected abstract LevelEntityGetter<Entity> getEntities(); protected abstract LevelEntityGetter<Entity> getEntities();
} }
@@ -4,8 +4,8 @@ import carpet.fakes.WorldChunkInterface;
import carpet.fakes.LevelInterface; import carpet.fakes.LevelInterface;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.util.profiling.Profiler;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -28,32 +28,18 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces
@Shadow @Shadow
public abstract LevelChunk getChunkAt(BlockPos blockPos_1); public abstract LevelChunk getChunkAt(BlockPos blockPos_1);
@Shadow
public abstract BlockState getBlockState(BlockPos blockPos_1);
//@Shadow
//public abstract ChunkManager getChunkManager();
@Shadow @Shadow
public abstract void setBlocksDirty(BlockPos blockPos_1, BlockState s1, BlockState s2); public abstract void setBlocksDirty(BlockPos blockPos_1, BlockState s1, BlockState s2);
@Shadow @Shadow
public abstract void sendBlockUpdated(BlockPos var1, BlockState var2, BlockState var3, int var4); 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 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 boolean isDebug();
@Shadow public abstract void updatePOIOnBlockStateChange(final BlockPos blockPos, final BlockState blockState, final BlockState blockState2);
/** /**
* @author 2No2Name * @author 2No2Name
*/ */
@@ -67,7 +53,7 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces
BlockState blockState_2; BlockState blockState_2;
if (newBlockEntity != null && block_1 instanceof EntityBlock) 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) if (newBlockEntity instanceof LidBlockEntity)
{ {
scheduleTick(blockPos_1, block_1, 5); scheduleTick(blockPos_1, block_1, 5);
@@ -75,24 +61,15 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces
} }
else 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) if (blockState_2 == null)
{ {
return false; return false;
} }
else
{
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())) BlockState blockState_3 = this.getBlockState(blockPos_1);
{
ProfilerFiller profiler = getProfiler();
profiler.push("queueCheckLight");
this.getChunkSource().getLightEngine().checkBlock(blockPos_1);
profiler.pop();
}
if (blockState_3 == blockState_1) if (blockState_3 == blockState_1)
{ {
@@ -122,9 +99,8 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces
blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours
blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare
} }
this.onBlockStateChange(blockPos_1, blockState_2, blockState_3); updatePOIOnBlockStateChange(blockPos_1, blockState_2, blockState_3);
} }
return true; return true;
} }
}
} }
@@ -2,7 +2,7 @@ package carpet.mixins;
import carpet.fakes.LevelInterface; import carpet.fakes.LevelInterface;
import carpet.utils.CarpetProfiler; import carpet.utils.CarpetProfiler;
import net.minecraft.world.level.redstone.NeighborUpdater; import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -22,7 +22,7 @@ import net.minecraft.world.level.Level;
public abstract class Level_tickMixin implements LevelInterface public abstract class Level_tickMixin implements LevelInterface
{ {
@Shadow @Final public boolean isClientSide; @Shadow @Final public boolean isClientSide;
@Shadow @Final protected NeighborUpdater neighborUpdater; @Shadow @Final protected CollectingNeighborUpdater neighborUpdater;
CarpetProfiler.ProfilerToken currentSection; CarpetProfiler.ProfilerToken currentSection;
CarpetProfiler.ProfilerToken entitySection; CarpetProfiler.ProfilerToken entitySection;
@@ -30,7 +30,7 @@ public abstract class Level_tickMixin implements LevelInterface
@Override @Override
@Unique @Unique
public NeighborUpdater getNeighborUpdater() { public CollectingNeighborUpdater getNeighborUpdater() {
return this.neighborUpdater; return this.neighborUpdater;
} }
Loaded 100 of 264 files, more files were not shown because too many files have changed in this diff. Show more