13
0
geforkt von Mirrors/Paper

[ci skip] Add more identifying patch comments, merge related patches

Dieser Commit ist enthalten in:
Nassim Jahnke 2024-01-19 12:30:04 +01:00
Ursprung 864f4072c1
Commit b5b92e90d8
38 geänderte Dateien mit 181 neuen und 229 gelöschten Zeilen

Datei anzeigen

@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType); + net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType);
+ return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror(); + return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror();
+ } + }
+ // Paper end + // Paper end - old getSpawnEgg API
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

Datei anzeigen

@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.passengers = ImmutableList.copyOf(pass); + this.passengers = ImmutableList.copyOf(pass);
+ return result; + return result;
+ } + }
+ // Paper end + // Paper end - Entity serialization api
public boolean save(CompoundTag nbt) { public boolean save(CompoundTag nbt) {
return this.isPassenger() ? false : this.saveAsPassenger(nbt); return this.isPassenger() ? false : this.saveAsPassenger(nbt);
} }

Datei anzeigen

@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ pitch = event.getTo().getPitch(); + pitch = event.getTo().getPitch();
+ velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter()); + velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter());
+ } + }
+ // Paper end + // Paper end - Call EntityPortalExitEvent
if (worldserver == this.level) { if (worldserver == this.level) {
// SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in
this.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); this.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot);
@ -43,8 +43,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
entity.restoreFrom(this); entity.restoreFrom(this);
- entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); - entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot());
- entity.setDeltaMovement(shapedetectorshape.speed); - entity.setDeltaMovement(shapedetectorshape.speed);
+ entity.moveTo(position.x, position.y, position.z, yaw, pitch); // Paper - use EntityPortalExitEvent values + entity.moveTo(position.x, position.y, position.z, yaw, pitch); // Paper - EntityPortalExitEvent
+ entity.setDeltaMovement(velocity); // Paper - use EntityPortalExitEvent values + entity.setDeltaMovement(velocity); // Paper - EntityPortalExitEvent
// CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned
if (this.inWorld) { if (this.inWorld) {
worldserver.addDuringTeleport(entity); worldserver.addDuringTeleport(entity);

Datei anzeigen

@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.critical = critical; + this.critical = critical;
+ return this; + return this;
+ } + }
+ // Paper end + // Paper end - add critical damage API
} }
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
- boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
+ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API - conflict on change + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API; diff on change
flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper
flag2 = flag2 && !this.isSprinting(); flag2 = flag2 && !this.isSprinting();

Datei anzeigen

@ -14,11 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
protected BlockPos findLightningTargetAround(BlockPos pos) { protected BlockPos findLightningTargetAround(BlockPos pos) {
+ // Paper start + // Paper start - Add methods to find targets for lightning strikes
+ return this.findLightningTargetAround(pos, false); + return this.findLightningTargetAround(pos, false);
+ } + }
+ public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) { + public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) {
+ // Paper end + // Paper end - Add methods to find targets for lightning strikes
BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos); BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
Optional<BlockPos> optional = this.findLightningRod(blockposition1); Optional<BlockPos> optional = this.findLightningRod(blockposition1);
@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!list.isEmpty()) { if (!list.isEmpty()) {
return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition(); return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition();
} else { } else {
+ if (returnNullWhenNoTarget) return null; // Paper + if (returnNullWhenNoTarget) return null; // Paper - Add methods to find targets for lightning strikes
if (blockposition1.getY() == this.getMinBuildHeight() - 1) { if (blockposition1.getY() == this.getMinBuildHeight() - 1) {
blockposition1 = blockposition1.above(2); blockposition1 = blockposition1.above(2);
} }
@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return (LightningStrike) lightning.getBukkitEntity(); return (LightningStrike) lightning.getBukkitEntity();
} }
+ // Paper start + // Paper start - Add methods to find targets for lightning strikes
+ @Override + @Override
+ public Location findLightningRod(Location location) { + public Location findLightningRod(Location location) {
+ return this.world.findLightningRod(io.papermc.paper.util.MCUtil.toBlockPosition(location)) + return this.world.findLightningRod(io.papermc.paper.util.MCUtil.toBlockPosition(location))
@ -53,7 +53,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final BlockPos pos = this.world.findLightningTargetAround(io.papermc.paper.util.MCUtil.toBlockPosition(location), true); + final BlockPos pos = this.world.findLightningTargetAround(io.papermc.paper.util.MCUtil.toBlockPosition(location), true);
+ return pos == null ? null : io.papermc.paper.util.MCUtil.toLocation(this.world, pos); + return pos == null ? null : io.papermc.paper.util.MCUtil.toLocation(this.world, pos);
+ } + }
+ // Paper end + // Paper end - Add methods to find targets for lightning strikes
+ +
@Override @Override
public boolean generateTree(Location loc, TreeType type) { public boolean generateTree(Location loc, TreeType type) {

Datei anzeigen

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public final class CraftServer implements Server { @@ -0,0 +0,0 @@ public final class CraftServer implements Server {
@Override @Override
public int getSpawnLimit(SpawnCategory spawnCategory) { public int getSpawnLimit(SpawnCategory spawnCategory) {
// Paper start // Paper start - Add mobcaps commands
+ Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); + Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null");
+ Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory." + spawnCategory + " does not have a spawn limit."); + Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory." + spawnCategory + " does not have a spawn limit.");
return this.getSpawnLimitUnsafe(spawnCategory); return this.getSpawnLimitUnsafe(spawnCategory);

Datei anzeigen

@ -91,7 +91,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final boolean hidden; private final boolean hidden;
private float x; private float x;
private float y; private float y;
+ public final io.papermc.paper.advancement.AdvancementDisplay paper = new io.papermc.paper.advancement.PaperAdvancementDisplay(this); // Paper + public final io.papermc.paper.advancement.AdvancementDisplay paper = new io.papermc.paper.advancement.PaperAdvancementDisplay(this); // Paper - Add more advancement API
public DisplayInfo(ItemStack icon, Component title, Component description, Optional<ResourceLocation> background, AdvancementType frame, boolean showToast, boolean announceToChat, boolean hidden) { public DisplayInfo(ItemStack icon, Component title, Component description, Optional<ResourceLocation> background, AdvancementType frame, boolean showToast, boolean announceToChat, boolean hidden) {
this.title = title; this.title = title;
@ -103,7 +103,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return Collections.unmodifiableCollection(this.handle.value().criteria().keySet()); return Collections.unmodifiableCollection(this.handle.value().criteria().keySet());
} }
+ // Paper start + // Paper start - Add more advancement API
@Override @Override
- public AdvancementDisplay getDisplay() { - public AdvancementDisplay getDisplay() {
- if (this.handle.value().display().isEmpty()) { - if (this.handle.value().display().isEmpty()) {
@ -149,7 +149,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle); + final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle);
+ return java.util.Objects.requireNonNull(advancementNode, "could not find internal advancement node for advancement " + this.handle.id()).root().holder().toBukkit(); + return java.util.Objects.requireNonNull(advancementNode, "could not find internal advancement node for advancement " + this.handle.id()).root().holder().toBukkit();
} }
+ // Paper end + // Paper end - Add more advancement API
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

Datei anzeigen

@ -264,7 +264,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
world.getProfiler().pop(); world.getProfiler().pop();
} }
+ // Paper start + // Paper start - Add mobcaps commands
+ public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) { + public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) {
+ final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category)); + final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category));
+ if (categoryLimit < 1) { + if (categoryLimit < 1) {
@ -272,7 +272,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ return categoryLimit * spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; + return categoryLimit * spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER;
+ } + }
+ // Paper end + // Paper end - Add mobcaps commands
+ +
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
// Paper start - add parameters and int ret type // Paper start - add parameters and int ret type
@ -285,11 +285,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public int getSpawnLimit(SpawnCategory spawnCategory) { public int getSpawnLimit(SpawnCategory spawnCategory) {
+ // Paper start + // Paper start - Add mobcaps commands
+ return this.getSpawnLimitUnsafe(spawnCategory); + return this.getSpawnLimitUnsafe(spawnCategory);
+ } + }
+ public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) { + public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
+ // Paper end + // Paper end - Add mobcaps commands
return this.spawnCategoryLimit.getOrDefault(spawnCategory, -1); return this.spawnCategoryLimit.getOrDefault(spawnCategory, -1);
} }
@ -301,7 +301,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null");
Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory);
+ // Paper start + // Paper start - Add mobcaps commands
+ return this.getSpawnLimitUnsafe(spawnCategory); + return this.getSpawnLimitUnsafe(spawnCategory);
+ } + }
+ public final int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) { + public final int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
@ -309,7 +309,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (limit < 0) { if (limit < 0) {
- limit = this.server.getSpawnLimit(spawnCategory); - limit = this.server.getSpawnLimit(spawnCategory);
+ limit = this.server.getSpawnLimitUnsafe(spawnCategory); + limit = this.server.getSpawnLimitUnsafe(spawnCategory);
+ // Paper end + // Paper end - Add mobcaps commands
} }
return limit; return limit;
} }

