Compare commits

...
15 changed files with 523 additions and 205 deletions

No files matched your search

+1
View File
@@ -585,6 +585,7 @@ public net.minecraft.world.level.block.entity.LecternBlockEntity bookAccess
public net.minecraft.world.level.block.entity.LecternBlockEntity setPage(I)V
public net.minecraft.world.level.block.entity.SculkCatalystBlockEntity$CatalystListener bloom(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/util/RandomSource;)V
public net.minecraft.world.level.block.entity.SculkShriekerBlockEntity warningLevel
public net.minecraft.world.level.block.entity.SignBlockEntity allowOpFeatures
public net.minecraft.world.level.block.entity.SkullBlockEntity customName
public net.minecraft.world.level.block.entity.SkullBlockEntity noteBlockSound
public net.minecraft.world.level.block.entity.SkullBlockEntity owner
@@ -1,27 +1,34 @@
package org.bukkit.block;
import io.papermc.paper.math.Position;
import java.util.List;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import org.bukkit.DyeColor;
import org.bukkit.block.sign.Side;
import org.bukkit.block.sign.SignSide;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.material.Colorable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a captured state of either a SignPost or a WallSign.
*/
@NullMarked
public interface Sign extends TileState, Colorable {
// Paper start
/**
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
*
* @return List of components containing each line of text
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
*/
@NotNull
@Deprecated
public java.util.List<net.kyori.adventure.text.Component> lines();
@Deprecated(since = "1.20")
default List<Component> lines() {
return this.getSide(Side.FRONT).lines();
}
/**
* Gets the line of text at the specified index on the {@link Side#FRONT}.
@@ -29,13 +36,14 @@ public interface Sign extends TileState, Colorable {
* For example, getLine(0) will return the first line of text.
*
* @param index Line number to get the text from, starting at 0
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @return Text on the given line
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
*/
@NotNull
@Deprecated
public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException;
@Deprecated(since = "1.20")
default Component line(int index) throws IndexOutOfBoundsException {
return this.getSide(Side.FRONT).line(index);
}
/**
* Sets the line of text at the specified index on the {@link Side#FRONT}.
@@ -44,23 +52,25 @@ public interface Sign extends TileState, Colorable {
* "Line One".
*
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, Component)}.
*/
@Deprecated
public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException;
// Paper end
@Deprecated(since = "1.20")
default void line(int index, Component line) throws IndexOutOfBoundsException {
this.getSide(Side.FRONT).line(index, line);
}
/**
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
*
* @return Array of Strings containing each line of text
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
*/
@Deprecated(since = "1.20")
@NotNull
public String[] getLines();
default String[] getLines() {
return this.getSide(Side.FRONT).getLines();
}
/**
* Gets the line of text at the specified index.
@@ -73,8 +83,9 @@ public interface Sign extends TileState, Colorable {
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
*/
@Deprecated(since = "1.20")
@NotNull
public String getLine(int index) throws IndexOutOfBoundsException;
default String getLine(int index) throws IndexOutOfBoundsException {
return this.getSide(Side.FRONT).getLine(index);
}
/**
* Sets the line of text at the specified index.
@@ -83,12 +94,14 @@ public interface Sign extends TileState, Colorable {
* "Line One".
*
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
*/
@Deprecated(since = "1.20")
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
default void setLine(int index, String line) throws IndexOutOfBoundsException {
this.getSide(Side.FRONT).setLine(index, line);
}
/**
* Marks whether this sign can be edited by players.
@@ -97,7 +110,9 @@ public interface Sign extends TileState, Colorable {
* @deprecated use {@link #isWaxed()} instead
*/
@Deprecated(since = "1.20.1")
public boolean isEditable();
default boolean isEditable() {
return !this.isWaxed();
}
/**
* Marks whether this sign can be edited by players.
@@ -106,7 +121,9 @@ public interface Sign extends TileState, Colorable {
* @deprecated use {@link #setWaxed(boolean)} instead
*/
@Deprecated(since = "1.20.1")
public void setEditable(boolean editable);
default void setEditable(boolean editable) {
this.setWaxed(!editable);
}
/**
* Gets whether or not this sign has been waxed. If a sign has been waxed, it
@@ -114,7 +131,7 @@ public interface Sign extends TileState, Colorable {
*
* @return if this sign is waxed
*/
public boolean isWaxed();
boolean isWaxed();
/**
* Sets whether or not this sign has been waxed. If a sign has been waxed, it
@@ -122,7 +139,7 @@ public interface Sign extends TileState, Colorable {
*
* @param waxed if this sign is waxed
*/
public void setWaxed(boolean waxed);
void setWaxed(boolean waxed);
/**
* Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
@@ -131,7 +148,9 @@ public interface Sign extends TileState, Colorable {
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#isGlowingText()}.
*/
@Deprecated(since = "1.20")
public boolean isGlowingText();
default boolean isGlowingText() {
return this.getSide(Side.FRONT).isGlowingText();
}
/**
* Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
@@ -140,17 +159,20 @@ public interface Sign extends TileState, Colorable {
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setGlowingText(boolean)}.
*/
@Deprecated(since = "1.20")
public void setGlowingText(boolean glowing);
default void setGlowingText(boolean glowing) {
this.getSide(Side.FRONT).setGlowingText(glowing);
}
/**
* {@inheritDoc}
*
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#getColor()}.
*/
@NotNull
@Override
@Deprecated(since = "1.20")
public DyeColor getColor();
default @Nullable DyeColor getColor() {
return this.getSide(Side.FRONT).getColor();
}
/**
* {@inheritDoc}
@@ -159,7 +181,9 @@ public interface Sign extends TileState, Colorable {
*/
@Override
@Deprecated(since = "1.20")
public void setColor(@NotNull DyeColor color);
default void setColor(DyeColor color) {
this.getSide(Side.FRONT).setColor(color);
}
/**
* Return the side of the sign.
@@ -167,8 +191,7 @@ public interface Sign extends TileState, Colorable {
* @param side the side of the sign
* @return the selected side of the sign
*/
@NotNull
public SignSide getSide(@NotNull Side side);
SignSide getSide(Side side);
/**
* Gets the side of this sign the given player is currently standing on.
@@ -176,8 +199,7 @@ public interface Sign extends TileState, Colorable {
* @param player the player
* @return the side the player is standing on
*/
@NotNull
public SignSide getTargetSide(@NotNull Player player);
SignSide getTargetSide(Player player);
/**
* Gets the player that is currently allowed to edit this sign. <br>
@@ -187,16 +209,15 @@ public interface Sign extends TileState, Colorable {
*
* @return the player allowed to edit this sign, or null
*/
@Nullable
public Player getAllowedEditor();
// Paper start - More Sign Block API
@Nullable Player getAllowedEditor();
/**
* Gets the allowed editor's UUID.
* <br>Edits from other players will be rejected if this value is not null.
*
* @return the allowed editor's UUID, or null
*/
@Nullable java.util.UUID getAllowedEditorUniqueId();
@Nullable UUID getAllowedEditorUniqueId();
/**
* Sets the allowed editor's UUID.
@@ -205,7 +226,7 @@ public interface Sign extends TileState, Colorable {
*
* @param uuid the allowed editor's UUID
*/
void setAllowedEditorUniqueId(@Nullable java.util.UUID uuid);
void setAllowedEditorUniqueId(@Nullable UUID uuid);
/**
* Compute the side facing the specified entity.
@@ -213,7 +234,7 @@ public interface Sign extends TileState, Colorable {
* @param entity the entity
* @return the side it is facing
*/
default @NotNull Side getInteractableSideFor(org.bukkit.entity.@NotNull Entity entity) {
default Side getInteractableSideFor(final Entity entity) {
return this.getInteractableSideFor(entity.getLocation());
}
@@ -223,7 +244,7 @@ public interface Sign extends TileState, Colorable {
* @param position the position
* @return the side the position is facing
*/
default @NotNull Side getInteractableSideFor(io.papermc.paper.math.@NotNull Position position) {
default Side getInteractableSideFor(final Position position) {
return this.getInteractableSideFor(position.x(), position.z());
}
@@ -234,6 +255,20 @@ public interface Sign extends TileState, Colorable {
* @param z the z coord
* @return the side the coordinates are facing
*/
@NotNull Side getInteractableSideFor(double x, double z);
// Paper end - More Sign Block API
Side getInteractableSideFor(double x, double z);
/**
* Gets whether operator features are allowed on this sign.
* When enabled, supported click events in the root component of each line are executed when the relevant side is used.
*
* @return if operator features are allowed
*/
boolean isOperatorFeaturesAllowed();
/**
* Sets whether operator features are allowed on this sign.
*
* @param allowed whether operator features are allowed
*/
void setOperatorFeaturesAllowed(boolean allowed);
}
+1 -1
View File
@@ -14,7 +14,7 @@ plugins {
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies {
mache("io.papermc:mache:26.3+build.1")
mache("io.papermc:mache:26.3+build.2")
paperclip("io.papermc:paperclip:3.0.4")
}
@@ -34050,10 +34050,10 @@ index 0000000000000000000000000000000000000000..863a9785c84af6e0c961ae32f0102b5d
+ }
+}
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
index 7050fd6efb6fec16ba5657e254c54de1c671c9a0..aa14dd369d5d2c5c843839f289afdc39c200f0c3 100644
index 130615b796d9568c8fc6db0cc838784f21976411..e8043e52b64ed565128bb18240694ad078911eed 100644
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -216,6 +216,11 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@@ -227,6 +227,11 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@Override
public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
final int fromVersion, final int toVersion) {
@@ -34065,7 +34065,7 @@ index 7050fd6efb6fec16ba5657e254c54de1c671c9a0..aa14dd369d5d2c5c843839f289afdc39
return (CompoundTag)dataFixer.update(
type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
).getValue();
@@ -257,4 +262,4 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@@ -268,4 +273,4 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
public boolean addTicketForEnderPearls(final ServerLevel world) {
return !world.paperConfig().misc.legacyEnderPearlBehavior;
}
@@ -300,10 +300,10 @@ index 0000000000000000000000000000000000000000..fff7a796a61542213bdaa417d44e25cd
+ }
+}
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
index aa14dd369d5d2c5c843839f289afdc39c200f0c3..76f990f150f040b1ad6d7d5b91cfb34ebd6f436a 100644
index e8043e52b64ed565128bb18240694ad078911eed..26e252d229dd1a63afa70b41299bc92fc367afdf 100644
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -13,6 +13,7 @@ import net.minecraft.server.level.ChunkHolder;
@@ -14,6 +14,7 @@ import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -311,7 +311,7 @@ index aa14dd369d5d2c5c843839f289afdc39c200f0c3..76f990f150f040b1ad6d7d5b91cfb34e
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart;
import net.minecraft.world.level.BlockGetter;
@@ -150,7 +151,15 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@@ -156,7 +157,15 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@Override
public long[] getCounterTypesUncached(final net.minecraft.server.level.TicketType type) {
@@ -328,7 +328,7 @@ index aa14dd369d5d2c5c843839f289afdc39c200f0c3..76f990f150f040b1ad6d7d5b91cfb34e
}
@Override
@@ -249,7 +258,7 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@@ -260,7 +269,7 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
@Override
public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
try (final net.minecraft.util.ProblemReporter.ScopedCollector scopedCollector = new net.minecraft.util.ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) {
@@ -876,10 +876,10 @@ index 0000000000000000000000000000000000000000..5916388854ba79ea1261f071c0712e0a
+}
diff --git a/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/PropertyAccess.java b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/PropertyAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..89e75b454695e174c5619104eeb15eb923a2d9a7
index 0000000000000000000000000000000000000000..ad0ef11297ff8875dd08e81a8376b37d81b0a20d
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/PropertyAccess.java
@@ -0,0 +1,12 @@
@@ -0,0 +1,14 @@
+package ca.spottedleaf.moonrise.patches.blockstate_propertyaccess;
+
+public interface PropertyAccess<T> {
@@ -891,6 +891,8 @@ index 0000000000000000000000000000000000000000..89e75b454695e174c5619104eeb15eb9
+ public T moonrise$getById(final int id);
+
+ public void moonrise$setById(final T[] values);
+
+ public void moonrise$ensureById();
+}
diff --git a/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/PropertyAccessStateHolder.java b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/PropertyAccessStateHolder.java
new file mode 100644
@@ -911,10 +913,10 @@ index 0000000000000000000000000000000000000000..5c9f02e82a9ce3511e710d8d00fc03bb
+}
diff --git a/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bb4008f2a09f0acd47dc7fd21c5a6d6f2c294fd
index 0000000000000000000000000000000000000000..fc41e96de69d5bab8ae1cffb24a5f43e4a137161
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java
@@ -0,0 +1,166 @@
@@ -0,0 +1,167 @@
+package ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.util;
+
+import ca.spottedleaf.common.util.IntegerUtil;
@@ -951,6 +953,7 @@ index 0000000000000000000000000000000000000000..6bb4008f2a09f0acd47dc7fd21c5a6d6
+
+ int currentMultiple = 1;
+ for (final Property<?> property : sortedProperties) {
+ ((PropertyAccess<?>)property).moonrise$ensureById();
+ final int totalValues = property.getPossibleValues().size();
+
+ this.propertyToIndexer.put(
@@ -1425,18 +1428,21 @@ index 0000000000000000000000000000000000000000..b9b8b4cef442b2788770957c7ecb169c
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_gen/noise/NoiseGradients.java b/ca/spottedleaf/moonrise/patches/chunk_gen/noise/NoiseGradients.java
new file mode 100644
index 0000000000000000000000000000000000000000..15c0893979c86a1295928e3e5687f8470639ba02
index 0000000000000000000000000000000000000000..66dd1a6844db8bbf0ca6f752e1f53402eaaa929b
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_gen/noise/NoiseGradients.java
@@ -0,0 +1,131 @@
@@ -0,0 +1,134 @@
+package ca.spottedleaf.moonrise.patches.chunk_gen.noise;
+
+import ca.spottedleaf.moonrise.common.util.FMA;
+import net.minecraft.world.level.levelgen.synth.GradientNoise;
+
+public final class NoiseGradients {
+
+ public static final boolean DEBUG_NOISE = false;
+
+ public static final boolean USE_FMA = FMA.isFMASupported();
+
+ public static final int PERM_SHIFT = 8;
+ public static final int PERM_SIZE = 1 << PERM_SHIFT;
+ public static final int PERM_MASK = PERM_SIZE - 1;
@@ -1486,7 +1492,7 @@ index 0000000000000000000000000000000000000000..15c0893979c86a1295928e3e5687f847
+ final float gz = GRADIENTF_FLAT[(hash << 2) + 2];
+ final float gy = GRADIENTF_FLAT[(hash << 2) + 1];
+ final float gx = GRADIENTF_FLAT[(hash << 2) + 0];
+ if (false) {
+ if (USE_FMA) {
+ return Math.fma(gz, z, Math.fma(gy, y, gx * x));
+ } else {
+ return gx * x + gy * y + gz * z;
@@ -1496,7 +1502,7 @@ index 0000000000000000000000000000000000000000..15c0893979c86a1295928e3e5687f847
+ public static float dotXz(final int hash, final float x, final float z) {
+ final float gz = GRADIENTF_FLAT[(hash << 2) + 2];
+ final float gx = GRADIENTF_FLAT[(hash << 2) + 0];
+ if (false) {
+ if (USE_FMA) {
+ return Math.fma(gz, z, gx * x);
+ } else {
+ return gx * x + gz * z;
@@ -1509,14 +1515,14 @@ index 0000000000000000000000000000000000000000..15c0893979c86a1295928e3e5687f847
+
+ public record GradientF(float x, float y, float z) {
+ public float dot(final float x, final float y, final float z) {
+ if (false) {
+ if (USE_FMA) {
+ return Math.fma(this.z, z, Math.fma(this.y, y, this.x * x));
+ } else {
+ return this.x * x + this.y * y + this.z * z;
+ }
+ }
+ public float dotXz(final float x, final float z) {
+ if (false) {
+ if (USE_FMA) {
+ return Math.fma(this.z, z, this.x * x);
+ } else {
+ return this.x * x + this.z * z;
@@ -1542,7 +1548,7 @@ index 0000000000000000000000000000000000000000..15c0893979c86a1295928e3e5687f847
+
+ public record GradientD(double x, double y, double z) {
+ public double dot(final double x, final double y, final double z) {
+ if (false) {
+ if (USE_FMA) {
+ return Math.fma(this.z, z, Math.fma(this.y, y, this.x * x));
+ } else {
+ return this.x * x + this.y * y + this.z * z;
@@ -10460,10 +10466,10 @@ index 0000000000000000000000000000000000000000..7f75cc224d1dea04405f19880b6a1b57
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a0006f9b56d1e43b06f9f7452e1b5bb0ec53e72
index 0000000000000000000000000000000000000000..1dc745d058d605dde0d10dea82c31b3303d670be
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
@@ -0,0 +1,1986 @@
@@ -0,0 +1,1992 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.scheduling;
+
+import ca.spottedleaf.concurrentutil.completable.CallbackCompletable;
@@ -11718,6 +11724,7 @@ index 0000000000000000000000000000000000000000..7a0006f9b56d1e43b06f9f7452e1b5bb
+ this.changeEntityChunkStatus(FullChunkStatus.FULL);
+ PlatformHooks.get().onChunkBorder(chunk, this.vanillaChunkHolder);
+ this.onFullChunkLoadChange(true, changedFullStatus);
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.INACCESSIBLE, FullChunkStatus.FULL);
+ this.completeFullStatusConsumers(FullChunkStatus.FULL, chunk);
+ }
+
@@ -11725,6 +11732,7 @@ index 0000000000000000000000000000000000000000..7a0006f9b56d1e43b06f9f7452e1b5bb
+ this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
+ this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
+ PlatformHooks.get().onChunkTicking(chunk, this.vanillaChunkHolder);
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.FULL, FullChunkStatus.BLOCK_TICKING);
+ this.completeFullStatusConsumers(FullChunkStatus.BLOCK_TICKING, chunk);
+ }
+
@@ -11732,22 +11740,26 @@ index 0000000000000000000000000000000000000000..7a0006f9b56d1e43b06f9f7452e1b5bb
+ this.updateCurrentState(FullChunkStatus.ENTITY_TICKING);
+ this.changeEntityChunkStatus(FullChunkStatus.ENTITY_TICKING);
+ PlatformHooks.get().onChunkEntityTicking(chunk, this.vanillaChunkHolder);
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.BLOCK_TICKING, FullChunkStatus.ENTITY_TICKING);
+ this.completeFullStatusConsumers(FullChunkStatus.ENTITY_TICKING, chunk);
+ }
+ } else {
+ if (current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && !pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.ENTITY_TICKING, FullChunkStatus.BLOCK_TICKING);
+ this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
+ PlatformHooks.get().onChunkNotEntityTicking(chunk, this.vanillaChunkHolder);
+ this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
+ }
+
+ if (current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && !pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.BLOCK_TICKING, FullChunkStatus.FULL);
+ this.changeEntityChunkStatus(FullChunkStatus.FULL);
+ PlatformHooks.get().onChunkNotTicking(chunk, this.vanillaChunkHolder);
+ this.updateCurrentState(FullChunkStatus.FULL);
+ }
+
+ if (current.isOrAfter(FullChunkStatus.FULL) && !pending.isOrAfter(FullChunkStatus.FULL)) {
+ PlatformHooks.get().onFullChunkStatusChange(chunk, FullChunkStatus.FULL, FullChunkStatus.INACCESSIBLE);
+ this.onFullChunkLoadChange(false, changedFullStatus);
+ this.changeEntityChunkStatus(FullChunkStatus.INACCESSIBLE);
+ PlatformHooks.get().onChunkNotBorder(chunk, this.vanillaChunkHolder);
@@ -32059,7 +32071,7 @@ index e3644ac93ffc2cfdc5e788456e9d54a9975272f3..6111ecdfaac7c003859040d49d91cc74
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 5fb9ac4b0fdd245207c15677795566c81b629a20..5c7b5a4e78457b691bae727844d63212949e7cf6 100644
index 5fb9ac4b0fdd245207c15677795566c81b629a20..02ddc534e534311c9f9b752007b30f16ff69a740 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -166,7 +166,7 @@ public abstract class Entity
@@ -32384,7 +32396,7 @@ index 5fb9ac4b0fdd245207c15677795566c81b629a20..5c7b5a4e78457b691bae727844d63212
+
+ final double stepHeight;
+
+ if ((!collidedDownwards && !this.onGround) || (!collidedX && !collidedZ) || (stepHeight = (double)this.maxUpStep()) <= 0.0) {
+ if ((!collidedDownwards && !this.onGround()) || (!collidedX && !collidedZ) || (stepHeight = (double)this.maxUpStep()) <= 0.0) {
+ return collided;
+ }
+
@@ -32606,7 +32618,7 @@ index 5fb9ac4b0fdd245207c15677795566c81b629a20..5c7b5a4e78457b691bae727844d63212
@Override
diff --git a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
index 81ad9099d2325a07b0b853b99e1d67b0caebd951..e2eb02d8a0a9481be2308c9052582591bc4f9850 100644
index 81ad9099d2325a07b0b853b99e1d67b0caebd951..019a5cbef59465147cbc59e2b8580624cac379e8 100644
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -94,12 +94,16 @@ public class AcquirePoi {
@@ -32621,7 +32633,7 @@ index 81ad9099d2325a07b0b853b99e1d67b0caebd951..e2eb02d8a0a9481be2308c9052582591
- .collect(Collectors.toSet());
+ // Paper start - optimise POI searches
+ java.util.List<Pair<Holder<PoiType>, BlockPos>> poiPositionsRaw = new java.util.ArrayList<>();
+ ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), SCAN_RANGE, Double.MAX_VALUE, PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw);
+ ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), SCAN_RANGE, (double)((long)SCAN_RANGE * (long)SCAN_RANGE), PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw);
+ Set<Pair<Holder<PoiType>, BlockPos>> poiPositions = new java.util.HashSet<>(poiPositionsRaw.size());
+ for (Pair<Holder<PoiType>, BlockPos> pair : poiPositionsRaw) {
+ if (validPoi.test(level, pair.getSecond())) {
@@ -33213,7 +33225,7 @@ index 892b338a2b0a185511c352ca2bb76ee3890836fd..cc938f43c4a5e947ed87ca2001cbaca4
// Paper start - Affects Spawning API
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index f83bfcaca787e74125763cb893b9c162031463ad..a828576457e0bb932750dba507bdef7e8903e144 100644
index f83bfcaca787e74125763cb893b9c162031463ad..c356736c779fc20b6a77ddd442b71b6ecb9745c2 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -85,6 +85,7 @@ import net.minecraft.world.level.storage.LevelData;
@@ -33264,7 +33276,7 @@ index f83bfcaca787e74125763cb893b9c162031463ad..a828576457e0bb932750dba507bdef7e
+ }
+
+ @Override
+ public final <T extends Entity> List<T> getEntitiesOfClass(final Class<T> entityClass, final AABB boundingBox, final Predicate<? super T> predicate) {
+ public <T extends Entity> List<T> getEntitiesOfClass(final Class<T> entityClass, final AABB boundingBox, final Predicate<? super T> predicate) {
+ Profiler.get().incrementCounter("getEntities");
+ final List<T> ret = new java.util.ArrayList<>();
+
@@ -35679,7 +35691,7 @@ index 1338213c0c918301a8fbc232b25d55804bda9cf9..8e89405ed73e68b641fd8a47963c60a1
@Override
diff --git a/net/minecraft/world/level/block/state/properties/Property.java b/net/minecraft/world/level/block/state/properties/Property.java
index b95665559d646ab8de313a19dadc197a1e8be02c..b82b935272efbc7a7518e148f665f4f24fa96814 100644
index b95665559d646ab8de313a19dadc197a1e8be02c..5d249a6197c4b18bf92e180fb318636e5ae5d203 100644
--- a/net/minecraft/world/level/block/state/properties/Property.java
+++ b/net/minecraft/world/level/block/state/properties/Property.java
@@ -10,7 +10,7 @@ import java.util.stream.Stream;
@@ -35691,7 +35703,7 @@ index b95665559d646ab8de313a19dadc197a1e8be02c..b82b935272efbc7a7518e148f665f4f2
private final Class<T> clazz;
private final String name;
private @Nullable Integer hashCode;
@@ -23,9 +23,38 @@ public abstract class Property<T extends Comparable<T>> {
@@ -23,9 +23,66 @@ public abstract class Property<T extends Comparable<T>> {
);
private final Codec<Property.Value<T>> valueCodec = this.codec.xmap(this::value, Property.Value::value);
@@ -35699,6 +35711,7 @@ index b95665559d646ab8de313a19dadc197a1e8be02c..b82b935272efbc7a7518e148f665f4f2
+ private static final java.util.concurrent.atomic.AtomicInteger ID_GENERATOR = new java.util.concurrent.atomic.AtomicInteger();
+ private final int id;
+ private T[] byId;
+ private volatile boolean byIdInitialised;
+
+ @Override
+ public final int moonrise$getId() {
@@ -35717,10 +35730,37 @@ index b95665559d646ab8de313a19dadc197a1e8be02c..b82b935272efbc7a7518e148f665f4f2
+ throw new IllegalStateException();
+ }
+ this.byId = byId;
+ this.byIdInitialised = true;
+ }
+
+ @Override
+ public abstract int moonrise$getIdFor(final T value);
+ public final void moonrise$ensureById() {
+ if (this.byIdInitialised) {
+ return;
+ }
+ // properties without a specialised implementation (i.e. custom Property subclasses) build their table here,
+ // as subclass fields are not yet initialised when the Property constructor returns
+ synchronized (this) {
+ if (this.byIdInitialised) {
+ return;
+ }
+ final List<T> values = this.getPossibleValues();
+ final T[] byId = (T[])values.toArray(new Comparable[0]);
+ for (int i = 0; i < byId.length; ++i) {
+ final int id = this.moonrise$getIdFor(byId[i]);
+ if (id != i) {
+ throw new IllegalStateException("Property " + this + " returned internal index " + id + " for value " + byId[i] + ", expected " + i);
+ }
+ }
+ this.moonrise$setById(byId);
+ }
+ }
+
+ @Override
+ public int moonrise$getIdFor(final T value) {
+ // fallback for properties without a specialised implementation (i.e. custom Property subclasses)
+ return this.getInternalIndex(value);
+ }
+ // Paper end - optimise blockstate property access
+
protected Property(final String name, final Class<T> clazz) {
@@ -35978,7 +36018,7 @@ index 12882e7448ff9b7febdb8475e6e14e87d23d87ae..9e66f6202439cc7780af1016289f3b08
public static ProblemReporter.PathElement problemPath(final ChunkPos pos) {
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
index 3061b7335af71453dd75ee98539cc7535df747ae..cc4800823c20e8ecbf0b4d74fd85a22bcb70c74c 100644
index 3061b7335af71453dd75ee98539cc7535df747ae..221657b7387f4ab0a1862127c90499f97bcc2276 100644
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -130,11 +130,14 @@ public abstract class ChunkGenerator {
@@ -36041,6 +36081,105 @@ index 3061b7335af71453dd75ee98539cc7535df747ae..cc4800823c20e8ecbf0b4d74fd85a22b
}
});
possibleBiomes.retainAll(this.biomeSource.possibleBiomes());
@@ -480,7 +499,98 @@ public abstract class ChunkGenerator {
throw new ReportedException(report);
}
}
+ this.fixSnow(level, chunk); // Paper - fix MC-119599
}
+
+ // Paper start - fix MC-119599
+ private static final int FEATURES_RADIUS = 1;
+
+ private void fixSnow(final WorldGenLevel level, final ChunkAccess center) {
+ final ChunkPos centerPos = center.getPos();
+ if (SharedConstants.debugVoidTerrain(centerPos)) {
+ return;
+ }
+ if (!ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC119599(level.getLevel())) {
+ return;
+ }
+
+ final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
+
+ final int cx = centerPos.x();
+ final int cz = centerPos.z();
+
+ // Biome lookups use the same zoom as Vanilla's level.getBiome, which reads noise biomes up to one chunk
+ // outside the chunk being processed, so up to 2 chunks from the center. The region only allows status
+ // checked access to its direct dependencies (TERRAIN within radius 1), so read the cached chunks directly:
+ // FEATURES requires TERRAIN at radius 1, which requires BIOMES at radius 1, so every chunk within
+ // radius 2 has completed BIOMES.
+ final BiomeManager biomeManager = new BiomeManager((final int quartX, final int quartY, final int quartZ) -> {
+ final int chunkX = QuartPos.toSection(quartX);
+ final int chunkZ = QuartPos.toSection(quartZ);
+ if (Math.max(Math.abs(chunkX - cx), Math.abs(chunkZ - cz)) > (FEATURES_RADIUS + 1)) {
+ throw new IllegalStateException("Biome lookup at chunk (" + chunkX + "," + chunkZ + ") is outside radius " + (FEATURES_RADIUS + 1) + " of (" + cx + "," + cz + ")");
+ }
+ return level.getChunk(chunkX, chunkZ).getNoiseBiome(quartX, quartY, quartZ);
+ }, BiomeManager.obfuscateSeed(level.getSeed()));
+ for (int dz = -FEATURES_RADIUS; dz <= FEATURES_RADIUS; ++dz) {
+ for (int dx = -FEATURES_RADIUS; dx <= FEATURES_RADIUS; ++dx) {
+ final int chunkX = dx + cx;
+ final int chunkZ = dz + cz;
+ final ChunkAccess chunk = level.getChunk(chunkX, chunkZ);
+
+ if (!(chunk instanceof ProtoChunk protoChunk) || (protoChunk instanceof ImposterProtoChunk || protoChunk.isUpgrading())
+ || ((dx != 0 || dz != 0) && protoChunk.getPersistedStatus().isBefore(ChunkStatus.FEATURES))) {
+ continue;
+ }
+
+ final int seaLevel = level.getSeaLevel();
+ final net.minecraft.world.level.block.state.BlockState defaultSnowBlock = net.minecraft.world.level.block.Blocks.SNOW.defaultBlockState();
+ for (int lz = 0; lz < 16; ++lz) {
+ for (int lx = 0; lx < 16; ++lx) {
+ final int blockX = (chunkX << 4) | lx;
+ final int blockZ = (chunkZ << 4) | lz;
+
+ final int heightWithoutLeaves = protoChunk.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockX, blockZ) + 1;
+
+ pos.set(blockX, heightWithoutLeaves, blockZ);
+
+ final Biome biome = biomeManager.getBiome(pos).value();
+
+ if (biome.getPrecipitationAt(pos, seaLevel) != Biome.Precipitation.SNOW) {
+ continue;
+ }
+
+ final int heightWithLeaves = protoChunk.getHeight(Heightmap.Types.MOTION_BLOCKING, blockX, blockZ) + 1;
+
+ boolean first = true;
+ for (int y = heightWithoutLeaves; y <= heightWithLeaves; ++y) {
+ pos.setY(y);
+
+ final net.minecraft.world.level.block.state.BlockState current = protoChunk.getBlockState(pos);
+
+ // note: light is not generated here (TERRAIN), so really it's 0...
+ if (!current.isAir() || !defaultSnowBlock.canSurvive(level, pos)) {
+ continue;
+ }
+
+ level.setBlock(pos, defaultSnowBlock, net.minecraft.world.level.block.Block.UPDATE_CLIENTS);
+
+ if (first) {
+ first = false;
+ pos.setY(y - 1);
+ final net.minecraft.world.level.block.state.BlockState below = protoChunk.getBlockState(pos);
+ if (below.hasProperty(net.minecraft.world.level.block.SnowyBlock.SNOWY)) {
+ level.setBlock(pos, below.setValue(net.minecraft.world.level.block.SnowyBlock.SNOWY, true), net.minecraft.world.level.block.Block.UPDATE_CLIENTS);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Paper end - fix MC-119599
+
// CraftBukkit start
public void applyBiomeDecoration(final WorldGenLevel level, final ChunkAccess chunk, final StructureManager structureManager) {
this.applyBiomeDecoration(level, chunk, structureManager, true);
diff --git a/net/minecraft/world/level/chunk/Configuration.java b/net/minecraft/world/level/chunk/Configuration.java
index 35e8ea13af811742f0e44afe66b53c3a513f210c..2521b46b128f175d82a9c8d8991346180583588b 100644
--- a/net/minecraft/world/level/chunk/Configuration.java
@@ -39465,16 +39604,17 @@ index d7b2a91df8c5c0ce480bc537b3457fcd144162e1..6da4d95f6a5f6043aaea6d62c550cd9f
return this.x * x + this.y * y + this.z * z;
}
diff --git a/net/minecraft/world/level/levelgen/synth/PerlinNoise.java b/net/minecraft/world/level/levelgen/synth/PerlinNoise.java
index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb4c7ee1b3 100644
index ecbd95204e4650b514d341f79c5756430e08e70f..12be06b795343d0f61cd908dd3f62fab70592a81 100644
--- a/net/minecraft/world/level/levelgen/synth/PerlinNoise.java
+++ b/net/minecraft/world/level/levelgen/synth/PerlinNoise.java
@@ -6,13 +6,39 @@ import net.minecraft.util.Mth;
@@ -6,13 +6,40 @@ import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.densityfunction.DensityBuffer;
import net.minecraft.world.level.levelgen.densityfunction.DensityVolume;
+// Paper start - optimise chunk generation
+import ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.DEBUG_NOISE;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.USE_FMA;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_MASK;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_SIZE;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_SHIFT;
@@ -39509,7 +39649,7 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
}
@Override
@@ -52,7 +78,55 @@ public class PerlinNoise extends GradientNoise {
@@ -52,7 +79,55 @@ public class PerlinNoise extends GradientNoise {
return this.sampleWithDerivative(floorX, floorY, floorZ, relativeX, relativeY, relativeZ, derivativeOut);
}
@@ -39566,7 +39706,7 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
final int x, final int y, final int z, final float relativeX, final float relativeY, final float relativeZ, final float originalRelativeY
) {
int x0 = this.permute(x);
@@ -75,8 +149,172 @@ public class PerlinNoise extends GradientNoise {
@@ -75,8 +150,186 @@ public class PerlinNoise extends GradientNoise {
return Mth.lerp3(xAlpha, yAlpha, zAlpha, d000, d100, d010, d110, d001, d101, d011, d111);
}
@@ -39615,7 +39755,7 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
+ for (int x = 0; x < sX; ++x, xv += xi) {
+ final double val = wrap(xv * xzScale) + this.offsetX;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final float relative = (float)(val - floorD);
+ final float alpha = Mth.smoothstep(relative);
+
@@ -39629,7 +39769,7 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
+ for (int y = 0; y < sY; ++y, yv += yi) {
+ final double val = wrap(yv * yScale) + this.offsetY;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final float relative = (float)(val - floorD);
+ final float alpha = Mth.smoothstep(relative);
+
@@ -39643,7 +39783,7 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
+ for (int z = 0; z < sZ; ++z, zv += zi) {
+ final double val = wrap(zv * xzScale) + this.offsetZ;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final float relative = (float)(val - floorD);
+ final float alpha = Mth.smoothstep(relative);
+
@@ -39723,7 +39863,21 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
+ g111y = NoiseGradients.gradY(g111);
+ }
+
+ buffer.values[index++] += (amplitude * Mth.lerp3(alphaX, alphaY, alphaZ, d000xz + g000y * relativeY, d100xz + g100y * relativeY, d010xz + g010y * (relativeY - 1.0F), d110xz + g110y * (relativeY - 1.0F), d001xz + g001y * relativeY, d101xz + g101y * relativeY, d011xz + g011y * (relativeY - 1.0F), d111xz + g111y * (relativeY - 1.0F)));
+ if (USE_FMA) {
+ buffer.values[index++] += amplitude * Mth.lerp3(
+ alphaX, alphaY, alphaZ,
+ Math.fma(g000y, relativeY, d000xz), Math.fma(g100y, relativeY, d100xz), Math.fma(g010y, (relativeY - 1.0F), d010xz),
+ Math.fma(g110y, (relativeY - 1.0F), d110xz), Math.fma(g001y, relativeY, d001xz), Math.fma(g101y, relativeY, d101xz),
+ Math.fma(g011y, (relativeY - 1.0F), d011xz), Math.fma(g111y, (relativeY - 1.0F), d111xz)
+ );
+ } else {
+ buffer.values[index++] += amplitude * Mth.lerp3(
+ alphaX, alphaY, alphaZ,
+ d000xz + g000y * relativeY, d100xz + g100y * relativeY, d010xz + g010y * (relativeY - 1.0F),
+ d110xz + g110y * (relativeY - 1.0F), d001xz + g001y * relativeY, d101xz + g101y * relativeY,
+ d011xz + g011y * (relativeY - 1.0F), d111xz + g111y * (relativeY - 1.0F)
+ );
+ }
+ }
+ }
+ }
@@ -39741,16 +39895,17 @@ index ecbd95204e4650b514d341f79c5756430e08e70f..8e5ba8f7bed5754b6b657db30cba92fb
float d100xz = 0.0F;
float d010xz = 0.0F;
diff --git a/net/minecraft/world/level/levelgen/synth/SmearedPerlinNoise.java b/net/minecraft/world/level/levelgen/synth/SmearedPerlinNoise.java
index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da6551f6ecc08 100644
index 4884b35596ea7ab327f75f0537affab97df492be..e8eafc7063c7563b0e97ec508dd5401efa3d2b31 100644
--- a/net/minecraft/world/level/levelgen/synth/SmearedPerlinNoise.java
+++ b/net/minecraft/world/level/levelgen/synth/SmearedPerlinNoise.java
@@ -5,6 +5,13 @@ import net.minecraft.util.Mth;
@@ -5,6 +5,14 @@ import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.densityfunction.DensityBuffer;
import net.minecraft.world.level.levelgen.densityfunction.DensityVolume;
+// Paper start - optimise chunk generation
+import ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.DEBUG_NOISE;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.USE_FMA;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_MASK;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_SIZE;
+import static ca.spottedleaf.moonrise.patches.chunk_gen.noise.NoiseGradients.PERM_SHIFT;
@@ -39758,7 +39913,7 @@ index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da655
@Deprecated
public class SmearedPerlinNoise extends PerlinNoise {
@@ -51,8 +58,175 @@ public class SmearedPerlinNoise extends PerlinNoise {
@@ -51,8 +59,189 @@ public class SmearedPerlinNoise extends PerlinNoise {
return Mth.floor(fudgeLimit / this.fudgeYScale + 1.0E-7F) * this.fudgeYScale;
}
@@ -39808,7 +39963,7 @@ index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da655
+ for (int x = 0; x < sX; ++x, xv += xi) {
+ final double val = wrap(xv * xzScale) + this.offsetX;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final float relative = (float)(val - floorD);
+ final float alpha = Mth.smoothstep(relative);
+
@@ -39823,7 +39978,7 @@ index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da655
+ final double original = yv * yScale;
+ final double val = wrap(original) + this.offsetY;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final double relative = val - floorD;
+ final float fudgedRelative = (float)(relative - this.computeFudgeY(original, relative));
+ final float alpha = Mth.smoothstep((float)relative);
@@ -39838,7 +39993,7 @@ index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da655
+ for (int z = 0; z < sZ; ++z, zv += zi) {
+ final double val = wrap(zv * xzScale) + this.offsetZ;
+ final double floorD = Math.floor(val);
+ final int floor = (int)floorD;
+ final int floor = (int)(long)floorD;
+ final float relative = (float)(val - floorD);
+ final float alpha = Mth.smoothstep(relative);
+
@@ -39918,7 +40073,21 @@ index 4884b35596ea7ab327f75f0537affab97df492be..64868bdc6554dea2b1b45fbdac8da655
+ g111y = NoiseGradients.gradY(g111);
+ }
+
+ buffer.values[index++] += (amplitude * Mth.lerp3(alphaX, alphaY, alphaZ, d000xz + g000y * relativeY, d100xz + g100y * relativeY, d010xz + g010y * (relativeY - 1.0F), d110xz + g110y * (relativeY - 1.0F), d001xz + g001y * relativeY, d101xz + g101y * relativeY, d011xz + g011y * (relativeY - 1.0F), d111xz + g111y * (relativeY - 1.0F)));
+ if (USE_FMA) {
+ buffer.values[index++] += amplitude * Mth.lerp3(
+ alphaX, alphaY, alphaZ,
+ Math.fma(g000y, relativeY, d000xz), Math.fma(g100y, relativeY, d100xz), Math.fma(g010y, (relativeY - 1.0F), d010xz),
+ Math.fma(g110y, (relativeY - 1.0F), d110xz), Math.fma(g001y, relativeY, d001xz), Math.fma(g101y, relativeY, d101xz),
+ Math.fma(g011y, (relativeY - 1.0F), d011xz), Math.fma(g111y, (relativeY - 1.0F), d111xz)
+ );
+ } else {
+ buffer.values[index++] += amplitude * Mth.lerp3(
+ alphaX, alphaY, alphaZ,
+ d000xz + g000y * relativeY, d100xz + g100y * relativeY, d010xz + g010y * (relativeY - 1.0F),
+ d110xz + g110y * (relativeY - 1.0F), d001xz + g001y * relativeY, d101xz + g101y * relativeY,
+ d011xz + g011y * (relativeY - 1.0F), d111xz + g111y * (relativeY - 1.0F)
+ );
+ }
+ }
+ }
+ }
@@ -522,10 +522,10 @@ index 0de6f540c5192dd152d2e0a55d6b26eee0f5107f..afb2c249078f85579f37a772c41c8138
delta = this.maybeBackOffFromEdge(delta, moverType);
Vec3 movement = this.collide(delta);
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 62ccee5c76303b679d591714e64ee93c1502f378..0ef6c4cefb457c87f4565701817d2f9034dfa0d8 100644
index db627b1d589e2c9d457b2f1b6429ea11849a1d3a..442bdb6b0bea65f4d2527eea43d2205cbaa4107a 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3380,6 +3380,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -3391,6 +3391,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
protected void playAttackSound() {
}
@@ -1,6 +1,6 @@
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -1,0 +_,260 @@
@@ -1,0 +_,271 @@
+package ca.spottedleaf.moonrise.paper;
+
+import ca.spottedleaf.moonrise.common.PlatformHooks;
@@ -13,6 +13,7 @@
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtOps;
+import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.GenerationChunkHolder;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
@@ -88,6 +89,11 @@
+ }
+
+ @Override
+ public void onFullChunkStatusChange(final LevelChunk chunk, final FullChunkStatus from, final FullChunkStatus to) {
+
+ }
+
+ @Override
+ public void chunkSyncSave(final ServerLevel world, final ChunkAccess chunk, final SerializableChunkData data) {
+
+ }
@@ -162,6 +168,11 @@
+ }
+
+ @Override
+ public boolean configFixMC119599(final ServerLevel world) {
+ return world.paperConfig().environment.fixMissingTreeSnow;
+ }
+
+ @Override
+ public boolean configAutoConfigSendDistance() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.autoConfigSendDistance;
+ }
@@ -1222,7 +1222,12 @@
this.player
.swingAndResetAttackStrength(hand, swingAnimation, success.swingSource() != InteractionResult.SwingSource.PREDICTED);
}
@@ -1462,20 +_,24 @@
@@ -1458,24 +_,28 @@
} else if (direction == Direction.DOWN && pos.getY() <= minY) {
this.player.sendBuildLimitMessage(false, minY);
}
- } else if (interactionResult instanceof InteractionResult.Success success && success.shouldSwing()) {
+ } else if (interactionResult instanceof InteractionResult.Success success && success.shouldSwing() && !this.player.gameMode.interactResult) { // Paper - Call interact event
this.player
.swingAndResetAttackStrength(hand, swingAnimation, success.swingSource() != InteractionResult.SwingSource.PREDICTED);
}
@@ -208,12 +208,13 @@
this.effectsDirty = true;
}
- this.setHealth(input.getFloatOr("Health", this.getMaxHealth()));
+ // CraftBukkit start
+ input.read("Bukkit.MaxHealth", com.mojang.serialization.Codec.DOUBLE).ifPresent(maxHealth -> {
+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(maxHealth);
+ });
+ // CraftBukkit end
this.setHealth(input.getFloatOr("Health", this.getMaxHealth()));
+ this.setHealth(input.getFloatOr("Health", this.getMaxHealth()), false); // Paper - Fix MC-17876
this.hurtTime = input.getShortOr("HurtTime", (short)0);
this.deathTime = input.getShortOr("DeathTime", (short)0);
this.setSharedFlag(Entity.FLAG_FALL_FLYING, input.getBooleanOr("FallFlying", false));
@@ -423,7 +424,7 @@
if (effectInstance != null) {
this.onEffectsRemoved(List.of(effectInstance));
return true;
@@ -1152,17 +_,62 @@
@@ -1152,18 +_,74 @@
}
public void heal(final float heal) {
@@ -463,9 +464,8 @@
return this.entityData.get(DATA_HEALTH_ID);
}
- public void setHealth(final float health) {
+ // Paper start - Check for NaN
+ public void setHealth(float health) {
+ public void setHealth(float health, final boolean clamp) { // Paper - Fix MC-17876 - add clamp parameter
+ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) {
+ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set");
+ } } // Paper end - Check for NaN
@@ -475,7 +475,7 @@
+ // Squeeze
+ if (health < 0.0F) {
+ player.setRealHealth(0.0);
+ } else if (health > player.getMaxHealth()) {
+ } else if (clamp && health > player.getMaxHealth()) { // Paper - Fix MC-17876
+ player.setRealHealth(player.getMaxHealth());
+ } else {
+ player.setRealHealth(health);
@@ -485,9 +485,22 @@
+ return;
+ }
+ // CraftBukkit end
this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
+ // Paper start - Fix MC-17876
+ if (clamp) {
+ health = Math.clamp(health, 0.0F, this.getMaxHealth());
+ } else {
+ health = Math.max(health, 0.0F);
+ }
+
+ this.entityData.set(DATA_HEALTH_ID, health);
+ }
public void setHealth(final float health) {
- this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
+ this.setHealth(health, true);
+ // Paper end - Fix MC-17876
}
public boolean isDeadOrDying() {
@@ -1180,7 +_,7 @@
return false;
}
@@ -6,6 +6,7 @@ import com.mojang.datafixers.DataFixer;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -53,6 +54,8 @@ public interface PlatformHooks extends ChunkSystemHooks {
public void chunkUnloadFromWorld(final LevelChunk chunk);
public void onFullChunkStatusChange(final LevelChunk chunk, final FullChunkStatus from, final FullChunkStatus to);
public void chunkSyncSave(final ServerLevel world, final ChunkAccess chunk, final SerializableChunkData data);
public void onChunkWatch(final ServerLevel world, final LevelChunk chunk, final ServerPlayer player);
@@ -70,6 +73,8 @@ public interface PlatformHooks extends ChunkSystemHooks {
public boolean configFixMC224294();
public boolean configFixMC119599(final ServerLevel world);
public boolean configAutoConfigSendDistance();
public double configPlayerMaxLoadRate();
@@ -0,0 +1,131 @@
package ca.spottedleaf.moonrise.common.util;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import oshi.SystemInfo;
import java.util.Locale;
public final class FMA {
private static final Logger LOGGER = LogUtils.getLogger();
static {
final Thread t = new Thread() {
@Override
public void run() {
FMAInit.init();
}
};
t.setPriority(Thread.MIN_PRIORITY);
t.setName(PlatformHooks.get().getBrand() + " FMA initialiser");
t.setDaemon(true);
t.setUncaughtExceptionHandler((final Thread thread, final Throwable thr) -> {
LOGGER.error("Uncaught exception in thread '" + thread.getName() + "': ", thr);
});
t.start();
}
public static void init() {}
public static boolean isFMASupported() {
return FMAInit.FMA_SUPPORTED;
}
private static final class FMAInit {
public static final boolean FMA_SUPPORTED = detectFma();
private static void init() {}
private static boolean detectFma() {
final String arch = System.getProperty("os.arch", "").toLowerCase(Locale.ROOT);
final boolean is64 = arch.contains("64");
final boolean arm = arch.contains("aarch64") || arch.contains("arm64");
if (arm) {
// FMA is ARMv8 baseline, Apple Silicon included
LOGGER.info("FMA supported: " + true + " for all ARMv8 platforms");
return true;
}
if (!is64) {
LOGGER.info("FMA supported: " + false + " for all non 64-bit platforms");
return false;
}
if (System.getProperty("os.name", "").toLowerCase(Locale.ROOT).contains("linux")) {
try {
for (final String line : new SystemInfo().getHardware().getProcessor().getFeatureFlags()) {
if (line.toLowerCase(Locale.ROOT).matches("(?s).*\\bfma\\b.*")) {
LOGGER.info("FMA supported: " + true + " for Linux platform with feature flag: " + line);
return true;
}
}
LOGGER.info("FMA supported: " + false + " for Linux platform without any matching feature flag");
return false;
} catch (final Throwable thr) {
LOGGER.debug("Error while retrieving platform flags: ", thr);
LOGGER.info("FMA supported: " + false + " for Linux platform: unable to retrieve feature flags");
return false;
}
}
// Windows, macOS: measure the actual thing
final boolean fma = testForFMA();
LOGGER.info("FMA supported: " + fma + " as determined by performance comparison test");
return fma;
}
private static boolean testForFMA() {
// warm into C2
for (int i = 0; i < 3; i++) {
timeFma(Sink.X);
timeMul(Sink.Y);
}
final long fma = Math.min(
timeFma(Sink.X),
Math.min(
timeFma(Sink.X), timeFma(Sink.X)
)
);
final long mul = Math.min(
timeMul(Sink.Y),
Math.min(
timeMul(Sink.Y), timeMul(Sink.Y)
)
);
// intrinsic fma ~= mul speed; software is 10x+
return fma < mul * 3;
}
private static final double A = 1.000001;
private static final double B = 0.999999;
private static final int LOOPS = 200_000;
private static long timeFma(final double[] s) {
double x = s[0];
long t = System.nanoTime();
for (int i = 0; i < LOOPS; i++) {
x = Math.fma(A, B, x);
}
s[0] = x;
return System.nanoTime() - t;
}
private static long timeMul(final double[] s) {
double y = s[0];
long t = System.nanoTime();
for (int i = 0; i < LOOPS; i++) {
y = y * A + B;
}
s[0] = y;
return System.nanoTime() - t;
}
static final class Sink {
static final double[] X = { 0.5 };
static final double[] Y = { 0.5 };
}
}
private FMA() {}
}
@@ -9,7 +9,8 @@ public final class MoonriseConstants {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int MAX_VIEW_DISTANCE = Integer.getInteger(PlatformHooks.get().getBrand() + ".MaxViewDistance", 32);
// note: only allows increasing the max view distance, as lower values are smaller than the chunk generation radius
public static final int MAX_VIEW_DISTANCE = Math.max(32, Integer.getInteger(PlatformHooks.get().getBrand() + ".MaxViewDistance", 32));
public static final boolean NUMA_ENABLE;
static {
final boolean numaScheduling = Boolean.getBoolean(PlatformHooks.get().getBrand() + ".NumaScheduling");
@@ -218,6 +218,7 @@ public class GlobalConfiguration extends ConfigurationPart {
@PostProcess
private void postProcess() {
ca.spottedleaf.moonrise.common.util.FMA.init();
ca.spottedleaf.moonrise.common.util.MoonriseCommon.adjustWorkerThreads(this.workerThreads, this.ioThreads);
}
}
@@ -418,6 +418,8 @@ public class WorldConfiguration extends ConfigurationPart {
public boolean optimizeExplosions = false;
public boolean disableExplosionKnockback = false;
public boolean generateFlatBedrock = false;
@Comment("Fixes MC-119599. Vanilla places snow on a chunk while generating that chunk's features, so tree parts that neighbouring chunks generate into it afterwards are left without snow, causing snowless patches of leaves with straight edges at chunk borders. Vanilla also only places snow on the top block of each column, so lower leaf layers and the ground under leaves never get snow. When enabled, snow is placed again as neighbouring chunks generate their features, including on lower leaf layers and the ground under leaves. This changes world generation and only affects newly generated chunks.")
public boolean fixMissingTreeSnow = false;
public FrostedIce frostedIce;
public DoubleOr.Disabled voidDamageAmount = new DoubleOr.Disabled(OptionalDouble.of(4));
public double voidDamageMinBuildHeightOffset = -64.0;
@@ -1,12 +1,14 @@
package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import io.papermc.paper.event.player.PlayerOpenSignEvent;
import java.util.List;
import java.util.UUID;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.entity.SignText;
import net.minecraft.world.level.block.entity.SignTextSlot;
import org.bukkit.Bukkit;
import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Sign;
@@ -19,107 +21,53 @@ import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerSignOpenEvent;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<T> implements Sign {
private @MonotonicNonNull CraftSignSide front;
private @MonotonicNonNull CraftSignSide back;
public CraftSign(World world, T blockEntity, boolean useSnapshot) {
public CraftSign(final World world, final T blockEntity, final boolean useSnapshot) {
super(world, blockEntity, useSnapshot);
}
protected CraftSign(CraftSign<T> state, Location location) {
protected CraftSign(final CraftSign<T> state, final @Nullable Location location) {
super(state, location);
}
@Override
protected void load(T blockEntity) {
protected void load(final T blockEntity) {
super.load(blockEntity);
this.front = new CraftSignSide(blockEntity.getText(SignTextSlot.FRONT));
this.back = new CraftSignSide(blockEntity.getText(SignTextSlot.BACK));
}
// Paper start
@Override
public java.util.@NotNull List<net.kyori.adventure.text.Component> lines() {
return this.front.lines();
}
@Override
public net.kyori.adventure.text.@NotNull Component line(int index) {
return this.front.line(index);
}
@Override
public void line(int index, net.kyori.adventure.text.@NotNull Component line) {
this.front.line(index, line);
}
// Paper end
@Override
public String[] getLines() {
return this.front.getLines();
}
@Override
public String getLine(int index) throws IndexOutOfBoundsException {
return this.front.getLine(index);
}
@Override
public void setLine(int index, String line) throws IndexOutOfBoundsException {
this.front.setLine(index, line);
}
@Override
public boolean isEditable() {
return !this.isWaxed();
}
@Override
public void setEditable(boolean editable) {
this.setWaxed(!editable);
}
@Override
public boolean isWaxed() {
return this.getSnapshot().isWaxed();
}
@Override
public void setWaxed(boolean waxed) {
public void setWaxed(final boolean waxed) {
this.getSnapshot().setWaxed(waxed);
}
@Override
public boolean isGlowingText() {
return this.front.isGlowingText();
}
@Override
public void setGlowingText(boolean glowing) {
this.front.setGlowingText(glowing);
}
@NotNull
@Override
public SignSide getSide(Side side) {
public SignSide getSide(final Side side) {
Preconditions.checkArgument(side != null, "side == null");
switch (side) {
case FRONT:
return this.front;
case BACK:
return this.back;
default:
throw new IllegalArgumentException();
}
return switch (side) {
case FRONT -> this.front;
case BACK -> this.back;
default -> throw new IllegalArgumentException("Unknown side: " + side);
};
}
@Override
public SignSide getTargetSide(Player player) {
public SignSide getTargetSide(final Player player) {
this.ensureNoWorldGeneration();
Preconditions.checkArgument(player != null, "player cannot be null");
@@ -131,26 +79,16 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
}
@Override
public Player getAllowedEditor() {
public @Nullable Player getAllowedEditor() {
this.ensureNoWorldGeneration();
// getPlayerWhoMayEdit is always null for the snapshot, so we use the wrapped BlockEntity
UUID id = this.getBlockEntity().getPlayerWhoMayEdit();
final UUID id = this.getBlockEntity().getPlayerWhoMayEdit();
return (id == null) ? null : Bukkit.getPlayer(id);
}
@Override
public DyeColor getColor() {
return this.front.getColor();
}
@Override
public void setColor(DyeColor color) {
this.front.setColor(color);
}
@Override
public void applyTo(T blockEntity) {
public void applyTo(final T blockEntity) {
this.getSnapshot().setText(this.front.applyLegacyStringToSignSide(), SignTextSlot.FRONT);
this.getSnapshot().setText(this.back.applyLegacyStringToSignSide(), SignTextSlot.BACK);
@@ -159,38 +97,37 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
@Override
public CraftSign<T> copy() {
return new CraftSign<T>(this, null);
return new CraftSign<>(this, null);
}
@Override
public CraftSign<T> copy(Location location) {
return new CraftSign<T>(this, location);
public CraftSign<T> copy(final Location location) {
return new CraftSign<>(this, location);
}
public static void openSign(Sign sign, Player player, Side side) {
public static void openSign(final Sign sign, final Player player, final Side side) {
Preconditions.checkArgument(sign != null, "sign == null");
Preconditions.checkArgument(side != null, "side == null");
Preconditions.checkArgument(sign.isPlaced(), "Sign must be placed");
Preconditions.checkArgument(sign.getWorld() == player.getWorld(), "Sign must be in same world as Player");
io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent(player, sign, side, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLUGIN);
final PlayerOpenSignEvent event = new PlayerOpenSignEvent(player, sign, side, PlayerOpenSignEvent.Cause.PLUGIN);;
if (!event.callEvent()) return;
if (PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
if (PlayerSignOpenEvent.getHandlerList().hasListeners()) {
if (!CraftEventFactory.callPlayerSignOpenEvent(player, sign, side, PlayerSignOpenEvent.Cause.PLUGIN)) {
return;
}
}
SignBlockEntity blockEntity = ((CraftSign<?>) sign).getBlockEntity();
final SignBlockEntity blockEntity = ((CraftSign<?>) sign).getBlockEntity();
blockEntity.setAllowedPlayerEditor(player.getUniqueId());
((CraftPlayer) player).getHandle().openTextEdit(blockEntity, CraftSignSide.toVanilla(side));
}
// Paper start
public static Component[] sanitizeLines(java.util.List<? extends net.kyori.adventure.text.Component> lines) {
Component[] components = new Component[4];
for (int i = 0; i < 4; i++) {
public static Component[] sanitizeLines(final List<? extends net.kyori.adventure.text.Component> lines) {
Component[] components = new Component[SignText.LINES];
for (int i = 0; i < SignText.LINES; i++) {
if (i < lines.size() && lines.get(i) != null) {
components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i));
} else {
@@ -199,17 +136,15 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
}
return components;
}
// Paper end
// Paper start - More Sign Block API
@Override
public java.util.UUID getAllowedEditorUniqueId() {
public @Nullable UUID getAllowedEditorUniqueId() {
this.ensureNoWorldGeneration();
return this.getBlockEntity().getPlayerWhoMayEdit();
}
@Override
public void setAllowedEditorUniqueId(java.util.UUID uuid) {
public void setAllowedEditorUniqueId(final @Nullable UUID uuid) {
this.ensureNoWorldGeneration();
this.getBlockEntity().setAllowedPlayerEditor(uuid);
}
@@ -219,12 +154,21 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
this.requirePlaced();
return CraftSignSide.fromVanilla(this.getSnapshot().getSlotPlayerIsFacing(x, z));
}
// Paper end - More Sign Block API
public static Component[] sanitizeLines(String[] lines) {
Component[] components = new Component[4];
@Override
public void setOperatorFeaturesAllowed(final boolean allowed) {
this.getSnapshot().allowOpFeatures = allowed;
}
for (int i = 0; i < 4; i++) {
@Override
public boolean isOperatorFeaturesAllowed() {
return this.getSnapshot().allowOpFeatures;
}
public static Component[] sanitizeLines(final String[] lines) {
final Component[] components = new Component[SignText.LINES];
for (int i = 0; i < SignText.LINES; i++) {
if (i < lines.length && lines[i] != null) {
components[i] = CraftChatMessage.fromString(lines[i])[0];
} else {
@@ -235,15 +179,15 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
return components;
}
public static String[] revertComponents(Component[] components) {
String[] lines = new String[components.length];
public static String[] revertComponents(final Component[] components) {
final String[] lines = new String[components.length];
for (int i = 0; i < lines.length; i++) {
lines[i] = CraftSign.revertComponent(components[i]);
}
return lines;
}
private static String revertComponent(Component component) {
private static String revertComponent(final Component component) {
return CraftChatMessage.fromComponent(component);
}
}