mirror of
https://github.com/PaperMC/Paper.git
synced 2026-11-04 17:00:09 -05:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76d2ac758c | ||
|
|
20938c7217 | ||
|
|
ca5e948ace | ||
|
|
e2c7e5cff2 | ||
|
|
d4fe85375a | ||
|
|
3580fa4066 | ||
|
|
10a73fe40f | ||
|
|
34cf3ab0f9 | ||
|
|
fd45f4b2e3 | ||
|
|
5c917dabab | ||
|
|
2186e1e407 | ||
|
|
711c5de2b0 | ||
|
|
687ba1e391 | ||
|
|
8dea6f1761 |
No files matched your search
@@ -122,6 +122,7 @@ public net.minecraft.stats.ServerRecipeBook known
|
||||
public net.minecraft.tags.TagEntry id
|
||||
public net.minecraft.tags.TagEntry required
|
||||
public net.minecraft.tags.TagEntry tag
|
||||
public net.minecraft.util.AbstractListBuilder
|
||||
public net.minecraft.util.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V
|
||||
public net.minecraft.util.datafix.fixes.BlockStateData register(ILcom/mojang/serialization/Dynamic;[Lcom/mojang/serialization/Dynamic;)V
|
||||
public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||
|
||||
plugins {
|
||||
id("io.papermc.paperweight.core") version "2.0.0-SNAPSHOT" apply false
|
||||
id("io.papermc.paperweight.core") version "2.0.0-beta.21" apply false
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Translatable;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.util.OldEnum;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -170,6 +171,13 @@ public interface Attribute extends OldEnum<Attribute>, Keyed, Translatable, net.
|
||||
@NotNull
|
||||
Sentiment getSentiment();
|
||||
|
||||
/**
|
||||
* {@return the default value of this attribute}
|
||||
* <p>
|
||||
* Default attribute values may differ between entity types, use {@link EntityType#getDefaultAttributes()} to get default attribute values for a specific entity type.
|
||||
*/
|
||||
double getDefaultValue();
|
||||
|
||||
/**
|
||||
* @param name of the attribute.
|
||||
* @return the attribute with the given name.
|
||||
|
||||
@@ -111,6 +111,11 @@ public interface AttributeInstance {
|
||||
* Gets the default value of the Attribute attached to this instance.
|
||||
*
|
||||
* @return server default value
|
||||
* @deprecated this method is placed misleadingly as it does not return the default value in the current entity's context, but in the server's context.
|
||||
* Use {@link Attribute#getDefaultValue()} as a replacement and see the note there about default values for specific entity types
|
||||
* @see Attribute#getDefaultValue()
|
||||
* @see org.bukkit.entity.EntityType#getDefaultAttributes()
|
||||
*/
|
||||
@Deprecated(since = "26.1")
|
||||
double getDefaultValue();
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public interface AreaEffectCloud extends Entity {
|
||||
float getRadiusPerTick();
|
||||
|
||||
/**
|
||||
* Gets the amount that the radius of this cloud will decrease by each tick.
|
||||
* Sets the amount that the radius of this cloud will decrease by each tick.
|
||||
*
|
||||
* @param radius per tick delta
|
||||
*/
|
||||
@@ -139,7 +139,7 @@ public interface AreaEffectCloud extends Entity {
|
||||
/**
|
||||
* Sets the particle which this cloud will be composed of
|
||||
*
|
||||
* @param <T> type of particle data (see {@link Particle#getDataType()}
|
||||
* @param <T> type of particle data (see {@link Particle#getDataType()})
|
||||
* @param particle the new particle type
|
||||
* @param data the data to use for the particle or null,
|
||||
* the type of this depends on {@link Particle#getDataType()}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public interface Firework extends Projectile {
|
||||
|
||||
/**
|
||||
* Get a copy of the fireworks meta
|
||||
*
|
||||
* @return A copy of the current Firework meta
|
||||
* @apiNote obsolete in favor of {@link #getItem()} / {@link #setItem(ItemStack)} with the equivalent {@link DataComponentTypes#FIREWORKS} component
|
||||
*/
|
||||
@NotNull
|
||||
@ApiStatus.Obsolete
|
||||
FireworkMeta getFireworkMeta();
|
||||
|
||||
/**
|
||||
@@ -20,8 +26,10 @@ public interface Firework extends Projectile {
|
||||
* Adjusts detonation ticks automatically.
|
||||
*
|
||||
* @param meta The FireworkMeta to apply
|
||||
* @apiNote obsolete in favor of {@link #getItem()} / {@link #setItem(ItemStack)} with the equivalent {@link DataComponentTypes#FIREWORKS} component
|
||||
*/
|
||||
void setFireworkMeta(@NotNull FireworkMeta meta);
|
||||
@ApiStatus.Obsolete
|
||||
void setFireworkMeta(FireworkMeta meta);
|
||||
|
||||
/**
|
||||
* Set the {@link LivingEntity} to which this firework is attached.
|
||||
@@ -48,8 +56,7 @@ public interface Firework extends Projectile {
|
||||
*
|
||||
* @return the attached entity, or null if none
|
||||
*/
|
||||
@Nullable
|
||||
LivingEntity getAttachedTo();
|
||||
@Nullable LivingEntity getAttachedTo();
|
||||
|
||||
/**
|
||||
* Set the ticks that this firework has been alive. If this value exceeds
|
||||
@@ -59,7 +66,7 @@ public interface Firework extends Projectile {
|
||||
* @deprecated use {@link #setTicksFlown(int)}
|
||||
* @return true if the life was set, false if this firework has already detonated
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
boolean setLife(int ticks);
|
||||
|
||||
/**
|
||||
@@ -69,7 +76,7 @@ public interface Firework extends Projectile {
|
||||
* @deprecated use {@link #getTicksFlown()}
|
||||
* @return the life ticks
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
int getLife();
|
||||
|
||||
/**
|
||||
@@ -79,7 +86,7 @@ public interface Firework extends Projectile {
|
||||
* @deprecated use {@link #setTicksToDetonate(int)}
|
||||
* @return true if the time was set, false if this firework has already detonated
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
boolean setMaxLife(int ticks);
|
||||
|
||||
/**
|
||||
@@ -88,7 +95,7 @@ public interface Firework extends Projectile {
|
||||
* @deprecated use {@link #getTicksToDetonate()}
|
||||
* @return the maximum life in ticks
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
int getMaxLife();
|
||||
|
||||
/**
|
||||
@@ -122,30 +129,30 @@ public interface Firework extends Projectile {
|
||||
*/
|
||||
void setShotAtAngle(boolean shotAtAngle);
|
||||
|
||||
// Paper start
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public java.util.UUID getSpawningEntity();
|
||||
/**
|
||||
* Retrieves the UUID of the entity responsible for spawning this firework.
|
||||
*
|
||||
* @return the UUID of the spawning entity, or null if no spawning entity is associated
|
||||
*/
|
||||
@Nullable UUID getSpawningEntity();
|
||||
|
||||
/**
|
||||
* If this firework is boosting an entity, return it
|
||||
* @deprecated use {@link #getAttachedTo()}
|
||||
* @see #setAttachedTo(LivingEntity)
|
||||
* @return The entity being boosted
|
||||
*/
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@Deprecated
|
||||
default LivingEntity getBoostedEntity() {
|
||||
return getAttachedTo();
|
||||
@Deprecated(since = "1.18.2")
|
||||
default @Nullable LivingEntity getBoostedEntity() {
|
||||
return this.getAttachedTo();
|
||||
}
|
||||
// Paper end
|
||||
|
||||
// Paper start - Firework API
|
||||
/**
|
||||
* Gets the item used in the firework.
|
||||
*
|
||||
* @return firework item
|
||||
*/
|
||||
@NotNull
|
||||
public org.bukkit.inventory.ItemStack getItem();
|
||||
ItemStack getItem();
|
||||
|
||||
/**
|
||||
* Sets the item used in the firework.
|
||||
@@ -154,7 +161,7 @@ public interface Firework extends Projectile {
|
||||
*
|
||||
* @param itemStack item to set
|
||||
*/
|
||||
void setItem(@org.jetbrains.annotations.Nullable org.bukkit.inventory.ItemStack itemStack);
|
||||
void setItem(@Nullable ItemStack itemStack);
|
||||
|
||||
/**
|
||||
* Gets the number of ticks the firework has flown.
|
||||
@@ -184,5 +191,4 @@ public interface Firework extends Projectile {
|
||||
* @param ticks ticks to detonate on
|
||||
*/
|
||||
void setTicksToDetonate(int ticks);
|
||||
// Paper end
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.Fireworks;
|
||||
import io.papermc.paper.datacomponent.item.UseCooldown;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import io.papermc.paper.datacomponent.item.UseCooldown;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@@ -20,7 +22,6 @@ import org.bukkit.inventory.MainHand;
|
||||
import org.bukkit.inventory.MenuType;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
@@ -1009,16 +1010,35 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
|
||||
* Perform a firework boost.
|
||||
* <p>
|
||||
* This method will only work such that {@link #isGliding()} is true and
|
||||
* the entity is actively gliding with an elytra. Additionally, the supplied
|
||||
* {@code fireworkItemStack} must be a firework rocket. The power of the boost
|
||||
* will directly correlate to {@link FireworkMeta#getPower()}.
|
||||
* the entity is actively gliding with an item with {@link DataComponentTypes#GLIDER} component.
|
||||
* <p>
|
||||
* The power of the boost will directly correlate to {@link Fireworks#flightDuration()} from {@link DataComponentTypes#FIREWORKS} component.
|
||||
* <p>
|
||||
* This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}.
|
||||
*
|
||||
* @param fireworkItemStack the firework item stack to use to glide
|
||||
* @param boosterItem the item to use to boost
|
||||
* @return the attached {@link Firework}, or null if the entity could not
|
||||
* be boosted
|
||||
* @throws IllegalArgumentException if the fireworkItemStack is not a firework
|
||||
*/
|
||||
@Nullable
|
||||
public Firework fireworkBoost(ItemStack fireworkItemStack);
|
||||
Firework fireworkBoost(ItemStack boosterItem);
|
||||
|
||||
/**
|
||||
* Perform a firework boost.
|
||||
* <p>
|
||||
* This method will only work such that {@link #isGliding()} is true and
|
||||
* the entity is actively gliding with an item with {@link DataComponentTypes#GLIDER} component.
|
||||
* <p>
|
||||
* The power of the boost will directly correlate to {@link Fireworks#flightDuration()} from {@link DataComponentTypes#FIREWORKS} component.
|
||||
* <p>
|
||||
* This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}.
|
||||
*
|
||||
* @return the attached {@link Firework}, or null if the entity could not
|
||||
* be boosted
|
||||
*/
|
||||
@Nullable
|
||||
default Firework fireworkBoost() {
|
||||
return this.fireworkBoost(ItemStack.empty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
import com.destroystokyo.paper.ClientOption;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.connection.PlayerGameConnection;
|
||||
import io.papermc.paper.entity.LookAnchor;
|
||||
import io.papermc.paper.entity.PlayerGiveResult;
|
||||
@@ -3616,24 +3617,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
<T> T getClientOption(ClientOption<T> option);
|
||||
// Paper end - client option API
|
||||
|
||||
// Paper start - elytra boost API
|
||||
/**
|
||||
* Boost a Player that's {@link #isGliding()} using a {@link Firework}.
|
||||
* If the creation of the entity is cancelled, no boosting is done.
|
||||
* This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}.
|
||||
*
|
||||
* @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with
|
||||
* @param boosterItem The itemstack to boost the player with
|
||||
* @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled
|
||||
* @throws IllegalArgumentException if {@link #isGliding()} is false
|
||||
* or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET}
|
||||
* @throws IllegalStateException if {@link #isGliding()} is false
|
||||
* @deprecated use {@link HumanEntity#fireworkBoost(ItemStack)} instead. Note that this method <b>does not</b>
|
||||
* check if the player is gliding or not.
|
||||
*/
|
||||
default @Nullable Firework boostElytra(final ItemStack firework) {
|
||||
com.google.common.base.Preconditions.checkState(this.isGliding(), "Player must be gliding");
|
||||
return this.fireworkBoost(firework);
|
||||
@Deprecated(since = "1.20.5")
|
||||
default @Nullable Firework boostElytra(final ItemStack boosterItem) {
|
||||
Preconditions.checkState(this.isGliding(), "Player must be gliding");
|
||||
return this.fireworkBoost(boosterItem);
|
||||
}
|
||||
// Paper end - elytra boost API
|
||||
|
||||
// Paper start - sendOpLevel API
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface ThrowableProjectile extends Projectile {
|
||||
|
||||
/**
|
||||
@@ -10,7 +11,6 @@ public interface ThrowableProjectile extends Projectile {
|
||||
*
|
||||
* @return The thrown item display ItemStack
|
||||
*/
|
||||
@NotNull
|
||||
ItemStack getItem();
|
||||
|
||||
/**
|
||||
@@ -18,5 +18,5 @@ public interface ThrowableProjectile extends Projectile {
|
||||
*
|
||||
* @param item ItemStack set to be displayed
|
||||
*/
|
||||
void setItem(@NotNull ItemStack item);
|
||||
void setItem(ItemStack item);
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Represents a thrown potion bottle
|
||||
*/
|
||||
@NullMarked
|
||||
public interface ThrownPotion extends ThrowableProjectile {
|
||||
|
||||
/**
|
||||
@@ -15,8 +19,7 @@ public interface ThrownPotion extends ThrowableProjectile {
|
||||
*
|
||||
* @return The potion effects
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<PotionEffect> getEffects();
|
||||
Collection<PotionEffect> getEffects();
|
||||
|
||||
/**
|
||||
* Returns a copy of the ItemStack for this thrown potion.
|
||||
@@ -27,25 +30,24 @@ public interface ThrownPotion extends ThrowableProjectile {
|
||||
*
|
||||
* @return A copy of the ItemStack for this thrown potion.
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStack getItem();
|
||||
ItemStack getItem();
|
||||
|
||||
/**
|
||||
* Set the ItemStack for this thrown potion.
|
||||
*
|
||||
* @param item New ItemStack
|
||||
*/
|
||||
public void setItem(@NotNull ItemStack item);
|
||||
void setItem(ItemStack item);
|
||||
|
||||
// Paper start - Projectile API
|
||||
/**
|
||||
* Gets a copy of the PotionMeta for this thrown potion.
|
||||
* This includes what effects will be applied by this potion.
|
||||
*
|
||||
* @return potion meta
|
||||
* @apiNote obsolete in favor of {@link #getItem()} / {@link #setItem(ItemStack)} with the equivalent {@link DataComponentTypes#POTION_CONTENTS} component
|
||||
*/
|
||||
@NotNull
|
||||
org.bukkit.inventory.meta.PotionMeta getPotionMeta();
|
||||
@ApiStatus.Obsolete
|
||||
PotionMeta getPotionMeta();
|
||||
|
||||
/**
|
||||
* Sets the PotionMeta of this thrown potion.
|
||||
@@ -54,12 +56,13 @@ public interface ThrownPotion extends ThrowableProjectile {
|
||||
* Note that the type of {@link #getItem()} is irrelevant
|
||||
*
|
||||
* @param meta potion meta
|
||||
* @apiNote obsolete in favor of {@link #getItem()} / {@link #setItem(ItemStack)} with the equivalent {@link DataComponentTypes#POTION_CONTENTS} component
|
||||
*/
|
||||
void setPotionMeta(@NotNull org.bukkit.inventory.meta.PotionMeta meta);
|
||||
@ApiStatus.Obsolete
|
||||
void setPotionMeta(PotionMeta meta);
|
||||
|
||||
/**
|
||||
* Splashes the potion at its current location.
|
||||
*/
|
||||
void splash();
|
||||
// Paper end
|
||||
}
|
||||
@@ -14,7 +14,7 @@ plugins {
|
||||
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||
|
||||
dependencies {
|
||||
mache("io.papermc:mache:26.1.2+build.1")
|
||||
mache("io.papermc:mache:26.1.2+build.3")
|
||||
paperclip("io.papermc:paperclip:3.0.4")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ paperweight {
|
||||
gitFilePatches = false
|
||||
|
||||
updatingMinecraft {
|
||||
// oldPaperCommit = "7e80cef5198561d0db53406127e5b8bc7af51577"
|
||||
// oldPaperCommit = "711c5de2b05df39b72c44ff54e9f9381f8d153cb"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -33491,7 +33491,7 @@ index 109d7b563ee799d998a5773c5a36e61ca3607d46..747755082639436731989d3ee4b3c30a
|
||||
return structureTemplate.save(new CompoundTag());
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index e11862c7e0617acfb36212cfe349bdade3a5164b..7ae2d491a3b2f379df99ccc649b8bb8cbf2304b9 100644
|
||||
index c809ea1f2620c543d9bc80afdd64489f2fb98744..49be7709026cd75cfcb31715550387f0ba954a16 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -299,6 +299,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -33503,18 +33503,18 @@ index e11862c7e0617acfb36212cfe349bdade3a5164b..7ae2d491a3b2f379df99ccc649b8bb8c
|
||||
Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> serverReference.get().runServer(), "Server thread");
|
||||
thread.setUncaughtExceptionHandler((t, e) -> LOGGER.error("Uncaught exception in server thread", e));
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
index c206c74acc80c281d06a669eb668239dc61018eb..884fa9545a93008fa92863c845aef8f18d88e25a 100644
|
||||
index 4346f3bace176e09d9ffb02e9af29a1281071e2a..df4f03f3a346e0ab0074757b3a077b2407135ac3 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
@@ -99,7 +99,7 @@ public class SimpleRegionStorage implements ca.spottedleaf.moonrise.patches.chun
|
||||
}
|
||||
// Spigot end
|
||||
injectDatafixingContext(chunkTag, dataFixContextTag);
|
||||
- chunkTag = this.dataFixType.update(this.fixerUpper, chunkTag, version, targetVersion);
|
||||
+ chunkTag = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), chunkTag, version, targetVersion); // Paper - rewrite dataconverter system
|
||||
// Spigot start
|
||||
if (stopBelowZero) {
|
||||
chunkTag.putString("Status", net.minecraft.core.registries.BuiltInRegistries.CHUNK_STATUS.getKey(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN).toString());
|
||||
@@ -100,7 +100,7 @@ public class SimpleRegionStorage implements ca.spottedleaf.moonrise.patches.chun
|
||||
}
|
||||
// Spigot end
|
||||
injectDatafixingContext(chunkTag, dataFixContextTag);
|
||||
- chunkTag = this.dataFixType.update(this.fixerUpper, chunkTag, version, targetVersion);
|
||||
+ chunkTag = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), chunkTag, version, targetVersion); // Paper - rewrite dataconverter system
|
||||
// Spigot start
|
||||
if (stopBelowZero) {
|
||||
chunkTag.putString("Status", net.minecraft.core.registries.BuiltInRegistries.CHUNK_STATUS.getKey(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN).toString());
|
||||
@@ -118,6 +118,20 @@ public class SimpleRegionStorage implements ca.spottedleaf.moonrise.patches.chun
|
||||
}
|
||||
}
|
||||
@@ -33537,23 +33537,23 @@ index c206c74acc80c281d06a669eb668239dc61018eb..884fa9545a93008fa92863c845aef8f1
|
||||
return this.upgradeChunkTag(chunkTag, defaultVersion, null, SharedConstants.getCurrentVersion().dataVersion().version());
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
index 2ab055d5cdfb1e2e7cfb6f8a769c3d571acb2861..a45da98735045d55d3da14271c9bbb7a37f3151c 100644
|
||||
index cba5c9ea5fd424e7aaeefaa8cc5ffe37f307b370..ce7856fa3b0f48099d09057bb44ce95a42367301 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
@@ -161,7 +161,7 @@ public class StructureCheck {
|
||||
@@ -163,7 +163,7 @@ public class StructureCheck {
|
||||
|
||||
CompoundTag fixedChunkTag;
|
||||
try {
|
||||
- fixedChunkTag = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, chunkTag, version);
|
||||
+ fixedChunkTag = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, chunkTag, version, ca.spottedleaf.dataconverter.minecraft.util.Version.getCurrentVersion()); // Paper - replace chunk converter
|
||||
} catch (Exception var12) {
|
||||
LOGGER.warn("Failed to partially datafix chunk {}", pos, var12);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Failed to partially datafix chunk {}", pos, e);
|
||||
return StructureCheckResult.CHUNK_LOAD_NEEDED;
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/templatesystem/loader/TemplateSource.java b/net/minecraft/world/level/levelgen/structure/templatesystem/loader/TemplateSource.java
|
||||
index 780a3eb08b7fb2c385c8e75e2e5f02a9d67297f4..2c7e4a6288f0c7101755de4be8f14449cdc4e01e 100644
|
||||
index e61076a9ff3d9bce5c44e548158716db105db3ee..fe1500ebbfb09bef18989c891a19608ec9d4661c 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/templatesystem/loader/TemplateSource.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/templatesystem/loader/TemplateSource.java
|
||||
@@ -79,7 +79,7 @@ public abstract class TemplateSource {
|
||||
@@ -71,7 +71,7 @@ public abstract class TemplateSource {
|
||||
public StructureTemplate readStructure(final CompoundTag tag) {
|
||||
StructureTemplate structureTemplate = new StructureTemplate();
|
||||
int version = NbtUtils.getDataVersion(tag, 500);
|
||||
@@ -33563,7 +33563,7 @@ index 780a3eb08b7fb2c385c8e75e2e5f02a9d67297f4..2c7e4a6288f0c7101755de4be8f14449
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
index 41cbb27861f33ad8d7523f3b2fef9a30a69693a9..c5898bfb8b4f075b08090cba2e9f980174e0a326 100644
|
||||
index 8eda63e1f07f7998875713447c5f39eea3f85ca4..eddb6ebe3fa50a818e54079b73ba117be0abd195 100644
|
||||
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
@@ -98,7 +98,7 @@ public class PlayerDataStorage {
|
||||
|
||||
+14
-14
@@ -28,10 +28,10 @@ and then catch exceptions and close if they fire.
|
||||
Part of this commit was authored by: Spottedleaf, sandtechnology
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c647b1cde27 100644
|
||||
index 13faa13a9d3120cdeaca63d6eb3a0feb8019fb3a..d14aea970ce98edfe3dc3692e707334e7e150804 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -65,7 +65,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -64,7 +64,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
private static final ProtocolInfo<ServerHandshakePacketListener> INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND;
|
||||
private final PacketFlow receiving;
|
||||
private volatile boolean sendLoginDisconnect = true;
|
||||
@@ -40,7 +40,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
public Channel channel;
|
||||
public SocketAddress address;
|
||||
// Spigot start
|
||||
@@ -124,6 +124,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -123,6 +123,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public boolean handledLegacyLoginEvent; // Paper - playerloginevent
|
||||
public net.minecraft.server.level.@Nullable ServerPlayer savedPlayerForLegacyEvents; // Paper - playerloginevent & PlayerSpawnLocationEvent
|
||||
public org.bukkit.event.player.PlayerResourcePackStatusEvent.@Nullable Status resourcePackStatus; // Paper
|
||||
@@ -51,7 +51,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
|
||||
public Connection(final PacketFlow receiving) {
|
||||
this.receiving = receiving;
|
||||
@@ -394,11 +398,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -392,11 +396,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void send(final Packet<?> packet, final @Nullable ChannelFutureListener listener, final boolean flush) {
|
||||
@@ -93,7 +93,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +438,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -405,7 +436,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
this.flushQueue();
|
||||
action.accept(this);
|
||||
} else {
|
||||
@@ -102,7 +102,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,21 +452,42 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -419,21 +450,42 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
private void doSendPacket(final Packet<?> packet, final @Nullable ChannelFutureListener listener, final boolean flush) {
|
||||
@@ -149,7 +149,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,16 +499,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -445,16 +497,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
|
||||
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
|
||||
private static int joinAttemptsThisTick; // Paper - Buffer joins to world
|
||||
@@ -526,6 +619,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -524,6 +617,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
public void disconnect(final DisconnectionDetails details) {
|
||||
this.preparing = false; // Spigot
|
||||
@@ -220,7 +220,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
if (this.channel == null) {
|
||||
this.delayedDisconnect = details;
|
||||
}
|
||||
@@ -715,7 +809,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -705,7 +799,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public void handleDisconnection() {
|
||||
if (this.channel != null && !this.channel.isOpen()) {
|
||||
if (this.disconnectionHandled) {
|
||||
@@ -229,7 +229,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
} else {
|
||||
this.disconnectionHandled = true;
|
||||
PacketListener packetListener = this.getPacketListener();
|
||||
@@ -726,7 +820,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -716,7 +810,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
);
|
||||
disconnectListener.onDisconnect(details);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c64
|
||||
// Paper start - Add PlayerConnectionCloseEvent
|
||||
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
|
||||
/* Player was logged in, either game listener or configuration listener */
|
||||
@@ -761,4 +855,96 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -751,4 +845,96 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public void setBandwidthLogger(final LocalSampleLogger bandwidthLogger) {
|
||||
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwidthLogger);
|
||||
}
|
||||
@@ -372,10 +372,10 @@ index 1480d0db90f5797e3dee19503e52d1e783493ac3..bd76e55ea56dd7c1e232806d1d13a747
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerConnectionListener.java b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index 387ac8a4e67ef07df73ce98d0add0937314ee497..9ae7c79e5088d9e1e3fb7e0dca00bb15fee118b6 100644
|
||||
index 77e1c02b74c1f6597fbb5a457bf463fe52de019e..6d506004583b2415ab356e34e2f8d6ac0e39cca2 100644
|
||||
--- a/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -52,11 +52,13 @@ public class ServerConnectionListener {
|
||||
@@ -51,11 +51,13 @@ public class ServerConnectionListener {
|
||||
|
||||
// Paper start - prevent blocking on adding a new connection while the server is ticking
|
||||
private final java.util.Queue<Connection> pending = new java.util.concurrent.ConcurrentLinkedQueue<>();
|
||||
@@ -389,7 +389,7 @@ index 387ac8a4e67ef07df73ce98d0add0937314ee497..9ae7c79e5088d9e1e3fb7e0dca00bb15
|
||||
}
|
||||
}
|
||||
// Paper end - prevent blocking on adding a new connection while the server is ticking
|
||||
@@ -92,6 +94,7 @@ public class ServerConnectionListener {
|
||||
@@ -87,6 +89,7 @@ public class ServerConnectionListener {
|
||||
} catch (ChannelException var5) {
|
||||
}
|
||||
|
||||
|
||||
@@ -31,18 +31,18 @@ this fix, as the data will remain in the oversized file. Once the server returns
|
||||
to a jar with this fix, the data will be restored.
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 5149635679ec03d881e63effbd79fc193d7e52c8..d628e06a8dbf11b491b323c10a512fde22e72a12 100644
|
||||
index 026b1f31d5041786e90ba372a228732aee094c16..d39f8ae8f5736a7f4590ca41ac95792a61975baf 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -69,6 +69,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@@ -68,6 +68,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
this.info = info;
|
||||
this.path = path;
|
||||
this.version = version;
|
||||
+ this.initOversizedState(); // Paper
|
||||
if (!Files.isDirectory(externalFileDir)) {
|
||||
throw new IllegalArgumentException("Expected directory, got " + externalFileDir.toAbsolutePath());
|
||||
} else {
|
||||
@@ -465,4 +466,75 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
@@ -463,4 +464,75 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
private interface CommitOp {
|
||||
void run() throws IOException;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ index 5149635679ec03d881e63effbd79fc193d7e52c8..d628e06a8dbf11b491b323c10a512fde
|
||||
+ private synchronized void initOversizedState() throws IOException {
|
||||
+ Path metaFile = getOversizedMetaFile();
|
||||
+ if (Files.exists(metaFile)) {
|
||||
+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile);
|
||||
+ final byte[] read = Files.readAllBytes(metaFile);
|
||||
+ System.arraycopy(read, 0, oversized, 0, oversized.length);
|
||||
+ for (byte temp : oversized) {
|
||||
+ oversizedCount += temp;
|
||||
@@ -98,7 +98,7 @@ index 5149635679ec03d881e63effbd79fc193d7e52c8..d628e06a8dbf11b491b323c10a512fde
|
||||
+ }
|
||||
+
|
||||
+ private void writeOversizedMeta() throws IOException {
|
||||
+ java.nio.file.Files.write(getOversizedMetaFile(), oversized);
|
||||
+ Files.write(this.getOversizedMetaFile(), this.oversized);
|
||||
+ }
|
||||
+
|
||||
+ private Path getOversizedMetaFile() {
|
||||
@@ -119,16 +119,24 @@ index 5149635679ec03d881e63effbd79fc193d7e52c8..d628e06a8dbf11b491b323c10a512fde
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index e9316cc08fe4cb4af28583a8cb1ec658243bffd0..aa36e241d49725eb13f00e57d020d4da24add53d 100644
|
||||
index 36f8c19e3e90740e6d58eb8dbf573b2fdf4fed3d..3d0a09662e5ed1f7bc0c02dbe6de529791f2f66f 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -241,6 +241,43 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -16,6 +16,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.io.ChunkSystemRegionFileStorage { // Paper - rewrite chunk system
|
||||
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
|
||||
public static final String ANVIL_EXTENSION = ".mca";
|
||||
private static final int MAX_CACHE_SIZE = 256;
|
||||
public final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>();
|
||||
@@ -241,6 +242,43 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper end - rewrite chunk system
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private static void printOversizedLog(String msg, Path file, int x, int z) {
|
||||
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
|
||||
+ LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4);
|
||||
+ }
|
||||
+
|
||||
+ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
|
||||
@@ -145,9 +153,9 @@ index e9316cc08fe4cb4af28583a8cb1ec658243bffd0..aa36e241d49725eb13f00e57d020d4da
|
||||
+ mergeChunkList(chunk.getCompoundOrEmpty("Level"), oversizedLevel, "TileEntities", "TileEntities");
|
||||
+
|
||||
+ return chunk;
|
||||
+ } catch (Throwable throwable) {
|
||||
+ throwable.printStackTrace();
|
||||
+ throw throwable;
|
||||
+ } catch (Throwable t) {
|
||||
+ t.printStackTrace();
|
||||
+ throw t;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -166,7 +174,7 @@ index e9316cc08fe4cb4af28583a8cb1ec658243bffd0..aa36e241d49725eb13f00e57d020d4da
|
||||
public @Nullable CompoundTag read(final ChunkPos pos) throws IOException {
|
||||
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
|
||||
RegionFile region = this.getRegionFile(pos, true);
|
||||
@@ -248,6 +285,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -248,6 +286,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
return null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -177,9 +185,9 @@ index e9316cc08fe4cb4af28583a8cb1ec658243bffd0..aa36e241d49725eb13f00e57d020d4da
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
CompoundTag var4;
|
||||
try (DataInputStream regionChunkInputStream = region.getChunkDataInputStream(pos)) {
|
||||
@@ -290,6 +333,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
return regionChunkInputStream == null ? null : NbtIo.read(regionChunkInputStream);
|
||||
@@ -283,6 +327,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
} else {
|
||||
try (DataOutputStream output = region.getChunkDataOutputStream(pos)) {
|
||||
NbtIo.write(value, output);
|
||||
|
||||
@@ -354,7 +354,7 @@ index 0000000000000000000000000000000000000000..ce6b57eeeeb1bd652f4bb53c19dcfbc0
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 91d27b90a9c9c348d3f93624ff8dbff8a70f522c..f4bbccee849ee3711a3b838884e4bcf4e24da039 100644
|
||||
index 89da20b0682708ba8bfc0d10381eb9784d80c395..b5d63d7b848c11ed322d512adeee102886cbb6fd 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -864,6 +864,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -462,7 +462,7 @@ index 0df8332933203a904bd9ef9efb3c9bce21e65441..1a502cbd8acea9420fa6dd8d716018b5
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index e087d5596979044fe7fbcf7f2cccdae4e81a3d3a..fea6c3b48c4eb162fbdc099fa775bc3161a4dd4e 100644
|
||||
index 593265d78564b60bacbb4899f18a6e74bf56601d..84c664711658eb83b5ff9d4c8470fd8ec54a5473 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -382,6 +382,15 @@ public abstract class Entity
|
||||
@@ -521,10 +521,10 @@ index e087d5596979044fe7fbcf7f2cccdae4e81a3d3a..fea6c3b48c4eb162fbdc099fa775bc31
|
||||
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 8b0abe9c7a3907419f6e4d55ea22fb9bc749f28b..36c0081e3e8f8776293ae619156cd0828fe5b21d 100644
|
||||
index f62e535b62d249dd3be19d7c1b02fae8dad31c10..6eb95b979ffe37d78fd68eb57ebe71891beb0d28 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3372,6 +3372,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
@@ -3380,6 +3380,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
protected void playAttackSound() {
|
||||
}
|
||||
|
||||
@@ -540,7 +540,7 @@ index 8b0abe9c7a3907419f6e4d55ea22fb9bc749f28b..36c0081e3e8f8776293ae619156cd082
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index c7c53ef16e104ebc48aeb8719783fb4c45d39fc2..5bbb5cbb51953399c7bce547cd6968eb3c6bd130 100644
|
||||
index e63ac861b785cf3dccac25404454289c44b7ec9d..8b036640be655c65852e0862e30962e443d3024d 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -211,6 +211,20 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
@@ -565,7 +565,7 @@ index c7c53ef16e104ebc48aeb8719783fb4c45d39fc2..5bbb5cbb51953399c7bce547cd6968eb
|
||||
return this.getControlledVehicle() instanceof Mob riding ? riding.getMoveControl() : this.moveControl;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/PathfinderMob.java b/net/minecraft/world/entity/PathfinderMob.java
|
||||
index c4b4a135f61955c2b87801772a2b31eeeb77bf45..9d12cc2d169f243ba23485e2782bca7064282a36 100644
|
||||
index a19d8d4c0075340e8d187d5f8b6ce989567d3163..c661311dfdc1e21e3d6ec65e1e8b953637149675 100644
|
||||
--- a/net/minecraft/world/entity/PathfinderMob.java
|
||||
+++ b/net/minecraft/world/entity/PathfinderMob.java
|
||||
@@ -17,6 +17,8 @@ public abstract class PathfinderMob extends Mob {
|
||||
@@ -578,7 +578,7 @@ index c4b4a135f61955c2b87801772a2b31eeeb77bf45..9d12cc2d169f243ba23485e2782bca70
|
||||
return this.getWalkTargetValue(pos, this.level());
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
index 6bc2d38fb990628784deb5ee615e34a0fc320a47..844ced7a271ffb557f3c8f2fcd6a4c6ad499aeae 100644
|
||||
index c918154444a05917a3622947d0ddbc29bdb9bead..b13bdc2852504903fa054c42f89299a5d33dfbd3 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
@@ -24,6 +24,7 @@ public class GoalSelector {
|
||||
@@ -640,7 +640,7 @@ index d46e0e3a4a7fc3bb3f1dd695d4cc563778b99db0..c6e9b155c2341c13d569f28f54f0c1d2
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index c482c3348267ca2b88109e34291aa860e0cde916..b11b59d80e37d272770ab51a63028fdddfe800d6 100644
|
||||
index ca0b7ce4ab535d7112b315a7de1dc5130797ea2d..974d1d7b283aace71f0ea8ef07ba68a17b75af8a 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -124,6 +124,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
@@ -674,7 +674,7 @@ index c482c3348267ca2b88109e34291aa860e0cde916..b11b59d80e37d272770ab51a63028fdd
|
||||
public void tick() {
|
||||
if (this.getItem().isEmpty()) {
|
||||
diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
index a80e6a23cf29cb44943339101f15565dbc19af1f..26108ac0543c7b4195f149c07d8348b5b15b8bdb 100644
|
||||
index 084a4a945d4fc6a76878da00e5015c79fc88b47f..e4ba6e200e85f4e226d6a3e68db734f277b89226 100644
|
||||
--- a/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
@@ -244,11 +244,35 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
||||
@@ -779,7 +779,7 @@ index f3861c936855a0d9c9170585f4da4ce1cd77b854..3b4cbbc4c8ca1cd3110d1d6ba9e35312
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java b/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java
|
||||
index 3a590d4dc980a2912e9cc043d8c8db4cf9d60803..06ab7c48b18c03af494ab10fc2b584cefc776749 100644
|
||||
index f46cca0467bb4da5511bc953ce5b43fa606bf978..445c5cafad71028171c1f261939661775dd7f2bd 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java
|
||||
@@ -50,6 +50,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
|
||||
@@ -790,20 +790,21 @@ index 3a590d4dc980a2912e9cc043d8c8db4cf9d60803..06ab7c48b18c03af494ab10fc2b584ce
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
@@ -103,11 +104,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
|
||||
@@ -103,12 +104,14 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
|
||||
|
||||
public boolean suckInItems() {
|
||||
if (HopperBlockEntity.suckInItems(this.level(), this)) {
|
||||
+ this.immunize(); // Paper
|
||||
return true;
|
||||
} else {
|
||||
for (ItemEntity entity : this.level()
|
||||
.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.25, 0.0, 0.25), EntitySelector.ENTITY_STILL_ALIVE)) {
|
||||
if (HopperBlockEntity.addItem(this, entity)) {
|
||||
+ this.immunize(); // Paper
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemEntity entity : this.level()
|
||||
.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.25, 0.0, 0.25), EntitySelector.ENTITY_STILL_ALIVE)) {
|
||||
if (HopperBlockEntity.addItem(this, entity)) {
|
||||
+ this.immunize(); // Paper
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -142,4 +145,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
|
||||
public AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
||||
return new HopperMenu(containerId, inventory, this);
|
||||
@@ -817,7 +818,7 @@ index 3a590d4dc980a2912e9cc043d8c8db4cf9d60803..06ab7c48b18c03af494ab10fc2b584ce
|
||||
+
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index c0f901c4ac61a0aa2b480f102feb3669b111f4c0..07c301ba02c7f2c032a29a0ae3bdf95fc522c03b 100644
|
||||
index cc492445307ddc08446484d272866f01646cf7b3..a5d46832d4f8a13b0bf67b523c21d5c3b44209a9 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -155,6 +155,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -834,7 +835,7 @@ index c0f901c4ac61a0aa2b480f102feb3669b111f4c0..07c301ba02c7f2c032a29a0ae3bdf95f
|
||||
public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
|
||||
// Paper start - add paper world config
|
||||
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
index ec01093094f1d4de2708791ae6a5545268a021ae..f904c587fafe7395473450f766354d874e36ebac 100644
|
||||
index ef78f286ca14512c3dfccdb8fb06ebe9affa1589..c5c0b01c41055a82e49c1546d4525da0acce13a4 100644
|
||||
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
@@ -159,6 +159,10 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
|
||||
@@ -30,7 +30,7 @@ Additionally, this lets us avoid even allocating new objects for this too, furth
|
||||
reducing memory usage.
|
||||
|
||||
diff --git a/net/minecraft/world/phys/shapes/IndirectMerger.java b/net/minecraft/world/phys/shapes/IndirectMerger.java
|
||||
index 7e525297aaca8c18cf1669ab80040475029ff652..b342e4c0260fc5a64e5943e6342de0703233a99b 100644
|
||||
index 6c637af546a411d5790ceba9936aa9128d05d97e..e18f24a3941e1102648bac841851a8749f2d9438 100644
|
||||
--- a/net/minecraft/world/phys/shapes/IndirectMerger.java
|
||||
+++ b/net/minecraft/world/phys/shapes/IndirectMerger.java
|
||||
@@ -10,12 +10,32 @@ public class IndirectMerger implements IndexMerger {
|
||||
@@ -67,7 +67,7 @@ index 7e525297aaca8c18cf1669ab80040475029ff652..b342e4c0260fc5a64e5943e6342de070
|
||||
this.firstIndices = new int[capacity];
|
||||
this.secondIndices = new int[capacity];
|
||||
diff --git a/net/minecraft/world/phys/shapes/Shapes.java b/net/minecraft/world/phys/shapes/Shapes.java
|
||||
index de10ce3faa86d6ed6d528575a083722a8feedf8d..7574443bc098c1a0958b64f1f54e76322e48a2e7 100644
|
||||
index ccdaf6043f667b6983e4492cf570947ed5179df1..5c552f618d09fa9456195bbfa643ce4a1a03bd84 100644
|
||||
--- a/net/minecraft/world/phys/shapes/Shapes.java
|
||||
+++ b/net/minecraft/world/phys/shapes/Shapes.java
|
||||
@@ -343,11 +343,26 @@ public final class Shapes {
|
||||
@@ -117,9 +117,9 @@ index de10ce3faa86d6ed6d528575a083722a8feedf8d..7574443bc098c1a0958b64f1f54e7632
|
||||
} else if (second.getDouble(secondSize) < first.getDouble(0) - 1.0E-7) {
|
||||
return new NonOverlappingMerger(second, first, true);
|
||||
} else {
|
||||
- return (IndexMerger)(firstSize == secondSize && Objects.equals(first, second)
|
||||
- return firstSize == secondSize && Objects.equals(first, second)
|
||||
- ? new IdenticalMerger(first)
|
||||
- : new IndirectMerger(first, second, firstOnlyMatters, secondOnlyMatters));
|
||||
- : new IndirectMerger(first, second, firstOnlyMatters, secondOnlyMatters);
|
||||
+ return new IndirectMerger(first, second, firstOnlyMatters, secondOnlyMatters); // Paper - Identical happens more often than Disjoint
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ Subject: [PATCH] optimize dirt and snow spreading
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/SpreadingSnowyBlock.java b/net/minecraft/world/level/block/SpreadingSnowyBlock.java
|
||||
index 6695d7f76daf45ed3e73c4984326b8b59e5a76cc..f868b1ccfa0e373c47344d000f26fbe8507c3510 100644
|
||||
index 85666946f8cb23255360bca8efde2ce13abcbc0a..839bfdda7f54e6aabe401db6da1856544b032bf8 100644
|
||||
--- a/net/minecraft/world/level/block/SpreadingSnowyBlock.java
|
||||
+++ b/net/minecraft/world/level/block/SpreadingSnowyBlock.java
|
||||
@@ -27,8 +27,13 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
@@ -22,8 +22,8 @@ index 6695d7f76daf45ed3e73c4984326b8b59e5a76cc..f868b1ccfa0e373c47344d000f26fbe8
|
||||
+ BlockState aboveState = chunk.getBlockState(above); // Paper - Perf: optimize dirt and snow spreading
|
||||
if (aboveState.is(Blocks.SNOW) && aboveState.getValue(SnowLayerBlock.LAYERS) == 1) {
|
||||
return true;
|
||||
} else if (aboveState.getFluidState().isFull()) {
|
||||
@@ -40,8 +45,14 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
}
|
||||
@@ -42,8 +47,14 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
}
|
||||
|
||||
private static boolean canPropagate(final BlockState state, final LevelReader level, final BlockPos pos) {
|
||||
@@ -39,7 +39,7 @@ index 6695d7f76daf45ed3e73c4984326b8b59e5a76cc..f868b1ccfa0e373c47344d000f26fbe8
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,7 +61,14 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
@@ -52,7 +63,14 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
Registry<Block> blocks = level.registryAccess().lookupOrThrow(Registries.BLOCK);
|
||||
Optional<Block> baseBlock = blocks.getOptional(this.baseBlock);
|
||||
if (!baseBlock.isEmpty()) {
|
||||
@@ -55,7 +55,7 @@ index 6695d7f76daf45ed3e73c4984326b8b59e5a76cc..f868b1ccfa0e373c47344d000f26fbe8
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, baseBlock.get().defaultBlockState()).isCancelled()) {
|
||||
return;
|
||||
@@ -63,8 +81,20 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
@@ -65,8 +83,20 @@ public abstract class SpreadingSnowyBlock extends SnowyBlock {
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos testPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
|
||||
|
||||
+35
-34
@@ -86,7 +86,7 @@ index 0003a548fe4a48ecfe3534f3de309a920568b773..fae764ffd6858c920cafd2fba4444793
|
||||
+ // Paper end - Use Velocity cipher
|
||||
}
|
||||
diff --git a/net/minecraft/network/CompressionDecoder.java b/net/minecraft/network/CompressionDecoder.java
|
||||
index 2f660186f00414b37fa5c01d00c048173feaef13..fe3f0b59561e7b7236aba9cca2a13cee8955a933 100644
|
||||
index 8497561d90bf6165d1e56a044b3b409c234e1ef8..ddd5daf92d03dd343e6164d55fff638509175e6d 100644
|
||||
--- a/net/minecraft/network/CompressionDecoder.java
|
||||
+++ b/net/minecraft/network/CompressionDecoder.java
|
||||
@@ -12,14 +12,22 @@ import java.util.zip.Inflater;
|
||||
@@ -169,7 +169,7 @@ index 2f660186f00414b37fa5c01d00c048173feaef13..fe3f0b59561e7b7236aba9cca2a13cee
|
||||
this.validateDecompressed = validateDecompressed;
|
||||
}
|
||||
diff --git a/net/minecraft/network/CompressionEncoder.java b/net/minecraft/network/CompressionEncoder.java
|
||||
index 319325e741cc314b84844bb49ea569aaf014f319..20b5cfe1ce36d74cd6b2f95566a1bc34fc0aaa7f 100644
|
||||
index 595db570b0ade9cad7de77d2ab7b10d9e68699df..ac095f59d9f17d8239d6493d1c1e3942139b039f 100644
|
||||
--- a/net/minecraft/network/CompressionEncoder.java
|
||||
+++ b/net/minecraft/network/CompressionEncoder.java
|
||||
@@ -6,17 +6,30 @@ import io.netty.handler.codec.MessageToByteEncoder;
|
||||
@@ -207,33 +207,34 @@ index 319325e741cc314b84844bb49ea569aaf014f319..20b5cfe1ce36d74cd6b2f95566a1bc34
|
||||
int uncompressedLength = uncompressed.readableBytes();
|
||||
if (uncompressedLength > 8388608) {
|
||||
throw new IllegalArgumentException("Packet too big (is " + uncompressedLength + ", should be less than 8388608)");
|
||||
@@ -25,6 +38,7 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
VarInt.write(out, 0);
|
||||
out.writeBytes(uncompressed);
|
||||
} else {
|
||||
+ if (this.deflater != null) { // Paper - Use Velocity cipher
|
||||
byte[] input = new byte[uncompressedLength];
|
||||
uncompressed.readBytes(input);
|
||||
VarInt.write(out, input.length);
|
||||
@@ -37,6 +51,17 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
}
|
||||
|
||||
this.deflater.reset();
|
||||
+ // Paper start - Use Velocity cipher
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ VarInt.write(out, uncompressedLength);
|
||||
+ final ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(ctx.alloc(), this.compressor, uncompressed);
|
||||
+ try {
|
||||
+ this.compressor.deflate(compatibleIn, out);
|
||||
+ } finally {
|
||||
+ compatibleIn.release();
|
||||
+ }
|
||||
@@ -26,6 +39,7 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
VarInt.write(out, 0);
|
||||
out.writeBytes(uncompressed);
|
||||
} else {
|
||||
+ if (this.deflater != null) { // Paper - Use Velocity cipher
|
||||
byte[] input = new byte[uncompressedLength];
|
||||
uncompressed.readBytes(input);
|
||||
VarInt.write(out, input.length);
|
||||
@@ -38,6 +52,18 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
}
|
||||
|
||||
this.deflater.reset();
|
||||
+ // Paper start - Use Velocity cipher
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ VarInt.write(out, uncompressedLength);
|
||||
+ final ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(ctx.alloc(), this.compressor, uncompressed);
|
||||
+ try {
|
||||
+ this.compressor.deflate(compatibleIn, out);
|
||||
+ } finally {
|
||||
+ compatibleIn.release();
|
||||
+ }
|
||||
+ // Paper end - Use Velocity cipher
|
||||
}
|
||||
}
|
||||
@@ -48,4 +73,31 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
@@ -48,4 +74,31 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
public void setThreshold(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
@@ -266,10 +267,10 @@ index 319325e741cc314b84844bb49ea569aaf014f319..20b5cfe1ce36d74cd6b2f95566a1bc34
|
||||
+ // Paper end - Use Velocity cipher
|
||||
}
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 104976b3eb04d80e5be5bd020cf16c647b1cde27..5a23f95aff982ecc58d2e2bc994f4e495285069c 100644
|
||||
index d14aea970ce98edfe3dc3692e707334e7e150804..0f06d509125e72ec11d263d0d5c2179d65f6d8dd 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -740,11 +740,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -730,11 +730,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@@ -296,7 +297,7 @@ index 104976b3eb04d80e5be5bd020cf16c647b1cde27..5a23f95aff982ecc58d2e2bc994f4e49
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return this.encrypted;
|
||||
@@ -782,16 +793,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -772,16 +783,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
public void setupCompression(final int threshold, final boolean validateDecompressed) {
|
||||
if (threshold >= 0) {
|
||||
@@ -318,10 +319,10 @@ index 104976b3eb04d80e5be5bd020cf16c647b1cde27..5a23f95aff982ecc58d2e2bc994f4e49
|
||||
this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper - Add Channel initialization listeners
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/network/ServerConnectionListener.java b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index 391435cf3d279c8f5a889702b50f57626864c7bb..19a77c8269c3f1998985d533d9099c7e6cf76af4 100644
|
||||
index 6d506004583b2415ab356e34e2f8d6ac0e39cca2..474b7f06223514d95bad3d91356dfaa5435b77f5 100644
|
||||
--- a/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -77,6 +77,10 @@ public class ServerConnectionListener {
|
||||
@@ -76,6 +76,10 @@ public class ServerConnectionListener {
|
||||
LOGGER.warn("Using HAProxy, please ensure the server port is adequately firewalled.");
|
||||
}
|
||||
// Paper end - Warn people with console access that HAProxy is in use.
|
||||
@@ -333,7 +334,7 @@ index 391435cf3d279c8f5a889702b50f57626864c7bb..19a77c8269c3f1998985d533d9099c7e
|
||||
.add(
|
||||
new ServerBootstrap()
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index c1edad046cbdd1627edba58bc06aef5c058e79eb..3a0d47a716ce5c5345640ed67ac306101791892b 100644
|
||||
index 50e4f4037702875fe7755b169947abd800b06e7b..722c832ce18fd930d9fdb4f718dc13bfc962e5dd 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -251,11 +251,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@@ -346,6 +347,6 @@ index c1edad046cbdd1627edba58bc06aef5c058e79eb..3a0d47a716ce5c5345640ed67ac30610
|
||||
this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING;
|
||||
- this.connection.setEncryptionKey(decryptCipher, encryptCipher);
|
||||
+ this.connection.setEncryptionKey(secretKey); // Paper - Use Velocity cipher
|
||||
} catch (CryptException var7) {
|
||||
throw new IllegalStateException("Protocol error", var7);
|
||||
} catch (CryptException e) {
|
||||
throw new IllegalStateException("Protocol error", e);
|
||||
}
|
||||
+11
-14
@@ -7,7 +7,7 @@ Optimise the stream.anyMatch statement to move to a bitset
|
||||
where we can replace the call with a single bitwise operation.
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
|
||||
index 5746eefd9e8fa851e74ccf6b5d889a9f8e6fc1e0..81fa892212f586e8cd7938556eeaa9f9dc2654aa 100644
|
||||
index aa5f0e00daf26650b943a24676638581e494a112..60e0d618c603caef5e3516c9fdfc63ff45a7cdff 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/Goal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
|
||||
@@ -7,7 +7,15 @@ import net.minecraft.world.entity.Entity;
|
||||
@@ -69,7 +69,7 @@ index 5746eefd9e8fa851e74ccf6b5d889a9f8e6fc1e0..81fa892212f586e8cd7938556eeaa9f9
|
||||
// Paper end - Mob Goal API
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
index 844ced7a271ffb557f3c8f2fcd6a4c6ad499aeae..75d8953845b2e9acb62b19a859d0e39fd63533eb 100644
|
||||
index b13bdc2852504903fa054c42f89299a5d33dfbd3..1ddf8796d14d472bec48546f25ac4583d483c8e9 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
@@ -23,7 +23,8 @@ public class GoalSelector {
|
||||
@@ -119,27 +119,24 @@ index 844ced7a271ffb557f3c8f2fcd6a4c6ad499aeae..75d8953845b2e9acb62b19a859d0e39f
|
||||
goal.stop();
|
||||
}
|
||||
}
|
||||
@@ -95,11 +96,14 @@ public class GoalSelector {
|
||||
@@ -95,8 +96,14 @@ public class GoalSelector {
|
||||
profiler.push("goalUpdate");
|
||||
|
||||
for (WrappedGoal goalx : this.availableGoals) {
|
||||
- if (!goalx.isRunning()
|
||||
- && !goalContainsAnyFlags(goalx, this.disabledFlags)
|
||||
- && goalCanBeReplacedForAllFlags(goalx, this.lockedFlags)
|
||||
- && goalx.canUse()) {
|
||||
- for (Goal.Flag flag : goalx.getFlags()) {
|
||||
for (WrappedGoal goal : this.availableGoals) {
|
||||
- if (!goal.isRunning() && !goalContainsAnyFlags(goal, this.disabledFlags) && goalCanBeReplacedForAllFlags(goal, this.lockedFlags) && goal.canUse()) {
|
||||
- for (Goal.Flag flag : goal.getFlags()) {
|
||||
+ // Paper start
|
||||
+ if (!goalx.isRunning() && !goalContainsAnyFlags(goalx, this.goalTypes) && goalCanBeReplacedForAllFlags(goalx, this.lockedFlags) && goalx.canUse()) {
|
||||
+ long flagIterator = goalx.getFlags().getBackingSet();
|
||||
+ int wrappedGoalSize = goalx.getFlags().size();
|
||||
+ if (!goal.isRunning() && !goalContainsAnyFlags(goal, this.goalTypes) && goalCanBeReplacedForAllFlags(goal, this.lockedFlags) && goal.canUse()) {
|
||||
+ long flagIterator = goal.getFlags().getBackingSet();
|
||||
+ int wrappedGoalSize = goal.getFlags().size();
|
||||
+ for (int i = 0; i < wrappedGoalSize; ++i) {
|
||||
+ final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
|
||||
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
|
||||
+ // Paper end
|
||||
WrappedGoal currentGoal = this.lockedFlags.getOrDefault(flag, NO_GOAL);
|
||||
currentGoal.stop();
|
||||
this.lockedFlags.put(flag, goalx);
|
||||
@@ -131,11 +135,11 @@ public class GoalSelector {
|
||||
this.lockedFlags.put(flag, goal);
|
||||
@@ -128,11 +135,11 @@ public class GoalSelector {
|
||||
}
|
||||
|
||||
public void disableControlFlag(final Goal.Flag flag) {
|
||||
|
||||
@@ -7,7 +7,7 @@ Co-authored-by: Bjarne Koll <git@lynxplay.dev>
|
||||
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/net/minecraft/world/entity/ai/behavior/GateBehavior.java
|
||||
index 135d932a31a557ff06643fb563262423d48cd540..9fb025b05cacc901d72d93c16cf2b7e48d4dd9a6 100644
|
||||
index c16463febcf74e20e8e984bc19e3179a0f5f4ed1..3adfb334068d3722329f91011c41d5e59b1956c9 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/GateBehavior.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/GateBehavior.java
|
||||
@@ -69,7 +69,7 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
||||
@@ -57,7 +57,7 @@ index 135d932a31a557ff06643fb563262423d48cd540..9fb025b05cacc901d72d93c16cf2b7e4
|
||||
@Override
|
||||
@@ -118,24 +132,36 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
||||
|
||||
public static enum RunningPolicy {
|
||||
public enum RunningPolicy {
|
||||
RUN_ONE {
|
||||
+ // Paper start - Perf: Remove streams from hot code
|
||||
@Override
|
||||
@@ -98,7 +98,7 @@ index 135d932a31a557ff06643fb563262423d48cd540..9fb025b05cacc901d72d93c16cf2b7e4
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
|
||||
index 75233df622242db6c23f7a1a5812bf25942bca41..133aab614b102419ec731e901858c0347076bae9 100644
|
||||
index 600633670eb269ab1f4f50865942c46ed4c66fc6..9008b12745628fdcc225415e20e740192185bdd8 100644
|
||||
--- a/net/minecraft/world/entity/ai/gossip/GossipContainer.java
|
||||
+++ b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
|
||||
@@ -28,7 +28,7 @@ import net.minecraft.util.VisibleForDebug;
|
||||
@@ -133,7 +133,7 @@ index 75233df622242db6c23f7a1a5812bf25942bca41..133aab614b102419ec731e901858c034
|
||||
+ List<GossipContainer.GossipEntry> entries = this.decompress(); // Paper - Perf: Remove streams from hot code
|
||||
if (entries.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
}
|
||||
@@ -176,7 +190,23 @@ public class GossipContainer {
|
||||
private final Object2IntMap<GossipType> entries = new Object2IntOpenHashMap<>();
|
||||
|
||||
|
||||
+32
-31
@@ -16,25 +16,24 @@ This lets us get faster foreach iteration, as well as avoids map lookups on
|
||||
the values when needed.
|
||||
|
||||
diff --git a/net/minecraft/world/level/pathfinder/PathFinder.java b/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
index bb36ebf3a57cf1de98506a6391d3273b0f8e0f76..7564a67d2d63c3a7f95e1d6008e7308620653774 100644
|
||||
index 53aa6995d18cae5663d392e606c049e2e9138a99..253074a0a14115cd3d18aaae6fa5822cf32346c9 100644
|
||||
--- a/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
+++ b/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
@@ -54,8 +54,12 @@ public class PathFinder {
|
||||
if (from == null) {
|
||||
@@ -55,20 +55,24 @@ public class PathFinder {
|
||||
return null;
|
||||
} else {
|
||||
- Map<Target, BlockPos> tos = targets.stream()
|
||||
- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), Function.identity()));
|
||||
+ // Paper start - Perf: remove streams and optimize collection
|
||||
+ List<Map.Entry<Target, BlockPos>> tos = Lists.newArrayList();
|
||||
+ for (BlockPos pos : targets) {
|
||||
+ tos.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos));
|
||||
+ }
|
||||
+ // Paper end - Perf: remove streams and optimize collection
|
||||
Path path = this.findPath(from, tos, maxPathLength, reachRange, maxVisitedNodesMultiplier);
|
||||
this.nodeEvaluator.done();
|
||||
return path;
|
||||
@@ -63,12 +67,12 @@ public class PathFinder {
|
||||
}
|
||||
|
||||
- Map<Target, BlockPos> tos = targets.stream()
|
||||
- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), Function.identity()));
|
||||
+ // Paper start - Perf: remove streams and optimize collection
|
||||
+ List<Map.Entry<Target, BlockPos>> tos = Lists.newArrayList();
|
||||
+ for (BlockPos pos : targets) {
|
||||
+ tos.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos));
|
||||
+ }
|
||||
+ // Paper end - Perf: remove streams and optimize collection
|
||||
Path path = this.findPath(from, tos, maxPathLength, reachRange, maxVisitedNodesMultiplier);
|
||||
this.nodeEvaluator.done();
|
||||
return path;
|
||||
}
|
||||
|
||||
private @Nullable Path findPath(
|
||||
@@ -63,7 +62,7 @@ index bb36ebf3a57cf1de98506a6391d3273b0f8e0f76..7564a67d2d63c3a7f95e1d6008e73086
|
||||
current.closed = true;
|
||||
|
||||
- for (Target target : targets) {
|
||||
+ // Paper start - optimize collection
|
||||
+ // Paper start - Perf: remove streams and optimize collection
|
||||
+ for (int positionIndex = 0, size = targets.size(); positionIndex < size; positionIndex++) {
|
||||
+ final Map.Entry<Target, BlockPos> entry = targets.get(positionIndex);
|
||||
+ Target target = entry.getKey();
|
||||
@@ -75,17 +74,21 @@ index bb36ebf3a57cf1de98506a6391d3273b0f8e0f76..7564a67d2d63c3a7f95e1d6008e73086
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,34 +134,40 @@ public class PathFinder {
|
||||
@@ -126,34 +134,41 @@ public class PathFinder {
|
||||
}
|
||||
}
|
||||
|
||||
- Optional<Path> optPath = !reachedTargets.isEmpty()
|
||||
- ? reachedTargets.stream()
|
||||
- .map(targetx -> this.reconstructPath(targetx.getBestNode(), targetMap.get(targetx), true))
|
||||
- .map(target -> this.reconstructPath(target.getBestNode(), targetMap.get(target), true))
|
||||
- .min(Comparator.comparingInt(Path::getNodeCount))
|
||||
- : targets.stream()
|
||||
- .map(targetx -> this.reconstructPath(targetx.getBestNode(), targetMap.get(targetx), false))
|
||||
- .map(target -> this.reconstructPath(target.getBestNode(), targetMap.get(target), false))
|
||||
- .min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
|
||||
- profiler.pop();
|
||||
- if (optPath.isEmpty()) {
|
||||
- return null;
|
||||
+ // Paper start - Perf: remove streams and optimize collection
|
||||
+ Path best = null;
|
||||
+ boolean entryListIsEmpty = reachedTargets.isEmpty();
|
||||
+ Comparator<Path> comparator = entryListIsEmpty
|
||||
@@ -96,23 +99,21 @@ index bb36ebf3a57cf1de98506a6391d3273b0f8e0f76..7564a67d2d63c3a7f95e1d6008e73086
|
||||
+ if (best == null || comparator.compare(path, best) < 0) {
|
||||
+ best = path;
|
||||
+ }
|
||||
+ }
|
||||
profiler.pop();
|
||||
- if (optPath.isEmpty()) {
|
||||
- return null;
|
||||
- } else {
|
||||
- Path path = optPath.get();
|
||||
- if (captureDebug) {
|
||||
- path.setDebug(this.openSet.getHeap(), closedSet.toArray(Node[]::new), targets);
|
||||
}
|
||||
-
|
||||
- Path path = optPath.get();
|
||||
- if (captureDebug) {
|
||||
- path.setDebug(this.openSet.getHeap(), closedSet.toArray(Node[]::new), targets);
|
||||
+ profiler.pop();
|
||||
+ if (captureDebug && best != null) {
|
||||
+ Set<Target> set = Sets.newHashSet();
|
||||
+ for(Map.Entry<Target, BlockPos> entry : targets) {
|
||||
+ set.add(entry.getKey());
|
||||
}
|
||||
-
|
||||
- return path;
|
||||
+ }
|
||||
+ best.setDebug(this.openSet.getHeap(), closedSet.toArray(Node[]::new), set);
|
||||
}
|
||||
-
|
||||
- return path;
|
||||
+ return best;
|
||||
+ // Paper end - Perf: remove streams and optimize collection
|
||||
}
|
||||
|
||||
+3
-3
@@ -48,10 +48,10 @@ index cff05f64af7f425b77cbbd7680c5cc592faa798c..0ab4080c8e30d5ee14ce5fcbac64b031
|
||||
serverEntity.getLastSentYRot(),
|
||||
entity.getType(),
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 23ae1694c3d5fffdb2277316f66c5fd59157f5ca..be28a41084d656c44b611cf3a01ba89de610d5b2 100644
|
||||
index 7f879bc44354c9fac0238208db12b55a948982fb..55cfe38c0daa3ca71a71bf8c7d88fd613fabd82d 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1361,6 +1361,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
@@ -1357,6 +1357,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
ChunkMap.this.level.debugSynchronizers().startTrackingEntity(player, this.entity);
|
||||
}
|
||||
// Paper end - entity tracking events
|
||||
@@ -60,7 +60,7 @@ index 23ae1694c3d5fffdb2277316f66c5fd59157f5ca..be28a41084d656c44b611cf3a01ba89d
|
||||
} else {
|
||||
this.removePlayer(player);
|
||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||
index 6774d12d04fa848624fb8bf7a3c2b8bcb88f6e8f..19bb751d3e9c347fe2446412f85c9f28ec8212e6 100644
|
||||
index a62ec41b1319857f0d6cd223d013a92b1e2c2b0d..5fad52157fc22755196ce9eaddaa2bc23c5bb86b 100644
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -89,6 +89,13 @@ public class ServerEntity {
|
||||
|
||||
+5
-5
@@ -2321,7 +2321,7 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index f4bbccee849ee3711a3b838884e4bcf4e24da039..0b9fbf0ae658f0b3e9c6106a42fb70948b6fb9be 100644
|
||||
index 9fc39230f52f4cf6b44edd34aa9542b9d500538e..965d9f515d0410df3395d07c6cf5e6349c75c923 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -233,6 +233,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2347,10 +2347,10 @@ index f4bbccee849ee3711a3b838884e4bcf4e24da039..0b9fbf0ae658f0b3e9c6106a42fb7094
|
||||
return toLevel.dimension() != Level.NETHER || this.getGameRules().get(GameRules.ALLOW_ENTERING_NETHER_USING_PORTALS);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 07c301ba02c7f2c032a29a0ae3bdf95fc522c03b..7e4cf8a13e0ff2198cb7b6d80fb3fa343339943b 100644
|
||||
index 8d1d7582730e05bf605db31e13ee24242592074e..3d20ef3bc4e891e3e6e5f9f6f5efc6c0367369ea 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -2153,6 +2153,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -2156,6 +2156,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
return this.palettedContainerFactory;
|
||||
}
|
||||
|
||||
@@ -2365,11 +2365,11 @@ index 07c301ba02c7f2c032a29a0ae3bdf95fc522c03b..7e4cf8a13e0ff2198cb7b6d80fb3fa34
|
||||
+ }
|
||||
+ // Paper end - optimize redstone (Alternate Current)
|
||||
+
|
||||
public static enum ExplosionInteraction implements StringRepresentable {
|
||||
public enum ExplosionInteraction implements StringRepresentable {
|
||||
NONE("none"),
|
||||
BLOCK("block"),
|
||||
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index a00002774755eb90a0b772fe742b30a5e09452cf..1e863e97bd1dc99ed6e2c0602f78f457ac618965 100644
|
||||
index 5bdeaa9ae20de9f42e760d2207219d5f22d95e9b..0e285f38d282b29f625c5578ee1871a6c2b8585d 100644
|
||||
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -269,7 +269,7 @@ public class RedStoneWireBlock extends Block {
|
||||
|
||||
+8
-16
@@ -8,10 +8,10 @@ This ensures at least a valid version of the chunk exists
|
||||
on disk, even if outdated
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index d628e06a8dbf11b491b323c10a512fde22e72a12..fc712f9dbc893a6dee8ccecc54d0af07659dee62 100644
|
||||
index d39f8ae8f5736a7f4590ca41ac95792a61975baf..4d83986bccc2003b291dd93534da2d2260f6c428 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
|
||||
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
|
||||
|
||||
public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -19,7 +19,7 @@ index d628e06a8dbf11b491b323c10a512fde22e72a12..fc712f9dbc893a6dee8ccecc54d0af07
|
||||
private static final int SECTOR_BYTES = 4096;
|
||||
@VisibleForTesting
|
||||
protected static final int SECTOR_INTS = 1024;
|
||||
@@ -453,6 +454,24 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@@ -451,6 +452,24 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@@ -45,18 +45,10 @@ index d628e06a8dbf11b491b323c10a512fde22e72a12..fc712f9dbc893a6dee8ccecc54d0af07
|
||||
public void close() throws IOException {
|
||||
ByteBuffer result = ByteBuffer.wrap(this.buf, 0, this.count);
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index aa36e241d49725eb13f00e57d020d4da24add53d..5fa64ff30b8252f139ca7f77c14352c384c8c0e5 100644
|
||||
index 3d0a09662e5ed1f7bc0c02dbe6de529791f2f66f..fedec4d680934730d38d8c5d609fe216938b668a 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -16,6 +16,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.io.ChunkSystemRegionFileStorage { // Paper - rewrite chunk system
|
||||
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
|
||||
public static final String ANVIL_EXTENSION = ".mca";
|
||||
private static final int MAX_CACHE_SIZE = 256;
|
||||
public final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>();
|
||||
@@ -122,11 +123,24 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -123,11 +123,24 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// (and, the regionfile parameter is unused for writing until the write call)
|
||||
final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData writeData = ((ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile)regionFile).moonrise$startWrite(compound, pos);
|
||||
|
||||
@@ -81,7 +73,7 @@ index aa36e241d49725eb13f00e57d020d4da24add53d..5fa64ff30b8252f139ca7f77c14352c3
|
||||
|
||||
return writeData;
|
||||
}
|
||||
@@ -331,9 +345,18 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -325,9 +338,18 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
if (value == null) {
|
||||
region.clear(pos);
|
||||
} else {
|
||||
@@ -96,12 +88,12 @@ index aa36e241d49725eb13f00e57d020d4da24add53d..5fa64ff30b8252f139ca7f77c14352c3
|
||||
+ } catch (final RegionFileSizeException ex) {
|
||||
+ region.clear(pos);
|
||||
+ final int maxSize = RegionFile.MAX_CHUNK_SIZE / (1024 * 1024);
|
||||
+ LOGGER.error("Chunk at (" + pos.x() + "," + pos.z() + ") in regionfile '" + region.getPath().toString() + "' exceeds max size of " + maxSize + "MiB, it has been deleted from disk.");
|
||||
+ LOGGER.error("Chunk at ({},{}) in regionfile '{}' exceeds max size of {}MiB, it has been deleted from disk.", pos.x(), pos.z(), region.getPath().toString(), maxSize);
|
||||
+ // Paper end - don't write garbage data to disk if writing serialization fails
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,4 +399,13 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -370,4 +392,13 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
public RegionStorageInfo info() {
|
||||
return this.info;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ index 0cfdbdee091f43ca011bc68f7479eb7b84801b09..8d9ce3d301d5f7e4106587ae00adb8dd
|
||||
scopedCollector.forChild(entity.problemPath()), entity.registryAccess()
|
||||
);
|
||||
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
|
||||
index 2cdbb5f9bace96a8c4ad7fc4de17678ec0db8a6c..6b19f8cd8655cc52a0d8deadb9ca9f24473637a4 100644
|
||||
index a1ee86c18c17e14ebf98f0e72680543addc4c7fa..1ee78f52205cbb0b254a28999f3707ccccbe998e 100644
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -1647,7 +1647,18 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
|
||||
@@ -1641,7 +1641,18 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
|
||||
}
|
||||
|
||||
public static Stream<Entity> loadEntitiesRecursive(final ValueInput.ValueInputList entities, final Level level, final EntitySpawnReason reason) {
|
||||
@@ -56,10 +56,10 @@ index 2cdbb5f9bace96a8c4ad7fc4de17678ec0db8a6c..6b19f8cd8655cc52a0d8deadb9ca9f24
|
||||
return entity;
|
||||
}));
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java
|
||||
index 04045397dff89870316d0d374b9e472540c3298d..b1cd822c114b99a25fad2e649ca44596109aa0e5 100644
|
||||
index 0326b79fea3f563c3cdfa8f7cf1a3af0e4f08d38..4bd083ecdea207ee5689760fccc9ce8a5a958d57 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
|
||||
@@ -95,7 +95,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
|
||||
@@ -92,7 +92,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
|
||||
} else {
|
||||
try (ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(pos), LOGGER)) {
|
||||
ListTag entities = new ListTag();
|
||||
|
||||
+182
-173
@@ -55,10 +55,10 @@ index a6f9435a8e2a6c8cc05bd3873cb6fc0ec98973b8..d44fd9eea0ccb09c894d6431ede8a4c2
|
||||
this.used.set(position, position + size);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d88245e5baa69 100644
|
||||
index 4d83986bccc2003b291dd93534da2d2260f6c428..42d07aef0b2f646ec52ed6f4e7c003dbf82bd92d 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -47,6 +47,363 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@@ -46,6 +46,363 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@VisibleForTesting
|
||||
protected final RegionBitmap usedSectors = new RegionBitmap();
|
||||
|
||||
@@ -127,11 +127,11 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ private void backupRegionFile(Path to) {
|
||||
+ try {
|
||||
+ this.file.force(true);
|
||||
+ LOGGER.warn("Backing up regionfile \"" + this.path.toAbsolutePath() + "\" to " + to.toAbsolutePath());
|
||||
+ java.nio.file.Files.copy(this.path, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
|
||||
+ LOGGER.warn("Backed up the regionfile to " + to.toAbsolutePath());
|
||||
+ LOGGER.warn("Backing up regionfile \"{}\" to {}", this.path.toAbsolutePath(), to.toAbsolutePath());
|
||||
+ Files.copy(this.path, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
|
||||
+ LOGGER.warn("Backed up the regionfile to {}", to.toAbsolutePath());
|
||||
+ } catch (IOException ex) {
|
||||
+ LOGGER.error("Failed to backup to " + to.toAbsolutePath(), ex);
|
||||
+ LOGGER.error("Failed to backup to {}", to.toAbsolutePath(), ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@@ -152,13 +152,13 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ }
|
||||
+ ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.path);
|
||||
+ if (ourLowerLeftPosition == null) {
|
||||
+ LOGGER.error("Unable to get chunk location of regionfile " + this.path.toAbsolutePath() + ", cannot recover header");
|
||||
+ LOGGER.error("Unable to get chunk location of regionfile {}, cannot recover header", this.path.toAbsolutePath());
|
||||
+ return false;
|
||||
+ }
|
||||
+ synchronized (this) {
|
||||
+ this.recalculateCount.getAndIncrement();
|
||||
+
|
||||
+ LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.path.toAbsolutePath(), new Throwable());
|
||||
+ LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile {}", this.path.toAbsolutePath(), new Throwable());
|
||||
+
|
||||
+ // try to backup file so maybe it could be sent to us for further investigation
|
||||
+
|
||||
@@ -182,7 +182,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+
|
||||
+ ChunkPos chunkPos = SerializableChunkData.getChunkCoordinate(compound);
|
||||
+ if (!inSameRegionfile(ourLowerLeftPosition, chunkPos)) {
|
||||
+ LOGGER.error("Ignoring absolute chunk " + chunkPos + " in regionfile as it is not contained in the bounds of the regionfile '" + this.path.toAbsolutePath() + "'. It should be in regionfile (" + (chunkPos.x() >> 5) + "," + (chunkPos.z() >> 5) + ")");
|
||||
+ LOGGER.error("Ignoring absolute chunk {} in regionfile as it is not contained in the bounds of the regionfile '{}'. It should be in regionfile ({},{})", chunkPos, this.path.toAbsolutePath(), chunkPos.x() >> 5, chunkPos.z() >> 5);
|
||||
+ continue;
|
||||
+ }
|
||||
+ int location = (chunkPos.x() & 31) | ((chunkPos.z() & 31) << 5);
|
||||
@@ -204,7 +204,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ isAikarOversized = true;
|
||||
+ }
|
||||
+ } catch (Exception ex) {
|
||||
+ LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x() + "," + chunkPos.z() + ") in regionfile " + this.path.toAbsolutePath() + ", oversized data for this chunk will be lost", ex);
|
||||
+ LOGGER.error("Failed to read aikar oversized data for absolute chunk ({},{}) in regionfile {}, oversized data for this chunk will be lost", chunkPos.x(), chunkPos.z(), this.path.toAbsolutePath(), ex);
|
||||
+ // fall through, if we can't read aikar oversized we can't risk corrupting chunk data
|
||||
+ }
|
||||
+ }
|
||||
@@ -253,7 +253,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ try {
|
||||
+ chunkData = Files.readAllBytes(regionFile);
|
||||
+ } catch (Exception ex) {
|
||||
+ LOGGER.error("Failed to read oversized chunk data in file " + regionFile.toAbsolutePath() + ", data will be lost", ex);
|
||||
+ LOGGER.error("Failed to read oversized chunk data in file {}, data will be lost", regionFile.toAbsolutePath(), ex);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
@@ -273,12 +273,12 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ }
|
||||
+
|
||||
+ if (compound == null) {
|
||||
+ LOGGER.error("Failed to read oversized chunk data in file " + regionFile.toAbsolutePath() + ", it's corrupt. Its data will be lost");
|
||||
+ LOGGER.error("Failed to read oversized chunk data in file {}, it's corrupt. Its data will be lost", regionFile.toAbsolutePath());
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!SerializableChunkData.getChunkCoordinate(compound).equals(oversizedCoords)) {
|
||||
+ LOGGER.error("Can't use oversized chunk stored in " + regionFile.toAbsolutePath() + ", got absolute chunkpos: " + SerializableChunkData.getChunkCoordinate(compound) + ", expected " + oversizedCoords);
|
||||
+ LOGGER.error("Can't use oversized chunk stored in {}, got absolute chunkpos: {}, expected {}", regionFile.toAbsolutePath(), net.minecraft.world.level.chunk.storage.SerializableChunkData.getChunkCoordinate(compound), oversizedCoords);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
@@ -312,7 +312,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ if (newSectorAllocations.tryAllocate(sectorOffset, sectorLength)) {
|
||||
+ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized
|
||||
+ } else {
|
||||
+ LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + ", chunk will be regenerated");
|
||||
+ LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at ({},{}) in regionfile {}, chunk will be regenerated", chunkX, chunkZ, this.path.toAbsolutePath());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -336,7 +336,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized
|
||||
+ } catch (IOException ex) {
|
||||
+ newSectorAllocations.free(sectorOffset, sectorLength);
|
||||
+ LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + " will be regenerated");
|
||||
+ LOGGER.error("Failed to write new oversized chunk data holder, local chunk at ({},{}) in regionfile {} will be regenerated", chunkX, chunkZ, this.path.toAbsolutePath());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -358,7 +358,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ try {
|
||||
+ this.writeOversizedMeta();
|
||||
+ } catch (Exception ex) {
|
||||
+ LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.path.toAbsolutePath(), ex);
|
||||
+ LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile {}", this.path.toAbsolutePath(), ex);
|
||||
+ Files.deleteIfExists(this.getOversizedMetaFile());
|
||||
+ }
|
||||
+ } else {
|
||||
@@ -369,7 +369,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+
|
||||
+ // before we overwrite the old sectors, print a summary of the chunks that got changed.
|
||||
+
|
||||
+ LOGGER.info("Starting summary of changes for regionfile " + this.path.toAbsolutePath());
|
||||
+ LOGGER.info("Starting summary of changes for regionfile {}", this.path.toAbsolutePath());
|
||||
+
|
||||
+ for (int chunkX = 0; chunkX < 32; ++chunkX) {
|
||||
+ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) {
|
||||
@@ -386,16 +386,16 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+
|
||||
+ if (oldOffset == 0) {
|
||||
+ // found lost data
|
||||
+ LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath());
|
||||
+ LOGGER.info("Found missing data for local chunk ({},{}) in regionfile {}", chunkX, chunkZ, this.path.toAbsolutePath());
|
||||
+ } else if (newOffset == 0) {
|
||||
+ LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.path.toAbsolutePath() + ", it will be regenerated");
|
||||
+ LOGGER.warn("Data for local chunk ({},{}) could not be recovered in regionfile {}, it will be regenerated", chunkX, chunkZ, this.path.toAbsolutePath());
|
||||
+ } else {
|
||||
+ LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.path.toAbsolutePath());
|
||||
+ LOGGER.info("Local chunk ({},{}) changed to point to newer data or correct chunk in regionfile {}", chunkX, chunkZ, this.path.toAbsolutePath());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ LOGGER.info("End of change summary for regionfile " + this.path.toAbsolutePath());
|
||||
+ LOGGER.info("End of change summary for regionfile {}", this.path.toAbsolutePath());
|
||||
+
|
||||
+ // simply destroy the timestamp header, it's not used
|
||||
+
|
||||
@@ -407,9 +407,9 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ try {
|
||||
+ this.flush();
|
||||
+ this.file.force(true); // try to ensure it goes through...
|
||||
+ LOGGER.info("Successfully wrote new header to disk for regionfile " + this.path.toAbsolutePath());
|
||||
+ LOGGER.info("Successfully wrote new header to disk for regionfile {}", this.path.toAbsolutePath());
|
||||
+ } catch (IOException ex) {
|
||||
+ LOGGER.error("Failed to write new header to disk for regionfile " + this.path.toAbsolutePath(), ex);
|
||||
+ LOGGER.error("Failed to write new header to disk for regionfile {}", this.path.toAbsolutePath(), ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@@ -423,75 +423,58 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
@Override
|
||||
public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(final net.minecraft.nbt.CompoundTag data, final ChunkPos pos) throws IOException {
|
||||
@@ -75,6 +432,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
throw new IllegalArgumentException("Expected directory, got " + externalFileDir.toAbsolutePath());
|
||||
} else {
|
||||
this.externalFileDir = externalFileDir;
|
||||
+ this.canRecalcHeader = info.dfuType()[0] == net.minecraft.util.datafix.DataFixTypes.CHUNK; // Paper - add can recalc flag
|
||||
this.offsets = this.header.asIntBuffer();
|
||||
this.offsets.limit(1024);
|
||||
this.header.position(4096);
|
||||
}
|
||||
|
||||
this.externalFileDir = externalFileDir;
|
||||
+ this.canRecalcHeader = info.dfuType()[0] == net.minecraft.util.datafix.DataFixTypes.CHUNK; // Paper - add can recalc flag
|
||||
this.offsets = this.header.asIntBuffer();
|
||||
this.offsets.limit(1024);
|
||||
this.header.position(4096);
|
||||
@@ -95,11 +453,13 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
|
||||
long size = Files.size(path);
|
||||
long size = Files.size(path);
|
||||
|
||||
- for (int i = 0; i < 1024; i++) {
|
||||
+ boolean needsHeaderRecalc = false; // Paper - recalculate header on header corruption
|
||||
+ boolean hasBackedUp = false; // Paper - recalculate header on header corruption
|
||||
+ for (int i = 0; i < 1024; i++) { final int headerLocation = i; // Paper - we expect this to be the header location
|
||||
int offset = this.offsets.get(i);
|
||||
if (offset != 0) {
|
||||
- int sectorNumber = getSectorNumber(offset);
|
||||
- int numSectors = getNumSectors(offset);
|
||||
+ int sectorNumber = getSectorNumber(offset); // Paper - we expect this to be offset in file in sectors
|
||||
+ int numSectors = getNumSectors(offset); // Paper - diff on change, we expect this to be sector length of region - watch out for reassignments
|
||||
// Spigot start
|
||||
if (numSectors == 255) {
|
||||
// We're maxed out, so we need to read the proper length from the section
|
||||
- for (int i = 0; i < 1024; i++) {
|
||||
+ boolean needsHeaderRecalc = false; // Paper - recalculate header on header corruption
|
||||
+ boolean hasBackedUp = false; // Paper - recalculate header on header corruption
|
||||
+ for (int i = 0; i < 1024; i++) { final int headerLocation = i; // Paper - diff on change, we expect this to be the header location
|
||||
int offset = this.offsets.get(i);
|
||||
if (offset != 0) {
|
||||
- int sectorNumber = getSectorNumber(offset);
|
||||
- int numSectors = getNumSectors(offset);
|
||||
+ int sectorNumber = getSectorNumber(offset); // Paper - diff on change, we expect this to be offset in file in sectors
|
||||
+ int numSectors = getNumSectors(offset); // Paper - diff on change, we expect this to be sector length of region - watch out for reassignments
|
||||
// Spigot start
|
||||
if (numSectors == 255) {
|
||||
// We're maxed out, so we need to read the proper length from the section
|
||||
@@ -110,18 +470,62 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
// Spigot end
|
||||
if (sectorNumber < 2) {
|
||||
LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", path, i, sectorNumber);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if (numSectors == 0) {
|
||||
LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, i);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if (sectorNumber * 4096L > size) {
|
||||
LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", path, i, sectorNumber);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else {
|
||||
- this.usedSectors.force(sectorNumber, numSectors);
|
||||
+ //this.usedSectors.force(sectorNumber, numSectors); // Paper - move this down so we can check if it fails to allocate
|
||||
+ }
|
||||
+ // Paper start - recalculate header on header corruption
|
||||
+ if (sectorNumber < 2 || numSectors <= 0 || ((long)sectorNumber * 4096L) > size) {
|
||||
+ if (this.canRecalcHeader) {
|
||||
+ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() + "! Recalculating header...");
|
||||
+ needsHeaderRecalc = true;
|
||||
+ break;
|
||||
+ } else {
|
||||
+ // location = chunkX | (chunkZ << 5);
|
||||
+ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() +
|
||||
+ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
|
||||
+ if (!hasBackedUp) {
|
||||
+ hasBackedUp = true;
|
||||
+ this.backupRegionFile();
|
||||
+ }
|
||||
+ this.timestamps.put(headerLocation, 0); // be consistent, delete the timestamp too
|
||||
+ this.offsets.put(headerLocation, 0); // delete the entry from header
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
+ boolean failedToAllocate = !this.usedSectors.tryAllocate(sectorNumber, numSectors);
|
||||
+ if (failedToAllocate) {
|
||||
+ LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.path.toAbsolutePath());
|
||||
+ }
|
||||
+ if (failedToAllocate & !this.canRecalcHeader) {
|
||||
// Spigot end
|
||||
if (sectorNumber < 2) {
|
||||
LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", path, i, sectorNumber);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if (numSectors == 0) {
|
||||
LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, i);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if (sectorNumber * 4096L > size) {
|
||||
LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", path, i, sectorNumber);
|
||||
- this.offsets.put(i, 0);
|
||||
+ //this.offsets.put(i, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else {
|
||||
- this.usedSectors.force(sectorNumber, numSectors);
|
||||
+ //this.usedSectors.force(sectorNumber, numSectors); // Paper - move this down so we can check if it fails to allocate
|
||||
+ }
|
||||
+ // Paper start - recalculate header on header corruption
|
||||
+ if (sectorNumber < 2 || numSectors <= 0 || ((long)sectorNumber * 4096L) > size) {
|
||||
+ if (this.canRecalcHeader) {
|
||||
+ LOGGER.error("Detected invalid header for regionfile {}! Recalculating header...", this.path.toAbsolutePath());
|
||||
+ needsHeaderRecalc = true;
|
||||
+ break;
|
||||
+ } else {
|
||||
+ // location = chunkX | (chunkZ << 5);
|
||||
+ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() +
|
||||
+ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
|
||||
+ LOGGER.error("Detected invalid header for regionfile {}! Cannot recalculate, removing local chunk ({},{}) from header",
|
||||
+ this.path.toAbsolutePath(), headerLocation & 31, headerLocation >>> 5);
|
||||
+ if (!hasBackedUp) {
|
||||
+ hasBackedUp = true;
|
||||
+ this.backupRegionFile();
|
||||
@@ -500,21 +483,38 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
+ this.offsets.put(headerLocation, 0); // delete the entry from header
|
||||
+ continue;
|
||||
+ }
|
||||
+ needsHeaderRecalc |= failedToAllocate;
|
||||
+ // Paper end - recalculate header on header corruption
|
||||
+ }
|
||||
+ boolean failedToAllocate = !this.usedSectors.tryAllocate(sectorNumber, numSectors);
|
||||
+ if (failedToAllocate) {
|
||||
+ LOGGER.error("Overlapping allocation by local chunk ({},{}) in regionfile {}", headerLocation & 31, headerLocation >>> 5, this.path.toAbsolutePath());
|
||||
}
|
||||
+ if (failedToAllocate & !this.canRecalcHeader) {
|
||||
+ // location = chunkX | (chunkZ << 5);
|
||||
+ LOGGER.error("Detected invalid header for regionfile {}! Cannot recalculate, removing local chunk ({},{}) from header",
|
||||
+ this.path.toAbsolutePath(), headerLocation & 31, headerLocation >>> 5);
|
||||
+ if (!hasBackedUp) {
|
||||
+ hasBackedUp = true;
|
||||
+ this.backupRegionFile();
|
||||
+ }
|
||||
+ this.timestamps.put(headerLocation, 0); // be consistent, delete the timestamp too
|
||||
+ this.offsets.put(headerLocation, 0); // delete the entry from header
|
||||
+ continue;
|
||||
+ }
|
||||
+ needsHeaderRecalc |= failedToAllocate;
|
||||
+ // Paper end - recalculate header on header corruption
|
||||
}
|
||||
+ // Paper start - recalculate header on header corruption
|
||||
+ // we move the recalc here so comparison to old header is correct when logging to console
|
||||
+ if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues
|
||||
+ LOGGER.error("Recalculating regionfile " + this.path.toAbsolutePath() + ", header gave erroneous offsets & locations");
|
||||
+ this.recalculateHeader();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
+ // Paper start - recalculate header on header corruption
|
||||
+ // we move the recalc here so comparison to old header is correct when logging to console
|
||||
+ if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues
|
||||
+ LOGGER.error("Recalculating regionfile {}, header gave erroneous offsets & locations", this.path.toAbsolutePath());
|
||||
+ this.recalculateHeader();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
@@ -131,10 +535,34 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
|
||||
@@ -130,10 +534,34 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
|
||||
private Path getExternalChunkPath(final ChunkPos pos) {
|
||||
@@ -550,77 +550,79 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
public synchronized @Nullable DataInputStream getChunkDataInputStream(final ChunkPos pos) throws IOException {
|
||||
int offset = this.getOffset(pos);
|
||||
if (offset == 0) {
|
||||
@@ -155,30 +583,67 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
buffer.flip();
|
||||
if (buffer.remaining() < 5) {
|
||||
LOGGER.error("Chunk {} header is truncated: expected {} but read {}", pos, sectorsLength, buffer.remaining());
|
||||
@@ -155,6 +583,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
buffer.flip();
|
||||
if (buffer.remaining() < 5) {
|
||||
LOGGER.error("Chunk {} header is truncated: expected {} but read {}", pos, sectorsLength, buffer.remaining());
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -162,6 +595,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
byte versionId = buffer.get();
|
||||
if (length == 0) {
|
||||
LOGGER.warn("Chunk {} is allocated, but stream is missing", pos);
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -169,18 +607,45 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
if (isExternalStreamChunk(versionId)) {
|
||||
if (streamLength != 0) {
|
||||
LOGGER.warn("Chunk has both internal and external streams");
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else {
|
||||
int length = buffer.getInt();
|
||||
byte versionId = buffer.get();
|
||||
if (length == 0) {
|
||||
LOGGER.warn("Chunk {} is allocated, but stream is missing", pos);
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else {
|
||||
int streamLength = length - 1;
|
||||
if (isExternalStreamChunk(versionId)) {
|
||||
if (streamLength != 0) {
|
||||
LOGGER.warn("Chunk has both internal and external streams");
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
}
|
||||
|
||||
- return this.createExternalChunkInputStream(pos, getExternalChunkVersion(versionId));
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ final DataInputStream ret = this.createExternalChunkInputStream(pos, getExternalChunkVersion(versionId));
|
||||
+ if (ret == null && this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
} else if (streamLength > buffer.remaining()) {
|
||||
LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", pos, streamLength, buffer.remaining());
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else if (streamLength < 0) {
|
||||
LOGGER.error("Declared size {} of chunk {} is negative", length, pos);
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else {
|
||||
JvmProfiler.INSTANCE.onRegionFileRead(this.info, pos, this.version, streamLength);
|
||||
- return this.createChunkInputStream(pos, versionId, createStream(buffer, streamLength));
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ final DataInputStream ret = this.createChunkInputStream(pos, versionId, createStream(buffer, streamLength));
|
||||
+ if (ret == null && this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,9 +823,14 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
|
||||
- return this.createExternalChunkInputStream(pos, getExternalChunkVersion(versionId));
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ final DataInputStream ret = this.createExternalChunkInputStream(pos, getExternalChunkVersion(versionId));
|
||||
+ if (ret == null && this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
} else if (streamLength > buffer.remaining()) {
|
||||
LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", pos, streamLength, buffer.remaining());
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else if (streamLength < 0) {
|
||||
LOGGER.error("Declared size {} of chunk {} is negative", length, pos);
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ if (this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else {
|
||||
JvmProfiler.INSTANCE.onRegionFileRead(this.info, pos, this.version, streamLength);
|
||||
- return this.createChunkInputStream(pos, versionId, createStream(buffer, streamLength));
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ final DataInputStream ret = this.createChunkInputStream(pos, versionId, createStream(buffer, streamLength));
|
||||
+ if (ret == null && this.canRecalcHeader && this.recalculateHeader()) {
|
||||
+ return this.getChunkDataInputStream(pos);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,9 +822,14 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
|
||||
private ByteBuffer createExternalStub() {
|
||||
@@ -637,7 +639,7 @@ index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d8824
|
||||
return stub;
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 5fa64ff30b8252f139ca7f77c14352c384c8c0e5..eae4963b6d18c5f92871477b93f81c2c79331cd9 100644
|
||||
index fedec4d680934730d38d8c5d609fe216938b668a..e47a91b1869801258d0db20c126722fb06522c80 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -24,6 +24,32 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@@ -739,26 +741,33 @@ index 5fa64ff30b8252f139ca7f77c14352c384c8c0e5..eae4963b6d18c5f92871477b93f81c2c
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.Contract("_, false -> !null") private @Nullable RegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit
|
||||
@@ -313,6 +365,19 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
@@ -307,7 +359,25 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper end
|
||||
|
||||
var4 = NbtIo.read(regionChunkInputStream);
|
||||
try (DataInputStream regionChunkInputStream = region.getChunkDataInputStream(pos)) {
|
||||
- return regionChunkInputStream == null ? null : NbtIo.read(regionChunkInputStream);
|
||||
+ // Paper start - recover from corrupt regionfile header
|
||||
+ if (regionChunkInputStream == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final CompoundTag serialisedChunkData = NbtIo.read(regionChunkInputStream);
|
||||
+ if (this.isChunkData) {
|
||||
+ ChunkPos headerChunkPos = SerializableChunkData.getChunkCoordinate(var4);
|
||||
+ ChunkPos headerChunkPos = SerializableChunkData.getChunkCoordinate(serialisedChunkData);
|
||||
+ if (!headerChunkPos.equals(pos)) {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.error("Attempting to read chunk data at " + pos + " but got chunk data for " + headerChunkPos + " instead! Attempting regionfile recalculation for regionfile " + region.getPath().toAbsolutePath());
|
||||
+ LOGGER.error("Attempting to read chunk data at {} but got chunk data for {} instead! Attempting regionfile recalculation for regionfile {}", pos, headerChunkPos, region.getPath().toAbsolutePath());
|
||||
+ if (region.recalculateHeader()) {
|
||||
+ return this.read(pos);
|
||||
+ }
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.error("Can't recalculate regionfile header, regenerating chunk " + pos + " for " + region.getPath().toAbsolutePath());
|
||||
+ LOGGER.error("Can't recalculate regionfile header, regenerating chunk {} for {}", pos, region.getPath().toAbsolutePath());
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ return serialisedChunkData;
|
||||
+ // Paper end - recover from corrupt regionfile header
|
||||
}
|
||||
}
|
||||
|
||||
return var4;
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java b/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
index ea229f63f81c5638ded74c28e1e13d8948f2e5e0..d991fccfc3d2cc51611f802a6d40429024e21d9a 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
@@ -791,7 +800,7 @@ index 590bd1ca60956e5c5be58481f97401e55f9e1aeb..4e0c9fa1eecfa9f21285b7911e25830b
|
||||
return new RegionStorageInfo(this.level, this.dimension, this.type + suffix);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
index 1e0afa9590de7fe492cf29aded96be3db498c51e..df0bb06176ad5cce3ed8785d22d68b2dcbf5a8ca 100644
|
||||
index 2d326c3090a5d7621350347e131ee31d4715d3a7..98fb7a282a33f4391de124ed9be9bcf069178516 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
@@ -120,6 +120,18 @@ public record SerializableChunkData(
|
||||
@@ -813,7 +822,7 @@ index 1e0afa9590de7fe492cf29aded96be3db498c51e..df0bb06176ad5cce3ed8785d22d68b2d
|
||||
|
||||
// Paper start - Do not let the server load chunks from newer versions
|
||||
private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().dataVersion().version();
|
||||
@@ -544,7 +556,7 @@ public record SerializableChunkData(
|
||||
@@ -542,7 +554,7 @@ public record SerializableChunkData(
|
||||
tag.putInt("xPos", this.chunkPos.x());
|
||||
tag.putInt("yPos", this.minSectionY);
|
||||
tag.putInt("zPos", this.chunkPos.z());
|
||||
@@ -823,7 +832,7 @@ index 1e0afa9590de7fe492cf29aded96be3db498c51e..df0bb06176ad5cce3ed8785d22d68b2d
|
||||
tag.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(this.chunkStatus).toString());
|
||||
tag.storeNullable("blending_data", BlendingData.Packed.CODEC, this.blendingData);
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
index 6e55cb304fd9a5a01bbe7666dddb882e684cdcf1..6d954064f409ddd2cb7cfd0d0c428ac186f5ca4d 100644
|
||||
index df4f03f3a346e0ab0074757b3a077b2407135ac3..0b0265c8d4cb70aef758c1b443d007ef8d6c282b 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
@@ -34,6 +34,7 @@ public class SimpleRegionStorage implements ca.spottedleaf.moonrise.patches.chun
|
||||
|
||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67ae3a8bea 100644
|
||||
index 49be7709026cd75cfcb31715550387f0ba954a16..f9da26656b18327e3bcc1537a5f51e84b32cc43a 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -968,7 +968,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -961,7 +961,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
public boolean saveAllChunks(final boolean silent, final boolean flush, final boolean force, final boolean close) {
|
||||
// Paper end - add close param
|
||||
@@ -17,7 +17,7 @@ index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67
|
||||
boolean result = false;
|
||||
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
@@ -980,13 +980,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -973,13 +973,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
result = true;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67
|
||||
|
||||
if (flush) {
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
@@ -1000,11 +994,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -993,10 +987,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -51,15 +51,14 @@ index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67
|
||||
+ // Paper end - split out global level data
|
||||
+
|
||||
public boolean saveEverything(final boolean silent, final boolean flush, final boolean force) {
|
||||
boolean var5;
|
||||
try {
|
||||
this.isSaving = true;
|
||||
- this.getPlayerList().saveAll();
|
||||
+ this.getPlayerList().saveAll(); // Paper - Incremental chunk and player saving; diff on change
|
||||
boolean result = this.saveAllChunks(silent, flush, force);
|
||||
this.warnOnLowDiskSpace();
|
||||
var5 = result;
|
||||
@@ -1651,9 +1659,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return result;
|
||||
@@ -1641,9 +1649,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
this.ticksUntilAutosave--;
|
||||
@@ -94,7 +93,7 @@ index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
this.server.spark.executeMainThreadTasks(); // Paper - spark
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 0b9fbf0ae658f0b3e9c6106a42fb70948b6fb9be..bbeb0f673f2b23d1748e33364dc12ac16528d4c4 100644
|
||||
index 965d9f515d0410df3395d07c6cf5e6349c75c923..49f688e3536fe4fdb052bbfeeec36b5b8666b9b1 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1451,6 +1451,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -114,10 +113,10 @@ index 0b9fbf0ae658f0b3e9c6106a42fb70948b6fb9be..bbeb0f673f2b23d1748e33364dc12ac1
|
||||
public void save(final @Nullable ProgressListener progressListener, final boolean flush, final boolean noSave) {
|
||||
// Paper start - add close param
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 41816ca8d4ef3d959d2b88cd4b2eedaaa541e612..82e87270d1ad89ad7aa56e028ced6b998ea0eca5 100644
|
||||
index f35f88da81abb14b393d6fce04054ee40e8d8397..ec4ad547c2d09f7313390ac6b8a91809baab5f2e 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -205,6 +205,7 @@ import org.slf4j.Logger;
|
||||
@@ -204,6 +204,7 @@ import org.slf4j.Logger;
|
||||
|
||||
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -126,10 +125,10 @@ index 41816ca8d4ef3d959d2b88cd4b2eedaaa541e612..82e87270d1ad89ad7aa56e028ced6b99
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||
private static final int FLY_STAT_RECORDING_SPEED = 25;
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 02605ebe6ef10727badadbf7fc4cec52583df965..3d62e4d275f32c8604a1bdaefb6b9b1d4ea6e21f 100644
|
||||
index eb41400b8948d3eecc6fd89e2fefbe638ccbaad1..3c38b8cadcab6575fca0b7c3cf61287c3793f00f 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -418,6 +418,7 @@ public abstract class PlayerList {
|
||||
@@ -413,6 +413,7 @@ public abstract class PlayerList {
|
||||
|
||||
protected void save(final ServerPlayer player) {
|
||||
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
||||
@@ -137,7 +136,7 @@ index 02605ebe6ef10727badadbf7fc4cec52583df965..3d62e4d275f32c8604a1bdaefb6b9b1d
|
||||
this.playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats(); // CraftBukkit
|
||||
if (stats != null) {
|
||||
@@ -950,10 +951,24 @@ public abstract class PlayerList {
|
||||
@@ -947,10 +948,24 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
|
||||
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index fad017de5d9fc31988aa4edf97fb3f9bcbee56c8..06132bde0aed9dd9088c884ee31056b9176b6f90 100644
|
||||
index 2e9b47e87a1dc9f0713420414eda71eb6c03d898..3527559c9520e07646c7fb63fe27ad1b14f28da4 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -633,6 +633,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -108,7 +108,7 @@ index fad017de5d9fc31988aa4edf97fb3f9bcbee56c8..06132bde0aed9dd9088c884ee31056b9
|
||||
if (!allowMovement) {
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, false);
|
||||
@@ -1751,7 +1796,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1753,7 +1798,7 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
private boolean updateAwaitingTeleport() {
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
@@ -117,7 +117,7 @@ index fad017de5d9fc31988aa4edf97fb3f9bcbee56c8..06132bde0aed9dd9088c884ee31056b9
|
||||
this.awaitingTeleportTime = this.tickCount;
|
||||
this.teleport(
|
||||
this.awaitingPositionFromClient.x,
|
||||
@@ -1770,6 +1815,34 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1772,6 +1817,34 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ index d87a00ee3cd04ce25dbe46ae6b386b7f0799102c..ace440c2b82a6368aa27a85ff433ba2c
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index abeca4714053fd0a4fa489d496e2e0b844de40a8..7ed50fc00c58c7781c958df1d828a67adf696f3e 100644
|
||||
index f9be3e8cbc05fe74ac7816f8b2d81d52f6f23e40..8b194a59f79eea32c9e7a46227034942f6a6e816 100644
|
||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -39,12 +39,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -205,7 +205,7 @@ index abeca4714053fd0a4fa489d496e2e0b844de40a8..7ed50fc00c58c7781c958df1d828a67a
|
||||
- final long elapsedTime = now - this.keepAliveTime;
|
||||
- if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
|
||||
- if (this.keepAlivePending) {
|
||||
- if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
- if (elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT); // Paper - kick event cause
|
||||
- }
|
||||
- // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||
|
||||
@@ -20,11 +20,11 @@ index 2bc436cdf5180a7943c45fabb9fbbedae6f7db56..f312a7f5b1b2a777ab36b94ce7cbf387
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 8c4b40362f77cdea6e57315a6639006ac7ab27c7..a5217deb236ee922d020a7a6a03141a5f67acd77 100644
|
||||
index f9da26656b18327e3bcc1537a5f51e84b32cc43a..e69b540be1e0f0c699a57e07057cee74d4f8a771 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1794,32 +1794,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
@@ -1784,32 +1784,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return new ServerStatus.Players(maxPlayers, players.size(), sample);
|
||||
}
|
||||
|
||||
+ public final io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList entitySchedulerTickList = new io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList(); // Paper - optimise Folia entity scheduler
|
||||
@@ -66,10 +66,10 @@ index 8c4b40362f77cdea6e57315a6639006ac7ab27c7..a5217deb236ee922d020a7a6a03141a5
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index fea6c3b48c4eb162fbdc099fa775bc3161a4dd4e..82f6582a92f17bdeb3218c4c1fcac86981fd9c37 100644
|
||||
index 5e030ff471248f501d8bca6cfa6cc4161a580d4d..5d4ae462c60723291b1c72dc5b933cd04d31133b 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -5146,6 +5146,11 @@ public abstract class Entity
|
||||
@@ -5148,6 +5148,11 @@ public abstract class Entity
|
||||
this.getBukkitEntity().taskScheduler.retire();
|
||||
}
|
||||
// Paper end - Folia schedulers
|
||||
|
||||
@@ -42,10 +42,10 @@ index d2877c20f389d0131e1dd208b464f590671e5d82..27bdc70d861ca39487ad16cb3afb89d6
|
||||
updateComponent(root, "minecraft:trim", hiddenComponents);
|
||||
updateComponent(root, "minecraft:unbreakable", hiddenComponents);
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 06132bde0aed9dd9088c884ee31056b9176b6f90..08374da2d9b84e8ff13c670d7f45867fb0bdd897 100644
|
||||
index 3527559c9520e07646c7fb63fe27ad1b14f28da4..810b352503cdf56091ec6340ad72edde238fe359 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1819,9 +1819,14 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1821,9 +1821,14 @@ public class ServerGamePacketListenerImpl
|
||||
private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
|
||||
final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
||||
final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
|
||||
@@ -62,10 +62,10 @@ index 06132bde0aed9dd9088c884ee31056b9176b6f90..08374da2d9b84e8ff13c670d7f45867f
|
||||
);
|
||||
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index fa3809be5c0488c5a1d2639579d68619b0a55de9..c332d48f5cac2f3be93201c66f4f7cdba916cbac 100644
|
||||
index 3d20ef3bc4e891e3e6e5f9f6f5efc6c0367369ea..62c8650462a866dcdb3f06f781c7a8c716b0d912 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -1529,7 +1529,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -1528,7 +1528,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups)
|
||||
return false;
|
||||
// Paper start - optimise collisions
|
||||
|
||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Optional per player mob spawns
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index be28a41084d656c44b611cf3a01ba89de610d5b2..15d9c2d601a48d2288d5110f9991280129f43087 100644
|
||||
index 55cfe38c0daa3ca71a71bf8c7d88fd613fabd82d..2afc89ab4404cf04ba1da813f1c4a05baa4f44e3 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -238,11 +238,29 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
@@ -42,10 +42,10 @@ index be28a41084d656c44b611cf3a01ba89de610d5b2..15d9c2d601a48d2288d5110f99912801
|
||||
protected ChunkGenerator generator() {
|
||||
return this.worldGenContext.generator();
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index fcb23814c2539f4e31ed5191e03cc28f4e7f9c2d..0edfb9866ee2d0ff71394bc74f139fe3b4550c42 100644
|
||||
index a5685e0b50610cc8213f34c5db62b475bd54789b..a5023f6f7d912560f3488b1823ee22a1dc639203 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -537,9 +537,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -535,9 +535,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
private void tickChunks(final ProfilerFiller profiler, final long timeDiff) {
|
||||
profiler.push("naturalSpawnCount");
|
||||
int chunkCount = this.distanceManager.getNaturalSpawnChunkCount();
|
||||
@@ -67,7 +67,7 @@ index fcb23814c2539f4e31ed5191e03cc28f4e7f9c2d..0edfb9866ee2d0ff71394bc74f139fe3
|
||||
this.lastSpawnState = spawnCookie;
|
||||
boolean doMobSpawning = this.level.getGameRules().get(GameRules.SPAWN_MOBS) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
int tickSpeed = this.level.getGameRules().get(GameRules.RANDOM_TICK_SPEED);
|
||||
@@ -567,7 +576,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -565,7 +574,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
profiler.popPush("shuffleSpawningChunks");
|
||||
// Paper start - chunk tick iteration optimisation
|
||||
this.shuffleRandom.setSeed(this.level.getRandom().nextLong());
|
||||
@@ -77,10 +77,10 @@ index fcb23814c2539f4e31ed5191e03cc28f4e7f9c2d..0edfb9866ee2d0ff71394bc74f139fe3
|
||||
profiler.popPush("tickSpawningChunks");
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 82e87270d1ad89ad7aa56e028ced6b998ea0eca5..558abe7248725a58b5aa1a36c7e372824c0fbe2e 100644
|
||||
index c8dd908ea52305d7ae1235ea430a26c88306f183..85d22ea2e0fb7c59c387df056ace9ef556f489a2 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -430,6 +430,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -411,6 +411,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public boolean queueHealthUpdatePacket;
|
||||
public net.minecraft.network.protocol.game.@Nullable ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
// Paper end - cancellable death event
|
||||
@@ -92,7 +92,7 @@ index 82e87270d1ad89ad7aa56e028ced6b998ea0eca5..558abe7248725a58b5aa1a36c7e37282
|
||||
public @Nullable String lastKnownName; // Better rename detection
|
||||
public String displayName;
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 8ab7bdd487de7dbc5ea19d1f361ec52e367f8251..d9c1a04e53bec4a268ab58bfc8025c00bd3fa8ce 100644
|
||||
index c0a986932c25d056877e3147d09dd50d1264b13d..b1ecbc50ea908c6c11e9e1ae2f73d1eed669db08 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -70,6 +70,18 @@ public final class NaturalSpawner {
|
||||
|
||||
+6
-6
@@ -6,7 +6,7 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 15d9c2d601a48d2288d5110f9991280129f43087..01cbebd70223389c6d952be23e5d739579b96ead 100644
|
||||
index 2afc89ab4404cf04ba1da813f1c4a05baa4f44e3..42ec67c53c35189838ce4767c2be620e05108159 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -257,8 +257,25 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
@@ -37,10 +37,10 @@ index 15d9c2d601a48d2288d5110f9991280129f43087..01cbebd70223389c6d952be23e5d7395
|
||||
// Paper end - Optional per player mob spawns
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 0edfb9866ee2d0ff71394bc74f139fe3b4550c42..5a309dcf3c357f6b3a12d74aca2e9592f952318c 100644
|
||||
index a5023f6f7d912560f3488b1823ee22a1dc639203..0609c4e7ac7d027ed01684ab4fec2a7838f1f30f 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -542,7 +542,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -540,7 +540,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
||||
// re-set mob counts
|
||||
for (ServerPlayer player : this.level.players()) {
|
||||
@@ -60,10 +60,10 @@ index 0edfb9866ee2d0ff71394bc74f139fe3b4550c42..5a309dcf3c357f6b3a12d74aca2e9592
|
||||
spawnCookie = NaturalSpawner.createState(chunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 558abe7248725a58b5aa1a36c7e372824c0fbe2e..06b938013f9dbee4fb3b86979d5a42f28a0ea33e 100644
|
||||
index 85d22ea2e0fb7c59c387df056ace9ef556f489a2..d354517cbfdcee0648daa8f3eb035b2024d5ce72 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -434,6 +434,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -415,6 +415,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
|
||||
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
|
||||
// Paper end - Optional per player mob spawns
|
||||
@@ -72,7 +72,7 @@ index 558abe7248725a58b5aa1a36c7e372824c0fbe2e..06b938013f9dbee4fb3b86979d5a42f2
|
||||
public @Nullable String lastKnownName; // Better rename detection
|
||||
public String displayName;
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index d9c1a04e53bec4a268ab58bfc8025c00bd3fa8ce..427573fc142c107d3fcc2be9000316221039ba4c 100644
|
||||
index b1ecbc50ea908c6c11e9e1ae2f73d1eed669db08..9764163a32b0389afa50ba093d0647de04d5119e 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -307,6 +307,11 @@ public final class NaturalSpawner {
|
||||
|
||||
@@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index af1f5e83bd24e671399af2a9aadc8e11959ec5f4..b9efed1df74651c894a416f1d3db320d4ab20401 100644
|
||||
index e69b540be1e0f0c699a57e07057cee74d4f8a771..cc35c6271c98615a486422d0490145227626bd85 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1850,6 +1850,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1840,6 +1840,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
level.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
||||
level.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
||||
level.updateLagCompensationTick(); // Paper - lag compensation
|
||||
@@ -60,10 +60,10 @@ index af1f5e83bd24e671399af2a9aadc8e11959ec5f4..b9efed1df74651c894a416f1d3db320d
|
||||
profiler.push("tick");
|
||||
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index ee0fde839f06b6b900053b792617f3738b8000e8..54d67c847c1de9ee216cedb0527136f50223ea2d 100644
|
||||
index 95e0fb32457f2113de8d3e78fc18398bec83eccf..1d08ac66271a441811a157ed6619b14bf58c403f 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -807,10 +807,16 @@ public final class ItemStack implements DataComponentHolder, ItemInstance {
|
||||
@@ -807,11 +807,17 @@ public final class ItemStack implements DataComponentHolder, ItemInstance {
|
||||
}
|
||||
|
||||
public ItemStack copy() {
|
||||
@@ -76,17 +76,18 @@ index ee0fde839f06b6b900053b792617f3738b8000e8..54d67c847c1de9ee216cedb0527136f5
|
||||
+ if (!originalItem && this.isEmpty()) {
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
return EMPTY;
|
||||
} else {
|
||||
- ItemStack copy = new ItemStack(this.typeHolder(), this.count, this.components.copy());
|
||||
+ ItemStack copy = new ItemStack(originalItem ? this.item : this.typeHolder(), this.count, this.components.copy()); // Paper - Perf: Optimize Hoppers
|
||||
copy.setPopTime(this.getPopTime());
|
||||
return copy;
|
||||
}
|
||||
|
||||
- ItemStack copy = new ItemStack(this.typeHolder(), this.count, this.components.copy());
|
||||
+ ItemStack copy = new ItemStack(originalItem ? this.item : this.typeHolder(), this.count, this.components.copy()); // Paper - Perf: Optimize Hoppers
|
||||
copy.setPopTime(this.getPopTime());
|
||||
return copy;
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 04cfd03f29b319225011b86d459626a6872a5e87..865f08c92946010a36947b7766b957f4c0517285 100644
|
||||
index 0e2b537ff5230e6bdb55e9e99d6b2202479b8fd2..2c9fb60cae8065b1cd70d6ec53122cec9cf7f2a7 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -40,6 +40,7 @@ import org.jspecify.annotations.Nullable;
|
||||
@@ -39,6 +39,7 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class BlockEntity implements DebugValueSource, TypedInstance<BlockEntityType<?>> {
|
||||
@@ -94,7 +95,7 @@ index 04cfd03f29b319225011b86d459626a6872a5e87..865f08c92946010a36947b7766b957f4
|
||||
// CraftBukkit start - data containers
|
||||
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer;
|
||||
@@ -229,6 +230,7 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
||||
@@ -214,6 +215,7 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
||||
|
||||
public void setChanged() {
|
||||
if (this.level != null) {
|
||||
@@ -103,7 +104,7 @@ index 04cfd03f29b319225011b86d459626a6872a5e87..865f08c92946010a36947b7766b957f4
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b8522610a941 100644
|
||||
index 920eb74888c1692b93eb060f408004f145489d7c..ce6b64e00a0a13ebdceda56d975d79f60c26b86d 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -142,6 +142,43 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -150,27 +151,29 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
private static boolean tryMoveItems(
|
||||
final Level level, final BlockPos pos, final BlockState state, final HopperBlockEntity entity, final BooleanSupplier action
|
||||
) {
|
||||
@@ -150,12 +187,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
} else {
|
||||
if (!entity.isOnCooldown() && state.getValue(HopperBlock.ENABLED)) {
|
||||
boolean changed = false;
|
||||
- if (!entity.isEmpty()) {
|
||||
+ final int fullState = getFullState(entity); // Paper - Perf: Optimize Hoppers
|
||||
+ if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hoppers
|
||||
changed = ejectItems(level, pos, entity);
|
||||
}
|
||||
@@ -151,11 +188,12 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
- if (!entity.inventoryFull()) {
|
||||
- changed |= action.getAsBoolean();
|
||||
+ if (changed || fullState != HOPPER_IS_FULL) { // Paper - Perf: Optimize Hoppers
|
||||
+ changed |= action.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
||||
}
|
||||
if (!entity.isOnCooldown() && state.getValue(HopperBlock.ENABLED)) {
|
||||
boolean changed = false;
|
||||
- if (!entity.isEmpty()) {
|
||||
+ final int fullState = getFullState(entity); // Paper - Perf: Optimize Hoppers
|
||||
+ if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hoppers
|
||||
changed = ejectItems(level, pos, entity);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@@ -179,6 +217,206 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
- if (!entity.inventoryFull()) {
|
||||
+ if (changed || fullState != HOPPER_IS_FULL) { // Paper - Perf: Optimize Hoppers
|
||||
changed |= action.getAsBoolean();
|
||||
}
|
||||
|
||||
@@ -179,67 +217,218 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
return true;
|
||||
}
|
||||
|
||||
- private static boolean ejectItems(final Level level, final BlockPos blockPos, final HopperBlockEntity self) {
|
||||
- Container container = getAttachedContainer(level, blockPos, self);
|
||||
- if (container == null) {
|
||||
- return false;
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ public static boolean skipHopperEvents;
|
||||
+ private static boolean skipPullModeEventFire;
|
||||
@@ -214,13 +217,16 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
+ }
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ if (foundItem && level.paperConfig().hopper.cooldownWhenFull) { // Inventory was full - cooldown
|
||||
+ hopper.setCooldown(level.spigotConfig.hopperTransfer);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
|
||||
- Direction direction = self.facing.getOpposite();
|
||||
- if (isFullContainer(container, direction)) {
|
||||
- return false;
|
||||
+ private static boolean hopperPull(final Level level, final Hopper hopper, final Container container, ItemStack origItemStack, final int i) {
|
||||
+ ItemStack movedItem = origItemStack;
|
||||
+ final int originalItemCount = origItemStack.getCount();
|
||||
@@ -237,8 +243,27 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
+ // site for IMIE did not exhibit the same behavior
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
- for (int slot = 0; slot < self.getContainerSize(); slot++) {
|
||||
- ItemStack itemStack = self.getItem(slot);
|
||||
- if (!itemStack.isEmpty()) {
|
||||
- int originalCount = itemStack.getCount();
|
||||
- // CraftBukkit start - Call event when pushing items into other inventories
|
||||
- ItemStack original = itemStack.copy();
|
||||
- org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(
|
||||
- self.removeItem(slot, level.spigotConfig.hopperAmount)
|
||||
- ); // Spigot
|
||||
-
|
||||
- org.bukkit.inventory.Inventory destinationInventory;
|
||||
- // Have to special case large chests as they work oddly
|
||||
- if (container instanceof final net.minecraft.world.CompoundContainer compoundContainer) {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
|
||||
- } else if (container.getOwner() != null) {
|
||||
- destinationInventory = container.getOwner().getInventory();
|
||||
- } else {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventory(container);
|
||||
- }
|
||||
+ final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
||||
+ final int remainingItemCount = remainingItem.getCount();
|
||||
+ if (remainingItemCount != movedItemCount) {
|
||||
@@ -331,28 +356,49 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
+ blockEntity.setCooldown(blockEntity.getLevel().spigotConfig.hopperTransfer);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
||||
- org.bukkit.event.inventory.InventoryMoveItemEvent event = new org.bukkit.event.inventory.InventoryMoveItemEvent(
|
||||
- self.getOwner().getInventory(),
|
||||
- oitemstack,
|
||||
- destinationInventory,
|
||||
- true
|
||||
- );
|
||||
- if (!event.callEvent()) {
|
||||
- self.setItem(slot, original);
|
||||
- self.setCooldown(level.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
|
||||
+ private static boolean allMatch(Container container, Direction direction, java.util.function.BiPredicate<ItemStack, Integer> test) {
|
||||
+ if (container instanceof WorldlyContainer) {
|
||||
+ for (int slot : ((WorldlyContainer) container).getSlotsForFace(direction)) {
|
||||
+ if (container instanceof WorldlyContainer worldlyContainer) {
|
||||
+ for (int slot : worldlyContainer.getSlotsForFace(direction)) {
|
||||
+ if (!test.test(container.getItem(slot), slot)) {
|
||||
+ return false;
|
||||
+ }
|
||||
return false;
|
||||
}
|
||||
- int origCount = event.getItem().getAmount(); // Spigot
|
||||
- ItemStack result = HopperBlockEntity.addItem(self, container, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), direction);
|
||||
- // CraftBukkit end
|
||||
- if (result.isEmpty()) {
|
||||
- container.setChanged();
|
||||
- return true;
|
||||
+ }
|
||||
+ } else {
|
||||
+ int size = container.getContainerSize();
|
||||
+ for (int slot = 0; slot < size; slot++) {
|
||||
+ if (!test.test(container.getItem(slot), slot)) {
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
|
||||
- itemStack.setCount(originalCount);
|
||||
- // Spigot start
|
||||
- itemStack.shrink(origCount - result.getCount());
|
||||
- if (originalCount <= level.spigotConfig.hopperAmount) {
|
||||
- // Spigot end
|
||||
- self.setItem(slot, itemStack);
|
||||
+ private static boolean anyMatch(Container container, Direction direction, java.util.function.BiPredicate<ItemStack, Integer> test) {
|
||||
+ if (container instanceof WorldlyContainer) {
|
||||
+ for (int slot : ((WorldlyContainer) container).getSlotsForFace(direction)) {
|
||||
+ if (container instanceof WorldlyContainer worldlyContainer) {
|
||||
+ for (int slot : worldlyContainer.getSlotsForFace(direction)) {
|
||||
+ if (test.test(container.getItem(slot), slot)) {
|
||||
+ return true;
|
||||
+ }
|
||||
@@ -362,78 +408,32 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
+ for (int slot = 0; slot < size; slot++) {
|
||||
+ if (test.test(container.getItem(slot), slot)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ private static final java.util.function.BiPredicate<ItemStack, Integer> STACK_SIZE_TEST = (itemStack, i) -> itemStack.getCount() >= itemStack.getMaxStackSize();
|
||||
+ private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemStack, i) -> itemStack.isEmpty();
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
+
|
||||
private static boolean ejectItems(final Level level, final BlockPos blockPos, final HopperBlockEntity self) {
|
||||
Container container = getAttachedContainer(level, blockPos, self);
|
||||
if (container == null) {
|
||||
@@ -188,57 +426,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (isFullContainer(container, direction)) {
|
||||
return false;
|
||||
} else {
|
||||
- for (int slot = 0; slot < self.getContainerSize(); slot++) {
|
||||
- ItemStack itemStack = self.getItem(slot);
|
||||
- if (!itemStack.isEmpty()) {
|
||||
- int originalCount = itemStack.getCount();
|
||||
- // CraftBukkit start - Call event when pushing items into other inventories
|
||||
- ItemStack original = itemStack.copy();
|
||||
- org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(
|
||||
- self.removeItem(slot, level.spigotConfig.hopperAmount)
|
||||
- ); // Spigot
|
||||
-
|
||||
- org.bukkit.inventory.Inventory destinationInventory;
|
||||
- // Have to special case large chests as they work oddly
|
||||
- if (container instanceof final net.minecraft.world.CompoundContainer compoundContainer) {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
|
||||
- } else if (container.getOwner() != null) {
|
||||
- destinationInventory = container.getOwner().getInventory();
|
||||
- } else {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventory(container);
|
||||
- }
|
||||
-
|
||||
- org.bukkit.event.inventory.InventoryMoveItemEvent event = new org.bukkit.event.inventory.InventoryMoveItemEvent(
|
||||
- self.getOwner().getInventory(),
|
||||
- oitemstack,
|
||||
- destinationInventory,
|
||||
- true
|
||||
- );
|
||||
- if (!event.callEvent()) {
|
||||
- self.setItem(slot, original);
|
||||
- self.setCooldown(level.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
|
||||
- return false;
|
||||
- }
|
||||
- int origCount = event.getItem().getAmount(); // Spigot
|
||||
- ItemStack result = HopperBlockEntity.addItem(self, container, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), direction);
|
||||
- // CraftBukkit end
|
||||
-
|
||||
- if (result.isEmpty()) {
|
||||
- container.setChanged();
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- itemStack.setCount(originalCount);
|
||||
- // Spigot start
|
||||
- itemStack.shrink(origCount - result.getCount());
|
||||
- if (originalCount <= level.spigotConfig.hopperAmount) {
|
||||
- // Spigot end
|
||||
- self.setItem(slot, itemStack);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ return hopperPush(level, container, direction, self); // Paper - Perf: Optimize Hoppers
|
||||
}
|
||||
}
|
||||
}
|
||||
+ return true;
|
||||
+ }
|
||||
+ private static final java.util.function.BiPredicate<ItemStack, Integer> STACK_SIZE_TEST = (itemStack, _) -> itemStack.getCount() >= itemStack.getMaxStackSize();
|
||||
+ private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemStack, _) -> itemStack.isEmpty();
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
|
||||
- return false;
|
||||
+ private static boolean ejectItems(final Level level, final BlockPos blockPos, final HopperBlockEntity self) {
|
||||
+ Container container = getAttachedContainer(level, blockPos, self);
|
||||
+ if (container == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ Direction direction = self.facing.getOpposite();
|
||||
+ if (isFullContainer(container, direction)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return hopperPush(level, container, direction, self); // Paper - Perf: Optimize Hoppers
|
||||
}
|
||||
@@ -293,6 +481,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
private static int[] getSlots(final Container container, final Direction direction) {
|
||||
@@ -292,6 +481,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
Container container = getSourceContainer(level, hopper, blockPos, blockState);
|
||||
if (container != null) {
|
||||
Direction direction = Direction.DOWN;
|
||||
@@ -441,7 +441,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
|
||||
for (int slot : getSlots(container, direction)) {
|
||||
if (tryTakeInItemFromSlot(hopper, container, slot, direction, level)) { // Spigot
|
||||
@@ -320,54 +509,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -319,54 +509,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
private static boolean tryTakeInItemFromSlot(final Hopper hopper, final Container container, final int slot, final Direction direction, final Level level) { // Spigot
|
||||
ItemStack itemStack = container.getItem(slot);
|
||||
if (!itemStack.isEmpty() && canTakeItemFromContainer(hopper, container, itemStack, slot, direction)) {
|
||||
@@ -497,7 +497,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -376,13 +518,15 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -375,13 +518,15 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public static boolean addItem(final Container container, final ItemEntity entity) {
|
||||
boolean changed = false;
|
||||
// CraftBukkit start
|
||||
@@ -514,7 +514,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
ItemStack copy = entity.getItem().copy();
|
||||
ItemStack result = addItem(null, container, copy, null);
|
||||
if (result.isEmpty()) {
|
||||
@@ -441,7 +585,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -440,7 +585,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
itemStack = itemStack.split(container.getMaxStackSize());
|
||||
}
|
||||
// Spigot end
|
||||
@@ -524,7 +524,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
itemStack = leftover; // Paper - Make hoppers respect inventory max stack size
|
||||
success = true;
|
||||
} else if (canMergeItems(current, itemStack)) {
|
||||
@@ -527,14 +673,22 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -526,14 +673,22 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
|
||||
public static @Nullable Container getContainerAt(final Level level, final BlockPos pos) {
|
||||
@@ -549,7 +549,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
result = getEntityContainer(level, x, y, z);
|
||||
}
|
||||
|
||||
@@ -558,14 +712,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -559,14 +714,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
|
||||
private static @Nullable Container getEntityContainer(final Level level, final double x, final double y, final double z) {
|
||||
@@ -568,7 +568,7 @@ index 0703e50ca36fbc084ed06811678efd0eb7d26455..085ed0eecc47cf9c0fa9fc26b3f7b852
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
index 557ef92009f51b54e710f105254eb3e352c6057c..2270b5e5696ef65366c372b9606c5f03b6a11565 100644
|
||||
index 9ded208a6e3b86e24a36791f8bb74cec08cd6e9c..5019356f5f29be895d1b2ea8ee9a0e0f6f237a6a 100644
|
||||
--- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -52,7 +52,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
|
||||
@@ -55,7 +55,7 @@ index cde895c776c3077292c1a8381461075b1fbc45c7..b817e30a23a0030f948ff6c12175767f
|
||||
|
||||
if (buffer.writerIndex() != buffer.capacity()) {
|
||||
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
index 488d5654f5414c9950f19e86a791507366366e01..42bfd4b3b626ef66b0f2ef8438add5342b367800 100644
|
||||
index d7a1dde0452632d46fe594afa158cace71698de8..a52f93d0563f713b1d2b707cdb6ab74e4793a54d 100644
|
||||
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
@@ -41,13 +41,23 @@ public class ClientboundLevelChunkPacketData {
|
||||
@@ -155,7 +155,7 @@ index a94e6ca1d396b6b0781de5d550c4a804274ee003..a1018e9ca9dfb978d6e6633577abd7d5
|
||||
|
||||
private ClientboundLevelChunkWithLightPacket(final RegistryFriendlyByteBuf input) {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 4ac7ef5a1ed1fac04a9fd246212f59919deb498c..e562aec4366d7724f915e3dd5ae440a77e0947c5 100644
|
||||
index ac3c00ccb3025cd45beb3c6b96f11dad38f78366..a9a00f9be49344b17b27f64834102df3a323f03b 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -631,7 +631,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -168,10 +168,10 @@ index 4ac7ef5a1ed1fac04a9fd246212f59919deb498c..e562aec4366d7724f915e3dd5ae440a7
|
||||
this.weatherData.setLevel(this);
|
||||
this.typeKey = typeKey;
|
||||
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index f1faa0439bf5bce583e70ce37ade4b7e66daaaa4..f7390b91fe1866c6a11beb93711d0fcde4293164 100644
|
||||
index 837f8de90fddb5f458d44ee42ea11557463454c3..515dfa9c71333f68d6a42535f98977b5681eb407 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -321,6 +321,7 @@ public class ServerPlayerGameMode {
|
||||
@@ -320,6 +320,7 @@ public class ServerPlayerGameMode {
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelectedItem()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
@@ -196,10 +196,10 @@ index ec40f02032f965f548b0c0a29aa9d9bbad6f439b..373da9d604cfb1614a0618d856aefd2b
|
||||
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), connection.getPlayer().getBukkitEntity()).callEvent();
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 5e11abcfd681d86b1c0e282cf901108822766ce2..3020a3208b14bb483b08cf59a796fb83c2403d1c 100644
|
||||
index bab8c73be9537a1d531871b1b72bed87d2e0956e..02d19fc610e738f5ed12c23ab92bbdcbabaeced3 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -331,7 +331,7 @@ public abstract class PlayerList {
|
||||
@@ -330,7 +330,7 @@ public abstract class PlayerList {
|
||||
.getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
||||
player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
new net.minecraft.world.level.chunk.EmptyLevelChunk(level, player.chunkPosition(), plains),
|
||||
@@ -209,7 +209,7 @@ index 5e11abcfd681d86b1c0e282cf901108822766ce2..3020a3208b14bb483b08cf59a796fb83
|
||||
}
|
||||
// Paper end - Send empty chunk
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 829bb616e5d72b955248bbc150254c239176ce64..4b228b5c563e40b6f301df22b5c8a7f7988cb072 100644
|
||||
index 5a5f7cbc0217ab7aa034698802f634d149662da1..f4302e835fa9684d0fc7d6b65075ec3ec40f8f9f 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -145,6 +145,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -238,14 +238,14 @@ index 829bb616e5d72b955248bbc150254c239176ce64..4b228b5c563e40b6f301df22b5c8a7f7
|
||||
}
|
||||
|
||||
// Paper start - Cancel hit for vanished players
|
||||
@@ -1085,6 +1088,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
}
|
||||
// CraftBukkit end - capture blockstates
|
||||
BlockState oldState = chunk.setBlockState(pos, blockState, updateFlags);
|
||||
+ this.chunkPacketBlockController.onBlockChange(this, pos, blockState, oldState, updateFlags, updateLimit); // Paper - Anti-Xray
|
||||
if (oldState == null) {
|
||||
// CraftBukkit start - remove blockstate if failed (or the same)
|
||||
if (this.captureBlockStates && captured) {
|
||||
@@ -1088,6 +1091,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
}
|
||||
// CraftBukkit end - capture blockstates
|
||||
BlockState oldState = chunk.setBlockState(pos, blockState, updateFlags);
|
||||
+ this.chunkPacketBlockController.onBlockChange(this, pos, blockState, oldState, updateFlags, updateLimit); // Paper - Anti-Xray
|
||||
if (oldState == null) {
|
||||
// CraftBukkit start - remove blockstate if failed (or the same)
|
||||
if (this.captureBlockStates && captured) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
index c974b1c276d29610cb59566afaad19f5bcf0c602..c73b9871faa87493e081cb54e1bf1dce487359c6 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -273,10 +273,10 @@ index c974b1c276d29610cb59566afaad19f5bcf0c602..c73b9871faa87493e081cb54e1bf1dce
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index b5b514b292f9fdbe410aba5facec1638682c9075..595e97d2772b504eb6a08e84e4f4a138eb7c5f37 100644
|
||||
index 536c24ec46bdf571637376728aee06755a6256ef..b381c4d5a8b981f34852d029bbe46374d24f7879 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -152,7 +152,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
@@ -151,7 +151,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
final LevelChunk.@Nullable PostLoadProcessor postLoad,
|
||||
final @Nullable BlendingData blendingData
|
||||
) {
|
||||
@@ -286,10 +286,10 @@ index b5b514b292f9fdbe410aba5facec1638682c9075..595e97d2772b504eb6a08e84e4f4a138
|
||||
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index 398018ad7037669a756f804403fd76cf333a06de..d274149a977ed828b6bd02d88d2850521ede6c60 100644
|
||||
index 0e7bb7db9e46b2cade771fa5e94469023d8b47b0..0f807317cc7fa113ee57ab31f91bb6b8df7c4ae0 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -61,8 +61,14 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||
@@ -60,8 +60,14 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||
this.recalcBlockCounts();
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ index 398018ad7037669a756f804403fd76cf333a06de..d274149a977ed828b6bd02d88d285052
|
||||
this.biomes = containerFactory.createForBiomes();
|
||||
}
|
||||
|
||||
@@ -284,11 +290,17 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||
@@ -283,11 +289,17 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||
this.biomes = biomes;
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ index 398018ad7037669a756f804403fd76cf333a06de..d274149a977ed828b6bd02d88d285052
|
||||
|
||||
public int getSerializedSize() {
|
||||
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6953bf0b2 100644
|
||||
index 4eeb920e4e71ab91cdb5a41f1eabdd47182c80fb..66a05adab494f8674f0636f8b34533f8ef640028 100644
|
||||
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
@@ -26,6 +26,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
@@ -421,7 +421,7 @@ index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6
|
||||
this.data = this.createOrReuseData(null, 0);
|
||||
this.data.palette.idFor(initialValue, this);
|
||||
@@ -123,15 +169,39 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
}
|
||||
return new PalettedContainer.Data<>(dataConfiguration, storage, palette);
|
||||
}
|
||||
|
||||
+ // Paper start - Anti-Xray
|
||||
@@ -462,7 +462,7 @@ index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6
|
||||
|
||||
public synchronized T getAndSet(final int x, final int y, final int z, final T value) { // Paper - synchronize
|
||||
this.acquire();
|
||||
@@ -203,6 +273,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
@@ -200,6 +270,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
newData.palette.read(buffer, this.strategy.globalMap());
|
||||
buffer.readFixedSizeLongArray(newData.storage.getRaw());
|
||||
this.data = newData;
|
||||
@@ -470,7 +470,7 @@ index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6
|
||||
this.updateData(this.data); // Paper - optimise palette reads
|
||||
} finally {
|
||||
this.release();
|
||||
@@ -210,18 +281,31 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
@@ -207,18 +278,31 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -504,16 +504,16 @@ index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6
|
||||
List<T> paletteEntries = discData.paletteEntries();
|
||||
int entryCount = strategy.entryCount();
|
||||
Configuration storedConfiguration = strategy.getConfigurationForPaletteSize(paletteEntries.size());
|
||||
@@ -259,7 +343,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
}
|
||||
@@ -257,7 +341,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
}
|
||||
|
||||
- return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette));
|
||||
+ return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette, paletteEntries, defaultValue, presetValues)); // Paper - Anti-Xray - Add preset values
|
||||
}
|
||||
|
||||
- return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette));
|
||||
+ return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette, paletteEntries, defaultValue, presetValues)); // Paper - Anti-Xray - Add preset values
|
||||
}
|
||||
|
||||
@@ -329,12 +413,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
@Override
|
||||
@@ -323,12 +407,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
|
||||
@Override
|
||||
public PalettedContainer<T> copy() {
|
||||
@@ -528,7 +528,7 @@ index edf2990bfbe3d6b64eed85446eef207d2506efc5..09111c50cb34b643b7717f107a6f5bf6
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -404,9 +488,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
@@ -398,9 +482,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
return 1 + this.palette.getSerializedSize(globalMap) + this.storage.getRaw().length * 8;
|
||||
}
|
||||
|
||||
@@ -587,7 +587,7 @@ index 9977331d182cbc592f00006aabce23f0f69d2393..cd20a791b101548367ed53080f78e78b
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/PalettedContainerRO.java b/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
||||
index d2a2d435d0eda14a04f2c8582abffb8f98092a59..1498e9a760878f444debac9d4257d096731bb3ba 100644
|
||||
index 4607d2d7591a35d09d748d1ecf7582947bb86f39..f5f40aa2fd1b478045cb9a28b5ae11bc19f337f0 100644
|
||||
--- a/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
||||
+++ b/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
||||
@@ -14,7 +14,11 @@ public interface PalettedContainerRO<T> {
|
||||
@@ -603,7 +603,7 @@ index d2a2d435d0eda14a04f2c8582abffb8f98092a59..1498e9a760878f444debac9d4257d096
|
||||
int getSerializedSize();
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/Strategy.java b/net/minecraft/world/level/chunk/Strategy.java
|
||||
index 45ff1447312f239154930f748637f413e2ea8f87..a0f8b23612f8315eef2aaf4c036c2ec759aafa66 100644
|
||||
index 5c518b6ec7da546460884c37e9af682b6ab9fc22..958be147cd940ac430576ca5b4ada70fa5d051e3 100644
|
||||
--- a/net/minecraft/world/level/chunk/Strategy.java
|
||||
+++ b/net/minecraft/world/level/chunk/Strategy.java
|
||||
@@ -4,7 +4,7 @@ import net.minecraft.core.IdMap;
|
||||
@@ -616,7 +616,7 @@ index 45ff1447312f239154930f748637f413e2ea8f87..a0f8b23612f8315eef2aaf4c036c2ec7
|
||||
private static final Palette.Factory HASHMAP_PALETTE_FACTORY = HashMapPalette::create;
|
||||
private static final Configuration ZERO_BITS = new Configuration.Simple(SINGLE_VALUE_PALETTE_FACTORY, 0);
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
index df0bb06176ad5cce3ed8785d22d68b2dcbf5a8ca..9823f20186679d75444eff2b7a7b9cf8bb2ef575 100644
|
||||
index 98fb7a282a33f4391de124ed9be9bcf069178516..7d29fdc6548324d97ec34d476b5b48ec0bdba0d2 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
@@ -141,6 +141,7 @@ public record SerializableChunkData(
|
||||
@@ -626,17 +626,17 @@ index df0bb06176ad5cce3ed8785d22d68b2dcbf5a8ca..9823f20186679d75444eff2b7a7b9cf8
|
||||
+ net.minecraft.server.level.ServerLevel serverLevel = (net.minecraft.server.level.ServerLevel) levelHeight; // Paper - Anti-Xray This is is seemingly only called from ChunkMap, where, we have a server level. We'll fight this later if needed.
|
||||
if (chunkData.getString("Status").isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -201,9 +202,11 @@ public record SerializableChunkData(
|
||||
int y = sectionTag.getByteOr("Y", (byte)0);
|
||||
LevelChunkSection section;
|
||||
if (y >= levelHeight.getMinSectionY() && y <= levelHeight.getMaxSectionY()) {
|
||||
+ final BlockState[] presetBlockStates = serverLevel.chunkPacketBlockController.getPresetBlockStates(serverLevel, chunkPos, y); // Paper - Anti-Xray - Add preset block states
|
||||
+ final Codec<PalettedContainer<BlockState>> antiXrayBlockStateCodec = presetBlockStates == null ? blockStatesCodec : PalettedContainer.codecRW(BlockState.CODEC, containerFactory.blockStatesStrategy(), net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), presetBlockStates); // Paper - Anti-Xray
|
||||
PalettedContainer<BlockState> blocks = sectionTag.getCompound("block_states")
|
||||
.map(
|
||||
- container -> blockStatesCodec.parse(NbtOps.INSTANCE, container)
|
||||
+ container -> antiXrayBlockStateCodec.parse(NbtOps.INSTANCE, container) // Paper - Anti-Xray
|
||||
.promotePartial(msg -> logErrors(chunkPos, y, msg))
|
||||
.getOrThrow(SerializableChunkData.ChunkReadException::new)
|
||||
)
|
||||
}
|
||||
@@ -202,9 +203,11 @@ public record SerializableChunkData(
|
||||
int y = sectionTag.getByteOr("Y", (byte)0);
|
||||
LevelChunkSection section;
|
||||
if (y >= levelHeight.getMinSectionY() && y <= levelHeight.getMaxSectionY()) {
|
||||
+ final BlockState[] presetBlockStates = serverLevel.chunkPacketBlockController.getPresetBlockStates(serverLevel, chunkPos, y); // Paper - Anti-Xray - Add preset block states
|
||||
+ final Codec<PalettedContainer<BlockState>> antiXrayBlockStateCodec = presetBlockStates == null ? blockStatesCodec : PalettedContainer.codecRW(BlockState.CODEC, containerFactory.blockStatesStrategy(), net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), presetBlockStates); // Paper - Anti-Xray
|
||||
PalettedContainer<BlockState> blocks = sectionTag.getCompound("block_states")
|
||||
.map(
|
||||
- container -> blockStatesCodec.parse(NbtOps.INSTANCE, container)
|
||||
+ container -> antiXrayBlockStateCodec.parse(NbtOps.INSTANCE, container) // Paper - Anti-Xray
|
||||
.promotePartial(msg -> logErrors(chunkPos, y, msg))
|
||||
.getOrThrow(SerializableChunkData.ChunkReadException::new)
|
||||
)
|
||||
@@ -10,13 +10,13 @@ inside an entity status callback) or during shutdown (which has
|
||||
chunk loading restrictions due to the chunk system being halted).
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index 9eb6cb86ff70f04863cae3def1006f82bcb4fa6b..da5fdf77dd26d97c8b92bac9a6af8d922c31eb9c 100644
|
||||
index b39b8176d6b1a1d3f7058387518bcbb71a3631bb..5ba46020b47edfc886ecd5c33483ebb0fa57e5dc 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -66,6 +66,13 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
Objects.requireNonNull(BarrelBlockEntity.this);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,13 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
private static final Component DEFAULT_NAME = Component.translatable("container.barrel");
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
@@ -28,13 +28,13 @@ index 9eb6cb86ff70f04863cae3def1006f82bcb4fa6b..da5fdf77dd26d97c8b92bac9a6af8d92
|
||||
protected void onOpen(final Level level, final BlockPos pos, final BlockState state) {
|
||||
BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_OPEN);
|
||||
diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index 81a293cc13653a9a0336cb25d75273969fee4d16..8ebcce4c4971a11d367fb39e9c7fd280f63594e3 100644
|
||||
index 3635bd9e9b6292ff4389984eae1ae89ebca4be51..324f19786c4e298e706184045aea3e8ab98aaf46 100644
|
||||
--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -35,6 +35,13 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
Objects.requireNonNull(ChestBlockEntity.this);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,13 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
public static final Component DEFAULT_NAME = Component.translatable("container.chest");
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
@@ -100,13 +100,13 @@ index baa8b5aba0500981a191626553d66650c7304b88..52737172ccfa0c7c977e4f2fe1db242e
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
index eeac644f60760570244380d3c454fd33e37b5a7f..751625124a87de63d933d9c7809e46361e3136a5 100644
|
||||
index 592d253921d8adb168840edcc1b24b64969e80f2..551149b8888d78fc17b153a59532ed08e7f5724b 100644
|
||||
--- a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
@@ -18,6 +18,13 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity
|
||||
Objects.requireNonNull(EnderChestBlockEntity.this);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,13 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity {
|
||||
private final ChestLidController chestLidController = new ChestLidController();
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
|
||||
@@ -151,17 +151,17 @@ index 0000000000000000000000000000000000000000..f47c12e9dd6cfa857ca07a764edc22de
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/recipebook/ServerPlaceRecipe.java b/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
index 31f8aa58b48aeb64e57480490a449b6c46913880..b7ee9fe694ea37eeb58b5dded7967e7d0f338d0d 100644
|
||||
index da0380782a846dbb2657c58668e398f36f191c6e..d5ce83d5abd4de6f014a2827780170d3341eb927 100644
|
||||
--- a/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
+++ b/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
@@ -41,6 +41,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
return RecipeBookMenu.PostPlaceAction.NOTHING;
|
||||
} else {
|
||||
StackedItemContents availableItems = new StackedItemContents();
|
||||
+ availableItems.initializeExtras(recipe.value(), null); // Paper - Improve exact choice recipe ingredients
|
||||
inventory.fillStackedContents(availableItems);
|
||||
menu.fillCraftSlotsStackedContents(availableItems);
|
||||
return placer.tryPlaceRecipe(recipe, availableItems);
|
||||
@@ -42,6 +42,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
|
||||
StackedItemContents availableItems = new StackedItemContents();
|
||||
+ availableItems.initializeExtras(recipe.value(), null); // Paper - Improve exact choice recipe ingredients
|
||||
inventory.fillStackedContents(availableItems);
|
||||
menu.fillCraftSlotsStackedContents(availableItems);
|
||||
return placer.tryPlaceRecipe(recipe, availableItems);
|
||||
@@ -100,7 +101,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ index 31f8aa58b48aeb64e57480490a449b6c46913880..b7ee9fe694ea37eeb58b5dded7967e7d
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -165,7 +168,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
@@ -167,7 +170,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ index 31f8aa58b48aeb64e57480490a449b6c46913880..b7ee9fe694ea37eeb58b5dded7967e7d
|
||||
int inventorySlotId = this.inventory.findSlotMatchingCraftingIngredient(itemInInventory, itemInTargetSlot);
|
||||
if (inventorySlotId == Inventory.NOT_FOUND_INDEX) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index da8bab81e135a9b240fbeac0e9e1d2aa12c6212d..f004911c438e6f89d6e079437e3f4104d6cbacbd 100644
|
||||
index 5c083f2ec110c388be951014d8e5a6eb64ded371..cd7714dffcd7e7b6d96d18a97e65fd0914a739d1 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -252,12 +252,12 @@ public class Inventory implements Container, Nameable {
|
||||
@@ -225,10 +225,10 @@ index da8bab81e135a9b240fbeac0e9e1d2aa12c6212d..f004911c438e6f89d6e079437e3f4104
|
||||
return i;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedContents.java b/net/minecraft/world/entity/player/StackedContents.java
|
||||
index 889b8e6c3762203deccf657b505f6f29cc893526..6710653d033a48c4b3fc267496f93a2548b5c966 100644
|
||||
index 2a8527a2712de71f4c0d6a2e5af8dd3c01b8ff0a..5982b79f6b391ac9c01c452747fc235faf78369e 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedContents.java
|
||||
@@ -14,7 +14,7 @@ import java.util.Objects;
|
||||
@@ -13,7 +13,7 @@ import java.util.List;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class StackedContents<T> {
|
||||
@@ -237,7 +237,7 @@ index 889b8e6c3762203deccf657b505f6f29cc893526..6710653d033a48c4b3fc267496f93a25
|
||||
|
||||
private boolean hasAtLeast(final T item, final int count) {
|
||||
return this.amounts.getInt(item) >= count;
|
||||
@@ -54,7 +54,7 @@ public class StackedContents<T> {
|
||||
@@ -53,7 +53,7 @@ public class StackedContents<T> {
|
||||
private List<T> getUniqueAvailableIngredientItems(final Iterable<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
List<T> result = new ArrayList<>();
|
||||
|
||||
@@ -246,7 +246,7 @@ index 889b8e6c3762203deccf657b505f6f29cc893526..6710653d033a48c4b3fc267496f93a25
|
||||
if (availableItem.getIntValue() > 0 && anyIngredientMatches(ingredients, availableItem.getKey())) {
|
||||
result.add(availableItem.getKey());
|
||||
}
|
||||
@@ -76,13 +76,13 @@ public class StackedContents<T> {
|
||||
@@ -75,13 +75,13 @@ public class StackedContents<T> {
|
||||
@VisibleForTesting
|
||||
public int getResultUpperBound(final List<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
@@ -344,7 +344,7 @@ index ffaa8e450a11a01060b6847d1b66a76323f9d8ba..1ace17d8fc7e7b8b4722a1889d49233c
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/item/crafting/Ingredient.java b/net/minecraft/world/item/crafting/Ingredient.java
|
||||
index 3a8a07712a15167dabd12d4bfd258de11706ce93..1deeb3fd148c5d59250346147681b7e8f2147574 100644
|
||||
index 653fb104bb51fb738aa3ad22093c24f196f33df2..d4601c6a77f89d89ac9f042ee7b8c25461409523 100644
|
||||
--- a/net/minecraft/world/item/crafting/Ingredient.java
|
||||
+++ b/net/minecraft/world/item/crafting/Ingredient.java
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.item.Items;
|
||||
@@ -383,7 +383,7 @@ index 3a8a07712a15167dabd12d4bfd258de11706ce93..1deeb3fd148c5d59250346147681b7e8
|
||||
return ingredient;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -79,21 +83,22 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
@@ -81,21 +85,22 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
public boolean test(final ItemStack input) {
|
||||
// CraftBukkit start
|
||||
if (this.isExact()) {
|
||||
@@ -415,7 +415,7 @@ index 3a8a07712a15167dabd12d4bfd258de11706ce93..1deeb3fd148c5d59250346147681b7e8
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,6 +123,11 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
@@ -120,6 +125,11 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
}
|
||||
|
||||
public SlotDisplay display() {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
--- a/com/mojang/math/OctahedralGroup.java
|
||||
+++ b/com/mojang/math/OctahedralGroup.java
|
||||
@@ -99,6 +_,12 @@
|
||||
@@ -99,6 +_,14 @@
|
||||
.map(f -> Arrays.stream(values()).filter(s -> f.compose(s) == IDENTITY).findAny().get())
|
||||
.toArray(OctahedralGroup[]::new);
|
||||
|
||||
+ // Paper start - Avoid Lazy Initialization for Enum Fields
|
||||
+ static {
|
||||
+ for (OctahedralGroup octahedralGroup : values()) {
|
||||
+ octahedralGroup.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
|
||||
+ octahedralGroup.initializeRotationDirections();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Avoid Lazy Initialization for Enum Fields
|
||||
+
|
||||
private OctahedralGroup(final String name, final SymmetricGroup3 permutation, final boolean invertX, final boolean invertY, final boolean invertZ) {
|
||||
OctahedralGroup(final String name, final SymmetricGroup3 permutation, final boolean invertX, final boolean invertY, final boolean invertZ) {
|
||||
this.name = name;
|
||||
this.invertX = invertX;
|
||||
@@ -139,7 +_,7 @@
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@@ -217,7 +_,7 @@
|
||||
@@ -214,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static void preload() {
|
||||
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/advancements/criterion/LocationPredicate.java
|
||||
+++ b/net/minecraft/advancements/criterion/LocationPredicate.java
|
||||
@@ -44,7 +_,7 @@
|
||||
public boolean matches(final ServerLevel level, final double x, final double y, final double z) {
|
||||
if (this.position.isPresent() && !this.position.get().matches(x, y, z)) {
|
||||
@@ -46,7 +_,7 @@
|
||||
return false;
|
||||
- } else if (this.dimension.isPresent() && this.dimension.get() != level.dimension()) {
|
||||
+ } else if (this.dimension.isPresent() && this.dimension.get() != (io.papermc.paper.configuration.GlobalConfiguration.get().misc.strictAdvancementDimensionCheck ? level.dimension() : org.bukkit.craftbukkit.util.CraftDimensionUtil.getMainDimensionKey(level))) { // Paper - Add option for strict advancement dimension checks
|
||||
}
|
||||
|
||||
- if (this.dimension.isPresent() && this.dimension.get() != level.dimension()) {
|
||||
+ if (this.dimension.isPresent() && this.dimension.get() != (io.papermc.paper.configuration.GlobalConfiguration.get().misc.strictAdvancementDimensionCheck ? level.dimension() : org.bukkit.craftbukkit.util.CraftDimensionUtil.getMainDimensionKey(level))) { // Paper - Add option for strict advancement dimension checks
|
||||
return false;
|
||||
} else {
|
||||
BlockPos pos = BlockPos.containing(x, y, z);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -157,6 +_,7 @@
|
||||
@@ -156,6 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class Commands {
|
||||
@@ -8,7 +8,7 @@
|
||||
public static final String COMMAND_PREFIX = "/";
|
||||
private static final ThreadLocal<@Nullable ExecutionContext<CommandSourceStack>> CURRENT_EXECUTION_CONTEXT = new ThreadLocal<>();
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -181,6 +_,7 @@
|
||||
@@ -180,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean isRestricted(final CommandNode<CommandSourceStack> node) {
|
||||
@@ -16,7 +16,7 @@
|
||||
Predicate<CommandSourceStack> requirement = node.getRequirement();
|
||||
return !requirement.test(this.noPermissionSource);
|
||||
}
|
||||
@@ -188,6 +_,11 @@
|
||||
@@ -187,6 +_,11 @@
|
||||
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
|
||||
|
||||
public Commands(final Commands.CommandSelection commandSelection, final CommandBuildContext context) {
|
||||
@@ -28,7 +28,7 @@
|
||||
AdvancementCommands.register(this.dispatcher);
|
||||
AttributeCommand.register(this.dispatcher, context);
|
||||
ExecuteCommand.register(this.dispatcher, context);
|
||||
@@ -299,6 +_,42 @@
|
||||
@@ -298,6 +_,42 @@
|
||||
PublishCommand.register(this.dispatcher);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
|
||||
}
|
||||
|
||||
@@ -318,6 +_,13 @@
|
||||
@@ -317,6 +_,13 @@
|
||||
}
|
||||
|
||||
public void performCommand(final ParseResults<CommandSourceStack> command, final String commandString) {
|
||||
@@ -85,36 +85,36 @@
|
||||
CommandSourceStack sender = command.getContext().getSource();
|
||||
Profiler.get().push(() -> "/" + commandString);
|
||||
ContextChain<CommandSourceStack> commandChain = finishParsing(command, commandString, sender);
|
||||
@@ -331,10 +_,12 @@
|
||||
@@ -330,10 +_,12 @@
|
||||
)
|
||||
);
|
||||
}
|
||||
- } catch (Exception var12) {
|
||||
- } catch (Exception e) {
|
||||
+ // Paper start
|
||||
+ } catch (Throwable var12) { // always gracefully handle it, no matter how bad:tm:
|
||||
+ if (throwCommandError) throw var12; // rethrow directly if requested
|
||||
MutableComponent hover = Component.literal(var12.getMessage() == null ? var12.getClass().getName() : var12.getMessage());
|
||||
+ } catch (Throwable e) { // always gracefully handle it, no matter how bad:tm:
|
||||
+ if (throwCommandError) throw e; // rethrow directly if requested
|
||||
MutableComponent hover = Component.literal(e.getMessage() == null ? e.getClass().getName() : e.getMessage());
|
||||
- if (LOGGER.isDebugEnabled()) {
|
||||
- LOGGER.error("Command exception: /{}", commandString, var12);
|
||||
+ LOGGER.error("Command exception: /{}", commandString, var12); // Paper - always show execution exception in console log
|
||||
- LOGGER.error("Command exception: /{}", commandString, e);
|
||||
+ LOGGER.error("Command exception: /{}", commandString, e); // Paper - always show execution exception in console log
|
||||
+ if (sender.getServer().isDebugging() || LOGGER.isDebugEnabled()) { // Paper - Debugging
|
||||
StackTraceElement[] stackTrace = var12.getStackTrace();
|
||||
StackTraceElement[] stackTrace = e.getStackTrace();
|
||||
|
||||
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
|
||||
@@ -365,7 +_,11 @@
|
||||
@@ -364,7 +_,11 @@
|
||||
return ContextChain.tryFlatten(command.getContext().build(commandString))
|
||||
.orElseThrow(() -> CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(command.getReader()));
|
||||
} catch (CommandSyntaxException var7) {
|
||||
- sender.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage()));
|
||||
} catch (CommandSyntaxException e) {
|
||||
- sender.sendFailure(ComponentUtils.fromMessage(e.getRawMessage()));
|
||||
+ // Paper start - Add UnknownCommandEvent
|
||||
+ final net.kyori.adventure.text.TextComponent.Builder builder = net.kyori.adventure.text.Component.text();
|
||||
+ // sender.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage()));
|
||||
+ builder.color(net.kyori.adventure.text.format.NamedTextColor.RED).append(io.papermc.paper.command.brigadier.MessageComponentSerializer.message().deserialize(var7.getRawMessage()));
|
||||
+ builder.color(net.kyori.adventure.text.format.NamedTextColor.RED).append(io.papermc.paper.command.brigadier.MessageComponentSerializer.message().deserialize(e.getRawMessage()));
|
||||
+ // Paper end - Add UnknownCommandEvent
|
||||
if (var7.getInput() != null && var7.getCursor() >= 0) {
|
||||
int cursor = Math.min(var7.getInput().length(), var7.getCursor());
|
||||
if (e.getInput() != null && e.getCursor() >= 0) {
|
||||
int cursor = Math.min(e.getInput().length(), e.getCursor());
|
||||
MutableComponent context = Component.empty()
|
||||
@@ -382,7 +_,17 @@
|
||||
@@ -381,7 +_,17 @@
|
||||
}
|
||||
|
||||
context.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
|
||||
@@ -133,7 +133,7 @@
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -410,19 +_,112 @@
|
||||
@@ -409,19 +_,112 @@
|
||||
}
|
||||
|
||||
public void sendCommands(final ServerPlayer player) {
|
||||
@@ -249,7 +249,7 @@
|
||||
if (builder.getRedirect() != null) {
|
||||
builder.redirect(converted.get(builder.getRedirect()));
|
||||
}
|
||||
@@ -431,7 +_,7 @@
|
||||
@@ -430,7 +_,7 @@
|
||||
converted.put(child, node);
|
||||
target.addChild(node);
|
||||
if (!child.getChildren().isEmpty()) {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/commands/arguments/EntityArgument.java
|
||||
+++ b/net/minecraft/commands/arguments/EntityArgument.java
|
||||
@@ -107,9 +_,14 @@
|
||||
@@ -106,9 +_,14 @@
|
||||
}
|
||||
|
||||
private EntitySelector parse(final StringReader reader, final boolean allowSelectors) throws CommandSyntaxException {
|
||||
@@ -16,7 +16,7 @@
|
||||
if (selector.getMaxResults() > 1 && this.single) {
|
||||
if (this.playersOnly) {
|
||||
reader.setCursor(0);
|
||||
@@ -131,7 +_,13 @@
|
||||
@@ -130,7 +_,13 @@
|
||||
if (contextBuilder.getSource() instanceof SharedSuggestionProvider source) {
|
||||
StringReader reader = new StringReader(builder.getInput());
|
||||
reader.setCursor(builder.getStart());
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
+ private final int adjZ;
|
||||
+ // Paper end - Perf: Inline shift direction fields
|
||||
+
|
||||
private Direction(
|
||||
Direction(
|
||||
final int data3d,
|
||||
final int oppositeIndex,
|
||||
@@ -81,6 +_,11 @@
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
--- a/net/minecraft/core/HolderLookup.java
|
||||
+++ b/net/minecraft/core/HolderLookup.java
|
||||
@@ -69,6 +_,9 @@
|
||||
@@ -68,6 +_,8 @@
|
||||
}
|
||||
|
||||
public interface RegistryLookup<T> extends HolderLookup<T>, HolderOwner<T> {
|
||||
+
|
||||
interface RegistryLookup<T> extends HolderLookup<T>, HolderOwner<T> {
|
||||
+ Optional<T> getValueForCopying(ResourceKey<T> resourceKey); // Paper - add method to get the value for pre-filling builders in the reg mod API
|
||||
+
|
||||
ResourceKey<? extends Registry<? extends T>> key();
|
||||
|
||||
Lifecycle registryLifecycle();
|
||||
@@ -83,6 +_,13 @@
|
||||
Objects.requireNonNull(RegistryLookup.this);
|
||||
}
|
||||
@@ -78,6 +_,13 @@
|
||||
|
||||
default HolderLookup.RegistryLookup<T> filterElements(final Predicate<T> filter) {
|
||||
return new HolderLookup.RegistryLookup.Delegate<T>() {
|
||||
+ // Paper start - add getValueForCopying
|
||||
+ @Override
|
||||
+ public Optional<T> getValueForCopying(final ResourceKey<T> resourceKey) {
|
||||
@@ -24,9 +23,9 @@
|
||||
@Override
|
||||
public HolderLookup.RegistryLookup<T> parent() {
|
||||
return RegistryLookup.this;
|
||||
@@ -102,6 +_,13 @@
|
||||
@@ -97,6 +_,13 @@
|
||||
|
||||
public interface Delegate<T> extends HolderLookup.RegistryLookup<T> {
|
||||
interface Delegate<T> extends HolderLookup.RegistryLookup<T> {
|
||||
HolderLookup.RegistryLookup<T> parent();
|
||||
+
|
||||
+ // Paper start - add getValueForCopying
|
||||
|
||||
@@ -31,23 +31,23 @@
|
||||
|
||||
@Override
|
||||
public Stream<HolderSet.Named<T>> listTags() {
|
||||
@@ -114,6 +_,7 @@
|
||||
this.toId.put(value, newId);
|
||||
this.registrationInfos.put(key, registrationInfo);
|
||||
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
|
||||
+ this.temporaryUnfrozenMap.put(key.identifier(), value); // Paper - support pre-filling in registry mod API
|
||||
return holder;
|
||||
}
|
||||
@@ -117,6 +_,7 @@
|
||||
this.toId.put(value, newId);
|
||||
this.registrationInfos.put(key, registrationInfo);
|
||||
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
|
||||
+ this.temporaryUnfrozenMap.put(key.identifier(), value); // Paper - support pre-filling in registry mod API
|
||||
return holder;
|
||||
}
|
||||
@@ -275,6 +_,7 @@
|
||||
return this;
|
||||
} else {
|
||||
this.frozen = true;
|
||||
+ this.temporaryUnfrozenMap.clear(); // Paper - support pre-filling in registry mod API
|
||||
this.byValue.forEach((value, holder) -> holder.bindValue((T)value));
|
||||
List<Identifier> unboundEntries = this.byKey
|
||||
.entrySet()
|
||||
@@ -522,4 +_,13 @@
|
||||
|
||||
@@ -278,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.frozen = true;
|
||||
+ this.temporaryUnfrozenMap.clear(); // Paper - support pre-filling in registry mod API
|
||||
this.byValue.forEach((value, holder) -> holder.bindValue((T)value));
|
||||
List<Identifier> unboundEntries = this.byKey
|
||||
.entrySet()
|
||||
@@ -512,4 +_,13 @@
|
||||
|
||||
Stream<HolderSet.Named<T>> getTags();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/RegistrySetBuilder.java
|
||||
+++ b/net/minecraft/core/RegistrySetBuilder.java
|
||||
@@ -42,6 +_,13 @@
|
||||
@@ -41,6 +_,13 @@
|
||||
final Map<ResourceKey<T>, Holder.Reference<T>> entries
|
||||
) {
|
||||
return new RegistrySetBuilder.EmptyTagRegistryLookup<T>(owner) {
|
||||
@@ -14,7 +14,7 @@
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<? extends T>> key() {
|
||||
return key;
|
||||
@@ -128,6 +_,13 @@
|
||||
@@ -123,6 +_,13 @@
|
||||
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(final ResourceKey<? extends Registry<? extends T>> registryKey) {
|
||||
return getEntry(registryKey).map(Entry::opsInfo);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/Rotations.java
|
||||
+++ b/net/minecraft/core/Rotations.java
|
||||
@@ -26,11 +_,22 @@
|
||||
@@ -26,10 +_,21 @@
|
||||
output.writeFloat(value.z);
|
||||
}
|
||||
};
|
||||
@@ -12,14 +12,13 @@
|
||||
+ SKIP_VALIDATION = false;
|
||||
+ return rotations;
|
||||
+ }
|
||||
+ // Paper end - add internal method for skipping validation for plugins using userdev
|
||||
+ // Paper end - add internal method for skipping validation for plugins using userdev
|
||||
|
||||
public Rotations(float x, float y, float z) {
|
||||
public Rotations {
|
||||
+ if (!SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins using userdev
|
||||
x = !Float.isInfinite(x) && !Float.isNaN(x) ? x % 360.0F : 0.0F;
|
||||
y = !Float.isInfinite(y) && !Float.isNaN(y) ? y % 360.0F : 0.0F;
|
||||
z = !Float.isInfinite(z) && !Float.isNaN(z) ? z % 360.0F : 0.0F;
|
||||
+ } // Paper - add internal method for skipping validation for plugins using userdev
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,5 +10,5 @@
|
||||
- InteractionResult interact(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack itemInHand);
|
||||
+ InteractionResult interact(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack itemInHand, net.minecraft.core.Direction hitDirection); // Paper - add hitDirection
|
||||
|
||||
public static class Dispatcher {
|
||||
class Dispatcher {
|
||||
private final Map<TagKey<Item>, CauldronInteraction> tags = new HashMap<>();
|
||||
+98
-95
@@ -32,7 +32,7 @@
|
||||
state,
|
||||
level,
|
||||
pos,
|
||||
@@ -76,33 +_,43 @@
|
||||
@@ -76,23 +_,28 @@
|
||||
itemInHand,
|
||||
new ItemStack(Items.WATER_BUCKET),
|
||||
s -> s.getValue(LayeredCauldronBlock.LEVEL) == 3,
|
||||
@@ -64,23 +64,24 @@
|
||||
+ WATER.put(Items.POTION, (state, level, pos, player, hand, itemInHand, hitDirection) -> { // Paper - add hitDirection
|
||||
if (state.getValue(LayeredCauldronBlock.LEVEL) == 3) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
PotionContents potion = itemInHand.get(DataComponents.POTION_CONTENTS);
|
||||
if (potion != null && potion.is(Potions.WATER)) {
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleCauldronLevelChangeEvent(level, pos, state.cycle(LayeredCauldronBlock.LEVEL), player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { // Paper - Call CauldronLevelChangeEvent
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(itemInHand.getItem()));
|
||||
- level.setBlockAndUpdate(pos, state.cycle(LayeredCauldronBlock.LEVEL));
|
||||
+ // level.setBlockAndUpdate(pos, state.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit
|
||||
level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
|
||||
}
|
||||
}
|
||||
@@ -100,10 +_,15 @@
|
||||
PotionContents potion = itemInHand.get(DataComponents.POTION_CONTENTS);
|
||||
if (potion != null && potion.is(Potions.WATER)) {
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleCauldronLevelChangeEvent(level, pos, state.cycle(LayeredCauldronBlock.LEVEL), player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { // Paper - Call CauldronLevelChangeEvent
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(itemInHand.getItem()));
|
||||
- level.setBlockAndUpdate(pos, state.cycle(LayeredCauldronBlock.LEVEL));
|
||||
+ // level.setBlockAndUpdate(pos, state.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit
|
||||
level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
|
||||
}
|
||||
@@ -148,14 +_,14 @@
|
||||
WATER.put(Items.YELLOW_SHULKER_BOX, CauldronInteractions::shulkerBoxInteraction);
|
||||
LAVA.put(
|
||||
@@ -108,7 +109,7 @@
|
||||
)
|
||||
);
|
||||
addDefaultInteractions(POWDER_SNOW);
|
||||
@@ -187,15 +_,46 @@
|
||||
@@ -187,16 +_,47 @@
|
||||
final Predicate<BlockState> canFill,
|
||||
final SoundEvent soundEvent
|
||||
) {
|
||||
@@ -131,31 +132,32 @@
|
||||
+ // Paper end - add hitDirection
|
||||
if (!canFill.test(state)) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
if (!level.isClientSide()) {
|
||||
+ // Paper start - fire PlayerBucketFillEvent
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(level, player, pos, pos, hitDirection, itemInHand, newItem.getItem(), hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ newItem = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
+ // Paper start - fire PlayerBucketFillEvent
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(level, player, pos, pos, hitDirection, itemInHand, newItem.getItem(), hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ // Paper end - fire PlayerBucketFillEvent
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleCauldronLevelChangeEvent(level, pos, Blocks.CAULDRON.defaultBlockState(), player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { // Paper - Call CauldronLevelChangeEvent
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Item itemUsed = itemInHand.getItem();
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, newItem));
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(itemUsed));
|
||||
- level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState());
|
||||
+ // level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit
|
||||
level.playSound(null, pos, soundEvent, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
|
||||
}
|
||||
+ newItem = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY;
|
||||
+ }
|
||||
+ // Paper end - fire PlayerBucketFillEvent
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleCauldronLevelChangeEvent(level, pos, Blocks.CAULDRON.defaultBlockState(), player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { // Paper - Call CauldronLevelChangeEvent
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Item itemUsed = itemInHand.getItem();
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, newItem));
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(itemUsed));
|
||||
- level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState());
|
||||
+ // level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit
|
||||
level.playSound(null, pos, soundEvent, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
|
||||
}
|
||||
@@ -213,12 +_,42 @@
|
||||
final BlockState newState,
|
||||
final SoundEvent soundEvent
|
||||
@@ -218,25 +220,25 @@
|
||||
- final BlockState state, final Level level, final BlockPos pos, final Player player, final InteractionHand hand, final ItemStack itemInHand
|
||||
+ final BlockState state, final Level level, final BlockPos pos, final Player player, final InteractionHand hand, final ItemStack itemInHand, final net.minecraft.core.Direction hitDirection // Paper - add hitDirection
|
||||
) {
|
||||
return (InteractionResult)(isUnderWater(level, pos)
|
||||
return isUnderWater(level, pos)
|
||||
? InteractionResult.CONSUME
|
||||
- : emptyBucket(level, pos, player, hand, itemInHand, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA));
|
||||
+ : emptyBucket(level, pos, player, hand, itemInHand, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA, hitDirection)); // Paper - add hitDirection
|
||||
- : emptyBucket(level, pos, player, hand, itemInHand, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA);
|
||||
+ : emptyBucket(level, pos, player, hand, itemInHand, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA, hitDirection); // Paper - add hitDirection
|
||||
}
|
||||
|
||||
private static InteractionResult fillPowderSnowInteraction(
|
||||
- final BlockState state, final Level level, final BlockPos pos, final Player player, final InteractionHand hand, final ItemStack itemInHand
|
||||
+ final BlockState state, final Level level, final BlockPos pos, final Player player, final InteractionHand hand, final ItemStack itemInHand, final net.minecraft.core.Direction hitDirection // Paper - add hitDirection
|
||||
) {
|
||||
return (InteractionResult)(isUnderWater(level, pos)
|
||||
return isUnderWater(level, pos)
|
||||
? InteractionResult.CONSUME
|
||||
@@ -254,22 +_,27 @@
|
||||
@@ -254,12 +_,12 @@
|
||||
hand,
|
||||
itemInHand,
|
||||
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3),
|
||||
- SoundEvents.BUCKET_EMPTY_POWDER_SNOW
|
||||
+ SoundEvents.BUCKET_EMPTY_POWDER_SNOW, hitDirection // Paper - add hitDirection
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
private static InteractionResult shulkerBoxInteraction(
|
||||
@@ -245,23 +247,23 @@
|
||||
) {
|
||||
Block block = Block.byItem(itemInHand.getItem());
|
||||
if (!(block instanceof ShulkerBoxBlock)) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack cleanedShulkerBox = itemInHand.transmuteCopy(Blocks.SHULKER_BOX, 1);
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, cleanedShulkerBox, false));
|
||||
player.awardStat(Stats.CLEAN_SHULKER_BOX);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
@@ -267,17 +_,22 @@
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -277,18 +_,23 @@
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack cleanedShulkerBox = itemInHand.transmuteCopy(Blocks.SHULKER_BOX, 1);
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, cleanedShulkerBox, false));
|
||||
player.awardStat(Stats.CLEAN_SHULKER_BOX);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static InteractionResult bannerInteraction(
|
||||
@@ -270,24 +272,24 @@
|
||||
) {
|
||||
BannerPatternLayers patterns = itemInHand.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
|
||||
if (patterns.layers().isEmpty()) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack cleanedBanner = itemInHand.copyWithCount(1);
|
||||
cleanedBanner.set(DataComponents.BANNER_PATTERNS, patterns.removeLast());
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, cleanedBanner, false));
|
||||
player.awardStat(Stats.CLEAN_BANNER);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
@@ -285,27 +_,37 @@
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -296,15 +_,20 @@
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack cleanedBanner = itemInHand.copyWithCount(1);
|
||||
cleanedBanner.set(DataComponents.BANNER_PATTERNS, patterns.removeLast());
|
||||
player.setItemInHand(hand, ItemUtils.createFilledResult(itemInHand, player, cleanedBanner, false));
|
||||
player.awardStat(Stats.CLEAN_BANNER);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static InteractionResult dyedItemIteration(
|
||||
@@ -296,17 +298,18 @@
|
||||
) {
|
||||
if (!itemInHand.has(DataComponents.DYED_COLOR)) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
itemInHand.remove(DataComponents.DYED_COLOR);
|
||||
player.awardStat(Stats.CLEAN_ARMOR);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
if (!level.isClientSide()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(state, level, pos, player, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
itemInHand.remove(DataComponents.DYED_COLOR);
|
||||
player.awardStat(Stats.CLEAN_ARMOR);
|
||||
- LayeredCauldronBlock.lowerFillLevel(state, level, pos);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(state, level, pos); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
+3
-3
@@ -24,10 +24,10 @@
|
||||
@@ -126,6 +_,7 @@
|
||||
patch.map
|
||||
)) {
|
||||
Optional<?> value = entryx.getValue();
|
||||
+ value = io.papermc.paper.util.sanitizer.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
|
||||
Optional<?> value = entry.getValue();
|
||||
+ value = io.papermc.paper.util.sanitizer.ItemComponentSanitizer.override(itemObfuscationSession, entry.getKey(), entry.getValue()); // Paper - data sanitization for items
|
||||
if (value.isPresent()) {
|
||||
DataComponentType<?> type = entryx.getKey();
|
||||
DataComponentType<?> type = entry.getKey();
|
||||
DataComponentType.STREAM_CODEC.encode(output, type);
|
||||
@@ -145,7 +_,13 @@
|
||||
}
|
||||
|
||||
+49
-48
@@ -124,7 +124,7 @@
|
||||
return this.consumeWithRemainder(source, dispensed, new ItemStack(Items.BUCKET));
|
||||
} else {
|
||||
return this.defaultDispenseItemBehavior.dispense(source, dispensed);
|
||||
@@ -174,12 +_,19 @@
|
||||
@@ -174,13 +_,20 @@
|
||||
BlockPos target = source.pos().relative(source.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockState = level.getBlockState(target);
|
||||
if (blockState.getBlock() instanceof BucketPickup bucket) {
|
||||
@@ -132,19 +132,20 @@
|
||||
+ ItemStack pickup = bucket.pickupBlock(null, org.bukkit.craftbukkit.util.DummyLevelAccessor.INSTANCE, target, blockState); // CraftBukkit
|
||||
if (pickup.isEmpty()) {
|
||||
return super.execute(source, dispensed);
|
||||
} else {
|
||||
level.gameEvent(null, GameEvent.FLUID_PICKUP, target);
|
||||
Item targetType = pickup.getItem();
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(source, target, dispensed, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
+ pickup = bucket.pickupBlock(null, level, target, blockState); // CraftBukkit - from above
|
||||
return this.consumeWithRemainder(source, dispensed, new ItemStack(targetType));
|
||||
}
|
||||
|
||||
level.gameEvent(null, GameEvent.FLUID_PICKUP, target);
|
||||
Item targetType = pickup.getItem();
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(source, target, dispensed, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
+ pickup = bucket.pickupBlock(null, level, target, blockState); // CraftBukkit - from above
|
||||
return this.consumeWithRemainder(source, dispensed, new ItemStack(targetType));
|
||||
} else {
|
||||
return super.execute(source, dispensed);
|
||||
@@ -194,15 +_,26 @@
|
||||
this.setSuccess(true);
|
||||
Direction facing = source.state().getValue(DispenserBlock.FACING);
|
||||
@@ -333,35 +334,35 @@
|
||||
RespawnAnchorBlock.charge(null, level, pos, blockState);
|
||||
dispensed.shrink(1);
|
||||
} else {
|
||||
@@ -383,6 +_,28 @@
|
||||
this.setSuccess(false);
|
||||
@@ -384,6 +_,28 @@
|
||||
return dispensed;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, source.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(dispensed); // Paper - ignore stack size on damageable items
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, source.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(dispensed); // Paper - ignore stack size on damageable items
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), armadillos.get(0).getBukkitLivingEntity());
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), armadillos.get(0).getBukkitLivingEntity());
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ this.setSuccess(false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ this.setSuccess(false);
|
||||
+ return dispensed;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(source, eventStack);
|
||||
+ return dispensed;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(source, eventStack);
|
||||
+ return dispensed;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
for (Armadillo armadillo : armadillos) {
|
||||
if (armadillo.brushOffScute(null, dispensed)) {
|
||||
dispensed.hurtAndBreak(16, level, null, item -> {});
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
for (Armadillo armadillo : armadillos) {
|
||||
if (armadillo.brushOffScute(null, dispensed)) {
|
||||
dispensed.hurtAndBreak(16, level, null, item -> {});
|
||||
@@ -403,6 +_,13 @@
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
Optional<BlockState> maybeWaxed = HoneycombItem.getWaxed(blockState);
|
||||
@@ -376,16 +377,16 @@
|
||||
level.setBlockAndUpdate(pos, maybeWaxed.get());
|
||||
level.levelEvent(LevelEvent.PARTICLES_AND_SOUND_WAX_ON, pos, 0);
|
||||
dispensed.shrink(1);
|
||||
@@ -430,6 +_,12 @@
|
||||
if (!level.getBlockState(target).is(BlockTags.CONVERTABLE_TO_MUD)) {
|
||||
return this.defaultDispenseItemBehavior.dispense(source, dispensed);
|
||||
} else {
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(source, target, dispensed, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (!level.isClientSide()) {
|
||||
RandomSource random = level.getRandom();
|
||||
@@ -432,6 +_,12 @@
|
||||
return this.defaultDispenseItemBehavior.dispense(source, dispensed);
|
||||
}
|
||||
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(source, target, dispensed, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (!level.isClientSide()) {
|
||||
RandomSource random = level.getRandom();
|
||||
|
||||
+39
-39
@@ -19,45 +19,45 @@
|
||||
BlockPos pos = source.pos().relative(source.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> entities = source.level().getEntitiesOfClass(LivingEntity.class, new AABB(pos), entity -> entity.canEquipWithDispenser(dispensed));
|
||||
if (entities.isEmpty()) {
|
||||
@@ -25,13 +_,39 @@
|
||||
} else {
|
||||
LivingEntity target = entities.getFirst();
|
||||
EquipmentSlot slot = target.getEquipmentSlotForItem(dispensed);
|
||||
- ItemStack equip = dispensed.split(1);
|
||||
- target.setItemSlot(slot, equip);
|
||||
+ ItemStack equip = dispensed.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ // CraftBukkit start
|
||||
+ net.minecraft.world.level.Level world = source.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, source.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(equip);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) target.getBukkitEntity());
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) {
|
||||
+ dispenseItemBehavior.dispense(source, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ target.setItemSlot(slot, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
if (target instanceof Mob targetMob) {
|
||||
targetMob.setGuaranteedDrop(slot);
|
||||
targetMob.setPersistenceRequired();
|
||||
}
|
||||
@@ -26,13 +_,39 @@
|
||||
|
||||
+ if (shrink) dispensed.shrink(1); // Paper - shrink here
|
||||
return true;
|
||||
LivingEntity target = entities.getFirst();
|
||||
EquipmentSlot slot = target.getEquipmentSlotForItem(dispensed);
|
||||
- ItemStack equip = dispensed.split(1);
|
||||
- target.setItemSlot(slot, equip);
|
||||
+ ItemStack equip = dispensed.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ // CraftBukkit start
|
||||
+ net.minecraft.world.level.Level world = source.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, source.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(equip);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) target.getBukkitEntity());
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) {
|
||||
+ dispenseItemBehavior.dispense(source, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ target.setItemSlot(slot, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
if (target instanceof Mob targetMob) {
|
||||
targetMob.setGuaranteedDrop(slot);
|
||||
targetMob.setPersistenceRequired();
|
||||
}
|
||||
|
||||
+ if (shrink) dispensed.shrink(1); // Paper - shrink here
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -35,6 +35,6 @@
|
||||
+ dispensed.shrink(1); // vanilla shrink is in the place function above, manually handle it here
|
||||
+ }
|
||||
+ // Paper end - track changed items in the dispense event
|
||||
} catch (Exception var8) {
|
||||
LOGGER.error("Error trying to place shulker box at {}", relativePos, var8);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error trying to place shulker box at {}", relativePos, e);
|
||||
}
|
||||
+38
-38
@@ -1,42 +1,42 @@
|
||||
--- a/net/minecraft/core/dispenser/SpawnEggItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/SpawnEggItemBehavior.java
|
||||
@@ -18,14 +_,37 @@
|
||||
if (type == null) {
|
||||
return dispensed;
|
||||
} else {
|
||||
+ // Paper start - block dispense event
|
||||
+ ItemStack singleDispensed = dispensed.copyWithCount(1);
|
||||
+ final org.bukkit.craftbukkit.inventory.CraftItemStack eventItemCopy = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleDispensed);
|
||||
+ final org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(source.level(), source.pos()),
|
||||
+ eventItemCopy,
|
||||
+ new org.bukkit.util.Vector(0, 0, 0)
|
||||
+ );
|
||||
+ if (!event.callEvent()) return dispensed;
|
||||
+
|
||||
+ final boolean shrink = event.getItem().equals(eventItemCopy);
|
||||
+ if (!shrink) {
|
||||
+ final ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem());
|
||||
+ final DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(source, eventStack);
|
||||
+ return dispensed;
|
||||
+ }
|
||||
+
|
||||
+ type = SpawnEggItem.getType(eventStack);
|
||||
+ singleDispensed = eventStack;
|
||||
+ }
|
||||
+ // Paper end - block dispense event
|
||||
try {
|
||||
- type.spawn(source.level(), dispensed, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false);
|
||||
+ type.spawn(source.level(), singleDispensed, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false); // Paper - block dispense event - update used item stack
|
||||
} catch (Exception var6) {
|
||||
LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), var6);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- dispensed.shrink(1);
|
||||
+ if (shrink) dispensed.shrink(1); // Paper - block dispense event - only shrink if above logic requires it.
|
||||
source.level().gameEvent(null, GameEvent.ENTITY_PLACE, source.pos());
|
||||
@@ -19,14 +_,37 @@
|
||||
return dispensed;
|
||||
}
|
||||
|
||||
+ // Paper start - block dispense event
|
||||
+ ItemStack singleDispensed = dispensed.copyWithCount(1);
|
||||
+ final org.bukkit.craftbukkit.inventory.CraftItemStack eventItemCopy = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleDispensed);
|
||||
+ final org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(source.level(), source.pos()),
|
||||
+ eventItemCopy,
|
||||
+ new org.bukkit.util.Vector(0, 0, 0)
|
||||
+ );
|
||||
+ if (!event.callEvent()) return dispensed;
|
||||
+
|
||||
+ final boolean shrink = event.getItem().equals(eventItemCopy);
|
||||
+ if (!shrink) {
|
||||
+ final ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem());
|
||||
+ final DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(source, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(source, eventStack);
|
||||
+ return dispensed;
|
||||
+ }
|
||||
+
|
||||
+ type = SpawnEggItem.getType(eventStack);
|
||||
+ singleDispensed = eventStack;
|
||||
+ }
|
||||
+ // Paper end - block dispense event
|
||||
try {
|
||||
- type.spawn(source.level(), dispensed, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false);
|
||||
+ type.spawn(source.level(), singleDispensed, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false); // Paper - block dispense event - update used item stack
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), e);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- dispensed.shrink(1);
|
||||
+ if (shrink) dispensed.shrink(1); // Paper - block dispense event - only shrink if above logic requires it.
|
||||
source.level().gameEvent(null, GameEvent.ENTITY_PLACE, source.pos());
|
||||
return dispensed;
|
||||
}
|
||||
+7
-10
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestServer.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestServer.java
|
||||
@@ -155,6 +_,8 @@
|
||||
@@ -154,6 +_,8 @@
|
||||
final int repeatCount
|
||||
) {
|
||||
super(
|
||||
@@ -9,21 +9,18 @@
|
||||
serverThread,
|
||||
levelStorageSource,
|
||||
packRepository,
|
||||
@@ -173,13 +_,21 @@
|
||||
@@ -172,9 +_,17 @@
|
||||
|
||||
@Override
|
||||
protected boolean initServer() {
|
||||
- this.setPlayerList(new PlayerList(this, this.registries(), this.playerDataStorage, new EmptyNotificationService()) {});
|
||||
+ // Paper start
|
||||
this.setPlayerList(new PlayerList(this, this.registries(), this.playerDataStorage, new EmptyNotificationService()) {
|
||||
{
|
||||
Objects.requireNonNull(GameTestServer.this);
|
||||
}
|
||||
+
|
||||
+ this.setPlayerList(new PlayerList(this, this.registries(), this.playerDataStorage, new EmptyNotificationService()) {
|
||||
+ @Override
|
||||
+ public void loadAndSaveFiles() {
|
||||
+ throw new UnsupportedOperationException("Should not be called in a GameTestServer");
|
||||
+ }
|
||||
});
|
||||
+ });
|
||||
+ this.initPostWorld();
|
||||
Gizmos.withCollector(GizmoCollector.NOOP);
|
||||
- this.loadLevel();
|
||||
@@ -32,7 +29,7 @@
|
||||
ServerLevel level = this.overworld();
|
||||
this.testBatches = this.evaluateTestsToRun(level);
|
||||
LOGGER.info("Started game test server");
|
||||
@@ -385,6 +_,13 @@
|
||||
@@ -380,6 +_,13 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -46,7 +43,7 @@
|
||||
@Override
|
||||
public boolean isSingleplayerOwner(final NameAndId nameAndId) {
|
||||
return false;
|
||||
@@ -432,5 +_,16 @@
|
||||
@@ -427,5 +_,16 @@
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/nbt/CompoundTag.java
|
||||
+++ b/net/minecraft/nbt/CompoundTag.java
|
||||
@@ -54,7 +_,7 @@
|
||||
@@ -51,7 +_,7 @@
|
||||
|
||||
private static CompoundTag loadCompound(final DataInput input, final NbtAccounter accounter) throws IOException {
|
||||
accounter.accountBytes(48L);
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
byte tagType;
|
||||
while ((tagType = input.readByte()) != 0) {
|
||||
@@ -171,7 +_,7 @@
|
||||
@@ -165,7 +_,7 @@
|
||||
}
|
||||
|
||||
public CompoundTag() {
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,9 +_,16 @@
|
||||
@@ -394,9 +_,16 @@
|
||||
|
||||
@Override
|
||||
public CompoundTag copy() {
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -523,22 +_,47 @@
|
||||
@@ -517,22 +_,47 @@
|
||||
this.merge((CompoundTag)codec.encoder().encodeStart(ops, value).getOrThrow());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/net/minecraft/nbt/NbtAccounter.java
|
||||
+++ b/net/minecraft/nbt/NbtAccounter.java
|
||||
@@ -50,6 +_,16 @@
|
||||
this.usage += size;
|
||||
}
|
||||
|
||||
+ // Paper start - Track codec depth
|
||||
+ public void pushDepth(final int depth) {
|
||||
+ if (this.depth + depth >= this.maxDepth) {
|
||||
+ throw new NbtAccounterException("Tried to read NBT tag with too high complexity, depth > " + this.maxDepth);
|
||||
+ } else {
|
||||
+ this.depth += depth;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Track codec depth
|
||||
+
|
||||
public void pushDepth() {
|
||||
if (this.depth >= this.maxDepth) {
|
||||
throw new NbtAccounterException("Tried to read NBT tag with too high complexity, depth > " + this.maxDepth);
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/nbt/NbtIo.java
|
||||
+++ b/net/minecraft/nbt/NbtIo.java
|
||||
@@ -117,7 +_,12 @@
|
||||
@@ -108,7 +_,12 @@
|
||||
return read(input, NbtAccounter.unlimitedHeap());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -68,6 +_,11 @@
|
||||
@@ -67,6 +_,11 @@
|
||||
private final Queue<Consumer<Connection>> pendingActions = Queues.newConcurrentLinkedQueue();
|
||||
public Channel channel;
|
||||
public SocketAddress address;
|
||||
@@ -12,7 +12,7 @@
|
||||
private volatile @Nullable PacketListener disconnectListener;
|
||||
private volatile @Nullable PacketListener packetListener;
|
||||
private @Nullable DisconnectionDetails disconnectionDetails;
|
||||
@@ -81,6 +_,44 @@
|
||||
@@ -80,6 +_,44 @@
|
||||
private boolean handlingFault;
|
||||
private volatile @Nullable DisconnectionDetails delayedDisconnect;
|
||||
private @Nullable BandwidthDebugMonitor bandwidthDebugMonitor;
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
public Connection(final PacketFlow receiving) {
|
||||
this.receiving = receiving;
|
||||
@@ -91,6 +_,7 @@
|
||||
@@ -90,6 +_,7 @@
|
||||
super.channelActive(ctx);
|
||||
this.channel = ctx.channel();
|
||||
this.address = this.channel.remoteAddress();
|
||||
@@ -65,7 +65,7 @@
|
||||
if (this.delayedDisconnect != null) {
|
||||
this.disconnect(this.delayedDisconnect);
|
||||
}
|
||||
@@ -102,15 +_,32 @@
|
||||
@@ -101,15 +_,32 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +99,7 @@
|
||||
this.disconnect(Component.translatable("disconnect.timeout"));
|
||||
} else {
|
||||
Component reason = Component.translatable("disconnect.genericReason", "Internal Exception: " + cause);
|
||||
@@ -122,9 +_,11 @@
|
||||
@@ -121,9 +_,11 @@
|
||||
details = new DisconnectionDetails(reason);
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@
|
||||
- if (this.getSending() == PacketFlow.CLIENTBOUND) {
|
||||
+ boolean doesDisconnectExist = this.packetListener.protocol() != ConnectionProtocol.STATUS && this.packetListener.protocol() != ConnectionProtocol.HANDSHAKING; // Paper
|
||||
+ if (this.getSending() == PacketFlow.CLIENTBOUND && doesDisconnectExist) { // Paper
|
||||
Packet<?> packet = (Packet<?>)(this.sendLoginDisconnect
|
||||
Packet<?> packet = this.sendLoginDisconnect
|
||||
? new ClientboundLoginDisconnectPacket(reason)
|
||||
: new ClientboundDisconnectPacket(reason));
|
||||
@@ -141,6 +_,7 @@
|
||||
: new ClientboundDisconnectPacket(reason);
|
||||
@@ -140,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,68 +120,69 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,10 +_,60 @@
|
||||
@@ -149,11 +_,60 @@
|
||||
if (packetListener == null) {
|
||||
throw new IllegalStateException("Received a packet before the packet listener was initialized");
|
||||
} else {
|
||||
+ // Paper start - packet limiter
|
||||
+ if (this.stopReadingPackets) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.allPacketCounts != null ||
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ long time = System.nanoTime();
|
||||
+ synchronized (PACKET_LIMIT_LOCK) {
|
||||
+ if (this.allPacketCounts != null) {
|
||||
+ this.allPacketCounts.updateAndAdd(1, time);
|
||||
+ if (this.allPacketCounts.getRate() >= io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.maxPacketRate()) {
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
+ // Paper start - packet limiter
|
||||
+ if (this.stopReadingPackets) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.allPacketCounts != null ||
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ long time = System.nanoTime();
|
||||
+ synchronized (PACKET_LIMIT_LOCK) {
|
||||
+ if (this.allPacketCounts != null) {
|
||||
+ this.allPacketCounts.updateAndAdd(1, time);
|
||||
+ if (this.allPacketCounts.getRate() >= io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.maxPacketRate()) {
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (Class<?> check = packet.getClass(); check != Object.class; check = check.getSuperclass()) {
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.PacketLimiter.PacketLimit packetSpecificLimit =
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.get(check);
|
||||
+ if (packetSpecificLimit == null || !packetSpecificLimit.isEnabled()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ io.papermc.paper.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> {
|
||||
+ return new io.papermc.paper.util.IntervalledCounter((long)(packetSpecificLimit.interval() * 1.0e9));
|
||||
+ });
|
||||
+ counter.updateAndAdd(1, time);
|
||||
+ if (counter.getRate() >= packetSpecificLimit.maxPacketRate()) {
|
||||
+ switch (packetSpecificLimit.action()) {
|
||||
+ case DROP:
|
||||
+ return;
|
||||
+ case KICK:
|
||||
+ String deobfedPacketName = check.getName();
|
||||
+ for (Class<?> check = packet.getClass(); check != Object.class; check = check.getSuperclass()) {
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.PacketLimiter.PacketLimit packetSpecificLimit =
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.get(check);
|
||||
+ if (packetSpecificLimit == null || !packetSpecificLimit.isEnabled()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ io.papermc.paper.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> {
|
||||
+ return new io.papermc.paper.util.IntervalledCounter((long)(packetSpecificLimit.interval() * 1.0e9));
|
||||
+ });
|
||||
+ counter.updateAndAdd(1, time);
|
||||
+ if (counter.getRate() >= packetSpecificLimit.maxPacketRate()) {
|
||||
+ switch (packetSpecificLimit.action()) {
|
||||
+ case DROP:
|
||||
+ return;
|
||||
+ case KICK:
|
||||
+ String deobfedPacketName = check.getName();
|
||||
+
|
||||
+ String playerName;
|
||||
+ if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
|
||||
+ playerName = impl.getOwner().name();
|
||||
+ } else {
|
||||
+ playerName = this.getLoggableAddress(net.minecraft.server.MinecraftServer.getServer().logIPs());
|
||||
+ }
|
||||
+ String playerName;
|
||||
+ if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
|
||||
+ playerName = impl.getOwner().name();
|
||||
+ } else {
|
||||
+ playerName = this.getLoggableAddress(net.minecraft.server.MinecraftServer.getServer().logIPs());
|
||||
+ }
|
||||
+
|
||||
+ Connection.LOGGER.warn("{} kicked for packet spamming: {}", playerName, deobfedPacketName.substring(deobfedPacketName.lastIndexOf(".") + 1));
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ Connection.LOGGER.warn("{} kicked for packet spamming: {}", playerName, deobfedPacketName.substring(deobfedPacketName.lastIndexOf(".") + 1));
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
if (packetListener.shouldHandleMessage(packet)) {
|
||||
try {
|
||||
genericsFtw(packet, packetListener);
|
||||
} catch (RunningOnDifferentThreadException var5) {
|
||||
+ } catch (io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop
|
||||
} catch (RejectedExecutionException var6) {
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
||||
} catch (ClassCastException var7) {
|
||||
@@ -344,10 +_,30 @@
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
if (packetListener.shouldHandleMessage(packet)) {
|
||||
try {
|
||||
genericsFtw(packet, packetListener);
|
||||
} catch (RunningOnDifferentThreadException var5) {
|
||||
+ } catch (io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop
|
||||
} catch (RejectedExecutionException ignored) {
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
||||
} catch (ClassCastException exception) {
|
||||
@@ -343,10 +_,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +213,7 @@
|
||||
}
|
||||
|
||||
if (!this.isConnected() && !this.disconnectionHandled) {
|
||||
@@ -355,7 +_,7 @@
|
||||
@@ -354,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (this.channel != null) {
|
||||
@@ -221,7 +222,7 @@
|
||||
}
|
||||
|
||||
if (this.tickCount++ % 20 == 0) {
|
||||
@@ -391,6 +_,7 @@
|
||||
@@ -390,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void disconnect(final DisconnectionDetails details) {
|
||||
@@ -229,7 +230,7 @@
|
||||
if (this.channel == null) {
|
||||
this.delayedDisconnect = details;
|
||||
}
|
||||
@@ -543,6 +_,14 @@
|
||||
@@ -534,6 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@
|
||||
public void setupCompression(final int threshold, final boolean validateDecompressed) {
|
||||
if (threshold >= 0) {
|
||||
if (this.channel.pipeline().get(HandlerNames.DECOMPRESS) instanceof CompressionDecoder compressionDecoder) {
|
||||
@@ -556,6 +_,7 @@
|
||||
@@ -547,6 +_,7 @@
|
||||
} else {
|
||||
this.channel.pipeline().addAfter(HandlerNames.PREPENDER, HandlerNames.COMPRESS, new CompressionEncoder(threshold));
|
||||
}
|
||||
@@ -252,7 +253,7 @@
|
||||
} else {
|
||||
if (this.channel.pipeline().get(HandlerNames.DECOMPRESS) instanceof CompressionDecoder) {
|
||||
this.channel.pipeline().remove(HandlerNames.DECOMPRESS);
|
||||
@@ -564,6 +_,7 @@
|
||||
@@ -555,6 +_,7 @@
|
||||
if (this.channel.pipeline().get(HandlerNames.COMPRESS) instanceof CompressionEncoder) {
|
||||
this.channel.pipeline().remove(HandlerNames.COMPRESS);
|
||||
}
|
||||
@@ -260,7 +261,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,6 +_,26 @@
|
||||
@@ -572,6 +_,26 @@
|
||||
);
|
||||
disconnectListener.onDisconnect(details);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
|
||||
try {
|
||||
NbtIo.writeAnyTag(tag, new ByteBufOutputStream(output));
|
||||
- } catch (IOException var3) {
|
||||
+ } catch (Exception var3) { // CraftBukkit - IOException -> Exception
|
||||
throw new EncoderException(var3);
|
||||
- } catch (IOException e) {
|
||||
+ } catch (Exception e) { // CraftBukkit - IOException -> Exception
|
||||
throw new EncoderException(e);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
@@ -44,7 +_,33 @@
|
||||
|
||||
throw var9;
|
||||
throw t;
|
||||
} finally {
|
||||
+ // Paper start - Handle large packets disconnecting client
|
||||
+ int packetLength = output.readableBytes();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/PacketProcessor.java
|
||||
+++ b/net/minecraft/network/PacketProcessor.java
|
||||
@@ -19,15 +_,42 @@
|
||||
@@ -19,16 +_,42 @@
|
||||
this.runningThread = runningThread;
|
||||
}
|
||||
|
||||
@@ -27,24 +27,26 @@
|
||||
public <T extends PacketListener> void scheduleIfPossible(final T listener, final Packet<T> packet) {
|
||||
if (this.closed) {
|
||||
- throw new RejectedExecutionException("Server already shutting down");
|
||||
- }
|
||||
-
|
||||
- this.packetsToBeHandled.add(new PacketProcessor.ListenerAndPacket<>(listener, packet));
|
||||
+ throw new io.papermc.paper.util.ServerStopRejectedExecutionException("Server already shutting down"); // Paper - do not prematurely disconnect players on stop
|
||||
} else {
|
||||
- this.packetsToBeHandled.add(new PacketProcessor.ListenerAndPacket<>(listener, packet));
|
||||
+ // Paper start - improve tick loop
|
||||
+ // wake up main thread inbetween ticks to process packets
|
||||
+ final boolean isEmpty = this.packetsToBeHandled.isEmpty();
|
||||
+ final ListenerAndPacket<T> toAdd = new PacketProcessor.ListenerAndPacket<>(listener, packet);
|
||||
+ this.packetsToBeHandled.add(toAdd);
|
||||
+ if (isEmpty || this.packetsToBeHandled.peek() == toAdd) {
|
||||
+ // only unpark if we are the first packet OR are at the head of the queue
|
||||
+ // we unpark if we are at the head in case the main thread emptied the queue
|
||||
+ // immediately before we added but after checking isEmpty
|
||||
+ java.util.concurrent.locks.LockSupport.unpark(this.runningThread);
|
||||
+ }
|
||||
+ // Paper end - improve tick loop
|
||||
}
|
||||
+ }
|
||||
+ // Paper start - improve tick loop
|
||||
+ // wake up main thread inbetween ticks to process packets
|
||||
+ final boolean isEmpty = this.packetsToBeHandled.isEmpty();
|
||||
+ final ListenerAndPacket<T> toAdd = new PacketProcessor.ListenerAndPacket<>(listener, packet);
|
||||
+ this.packetsToBeHandled.add(toAdd);
|
||||
+ if (isEmpty || this.packetsToBeHandled.peek() == toAdd) {
|
||||
+ // only unpark if we are the first packet OR are at the head of the queue
|
||||
+ // we unpark if we are at the head in case the main thread emptied the queue
|
||||
+ // immediately before we added but after checking isEmpty
|
||||
+ java.util.concurrent.locks.LockSupport.unpark(this.runningThread);
|
||||
+ }
|
||||
+ // Paper end - improve tick loop
|
||||
}
|
||||
|
||||
public void processQueuedPackets() {
|
||||
@@ -44,8 +_,28 @@
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
--- a/net/minecraft/network/RegistryFriendlyByteBuf.java
|
||||
+++ b/net/minecraft/network/RegistryFriendlyByteBuf.java
|
||||
@@ -12,6 +_,15 @@
|
||||
this.registryAccess = registryAccess;
|
||||
}
|
||||
|
||||
+ // Paper start - Track codec depth
|
||||
+ public RegistryFriendlyByteBuf(final ByteBuf source, final RegistryFriendlyByteBuf parent) {
|
||||
+ super(source);
|
||||
+ this.registryAccess = parent.registryAccess;
|
||||
+ this.trackCodecDepth = parent.trackCodecDepth;
|
||||
+ this.codecDepth = parent.codecDepth;
|
||||
+ }
|
||||
+ // Paper end - Track codec depth
|
||||
+
|
||||
public RegistryAccess registryAccess() {
|
||||
return this.registryAccess;
|
||||
}
|
||||
+5
-5
@@ -11,10 +11,10 @@
|
||||
+ // Paper end
|
||||
+
|
||||
static OutgoingChatMessage create(final PlayerChatMessage message) {
|
||||
return (OutgoingChatMessage)(message.isSystem()
|
||||
? new OutgoingChatMessage.Disguised(message.decoratedContent())
|
||||
@@ -16,7 +_,13 @@
|
||||
public record Disguised(@Override Component content) implements OutgoingChatMessage {
|
||||
return message.isSystem() ? new OutgoingChatMessage.Disguised(message.decoratedContent()) : new OutgoingChatMessage.Player(message);
|
||||
}
|
||||
@@ -14,7 +_,13 @@
|
||||
record Disguised(@Override Component content) implements OutgoingChatMessage {
|
||||
@Override
|
||||
public void sendToPlayer(final ServerPlayer player, final boolean filtered, final ChatType.Bound chatType) {
|
||||
- player.connection.sendDisguisedChatMessage(this.content, chatType);
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +_,14 @@
|
||||
@@ -26,7 +_,14 @@
|
||||
|
||||
@Override
|
||||
public void sendToPlayer(final ServerPlayer player, final boolean filtered, final ChatType.Bound chatType) {
|
||||
|
||||
+17
-16
@@ -1,23 +1,24 @@
|
||||
--- a/net/minecraft/network/chat/SignedMessageChain.java
|
||||
+++ b/net/minecraft/network/chat/SignedMessageChain.java
|
||||
@@ -44,14 +_,14 @@
|
||||
if (signature == null) {
|
||||
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.MISSING_PROFILE_KEY);
|
||||
} else if (profilePublicKey.data().hasExpired()) {
|
||||
@@ -41,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (profilePublicKey.data().hasExpired()) {
|
||||
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.EXPIRED_PROFILE_KEY);
|
||||
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.EXPIRED_PROFILE_KEY, org.bukkit.event.player.PlayerKickEvent.Cause.EXPIRED_PROFILE_PUBLIC_KEY); // Paper - kick event causes
|
||||
} else {
|
||||
SignedMessageLink link = SignedMessageChain.this.nextLink;
|
||||
if (link == null) {
|
||||
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
|
||||
} else if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
|
||||
this.setChainBroken();
|
||||
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT);
|
||||
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
|
||||
} else {
|
||||
SignedMessageChain.this.lastTimeStamp = body.timeStamp();
|
||||
PlayerChatMessage unpacked = new PlayerChatMessage(link, signature, body, null, FilterMask.PASS_THROUGH);
|
||||
@@ -84,8 +_,15 @@
|
||||
}
|
||||
|
||||
SignedMessageLink link = SignedMessageChain.this.nextLink;
|
||||
@@ -51,7 +_,7 @@
|
||||
|
||||
if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
|
||||
this.setChainBroken();
|
||||
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT);
|
||||
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
|
||||
}
|
||||
|
||||
SignedMessageChain.this.lastTimeStamp = body.timeStamp();
|
||||
@@ -83,8 +_,15 @@
|
||||
private static final Component INVALID_SIGNATURE = Component.translatable("chat.disabled.invalid_signature");
|
||||
private static final Component OUT_OF_ORDER_CHAT = Component.translatable("chat.disabled.out_of_order_chat");
|
||||
|
||||
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/network/chat/contents/SelectorContents.java
|
||||
+++ b/net/minecraft/network/chat/contents/SelectorContents.java
|
||||
@@ -37,7 +_,7 @@
|
||||
if (source == null) {
|
||||
@@ -38,7 +_,7 @@
|
||||
return Component.empty();
|
||||
} else {
|
||||
- Optional<? extends Component> resolvedSeparator = ComponentUtils.resolve(context, this.separator, recursionDepth);
|
||||
+ Optional<? extends Component> resolvedSeparator = ComponentUtils.resolveSeparator(context, this.separator, recursionDepth); // Paper - validate separator
|
||||
return ComponentUtils.formatList(this.selector.compiled().findEntities(source), resolvedSeparator, Entity::getDisplayName);
|
||||
}
|
||||
|
||||
- Optional<? extends Component> resolvedSeparator = ComponentUtils.resolve(context, this.separator, recursionDepth);
|
||||
+ Optional<? extends Component> resolvedSeparator = ComponentUtils.resolveSeparator(context, this.separator, recursionDepth); // Paper - validate separator
|
||||
return ComponentUtils.formatList(this.selector.compiled().findEntities(source), resolvedSeparator, Entity::getDisplayName);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
--- a/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
@@ -334,7 +_,13 @@
|
||||
return new StreamCodec<ByteBuf, Tag>() {
|
||||
@Override
|
||||
public Tag decode(final ByteBuf input) {
|
||||
- Tag result = FriendlyByteBuf.readNbt(input, accounter.get());
|
||||
+ // Paper start - Track codec depth
|
||||
+ final NbtAccounter acc = accounter.get();
|
||||
+ if (input instanceof FriendlyByteBuf friendlyByteBuf && friendlyByteBuf.trackCodecDepth) {
|
||||
+ acc.pushDepth(friendlyByteBuf.codecDepth * 3);
|
||||
+ }
|
||||
+ Tag result = FriendlyByteBuf.readNbt(input, acc);
|
||||
+ // Paper end - Track codec depth
|
||||
if (result == null) {
|
||||
throw new DecoderException("Expected non-null compound tag");
|
||||
} else {
|
||||
@@ -418,6 +_,48 @@
|
||||
};
|
||||
}
|
||||
@@ -49,3 +64,12 @@
|
||||
static <B extends ByteBuf, V> StreamCodec<B, Optional<V>> optional(final StreamCodec<? super B, V> original) {
|
||||
return new StreamCodec<B, Optional<V>>() {
|
||||
@Override
|
||||
@@ -594,7 +_,7 @@
|
||||
}
|
||||
|
||||
static <V> StreamCodec.CodecOperation<RegistryFriendlyByteBuf, V, V> registryFriendlyLengthPrefixed(final int maxSize) {
|
||||
- return lengthPrefixed(maxSize, (parent, child) -> new RegistryFriendlyByteBuf(child, parent.registryAccess()));
|
||||
+ return lengthPrefixed(maxSize, (parent, child) -> new RegistryFriendlyByteBuf(child, parent)); // Paper - Track codec depth
|
||||
}
|
||||
|
||||
static <T> StreamCodec<ByteBuf, T> idMapper(final IntFunction<T> byId, final ToIntFunction<T> toId) {
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java
|
||||
+++ b/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java
|
||||
@@ -20,7 +_,7 @@
|
||||
@@ -16,7 +_,7 @@
|
||||
}
|
||||
|
||||
private ClientIntentionPacket(final FriendlyByteBuf input) {
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
public boolean isDirty() {
|
||||
return this.isDirty;
|
||||
}
|
||||
@@ -167,6 +_,19 @@
|
||||
@@ -171,6 +_,19 @@
|
||||
return new SynchedEntityData(this.entity, this.itemsById);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/resources/Identifier.java
|
||||
+++ b/net/minecraft/resources/Identifier.java
|
||||
@@ -22,6 +_,7 @@
|
||||
@@ -22,12 +_,20 @@
|
||||
public static final String DEFAULT_NAMESPACE = "minecraft";
|
||||
public static final String REALMS_NAMESPACE = "realms";
|
||||
public static final String ALLOWED_NAMESPACE_CHARACTERS = "[a-z0-9_.-]";
|
||||
@@ -8,10 +8,9 @@
|
||||
private final String namespace;
|
||||
private final String path;
|
||||
|
||||
@@ -30,6 +_,13 @@
|
||||
|
||||
private Identifier(final String namespace, final String path) {
|
||||
assert isValidNamespace(namespace);
|
||||
assert isValidPath(path);
|
||||
|
||||
+ // Paper start - Validate Identifier
|
||||
+ // Check for the max network string length (capped at Short.MAX_VALUE) as well as the max bytes of a StringTag (length written as an unsigned short)
|
||||
+ final int length = namespace.length() + path.length() + 1;
|
||||
@@ -22,7 +21,7 @@
|
||||
this.namespace = namespace;
|
||||
this.path = path;
|
||||
}
|
||||
@@ -242,7 +_,7 @@
|
||||
@@ -240,7 +_,7 @@
|
||||
|
||||
private static String assertValidNamespace(final String namespace, final String path) {
|
||||
if (!isValidNamespace(namespace)) {
|
||||
@@ -31,7 +30,7 @@
|
||||
} else {
|
||||
return namespace;
|
||||
}
|
||||
@@ -258,7 +_,7 @@
|
||||
@@ -256,7 +_,7 @@
|
||||
|
||||
private static String assertValidPath(final String namespace, final String path) {
|
||||
if (!isValidPath(path)) {
|
||||
|
||||
+8
-8
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/resources/NetworkRegistryLoadTask.java
|
||||
+++ b/net/minecraft/resources/NetworkRegistryLoadTask.java
|
||||
@@ -79,7 +_,7 @@
|
||||
}
|
||||
@@ -80,7 +_,7 @@
|
||||
}
|
||||
|
||||
return Util.sequence(elements).thenAcceptAsync(pendingRegistrations -> {
|
||||
- this.registerElements(pendingRegistrations.stream());
|
||||
+ this.registerElements(pendingRegistrations.stream(), null); // Paper - this code is only used on the client
|
||||
Map<TagKey<T>, List<Holder<T>>> pendingTags = TagLoader.loadTagsFromNetwork(registryEntries.tags(), this.readOnlyRegistry());
|
||||
this.registerTags(pendingTags);
|
||||
}, executor);
|
||||
return Util.sequence(elements).thenAcceptAsync(pendingRegistrations -> {
|
||||
- this.registerElements(pendingRegistrations.stream());
|
||||
+ this.registerElements(pendingRegistrations.stream(), null); // Paper - this code is only used on the client
|
||||
Map<TagKey<T>, List<Holder<T>>> pendingTags = TagLoader.loadTagsFromNetwork(registryEntries.tags(), this.readOnlyRegistry());
|
||||
this.registerTags(pendingTags);
|
||||
}, executor);
|
||||
@@ -7,91 +7,90 @@
|
||||
+ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping
|
||||
if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) {
|
||||
throw new IllegalStateException("Unable to load registries");
|
||||
} else {
|
||||
@@ -54,11 +_,85 @@
|
||||
EntitySelectorOptions.bootStrap();
|
||||
DispenseItemBehavior.bootStrap();
|
||||
CauldronInteractions.bootStrap();
|
||||
- BuiltInRegistries.bootStrap();
|
||||
+ // Paper start
|
||||
+ BuiltInRegistries.bootStrap(() -> {
|
||||
+ io.papermc.paper.world.worldgen.OptionallyFlatBedrockConditionSource.bootstrap(); // Paper - Flat bedrock generator settings
|
||||
+ });
|
||||
+ // Paper end
|
||||
CreativeModeTabs.validate();
|
||||
wrapStreams();
|
||||
bootstrapDuration.set(Duration.between(start, Instant.now()).toMillis());
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ // TODO Check what of this is needed, maybe report it to Mojira. if deemed relevant, move to the respective classes
|
||||
+ // Used in CraftLegacy
|
||||
+ for (int i = 0; i <= 15; i++) {
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(
|
||||
+ 1008 + i,
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:oak_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:standing_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440,
|
||||
}
|
||||
@@ -56,10 +_,84 @@
|
||||
EntitySelectorOptions.bootStrap();
|
||||
DispenseItemBehavior.bootStrap();
|
||||
CauldronInteractions.bootStrap();
|
||||
- BuiltInRegistries.bootStrap();
|
||||
+ // Paper start
|
||||
+ BuiltInRegistries.bootStrap(() -> {
|
||||
+ io.papermc.paper.world.worldgen.OptionallyFlatBedrockConditionSource.bootstrap(); // Paper - Flat bedrock generator settings
|
||||
+ });
|
||||
+ // Paper end
|
||||
CreativeModeTabs.validate();
|
||||
wrapStreams();
|
||||
bootstrapDuration.set(Duration.between(start, Instant.now()).toMillis());
|
||||
+ // CraftBukkit start
|
||||
+ // TODO Check what of this is needed, maybe report it to Mojira. if deemed relevant, move to the respective classes
|
||||
+ // Used in CraftLegacy
|
||||
+ for (int i = 0; i <= 15; i++) {
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(
|
||||
+ 1008 + i,
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ "Name", "minecraft:oak_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ "Name", "minecraft:standing_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440,
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
|
||||
+ );
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand");
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow";
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book");
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow";
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
}
|
||||
},
|
||||
WorldStem::new,
|
||||
@@ -191,6 +_,7 @@
|
||||
@@ -190,6 +_,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
RegistryAccess.Frozen registryHolder = worldStem.registries().compositeAccess();
|
||||
WorldData data = worldStem.worldDataAndGenSettings().data();
|
||||
boolean recreateRegionFilesValue = options.has(recreateRegionFiles);
|
||||
@@ -199,22 +_,51 @@
|
||||
@@ -198,22 +_,51 @@
|
||||
}
|
||||
|
||||
access.saveDataTag(data);
|
||||
@@ -253,13 +253,13 @@
|
||||
Thread shutdownThread = new Thread("Server Shutdown Thread") {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -223,12 +_,13 @@
|
||||
@@ -222,12 +_,13 @@
|
||||
};
|
||||
shutdownThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
|
||||
Runtime.getRuntime().addShutdownHook(shutdownThread);
|
||||
+ */ // CraftBukkit end
|
||||
} catch (Throwable var40) {
|
||||
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", var40);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
final DedicatedServerSettings settings,
|
||||
final WorldLoader.DataLoadContext context,
|
||||
final Registry<LevelStem> datapackDimensions,
|
||||
@@ -299,7 +_,11 @@
|
||||
@@ -298,7 +_,11 @@
|
||||
final RegistryAccess registryAccess,
|
||||
final boolean recreateRegionFiles
|
||||
) {
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
try (WorldUpgrader upgrader = new WorldUpgrader(storageSource, fixerUpper, registryAccess, eraseCache, recreateRegionFiles)) {
|
||||
Component lastStatus = null;
|
||||
@@ -327,5 +_,6 @@
|
||||
@@ -326,5 +_,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
final Thread serverThread,
|
||||
final LevelStorageSource.LevelStorageAccess storageSource,
|
||||
final PackRepository packRepository,
|
||||
@@ -322,27 +_,27 @@
|
||||
@@ -322,28 +_,28 @@
|
||||
final boolean propagatesCrashes
|
||||
) {
|
||||
super("Server", propagatesCrashes);
|
||||
@@ -209,41 +209,40 @@
|
||||
- if (!this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) {
|
||||
+ if (false && !this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later
|
||||
throw new IllegalStateException("Missing Overworld dimension data");
|
||||
} else {
|
||||
- this.savedDataStorage = new SavedDataStorage(storageSource.getLevelPath(LevelResource.DATA), fixerUpper, this.registries.compositeAccess());
|
||||
+ this.savedDataStorage = new SavedDataStorage(storageSource.getLevelPath(LevelResource.ROOT).resolve(LevelResource.DATA.id()), fixerUpper, this.registries.compositeAccess());
|
||||
this.worldData = worldStem.worldDataAndGenSettings().data();
|
||||
this.worldGenSettings = worldStem.worldDataAndGenSettings().genSettings();
|
||||
- this.savedDataStorage.set(WorldGenSettings.TYPE, this.worldGenSettings);
|
||||
+ // this.savedDataStorage.set(WorldGenSettings.TYPE, this.worldGenSettings); // Paper - save in level storage
|
||||
this.proxy = proxy;
|
||||
this.packRepository = packRepository;
|
||||
this.resources = new MinecraftServer.ReloadableResources(worldStem.resourceManager(), worldStem.dataPackResources());
|
||||
this.services = services;
|
||||
- this.connection = new ServerConnectionListener(this);
|
||||
+ // this.connection = new ServerConnectionListener(this); // Spigot
|
||||
this.tickRateManager = new ServerTickRateManager(this);
|
||||
- this.levelLoadListener = levelLoadListener;
|
||||
+ // Paper - per-level load listener - move LevelLoadListener to ServerLevel
|
||||
this.storageSource = storageSource;
|
||||
this.playerDataStorage = storageSource.createPlayerStorage();
|
||||
this.randomSequences = this.savedDataStorage.computeIfAbsent(RandomSequences.TYPE);
|
||||
- this.weatherData = this.getDataStorage().computeIfAbsent(WeatherData.TYPE);
|
||||
- this.gameRules = new GameRules(this.worldData.enabledFeatures(), this.savedDataStorage.computeIfAbsent(GameRuleMap.TYPE));
|
||||
- gameRules.ifPresent(g -> this.gameRules.setAll(g, null));
|
||||
+ // Paper - per-level WeatherData
|
||||
+ // Paper - per-level GameRules
|
||||
this.fixerUpper = fixerUpper;
|
||||
this.functionManager = new ServerFunctionManager(this, this.resources.managers.getFunctionLibrary());
|
||||
HolderGetter<Block> blockLookup = this.registries
|
||||
@@ -362,8 +_,40 @@
|
||||
this.clockManager = this.getDataStorage().computeIfAbsent(ServerClockManager.TYPE);
|
||||
this.clockManager.init(this);
|
||||
this.customBossEvents = this.savedDataStorage.computeIfAbsent(CustomBossEvents.TYPE);
|
||||
- this.scheduledEvents = this.savedDataStorage.computeIfAbsent(TimerQueue.TYPE);
|
||||
- }
|
||||
+ // Paper - per-level scheduledEvents
|
||||
+ }
|
||||
}
|
||||
|
||||
- this.savedDataStorage = new SavedDataStorage(storageSource.getLevelPath(LevelResource.DATA), fixerUpper, this.registries.compositeAccess());
|
||||
+ this.savedDataStorage = new SavedDataStorage(storageSource.getLevelPath(LevelResource.ROOT).resolve(LevelResource.DATA.id()), fixerUpper, this.registries.compositeAccess()); // Paper - save in level storage
|
||||
this.worldData = worldStem.worldDataAndGenSettings().data();
|
||||
this.worldGenSettings = worldStem.worldDataAndGenSettings().genSettings();
|
||||
- this.savedDataStorage.set(WorldGenSettings.TYPE, this.worldGenSettings);
|
||||
+ // this.savedDataStorage.set(WorldGenSettings.TYPE, this.worldGenSettings); // Paper - save in level storage
|
||||
this.proxy = proxy;
|
||||
this.packRepository = packRepository;
|
||||
this.resources = new MinecraftServer.ReloadableResources(worldStem.resourceManager(), worldStem.dataPackResources());
|
||||
this.services = services;
|
||||
- this.connection = new ServerConnectionListener(this);
|
||||
+ // this.connection = new ServerConnectionListener(this); // Spigot
|
||||
this.tickRateManager = new ServerTickRateManager(this);
|
||||
- this.levelLoadListener = levelLoadListener;
|
||||
+ // Paper - per-level load listener - move LevelLoadListener to ServerLevel
|
||||
this.storageSource = storageSource;
|
||||
this.playerDataStorage = storageSource.createPlayerStorage();
|
||||
this.randomSequences = this.savedDataStorage.computeIfAbsent(RandomSequences.TYPE);
|
||||
- this.weatherData = this.getDataStorage().computeIfAbsent(WeatherData.TYPE);
|
||||
- this.gameRules = new GameRules(this.worldData.enabledFeatures(), this.savedDataStorage.computeIfAbsent(GameRuleMap.TYPE));
|
||||
- gameRules.ifPresent(g -> this.gameRules.setAll(g, null));
|
||||
+ // Paper - per-level WeatherData
|
||||
+ // Paper - per-level GameRules
|
||||
this.fixerUpper = fixerUpper;
|
||||
this.functionManager = new ServerFunctionManager(this, this.resources.managers.getFunctionLibrary());
|
||||
HolderGetter<Block> blockLookup = this.registries.compositeAccess().lookupOrThrow(Registries.BLOCK).filterFeatures(this.worldData.enabledFeatures());
|
||||
@@ -360,7 +_,39 @@
|
||||
this.clockManager = this.getDataStorage().computeIfAbsent(ServerClockManager.TYPE);
|
||||
this.clockManager.init(this);
|
||||
this.customBossEvents = this.savedDataStorage.computeIfAbsent(CustomBossEvents.TYPE);
|
||||
- this.scheduledEvents = this.savedDataStorage.computeIfAbsent(TimerQueue.TYPE);
|
||||
+ // Paper - per-level scheduledEvents
|
||||
+ // CraftBukkit start
|
||||
+ this.options = options;
|
||||
+ this.worldLoaderContext = worldLoaderContext;
|
||||
@@ -279,7 +278,7 @@
|
||||
}
|
||||
|
||||
protected abstract boolean initServer() throws IOException;
|
||||
@@ -400,15 +_,15 @@
|
||||
@@ -393,15 +_,15 @@
|
||||
};
|
||||
}
|
||||
|
||||
@@ -300,7 +299,7 @@
|
||||
if (profiledDuration != null) {
|
||||
profiledDuration.finish(true);
|
||||
}
|
||||
@@ -422,33 +_,150 @@
|
||||
@@ -415,33 +_,150 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,9 +462,9 @@
|
||||
- this.setupDebugLevel(this.worldData);
|
||||
+ this.setupDebugLevel(this.worldData, overworld); // Paper - per-level GameRules
|
||||
}
|
||||
} catch (Throwable var20) {
|
||||
CrashReport report = CrashReport.forThrowable(var20, "Exception initializing level");
|
||||
@@ -465,25 +_,7 @@
|
||||
} catch (Throwable t) {
|
||||
CrashReport report = CrashReport.forThrowable(t, "Exception initializing level");
|
||||
@@ -458,25 +_,7 @@
|
||||
}
|
||||
|
||||
GlobalPos focusPos = this.selectLevelLoadFocusPos();
|
||||
@@ -492,7 +491,7 @@
|
||||
}
|
||||
|
||||
private static void setInitialSpawn(
|
||||
@@ -499,6 +_,28 @@
|
||||
@@ -492,6 +_,28 @@
|
||||
levelData.setSpawn(LevelData.RespawnData.of(level.dimension(), BlockPos.ZERO.above(80), 0.0F, 0.0F));
|
||||
} else {
|
||||
ServerChunkCache chunkSource = level.getChunkSource();
|
||||
@@ -506,7 +505,7 @@
|
||||
+ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().key().asString() + ")");
|
||||
+ } else {
|
||||
+ levelData.setSpawn(
|
||||
+ net.minecraft.world.level.storage.LevelData.RespawnData.of(
|
||||
+ LevelData.RespawnData.of(
|
||||
+ level.dimension(),
|
||||
+ org.bukkit.craftbukkit.util.CraftLocation.toBlockPos(spawn),
|
||||
+ spawn.getYaw(),
|
||||
@@ -521,7 +520,7 @@
|
||||
ChunkPos spawnChunk = ChunkPos.containing(chunkSource.randomState().sampler().findSpawnPosition());
|
||||
levelLoadListener.start(LevelLoadListener.Stage.PREPARE_GLOBAL_SPAWN, 0);
|
||||
levelLoadListener.updateFocus(level.dimension(), spawnChunk);
|
||||
@@ -544,19 +_,22 @@
|
||||
@@ -537,19 +_,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +547,7 @@
|
||||
chunkLoadCounter.track(level, () -> {
|
||||
TicketStorage savedTickets = level.getDataStorage().get(TicketStorage.TYPE);
|
||||
if (savedTickets != null) {
|
||||
@@ -565,17 +_,19 @@
|
||||
@@ -558,17 +_,19 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -574,7 +573,7 @@
|
||||
}
|
||||
|
||||
protected GlobalPos selectLevelLoadFocusPos() {
|
||||
@@ -649,19 +_,49 @@
|
||||
@@ -639,19 +_,49 @@
|
||||
this.stopServer();
|
||||
}
|
||||
|
||||
@@ -625,15 +624,15 @@
|
||||
}
|
||||
|
||||
LOGGER.info("Saving worlds");
|
||||
@@ -704,6 +_,20 @@
|
||||
} catch (IOException var4) {
|
||||
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4);
|
||||
@@ -694,6 +_,20 @@
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), e);
|
||||
}
|
||||
+ // Spigot start
|
||||
+ io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR.shutdown(); // Paper
|
||||
+ try {
|
||||
+ io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS); // Paper
|
||||
+ } catch (java.lang.InterruptedException ignored) {} // Paper
|
||||
+ } catch (InterruptedException _) {} // Paper
|
||||
+ if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
|
||||
+ LOGGER.info("Saving usercache.json");
|
||||
+ this.services().nameToIdCache().save(false); // Paper - Perf: Async GameProfileCache saving
|
||||
@@ -646,7 +645,7 @@
|
||||
}
|
||||
|
||||
public String getLocalIp() {
|
||||
@@ -719,6 +_,14 @@
|
||||
@@ -709,6 +_,14 @@
|
||||
}
|
||||
|
||||
public void halt(final boolean wait) {
|
||||
@@ -661,7 +660,7 @@
|
||||
this.running = false;
|
||||
if (wait) {
|
||||
try {
|
||||
@@ -729,6 +_,122 @@
|
||||
@@ -719,6 +_,122 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,7 +783,7 @@
|
||||
protected void runServer() {
|
||||
try {
|
||||
if (!this.initServer()) {
|
||||
@@ -736,30 +_,73 @@
|
||||
@@ -726,30 +_,73 @@
|
||||
}
|
||||
|
||||
this.nextTickTimeNanos = Util.getNanos();
|
||||
@@ -872,7 +871,7 @@
|
||||
|
||||
boolean sprinting = thisTickNanos == 0L;
|
||||
if (this.debugCommandProfilerDelayStart) {
|
||||
@@ -767,7 +_,7 @@
|
||||
@@ -757,7 +_,7 @@
|
||||
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
|
||||
}
|
||||
|
||||
@@ -881,7 +880,7 @@
|
||||
|
||||
try (Profiler.Scope ignored = Profiler.use(this.createProfiler())) {
|
||||
this.processPacketsAndTick(sprinting);
|
||||
@@ -776,7 +_,7 @@
|
||||
@@ -766,7 +_,7 @@
|
||||
this.mayHaveDelayedTasks = true;
|
||||
this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + thisTickNanos, this.nextTickTimeNanos);
|
||||
this.startMeasuringTaskExecutionTime();
|
||||
@@ -890,16 +889,16 @@
|
||||
this.finishMeasuringTaskExecutionTime();
|
||||
if (sprinting) {
|
||||
this.tickRateManager.endTickWork();
|
||||
@@ -810,7 +_,7 @@
|
||||
} catch (Throwable var64) {
|
||||
LOGGER.error("Exception stopping the server", var64);
|
||||
@@ -800,7 +_,7 @@
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("Exception stopping the server", t);
|
||||
} finally {
|
||||
- this.onServerExit();
|
||||
+ //this.onServerExit(); // Paper - Improved watchdog support; moved into stop
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -862,7 +_,14 @@
|
||||
@@ -852,7 +_,14 @@
|
||||
}
|
||||
|
||||
private boolean haveTime() {
|
||||
@@ -915,7 +914,7 @@
|
||||
}
|
||||
|
||||
public NotificationManager notificationManager() {
|
||||
@@ -870,11 +_,11 @@
|
||||
@@ -860,11 +_,11 @@
|
||||
}
|
||||
|
||||
protected void waitUntilNextTick() {
|
||||
@@ -929,7 +928,7 @@
|
||||
} finally {
|
||||
this.waitingForNextTick = false;
|
||||
}
|
||||
@@ -892,18 +_,38 @@
|
||||
@@ -882,18 +_,38 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -972,26 +971,26 @@
|
||||
this.mayHaveDelayedTasks = mayHaveMoreTasks;
|
||||
return mayHaveMoreTasks;
|
||||
}
|
||||
@@ -912,15 +_,16 @@
|
||||
if (super.pollTask()) {
|
||||
@@ -903,15 +_,16 @@
|
||||
return true;
|
||||
} else {
|
||||
+ boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
if (this.tickRateManager.isSprinting() || this.shouldRunAllTasks() || this.haveTime()) {
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
if (level.getChunkSource().pollTask()) {
|
||||
- return true;
|
||||
+ ret = true; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
|
||||
+ boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
if (this.tickRateManager.isSprinting() || this.shouldRunAllTasks() || this.haveTime()) {
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
if (level.getChunkSource().pollTask()) {
|
||||
- return true;
|
||||
+ ret = true; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
|
||||
- return false;
|
||||
+ return ret; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
|
||||
- return false;
|
||||
+ return ret; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
|
||||
@@ -973,26 +_,44 @@
|
||||
@Override
|
||||
@@ -963,26 +_,44 @@
|
||||
}
|
||||
|
||||
protected void tickServer(final BooleanSupplier haveTime) {
|
||||
@@ -1037,7 +1036,7 @@
|
||||
this.tickCount++;
|
||||
this.tickRateManager.tick();
|
||||
this.tickChildren(haveTime);
|
||||
@@ -1002,11 +_,18 @@
|
||||
@@ -992,11 +_,18 @@
|
||||
}
|
||||
|
||||
this.ticksUntilAutosave--;
|
||||
@@ -1057,7 +1056,7 @@
|
||||
profiler.push("tallying");
|
||||
long tickTime = Util.getNanos() - nano;
|
||||
int tickIndex = this.tickCount % 100;
|
||||
@@ -1022,16 +_,16 @@
|
||||
@@ -1012,16 +_,16 @@
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("tick");
|
||||
this.tickFrame.start();
|
||||
@@ -1078,7 +1077,7 @@
|
||||
LOGGER.debug("Autosave started");
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("save");
|
||||
@@ -1073,7 +_,7 @@
|
||||
@@ -1063,7 +_,7 @@
|
||||
private ServerStatus buildServerStatus() {
|
||||
ServerStatus.Players players = this.buildPlayerStatus();
|
||||
return new ServerStatus(
|
||||
@@ -1087,16 +1086,16 @@
|
||||
Optional.of(players),
|
||||
Optional.of(ServerStatus.Version.current()),
|
||||
Optional.ofNullable(this.statusIcon),
|
||||
@@ -1087,7 +_,7 @@
|
||||
if (this.hidesOnlinePlayers()) {
|
||||
@@ -1078,7 +_,7 @@
|
||||
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||
} else {
|
||||
- int sampleSize = Math.min(players.size(), 12);
|
||||
+ int sampleSize = Math.min(players.size(), org.spigotmc.SpigotConfig.playerSample); // Paper - PaperServerListPingEvent
|
||||
ObjectArrayList<NameAndId> sample = new ObjectArrayList<>(sampleSize);
|
||||
int offset = Mth.nextInt(this.random, 0, players.size() - sampleSize);
|
||||
}
|
||||
|
||||
@@ -1104,12 +_,46 @@
|
||||
- int sampleSize = Math.min(players.size(), 12);
|
||||
+ int sampleSize = Math.min(players.size(), org.spigotmc.SpigotConfig.playerSample); // Paper - PaperServerListPingEvent
|
||||
ObjectArrayList<NameAndId> sample = new ObjectArrayList<>(sampleSize);
|
||||
int offset = Mth.nextInt(this.random, 0, players.size() - sampleSize);
|
||||
|
||||
@@ -1094,12 +_,46 @@
|
||||
protected void tickChildren(final BooleanSupplier haveTime) {
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
this.getPlayerList().getPlayers().forEach(playerx -> playerx.connection.suspendFlushing());
|
||||
@@ -1144,7 +1143,7 @@
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -1119,10 +_,20 @@
|
||||
@@ -1109,10 +_,20 @@
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -1165,7 +1164,7 @@
|
||||
profiler.push(() -> level + " " + level.dimension().identifier());
|
||||
profiler.push("tick");
|
||||
|
||||
@@ -1136,7 +_,9 @@
|
||||
@@ -1126,7 +_,9 @@
|
||||
|
||||
profiler.pop();
|
||||
profiler.pop();
|
||||
@@ -1175,7 +1174,7 @@
|
||||
|
||||
profiler.popPush("connection");
|
||||
this.tickConnection();
|
||||
@@ -1166,9 +_,12 @@
|
||||
@@ -1156,9 +_,12 @@
|
||||
this.serverActivityMonitor.tick();
|
||||
}
|
||||
|
||||
@@ -1190,7 +1189,7 @@
|
||||
this.effectiveRespawnData = respawnLevel.getWorldBorderAdjustedRespawnData(respawnData);
|
||||
}
|
||||
|
||||
@@ -1179,7 +_,11 @@
|
||||
@@ -1169,7 +_,11 @@
|
||||
public void forceGameTimeSynchronization() {
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("timeSync");
|
||||
@@ -1203,7 +1202,7 @@
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -1207,6 +_,22 @@
|
||||
@@ -1197,6 +_,22 @@
|
||||
return this.levels.get(dimension);
|
||||
}
|
||||
|
||||
@@ -1226,7 +1225,7 @@
|
||||
public Set<ResourceKey<Level>> levelKeys() {
|
||||
return this.levels.keySet();
|
||||
}
|
||||
@@ -1230,7 +_,7 @@
|
||||
@@ -1220,7 +_,7 @@
|
||||
}
|
||||
|
||||
public String getServerModName() {
|
||||
@@ -1235,7 +1234,7 @@
|
||||
}
|
||||
|
||||
public ServerClockManager clockManager() {
|
||||
@@ -1269,7 +_,7 @@
|
||||
@@ -1259,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void sendSystemMessage(final Component message) {
|
||||
@@ -1244,7 +1243,7 @@
|
||||
}
|
||||
|
||||
public KeyPair getKeyPair() {
|
||||
@@ -1306,11 +_,17 @@
|
||||
@@ -1296,11 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,7 +1266,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,6 +_,11 @@
|
||||
@@ -1316,6 +_,11 @@
|
||||
|
||||
public void setDifficultyLocked(final boolean locked) {
|
||||
this.worldData.setDifficultyLocked(locked);
|
||||
@@ -1279,7 +1278,7 @@
|
||||
this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
|
||||
}
|
||||
|
||||
@@ -1382,10 +_,20 @@
|
||||
@@ -1372,10 +_,20 @@
|
||||
|
||||
@Override
|
||||
public String getMotd() {
|
||||
@@ -1301,23 +1300,22 @@
|
||||
this.motd = motd;
|
||||
}
|
||||
|
||||
@@ -1414,17 +_,20 @@
|
||||
int count = 0;
|
||||
@@ -1405,16 +_,20 @@
|
||||
int count = 0;
|
||||
|
||||
for (ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||
- if (player.setGameMode(gameType)) {
|
||||
- count++;
|
||||
+ // Paper start - Expand PlayerGameModeChangeEvent
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = player.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null);
|
||||
+ if (event == null || event.isCancelled()) {
|
||||
+ continue;
|
||||
}
|
||||
+ count++;
|
||||
+ // Paper end - Expand PlayerGameModeChangeEvent
|
||||
for (ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||
- if (player.setGameMode(gameType)) {
|
||||
- count++;
|
||||
+ // Paper start - Expand PlayerGameModeChangeEvent
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = player.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null);
|
||||
+ if (event == null || event.isCancelled()) {
|
||||
+ continue;
|
||||
}
|
||||
-
|
||||
return count;
|
||||
+ count++;
|
||||
+ // Paper end - Expand PlayerGameModeChangeEvent
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public ServerConnectionListener getConnection() {
|
||||
@@ -1326,16 +1324,16 @@
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
@@ -1487,7 +_,7 @@
|
||||
@@ -1477,7 +_,7 @@
|
||||
@Override
|
||||
public void executeIfPossible(final Runnable command) {
|
||||
if (this.isStopped()) {
|
||||
- throw new RejectedExecutionException("Server already shutting down");
|
||||
+ throw new io.papermc.paper.util.ServerStopRejectedExecutionException("Server already shutting down"); // Paper - do not prematurely disconnect players on stop
|
||||
} else {
|
||||
super.executeIfPossible(command);
|
||||
}
|
||||
@@ -1522,7 +_,16 @@
|
||||
|
||||
super.executeIfPossible(command);
|
||||
@@ -1512,7 +_,16 @@
|
||||
return this.functionManager;
|
||||
}
|
||||
|
||||
@@ -1352,7 +1350,7 @@
|
||||
CompletableFuture<Void> result = CompletableFuture.<ImmutableList>supplyAsync(
|
||||
() -> packsToEnable.stream()
|
||||
.map(this.packRepository::getPack)
|
||||
@@ -1534,7 +_,7 @@
|
||||
@@ -1524,7 +_,7 @@
|
||||
.thenCompose(
|
||||
packsToLoad -> {
|
||||
CloseableResourceManager resources = new MultiPackResourceManager(PackType.SERVER_DATA, packsToLoad);
|
||||
@@ -1361,7 +1359,7 @@
|
||||
return ReloadableServerResources.loadResources(
|
||||
resources,
|
||||
this.registries,
|
||||
@@ -1554,18 +_,37 @@
|
||||
@@ -1544,18 +_,37 @@
|
||||
}
|
||||
)
|
||||
.thenAcceptAsync(newResources -> {
|
||||
@@ -1401,7 +1399,7 @@
|
||||
}, this);
|
||||
if (this.isSameThread()) {
|
||||
this.managedBlock(result::isDone);
|
||||
@@ -1580,7 +_,7 @@
|
||||
@@ -1570,7 +_,7 @@
|
||||
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
|
||||
FeatureFlagSet forcedFeatures = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
|
||||
FeatureFlagSet allowedFeatures = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
|
||||
@@ -1409,8 +1407,8 @@
|
||||
+ packRepository.reload(true); // Paper - will load resource packs
|
||||
if (safeMode) {
|
||||
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), forcedFeatures, false);
|
||||
} else {
|
||||
@@ -1635,7 +_,7 @@
|
||||
}
|
||||
@@ -1625,7 +_,7 @@
|
||||
private static WorldDataConfiguration configureRepositoryWithSelection(
|
||||
final PackRepository packRepository, final Collection<String> selected, final FeatureFlagSet forcedFeatures, final boolean disableInactive
|
||||
) {
|
||||
@@ -1419,7 +1417,7 @@
|
||||
enableForcedFeaturePacks(packRepository, forcedFeatures);
|
||||
DataPackConfig packConfig = getSelectedPacks(packRepository, disableInactive);
|
||||
FeatureFlagSet packRequestedFeatures = packRepository.getRequestedFeatureFlags().join(forcedFeatures);
|
||||
@@ -1667,7 +_,7 @@
|
||||
@@ -1657,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1428,7 +1426,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,8 +_,8 @@
|
||||
@@ -1674,8 +_,8 @@
|
||||
UserWhiteList whiteList = playerList.getWhiteList();
|
||||
|
||||
for (ServerPlayer player : Lists.newArrayList(playerList.getPlayers())) {
|
||||
@@ -1439,7 +1437,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1715,12 +_,12 @@
|
||||
@@ -1705,12 +_,12 @@
|
||||
}
|
||||
|
||||
public ServerLevel findRespawnDimension() {
|
||||
@@ -1454,7 +1452,7 @@
|
||||
public void setRespawnData(final LevelData.RespawnData respawnData) {
|
||||
ServerLevelData levelData = this.worldData.overworldData();
|
||||
LevelData.RespawnData oldRespawnData = levelData.getRespawnData();
|
||||
@@ -1788,17 +_,20 @@
|
||||
@@ -1778,17 +_,20 @@
|
||||
return this.randomSequences;
|
||||
}
|
||||
|
||||
@@ -1480,16 +1478,16 @@
|
||||
}
|
||||
|
||||
public boolean isEnforceWhitelist() {
|
||||
@@ -1889,7 +_,7 @@
|
||||
@@ -1879,7 +_,7 @@
|
||||
private void dumpGameRules(final Path path) throws IOException {
|
||||
try (Writer output = Files.newBufferedWriter(path)) {
|
||||
final List<String> entries = Lists.newArrayList();
|
||||
- final GameRules gameRules = this.getGameRules();
|
||||
+ final GameRules gameRules = this.overworld().getGameRules(); // Paper - per-level GameRules
|
||||
gameRules.visitGameRuleTypes(new GameRuleTypeVisitor() {
|
||||
{
|
||||
Objects.requireNonNull(MinecraftServer.this);
|
||||
@@ -1951,6 +_,17 @@
|
||||
@Override
|
||||
public <T> void visit(final GameRule<T> gameRule) {
|
||||
@@ -1937,6 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1507,7 +1505,7 @@
|
||||
private ProfilerFiller createProfiler() {
|
||||
if (this.willStartRecordingMetrics) {
|
||||
this.metricsRecorder = ActiveMetricsRecorder.createStarted(
|
||||
@@ -2071,16 +_,22 @@
|
||||
@@ -2057,16 +_,22 @@
|
||||
}
|
||||
|
||||
public void logChatMessage(final Component message, final ChatType.Bound chatType, final @Nullable String tag) {
|
||||
@@ -1534,7 +1532,7 @@
|
||||
}
|
||||
|
||||
public boolean logIPs() {
|
||||
@@ -2091,8 +_,9 @@
|
||||
@@ -2077,8 +_,9 @@
|
||||
LOGGER.debug("Received custom click action {} with payload {}", id, payload.orElse(null));
|
||||
}
|
||||
|
||||
@@ -1545,7 +1543,7 @@
|
||||
}
|
||||
|
||||
public boolean setAutoSave(final boolean enable) {
|
||||
@@ -2118,12 +_,14 @@
|
||||
@@ -2104,12 +_,14 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1563,7 +1561,7 @@
|
||||
player.connection.send(new ClientboundEntityEventPacket(player, event));
|
||||
}
|
||||
} else if (rule == GameRules.LIMITED_CRAFTING || rule == GameRules.IMMEDIATE_RESPAWN) {
|
||||
@@ -2131,20 +_,21 @@
|
||||
@@ -2117,20 +_,21 @@
|
||||
? ClientboundGameEventPacket.LIMITED_CRAFTING
|
||||
: ClientboundGameEventPacket.IMMEDIATE_RESPAWN;
|
||||
ClientboundGameEventPacket packet = new ClientboundGameEventPacket(eventType, (Boolean)value ? 1.0F : 0.0F);
|
||||
@@ -1590,7 +1588,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2157,12 +_,14 @@
|
||||
@@ -2143,12 +_,14 @@
|
||||
return this.savedDataStorage;
|
||||
}
|
||||
|
||||
@@ -1607,7 +1605,7 @@
|
||||
}
|
||||
|
||||
public boolean acceptsTransfers() {
|
||||
@@ -2312,4 +_,53 @@
|
||||
@@ -2294,4 +_,53 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/server/commands/BanIpCommands.java
|
||||
+++ b/net/minecraft/server/commands/BanIpCommands.java
|
||||
@@ -62,7 +_,7 @@
|
||||
}
|
||||
@@ -63,7 +_,7 @@
|
||||
}
|
||||
|
||||
for (ServerPlayer player : players) {
|
||||
- player.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"));
|
||||
+ player.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"), org.bukkit.event.player.PlayerKickEvent.Cause.IP_BANNED); // Paper - kick event cause
|
||||
}
|
||||
for (ServerPlayer player : players) {
|
||||
- player.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"));
|
||||
+ player.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"), org.bukkit.event.player.PlayerKickEvent.Cause.IP_BANNED); // Paper - kick event cause
|
||||
}
|
||||
|
||||
return players.size();
|
||||
return players.size();
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/commands/DebugCommand.java
|
||||
+++ b/net/minecraft/server/commands/DebugCommand.java
|
||||
@@ -277,6 +_,13 @@
|
||||
@@ -273,6 +_,13 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
+
|
||||
@Override
|
||||
public void close() {
|
||||
IOUtils.closeQuietly((Writer)this.output);
|
||||
IOUtils.closeQuietly(this.output);
|
||||
+7
-6
@@ -1,15 +1,16 @@
|
||||
--- a/net/minecraft/server/commands/DifficultyCommand.java
|
||||
+++ b/net/minecraft/server/commands/DifficultyCommand.java
|
||||
@@ -31,10 +_,10 @@
|
||||
@@ -31,11 +_,11 @@
|
||||
|
||||
public static int setDifficulty(final CommandSourceStack source, final Difficulty difficulty) throws CommandSyntaxException {
|
||||
MinecraftServer server = source.getServer();
|
||||
- if (server.getWorldData().getDifficulty() == difficulty) {
|
||||
+ if (source.getLevel().getDifficulty() == difficulty) { // CraftBukkit
|
||||
throw ERROR_ALREADY_SAME_DIFFICULTY.create(difficulty.getSerializedName());
|
||||
} else {
|
||||
- server.setDifficulty(difficulty, true);
|
||||
+ server.setDifficulty(source.getLevel(), difficulty, source, true); // Paper - per level difficulty; don't skip other difficulty-changing logic (fix upstream's fix); WorldDifficultyChangeEvent
|
||||
source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- server.setDifficulty(difficulty, true);
|
||||
+ server.setDifficulty(source.getLevel(), difficulty, source, true); // Paper - per level difficulty; don't skip other difficulty-changing logic (fix upstream's fix); WorldDifficultyChangeEvent
|
||||
source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -62,7 +_,7 @@
|
||||
ItemStack copyToDrop = prototypeItemStack.copyWithCount(size);
|
||||
boolean added = player.getInventory().add(copyToDrop);
|
||||
if (added && copyToDrop.isEmpty()) {
|
||||
- ItemEntity drop = player.drop(prototypeItemStack.copy(), false);
|
||||
+ ItemEntity drop = player.drop(prototypeItemStack.copy(), false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
|
||||
if (drop != null) {
|
||||
drop.makeFakeItem();
|
||||
}
|
||||
@@ -80,7 +_,7 @@
|
||||
);
|
||||
player.containerMenu.broadcastChanges();
|
||||
} else {
|
||||
- ItemEntity drop = player.drop(copyToDrop, false);
|
||||
+ ItemEntity drop = player.drop(copyToDrop, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
|
||||
if (drop != null) {
|
||||
drop.setNoPickUpDelay();
|
||||
drop.setTarget(player.getUUID());
|
||||
@@ -63,7 +_,7 @@
|
||||
ItemStack copyToDrop = prototypeItemStack.copyWithCount(size);
|
||||
boolean added = player.getInventory().add(copyToDrop);
|
||||
if (added && copyToDrop.isEmpty()) {
|
||||
- ItemEntity drop = player.drop(prototypeItemStack.copy(), false);
|
||||
+ ItemEntity drop = player.drop(prototypeItemStack.copy(), false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
|
||||
if (drop != null) {
|
||||
drop.makeFakeItem();
|
||||
}
|
||||
@@ -81,7 +_,7 @@
|
||||
);
|
||||
player.containerMenu.broadcastChanges();
|
||||
} else {
|
||||
- ItemEntity drop = player.drop(copyToDrop, false);
|
||||
+ ItemEntity drop = player.drop(copyToDrop, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
|
||||
if (drop != null) {
|
||||
drop.setNoPickUpDelay();
|
||||
drop.setTarget(player.getUUID());
|
||||
@@ -98,7 +_,7 @@
|
||||
);
|
||||
} else {
|
||||
source.sendSuccess(
|
||||
- () -> Component.translatable("commands.give.success.single", count, prototypeItemStack.getDisplayName(), players.size()), true
|
||||
+ () -> Component.translatable("commands.give.success.multiple", count, prototypeItemStack.getDisplayName(), players.size()), true // Paper - MC-151857 - correct translation key
|
||||
);
|
||||
}
|
||||
true
|
||||
);
|
||||
} else {
|
||||
- source.sendSuccess(() -> Component.translatable("commands.give.success.single", count, prototypeItemStack.getDisplayName(), players.size()), true);
|
||||
+ source.sendSuccess(() -> Component.translatable("commands.give.success.multiple", count, prototypeItemStack.getDisplayName(), players.size()), true); // Paper - MC-151857 - correct translation key
|
||||
}
|
||||
|
||||
return players.size();
|
||||
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/server/commands/KickCommand.java
|
||||
+++ b/net/minecraft/server/commands/KickCommand.java
|
||||
@@ -42,7 +_,7 @@
|
||||
@@ -43,7 +_,7 @@
|
||||
|
||||
for (ServerPlayer player : players) {
|
||||
if (!source.getServer().isSingleplayerOwner(player.nameAndId())) {
|
||||
- player.connection.disconnect(reason);
|
||||
+ player.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause
|
||||
source.sendSuccess(() -> Component.translatable("commands.kick.success", player.getDisplayName(), reason), true);
|
||||
count++;
|
||||
}
|
||||
for (ServerPlayer player : players) {
|
||||
if (!source.getServer().isSingleplayerOwner(player.nameAndId())) {
|
||||
- player.connection.disconnect(reason);
|
||||
+ player.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause
|
||||
source.sendSuccess(() -> Component.translatable("commands.kick.success", player.getDisplayName(), reason), true);
|
||||
count++;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
--- a/net/minecraft/server/commands/PlaceCommand.java
|
||||
+++ b/net/minecraft/server/commands/PlaceCommand.java
|
||||
@@ -298,6 +_,7 @@
|
||||
if (!start.isValid()) {
|
||||
@@ -299,6 +_,7 @@
|
||||
throw ERROR_STRUCTURE_FAILED.create();
|
||||
} else {
|
||||
+ start.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause
|
||||
BoundingBox boundingBox = start.getBoundingBox();
|
||||
ChunkPos chunkMin = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ()));
|
||||
ChunkPos chunkMax = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ()));
|
||||
}
|
||||
|
||||
+ start.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause
|
||||
BoundingBox boundingBox = start.getBoundingBox();
|
||||
ChunkPos chunkMin = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ()));
|
||||
ChunkPos chunkMax = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ()));
|
||||
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/server/commands/RideCommand.java
|
||||
+++ b/net/minecraft/server/commands/RideCommand.java
|
||||
@@ -54,7 +_,7 @@
|
||||
Entity currentVehicle = target.getVehicle();
|
||||
if (currentVehicle != null) {
|
||||
@@ -56,7 +_,7 @@
|
||||
throw ERROR_ALREADY_RIDING.create(target.getDisplayName(), currentVehicle.getDisplayName());
|
||||
- } else if (vehicle.is(EntityType.PLAYER)) {
|
||||
+ } else if (vehicle.is(EntityType.PLAYER) && !io.papermc.paper.configuration.GlobalConfiguration.get().commands.rideCommandAllowPlayerAsVehicle) { // Paper - allow player as vehicle
|
||||
}
|
||||
|
||||
- if (vehicle.is(EntityType.PLAYER)) {
|
||||
+ if (vehicle.is(EntityType.PLAYER) && !io.papermc.paper.configuration.GlobalConfiguration.get().commands.rideCommandAllowPlayerAsVehicle) { // Paper - allow player as vehicle
|
||||
throw ERROR_MOUNTING_PLAYER.create();
|
||||
} else if (target.getSelfAndPassengers().anyMatch(e -> e == vehicle)) {
|
||||
throw ERROR_MOUNTING_LOOP.create();
|
||||
}
|
||||
|
||||
+11
-11
@@ -9,16 +9,16 @@
|
||||
);
|
||||
|
||||
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
@@ -101,7 +_,7 @@
|
||||
} else {
|
||||
long tickTime = source.getLevel().getGameTime() + time;
|
||||
Identifier callbackId = callback.getFirst();
|
||||
- TimerQueue<MinecraftServer> queue = source.getServer().getScheduledEvents();
|
||||
+ TimerQueue<MinecraftServer> queue = source.getLevel().scheduledEvents; // CraftBukkit - SPIGOT-6667: Use world specific function timer
|
||||
Optional<CommandFunction<CommandSourceStack>> function = callback.getSecond().left();
|
||||
if (function.isPresent()) {
|
||||
if (function.get() instanceof MacroFunction) {
|
||||
@@ -132,7 +_,7 @@
|
||||
@@ -102,7 +_,7 @@
|
||||
|
||||
long tickTime = source.getLevel().getGameTime() + time;
|
||||
Identifier callbackId = callback.getFirst();
|
||||
- TimerQueue<MinecraftServer> queue = source.getServer().getScheduledEvents();
|
||||
+ TimerQueue<MinecraftServer> queue = source.getLevel().scheduledEvents; // CraftBukkit - SPIGOT-6667: Use world specific function timer
|
||||
Optional<CommandFunction<CommandSourceStack>> function = callback.getSecond().left();
|
||||
if (function.isPresent()) {
|
||||
if (function.get() instanceof MacroFunction) {
|
||||
@@ -130,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static int remove(final CommandSourceStack source, final String id) throws CommandSyntaxException {
|
||||
@@ -26,4 +26,4 @@
|
||||
+ int count = source.getLevel().scheduledEvents.remove(id); // Paper - Make schedule command per-world
|
||||
if (count == 0) {
|
||||
throw ERROR_CANT_REMOVE.create(id);
|
||||
} else {
|
||||
}
|
||||
+24
-24
@@ -1,28 +1,28 @@
|
||||
--- a/net/minecraft/server/commands/SummonCommand.java
|
||||
+++ b/net/minecraft/server/commands/SummonCommand.java
|
||||
@@ -78,7 +_,7 @@
|
||||
BlockPos blockPos = BlockPos.containing(pos);
|
||||
if (!Level.isInSpawnableBounds(blockPos)) {
|
||||
@@ -80,7 +_,7 @@
|
||||
throw INVALID_POSITION.create();
|
||||
- } else if (source.getLevel().getDifficulty() == Difficulty.PEACEFUL && !type.value().isAllowedInPeaceful()) {
|
||||
+ } else if (source.getLevel().getDifficulty() == Difficulty.PEACEFUL && !type.value().isAllowedInPeaceful(nbt)) { // Paper - check peaceful override
|
||||
throw ERROR_FAILED_PEACEFUL.create();
|
||||
} else {
|
||||
CompoundTag entityTag = nbt.copy();
|
||||
@@ -86,6 +_,7 @@
|
||||
ServerLevel level = source.getLevel();
|
||||
Entity entity = EntityType.loadEntityRecursive(entityTag, level, EntitySpawnReason.COMMAND, e -> {
|
||||
e.snapTo(pos.x, pos.y, pos.z, e.getYRot(), e.getXRot());
|
||||
+ e.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND; // Paper - Entity#getEntitySpawnReason
|
||||
return e;
|
||||
});
|
||||
if (entity == null) {
|
||||
@@ -95,7 +_,7 @@
|
||||
mob.finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.COMMAND, null);
|
||||
}
|
||||
}
|
||||
|
||||
- if (!level.tryAddFreshEntityWithPassengers(entity)) {
|
||||
+ if (!level.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND"
|
||||
throw ERROR_DUPLICATE_UUID.create();
|
||||
} else {
|
||||
return entity;
|
||||
- if (source.getLevel().getDifficulty() == Difficulty.PEACEFUL && !type.value().isAllowedInPeaceful()) {
|
||||
+ if (source.getLevel().getDifficulty() == Difficulty.PEACEFUL && !type.value().isAllowedInPeaceful(nbt)) { // Paper - check peaceful override
|
||||
throw ERROR_FAILED_PEACEFUL.create();
|
||||
}
|
||||
|
||||
@@ -89,6 +_,7 @@
|
||||
ServerLevel level = source.getLevel();
|
||||
Entity entity = EntityType.loadEntityRecursive(entityTag, level, EntitySpawnReason.COMMAND, e -> {
|
||||
e.snapTo(pos.x, pos.y, pos.z, e.getYRot(), e.getXRot());
|
||||
+ e.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND; // Paper - Entity#getEntitySpawnReason
|
||||
return e;
|
||||
});
|
||||
if (entity == null) {
|
||||
@@ -99,7 +_,7 @@
|
||||
mob.finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.COMMAND, null);
|
||||
}
|
||||
|
||||
- if (!level.tryAddFreshEntityWithPassengers(entity)) {
|
||||
+ if (!level.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND"
|
||||
throw ERROR_DUPLICATE_UUID.create();
|
||||
} else {
|
||||
return entity;
|
||||
+9
-9
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/server/commands/TeleportCommand.java
|
||||
+++ b/net/minecraft/server/commands/TeleportCommand.java
|
||||
@@ -255,7 +_,7 @@
|
||||
float relativeOrAbsoluteXRot = relatives.contains(Relative.X_ROT) ? xRot - victim.getXRot() : xRot;
|
||||
float newYRot = Mth.wrapDegrees(relativeOrAbsoluteYRot);
|
||||
float newXRot = Mth.wrapDegrees(relativeOrAbsoluteXRot);
|
||||
- if (victim.teleportTo(level, relativeOrAbsoluteX, relativeOrAbsoluteY, relativeOrAbsoluteZ, relatives, newYRot, newXRot, true)) {
|
||||
+ if (victim.teleportTo(level, relativeOrAbsoluteX, relativeOrAbsoluteY, relativeOrAbsoluteZ, relatives, newYRot, newXRot, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND)) { // Paper - teleport cause
|
||||
if (lookAt != null) {
|
||||
lookAt.perform(source, victim);
|
||||
}
|
||||
@@ -256,7 +_,7 @@
|
||||
float relativeOrAbsoluteXRot = relatives.contains(Relative.X_ROT) ? xRot - victim.getXRot() : xRot;
|
||||
float newYRot = Mth.wrapDegrees(relativeOrAbsoluteYRot);
|
||||
float newXRot = Mth.wrapDegrees(relativeOrAbsoluteXRot);
|
||||
- if (victim.teleportTo(level, relativeOrAbsoluteX, relativeOrAbsoluteY, relativeOrAbsoluteZ, relatives, newYRot, newXRot, true)) {
|
||||
+ if (victim.teleportTo(level, relativeOrAbsoluteX, relativeOrAbsoluteY, relativeOrAbsoluteZ, relatives, newYRot, newXRot, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND)) { // Paper - teleport cause
|
||||
if (lookAt != null) {
|
||||
lookAt.perform(source, victim);
|
||||
}
|
||||
@@ -18,25 +18,24 @@
|
||||
long totalTicks = clockManager.getTotalTicks(clock);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.absolute", clock.getRegisteredName(), totalTicks), false);
|
||||
return wrapTime(totalTicks);
|
||||
@@ -151,7 +_,7 @@
|
||||
if (!clock.equals(timeline.value().clock())) {
|
||||
@@ -152,7 +_,7 @@
|
||||
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
|
||||
} else {
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long currentTicks = timeline.value().getCurrentTicks(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline", timeline.getRegisteredName(), currentTicks), false);
|
||||
return wrapTime(currentTicks);
|
||||
@@ -162,33 +_,53 @@
|
||||
if (!clock.equals(timeline.value().clock())) {
|
||||
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
|
||||
} else {
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long repetitions = timeline.value().getPeriodCount(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline.repetitions", timeline.getRegisteredName(), repetitions), false);
|
||||
return wrapTime(repetitions);
|
||||
}
|
||||
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long currentTicks = timeline.value().getCurrentTicks(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline", timeline.getRegisteredName(), currentTicks), false);
|
||||
return wrapTime(currentTicks);
|
||||
@@ -163,45 +_,67 @@
|
||||
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
|
||||
}
|
||||
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long repetitions = timeline.value().getPeriodCount(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline.repetitions", timeline.getRegisteredName(), repetitions), false);
|
||||
return wrapTime(repetitions);
|
||||
}
|
||||
|
||||
+ // Paper start - per-world time
|
||||
@@ -79,18 +78,19 @@
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager();
|
||||
+ java.util.OptionalLong targetTime = clockManager.getTotalTicksToTimeMarker(clock, timeMarkerId);
|
||||
+ if (targetTime.isEmpty()) {
|
||||
throw ERROR_NO_TIME_MARKER_FOUND.create(clock.getRegisteredName(), timeMarkerId);
|
||||
} else {
|
||||
+ final long currentTime = clockManager.getTotalTicks(clock);
|
||||
+ final org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.createTimeSkipEvent(source, targetTime.getAsLong() - currentTime);
|
||||
+ if (event.callEvent()) {
|
||||
+ clockManager.setTotalTicks(clock, currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
source.sendSuccess(
|
||||
() -> Component.translatable("commands.time.set.time_marker", clock.getRegisteredName(), timeMarkerId.identifier().toString()), true
|
||||
);
|
||||
@@ -197,13 +_,13 @@
|
||||
throw ERROR_NO_TIME_MARKER_FOUND.create(clock.getRegisteredName(), timeMarkerId);
|
||||
}
|
||||
|
||||
+ // Paper start - per-world time
|
||||
+ final long currentTime = clockManager.getTotalTicks(clock);
|
||||
+ final org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.createTimeSkipEvent(source, targetTime.getAsLong() - currentTime);
|
||||
+ if (event.callEvent()) {
|
||||
+ clockManager.setTotalTicks(clock, currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.set.time_marker", clock.getRegisteredName(), timeMarkerId.identifier().toString()), true);
|
||||
return wrapTime(clockManager.getTotalTicks(clock));
|
||||
}
|
||||
|
||||
private static int setPaused(final CommandSourceStack source, final Holder<WorldClock> clock, final boolean paused) {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
private static void mutateIcon(final CommandSourceStack source, final WaypointTransmitter waypoint, final Consumer<Waypoint.Icon> iconConsumer) {
|
||||
- ServerLevel level = source.getLevel();
|
||||
+ ServerLevel level = (waypoint instanceof LivingEntity livingEntity) ? (net.minecraft.server.level.ServerLevel) livingEntity.level() : source.getLevel(); // Paper - MC-300685 use level of waypoint if it's a living entity for broadcast
|
||||
+ ServerLevel level = (waypoint instanceof LivingEntity livingEntity) ? (ServerLevel) livingEntity.level() : source.getLevel(); // Paper - MC-300685 use level of waypoint if it's a living entity for broadcast
|
||||
level.getWaypointManager().untrackWaypoint(waypoint);
|
||||
iconConsumer.accept(waypoint.waypointIcon());
|
||||
level.getWaypointManager().trackWaypoint(waypoint);
|
||||
+55
-54
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -84,9 +_,9 @@
|
||||
@@ -83,9 +_,9 @@
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int CONVERSION_RETRY_DELAY_MS = 5000;
|
||||
private static final int CONVERSION_RETRIES = 2;
|
||||
@@ -12,7 +12,7 @@
|
||||
private @Nullable RconThread rconThread;
|
||||
public DedicatedServerSettings settings;
|
||||
private @Nullable MinecraftServerGui gui;
|
||||
@@ -99,6 +_,7 @@
|
||||
@@ -98,6 +_,7 @@
|
||||
private long lastHeartbeat;
|
||||
|
||||
public DedicatedServer(
|
||||
@@ -20,7 +20,7 @@
|
||||
final Thread serverThread,
|
||||
final LevelStorageSource.LevelStorageAccess levelStorageSource,
|
||||
final PackRepository packRepository,
|
||||
@@ -109,6 +_,7 @@
|
||||
@@ -108,6 +_,7 @@
|
||||
final Services services
|
||||
) {
|
||||
super(
|
||||
@@ -28,7 +28,7 @@
|
||||
serverThread,
|
||||
levelStorageSource,
|
||||
packRepository,
|
||||
@@ -121,7 +_,8 @@
|
||||
@@ -120,7 +_,8 @@
|
||||
true
|
||||
);
|
||||
this.settings = settings;
|
||||
@@ -38,8 +38,8 @@
|
||||
this.serverTextFilter = ServerTextFilter.createFromConfig(settings.getProperties());
|
||||
this.serverLinks = createServerLinks(settings);
|
||||
if (settings.getProperties().codeOfConduct) {
|
||||
@@ -211,6 +_,10 @@
|
||||
|
||||
@@ -206,6 +_,10 @@
|
||||
Thread consoleThread = new Thread("Server console handler") {
|
||||
@Override
|
||||
public void run() {
|
||||
+ if (!org.bukkit.craftbukkit.Main.useConsole) return; // CraftBukkit
|
||||
@@ -49,9 +49,9 @@
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
|
||||
|
||||
String line;
|
||||
@@ -221,16 +_,41 @@
|
||||
} catch (IOException var4) {
|
||||
DedicatedServer.LOGGER.error("Exception handling console input", (Throwable)var4);
|
||||
@@ -216,16 +_,41 @@
|
||||
} catch (IOException e) {
|
||||
DedicatedServer.LOGGER.error("Exception handling console input", e);
|
||||
}
|
||||
+ */
|
||||
+ // Paper end - Use TerminalConsoleAppender
|
||||
@@ -92,7 +92,7 @@
|
||||
LOGGER.info("Loading properties");
|
||||
DedicatedServerProperties properties = this.settings.getProperties();
|
||||
if (this.isSingleplayer()) {
|
||||
@@ -241,8 +_,45 @@
|
||||
@@ -236,8 +_,45 @@
|
||||
this.setLocalIp(properties.serverIp);
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
InetAddress localAddress = null;
|
||||
if (!this.getLocalIp().isEmpty()) {
|
||||
localAddress = InetAddress.getByName(this.getLocalIp());
|
||||
@@ -251,46 +_,72 @@
|
||||
@@ -246,47 +_,73 @@
|
||||
if (this.getPort() < 0) {
|
||||
this.setPort(properties.serverPort);
|
||||
}
|
||||
@@ -153,11 +153,11 @@
|
||||
try {
|
||||
- this.getConnection().startTcpServerListener(localAddress, this.getPort());
|
||||
+ this.getConnection().startTcpServerListener(bindAddress); // Paper - Unix domain socket support
|
||||
} catch (IOException var11) {
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("**** FAILED TO BIND TO PORT!");
|
||||
LOGGER.warn("The exception was: {}", var11.toString());
|
||||
LOGGER.warn("The exception was: {}", e.toString());
|
||||
LOGGER.warn("Perhaps a server is already running on that port?");
|
||||
+ if (true) throw new IllegalStateException("Failed to bind to port", var11); // Paper - Propagate failed to bind to port error
|
||||
+ if (true) throw new IllegalStateException("Failed to bind to port", e); // Paper - Propagate failed to bind to port error
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -200,37 +200,38 @@
|
||||
|
||||
if (!OldUsersConverter.areOldUserlistsRemoved()) {
|
||||
return false;
|
||||
} else {
|
||||
- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
+ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up
|
||||
this.tickTimeLogger = new RemoteSampleLogger(TpsDebugDimensions.values().length, this.debugSubscribers(), RemoteDebugSampleType.TICK_TIME);
|
||||
long levelNanoTime = Util.getNanos();
|
||||
this.services.nameToIdCache().resolveOfflineUsers(!this.usesAuthentication());
|
||||
LOGGER.info("Preparing level \"{}\"", this.getLevelIdName());
|
||||
- this.loadLevel();
|
||||
+ this.loadLevel(this.storageSource.getLevelId()); // CraftBukkit
|
||||
long elapsed = Util.getNanos() - levelNanoTime;
|
||||
String time = String.format(Locale.ROOT, "%.3fs", elapsed / 1.0E9);
|
||||
- LOGGER.info("Done ({})! For help, type \"help\"", time);
|
||||
+ LOGGER.info("Done preparing level \"{}\" ({})", this.getLevelIdName(), time); // Paper - Improve startup message, add total time
|
||||
+ this.initPostWorld(); // Paper - don't include plugins in world preparation time
|
||||
if (properties.announcePlayerAchievements != null) {
|
||||
- this.getGameRules().set(GameRules.SHOW_ADVANCEMENT_MESSAGES, properties.announcePlayerAchievements, this);
|
||||
+ this.getAllLevels().forEach(l -> l.getGameRules().set(GameRules.SHOW_ADVANCEMENT_MESSAGES, properties.announcePlayerAchievements, this.overworld())); // Paper - per-world game rules
|
||||
}
|
||||
|
||||
if (properties.enableQuery) {
|
||||
@@ -303,7 +_,7 @@
|
||||
this.rconThread = RconThread.create(this);
|
||||
}
|
||||
|
||||
- if (this.getMaxTickLength() > 0L) {
|
||||
+ if (false && this.getMaxTickLength() > 0L) { // Spigot - disable
|
||||
Thread watchdog = new Thread(new ServerWatchdog(this));
|
||||
watchdog.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(LOGGER));
|
||||
watchdog.setName("Server Watchdog");
|
||||
@@ -322,6 +_,12 @@
|
||||
}
|
||||
|
||||
- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
+ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up
|
||||
this.tickTimeLogger = new RemoteSampleLogger(TpsDebugDimensions.values().length, this.debugSubscribers(), RemoteDebugSampleType.TICK_TIME);
|
||||
long levelNanoTime = Util.getNanos();
|
||||
this.services.nameToIdCache().resolveOfflineUsers(!this.usesAuthentication());
|
||||
LOGGER.info("Preparing level \"{}\"", this.getLevelIdName());
|
||||
- this.loadLevel();
|
||||
+ this.loadLevel(this.storageSource.getLevelId()); // CraftBukkit
|
||||
long elapsed = Util.getNanos() - levelNanoTime;
|
||||
String time = String.format(Locale.ROOT, "%.3fs", elapsed / 1.0E9);
|
||||
- LOGGER.info("Done ({})! For help, type \"help\"", time);
|
||||
+ LOGGER.info("Done preparing level \"{}\" ({})", this.getLevelIdName(), time); // Paper - Improve startup message, add total time
|
||||
+ this.initPostWorld(); // Paper - don't include plugins in world preparation time
|
||||
if (properties.announcePlayerAchievements != null) {
|
||||
- this.getGameRules().set(GameRules.SHOW_ADVANCEMENT_MESSAGES, properties.announcePlayerAchievements, this);
|
||||
+ this.getAllLevels().forEach(l -> l.getGameRules().set(GameRules.SHOW_ADVANCEMENT_MESSAGES, properties.announcePlayerAchievements, this.overworld())); // Paper - per-world game rules
|
||||
}
|
||||
|
||||
if (properties.enableQuery) {
|
||||
@@ -299,7 +_,7 @@
|
||||
this.rconThread = RconThread.create(this);
|
||||
}
|
||||
|
||||
- if (this.getMaxTickLength() > 0L) {
|
||||
+ if (false && this.getMaxTickLength() > 0L) { // Spigot - disable
|
||||
Thread watchdog = new Thread(new ServerWatchdog(this));
|
||||
watchdog.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(LOGGER));
|
||||
watchdog.setName("Server Watchdog");
|
||||
@@ -317,6 +_,12 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
@@ -242,7 +243,7 @@
|
||||
@Override
|
||||
public boolean isEnforceWhitelist() {
|
||||
return this.settings.getProperties().enforceWhitelist.get();
|
||||
@@ -339,6 +_,7 @@
|
||||
@@ -334,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void setUsingWhitelist(final boolean usingWhitelist) {
|
||||
@@ -250,7 +251,7 @@
|
||||
this.settings.update(p -> p.whiteList.update(this.registryAccess(), usingWhitelist));
|
||||
}
|
||||
|
||||
@@ -400,7 +_,7 @@
|
||||
@@ -395,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
protected void forceDifficulty() {
|
||||
@@ -259,7 +260,7 @@
|
||||
}
|
||||
|
||||
public int viewDistance() {
|
||||
@@ -456,11 +_,11 @@
|
||||
@@ -451,11 +_,11 @@
|
||||
}
|
||||
|
||||
if (this.rconThread != null) {
|
||||
@@ -273,8 +274,8 @@
|
||||
}
|
||||
|
||||
if (this.jsonRpcServer != null) {
|
||||
@@ -470,6 +_,9 @@
|
||||
LOGGER.error("Interrupted while stopping the management server", (Throwable)var2);
|
||||
@@ -465,6 +_,9 @@
|
||||
LOGGER.error("Interrupted while stopping the management server", e);
|
||||
}
|
||||
}
|
||||
+
|
||||
@@ -283,7 +284,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -479,12 +_,20 @@
|
||||
@@ -474,12 +_,20 @@
|
||||
}
|
||||
|
||||
public void handleConsoleInput(final String msg, final CommandSourceStack source) {
|
||||
@@ -307,7 +308,7 @@
|
||||
this.getCommands().performPrefixedCommand(input.source, input.msg);
|
||||
}
|
||||
}
|
||||
@@ -624,12 +_,15 @@
|
||||
@@ -625,12 +_,15 @@
|
||||
|
||||
@Override
|
||||
public String getMotd() {
|
||||
@@ -325,7 +326,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -655,7 +_,11 @@
|
||||
@@ -656,7 +_,11 @@
|
||||
@Override
|
||||
public boolean enforceSecureProfile() {
|
||||
DedicatedServerProperties properties = this.getProperties();
|
||||
@@ -338,7 +339,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -740,21 +_,60 @@
|
||||
@@ -741,21 +_,60 @@
|
||||
|
||||
@Override
|
||||
public String getPluginNames() {
|
||||
@@ -404,7 +405,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -882,4 +_,15 @@
|
||||
@@ -883,4 +_,15 @@
|
||||
public Map<String, String> getCodeOfConducts() {
|
||||
return this.codeOfConductTexts;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/dedicated/ServerWatchdog.java
|
||||
+++ b/net/minecraft/server/dedicated/ServerWatchdog.java
|
||||
@@ -49,7 +_,7 @@
|
||||
@@ -48,7 +_,7 @@
|
||||
CrashReport report = createWatchdogCrashReport("Watching Server", this.server.getRunningThread().threadId());
|
||||
this.server.fillSystemReport(report.getSystemReport());
|
||||
CrashReportCategory serverStats = report.addCategory("Performance stats");
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
public static Properties loadFromFile(final Path file) {
|
||||
+ if (!Files.exists(file)) return new Properties(); // CraftBukkit - SPIGOT-7465, MC-264979: Don't load if file doesn't exist
|
||||
try {
|
||||
try {
|
||||
Properties var13;
|
||||
@@ -65,7 +_,53 @@
|
||||
try (InputStream is = Files.newInputStream(file)) {
|
||||
CharsetDecoder reportingUtf8Decoder = StandardCharsets.UTF_8
|
||||
@@ -57,7 +_,53 @@
|
||||
}
|
||||
|
||||
public void store(final Path output) {
|
||||
@@ -81,9 +81,9 @@
|
||||
+ java.io.BufferedWriter os = new java.io.BufferedWriter(new java.io.OutputStreamWriter(bufferedOutputStream, java.nio.charset.StandardCharsets.UTF_8.newEncoder()));
|
||||
+ // Paper end - allow skipping server.properties comments
|
||||
this.properties.store(os, "Minecraft server properties");
|
||||
} catch (IOException var7) {
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to store properties to file: {}", output);
|
||||
@@ -95,7 +_,7 @@
|
||||
@@ -87,7 +_,7 @@
|
||||
}
|
||||
|
||||
public @Nullable String getStringRaw(final String key) {
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
|
||||
protected <V> @Nullable V getLegacy(final String key, final Function<String, V> deserializer) {
|
||||
@@ -109,6 +_,16 @@
|
||||
@@ -101,6 +_,16 @@
|
||||
}
|
||||
|
||||
protected <V> V get(final String key, final Function<String, @Nullable V> deserializer, final Function<V, String> serializer, final V defaultValue) {
|
||||
@@ -109,7 +109,7 @@
|
||||
String value = this.getStringRaw(key);
|
||||
V result = MoreObjects.firstNonNull(value != null ? deserializer.apply(value) : null, defaultValue);
|
||||
this.properties.put(key, serializer.apply(result));
|
||||
@@ -191,7 +_,7 @@
|
||||
@@ -183,7 +_,7 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
public class MutableValue<V> implements Supplier<V> {
|
||||
private final String key;
|
||||
@@ -214,7 +_,7 @@
|
||||
@@ -204,7 +_,7 @@
|
||||
public T update(final RegistryAccess registryAccess, final V value) {
|
||||
Properties properties = Settings.this.cloneProperties();
|
||||
properties.put(this.key, this.serializer.apply(value));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -54,6 +_,13 @@
|
||||
@@ -53,6 +_,13 @@
|
||||
frame.pack();
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
@@ -14,15 +14,15 @@
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(final WindowEvent event) {
|
||||
@@ -75,6 +_,7 @@
|
||||
@@ -74,6 +_,7 @@
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
try {
|
||||
+ this.add(this.buildOnboardingPanel(), "North"); // Paper - Add onboarding message for initial server start
|
||||
this.add(this.buildChatPanel(), "Center");
|
||||
this.add(this.buildInfoPanel(), "West");
|
||||
} catch (Exception var3) {
|
||||
@@ -88,7 +_,7 @@
|
||||
} catch (Exception e) {
|
||||
@@ -87,7 +_,7 @@
|
||||
|
||||
private JComponent buildInfoPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
@@ -31,7 +31,7 @@
|
||||
this.finalizers.add(comp::close);
|
||||
panel.add(comp, "North");
|
||||
panel.add(this.buildPlayerPanel(), "Center");
|
||||
@@ -155,6 +_,7 @@
|
||||
@@ -150,6 +_,7 @@
|
||||
this.finalizers.forEach(Runnable::run);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
public void print(final JTextArea console, final JScrollPane scrollPane, final String line) {
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
SwingUtilities.invokeLater(() -> this.print(console, scrollPane, line));
|
||||
@@ -167,7 +_,7 @@
|
||||
@@ -162,7 +_,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -48,7 +48,7 @@
|
||||
} catch (BadLocationException var8) {
|
||||
}
|
||||
|
||||
@@ -176,4 +_,37 @@
|
||||
@@ -171,4 +_,37 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,14 +41,14 @@
|
||||
return this.getTickingChunkFuture().getNow(UNLOADED_LEVEL_CHUNK).orElse(null);
|
||||
}
|
||||
|
||||
@@ -127,6 +_,7 @@
|
||||
} else {
|
||||
boolean hadChangedSections = this.hasChangedSections;
|
||||
int sectionIndex = this.levelHeightAccessor.getSectionIndex(pos.getY());
|
||||
+ if (sectionIndex < 0 || sectionIndex >= this.changedBlocksPerSection.length) return false; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
ShortSet changedBlocksInSection = this.changedBlocksPerSection[sectionIndex];
|
||||
if (changedBlocksInSection == null) {
|
||||
this.hasChangedSections = true;
|
||||
@@ -128,6 +_,7 @@
|
||||
|
||||
boolean hadChangedSections = this.hasChangedSections;
|
||||
int sectionIndex = this.levelHeightAccessor.getSectionIndex(pos.getY());
|
||||
+ if (sectionIndex < 0 || sectionIndex >= this.changedBlocksPerSection.length) return false; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
ShortSet changedBlocksInSection = this.changedBlocksPerSection[sectionIndex];
|
||||
if (changedBlocksInSection == null) {
|
||||
this.hasChangedSections = true;
|
||||
@@ -270,6 +_,38 @@
|
||||
scheduler.onFullChunkStatusChange(this.pos, status);
|
||||
}
|
||||
|
||||
@@ -81,14 +81,14 @@
|
||||
CrashReport report = CrashReport.forThrowable(exception, "Chunk loading");
|
||||
CrashReportCategory category = report.addCategory("Chunk loading");
|
||||
category.setDetail("Details", details);
|
||||
@@ -385,6 +_,7 @@
|
||||
chunk.setTicketLevel(level);
|
||||
} else {
|
||||
chunk = new ChunkHolder(ChunkPos.unpack(node), level, this.level, this.lightEngine, this::onLevelChange, this);
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, chunk); // Paper
|
||||
}
|
||||
@@ -386,6 +_,7 @@
|
||||
chunk.setTicketLevel(level);
|
||||
} else {
|
||||
chunk = new ChunkHolder(ChunkPos.unpack(node), level, this.level, this.lightEngine, this::onLevelChange, this);
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, chunk); // Paper
|
||||
}
|
||||
|
||||
this.updatingChunkMap.put(node, chunk);
|
||||
this.updatingChunkMap.put(node, chunk);
|
||||
@@ -413,8 +_,8 @@
|
||||
|
||||
protected void saveAllChunks(final boolean flushStorage) {
|
||||
@@ -141,7 +141,7 @@
|
||||
}
|
||||
}, this.unloadQueue::add).whenComplete((ignored, throwable) -> {
|
||||
if (throwable != null) {
|
||||
@@ -841,7 +_,7 @@
|
||||
@@ -843,7 +_,7 @@
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@@ -150,7 +150,7 @@
|
||||
}
|
||||
|
||||
public net.minecraft.server.level.DistanceManager getDistanceManager() {
|
||||
@@ -868,10 +_,10 @@
|
||||
@@ -870,10 +_,10 @@
|
||||
.addColumn("fluid_ticks")
|
||||
.build(output);
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
Optional<ChunkAccess> chunk = Optional.ofNullable(holder.getLatestChunk());
|
||||
Optional<LevelChunk> fullChunk = chunk.flatMap(
|
||||
chunkAccess -> chunkAccess instanceof LevelChunk ? Optional.of((LevelChunk)chunkAccess) : Optional.empty()
|
||||
@@ -920,14 +_,14 @@
|
||||
@@ -922,14 +_,14 @@
|
||||
return this.upgradeChunkTag(
|
||||
tag,
|
||||
-1,
|
||||
@@ -183,7 +183,7 @@
|
||||
generatorIdentifier.ifPresent(identifier -> contextTag.putString("generator", identifier.toString()));
|
||||
return contextTag;
|
||||
}
|
||||
@@ -939,7 +_,7 @@
|
||||
@@ -941,7 +_,7 @@
|
||||
ChunkHolder holder = this.visibleChunkMap.get(spawnCandidateChunks.nextLong());
|
||||
if (holder != null) {
|
||||
LevelChunk chunk = holder.getTickingChunk();
|
||||
@@ -192,7 +192,7 @@
|
||||
output.add(chunk);
|
||||
}
|
||||
}
|
||||
@@ -959,8 +_,14 @@
|
||||
@@ -961,8 +_,14 @@
|
||||
}
|
||||
|
||||
public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) {
|
||||
@@ -208,7 +208,7 @@
|
||||
}
|
||||
|
||||
boolean anyPlayerCloseEnoughTo(final BlockPos pos, final int maxDistance) {
|
||||
@@ -976,8 +_,24 @@
|
||||
@@ -978,8 +_,24 @@
|
||||
}
|
||||
|
||||
private boolean anyPlayerCloseEnoughForSpawningInternal(final ChunkPos pos) {
|
||||
@@ -234,31 +234,32 @@
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -993,7 +_,7 @@
|
||||
Builder<ServerPlayer> builder = ImmutableList.builder();
|
||||
@@ -996,7 +_,7 @@
|
||||
Builder<ServerPlayer> builder = ImmutableList.builder();
|
||||
|
||||
for (ServerPlayer player : this.playerMap.getAllPlayers()) {
|
||||
- if (this.playerIsCloseEnoughForSpawning(player, pos)) {
|
||||
+ if (this.playerIsCloseEnoughForSpawning(player, pos, 16384.0)) { // Spigot
|
||||
builder.add(player);
|
||||
}
|
||||
for (ServerPlayer player : this.playerMap.getAllPlayers()) {
|
||||
- if (this.playerIsCloseEnoughForSpawning(player, pos)) {
|
||||
+ if (this.playerIsCloseEnoughForSpawning(player, pos, 16384.0)) { // Spigot
|
||||
builder.add(player);
|
||||
}
|
||||
@@ -1002,12 +_,12 @@
|
||||
}
|
||||
@@ -1004,13 +_,13 @@
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
- private boolean playerIsCloseEnoughForSpawning(final ServerPlayer player, final ChunkPos pos) {
|
||||
+ private boolean playerIsCloseEnoughForSpawning(final ServerPlayer player, final ChunkPos pos, final double range) { // Spigot
|
||||
if (player.isSpectator()) {
|
||||
return false;
|
||||
} else {
|
||||
double distanceToChunk = euclideanDistanceSquared(pos, player.position());
|
||||
- return distanceToChunk < 16384.0;
|
||||
+ return distanceToChunk < range; // Spigot
|
||||
}
|
||||
|
||||
double distanceToChunk = euclideanDistanceSquared(pos, player.position());
|
||||
- return distanceToChunk < 16384.0;
|
||||
+ return distanceToChunk < range; // Spigot
|
||||
}
|
||||
|
||||
@@ -1136,9 +_,19 @@
|
||||
private boolean playerIsCloseEnoughTo(final ServerPlayer player, final Vec3 pos, final int maxDistance) {
|
||||
@@ -1138,9 +_,19 @@
|
||||
}
|
||||
|
||||
public void addEntity(final Entity entity) {
|
||||
@@ -278,7 +279,7 @@
|
||||
if (range != 0) {
|
||||
int updateInterval = type.updateInterval();
|
||||
if (this.entityMap.containsKey(entity.getId())) {
|
||||
@@ -1162,6 +_,7 @@
|
||||
@@ -1164,6 +_,7 @@
|
||||
}
|
||||
|
||||
protected void removeEntity(final Entity entity) {
|
||||
@@ -286,18 +287,20 @@
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
this.updatePlayerStatus(player, false);
|
||||
|
||||
@@ -1329,8 +_,8 @@
|
||||
@@ -1325,10 +_,10 @@
|
||||
private final Entity entity;
|
||||
private final int range;
|
||||
private SectionPos lastSectionPos;
|
||||
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
|
||||
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
|
||||
Objects.requireNonNull(ChunkMap.this);
|
||||
super();
|
||||
- this.seenBy = Sets.newIdentityHashSet();
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this);
|
||||
+ this.seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this, this.seenBy); // Paper
|
||||
this.entity = entity;
|
||||
this.range = range;
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
@@ -1377,6 +_,7 @@
|
||||
@@ -1375,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void removePlayer(final ServerPlayer player) {
|
||||
@@ -305,7 +308,7 @@
|
||||
if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
if (this.seenBy.isEmpty()) {
|
||||
@@ -1386,23 +_,47 @@
|
||||
@@ -1384,23 +_,47 @@
|
||||
}
|
||||
|
||||
public void updatePlayer(final ServerPlayer player) {
|
||||
@@ -356,7 +359,7 @@
|
||||
}
|
||||
} else {
|
||||
this.removePlayer(player);
|
||||
@@ -1419,6 +_,7 @@
|
||||
@@ -1417,6 +_,7 @@
|
||||
|
||||
for (Entity passenger : this.entity.getIndirectPassengers()) {
|
||||
int passengerRange = passenger.getType().clientTrackingRange() * 16;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -73,6 +_,12 @@
|
||||
@@ -72,6 +_,12 @@
|
||||
}
|
||||
|
||||
if (!this.chunksToUpdateFutures.isEmpty()) {
|
||||
@@ -13,7 +13,7 @@
|
||||
for (ChunkHolder chunksToUpdateFuture : this.chunksToUpdateFutures) {
|
||||
chunksToUpdateFuture.updateHighestAllowedStatus(scheduler);
|
||||
}
|
||||
@@ -120,8 +_,10 @@
|
||||
@@ -119,8 +_,10 @@
|
||||
ChunkPos chunk = pos.chunk();
|
||||
long chunkPos = chunk.pack();
|
||||
ObjectSet<ServerPlayer> chunkPlayers = this.playersPerChunk.get(chunkPos);
|
||||
|
||||
+16
-24
@@ -31,7 +31,7 @@
|
||||
this.level = level;
|
||||
this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(level);
|
||||
@@ -99,7 +_,7 @@
|
||||
LOGGER.error("Failed to create dimension data storage directory", (Throwable)var14);
|
||||
LOGGER.error("Failed to create dimension data storage directory", e);
|
||||
}
|
||||
|
||||
- this.savedDataStorage = new SavedDataStorage(dataFolder, fixerUpper, level.registryAccess());
|
||||
@@ -83,11 +83,11 @@
|
||||
+ // Note: Partially copied from the getChunkAt method below
|
||||
+ @Nullable
|
||||
+ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) {
|
||||
+ long k = ChunkPos.pack(x, z);
|
||||
+ long key = ChunkPos.pack(x, z);
|
||||
+
|
||||
+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe
|
||||
+
|
||||
+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k);
|
||||
+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(key);
|
||||
+ if (playerChunk == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
@@ -104,23 +104,15 @@
|
||||
@Override
|
||||
public ThreadedLevelLightEngine getLightEngine() {
|
||||
return this.lightEngine;
|
||||
@@ -155,7 +_,7 @@
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (pos == this.lastChunkPos[i] && targetStatus == this.lastChunkStatus[i]) {
|
||||
ChunkAccess chunkAccess = this.lastChunk[i];
|
||||
- if (chunkAccess != null || !loadOrGenerate) {
|
||||
+ if (chunkAccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
|
||||
return chunkAccess;
|
||||
}
|
||||
@@ -156,7 +_,7 @@
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (pos == this.lastChunkPos[i] && targetStatus == this.lastChunkStatus[i]) {
|
||||
ChunkAccess chunkAccess = this.lastChunk[i];
|
||||
- if (chunkAccess != null || !loadOrGenerate) {
|
||||
+ if (chunkAccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
|
||||
return chunkAccess;
|
||||
}
|
||||
@@ -164,6 +_,7 @@
|
||||
profiler.incrementCounter("getChunkCacheMiss");
|
||||
CompletableFuture<ChunkResult<ChunkAccess>> serverFuture = this.getChunkFutureMainThread(x, z, targetStatus, loadOrGenerate);
|
||||
this.mainThreadProcessor.managedBlock(serverFuture::isDone);
|
||||
+ // com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads
|
||||
ChunkResult<ChunkAccess> chunkResult = serverFuture.join();
|
||||
ChunkAccess chunk = chunkResult.orElse(null);
|
||||
if (chunk == null && loadOrGenerate) {
|
||||
}
|
||||
@@ -236,7 +_,15 @@
|
||||
long key = pos.pack();
|
||||
int targetTicketLevel = ChunkLevel.byStatus(targetStatus);
|
||||
@@ -223,7 +215,7 @@
|
||||
} else {
|
||||
spawningCategories = List.of();
|
||||
}
|
||||
@@ -556,7 +_,13 @@
|
||||
@@ -558,7 +_,13 @@
|
||||
|
||||
@Override
|
||||
public void setSpawnSettings(final boolean spawnEnemies) {
|
||||
@@ -237,17 +229,17 @@
|
||||
}
|
||||
|
||||
public String getChunkDebugData(final ChunkPos pos) {
|
||||
@@ -624,12 +_,18 @@
|
||||
@@ -625,12 +_,18 @@
|
||||
|
||||
@Override
|
||||
protected boolean pollTask() {
|
||||
+ try { // CraftBukkit - process pending Chunk loadCallback() and unloadCallback() after each run task
|
||||
if (ServerChunkCache.this.runDistanceManagerUpdates()) {
|
||||
return true;
|
||||
} else {
|
||||
ServerChunkCache.this.lightEngine.tryScheduleUpdate();
|
||||
return super.pollTask();
|
||||
}
|
||||
|
||||
ServerChunkCache.this.lightEngine.tryScheduleUpdate();
|
||||
return super.pollTask();
|
||||
+ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
|
||||
+ } finally {
|
||||
+ ServerChunkCache.this.chunkMap.callbackExecutor.run();
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,16 +_,24 @@
|
||||
@@ -611,6 +_,13 @@
|
||||
}
|
||||
|
||||
protected BlockPos findLightningTargetAround(final BlockPos pos) {
|
||||
@@ -431,18 +431,20 @@
|
||||
BlockPos center = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
|
||||
Optional<BlockPos> lightningRodTarget = this.findLightningRod(center);
|
||||
if (lightningRodTarget.isPresent()) {
|
||||
return lightningRodTarget.get();
|
||||
} else {
|
||||
AABB search = AABB.encapsulatingFullBlocks(center, center.atY(this.getMaxY() + 1)).inflate(3.0);
|
||||
- List<LivingEntity> entities = this.getEntitiesOfClass(LivingEntity.class, search, input -> input.isAlive() && this.canSeeSky(input.blockPosition()));
|
||||
+ List<LivingEntity> entities = this.getEntitiesOfClass(LivingEntity.class, search, input -> input.isAlive() && this.canSeeSky(input.blockPosition()) && !input.isSpectator()); // Paper - Fix lightning being able to hit spectators (MC-262422)
|
||||
if (!entities.isEmpty()) {
|
||||
return entities.get(this.random.nextInt(entities.size())).blockPosition();
|
||||
} else {
|
||||
+ if (returnNullWhenNoTarget) return null; // Paper - Add methods to find targets for lightning strikes
|
||||
if (center.getY() == this.getMinY() - 1) {
|
||||
center = center.above(2);
|
||||
}
|
||||
@@ -618,11 +_,12 @@
|
||||
}
|
||||
|
||||
AABB search = AABB.encapsulatingFullBlocks(center, center.atY(this.getMaxY() + 1)).inflate(3.0);
|
||||
- List<LivingEntity> entities = this.getEntitiesOfClass(LivingEntity.class, search, input -> input.isAlive() && this.canSeeSky(input.blockPosition()));
|
||||
+ List<LivingEntity> entities = this.getEntitiesOfClass(LivingEntity.class, search, input -> input.isAlive() && this.canSeeSky(input.blockPosition()) && !input.isSpectator()); // Paper - Fix lightning being able to hit spectators (MC-262422)
|
||||
if (!entities.isEmpty()) {
|
||||
return entities.get(this.random.nextInt(entities.size())).blockPosition();
|
||||
}
|
||||
|
||||
+ if (returnNullWhenNoTarget) return null; // Paper - Add methods to find targets for lightning strikes
|
||||
if (center.getY() == this.getMinY() - 1) {
|
||||
center = center.above(2);
|
||||
}
|
||||
@@ -739,8 +_,8 @@
|
||||
weatherData.setThunderTime(thunderTime);
|
||||
weatherData.setRainTime(rainTime);
|
||||
@@ -682,11 +684,11 @@
|
||||
+ // CraftBukkit end
|
||||
if (entity.getSelfAndPassengers().map(Entity::getUUID).anyMatch(this.entityManager::isLoaded)) {
|
||||
return false;
|
||||
} else {
|
||||
- this.addFreshEntityWithPassengers(entity);
|
||||
+ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
|
||||
return true;
|
||||
}
|
||||
|
||||
- this.addFreshEntityWithPassengers(entity);
|
||||
+ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unload(final LevelChunk levelChunk) {
|
||||
@@ -976,8 +978,8 @@
|
||||
- if (!this.server.getWorldGenSettings().options().generateStructures()) {
|
||||
+ if (!this.worldGenSettings.options().generateStructures()) { // CraftBukkit
|
||||
return null;
|
||||
} else {
|
||||
Optional<HolderSet.Named<Structure>> tag = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
|
||||
}
|
||||
|
||||
@@ -1479,10 +_,36 @@
|
||||
|
||||
@Override
|
||||
@@ -1115,7 +1117,7 @@
|
||||
|
||||
@Override
|
||||
public CrashReportCategory fillReportDetails(final CrashReport report) {
|
||||
@@ -1905,6 +_,7 @@
|
||||
@@ -1900,6 +_,7 @@
|
||||
if (entity instanceof WaypointTransmitter waypoint && waypoint.isTransmittingWaypoint()) {
|
||||
ServerLevel.this.getWaypointManager().trackWaypoint(waypoint);
|
||||
}
|
||||
@@ -1123,7 +1125,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1918,17 +_,24 @@
|
||||
@@ -1913,17 +_,24 @@
|
||||
|
||||
@Override
|
||||
public void onTickingStart(final Entity entity) {
|
||||
@@ -1149,7 +1151,7 @@
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
ServerLevel.this.players.add(player);
|
||||
if (player.isReceivingWaypoints()) {
|
||||
@@ -1943,7 +_,7 @@
|
||||
@@ -1938,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (entity instanceof Mob mob) {
|
||||
@@ -1158,7 +1160,7 @@
|
||||
String message = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1960,10 +_,52 @@
|
||||
@@ -1955,10 +_,52 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
@@ -1211,7 +1213,7 @@
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
ServerLevel.this.players.remove(player);
|
||||
@@ -1972,7 +_,7 @@
|
||||
@@ -1967,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (entity instanceof Mob mob) {
|
||||
@@ -1220,7 +1222,7 @@
|
||||
String message = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1990,6 +_,15 @@
|
||||
@@ -1985,6 +_,15 @@
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
|
||||
ServerLevel.this.debugSynchronizers.dropEntity(entity);
|
||||
@@ -1236,7 +1238,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1997,4 +_,24 @@
|
||||
@@ -1992,4 +_,24 @@
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+123
-124
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -46,16 +_,37 @@
|
||||
@@ -46,17 +_,37 @@
|
||||
private BlockPos delayedDestroyPos = BlockPos.ZERO;
|
||||
private int delayedTickStart;
|
||||
private int lastSentState = -1;
|
||||
@@ -23,38 +23,40 @@
|
||||
+ // Paper end - Expand PlayerGameModeChangeEvent
|
||||
if (gameModeForPlayer == this.gameModeForPlayer) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
+ return null; // Paper - Expand PlayerGameModeChangeEvent
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = new org.bukkit.event.player.PlayerGameModeChangeEvent(
|
||||
+ this.player.getBukkitEntity(),
|
||||
+ org.bukkit.GameMode.getByValue(gameModeForPlayer.getId()),
|
||||
+ playerGameModeChangeCause, // Paper
|
||||
+ cancelMessage
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return event; // Paper - Expand PlayerGameModeChangeEvent
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Abilities abilities = this.player.getAbilities();
|
||||
this.setGameModeForPlayer(gameModeForPlayer, this.gameModeForPlayer);
|
||||
if (abilities.flying && gameModeForPlayer != GameType.SPECTATOR && this.isInRangeOfGround()) {
|
||||
@@ -66,13 +_,13 @@
|
||||
this.level
|
||||
.getServer()
|
||||
.getPlayerList()
|
||||
- .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player));
|
||||
+ .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit
|
||||
this.level.updateSleepingPlayerList();
|
||||
if (gameModeForPlayer == GameType.CREATIVE) {
|
||||
this.player.resetCurrentImpulseContext();
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ }
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = new org.bukkit.event.player.PlayerGameModeChangeEvent(
|
||||
+ this.player.getBukkitEntity(),
|
||||
+ org.bukkit.GameMode.getByValue(gameModeForPlayer.getId()),
|
||||
+ playerGameModeChangeCause,
|
||||
+ cancelMessage
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return event; // Paper - Expand PlayerGameModeChangeEvent
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Abilities abilities = this.player.getAbilities();
|
||||
this.setGameModeForPlayer(gameModeForPlayer, this.gameModeForPlayer);
|
||||
if (abilities.flying && gameModeForPlayer != GameType.SPECTATOR && this.isInRangeOfGround()) {
|
||||
@@ -67,13 +_,13 @@
|
||||
this.level
|
||||
.getServer()
|
||||
.getPlayerList()
|
||||
- .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player));
|
||||
+ .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit
|
||||
this.level.updateSleepingPlayerList();
|
||||
if (gameModeForPlayer == GameType.CREATIVE) {
|
||||
this.player.resetCurrentImpulseContext();
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ return event; // Paper - Expand PlayerGameModeChangeEvent
|
||||
}
|
||||
|
||||
protected void setGameModeForPlayer(final GameType gameModeForPlayer, final @Nullable GameType previousGameModeForPlayer) {
|
||||
@@ -105,10 +_,11 @@
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,17 +_,62 @@
|
||||
@@ -261,13 +_,53 @@
|
||||
|
||||
public boolean destroyBlock(final BlockPos pos) {
|
||||
BlockState state = this.level.getBlockState(pos);
|
||||
@@ -235,103 +237,98 @@
|
||||
+
|
||||
+ if (false && !this.player.getMainHandItem().canDestroyBlock(state, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
return false;
|
||||
} else {
|
||||
+ state = this.level.getBlockState(pos); // CraftBukkit - update state from plugins
|
||||
+ if (state.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling
|
||||
BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||
Block block = state.getBlock();
|
||||
- if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
|
||||
+ if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks() && !(block instanceof net.minecraft.world.level.block.CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission
|
||||
this.level.sendBlockUpdated(pos, state, state, Block.UPDATE_ALL);
|
||||
return false;
|
||||
} else if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.BlockState bState = bblock.getState();
|
||||
+ this.level.captureDrops = new java.util.ArrayList<>();
|
||||
+ // CraftBukkit end
|
||||
BlockState adjustedState = block.playerWillDestroy(this.level, pos, state, this.player);
|
||||
boolean changed = this.level.removeBlock(pos, false);
|
||||
if (SharedConstants.DEBUG_BLOCK_BREAK) {
|
||||
@@ -282,19 +_,44 @@
|
||||
block.destroy(this.level, pos, adjustedState);
|
||||
}
|
||||
|
||||
+ ItemStack mainHandStack = null; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ boolean isCorrectTool = false; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
if (this.player.preventsBlockDrops()) {
|
||||
- return true;
|
||||
+ // return true; // CraftBukkit
|
||||
} else {
|
||||
ItemStack itemStack = this.player.getMainHandItem();
|
||||
ItemStack destroyedWith = itemStack.copy();
|
||||
boolean canDestroy = this.player.hasCorrectToolForDrops(adjustedState);
|
||||
+ mainHandStack = destroyedWith; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ isCorrectTool = canDestroy; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
itemStack.mineBlock(this.level, adjustedState, pos, this.player);
|
||||
- if (changed && canDestroy) {
|
||||
- block.playerDestroy(this.level, this.player, pos, adjustedState, blockEntity, destroyedWith);
|
||||
- }
|
||||
}
|
||||
-
|
||||
- return true;
|
||||
- }
|
||||
+ if (changed && canDestroy) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
|
||||
+ block.playerDestroy(this.level, this.player, pos, adjustedState, blockEntity, destroyedWith, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion
|
||||
+ }
|
||||
+
|
||||
+ // return true; // CraftBukkit
|
||||
+ }
|
||||
+ // CraftBukkit start
|
||||
+ java.util.List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = this.level.captureDrops; // Paper - capture all item additions to the world
|
||||
+ this.level.captureDrops = null; // Paper - capture all item additions to the world; Remove this earlier so that we can actually drop stuff
|
||||
+ if (event.isDropItems()) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, bState, this.player, itemsToDrop); // Paper - capture all item additions to the world
|
||||
+ }
|
||||
+
|
||||
+ // Drop event experience
|
||||
+ if (changed) {
|
||||
+ state.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper
|
||||
+ }
|
||||
+ // Paper start - Trigger bee_nest_destroyed trigger in the correct place (check impls of block#playerDestroy)
|
||||
+ if (mainHandStack != null) {
|
||||
+ if (changed && isCorrectTool && event.isDropItems() && block instanceof net.minecraft.world.level.block.BeehiveBlock && blockEntity instanceof net.minecraft.world.level.block.entity.BeehiveBlockEntity beehiveBlockEntity) { // simulates the guard on block#playerDestroy above
|
||||
+ CriteriaTriggers.BEE_NEST_DESTROYED.trigger(player, state, mainHandStack, beehiveBlockEntity.getOccupantCount());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
+ state = this.level.getBlockState(pos); // CraftBukkit - update state from plugins
|
||||
+ if (state.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling
|
||||
BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||
Block block = state.getBlock();
|
||||
- if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
|
||||
+ if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks() && !(block instanceof net.minecraft.world.level.block.CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission
|
||||
this.level.sendBlockUpdated(pos, state, state, Block.UPDATE_ALL);
|
||||
return false;
|
||||
}
|
||||
@@ -276,6 +_,10 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.BlockState bState = bblock.getState();
|
||||
+ this.level.captureDrops = new java.util.ArrayList<>();
|
||||
+ // CraftBukkit end
|
||||
BlockState adjustedState = block.playerWillDestroy(this.level, pos, state, this.player);
|
||||
boolean changed = this.level.removeBlock(pos, false);
|
||||
if (SharedConstants.DEBUG_BLOCK_BREAK) {
|
||||
@@ -286,17 +_,38 @@
|
||||
block.destroy(this.level, pos, adjustedState);
|
||||
}
|
||||
|
||||
- if (this.player.preventsBlockDrops()) {
|
||||
- return true;
|
||||
- }
|
||||
+ ItemStack destroyedWith = null; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ boolean canDestroy = false; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
|
||||
+ if (!this.player.preventsBlockDrops()) { // CraftBukkit
|
||||
ItemStack itemStack = this.player.getMainHandItem();
|
||||
- ItemStack destroyedWith = itemStack.copy();
|
||||
- boolean canDestroy = this.player.hasCorrectToolForDrops(adjustedState);
|
||||
+ destroyedWith = itemStack.copy(); // Paper
|
||||
+ canDestroy = this.player.hasCorrectToolForDrops(adjustedState); // Paper
|
||||
itemStack.mineBlock(this.level, adjustedState, pos, this.player);
|
||||
if (changed && canDestroy) {
|
||||
- block.playerDestroy(this.level, this.player, pos, adjustedState, blockEntity, destroyedWith);
|
||||
- }
|
||||
+ block.playerDestroy(this.level, this.player, pos, adjustedState, blockEntity, destroyedWith, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion
|
||||
+ }
|
||||
+ } // CraftBukkit
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = this.level.captureDrops; // Paper - capture all item additions to the world
|
||||
+ this.level.captureDrops = null; // Paper - capture all item additions to the world; Remove this earlier so that we can actually drop stuff
|
||||
+ if (event.isDropItems()) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, bState, this.player, itemsToDrop); // Paper - capture all item additions to the world
|
||||
+ }
|
||||
+
|
||||
+ // Drop event experience
|
||||
+ if (changed) {
|
||||
+ state.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper
|
||||
+ }
|
||||
+ // Paper start - Trigger bee_nest_destroyed trigger in the correct place (check impls of block#playerDestroy)
|
||||
+ if (destroyedWith != null) {
|
||||
+ if (changed && canDestroy && event.isDropItems() && block instanceof net.minecraft.world.level.block.BeehiveBlock && blockEntity instanceof net.minecraft.world.level.block.entity.BeehiveBlockEntity beehiveBlockEntity) { // simulates the guard on block#playerDestroy above
|
||||
+ CriteriaTriggers.BEE_NEST_DESTROYED.trigger(this.player, state, destroyedWith, beehiveBlockEntity.getOccupantCount());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ // CraftBukkit end
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -307,6 +_,7 @@
|
||||
} else {
|
||||
int oldCount = itemStack.getCount();
|
||||
int oldDamage = itemStack.getDamageValue();
|
||||
+ final ItemStack stackBeforeUse = itemStack.copy(); // Paper - Store stack before use for interact prediction check
|
||||
InteractionResult result = itemStack.use(level, player, hand);
|
||||
ItemStack resultStack;
|
||||
if (result instanceof InteractionResult.Success success) {
|
||||
@@ -332,7 +_,14 @@
|
||||
}
|
||||
@@ -312,6 +_,7 @@
|
||||
|
||||
if (!player.isUsingItem()) {
|
||||
- player.inventoryMenu.sendAllDataToRemote();
|
||||
+ // Paper start - Optimize sendAllDataToRemote calls
|
||||
+ // This is a weird one where the Vanilla behavior is from an ancient version, but also isn't calling startUsingItem on certain instant-use items
|
||||
+ // TODO Check up on this proper, possibly remove all and move into more specific places
|
||||
+ if (io.papermc.paper.util.MCUtil.clientPredictsInteraction(player, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), stackBeforeUse)) {
|
||||
+ player.inventoryMenu.forceHeldSlot(hand);
|
||||
+ }
|
||||
+ player.inventoryMenu.broadcastChanges();
|
||||
+ // Paper end - Optimize sendAllDataToRemote calls
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -340,17 +_,55 @@
|
||||
int oldCount = itemStack.getCount();
|
||||
int oldDamage = itemStack.getDamageValue();
|
||||
+ final ItemStack stackBeforeUse = itemStack.copy(); // Paper - Store stack before use for interact prediction check
|
||||
InteractionResult result = itemStack.use(level, player, hand);
|
||||
ItemStack resultStack;
|
||||
if (result instanceof InteractionResult.Success success) {
|
||||
@@ -340,25 +_,70 @@
|
||||
}
|
||||
|
||||
if (!player.isUsingItem()) {
|
||||
- player.inventoryMenu.sendAllDataToRemote();
|
||||
+ // Paper start - Optimize sendAllDataToRemote calls
|
||||
+ // This is a weird one where the Vanilla behavior is from an ancient version, but also isn't calling startUsingItem on certain instant-use items
|
||||
+ // TODO Check up on this proper, possibly remove all and move into more specific places
|
||||
+ if (io.papermc.paper.util.MCUtil.clientPredictsInteraction(player, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), stackBeforeUse)) {
|
||||
+ player.inventoryMenu.forceHeldSlot(hand);
|
||||
+ }
|
||||
+ player.inventoryMenu.broadcastChanges();
|
||||
+ // Paper end - Optimize sendAllDataToRemote calls
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - whole method
|
||||
@@ -349,7 +346,9 @@
|
||||
+ boolean cancelledItem = false; // Paper - correctly handle items on cooldown
|
||||
if (!state.getBlock().isEnabled(level.enabledFeatures())) {
|
||||
return InteractionResult.FAIL;
|
||||
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
||||
}
|
||||
|
||||
if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
||||
MenuProvider menuProvider = state.getMenuProvider(level, pos);
|
||||
- if (menuProvider != null) {
|
||||
- player.openMenu(menuProvider);
|
||||
@@ -388,7 +387,7 @@
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
@@ -375,7 +_,7 @@
|
||||
@@ -383,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +396,7 @@
|
||||
UseOnContext context = new UseOnContext(player, hand, hitResult);
|
||||
InteractionResult success;
|
||||
if (player.hasInfiniteMaterials()) {
|
||||
@@ -392,6 +_,11 @@
|
||||
@@ -400,6 +_,11 @@
|
||||
|
||||
return success;
|
||||
} else {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
public BlockState getBlockState(final BlockPos pos) {
|
||||
return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos);
|
||||
@@ -221,6 +_,7 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+ private boolean hasSetFarWarned = false; // Paper - Buffer OOB setBlock calls
|
||||
@@ -59,24 +59,24 @@
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -273,6 +_,17 @@
|
||||
chunk.removeBlockEntity(pos);
|
||||
}
|
||||
} else {
|
||||
+ // Paper start - Clear block entity before setting up a DUMMY block entity
|
||||
+ // The concept of removing a block entity when the block itself changes is generally lifted
|
||||
+ // from LevelChunk#setBlockState.
|
||||
+ // It is however to note that this may only run if the block actually changes.
|
||||
+ // Otherwise a chest block entity generated by a structure template that is later "updated" to
|
||||
+ // be waterlogged would remove its existing block entity (see PaperMC/Paper#10750)
|
||||
+ // This logic is *also* found in LevelChunk#setBlockState.
|
||||
+ if (oldState != null && !java.util.Objects.equals(oldState.getBlock(), blockState.getBlock())) {
|
||||
+ chunk.removeBlockEntity(pos);
|
||||
+ }
|
||||
+ // Paper end - Clear block entity before setting up a DUMMY block entity
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("x", pos.getX());
|
||||
tag.putInt("y", pos.getY());
|
||||
@@ -274,6 +_,17 @@
|
||||
chunk.removeBlockEntity(pos);
|
||||
}
|
||||
} else {
|
||||
+ // Paper start - Clear block entity before setting up a DUMMY block entity
|
||||
+ // The concept of removing a block entity when the block itself changes is generally lifted
|
||||
+ // from LevelChunk#setBlockState.
|
||||
+ // It is however to note that this may only run if the block actually changes.
|
||||
+ // Otherwise a chest block entity generated by a structure template that is later "updated" to
|
||||
+ // be waterlogged would remove its existing block entity (see PaperMC/Paper#10750)
|
||||
+ // This logic is *also* found in LevelChunk#setBlockState.
|
||||
+ if (oldState != null && !java.util.Objects.equals(oldState.getBlock(), blockState.getBlock())) {
|
||||
+ chunk.removeBlockEntity(pos);
|
||||
+ }
|
||||
+ // Paper end - Clear block entity before setting up a DUMMY block entity
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("x", pos.getX());
|
||||
tag.putInt("y", pos.getY());
|
||||
@@ -301,6 +_,13 @@
|
||||
|
||||
@Override
|
||||
|
||||
+14
-12
@@ -53,15 +53,22 @@
|
||||
|
||||
if (in.isReadable()) {
|
||||
- if (!readCustomPayloadPacket(in)) {
|
||||
- return;
|
||||
+ // Paper start - Replace below
|
||||
+ if (in.readUnsignedByte() != LegacyProtocolUtils.CUSTOM_PAYLOAD_PACKET_ID) {
|
||||
+ body = this.readLegacy1_6(ctx, in);
|
||||
+ if (body == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
-
|
||||
- LOGGER.debug("Ping: (1.6) from {}", socket);
|
||||
+ // Paper end - Replace below
|
||||
+ } else {
|
||||
} else {
|
||||
- LOGGER.debug("Ping: (1.4-1.5.x) from {}", socket);
|
||||
- }
|
||||
-
|
||||
- String body = createVersion1Response(this.server);
|
||||
+ LOGGER.debug("Ping: (1.4-1.5.x) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? socket : "<ip address withheld>"); // Paper - Respect logIPs option
|
||||
+ }
|
||||
+
|
||||
@@ -72,12 +79,9 @@
|
||||
+ ctx.close();
|
||||
+ in.release();
|
||||
+ connectNormally = false;
|
||||
return;
|
||||
}
|
||||
|
||||
- LOGGER.debug("Ping: (1.6) from {}", socket);
|
||||
- } else {
|
||||
- LOGGER.debug("Ping: (1.4-1.5.x) from {}", socket);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // See createVersion1Response
|
||||
+ body = String.format(
|
||||
+ Locale.ROOT,
|
||||
@@ -87,10 +91,8 @@
|
||||
+ event.getNumPlayers(),
|
||||
+ event.getMaxPlayers()
|
||||
+ );
|
||||
+ // Paper end - Call PaperServerListPingEvent and use results
|
||||
}
|
||||
-
|
||||
- String body = createVersion1Response(this.server);
|
||||
+ }
|
||||
+ // Paper end - Call PaperServerListPingEvent and use results
|
||||
sendFlushAndClose(ctx, createLegacyDisconnectPacket(ctx.alloc(), body));
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 368 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user