Datei anzeigen

@ -72,7 +72,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ DedicatedServer.LOGGER.warn("FOR MORE INFORMATION, SEE https://madelinemiller.dev/blog/root-minecraft-server/"); + DedicatedServer.LOGGER.warn("FOR MORE INFORMATION, SEE https://madelinemiller.dev/blog/root-minecraft-server/");
+ DedicatedServer.LOGGER.warn("****************************"); + DedicatedServer.LOGGER.warn("****************************");
+ } + }
+ // Paper end + // Paper end - detect running as root
+ +
DedicatedServer.LOGGER.info("Loading properties"); DedicatedServer.LOGGER.info("Loading properties");
DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties(); DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties();

Datei anzeigen

@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -0,0 +0,0 @@ public class ServerConnectionListener { @@ -0,0 +0,0 @@ public class ServerConnectionListener {
ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
// Paper end // Paper end - Use Velocity cipher
+ // Paper start - Add support for proxy protocol + // Paper start - Add support for proxy protocol
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.proxyProtocol) { + if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.proxyProtocol) {

Datei anzeigen

@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.slf4j.Logger; import org.slf4j.Logger;
public class ChunkSerializer { public class ChunkSerializer {
+ // Paper start + // Paper start - Attempt to recalculate regionfile header if it is corrupt
+ // TODO: Check on update + // TODO: Check on update
+ public static long getLastWorldSaveTime(CompoundTag chunkData) { + public static long getLastWorldSaveTime(CompoundTag chunkData) {
+ final int dataVersion = ChunkStorage.getVersion(chunkData); + final int dataVersion = ChunkStorage.getVersion(chunkData);
@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return chunkData.getLong("LastUpdate"); + return chunkData.getLong("LastUpdate");
+ } + }
+ } + }
+ // Paper end + // Paper end - Attempt to recalculate regionfile header if it is corrupt
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null); // Paper - Anti-Xray - Add preset block states public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null); // Paper - Anti-Xray - Add preset block states
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Paper start - async chunk io // Paper start - async chunk io
// remove IO worker // remove IO worker
- this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker - this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker
+ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - nuke IOWorker // Paper + this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - nuke IOWorker // Paper - Attempt to recalculate regionfile header if it is corrupt
// Paper end - async chunk io // Paper end - async chunk io
} }
@ -62,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public class RegionBitmap { public class RegionBitmap {
private final BitSet used = new BitSet(); private final BitSet used = new BitSet();
+ // Paper start + // Paper start - Attempt to recalculate regionfile header if it is corrupt
+ public final void copyFrom(RegionBitmap other) { + public final void copyFrom(RegionBitmap other) {
+ BitSet thisBitset = this.used; + BitSet thisBitset = this.used;
+ BitSet otherBitset = other.used; + BitSet otherBitset = other.used;
@ -81,7 +81,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ bitset.set(from, from + length); + bitset.set(from, from + length);
+ return true; + return true;
+ } + }
+ // Paper end + // Paper end - Attempt to recalculate regionfile header if it is corrupt
+ +
public void force(int start, int size) { public void force(int start, int size) {
this.used.set(start, start + size); this.used.set(start, start + size);
@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
public final Path regionFile; // Paper public final Path regionFile; // Paper
+ // Paper start - try to recover from RegionFile header corruption + // Paper start - Attempt to recalculate regionfile header if it is corrupt
+ private static long roundToSectors(long bytes) { + private static long roundToSectors(long bytes) {
+ long sectors = bytes >>> 12; // 4096 = 2^12 + long sectors = bytes >>> 12; // 4096 = 2^12
+ long remainingBytes = bytes & 4095; + long remainingBytes = bytes & 4095;
@ -441,7 +441,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ final boolean canRecalcHeader; // final forces compile fail on new constructor + final boolean canRecalcHeader; // final forces compile fail on new constructor
+ // Paper end + // Paper end - Attempt to recalculate regionfile header if it is corrupt
+ +
// Paper start - Cache chunk status // Paper start - Cache chunk status
private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32]; private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];

Datei anzeigen

@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} catch (final CommandSyntaxException ignored) { } catch (final CommandSyntaxException ignored) {
} }
+ } + }
+ // Paper end + // Paper end - Don't suggest if the requirement isn't met
futures[i++] = future; futures[i++] = future;
} }

Datei anzeigen

@ -27,14 +27,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}; };
- seededrandom.setFeatureSeed(i, l1, l); - seededrandom.setFeatureSeed(i, l1, l);
+ // Paper start - change populationSeed used in random + // Paper start - Configurable feature seeds; change populationSeed used in random
+ long featurePopulationSeed = i; + long featurePopulationSeed = i;
+ final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig().featureSeeds.features.getLong(placedfeature.feature()); + final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig().featureSeeds.features.getLong(placedfeature.feature());
+ if (configFeatureSeed != -1) { + if (configFeatureSeed != -1) {
+ featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above + featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above
+ } + }
+ seededrandom.setFeatureSeed(featurePopulationSeed, l1, l); + seededrandom.setFeatureSeed(featurePopulationSeed, l1, l);
+ // Paper end + // Paper end - Configurable feature seeds
try { try {
generatoraccessseed.setCurrentlyGenerating(supplier1); generatoraccessseed.setCurrentlyGenerating(supplier1);

Datei anzeigen

@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper
+ ((org.bukkit.craftbukkit.entity.CraftHumanEntity)h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + ((org.bukkit.craftbukkit.entity.CraftHumanEntity)h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper
} }
+ // Paper end + // Paper end - this area looks like it can load chunks, change the behavior
} }
} }
// Spigot End // Spigot End

Datei anzeigen

@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start // CraftBukkit start
private boolean check(ServerChunkCache cps, int x, int z) { private boolean check(ServerChunkCache cps, int x, int z) {
+ if (true) return true; // Paper - this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full" + if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full"
ChunkPos pos = new ChunkPos(x, z); ChunkPos pos = new ChunkPos(x, z);
if (cps != null) { if (cps != null) {
//com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe

Datei anzeigen

@ -1,8 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Sun, 10 May 2020 22:12:46 -0400 Date: Sun, 10 May 2020 22:12:46 -0400
Subject: [PATCH] Ensure Entity AABB's are never invalid Subject: [PATCH] Ensure Entity position and AABB are never invalid
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -14,20 +15,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void setPos(double x, double y, double z) { public void setPos(double x, double y, double z) {
- this.setPosRaw(x, y, z); - this.setPosRaw(x, y, z);
- this.setBoundingBox(this.makeBoundingBox()); - this.setBoundingBox(this.makeBoundingBox());
+ this.setPosRaw(x, y, z, true); // Paper - force bounding box update + this.setPosRaw(x, y, z, true); // Paper - Block invalid positions and bounding box; force update
+ // this.setBoundingBox(this.makeBoundingBox()); // Paper - move into setPositionRaw + // this.setBoundingBox(this.makeBoundingBox()); // Paper - Block invalid positions and bounding box; move into setPosRaw
} }
protected AABB makeBoundingBox() { protected AABB makeBoundingBox() {
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * widthScale);
} }
+ // Paper start - Block invalid positions and bounding box
+ public static boolean checkPosition(Entity entity, double newX, double newY, double newZ) {
+ if (Double.isFinite(newX) && Double.isFinite(newY) && Double.isFinite(newZ)) {
+ return true;
+ }
+
+ String entityInfo;
+ try {
+ entityInfo = entity.toString();
+ } catch (Exception ex) {
+ entityInfo = "[Entity info unavailable] ";
+ }
+ LOGGER.error("New entity position is invalid! Tried to set invalid position ({},{},{}) for entity {} located at {}, entity info: {}", newX, newY, newZ, entity.getClass().getName(), entity.position, entityInfo, new Throwable());
+ return false;
+ }
public final void setPosRaw(double x, double y, double z) { public final void setPosRaw(double x, double y, double z) {
+ // Paper start
+ this.setPosRaw(x, y, z, false); + this.setPosRaw(x, y, z, false);
+ } + }
+ public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { + public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
+ // Paper end + if (!checkPosition(this, x, y, z)) {
+ return;
+ }
+ // Paper end - Block invalid positions and bounding box
// Paper start - rewrite chunk system // Paper start - rewrite chunk system
if (this.updatingSectionStatus) { if (this.updatingSectionStatus) {
LOGGER.error("Refusing to update position for entity " + this + " to position " + new Vec3(x, y, z) + " since it is processing a section status update", new Throwable()); LOGGER.error("Refusing to update position for entity " + this + " to position " + new Vec3(x, y, z) + " since it is processing a section status update", new Throwable());
@ -35,12 +54,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.levelCallback.onMove(); this.levelCallback.onMove();
} }
+ // Paper start - never allow AABB to become desynced from position + // Paper start - Block invalid positions and bounding box; don't allow desync of pos and AABB
+ // hanging has its own special logic + // hanging has its own special logic
+ if (!(this instanceof net.minecraft.world.entity.decoration.HangingEntity) && (forceBoundingBoxUpdate || this.position.x != x || this.position.y != y || this.position.z != z)) { + if (!(this instanceof net.minecraft.world.entity.decoration.HangingEntity) && (forceBoundingBoxUpdate || this.position.x != x || this.position.y != y || this.position.z != z)) {
+ this.setBoundingBox(this.makeBoundingBox()); + this.setBoundingBox(this.makeBoundingBox());
+ } + }
+ // Paper end + // Paper end - Block invalid positions and bounding box
} }
public void checkDespawn() {} public void checkDespawn() {}

Datei anzeigen

@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
- if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { - if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) {
+ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper + if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper - Ensure valid vehicle status
// CraftBukkit end // CraftBukkit end
CompoundTag nbttagcompound2 = new CompoundTag(); CompoundTag nbttagcompound2 = new CompoundTag();
CompoundTag nbttagcompound3 = new CompoundTag(); CompoundTag nbttagcompound3 = new CompoundTag();

Datei anzeigen

@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public void place(TreeDecorator.Context generator) { public void place(TreeDecorator.Context generator) {
+ if (generator.logs().isEmpty()) return; // Paper + if (generator.logs().isEmpty()) return; // Paper - Fix crash when trying to generate without logs
RandomSource randomSource = generator.random(); RandomSource randomSource = generator.random();
if (!(randomSource.nextFloat() >= this.probability)) { if (!(randomSource.nextFloat() >= this.probability)) {
List<BlockPos> list = generator.logs(); List<BlockPos> list = generator.logs();

Datei anzeigen

@ -14,10 +14,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable @Nullable
private Executor executor; private Executor executor;
+ // Paper start + // Paper start - Fix GameProfileCache concurrency
+ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock(); + protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock();
+ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock(); + protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock();
+ // Paper end + // Paper end - Fix GameProfileCache concurrency
+ +
public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) { public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) {
this.profileRepository = profileRepository; this.profileRepository = profileRepository;
@ -26,13 +26,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
private void safeAdd(GameProfileCache.GameProfileInfo entry) { private void safeAdd(GameProfileCache.GameProfileInfo entry) {
+ try { this.stateLock.lock(); // Paper - allow better concurrency + try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfile gameprofile = entry.getProfile(); GameProfile gameprofile = entry.getProfile();
entry.setLastAccess(this.getNextOperation()); entry.setLastAccess(this.getNextOperation());
this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), entry); this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), entry);
this.profilesByUUID.put(gameprofile.getId(), entry); this.profilesByUUID.put(gameprofile.getId(), entry);
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency + } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
} }
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository repository, String name) { private static Optional<GameProfile> lookupGameProfile(GameProfileRepository repository, String name) {
@ -40,20 +40,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Paper start // Paper start
public @Nullable GameProfile getProfileIfCached(String name) { public @Nullable GameProfile getProfileIfCached(String name) {
+ try { this.stateLock.lock(); // Paper - allow better concurrency + try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
if (entry == null) { if (entry == null) {
return null; return null;
} }
entry.setLastAccess(this.getNextOperation()); entry.setLastAccess(this.getNextOperation());
return entry.getProfile(); return entry.getProfile();
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency + } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
} }
// Paper end // Paper end
public Optional<GameProfile> get(String name) { public Optional<GameProfile> get(String name) {
String s1 = name.toLowerCase(Locale.ROOT); String s1 = name.toLowerCase(Locale.ROOT);
+ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - allow better concurrency + boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
boolean flag = false; boolean flag = false;
@ -61,12 +61,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (usercache_usercacheentry != null) { if (usercache_usercacheentry != null) {
usercache_usercacheentry.setLastAccess(this.getNextOperation()); usercache_usercacheentry.setLastAccess(this.getNextOperation());
optional = Optional.of(usercache_usercacheentry.getProfile()); optional = Optional.of(usercache_usercacheentry.getProfile());
+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency + stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
} else { } else {
+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency + stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
+ try { this.lookupLock.lock(); // Paper - allow better concurrency + try { this.lookupLock.lock(); // Paper - Fix GameProfileCache concurrency
optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // CraftBukkit - use correct case for offline players optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // CraftBukkit - use correct case for offline players
+ } finally { this.lookupLock.unlock(); } // Paper - allow better concurrency + } finally { this.lookupLock.unlock(); } // Paper - Fix GameProfileCache concurrency
if (optional.isPresent()) { if (optional.isPresent()) {
this.add((GameProfile) optional.get()); this.add((GameProfile) optional.get());
flag = false; flag = false;
@ -74,7 +74,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
return optional; return optional;
+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - allow better concurrency + } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - Fix GameProfileCache concurrency
} }
public CompletableFuture<Optional<GameProfile>> getAsync(String username) { public CompletableFuture<Optional<GameProfile>> getAsync(String username) {
@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
public Optional<GameProfile> get(UUID uuid) { public Optional<GameProfile> get(UUID uuid) {
+ try { this.stateLock.lock(); // Paper - allow better concurrency + try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
if (usercache_usercacheentry == null) { if (usercache_usercacheentry == null) {
@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
usercache_usercacheentry.setLastAccess(this.getNextOperation()); usercache_usercacheentry.setLastAccess(this.getNextOperation());
return Optional.of(usercache_usercacheentry.getProfile()); return Optional.of(usercache_usercacheentry.getProfile());
} }
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency + } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
} }
public void setExecutor(Executor executor) { public void setExecutor(Executor executor) {
@ -99,7 +99,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
DateFormat dateformat = GameProfileCache.createDateFormat(); DateFormat dateformat = GameProfileCache.createDateFormat();
- this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot - this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot
+ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - allow better concurrency + this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - Fix GameProfileCache concurrency
jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat)); jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat));
}); });
String s = this.gson.toJson(jsonarray); String s = this.gson.toJson(jsonarray);
@ -108,7 +108,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) { private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) {
- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); - return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit);
+ // Paper start - allow better concurrency + // Paper start - Fix GameProfileCache concurrency
+ return this.listTopMRUProfiles(limit).stream(); + return this.listTopMRUProfiles(limit).stream();
+ } + }
+ +
@ -120,7 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.stateLock.unlock(); + this.stateLock.unlock();
+ } + }
} }
+ // Paper end + // Paper end - Fix GameProfileCache concurrency
private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) { private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) {
JsonObject jsonobject = new JsonObject(); JsonObject jsonobject = new JsonObject();

Datei anzeigen

@ -13,15 +13,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void doFreezeConversion() { protected void doFreezeConversion() {
- this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons - this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons
+ Stray stray = this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons // Paper - track result of conversion + Stray stray = this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons // Paper - Fix issues with mob conversion
if (!this.isSilent()) { if (!this.isSilent()) {
this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0);
} }
+ // Paper start - reset conversion time to prevent event spam + // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam
+ if (stray == null) { + if (stray == null) {
+ this.conversionTime = 300; + this.conversionTime = 300;
+ } + }
+ // Paper end + // Paper end - Fix issues with mob conversion
} }
@ -33,11 +33,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (zoglin != null) { if (zoglin != null) {
zoglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); zoglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
} }
+ // Paper start - reset to prevent event spam + // Paper start - Fix issues with mob conversion; reset to prevent event spam
+ else { + else {
+ this.timeInOverworld = 0; + this.timeInOverworld = 0;
+ } + }
+ // Paper end + // Paper end - Fix issues with mob conversion
} }
@ -49,11 +49,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (entitypigzombie != null) { if (entitypigzombie != null) {
entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
} }
+ // Paper start - reset to prevent event spam + // Paper start - Fix issues with mob conversion; reset to prevent event spam
+ else { + else {
+ this.timeInOverworld = 0; + this.timeInOverworld = 0;
+ } + }
+ // Paper end + // Paper end - Fix issues with mob conversion
} }

Datei anzeigen

@ -12,11 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Spigot end // Spigot end
// Spigot Start // Spigot Start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
+ // Paper start + // Paper start - Fix merchant inventory not closing on entity removal
+ if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); + merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
+ } + }
+ // Paper end + // Paper end - Fix merchant inventory not closing on entity removal
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) {
h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper
} }

Datei anzeigen

@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
+ brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM); + brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM);
+ } + }
+ // Paper end + // Paper end - Goat ram API
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

Datei anzeigen

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 31 Mar 2022 05:18:28 -0700
Subject: [PATCH] Guard against invalid entity positions
Anything not finite should be blocked and logged
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * widthScale);
}
+ // Paper start - block invalid positions
+ public static boolean checkPosition(Entity entity, double newX, double newY, double newZ) {
+ if (Double.isFinite(newX) && Double.isFinite(newY) && Double.isFinite(newZ)) {
+ return true;
+ }
+
+ String entityInfo = null;
+ try {
+ entityInfo = entity.toString();
+ } catch (Exception ex) {
+ entityInfo = "[Entity info unavailable] ";
+ }
+ LOGGER.error("New entity position is invalid! Tried to set invalid position (" + newX + "," + newY + "," + newZ + ") for entity " + entity.getClass().getName() + " located at " + entity.position + ", entity info: " + entityInfo, new Throwable());
+ return false;
+ }
+ // Paper end - block invalid positions
+
public final void setPosRaw(double x, double y, double z) {
// Paper start
this.setPosRaw(x, y, z, false);
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
+ // Paper start - block invalid positions
+ if (!checkPosition(this, x, y, z)) {
+ return;
+ }
+ // Paper end - block invalid positions
// Paper end
// Paper start - rewrite chunk system
if (this.updatingSectionStatus) {

Datei anzeigen

@ -11,8 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror(); return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror();
} }
// Paper end // Paper end - old getSpawnEgg API
+
+ // Paper start - enchantWithLevels API + // Paper start - enchantWithLevels API
+ @Override + @Override
+ public ItemStack enchantWithLevels(ItemStack itemStack, int levels, boolean allowTreasure, java.util.Random random) { + public ItemStack enchantWithLevels(ItemStack itemStack, int levels, boolean allowTreasure, java.util.Random random) {

Datei anzeigen

@ -9,11 +9,14 @@ type and we are not using its capabilities.
Set thread priorities so main thread has above normal priority over Set thread priorities so main thread has above normal priority over
server threads server threads
Allow usage of a single thread executor by not using ForkJoin so single core CPU's. Allow usage of a single thread executor by not using ForkJoin so single core CPU's
and reduce worldgen thread worker count for low core count CPUs.
== AT == == AT ==
public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/src/main/java/io/papermc/paper/util/ServerWorkerThread.java b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java diff --git a/src/main/java/io/papermc/paper/util/ServerWorkerThread.java b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
@ -54,11 +57,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- private static ExecutorService makeExecutor(String name) { - private static ExecutorService makeExecutor(String name) {
- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads()); - int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads());
+ private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority + private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
+ // Paper start - use simpler thread pool that allows 1 thread + // Paper start - use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs
+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); + int cpus = Runtime.getRuntime().availableProcessors() / 2;
+ int i;
+ if (cpus <= 4) {
+ i = cpus <= 2 ? 1 : 2;
+ } else if (cpus <= 8) {
+ // [5, 8]
+ i = Math.max(3, cpus - 2);
+ } else {
+ i = cpus * 2 / 3;
+ }
+ i = Math.min(8, i);
+ i = Integer.getInteger("Paper.WorkerThreadCount", i); + i = Integer.getInteger("Paper.WorkerThreadCount", i);
ExecutorService executorService; ExecutorService executorService;
+
if (i <= 0) { if (i <= 0) {
executorService = MoreExecutors.newDirectExecutorService(); executorService = MoreExecutors.newDirectExecutorService();
} else { } else {

Datei anzeigen

@ -9,9 +9,6 @@ previous getChunkAt method which had inlined logic for loaded
chunks did get inlined, but the standard CPS.getChunkAt chunks did get inlined, but the standard CPS.getChunkAt
method was not inlined. method was not inlined.
Paper recently reverted this optimisation, so it's been reintroduced
here.
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java --- a/src/main/java/net/minecraft/world/level/Level.java
@ -20,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline
+ // Paper start - make sure loaded chunks get the inlined variant of this function + // Paper start - Perf: make sure loaded chunks get the inlined variant of this function
+ net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource(); + net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource();
+ if (cps.mainThread == Thread.currentThread()) { + if (cps.mainThread == Thread.currentThread()) {
+ LevelChunk ifLoaded = cps.getChunkAtIfLoadedMainThread(chunkX, chunkZ); + LevelChunk ifLoaded = cps.getChunkAtIfLoadedMainThread(chunkX, chunkZ);
@ -28,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return ifLoaded; + return ifLoaded;
+ } + }
+ } + }
+ // Paper end - make sure loaded chunks get the inlined variant of this function + // Paper end - Perf: make sure loaded chunks get the inlined variant of this function
return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump
} }

Datei anzeigen

@ -26,21 +26,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public BlockPos.MutableBlockPos setX(int i) { public BlockPos.MutableBlockPos setX(int i) {
- super.setX(i); - super.setX(i);
+ this.x = i; // Paper + this.x = i; // Paper - force line
return this; return this;
} }
@Override @Override
public BlockPos.MutableBlockPos setY(int i) { public BlockPos.MutableBlockPos setY(int i) {
- super.setY(i); - super.setY(i);
+ this.y = i; // Paper + this.y = i; // Paper - force line
return this; return this;
} }
@Override @Override
public BlockPos.MutableBlockPos setZ(int i) { public BlockPos.MutableBlockPos setZ(int i) {
- super.setZ(i); - super.setZ(i);
+ this.z = i; // Paper + this.z = i; // Paper - force line
return this; return this;
} }
@ -55,9 +55,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- private int x; - private int x;
- private int y; - private int y;
- private int z; - private int z;
+ protected int x; // Paper - protected + protected int x; // Paper - force line; protected
+ protected int y; // Paper - protected + protected int y; // Paper - force line; protected
+ protected int z; // Paper - protected + protected int z; // Paper - force line; protected
public static Codec<Vec3i> offsetCodec(int maxAbsValue) { public static Codec<Vec3i> offsetCodec(int maxAbsValue) {
return ExtraCodecs.validate(CODEC, (vec) -> { return ExtraCodecs.validate(CODEC, (vec) -> {

Datei anzeigen

@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
} }
+ } finally { thread.setName(nameBefore); } // Paper - name worker thread according + } finally { thread.setName(nameBefore); } // Paper - name threads according to running plugin
} }
LinkedList<BukkitWorker> getWorkers() { LinkedList<BukkitWorker> getWorkers() {

Datei anzeigen

@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final int range; private final int range;
SectionPos lastSectionPos; SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet(); - public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - optimise map impl + public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
public TrackedEntity(Entity entity, int i, int j, boolean flag) { public TrackedEntity(Entity entity, int i, int j, boolean flag) {
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit

Datei anzeigen

@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- do { - do {
- if (!iterator.hasNext()) { - if (!iterator.hasNext()) {
- return false; - return false;
+ // Paper start - remove abstract block iteration + // Paper start - Perf: remove abstract block iteration
+ int xOff = pos.getX(); + int xOff = pos.getX();
+ int yOff = pos.getY(); + int yOff = pos.getY();
+ int zOff = pos.getZ(); + int zOff = pos.getZ();
@ -46,6 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- -
- return true; - return true;
+ return false; + return false;
+ // Paper end - Perf: remove abstract block iteration
} }
@Override @Override

Datei anzeigen

@ -12,10 +12,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F;
} }
+ protected long lastJumpTime = 0L; // Paper + protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits
protected void jumpFromGround() { protected void jumpFromGround() {
Vec3 vec3d = this.getDeltaMovement(); Vec3 vec3d = this.getDeltaMovement();
+ // Paper start + // Paper start - Prevent excessive velocity through repeated crits
+ long time = System.nanoTime(); + long time = System.nanoTime();
+ boolean canCrit = true; + boolean canCrit = true;
+ if (this instanceof net.minecraft.world.entity.player.Player) { + if (this instanceof net.minecraft.world.entity.player.Player) {
@ -25,13 +25,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ canCrit = true; + canCrit = true;
+ } + }
+ } + }
+ // Paper end + // Paper end - Prevent excessive velocity through repeated crits
this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z);
if (this.isSprinting()) { if (this.isSprinting()) {
float f = this.getYRot() * 0.017453292F; float f = this.getYRot() * 0.017453292F;
+ if (canCrit) // Paper + if (canCrit) // Paper - Prevent excessive velocity through repeated crits
this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F))); this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F)));
} }

Datei anzeigen

@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) { + if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) {
+ this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1); + this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
+ } + }
+ // Paper end + // Paper end - Prevent "softlocked" exit portal generation
if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) { if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) {
int i = Mth.positiveCeilDiv(4, 16); int i = Mth.positiveCeilDiv(4, 16);

Datei anzeigen

@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 30 Aug 2021 04:26:40 -0700
Subject: [PATCH] Reduce worldgen thread worker count for low core count CPUs
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -0,0 +0,0 @@ public class Util {
private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
// Paper start - use simpler thread pool that allows 1 thread
- int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1));
+ // Paper start - also try to avoid suffocating the system with the worldgen workers
+ int cpus = Runtime.getRuntime().availableProcessors() / 2;
+ int i;
+ if (cpus <= 4) {
+ i = cpus <= 2 ? 1 : 2;
+ } else if (cpus <= 8) {
+ // [5, 8]
+ i = Math.max(3, cpus - 2);
+ } else {
+ i = cpus * 2 / 3;
+ }
+ i = Math.min(8, i);
+ // Paper end - also try to avoid suffocating the system with the worldgen workers
i = Integer.getInteger("Paper.WorkerThreadCount", i);
ExecutorService executorService;

Datei anzeigen

@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static String assertValidNamespace(String namespace, String path) { private static String assertValidNamespace(String namespace, String path) {
if (!isValidNamespace(namespace)) { if (!isValidNamespace(namespace)) {
- throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + namespace + ":" + path); - throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + namespace + ":" + path);
+ throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper + throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
} else { } else {
return namespace; return namespace;
} }
@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static String assertValidPath(String namespace, String path) { private static String assertValidPath(String namespace, String path) {
if (!isValidPath(path)) { if (!isValidPath(path)) {
- throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + path); - throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + path);
+ throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper + throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
} else { } else {
return path; return path;
} }

Datei anzeigen

@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") { + implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") {
+ isTransitive = false + isTransitive = false
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6") runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6")
runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
@ -29,17 +29,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public class CipherDecoder extends MessageToMessageDecoder<ByteBuf> { public class CipherDecoder extends MessageToMessageDecoder<ByteBuf> {
- private final CipherBase cipher; - private final CipherBase cipher;
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper + private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper - Use Velocity cipher
- public CipherDecoder(Cipher cipher) { - public CipherDecoder(Cipher cipher) {
- this.cipher = new CipherBase(cipher); - this.cipher = new CipherBase(cipher);
+ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper + public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper - Use Velocity cipher
+ this.cipher = cipher; // Paper + this.cipher = cipher; // Paper - Use Velocity cipher
} }
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception { protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
- list.add(this.cipher.decipher(channelHandlerContext, byteBuf)); - list.add(this.cipher.decipher(channelHandlerContext, byteBuf));
+ // Paper start + // Paper start - Use Velocity cipher
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf); + ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
+ try { + try {
+ cipher.process(compatible); + cipher.process(compatible);
@ -48,15 +48,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ compatible.release(); // compatible will never be used if we throw an exception + compatible.release(); // compatible will never be used if we throw an exception
+ throw e; + throw e;
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
} }
+ +
+ // Paper start + // Paper start - Use Velocity cipher
+ @Override + @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ cipher.close(); + cipher.close();
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
} }
diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -70,19 +70,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
-public class CipherEncoder extends MessageToByteEncoder<ByteBuf> { -public class CipherEncoder extends MessageToByteEncoder<ByteBuf> {
- private final CipherBase cipher; - private final CipherBase cipher;
+public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder<ByteBuf> { // Paper - change superclass +public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder<ByteBuf> { // Paper - Use Velocity cipher; change superclass
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper + private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper - Use Velocity cipher
- public CipherEncoder(Cipher cipher) { - public CipherEncoder(Cipher cipher) {
- this.cipher = new CipherBase(cipher); - this.cipher = new CipherBase(cipher);
+ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper + public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper - Use Velocity cipher
+ this.cipher = cipher; // Paper + this.cipher = cipher; // Paper - Use Velocity cipher
} }
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception {
- this.cipher.encipher(byteBuf, byteBuf2); - this.cipher.encipher(byteBuf, byteBuf2);
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception { + protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
+ // Paper start + // Paper start - Use Velocity cipher
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf); + ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
+ try { + try {
+ cipher.process(compatible); + cipher.process(compatible);
@ -91,15 +91,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ compatible.release(); // compatible will never be used if we throw an exception + compatible.release(); // compatible will never be used if we throw an exception
+ throw e; + throw e;
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
} }
+ +
+ // Paper start + // Paper start - Use Velocity cipher
+ @Override + @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ cipher.close(); + cipher.close();
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
} }
diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -109,11 +109,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152; public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608; public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
private final Inflater inflater; private final Inflater inflater;
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper + private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher
private int threshold; private int threshold;
private boolean validateDecompressed; private boolean validateDecompressed;
+ // Paper start + // Paper start - Use Velocity cipher
public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) { public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) {
+ this(null, compressionThreshold, rejectsBadPackets); + this(null, compressionThreshold, rejectsBadPackets);
+ } + }
@ -123,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.inflater = new Inflater(); - this.inflater = new Inflater();
+ this.inflater = compressor == null ? new Inflater() : null; + this.inflater = compressor == null ? new Inflater() : null;
+ this.compressor = compressor; + this.compressor = compressor;
+ // Paper end + // Paper end - Use Velocity cipher
} }
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception { protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
@ -131,15 +131,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
+ if (inflater != null) { // Paper - use velocity compression - fallback to vanilla inflater + if (inflater != null) { // Paper - Use Velocity cipher; fallback to vanilla inflater
this.setupInflaterInput(byteBuf); this.setupInflaterInput(byteBuf);
ByteBuf byteBuf2 = this.inflate(channelHandlerContext, i); ByteBuf byteBuf2 = this.inflate(channelHandlerContext, i);
this.inflater.reset(); this.inflater.reset();
list.add(byteBuf2); list.add(byteBuf2);
+ return; // Paper - use velocity compression + return; // Paper - Use Velocity cipher
+ } // Paper - use velocity compression + } // Paper - use velocity compression
+ +
+ // Paper start - use velocity compression + // Paper start - Use Velocity cipher
+ int claimedUncompressedSize = i; // OBFHELPER + int claimedUncompressedSize = i; // OBFHELPER
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf); + ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
+ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize); + ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize);
@ -153,19 +153,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } finally { + } finally {
+ compatibleIn.release(); + compatibleIn.release();
+ } + }
+ // Paper end - use velocity compression + // Paper end - Use Velocity cipher
} }
} }
} }
+ // Paper start + // Paper start - Use Velocity cipher
+ @Override + @Override
+ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { + public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
+ if (this.compressor != null) { + if (this.compressor != null) {
+ this.compressor.close(); + this.compressor.close();
+ } + }
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
+ +
private void setupInflaterInput(ByteBuf buf) { private void setupInflaterInput(ByteBuf buf) {
ByteBuffer byteBuffer; ByteBuffer byteBuffer;
@ -179,12 +179,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> { public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
- private final byte[] encodeBuf = new byte[8192]; - private final byte[] encodeBuf = new byte[8192];
+ private final byte[] encodeBuf; // Paper + private final byte[] encodeBuf; // Paper - Use Velocity cipher
private final Deflater deflater; private final Deflater deflater;
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper + private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher
private int threshold; private int threshold;
+ // Paper start + // Paper start - Use Velocity cipher
public CompressionEncoder(int compressionThreshold) { public CompressionEncoder(int compressionThreshold) {
+ this(null, compressionThreshold); + this(null, compressionThreshold);
+ } + }
@ -199,17 +199,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.deflater = null; + this.deflater = null;
+ } + }
+ this.compressor = compressor; + this.compressor = compressor;
+ // Paper end + // Paper end - Use Velocity cipher
} }
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) { - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) {
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper + protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper - Use Velocity cipher
int i = byteBuf.readableBytes(); int i = byteBuf.readableBytes();
if (i < this.threshold) { if (i < this.threshold) {
VarInt.write(byteBuf2, 0); VarInt.write(byteBuf2, 0);
byteBuf2.writeBytes(byteBuf); byteBuf2.writeBytes(byteBuf);
} else { } else {
+ // Paper start + // Paper start - Use Velocity cipher
+ if (this.deflater != null) { + if (this.deflater != null) {
byte[] bs = new byte[i]; byte[] bs = new byte[i];
byteBuf.readBytes(bs); byteBuf.readBytes(bs);
@ -228,12 +228,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } finally { + } finally {
+ compatibleIn.release(); + compatibleIn.release();
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
} }
} }
+ // Paper start + // Paper start - Use Velocity cipher
+ @Override + @Override
+ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{ + protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{
+ if (this.compressor != null) { + if (this.compressor != null) {
@ -258,7 +258,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.compressor.close(); + this.compressor.close();
+ } + }
+ } + }
+ // Paper end + // Paper end - Use Velocity cipher
+ +
public int getThreshold() { public int getThreshold() {
return this.threshold; return this.threshold;
@ -275,7 +275,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.encrypted = true; - this.encrypted = true;
- this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher)); - this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
- this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher)); - this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
+ // Paper start + // Paper start - Use Velocity cipher
+// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) { +// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
+// this.encrypted = true; +// this.encrypted = true;
+// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher)); +// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
@ -296,7 +296,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ } + }
} }
+ // Paper end + // Paper end - Use Velocity cipher
public boolean isEncrypted() { public boolean isEncrypted() {
return this.encrypted; return this.encrypted;
@ -304,19 +304,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) { public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
if (compressionThreshold >= 0) { if (compressionThreshold >= 0) {
+ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper + com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper - Use Velocity cipher
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets); ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets);
} else { } else {
- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets)); - this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper + this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper - Use Velocity cipher
} }
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold); ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold);
} else { } else {
- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold)); - this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
+ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper + this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper - Use Velocity cipher
} }
this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper
} else { } else {
@ -328,10 +328,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
ServerConnectionListener.LOGGER.info("Using default channel type"); ServerConnectionListener.LOGGER.info("Using default channel type");
} }
+ // Paper start - indicate Velocity natives in use + // Paper start - Use Velocity cipher
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity."); + ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); + ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
+ // Paper end + // Paper end - Use Velocity cipher
+ +
this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() { this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) { protected void initChannel(Channel channel) {
@ -346,15 +346,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
SecretKey secretkey = packet.getSecretKey(privatekey); SecretKey secretkey = packet.getSecretKey(privatekey);
- Cipher cipher = Crypt.getCipher(2, secretkey); - Cipher cipher = Crypt.getCipher(2, secretkey);
- Cipher cipher1 = Crypt.getCipher(1, secretkey); - Cipher cipher1 = Crypt.getCipher(1, secretkey);
+ // Paper start + // Paper start - Use Velocity cipher
+// Cipher cipher = Crypt.getCipher(2, secretkey); +// Cipher cipher = Crypt.getCipher(2, secretkey);
+// Cipher cipher1 = Crypt.getCipher(1, secretkey); +// Cipher cipher1 = Crypt.getCipher(1, secretkey);
+ // Paper end + // Paper end - Use Velocity cipher
s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16); s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16);
this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING; this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING;
- this.connection.setEncryptionKey(cipher, cipher1); - this.connection.setEncryptionKey(cipher, cipher1);
+ this.connection.setupEncryption(secretkey); // Paper + this.connection.setupEncryption(secretkey); // Paper - Use Velocity cipher
} catch (CryptException cryptographyexception) { } catch (CryptException cryptographyexception) {
throw new IllegalStateException("Protocol error", cryptographyexception); throw new IllegalStateException("Protocol error", cryptographyexception);
} }

Datei anzeigen

@ -17,18 +17,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import java.util.function.Predicate; import java.util.function.Predicate;
public abstract class ArgumentBuilder<S, T extends ArgumentBuilder<S, T>> { public abstract class ArgumentBuilder<S, T extends ArgumentBuilder<S, T>> {
+ // Paper start + // Paper start - Vanilla command permission fixes
+ private static final Predicate<Object> DEFAULT_REQUIREMENT = s -> true; + private static final Predicate<Object> DEFAULT_REQUIREMENT = s -> true;
+ +
+ @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked")
+ public static <S> Predicate<S> defaultRequirement() { + public static <S> Predicate<S> defaultRequirement() {
+ return (Predicate<S>) DEFAULT_REQUIREMENT; + return (Predicate<S>) DEFAULT_REQUIREMENT;
+ } + }
+ // Paper end + // Paper end - Vanilla command permission fixes
private final RootCommandNode<S> arguments = new RootCommandNode<>(); private final RootCommandNode<S> arguments = new RootCommandNode<>();
private Command<S> command; private Command<S> command;
- private Predicate<S> requirement = s -> true; - private Predicate<S> requirement = s -> true;
+ private Predicate<S> requirement = defaultRequirement(); // Paper + private Predicate<S> requirement = defaultRequirement(); // Paper - Vanilla command permission fixes
private CommandNode<S> target; private CommandNode<S> target;
private RedirectModifier<S> modifier = null; private RedirectModifier<S> modifier = null;
private boolean forks; private boolean forks;
@ -40,13 +40,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
this.vanillaCommandNodes.addAll(this.dispatcher.getRoot().getChildren()); // Paper this.vanillaCommandNodes.addAll(this.dispatcher.getRoot().getChildren()); // Paper
+ // Paper start + // Paper start - Vanilla command permission fixes
+ for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) { + for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) {
+ if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) { + if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) {
+ node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node)); + node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node));
+ } + }
+ } + }
+ // Paper end + // Paper end - Vanilla command permission fixes
// CraftBukkit start // CraftBukkit start
} }
@ -59,7 +59,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static String getPermission(CommandNode<CommandSourceStack> vanillaCommand) { public static String getPermission(CommandNode<CommandSourceStack> vanillaCommand) {
- return "minecraft.command." + ((vanillaCommand.getRedirect() == null) ? vanillaCommand.getName() : vanillaCommand.getRedirect().getName()); - return "minecraft.command." + ((vanillaCommand.getRedirect() == null) ? vanillaCommand.getName() : vanillaCommand.getRedirect().getName());
+ // Paper start + // Paper start - Vanilla command permission fixes
+ final String commandName; + final String commandName;
+ if (vanillaCommand.getRedirect() == null) { + if (vanillaCommand.getRedirect() == null) {
+ commandName = vanillaCommand.getName(); + commandName = vanillaCommand.getName();
@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return maybeNamespaced.substring(prefix.length()); + return maybeNamespaced.substring(prefix.length());
+ } + }
+ return maybeNamespaced; + return maybeNamespaced;
+ // Paper end + // Paper end - Vanilla command permission fixes
} }
private String toDispatcher(String[] args, String name) { private String toDispatcher(String[] args, String name) {

Datei anzeigen

@ -12,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) { public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
return Optional.empty(); return Optional.empty();
} }
+ // Paper start + // Paper start - fix menus with empty level accesses
+ @Override + @Override
+ public org.bukkit.Location getLocation() { + public org.bukkit.Location getLocation() {
+ return null; + return null;
+ } + }
+ // Paper end + // Paper end - fix menus with empty level accesses
}; };
static ContainerLevelAccess create(final Level world, final BlockPos pos) { static ContainerLevelAccess create(final Level world, final BlockPos pos) {

Datei anzeigen

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (!world.isClientSide && player.canUseGameMasterBlocks()) { if (!world.isClientSide && player.canUseGameMasterBlocks()) {
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper + if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper - Prevent unintended light block manipulation
world.setBlock(pos, state.cycle(LEVEL), 2); world.setBlock(pos, state.cycle(LEVEL), 2);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} else { } else {