1.21.6 dev

Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
This commit is contained in:
Bjarne Koll
2025-05-28 13:23:32 +02:00
committed by Nassim Jahnke
parent 39203a65e0
commit a24f9b204c
788 changed files with 41006 additions and 6324 deletions

View File

@@ -10,11 +10,14 @@ import java.util.Map;
import java.util.UUID;
import net.minecraft.core.GlobalPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundTagQueryPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.UserWhiteListEntry;
import net.minecraft.stats.ServerStatsCounter;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.level.storage.PlayerDataStorage;
import net.minecraft.world.level.storage.TagValueOutput;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.bukkit.BanEntry;
@@ -196,7 +199,8 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
}
private CompoundTag getData() {
return this.storage.load(this.profile.getName(), this.profile.getId().toString()).orElse(null);
// This method does not use the problem reporter
return this.storage.load(this.profile.getName(), this.profile.getId().toString(), ProblemReporter.DISCARDING).orElse(null);
}
private CompoundTag getBukkitData() {

View File

@@ -198,7 +198,6 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
BlockPos pos = CraftLocation.toBlockPosition(location);
BlockStateListPopulator populator = new BlockStateListPopulator(this.getHandle());
boolean result = this.generateTree(populator, this.getHandle().getMinecraftWorld().getChunkSource().getGenerator(), pos, new RandomSourceWrapper(random), treeType);
populator.refreshTiles();
populator.placeSomeBlocks(predicate == null ? ($ -> true) : predicate);
return result;
}

View File

@@ -205,7 +205,8 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return cached;
}
final Optional<Holder.Reference<M>> holderOptional = this.minecraftRegistry.get(CraftNamespacedKey.toMinecraft(namespacedKey));
// Important to use the ResourceKey<?> "get" method below because it will work before registry is frozen
final Optional<Holder.Reference<M>> holderOptional = this.minecraftRegistry.get(MCUtil.toResourceKey(this.minecraftRegistry.key(), namespacedKey));
final Holder.Reference<M> holder;
if (holderOptional.isPresent()) {
holder = holderOptional.get();
@@ -215,12 +216,9 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
// to create something to fill the API constant fields, so we create a dummy reference holder.
holder = Holder.Reference.createStandAlone(this.invalidHolderOwner, MCUtil.toResourceKey(this.minecraftRegistry.key(), namespacedKey));
} else {
holder = null;
}
final B bukkit = this.createBukkit(holder);
if (bukkit == null) {
return null;
}
final B bukkit = this.createBukkit(holder);
this.cache.put(namespacedKey, bukkit);
@@ -250,10 +248,6 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
}
public B createBukkit(Holder<M> minecraft) {
if (minecraft == null) {
return null;
}
return this.minecraftToBukkit.createBukkit(minecraft);
}

View File

@@ -21,7 +21,7 @@ import org.bukkit.entity.EntityType;
public enum CraftStatistic {
// Start generate - CraftStatisticCustom
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
ANIMALS_BRED(Stats.ANIMALS_BRED),
AVIATE_ONE_CM(Stats.AVIATE_ONE_CM),
BELL_RING(Stats.BELL_RING),
@@ -46,6 +46,7 @@ public enum CraftStatistic {
CAULDRON_FILLED(Stats.FILL_CAULDRON),
FISH_CAUGHT(Stats.FISH_CAUGHT),
FLY_ONE_CM(Stats.FLY_ONE_CM),
HAPPY_GHAST_ONE_CM(Stats.HAPPY_GHAST_ONE_CM),
HORSE_ONE_CM(Stats.HORSE_ONE_CM),
DISPENSER_INSPECTED(Stats.INSPECT_DISPENSER),
DROPPER_INSPECTED(Stats.INSPECT_DROPPER),
@@ -99,7 +100,7 @@ public enum CraftStatistic {
WALK_UNDER_WATER_ONE_CM(Stats.WALK_UNDER_WATER_ONE_CM),
// End generate - CraftStatisticCustom
// Start generate - CraftStatisticType
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
BREAK_ITEM(ResourceLocation.withDefaultNamespace("broken")),
CRAFT_ITEM(ResourceLocation.withDefaultNamespace("crafted")),
DROP(ResourceLocation.withDefaultNamespace("dropped")),

View File

@@ -1,5 +1,7 @@
package org.bukkit.craftbukkit;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.mojang.datafixers.util.Pair;
@@ -12,6 +14,7 @@ import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -19,6 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.PrimitiveIterator;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
@@ -40,6 +44,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
@@ -243,7 +248,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public BiomeProvider vanillaBiomeProvider() {
net.minecraft.server.level.ServerChunkCache serverCache = this.getHandle().chunkSource;
ServerChunkCache serverCache = this.getHandle().chunkSource;
final net.minecraft.world.level.chunk.ChunkGenerator gen = serverCache.getGenerator();
net.minecraft.world.level.biome.BiomeSource biomeSource;
@@ -421,8 +426,21 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public Chunk[] getLoadedChunks() {
List<ChunkHolder> chunks = ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.world); // Paper
return chunks.stream().map(ChunkHolder::getFullChunkNow).filter(Objects::nonNull).map(CraftChunk::new).toArray(Chunk[]::new);
ServerChunkCache serverChunkCache = this.getHandle().chunkSource;
ReferenceList<Chunk> chunks = new ReferenceList<>(new Chunk[serverChunkCache.fullChunks.size()]);
for (PrimitiveIterator.OfLong iterator = serverChunkCache.fullChunks.keyIterator(); iterator.hasNext();) {
long chunk = iterator.nextLong();
chunks.add(new CraftChunk(this.world, CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk)));
}
Chunk[] raw = chunks.getRawDataUnchecked();
int size = chunks.size();
if (raw.length == size) {
// always true when on main
return raw;
}
return Arrays.copyOf(raw, size);
}
@Override
@@ -631,7 +649,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Set<Chunk> chunks = new HashSet<>();
for (long coord : this.getHandle().getForceLoadedChunks()) {
chunks.add(this.getChunkAt(ChunkPos.getX(coord), ChunkPos.getZ(coord)));
chunks.add(new CraftChunk(this.getHandle(), ChunkPos.getX(coord), ChunkPos.getZ(coord)));
}
return Collections.unmodifiableCollection(chunks);
@@ -828,7 +846,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
CraftPlayer cp = (CraftPlayer) p;
if (cp.getHandle().connection == null) continue;
cp.getHandle().connection.send(new ClientboundSetTimePacket(cp.getHandle().level().getGameTime(), cp.getHandle().getPlayerTime(), cp.getHandle().relativeTime && cp.getHandle().serverLevel().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
cp.getHandle().connection.send(new ClientboundSetTimePacket(cp.getHandle().level().getGameTime(), cp.getHandle().getPlayerTime(), cp.getHandle().relativeTime && cp.getHandle().level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
}
}

View File

@@ -3,16 +3,16 @@ package org.bukkit.craftbukkit;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.util.PathConverter;
import static java.util.Arrays.asList;
public class Main {
public static final java.time.Instant BOOT_TIME = java.time.Instant.now(); // Paper - track initial start time
public static boolean useJline = true;
@@ -25,41 +25,40 @@ public class Main {
// Paper end - Reset loggers after shutdown
public static void main(String[] args) {
// Todo: Installation script
if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size; https://www.evanjones.ca/java-bytebuffer-leak.html
OptionParser parser = new OptionParser() {
{
this.acceptsAll(Main.asList("?", "help"), "Show the help");
this.acceptsAll(asList("?", "help"), "Show the help");
this.acceptsAll(Main.asList("c", "config"), "Properties file to use")
this.acceptsAll(asList("c", "config"), "Properties file to use")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("server.properties"))
.describedAs("Properties file");
this.acceptsAll(Main.asList("P", "plugins"), "Plugin directory to use")
this.acceptsAll(asList("P", "plugins"), "Plugin directory to use")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("plugins"))
.describedAs("Plugin directory");
this.acceptsAll(Main.asList("h", "host", "server-ip"), "Host to listen on")
this.acceptsAll(asList("h", "host", "server-ip"), "Host to listen on")
.withRequiredArg()
.ofType(String.class)
.describedAs("Hostname or IP");
this.acceptsAll(Main.asList("W", "world-dir", "universe", "world-container"), "World container")
this.acceptsAll(asList("W", "world-dir", "universe", "world-container"), "World container")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("."))
.describedAs("Directory containing worlds");
this.acceptsAll(Main.asList("w", "world", "level-name"), "World name")
this.acceptsAll(asList("w", "world", "level-name"), "World name")
.withRequiredArg()
.ofType(String.class)
.describedAs("World name");
this.acceptsAll(Main.asList("p", "port", "server-port"), "Port to listen on")
this.acceptsAll(asList("p", "port", "server-port"), "Port to listen on")
.withRequiredArg()
.ofType(Integer.class)
.describedAs("Port");
@@ -73,99 +72,99 @@ public class Main {
.withRequiredArg()
.withValuesConvertedBy(new PathConverter());
this.acceptsAll(Main.asList("o", "online-mode"), "Whether to use online authentication")
this.acceptsAll(asList("o", "online-mode"), "Whether to use online authentication")
.withRequiredArg()
.ofType(Boolean.class)
.describedAs("Authentication");
this.acceptsAll(Main.asList("s", "size", "max-players"), "Maximum amount of players")
this.acceptsAll(asList("s", "size", "max-players"), "Maximum amount of players")
.withRequiredArg()
.ofType(Integer.class)
.describedAs("Server size");
this.acceptsAll(Main.asList("d", "date-format"), "Format of the date to display in the console (for log entries)")
this.acceptsAll(asList("d", "date-format"), "Format of the date to display in the console (for log entries)")
.withRequiredArg()
.ofType(SimpleDateFormat.class)
.describedAs("Log date format");
this.acceptsAll(Main.asList("log-pattern"), "Specfies the log filename pattern")
this.accepts("log-pattern", "Specfies the log filename pattern")
.withRequiredArg()
.ofType(String.class)
.defaultsTo("server.log")
.describedAs("Log filename");
this.acceptsAll(Main.asList("log-limit"), "Limits the maximum size of the log file (0 = unlimited)")
this.accepts("log-limit", "Limits the maximum size of the log file (0 = unlimited)")
.withRequiredArg()
.ofType(Integer.class)
.defaultsTo(0)
.describedAs("Max log size");
this.acceptsAll(Main.asList("log-count"), "Specified how many log files to cycle through")
this.accepts("log-count", "Specified how many log files to cycle through")
.withRequiredArg()
.ofType(Integer.class)
.defaultsTo(1)
.describedAs("Log count");
this.acceptsAll(Main.asList("log-append"), "Whether to append to the log file")
this.accepts("log-append", "Whether to append to the log file")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(true)
.describedAs("Log append");
this.acceptsAll(Main.asList("log-strip-color"), "Strips color codes from log file");
this.accepts("log-strip-color", "Strips color codes from log file");
this.acceptsAll(Main.asList("b", "bukkit-settings"), "File for bukkit settings")
this.acceptsAll(asList("b", "bukkit-settings"), "File for bukkit settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("bukkit.yml"))
.describedAs("Yml file");
this.acceptsAll(Main.asList("C", "commands-settings"), "File for command settings")
this.acceptsAll(asList("C", "commands-settings"), "File for command settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("commands.yml"))
.describedAs("Yml file");
this.acceptsAll(Main.asList("forceUpgrade"), "Whether to force a world upgrade");
this.acceptsAll(Main.asList("eraseCache"), "Whether to force cache erase during world upgrade");
this.acceptsAll(Main.asList("recreateRegionFiles"), "Whether to recreate region files during world upgrade");
this.accepts("forceUpgrade", "Whether to force a world upgrade");
this.accepts("eraseCache", "Whether to force cache erase during world upgrade");
this.accepts("recreateRegionFiles", "Whether to recreate region files during world upgrade");
this.accepts("safeMode", "Loads level with vanilla datapack only"); // Paper
this.acceptsAll(Main.asList("nogui"), "Disables the graphical console");
this.accepts("nogui", "Disables the graphical console");
this.acceptsAll(Main.asList("nojline"), "Disables jline and emulates the vanilla console");
this.accepts("nojline", "Disables jline and emulates the vanilla console");
this.acceptsAll(Main.asList("noconsole"), "Disables the console");
this.accepts("noconsole", "Disables the console");
this.acceptsAll(Main.asList("v", "version"), "Show the CraftBukkit Version");
this.acceptsAll(asList("v", "version"), "Show the CraftBukkit Version");
this.acceptsAll(Main.asList("demo"), "Demo mode");
this.accepts("demo", "Demo mode");
this.acceptsAll(Main.asList("initSettings"), "Only create configuration files and then exit"); // SPIGOT-5761: Add initSettings option
this.accepts("initSettings", "Only create configuration files and then exit"); // SPIGOT-5761: Add initSettings option
this.acceptsAll(Main.asList("S", "spigot-settings"), "File for spigot settings")
this.acceptsAll(asList("S", "spigot-settings"), "File for spigot settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("spigot.yml"))
.describedAs("Yml file");
acceptsAll(asList("paper-dir", "paper-settings-directory"), "Directory for Paper settings")
this.acceptsAll(asList("paper-dir", "paper-settings-directory"), "Directory for Paper settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File(io.papermc.paper.configuration.PaperConfigurations.CONFIG_DIR))
.describedAs("Config directory");
acceptsAll(asList("paper", "paper-settings"), "File for Paper settings")
this.acceptsAll(asList("paper", "paper-settings"), "File for Paper settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("paper.yml"))
.describedAs("Yml file");
acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.")
this.acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File[] {})
.describedAs("Jar file");
acceptsAll(asList("server-name"), "Name of the server")
this.accepts("server-name", "Name of the server")
.withRequiredArg()
.ofType(String.class)
.defaultsTo("Unknown Server")
@@ -246,8 +245,4 @@ public class Main {
}
}
}
private static List<String> asList(String... params) {
return Arrays.asList(params);
}
}

View File

@@ -40,10 +40,7 @@ public final class CapturedBlockState extends CraftBlockState {
@Override
public boolean place(int flags) {
boolean result = super.place(flags);
if (result) {
this.addBees();
}
this.addBees();
return result;
}

View File

@@ -7,7 +7,6 @@ import org.bukkit.NamespacedKey;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.Objects;
@@ -61,17 +60,17 @@ public class CraftBiome extends OldEnumHolderable<Biome, net.minecraft.world.lev
}
@Override
public @NotNull NamespacedKey getKey() {
public NamespacedKey getKey() {
return LEGACY_CUSTOM_KEY;
}
@Override
public int compareTo(@NotNull final Biome other) {
public int compareTo(final Biome other) {
return this.ordinal - other.ordinal();
}
@Override
public @NotNull String name() {
public String name() {
return "CUSTOM";
}

View File

@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.block;
import java.util.Set;
import com.mojang.logging.LogUtils;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentPatch;
@@ -9,8 +10,11 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.TileState;
@@ -19,9 +23,12 @@ import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
private static final Logger LOGGER = LogUtils.getLogger();
private final T blockEntity;
private final T snapshot;
public boolean snapshotDisabled; // Paper
@@ -67,10 +74,6 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
this.loadData(state.getSnapshotNBT());
}
public void refreshSnapshot() {
this.load(this.blockEntity);
}
private RegistryAccess getRegistryAccess() {
LevelAccessor worldHandle = this.getWorldHandle();
return (worldHandle != null) ? worldHandle.registryAccess() : CraftRegistry.getMinecraftRegistry();
@@ -97,14 +100,22 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
// Loads the specified data into the snapshot BlockEntity.
public void loadData(CompoundTag tag) {
this.snapshot.loadWithComponents(tag, this.getRegistryAccess());
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "CraftBlockEntityState@" + getPosition().toShortString(), LOGGER
)) {
this.snapshot.loadWithComponents(TagValueInput.create(problemReporter, this.getRegistryAccess(), tag));
}
this.load(this.snapshot);
}
// copies the BlockEntity-specific data, retains the position
private void copyData(T from, T to) {
CompoundTag tag = from.saveWithFullMetadata(this.getRegistryAccess());
to.loadWithComponents(tag, this.getRegistryAccess());
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "CraftBlockEntityState@" + getPosition().toShortString(), LOGGER
)) {
to.loadWithComponents(TagValueInput.create(problemReporter, this.getRegistryAccess(), tag));
}
}
// gets the wrapped BlockEntity
@@ -143,13 +154,21 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
// Paper start - properly save blockentity itemstacks
public CompoundTag getSnapshotCustomNbtOnly() {
this.applyTo(this.snapshot);
final CompoundTag nbt = this.snapshot.saveCustomOnly(this.getRegistryAccess());
this.snapshot.removeComponentsFromTag(nbt);
if (!nbt.isEmpty()) {
// have to include the "id" if it's going to have block entity data
this.snapshot.saveId(nbt);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "CraftBlockEntityState@" + getPosition().toShortString(), LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWrappingWithContext(
problemReporter,
this.getRegistryAccess(),
this.snapshot.saveCustomOnly(this.getRegistryAccess())
);
this.snapshot.removeComponentsFromTag(output);
if (!output.isEmpty()) {
// have to include the "id" if it's going to have block entity data
this.snapshot.saveId(output);
}
return output.buildResult();
}
return nbt;
}
// Paper end
@@ -183,15 +202,14 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
@Override
public boolean place(int flags) {
if (super.place(flags)) {
this.getWorldHandle().getBlockEntity(this.getPosition(), this.blockEntity.getType()).ifPresent(blockEntity -> {
this.applyTo((T) blockEntity);
blockEntity.setChanged();
});
return true;
}
boolean result = super.place(flags);
return false;
this.getWorldHandle().getBlockEntity(this.getPosition(), this.blockEntity.getType()).ifPresent(blockEntity -> {
this.applyTo((T) blockEntity);
blockEntity.setChanged();
});
return result;
}
@Override

View File

@@ -85,7 +85,7 @@ public final class CraftBlockStates {
static {
// Start generate - CraftBlockEntityStates
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);

View File

@@ -2,7 +2,9 @@ package org.bukkit.craftbukkit.block;
import java.util.ArrayList;
import java.util.Collection;
import net.minecraft.Optionull;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.phys.AABB;
import org.bukkit.Location;
@@ -83,7 +85,7 @@ public class CraftConduit extends CraftBlockEntityState<ConduitBlockEntity> impl
return false;
}
net.minecraft.world.entity.LivingEntity currentTarget = conduit.destroyTarget;
EntityReference<net.minecraft.world.entity.LivingEntity> currentTarget = conduit.destroyTarget;
if (target == null) {
if (currentTarget == null) {
@@ -91,17 +93,22 @@ public class CraftConduit extends CraftBlockEntityState<ConduitBlockEntity> impl
}
conduit.destroyTarget = null;
conduit.destroyTargetUUID = null;
} else {
if (currentTarget != null && target.getUniqueId().equals(currentTarget.getUUID())) {
return false;
}
conduit.destroyTarget = ((CraftLivingEntity) target).getHandle();
conduit.destroyTargetUUID = target.getUniqueId();
conduit.destroyTarget = new EntityReference<>(((CraftLivingEntity) target).getHandle());
}
ConduitBlockEntity.updateDestroyTarget(conduit.getLevel(), this.getPosition(), this.data, conduit.effectBlocks, conduit, false);
ConduitBlockEntity.updateAndAttackTarget(
conduit.getLevel().getMinecraftWorld(),
this.getPosition(),
this.data,
conduit,
conduit.effectBlocks.size() >= ConduitBlockEntity.MIN_KILL_SIZE,
false
);
return true;
}
@@ -112,14 +119,17 @@ public class CraftConduit extends CraftBlockEntityState<ConduitBlockEntity> impl
return null;
}
net.minecraft.world.entity.LivingEntity nmsEntity = conduit.destroyTarget;
return (nmsEntity != null) ? (LivingEntity) nmsEntity.getBukkitEntity() : null;
final net.minecraft.world.entity.LivingEntity nmsEntity = EntityReference.get(conduit.destroyTarget, this.getWorldHandle().getMinecraftWorld(), net.minecraft.world.entity.LivingEntity.class);
return nmsEntity == null ? null : nmsEntity.getBukkitLivingEntity();
}
@Override
public boolean hasTarget() {
ConduitBlockEntity conduit = (ConduitBlockEntity) this.getBlockEntityFromWorld();
return conduit != null && conduit.destroyTarget != null && conduit.destroyTarget.isAlive();
if (conduit == null) return false;
final net.minecraft.world.entity.LivingEntity destroyTarget = EntityReference.get(conduit.destroyTarget, this.getWorldHandle().getMinecraftWorld(), net.minecraft.world.entity.LivingEntity.class);
return destroyTarget != null && destroyTarget.isAlive();
}
@Override

View File

@@ -8,8 +8,10 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.InclusiveRange;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.Weighted;
import net.minecraft.util.random.WeightedList;
@@ -17,6 +19,8 @@ import net.minecraft.world.entity.EquipmentTable;
import net.minecraft.world.level.BaseSpawner;
import net.minecraft.world.level.SpawnData;
import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.ValueInput;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
@@ -46,8 +50,11 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
return null;
}
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn());
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getInternalWorld().registryAccess(), spawnData.entityToSpawn());
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
}
}
@Override
@@ -175,9 +182,12 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
if (spawnData == null) {
return null;
}
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getInternalWorld().registryAccess(), spawnData.getEntityToSpawn());
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn());
return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null);
return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null);
}
}
@Override

View File

@@ -46,8 +46,8 @@ public abstract class CraftFurnace<T extends AbstractFurnaceBlockEntity> extends
@Override
public void setBurnTime(short burnTime) {
this.getSnapshot().litTimeRemaining = burnTime;
// SPIGOT-844: Allow lighting and relighting using this API
this.data = this.data.setValue(AbstractFurnaceBlock.LIT, burnTime > 0);
this.data = this.data.trySetValue(AbstractFurnaceBlock.LIT, burnTime > 0);
// only try, block data might have changed to something different that would not allow this property
}
@Override

View File

@@ -7,7 +7,7 @@ import java.util.UUID;
import net.minecraft.core.Holder;
import net.minecraft.world.level.block.TrialSpawnerBlock;
import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerStateData;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -23,8 +23,8 @@ public class CraftTrialSpawner extends CraftBlockEntityState<TrialSpawnerBlockEn
public CraftTrialSpawner(World world, TrialSpawnerBlockEntity blockEntity) {
super(world, blockEntity);
this.normalConfig = new CraftTrialSpawnerConfiguration(blockEntity.getTrialSpawner().getNormalConfig(), this.getSnapshot());
this.ominousConfig = new CraftTrialSpawnerConfiguration(blockEntity.getTrialSpawner().getOminousConfig(), this.getSnapshot());
this.normalConfig = new CraftTrialSpawnerConfiguration(blockEntity.getTrialSpawner().normalConfig(), this.getSnapshot());
this.ominousConfig = new CraftTrialSpawnerConfiguration(blockEntity.getTrialSpawner().ominousConfig(), this.getSnapshot());
}
protected CraftTrialSpawner(CraftTrialSpawner state, Location location) {
@@ -35,22 +35,22 @@ public class CraftTrialSpawner extends CraftBlockEntityState<TrialSpawnerBlockEn
@Override
public long getCooldownEnd() {
return this.getSnapshot().trialSpawner.getData().cooldownEndsAt;
return this.getSnapshot().trialSpawner.getStateData().cooldownEndsAt;
}
@Override
public void setCooldownEnd(long ticks) {
this.getSnapshot().trialSpawner.getData().cooldownEndsAt = ticks;
this.getSnapshot().trialSpawner.getStateData().cooldownEndsAt = ticks;
}
@Override
public long getNextSpawnAttempt() {
return this.getSnapshot().trialSpawner.getData().nextMobSpawnsAt;
return this.getSnapshot().trialSpawner.getStateData().nextMobSpawnsAt;
}
@Override
public void setNextSpawnAttempt(long ticks) {
this.getSnapshot().trialSpawner.getData().nextMobSpawnsAt = ticks;
this.getSnapshot().trialSpawner.getStateData().nextMobSpawnsAt = ticks;
}
@Override
@@ -60,17 +60,17 @@ public class CraftTrialSpawner extends CraftBlockEntityState<TrialSpawnerBlockEn
@Override
public void setCooldownLength(int ticks) {
this.getSnapshot().trialSpawner.targetCooldownLength = ticks;
this.getSnapshot().trialSpawner.config = this.getSnapshot().trialSpawner.config.overrideTargetCooldownLength(ticks);
}
@Override
public int getRequiredPlayerRange() {
return this.getSnapshot().trialSpawner.getRequiredPlayerRange();
return this.getSnapshot().trialSpawner.getRequiredPlayerRange();
}
@Override
public void setRequiredPlayerRange(int requiredPlayerRange) {
this.getSnapshot().trialSpawner.requiredPlayerRange = requiredPlayerRange;
this.getSnapshot().trialSpawner.config = this.getSnapshot().trialSpawner.config.overrideRequiredPlayerRange(requiredPlayerRange);
}
@Override
@@ -160,24 +160,26 @@ public class CraftTrialSpawner extends CraftBlockEntityState<TrialSpawnerBlockEn
@Override
public TrialSpawnerConfiguration getNormalConfiguration() {
return this.normalConfig;
return this.normalConfig;
}
@Override
public TrialSpawnerConfiguration getOminousConfiguration() {
return this.ominousConfig;
return this.ominousConfig;
}
@Override
protected void applyTo(TrialSpawnerBlockEntity blockEntity) {
super.applyTo(blockEntity);
blockEntity.trialSpawner.normalConfig = Holder.direct(this.normalConfig.toMinecraft());
blockEntity.trialSpawner.ominousConfig = Holder.direct(this.ominousConfig.toMinecraft());
blockEntity.trialSpawner.config = blockEntity.trialSpawner.config.overrideConfigs(
Holder.direct(this.normalConfig.toMinecraft()),
Holder.direct(this.ominousConfig.toMinecraft())
);
}
private TrialSpawnerData getTrialData() {
return this.getSnapshot().getTrialSpawner().getData();
private TrialSpawnerStateData getTrialData() {
return this.getSnapshot().getTrialSpawner().getStateData();
}
@Override

View File

@@ -7,16 +7,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.mojang.logging.LogUtils;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.random.Weighted;
import net.minecraft.util.random.WeightedList;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.SpawnData;
import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerStateData;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.block.spawner.SpawnRule;
import org.bukkit.block.spawner.SpawnerEntry;
import org.bukkit.craftbukkit.CraftLootTable;
@@ -26,8 +30,12 @@ import org.bukkit.entity.EntitySnapshot;
import org.bukkit.entity.EntityType;
import org.bukkit.loot.LootTable;
import org.bukkit.spawner.TrialSpawnerConfiguration;
import org.slf4j.Logger;
public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration {
private static final Logger LOGGER = LogUtils.getLogger();
private final TrialSpawnerBlockEntity snapshot;
private int spawnRange;
@@ -56,12 +64,21 @@ public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration
@Override
public EntityType getSpawnedType() {
if (this.spawnPotentialsDefinition.isEmpty()) {
return null;
}
if (this.spawnPotentialsDefinition.isEmpty()) {
return null;
}
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(this.spawnPotentialsDefinition.unwrap().get(0).value().getEntityToSpawn());
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "TrialSpawnerConfiguration@" + snapshot.getBlockPos().toShortString(), LOGGER
)) {
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(
TagValueInput.createGlobal(
problemReporter,
this.spawnPotentialsDefinition.unwrap().getFirst().value().getEntityToSpawn()
)
);
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
}
}
@Override
@@ -74,7 +91,7 @@ public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration
Preconditions.checkArgument(entityType != EntityType.UNKNOWN, "Can't spawn EntityType %s from mob spawners!", entityType);
SpawnData data = new SpawnData();
data.getEntityToSpawn().putString(Entity.ID_TAG, BuiltInRegistries.ENTITY_TYPE.getKey(CraftEntityType.bukkitToMinecraft(entityType)).toString());
data.getEntityToSpawn().putString(Entity.TAG_ID, BuiltInRegistries.ENTITY_TYPE.getKey(CraftEntityType.bukkitToMinecraft(entityType)).toString());
this.getTrialData().nextSpawnData = Optional.of(data);
this.spawnPotentialsDefinition = WeightedList.of(data);
}
@@ -121,7 +138,7 @@ public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration
@Override
public int getDelay() {
return this.ticksBetweenSpawn;
return this.ticksBetweenSpawn;
}
@Override
@@ -287,16 +304,16 @@ public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration
@Override
public int getRequiredPlayerRange() {
return this.snapshot.trialSpawner.getRequiredPlayerRange();
return this.snapshot.trialSpawner.getRequiredPlayerRange();
}
@Override
public void setRequiredPlayerRange(int requiredPlayerRange) {
this.snapshot.trialSpawner.requiredPlayerRange = requiredPlayerRange;
this.snapshot.trialSpawner.config = this.snapshot.trialSpawner.config.overrideRequiredPlayerRange(requiredPlayerRange);
}
private TrialSpawnerData getTrialData() {
return this.snapshot.getTrialSpawner().getData();
private TrialSpawnerStateData getTrialData() {
return this.snapshot.getTrialSpawner().getStateData();
}
protected TrialSpawnerConfig toMinecraft() {

View File

@@ -362,7 +362,7 @@ public class CraftBlockData implements BlockData {
static {
//<editor-fold desc="CraftBlockData Registration" defaultstate="collapsed">
// Start generate - CraftBlockData#MAP
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
register(net.minecraft.world.level.block.AmethystClusterBlock.class, org.bukkit.craftbukkit.block.impl.CraftAmethystCluster::new);
register(net.minecraft.world.level.block.AnvilBlock.class, org.bukkit.craftbukkit.block.impl.CraftAnvil::new);
register(net.minecraft.world.level.block.AttachedStemBlock.class, org.bukkit.craftbukkit.block.impl.CraftAttachedStem::new);
@@ -418,6 +418,7 @@ public class CraftBlockData implements BlockData {
register(net.minecraft.world.level.block.DispenserBlock.class, org.bukkit.craftbukkit.block.impl.CraftDispenser::new);
register(net.minecraft.world.level.block.DoorBlock.class, org.bukkit.craftbukkit.block.impl.CraftDoor::new);
register(net.minecraft.world.level.block.DoublePlantBlock.class, org.bukkit.craftbukkit.block.impl.CraftDoublePlant::new);
register(net.minecraft.world.level.block.DriedGhastBlock.class, org.bukkit.craftbukkit.block.impl.CraftDriedGhast::new);
register(net.minecraft.world.level.block.DropperBlock.class, org.bukkit.craftbukkit.block.impl.CraftDropper::new);
register(net.minecraft.world.level.block.EndPortalFrameBlock.class, org.bukkit.craftbukkit.block.impl.CraftEndPortalFrame::new);
register(net.minecraft.world.level.block.EndRodBlock.class, org.bukkit.craftbukkit.block.impl.CraftEndRod::new);

View File

@@ -1,5 +1,8 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.Optionull;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityReference;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Projectile;
@@ -76,7 +79,7 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
@Override
public java.util.UUID getOwnerUniqueId() {
return this.getHandle().ownerUUID;
return Optionull.map(this.getHandle().owner, EntityReference::getUUID);
}
// Paper end - More projectile API
}

View File

@@ -139,7 +139,11 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac
@Override
public void setRearing(boolean rearing) {
this.getHandle().setForceStanding(rearing);
if (rearing) {
this.getHandle().setStanding(Integer.MAX_VALUE);
} else {
this.getHandle().clearStanding();
}
}
@Override

View File

@@ -2,6 +2,8 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import java.util.UUID;
import net.minecraft.Optionull;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.entity.animal.Animal;
import org.bukkit.Material;
import org.bukkit.craftbukkit.CraftServer;
@@ -22,12 +24,12 @@ public class CraftAnimals extends CraftAgeable implements Animals {
@Override
public UUID getBreedCause() {
return this.getHandle().loveCause;
return Optionull.map(this.getHandle().loveCause, EntityReference::getUUID);
}
@Override
public void setBreedCause(UUID uuid) {
this.getHandle().loveCause = uuid;
this.getHandle().loveCause = uuid == null ? null : new EntityReference<>(uuid);
}
@Override

View File

@@ -3,9 +3,11 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
import net.minecraft.Optionull;
import net.minecraft.core.Holder;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.item.alchemy.PotionContents;
import org.bukkit.Color;
import org.bukkit.Particle;
@@ -115,7 +117,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public <T> void setParticle(Particle particle, T data) {
this.getHandle().setParticle(CraftParticle.createParticleParam(particle, data));
this.getHandle().setCustomParticle(CraftParticle.createParticleParam(particle, data));
}
@Override
@@ -226,13 +228,12 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
// Paper start - owner API
@Override
public java.util.UUID getOwnerUniqueId() {
return this.getHandle().ownerUUID;
return Optionull.map(this.getHandle().owner, EntityReference::getUUID);
}
@Override
public void setOwnerUniqueId(final java.util.UUID ownerUuid) {
this.getHandle().setOwner(null);
this.getHandle().ownerUUID = ownerUuid;
this.getHandle().owner = ownerUuid == null ? null : new EntityReference<>(ownerUuid);
}
// Paper end
}

View File

@@ -18,7 +18,7 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo {
@Override
public State getState() {
return CraftArmadillo.stateToBukkit(this.getHandle().getState());
return State.valueOf(this.getHandle().getState().name());
}
@Override
@@ -37,22 +37,4 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo {
this.getHandle().lastHurtByMob = null; // Clear this memory to not have the sensor trigger rollUp instantly for damaged armadillo
this.getHandle().getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, ArmadilloState.UNROLLING.animationDuration());
}
public static State stateToBukkit(ArmadilloState state) {
return switch (state) {
case IDLE -> State.IDLE;
case ROLLING -> State.ROLLING;
case SCARED -> State.SCARED;
case UNROLLING -> State.UNROLLING;
};
}
public static ArmadilloState stateToNMS(State state) {
return switch (state) {
case State.IDLE -> ArmadilloState.IDLE;
case State.ROLLING -> ArmadilloState.ROLLING;
case State.SCARED -> ArmadilloState.SCARED;
case State.UNROLLING -> ArmadilloState.UNROLLING;
};
}
}

View File

@@ -72,7 +72,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getBodyPose() {
return CraftArmorStand.fromNMS(this.getHandle().bodyPose);
return CraftArmorStand.fromNMS(this.getHandle().getBodyPose());
}
@Override
@@ -82,7 +82,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getLeftArmPose() {
return CraftArmorStand.fromNMS(this.getHandle().leftArmPose);
return CraftArmorStand.fromNMS(this.getHandle().getLeftArmPose());
}
@Override
@@ -92,7 +92,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getRightArmPose() {
return CraftArmorStand.fromNMS(this.getHandle().rightArmPose);
return CraftArmorStand.fromNMS(this.getHandle().getRightArmPose());
}
@Override
@@ -102,7 +102,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getLeftLegPose() {
return CraftArmorStand.fromNMS(this.getHandle().leftLegPose);
return CraftArmorStand.fromNMS(this.getHandle().getLeftLegPose());
}
@Override
@@ -112,7 +112,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getRightLegPose() {
return CraftArmorStand.fromNMS(this.getHandle().rightLegPose);
return CraftArmorStand.fromNMS(this.getHandle().getRightLegPose());
}
@Override
@@ -122,7 +122,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public EulerAngle getHeadPose() {
return CraftArmorStand.fromNMS(this.getHandle().headPose);
return CraftArmorStand.fromNMS(this.getHandle().getHeadPose());
}
@Override
@@ -293,7 +293,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getBodyRotations() {
return fromNMSRotations(this.getHandle().bodyPose);
return fromNMSRotations(this.getHandle().getBodyPose());
}
@Override
@@ -303,7 +303,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getLeftArmRotations() {
return fromNMSRotations(this.getHandle().leftArmPose);
return fromNMSRotations(this.getHandle().getLeftArmPose());
}
@Override
@@ -313,7 +313,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getRightArmRotations() {
return fromNMSRotations(this.getHandle().rightArmPose);
return fromNMSRotations(this.getHandle().getRightArmPose());
}
@Override
@@ -323,7 +323,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getLeftLegRotations() {
return fromNMSRotations(this.getHandle().leftLegPose);
return fromNMSRotations(this.getHandle().getLeftLegPose());
}
@Override
@@ -333,7 +333,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getRightLegRotations() {
return fromNMSRotations(this.getHandle().rightLegPose);
return fromNMSRotations(this.getHandle().getRightLegPose());
}
@Override
@@ -343,7 +343,7 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
@Override
public io.papermc.paper.math.Rotations getHeadRotations() {
return fromNMSRotations(this.getHandle().headPose);
return fromNMSRotations(this.getHandle().getHeadPose());
}
@Override

View File

@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.Optionull;
import net.minecraft.world.entity.projectile.EyeOfEnder;
import net.minecraft.world.item.Items;
import org.bukkit.Location;
@@ -22,7 +23,7 @@ public class CraftEnderSignal extends CraftEntity implements EnderSignal {
@Override
public Location getTargetLocation() {
return new Location(this.getWorld(), this.getHandle().tx, this.getHandle().ty, this.getHandle().tz, this.getHandle().getYRot(), this.getHandle().getXRot());
return Optionull.map(this.getHandle().target, target -> CraftLocation.toBukkit(target, this.getWorld(), this.getHandle().getYRot(), this.getHandle().getXRot()));
}
@Override
@@ -35,7 +36,7 @@ public class CraftEnderSignal extends CraftEntity implements EnderSignal {
public void setTargetLocation(Location location, boolean update) {
// Paper end - Change EnderEye target without changing other things
Preconditions.checkArgument(this.getWorld().equals(location.getWorld()), "Cannot target EnderSignal across worlds");
this.getHandle().signalTo(CraftLocation.toBlockPosition(location), update); // Paper - Change EnderEye target without changing other things
this.getHandle().signalTo(CraftLocation.toVec3(location), update); // Paper - Change EnderEye target without changing other things
}
@Override

View File

@@ -5,6 +5,7 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.mojang.logging.LogUtils;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.entity.TeleportFlag;
import java.util.HashSet;
@@ -15,7 +16,6 @@ import io.papermc.paper.entity.LookAnchor;
import java.util.concurrent.CompletableFuture;
import net.kyori.adventure.util.TriState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
@@ -24,12 +24,16 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.level.storage.TagValueOutput;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.bukkit.EntityEffect;
@@ -73,8 +77,12 @@ import org.bukkit.util.Vector;
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public abstract class CraftEntity implements org.bukkit.entity.Entity {
private static final Logger LOGGER = LogUtils.getLogger();
private static PermissibleBase perm;
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
@@ -979,12 +987,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@Override
public String getAsString() {
CompoundTag tag = new CompoundTag();
if (!this.getHandle().saveAsPassenger(tag, false, true, true)) {
return null;
}
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "Entity#toString", LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWithContext(
problemReporter,
this.getHandle().registryAccess()
);
if (!this.getHandle().saveAsPassenger(output, false, true, true)) {
return null;
}
return tag.toString();
return output.buildResult().toString();
}
}
@Override
@@ -1012,32 +1027,40 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
private Entity copy(net.minecraft.world.level.Level level) {
CompoundTag compoundTag = new CompoundTag();
this.getHandle().saveAsPassenger(compoundTag, false, true, true);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "Entity#copy", LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWithContext(problemReporter, level.registryAccess());
this.getHandle().saveAsPassenger(output, false, true, true);
return net.minecraft.world.entity.EntityType.loadEntityRecursive(compoundTag, level, EntitySpawnReason.LOAD, java.util.function.Function.identity());
return net.minecraft.world.entity.EntityType.loadEntityRecursive(output.buildResult(), level, EntitySpawnReason.LOAD, java.util.function.Function.identity());
}
}
public void storeBukkitValues(CompoundTag c) {
public void storeBukkitValues(ValueOutput output) {
if (!this.persistentDataContainer.isEmpty()) {
c.put("BukkitValues", this.persistentDataContainer.toTagCompound());
output.store("BukkitValues", CompoundTag.CODEC, this.persistentDataContainer.toTagCompound());
}
}
public void readBukkitValues(CompoundTag c) {
Tag base = c.get("BukkitValues");
if (base instanceof CompoundTag) {
this.persistentDataContainer.putAll((CompoundTag) base);
}
public void readBukkitValues(ValueInput input) {
input.read("BukkitValues", CompoundTag.CODEC).ifPresent(this.persistentDataContainer::putAll);
}
protected CompoundTag save() {
CompoundTag tag = new CompoundTag();
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "Entity#save", LOGGER
)) {
final TagValueOutput tagValueOutput = TagValueOutput.createWithContext(
problemReporter,
this.getHandle().registryAccess()
);
tag.putString(Entity.ID_TAG, this.getHandle().getEncodeId()); // todo NPE?
this.getHandle().saveWithoutId(tag);
tagValueOutput.putString(Entity.TAG_ID, this.getHandle().getEncodeId(true));
this.getHandle().saveWithoutId(tagValueOutput);
return tag;
return tagValueOutput.buildResult();
}
}
// re-sends the spawn entity packet to updated values which cannot be updated otherwise

View File

@@ -2,14 +2,19 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.logging.LogUtils;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.entity.EntityFactory;
import org.bukkit.entity.EntitySnapshot;
import org.slf4j.Logger;
public class CraftEntityFactory implements EntityFactory {
private static final Logger LOGGER = LogUtils.getLogger();
private static final CraftEntityFactory instance;
static {
@@ -30,7 +35,12 @@ public class CraftEntityFactory implements EntityFactory {
throw new IllegalArgumentException("Could not parse Entity: " + input, e);
}
EntityType<?> type = EntityType.by(tag).orElse(null);
final EntityType<?> type;
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "createEntitySnapshot", LOGGER
)) {
type = EntityType.by(TagValueInput.createGlobal(problemReporter, tag)).orElse(null);
}
if (type == null) {
throw new IllegalArgumentException("Could not parse Entity: " + input);
}

View File

@@ -2,16 +2,25 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import java.util.function.Function;
import com.mojang.logging.LogUtils;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntitySnapshot;
import org.bukkit.entity.EntityType;
import org.slf4j.Logger;
public class CraftEntitySnapshot implements EntitySnapshot {
private static final Logger LOGGER = LogUtils.getLogger();
private final CompoundTag data;
private final EntityType type;
@@ -55,7 +64,11 @@ public class CraftEntitySnapshot implements EntitySnapshot {
}
Preconditions.checkArgument(internal != null, "Error creating new entity."); // This should only fail if the stored CompoundTag is malformed.
internal.load(this.data);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "EntitySnapshot#createEntity", LOGGER
)) {
internal.load(TagValueInput.createGlobal(problemReporter, this.data));
}
return internal;
}
@@ -65,12 +78,19 @@ public class CraftEntitySnapshot implements EntitySnapshot {
}
public static CraftEntitySnapshot create(CraftEntity entity) {
CompoundTag tag = new CompoundTag();
if (!entity.getHandle().saveAsPassenger(tag, false, false, false)) {
return null;
}
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "create@" + entity.getUniqueId(), LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWithContext(
problemReporter,
CraftRegistry.getMinecraftRegistry()
);
if (!entity.getHandle().saveAsPassenger(output, false, false, false)) {
return null;
}
return new CraftEntitySnapshot(tag, entity.getType());
return new CraftEntitySnapshot(output.buildResult(), entity.getType());
}
}
public static CraftEntitySnapshot create(CompoundTag tag, EntityType type) {
@@ -82,7 +102,13 @@ public class CraftEntitySnapshot implements EntitySnapshot {
}
public static CraftEntitySnapshot create(CompoundTag tag) {
EntityType type = net.minecraft.world.entity.EntityType.by(tag).map(CraftEntityType::minecraftToBukkit).orElse(null);
return CraftEntitySnapshot.create(tag, type);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "create", LOGGER
)) {
EntityType type = net.minecraft.world.entity.EntityType.by(
TagValueInput.createGlobal(problemReporter, tag)
).map(CraftEntityType::minecraftToBukkit).orElse(null);
return CraftEntitySnapshot.create(tag, type);
}
}
}

View File

@@ -106,6 +106,7 @@ import org.bukkit.entity.GlowSquid;
import org.bukkit.entity.Goat;
import org.bukkit.entity.Guardian;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.HappyGhast;
import org.bukkit.entity.Hoglin;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Husk;
@@ -352,6 +353,7 @@ public final class CraftEntityTypes {
register(new EntityTypeData<>(EntityType.BREEZE, Breeze.class, CraftBreeze::new, createLiving(net.minecraft.world.entity.EntityType.BREEZE)));
register(new EntityTypeData<>(EntityType.ARMADILLO, Armadillo.class, CraftArmadillo::new, createLiving(net.minecraft.world.entity.EntityType.ARMADILLO)));
register(new EntityTypeData<>(EntityType.CREAKING, Creaking.class, CraftCreaking::new, createLiving(net.minecraft.world.entity.EntityType.CREAKING)));
register(new EntityTypeData<>(EntityType.HAPPY_GHAST, HappyGhast.class, CraftHappyGhast::new, createLiving(net.minecraft.world.entity.EntityType.HAPPY_GHAST)));
Function<SpawnData, net.minecraft.world.entity.boss.enderdragon.EnderDragon> dragonFunction = createLiving(net.minecraft.world.entity.EntityType.ENDER_DRAGON);
register(new EntityTypeData<>(EntityType.ENDER_DRAGON, EnderDragon.class, CraftEnderDragon::new, spawnData -> {

View File

@@ -1,17 +0,0 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.world.entity.FlyingMob;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Flying;
public class CraftFlying extends CraftMob implements Flying {
public CraftFlying(CraftServer server, FlyingMob entity) {
super(server, entity);
}
@Override
public FlyingMob getHandle() {
return (FlyingMob) this.entity;
}
}

View File

@@ -3,7 +3,7 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Ghast;
public class CraftGhast extends CraftFlying implements Ghast, CraftEnemy {
public class CraftGhast extends CraftMob implements Ghast, CraftEnemy {
public CraftGhast(CraftServer server, net.minecraft.world.entity.monster.Ghast entity) {
super(server, entity);

View File

@@ -0,0 +1,10 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.HappyGhast;
public class CraftHappyGhast extends CraftAnimals implements HappyGhast {
public CraftHappyGhast(final CraftServer server, final net.minecraft.world.entity.animal.HappyGhast entity) {
super(server, entity);
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import com.mojang.logging.LogUtils;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.key.Key;
import net.minecraft.core.BlockPos;
@@ -18,11 +19,13 @@ import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
@@ -38,6 +41,7 @@ import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -78,9 +82,11 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
private static final Logger LOGGER = LogUtils.getLogger();
private CraftInventoryPlayer inventory;
private final CraftInventory enderChest;
protected final PermissibleBase perm = new PermissibleBase(this);
@@ -175,7 +181,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
return null;
}
net.minecraft.server.level.ServerLevel level = ((ServerPlayer) this.getHandle()).server.getLevel(respawnConfig.dimension());
net.minecraft.server.level.ServerLevel level = ((ServerPlayer) this.getHandle()).getServer().getLevel(respawnConfig.dimension());
if (level == null) {
return null;
}
@@ -769,8 +775,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@Override
public org.bukkit.entity.Entity getShoulderEntityLeft() {
if (!this.getHandle().getShoulderEntityLeft().isEmpty()) {
Optional<Entity> shoulder = EntityType.create(this.getHandle().getShoulderEntityLeft(), this.getHandle().level(), EntitySpawnReason.LOAD);
return shoulder.map(Entity::getBukkitEntity).orElse(null);
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(this.getHandle().problemPath(), LOGGER)) {
return EntityType.create(
TagValueInput.create(scopedCollector.forChild(() -> ".shoulder"), this.getHandle().registryAccess(), this.getHandle().getShoulderEntityLeft()),
this.getHandle().level(),
EntitySpawnReason.LOAD
).map(Entity::getBukkitEntity).orElse(null);
}
}
return null;
@@ -778,6 +789,9 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@Override
public void setShoulderEntityLeft(org.bukkit.entity.Entity entity) {
if (entity != null) {
Preconditions.checkArgument(((CraftEntity) entity).getHandle().getType().canSerialize(), "Cannot set entity of type %s as a shoulder entity", entity.getType().getKey());
}
this.getHandle().setShoulderEntityLeft(entity == null ? new CompoundTag() : ((CraftEntity) entity).save());
if (entity != null) {
entity.remove();
@@ -787,8 +801,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@Override
public org.bukkit.entity.Entity getShoulderEntityRight() {
if (!this.getHandle().getShoulderEntityRight().isEmpty()) {
Optional<Entity> shoulder = EntityType.create(this.getHandle().getShoulderEntityRight(), this.getHandle().level(), EntitySpawnReason.LOAD);
return shoulder.map(Entity::getBukkitEntity).orElse(null);
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(this.getHandle().problemPath(), LOGGER)) {
return EntityType.create(
TagValueInput.create(scopedCollector.forChild(() -> ".shoulder"), this.getHandle().registryAccess(), this.getHandle().getShoulderEntityRight()),
this.getHandle().level(),
EntitySpawnReason.LOAD
).map(Entity::getBukkitEntity).orElse(null);
}
}
return null;
@@ -796,6 +815,9 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@Override
public void setShoulderEntityRight(org.bukkit.entity.Entity entity) {
if (entity != null) {
Preconditions.checkArgument(((CraftEntity) entity).getHandle().getType().canSerialize(), "Cannot set entity of type %s as a shoulder entity", entity.getType().getKey());
}
this.getHandle().setShoulderEntityRight(entity == null ? new CompoundTag() : ((CraftEntity) entity).save());
if (entity != null) {
entity.remove();

View File

@@ -1,7 +1,9 @@
package org.bukkit.craftbukkit.entity;
import java.util.UUID;
import com.google.common.base.Preconditions;
import java.util.UUID;
import net.minecraft.Optionull;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.entity.item.ItemEntity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
@@ -136,11 +138,11 @@ public class CraftItem extends CraftEntity implements Item {
@Override
public void setThrower(UUID uuid) {
this.getHandle().thrower = uuid;
this.getHandle().thrower = uuid == null ? null : new EntityReference<>(uuid);
}
@Override
public UUID getThrower() {
return this.getHandle().thrower;
return Optionull.map(this.getHandle().thrower, EntityReference::getUUID);
}
}

View File

@@ -4,10 +4,12 @@ import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.WeightedList;
import net.minecraft.world.entity.vehicle.MinecartSpawner;
import net.minecraft.world.level.SpawnData;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.block.spawner.SpawnRule;
import org.bukkit.block.spawner.SpawnerEntry;
import org.bukkit.craftbukkit.CraftServer;
@@ -34,8 +36,14 @@ public class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMin
return null;
}
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn());
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "getSpawnedType@" + this.getUniqueId(), LOGGER
)) {
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(
TagValueInput.create(problemReporter, getHandle().registryAccess(), spawnData.getEntityToSpawn())
);
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
}
}
@Override

View File

@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.Phantom;
import java.util.UUID;
public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy {
public class CraftPhantom extends CraftMob implements Phantom, CraftEnemy {
public CraftPhantom(CraftServer server, net.minecraft.world.entity.monster.Phantom entity) {
super(server, entity);
@@ -50,7 +50,6 @@ public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy {
@Override
public void setAnchorLocation(Location location) {
com.google.common.base.Preconditions.checkArgument(location != null, "location cannot be null");
this.getHandle().anchorPoint = location == null ? null : CraftLocation.toBlockPosition(location);
}
}

View File

@@ -106,6 +106,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.players.UserWhiteListEntry;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attributes;
@@ -120,6 +121,8 @@ import net.minecraft.world.level.border.BorderChangeListener;
import net.minecraft.world.level.saveddata.maps.MapDecoration;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import org.bukkit.BanEntry;
import org.bukkit.BanList;
import org.bukkit.Bukkit;
@@ -1530,7 +1533,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void loadData() {
this.server.getHandle().playerIo.load(this.getHandle());
this.server.getHandle().playerIo.load(this.getHandle(), ProblemReporter.DISCARDING);
}
@Override
@@ -1560,7 +1563,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
final ServerPlayer.RespawnConfig respawnConfig = this.getHandle().getRespawnConfig();
if (respawnConfig == null) return null;
final ServerLevel world = this.getHandle().server.getLevel(respawnConfig.dimension());
final ServerLevel world = this.getHandle().getServer().getLevel(respawnConfig.dimension());
if (world == null) return null;
if (!loadLocationAndValidate) {
@@ -1885,7 +1888,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ());
final int possibleDurabilityFromXp = net.minecraft.world.item.enchantment.EnchantmentHelper.modifyDurabilityToRepairFromXp(
handle.serverLevel(), itemstack, amount
handle.level(), itemstack, amount
);
int i = Math.min(possibleDurabilityFromXp, itemstack.getDamageValue());
final int consumedExperience = i > 0 ? i * amount / possibleDurabilityFromXp : possibleDurabilityFromXp; // Paper - taken from ExperienceOrb#repairPlayerItems + prevent division by 0
@@ -2234,11 +2237,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
ServerGamePacketListenerImpl connection = handle.connection;
// Respawn the player then update their position and selected slot
ServerLevel level = handle.serverLevel();
ServerLevel level = handle.level();
connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(handle.createCommonSpawnInfo(level), net.minecraft.network.protocol.game.ClientboundRespawnPacket.KEEP_ALL_DATA));
handle.onUpdateAbilities();
connection.internalTeleport(net.minecraft.world.entity.PositionMoveRotation.of(this.getHandle()), java.util.Collections.emptySet());
net.minecraft.server.players.PlayerList playerList = handle.server.getPlayerList();
net.minecraft.server.players.PlayerList playerList = handle.getServer().getPlayerList();
playerList.sendPlayerPermissionLevel(handle, false);
playerList.sendLevelInfo(handle, level);
playerList.sendAllPlayerInfo(handle);
@@ -2351,9 +2354,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// Paper end - getLastPlayed replacement API
public void readExtraData(CompoundTag tag) {
public void readExtraData(ValueInput input) {
this.hasPlayedBefore = true;
tag.getCompound("bukkit").ifPresent(data -> {
input.child("bukkit").ifPresent(data -> {
this.firstPlayed = data.getLongOr("firstPlayed", 0);
this.lastPlayed = data.getLongOr("lastPlayed", 0);
@@ -2366,14 +2369,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
});
}
public void setExtraData(CompoundTag tag) {
public void setExtraData(ValueOutput output) {
this.lastSaveTime = System.currentTimeMillis(); // Paper
if (!tag.contains("bukkit")) {
tag.put("bukkit", new CompoundTag());
}
CompoundTag data = tag.getCompoundOrEmpty("bukkit");
ValueOutput data = output.child("bukkit");
ServerPlayer handle = this.getHandle();
data.putInt("newExp", handle.newExp);
data.putInt("newTotalExp", handle.newTotalExp);
@@ -2385,11 +2384,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
data.putString("lastKnownName", handle.getScoreboardName());
// Paper start - persist for use in offline save data
if (!tag.contains("Paper")) {
tag.put("Paper", new CompoundTag());
}
CompoundTag paper = tag.getCompoundOrEmpty("Paper");
ValueOutput paper = output.child("Paper");
paper.putLong("LastLogin", handle.loginTime);
paper.putLong("LastSeen", System.currentTimeMillis());
// Paper end
@@ -3016,7 +3011,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void updateCommands() {
if (this.getHandle().connection == null) return;
this.getHandle().server.getCommands().sendCommands(this.getHandle());
this.getHandle().getServer().getCommands().sendCommands(this.getHandle());
}
@Override

View File

@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.entity.item.PrimedTnt;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Entity;
@@ -57,7 +58,7 @@ public class CraftTNTPrimed extends CraftEntity implements TNTPrimed {
@Override
public void setSource(Entity source) {
if (source instanceof LivingEntity) {
this.getHandle().owner = ((CraftLivingEntity) source).getHandle();
this.getHandle().owner = new EntityReference<>(((CraftLivingEntity) source).getHandle());
} else {
this.getHandle().owner = null;
}

View File

@@ -2,6 +2,7 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.EntityReference;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.CraftLocation;
@@ -20,13 +21,13 @@ public class CraftVex extends CraftMonster implements Vex {
@Override
public org.bukkit.entity.Mob getSummoner() {
net.minecraft.world.entity.Mob owner = getHandle().getOwner();
net.minecraft.world.entity.Mob owner = this.getHandle().getOwner();
return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null;
}
@Override
public void setSummoner(org.bukkit.entity.Mob summoner) {
getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle());
this.getHandle().owner = summoner == null ? null : new EntityReference<>(((CraftMob) summoner).getHandle());
}
@Override

View File

@@ -27,6 +27,7 @@ import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.animal.AbstractFish;
import net.minecraft.world.entity.animal.AbstractGolem;
@@ -881,7 +882,7 @@ public class CraftEventFactory {
public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List<Entity.DefaultDrop> drops, net.kyori.adventure.text.Component deathMessage, boolean showDeathMessages, boolean keepInventory) {
CraftPlayer entity = victim.getBukkitEntity();
CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource);
PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(victim.serverLevel(), damageSource.getEntity()), 0, deathMessage, showDeathMessages);
PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(victim.level(), damageSource.getEntity()), 0, deathMessage, showDeathMessages);
event.setKeepInventory(keepInventory);
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
populateFields(victim, event); // Paper - make cancellable
@@ -1490,10 +1491,56 @@ public class CraftEventFactory {
Bukkit.getPluginManager().callEvent(new PlayerRecipeBookSettingsChangeEvent(player.getBukkitEntity(), bukkitType, open, filter));
}
public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Entity entity, net.minecraft.world.entity.player.Player player, InteractionHand hand, boolean dropLeash) {
public static boolean handlePlayerUnleashEntityEvent(
final Leashable leashable,
final net.minecraft.world.entity.player.@Nullable Player player,
final @Nullable InteractionHand hand,
final boolean dropLeash,
final boolean resendState
) {
if (!(leashable instanceof final Entity entity)) return true;
return handlePlayerUnleashEntityEvent(entity, player, hand, dropLeash, resendState);
}
public static boolean handlePlayerUnleashEntityEvent(
final Entity entity,
final net.minecraft.world.entity.player.@Nullable Player player,
final @Nullable InteractionHand hand,
final boolean dropLeash,
final boolean resendState
) {
if (player == null || hand == null) {
if (entity instanceof final Leashable leashable) {
if (dropLeash) leashable.dropLeash();
else leashable.removeLeash();
}
return true;
}
PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), dropLeash);
entity.level().getCraftServer().getPluginManager().callEvent(event);
return event;
if (event.isCancelled()) {
if (resendState && entity instanceof final Leashable leashable) {
((ServerPlayer) player).connection.send(new net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket(entity, leashable.getLeashHolder()));
}
return false;
}
if (entity instanceof final Leashable leashable) {
if (event.isDropLeash()) leashable.dropLeash();
else leashable.removeLeash();
}
return true;
}
public static boolean handlePlayerLeashEntityEvent(Leashable leashed, Entity leashHolder, net.minecraft.world.entity.player.Player player, InteractionHand hand) {
if (!(leashed instanceof final Entity leashedEntity)) return false;
return callPlayerLeashEntityEvent(leashedEntity, leashHolder, player, hand).callEvent();
}
public static @Nullable PlayerLeashEntityEvent callPlayerLeashEntityEvent(Leashable leashed, Entity leashHolder, net.minecraft.world.entity.player.Player player, InteractionHand hand) {
if (!(leashed instanceof final Entity leashedEntity)) return null;
return callPlayerLeashEntityEvent(leashedEntity, leashHolder, player, hand);
}
public static PlayerLeashEntityEvent callPlayerLeashEntityEvent(Entity entity, Entity leashHolder, net.minecraft.world.entity.player.Player player, InteractionHand hand) {

View File

@@ -7,9 +7,11 @@ import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.ChunkPos;
@@ -17,6 +19,7 @@ import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.HeightMap;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -30,9 +33,12 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.LimitedRegion;
import org.bukkit.util.BoundingBox;
import org.slf4j.Logger;
public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRegion {
private static final Logger LOGGER = LogUtils.getLogger();
private final WeakReference<WorldGenLevel> weakAccess;
private final int centerChunkX;
private final int centerChunkZ;
@@ -271,7 +277,16 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
if (!state.getBlockData().matches(getHandle().getBlockState(pos).createCraftBlockData())) {
throw new IllegalArgumentException("BlockData does not match! Expected " + state.getBlockData().getAsString(false) + ", got " + getHandle().getBlockState(pos).createCraftBlockData().getAsString(false));
}
getHandle().getBlockEntity(pos).loadWithComponents(((org.bukkit.craftbukkit.block.CraftBlockEntityState<?>) state).getSnapshotNBT(), this.getHandle().registryAccess());
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "CraftLimitedRegion@" + pos.toShortString(), LOGGER
)) {
getHandle().getBlockEntity(pos).loadWithComponents(TagValueInput.create(
problemReporter,
this.getHandle().registryAccess(),
((org.bukkit.craftbukkit.block.CraftBlockEntityState<?>) state).getSnapshotNBT()
));
}
}
@Override

View File

@@ -20,12 +20,12 @@ public class CraftInventoryAbstractHorse extends CraftInventory implements Abstr
@Override
public ItemStack getSaddle() {
return this.getItem(HorseInventoryMenu.SLOT_SADDLE); // Paper
return this.getItem(HorseInventoryMenu.SLOT_SADDLE);
}
@Override
public void setSaddle(ItemStack stack) {
this.setItem(HorseInventoryMenu.SLOT_SADDLE, stack); // Paper
this.setItem(HorseInventoryMenu.SLOT_SADDLE, stack);
}
public Container getMainInventory() {
@@ -88,14 +88,17 @@ public class CraftInventoryAbstractHorse extends CraftInventory implements Abstr
@Override
public ItemStack getItem(final int index) {
if (index == HorseInventoryMenu.SLOT_BODY_ARMOR) {
final net.minecraft.world.item.ItemStack item = this.getArmorInventory().getItem(0);
return item.isEmpty() ? null : CraftItemStack.asCraftMirror(item);
} else if (index == HorseInventoryMenu.SLOT_SADDLE) {
if (index == HorseInventoryMenu.SLOT_SADDLE) {
final net.minecraft.world.item.ItemStack item = this.getSaddleInventory().getItem(0);
return item.isEmpty() ? null : CraftItemStack.asCraftMirror(item);
} else if (index == HorseInventoryMenu.SLOT_BODY_ARMOR) {
final net.minecraft.world.item.ItemStack item = this.getArmorInventory().getItem(0);
return item.isEmpty() ? null : CraftItemStack.asCraftMirror(item);
} else {
int shiftedIndex = index;
if (index > HorseInventoryMenu.SLOT_SADDLE) {
shiftedIndex--;
}
if (index > HorseInventoryMenu.SLOT_BODY_ARMOR) {
shiftedIndex--;
}
@@ -107,16 +110,16 @@ public class CraftInventoryAbstractHorse extends CraftInventory implements Abstr
@Override
public void setItem(final int index, final ItemStack item) {
if (index == HorseInventoryMenu.SLOT_BODY_ARMOR) {
this.getArmorInventory().setItem(0, CraftItemStack.asNMSCopy(item));
} else if (index == HorseInventoryMenu.SLOT_SADDLE) {
if (index == HorseInventoryMenu.SLOT_SADDLE) {
this.getSaddleInventory().setItem(0, CraftItemStack.asNMSCopy(item));
} else if (index == HorseInventoryMenu.SLOT_BODY_ARMOR) {
this.getArmorInventory().setItem(0, CraftItemStack.asNMSCopy(item));
} else {
int shiftedIndex = index;
if (index > HorseInventoryMenu.SLOT_BODY_ARMOR) {
if (index > HorseInventoryMenu.SLOT_SADDLE) {
shiftedIndex--;
}
if (index > HorseInventoryMenu.SLOT_SADDLE) {
if (index > HorseInventoryMenu.SLOT_BODY_ARMOR) {
shiftedIndex--;
}
this.getMainInventory().setItem(shiftedIndex, CraftItemStack.asNMSCopy(item));

View File

@@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import java.util.List;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket;
import net.minecraft.network.protocol.game.ClientboundSetPlayerInventoryPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
@@ -71,14 +72,25 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
@Override
public void setItem(int index, ItemStack item) {
// Paper start - Validate setItem index
if (index < 0 || index > 40) {
throw new ArrayIndexOutOfBoundsException("Index must be between 0 and 40");
if (index < 0 || index > 42) {
throw new ArrayIndexOutOfBoundsException("Index must be between 0 and 42");
}
// Paper end - Validate setItem index
super.setItem(index, item);
if (this.getHolder() == null) return;
ServerPlayer player = ((CraftPlayer) this.getHolder()).getHandle();
if (player.connection == null) return;
// Of course, these are not part of the player inventory "menu" because these slots are not accessible.
// However they are technically part of the player inventory.
// This is a poor representation by this API, but basically instead send a player inventory update packet.
// This will allow updates to the player inventory rather than through the menu.
// TODO: This could be something worth cleaning up in the future.
if (index > 40) {
player.connection.send(new ClientboundSetPlayerInventoryPacket(index, CraftItemStack.asNMSCopy(item)));
return;
}
// PacketPlayOutSetSlot places the items differently than setItem()
//
// Between, and including, index 9 (the first index outside of the hotbar) and index 35 (the last index before
@@ -123,11 +135,8 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
switch (slot) {
case HAND -> this.setItemInMainHand(item);
case OFF_HAND, FEET, LEGS, CHEST, HEAD ->
case OFF_HAND, FEET, LEGS, CHEST, HEAD, BODY, SADDLE ->
this.getInventory().equipment.set(CraftEquipmentSlot.getNMS(slot), CraftItemStack.asNMSCopy(item));
case BODY -> throw new IllegalArgumentException("BODY is not valid for players!"); // Paper end
default ->
throw new IllegalArgumentException("Could not set slot " + slot + " - not a valid slot for PlayerInventory");
}
}
@@ -142,10 +151,7 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
return switch (slot) {
case HAND -> this.getItemInMainHand();
case OFF_HAND, FEET, LEGS, CHEST, HEAD -> CraftItemStack.asCraftMirror(this.getInventory().equipment.get(CraftEquipmentSlot.getNMS(slot)));
case BODY -> throw new IllegalArgumentException("BODY is not valid for players!");
default ->
throw new IllegalArgumentException("Could not get slot " + slot + " - not a valid slot for PlayerInventory");
case OFF_HAND, FEET, LEGS, CHEST, HEAD, BODY, SADDLE -> CraftItemStack.asCraftMirror(this.getInventory().equipment.get(CraftEquipmentSlot.getNMS(slot)));
};
}
@@ -253,12 +259,12 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
@Override
public ItemStack[] getExtraContents() {
return this.asCraftMirror(List.of(this.getInventory().equipment.get(net.minecraft.world.entity.EquipmentSlot.OFFHAND)));
return this.asCraftMirror(this.getInventory().getExtraContent());
}
@Override
public void setExtraContents(ItemStack[] items) {
this.setSlots(items, this.getInventory().getNonEquipmentItems().size() + this.getInventory().getArmorContents().size(), 1);
this.setSlots(items, this.getInventory().getNonEquipmentItems().size() + this.getInventory().getArmorContents().size(), 3);
}
@Override

View File

@@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Optional;
import io.papermc.paper.registry.data.util.Conversions;
import net.minecraft.commands.arguments.item.ItemParser;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
@@ -332,7 +333,7 @@ public final class CraftItemFactory implements ItemFactory {
Optional.of(
io.papermc.paper.registry.set.PaperRegistrySets.convertToNms(
Registries.ENCHANTMENT,
net.minecraft.server.MinecraftServer.getServer().registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE).lookupProvider,
Conversions.global().lookup(),
keySet
)
),

View File

@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.inventory;
import com.destroystokyo.paper.inventory.meta.ArmorStandMeta;
import java.util.function.BiFunction;
import net.minecraft.world.item.BannerItem;
import net.minecraft.world.item.BedItem;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.BundleItem;
import net.minecraft.world.item.Item;
@@ -247,7 +248,8 @@ public final class CraftItemMetas {
|| itemType == ItemType.SUSPICIOUS_GRAVEL || itemType == ItemType.CRAFTER
|| itemType == ItemType.TRIAL_SPAWNER || itemType == ItemType.VAULT
|| itemType == ItemType.CREAKING_HEART || itemType == ItemType.TEST_BLOCK
|| itemType == ItemType.TEST_INSTANCE_BLOCK) {
|| itemType == ItemType.TEST_INSTANCE_BLOCK || itemHandle instanceof BedItem
|| itemType == ItemType.CONDUIT) {
return CraftItemMetas.asType(CraftItemMetas.BLOCK_STATE_META_DATA);
}
if (itemType == ItemType.SHIELD) {

View File

@@ -17,8 +17,10 @@ import net.minecraft.core.component.TypedDataComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
@@ -144,12 +146,17 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
final BlockVector legacyPosition = SerializableMeta.getObject(BlockVector.class, map, "blockPosition", true);
if (legacyPosition != null) {
this.blockEntityTag = this.blockEntityTag.update(blockEntityTag -> {
if (blockEntityTag.isEmpty()) {
BlockEntity.addEntityType(blockEntityTag, java.util.Objects.requireNonNull(CraftBlockStates.getBlockEntityType(this.materialForBlockEntityType())));
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "blockEntityTag", LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWrappingWithContext(problemReporter, CraftRegistry.getMinecraftRegistry(), blockEntityTag);
if (blockEntityTag.isEmpty()) {
BlockEntity.addEntityType(output, java.util.Objects.requireNonNull(CraftBlockStates.getBlockEntityType(this.materialForBlockEntityType())));
}
output.putInt("x", legacyPosition.getBlockX());
output.putInt("y", legacyPosition.getBlockY());
output.putInt("z", legacyPosition.getBlockZ());
}
blockEntityTag.putInt("x", legacyPosition.getBlockX());
blockEntityTag.putInt("y", legacyPosition.getBlockY());
blockEntityTag.putInt("z", legacyPosition.getBlockZ());
});
}
// Paper end - general item meta fixes - parse spigot legacy position and merge into block entity tag
@@ -164,7 +171,14 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
final CompoundTag nbt = this.blockEntityTag.copyTag();
if (!nbt.isEmpty()) {
if (nbt.getString("id").isEmpty()) {
BlockEntity.addEntityType(nbt, java.util.Objects.requireNonNull(CraftBlockStates.getBlockEntityType(this.materialForBlockEntityType())));
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "CraftMetaBlockState#apply", LOGGER
)) {
BlockEntity.addEntityType(
TagValueOutput.createWrappingWithContext(problemReporter, CraftRegistry.getMinecraftRegistry(), nbt),
java.util.Objects.requireNonNull(CraftBlockStates.getBlockEntityType(this.materialForBlockEntityType()))
);
}
}
tag.put(CraftMetaBlockState.BLOCK_ENTITY_TAG, CustomData.of(nbt));
}

View File

@@ -274,7 +274,6 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta {
return page > 0 && page <= this.getPageCount();
}
// TODO Expose this attribute in Bukkit?
public boolean isResolved() {
return this.resolved;
}

View File

@@ -11,6 +11,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.DynamicOps;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -37,8 +38,6 @@ import java.util.Optional;
import java.util.SequencedSet;
import java.util.Set;
import java.util.StringJoiner;
import java.util.logging.Level;
import java.util.logging.Logger;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -131,6 +130,7 @@ import org.bukkit.inventory.meta.components.UseCooldownComponent;
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.tag.DamageTypeTags;
import org.slf4j.Logger;
/**
* Children must include the following:
@@ -158,6 +158,8 @@ import org.bukkit.tag.DamageTypeTags;
// Important: ItemMeta needs to be the first interface see #applicableTo(Material)
class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
static final Logger LOGGER = LogUtils.getLogger();
static class ItemMetaKey {
@Retention(RetentionPolicy.SOURCE)
@@ -750,7 +752,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
CompoundTag internalTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap());
this.deserializeInternal(internalTag, map);
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to read internal tag from object", ex);
}
}
@@ -779,7 +781,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
}
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to read unhandled tag for item", ex);
}
}
@@ -809,7 +811,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
try {
this.customTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap());
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to read custom tag for item", ex);
}
}
}
@@ -2238,7 +2240,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
NbtIo.writeCompressed(internal, buf);
builder.put("internal", Base64.getEncoder().encodeToString(buf.toByteArray()));
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to write internal tag for item", ex);
}
}
@@ -2258,7 +2260,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
NbtIo.writeCompressed((CompoundTag) unhandled, buf);
builder.put("unhandled", Base64.getEncoder().encodeToString(buf.toByteArray()));
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to write unhandled tag for item", ex);
}
}
@@ -2293,7 +2295,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
NbtIo.writeCompressed(this.customTag, buf);
builder.put("custom", Base64.getEncoder().encodeToString(buf.toByteArray()));
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
LOGGER.error("Failed to write custom tag for item", ex);
}
}

View File

@@ -323,11 +323,11 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@Override
@NotNull
public Color computeEffectiveColor() {
if (hasColor()) return getColor();
if (this.hasColor()) return this.getColor();
return Color.fromRGB(
PotionContents.getColorOptional(Collections2.transform(getAllEffects(), CraftPotionUtil::fromBukkit))
.orElse(PotionContents.BASE_POTION_COLOR) & 0xFFFFFF
.orElse(PotionContents.BASE_POTION_COLOR) & 0x00FFFFFF
);
}

View File

@@ -8,6 +8,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
@@ -74,7 +75,8 @@ public final class CraftEquippableComponent implements EquippableComponent {
(dispensable != null) ? dispensable : true,
(swappable != null) ? swappable : true,
(damageOnHurt != null) ? damageOnHurt : true,
(equipOnInteract != null) ? equipOnInteract : false
(equipOnInteract != null) ? equipOnInteract : false,
false, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvents.SHEARS_SNIP) // TODO - 1.21.6
);
}
@@ -115,7 +117,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setSlot(EquipmentSlot slot) {
this.handle = new Equippable(CraftEquipmentSlot.getNMS(slot), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(CraftEquipmentSlot.getNMS(slot), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -125,7 +127,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setEquipSound(Sound sound) {
this.handle = new Equippable(this.handle.slot(), (sound != null) ? CraftSound.bukkitToMinecraftHolder(sound) : SoundEvents.ARMOR_EQUIP_GENERIC, this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), (sound != null) ? CraftSound.bukkitToMinecraftHolder(sound) : SoundEvents.ARMOR_EQUIP_GENERIC, this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -135,7 +137,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setModel(NamespacedKey key) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft).map((k) -> ResourceKey.create(EquipmentAssets.ROOT_ID, k)), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft).map((k) -> ResourceKey.create(EquipmentAssets.ROOT_ID, k)), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -145,7 +147,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setCameraOverlay(NamespacedKey key) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -157,7 +159,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
public void setAllowedEntities(EntityType entities) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(),
(entities != null) ? Optional.of(HolderSet.direct(CraftEntityType.bukkitToMinecraftHolder(entities))) : Optional.empty(),
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract()
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound()
);
}
@@ -165,7 +167,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
public void setAllowedEntities(Collection<EntityType> entities) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(),
(entities != null) ? Optional.of(HolderSet.direct(entities.stream().map(CraftEntityType::bukkitToMinecraftHolder).collect(Collectors.toList()))) : Optional.empty(),
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract()
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound()
);
}
@@ -175,7 +177,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(),
(tag != null) ? Optional.of(((CraftEntityTag) tag).getHandle()) : Optional.empty(),
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract()
this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound()
);
}
@@ -186,7 +188,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setDispensable(boolean dispensable) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), dispensable, this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), dispensable, this.handle.swappable(), this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -196,7 +198,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setSwappable(boolean swappable) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), swappable, this.handle.damageOnHurt(), this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), swappable, this.handle.damageOnHurt(), this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -206,7 +208,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setDamageOnHurt(boolean damage) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), damage, this.handle.equipOnInteract());
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), damage, this.handle.equipOnInteract(), this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override
@@ -216,7 +218,7 @@ public final class CraftEquippableComponent implements EquippableComponent {
@Override
public void setEquipOnInteract(final boolean equip) {
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), equip);
this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt(), equip, this.handle.canBeSheared(), this.handle.shearingSound());
}
@Override

View File

@@ -15,7 +15,7 @@ public class CraftPotionUtil {
private static final BiMap<PotionType, PotionType> upgradeable = ImmutableBiMap.<PotionType, PotionType>builder()
// Start generate - CraftPotionUtil#upgradeable
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
.put(PotionType.HARMING, PotionType.STRONG_HARMING)
.put(PotionType.HEALING, PotionType.STRONG_HEALING)
.put(PotionType.LEAPING, PotionType.STRONG_LEAPING)
@@ -29,7 +29,7 @@ public class CraftPotionUtil {
.build();
private static final BiMap<PotionType, PotionType> extendable = ImmutableBiMap.<PotionType, PotionType>builder()
// Start generate - CraftPotionUtil#extendable
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
.put(PotionType.FIRE_RESISTANCE, PotionType.LONG_FIRE_RESISTANCE)
.put(PotionType.INVISIBILITY, PotionType.LONG_INVISIBILITY)
.put(PotionType.LEAPING, PotionType.LONG_LEAPING)

View File

@@ -2,29 +2,39 @@ package org.bukkit.craftbukkit.spawner;
import com.google.common.base.Preconditions;
import java.util.Optional;
import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.BaseSpawner;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.SpawnData;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.bukkit.spawner.Spawner;
import org.slf4j.Logger;
/**
* A common parent interface for both the {@link org.bukkit.craftbukkit.block.CraftCreatureSpawner} and minecart mob spawner.
*/
public interface PaperSharedSpawnerLogic extends Spawner {
static final Logger LOGGER = LogUtils.getLogger();
BaseSpawner getSpawner();
Level getInternalWorld();
BlockPos getInternalPosition();
default boolean isActivated() {
return this.getSpawner().isNearPlayer(this.getInternalWorld(), this.getInternalPosition());
}
@@ -41,16 +51,20 @@ public interface PaperSharedSpawnerLogic extends Spawner {
Preconditions.checkArgument(itemStack != null && !itemStack.getType().isAir(), "spawners cannot spawn air");
final net.minecraft.world.item.ItemStack item = CraftItemStack.asNMSCopy(itemStack);
final CompoundTag entity = new CompoundTag();
entity.putString(Entity.ID_TAG, BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ITEM).toString());
entity.put("Item", item.save(this.getInternalWorld().registryAccess()));
this.setNextSpawnData(
new net.minecraft.world.level.SpawnData(
entity,
java.util.Optional.empty(),
Optional.ofNullable(this.getSpawner().nextSpawnData).flatMap(SpawnData::equipment)
)
);
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> getSpawner().toString(), LOGGER)) {
TagValueOutput tagValueOutput = TagValueOutput.createWithContext(scopedCollector, this.getInternalWorld().registryAccess());
tagValueOutput.putString(Entity.TAG_ID, BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ITEM).toString());
tagValueOutput.store("Item", net.minecraft.world.item.ItemStack.CODEC, item);
this.setNextSpawnData(
new net.minecraft.world.level.SpawnData(
tagValueOutput.buildResult(),
java.util.Optional.empty(),
Optional.ofNullable(this.getSpawner().nextSpawnData).flatMap(SpawnData::equipment)
)
);
}
}
}

View File

@@ -7,8 +7,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
@@ -19,6 +21,7 @@ import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockRotProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.RegionAccessor;
@@ -39,9 +42,12 @@ import org.bukkit.structure.Structure;
import org.bukkit.util.BlockTransformer;
import org.bukkit.util.BlockVector;
import org.bukkit.util.EntityTransformer;
import org.slf4j.Logger;
public class CraftStructure implements Structure {
private static final Logger LOGGER = LogUtils.getLogger();
private final StructureTemplate structure;
private final RegistryAccess registry;
@@ -121,7 +127,7 @@ public class CraftStructure implements Structure {
Preconditions.checkArgument(size != null, "BlockVector size cannot be null");
Preconditions.checkArgument(size.getBlockX() >= 1 && size.getBlockY() >= 1 && size.getBlockZ() >= 1, "Size must be at least 1x1x1 but was %sx%sx%s", size.getBlockX(), size.getBlockY(), size.getBlockZ());
this.structure.fillFromWorld(((CraftWorld) world).getHandle(), CraftLocation.toBlockPosition(origin), CraftBlockVector.toBlockPosition(size), includeEntities, Blocks.STRUCTURE_VOID);
this.structure.fillFromWorld(((CraftWorld) world).getHandle(), CraftLocation.toBlockPosition(origin), CraftBlockVector.toBlockPosition(size), includeEntities, List.of(Blocks.STRUCTURE_VOID));
}
@Override
@@ -133,10 +139,18 @@ public class CraftStructure implements Structure {
public List<Entity> getEntities() {
List<Entity> entities = new ArrayList<>();
for (StructureTemplate.StructureEntityInfo entity : this.structure.entityInfoList) {
EntityType.create(entity.nbt, ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(), EntitySpawnReason.STRUCTURE).ifPresent(dummyEntity -> {
dummyEntity.setPos(entity.pos.x, entity.pos.y, entity.pos.z);
entities.add(dummyEntity.getBukkitEntity());
});
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "entity@" + entity.pos, LOGGER
)) {
EntityType.create(
TagValueInput.createGlobal(problemReporter, entity.nbt),
((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(),
EntitySpawnReason.STRUCTURE
).ifPresent(dummyEntity -> {
dummyEntity.setPos(entity.pos.x, entity.pos.y, entity.pos.z);
entities.add(dummyEntity.getBukkitEntity());
});
}
}
return Collections.unmodifiableList(entities);
}

View File

@@ -17,7 +17,7 @@ public final class ApiVersion implements Comparable<ApiVersion>, Serializable {
static {
versions = new HashMap<>();
CURRENT = getOrCreateVersion("1.21.5");
CURRENT = getOrCreateVersion("1.21.6");
FLATTENING = getOrCreateVersion("1.13");
FIELD_NAME_PARITY = getOrCreateVersion("1.20.5");
ABSTRACT_COW = getOrCreateVersion("1.21.5");

View File

@@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -11,6 +10,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -18,84 +18,86 @@ import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.storage.LevelData;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.craftbukkit.block.CraftBlockEntityState;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.CraftBlockStates;
public class BlockStateListPopulator extends DummyGeneratorAccess {
private final LevelAccessor world;
private final Map<BlockPos, net.minecraft.world.level.block.state.BlockState> dataMap = new HashMap<>();
private final Map<BlockPos, BlockEntity> entityMap = new HashMap<>();
private final LinkedHashMap<BlockPos, CraftBlockState> blocks;
public BlockStateListPopulator(LevelAccessor world) {
this(world, new LinkedHashMap<>());
}
private final LevelAccessor level;
private final Map<BlockPos, CapturedBlock> blocks = new LinkedHashMap<>();
private BlockStateListPopulator(LevelAccessor world, LinkedHashMap<BlockPos, CraftBlockState> blocks) {
this.world = world;
this.blocks = blocks;
private List<CraftBlockState> snapshots;
public BlockStateListPopulator(LevelAccessor level) {
this.level = level;
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(BlockPos pos) {
net.minecraft.world.level.block.state.BlockState state = this.dataMap.get(pos);
return (state != null) ? state : this.world.getBlockState(pos);
CapturedBlock block = this.blocks.get(pos);
return block != null ? block.state() : this.level.getBlockState(pos);
}
@Override
public FluidState getFluidState(BlockPos pos) {
net.minecraft.world.level.block.state.BlockState state = this.dataMap.get(pos);
return (state != null) ? state.getFluidState() : this.world.getFluidState(pos);
CapturedBlock block = this.blocks.get(pos);
return block != null ? block.state().getFluidState() : this.level.getFluidState(pos);
}
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
// The contains is important to check for null values
if (this.entityMap.containsKey(pos)) {
return this.entityMap.get(pos);
}
return this.world.getBlockEntity(pos);
CapturedBlock block = this.blocks.get(pos);
return block != null ? block.blockEntity() : this.level.getBlockEntity(pos);
}
@Override
public boolean setBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState state, int flags, int recursionLeft) {
pos = pos.immutable();
// remove first to keep insertion order
// remove first to keep last updated order
this.blocks.remove(pos);
this.dataMap.put(pos, state);
if (state.hasBlockEntity()) {
this.entityMap.put(pos, ((EntityBlock) state.getBlock()).newBlockEntity(pos, state));
final BlockEntity newBlockEntity;
if (state.getBlock() instanceof EntityBlock entityBlock) {
// based on LevelChunk#setBlockState
BlockEntity currentBlockEntity = this.getBlockEntity(pos);
if (currentBlockEntity != null && currentBlockEntity.isValidBlockState(state)) {
newBlockEntity = currentBlockEntity; // previous block entity is still valid for this block state
currentBlockEntity.setBlockState(state);
} else {
newBlockEntity = entityBlock.newBlockEntity(pos, state); // create a new one when the block change
}
} else {
this.entityMap.put(pos, null);
newBlockEntity = null;
}
// use 'this' to ensure that the block state is the correct TileState
CraftBlockState snapshot = (CraftBlockState) CraftBlock.at(this, pos).getState();
snapshot.setFlags(flags);
// set world handle to ensure that updated calls are done to the world and not to this populator
snapshot.setWorldHandle(this.world);
this.blocks.put(pos, snapshot);
this.blocks.put(pos, new CapturedBlock(state, flags, newBlockEntity));
return true;
}
@Override
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft) {
net.minecraft.world.level.block.state.BlockState blockState = this.getBlockState(pos);
if (blockState.isAir()) {
return false;
}
this.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3, recursionLeft); // capture block without the event
return true;
}
@Override
public ServerLevel getMinecraftWorld() {
return this.world.getMinecraftWorld();
return this.level.getMinecraftWorld();
}
@Override
public ServerLevel getLevel() {
return this.getMinecraftWorld();
}
public void refreshTiles() {
for (CraftBlockState snapshot : this.blocks.values()) {
if (snapshot instanceof CraftBlockEntityState) {
((CraftBlockEntityState<?>) snapshot).refreshSnapshot();
}
private void iterateSnapshots(Consumer<CraftBlockState> callback) {
for (Map.Entry<BlockPos, CapturedBlock> entry : this.blocks.entrySet()) {
CapturedBlock block = entry.getValue();
CraftBlockState snapshot = CraftBlockStates.getBlockState(
this.getMinecraftWorld().getWorld(), entry.getKey(), block.state(), block.blockEntity()
);
snapshot.setFlags(block.flags());
callback.accept(snapshot);
}
}
@@ -112,27 +114,38 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
}
public void placeSomeBlocks(Consumer<? super CraftBlockState> beforeRun, Predicate<? super BlockState> filter) {
for (CraftBlockState state : this.blocks.values()) {
if (filter.test(state)) {
beforeRun.accept(state);
state.place(state.getFlags());
for (CraftBlockState snapshot : this.getSnapshotBlocks()) {
if (filter.test(snapshot)) {
beforeRun.accept(snapshot);
snapshot.place(snapshot.getFlags());
}
}
}
public List<CraftBlockState> getSnapshotBlocks() {
return new ArrayList<>(this.blocks.values());
if (this.snapshots == null) {
List<CraftBlockState> snapshots = new ArrayList<>();
this.iterateSnapshots(snapshots::add);
this.snapshots = snapshots;
}
return snapshots;
}
// For tree generation
@Override
public ServerLevel getLevel() {
return this.getMinecraftWorld();
}
@Override
public int getMinY() {
return this.world.getMinY();
return this.level.getMinY();
}
@Override
public int getHeight() {
return this.world.getHeight();
return this.level.getHeight();
}
@Override
@@ -147,29 +160,29 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
@Override
public DimensionType dimensionType() {
return this.world.dimensionType();
return this.level.dimensionType();
}
@Override
public RegistryAccess registryAccess() {
return this.world.registryAccess();
return this.level.registryAccess();
}
// Needed when a tree generates in water
@Override
public LevelData getLevelData() {
return this.world.getLevelData();
return this.level.getLevelData();
}
@Override
public long nextSubTickCount() {
return this.world.nextSubTickCount();
return this.level.nextSubTickCount();
}
// SPIGOT-7966: Needed for some tree generations
@Override
public RandomSource getRandom() {
return this.world.getRandom();
return this.level.getRandom();
}
@Override
@@ -179,22 +192,22 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
}
@Override
public BlockPos getHeightmapPos(net.minecraft.world.level.levelgen.Heightmap.Types heightmap, BlockPos pos) {
return this.world.getHeightmapPos(heightmap, pos);
public BlockPos getHeightmapPos(net.minecraft.world.level.levelgen.Heightmap.Types heightmapType, BlockPos pos) {
return this.level.getHeightmapPos(heightmapType, pos);
}
@Override
public int getHeight(net.minecraft.world.level.levelgen.Heightmap.Types heightmap, int x, int z) {
return this.world.getHeight(heightmap, x, z);
public int getHeight(net.minecraft.world.level.levelgen.Heightmap.Types heightmapType, int x, int z) {
return this.level.getHeight(heightmapType, x, z);
}
@Override
public int getRawBrightness(BlockPos pos, int amount) {
return this.world.getRawBrightness(pos, amount);
return this.level.getRawBrightness(pos, amount);
}
@Override
public int getBrightness(net.minecraft.world.level.LightLayer lightLayer, BlockPos pos) {
return this.world.getBrightness(lightLayer, pos);
public int getBrightness(net.minecraft.world.level.LightLayer lightType, BlockPos pos) {
return this.level.getBrightness(lightType, pos);
}
}

View File

@@ -0,0 +1,10 @@
package org.bukkit.craftbukkit.util;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public record CapturedBlock(BlockState state, int flags, @Nullable BlockEntity blockEntity) {
}

View File

@@ -2,6 +2,9 @@ package org.bukkit.craftbukkit.util;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import java.net.URI;
import java.util.ArrayList;
@@ -11,6 +14,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.mojang.serialization.JsonOps;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ChatVersion;
import net.md_5.bungee.chat.VersionedComponentSerializer;
@@ -18,6 +22,7 @@ import com.mojang.serialization.JavaOps;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
@@ -28,6 +33,7 @@ import org.bukkit.craftbukkit.CraftRegistry;
public final class CraftChatMessage {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
private static final Map<Character, ChatFormatting> formatMap;
static {
@@ -223,7 +229,11 @@ public final class CraftChatMessage {
}
public static String toJSON(Component component) {
return Component.Serializer.toJson(component, CraftRegistry.getMinecraftRegistry());
return GSON.toJson(
ComponentSerialization.CODEC
.encodeStart(CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), component)
.getOrThrow(JsonParseException::new)
);
}
public static String toJSONOrNull(Component component) {
@@ -234,7 +244,10 @@ public final class CraftChatMessage {
public static Component fromJSON(String jsonMessage) throws JsonParseException {
// Note: This also parses plain Strings to text components.
// Note: An empty message (empty, or only consisting of whitespace) results in null rather than a parse exception.
return Component.Serializer.fromJson(jsonMessage, CraftRegistry.getMinecraftRegistry());
final JsonElement jsonElement = GSON.fromJson(jsonMessage, JsonElement.class);
return jsonElement == null ? null : ComponentSerialization.CODEC.parse(
CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), jsonElement
).getOrThrow(JsonParseException::new);
}
public static Component fromJSONOrNull(String jsonMessage) {

View File

@@ -4,12 +4,12 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
import com.google.common.base.Preconditions;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.JsonOps;
import io.papermc.paper.registry.RegistryKey;
@@ -41,7 +41,7 @@ import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.datafix.fixes.References;
import net.minecraft.world.entity.player.Player;
@@ -50,6 +50,8 @@ import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Material;
@@ -82,9 +84,13 @@ import org.bukkit.material.MaterialData;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.potion.PotionType;
import org.slf4j.Logger;
@SuppressWarnings("deprecation")
public final class CraftMagicNumbers implements UnsafeValues {
private static final Logger LOGGER = LogUtils.getLogger();
public static final CraftMagicNumbers INSTANCE = new CraftMagicNumbers();
public static final boolean DISABLE_OLD_API_SUPPORT = Boolean.getBoolean("paper.disableOldApiSupport"); // Paper
@@ -260,27 +266,17 @@ public final class CraftMagicNumbers implements UnsafeValues {
}
/**
* This string should be changed if the NMS mappings do.
*
* It has no meaning and should only be used as an equality check. Plugins
* which are sensitive to the NMS mappings may read it and refuse to load if
* it cannot be found or is different to the expected value.
*
* Remember: NMS is not supported API and may break at any time for any
* reason irrespective of this. There is often supported API to do the same
* thing as many common NMS usages. If not, you are encouraged to open a
* feature and/or pull request for consideration, or use a well abstracted
* third-party API such as ProtocolLib.
*
* @return string
* @deprecated in favor of {@link io.papermc.paper.ServerBuildInfo#minecraftVersionId()}
* Paper has used Mojang mappings since 1.20.5, and this method no longer returns a useful value.
*/
@Deprecated(forRemoval = true, since = "1.21.6")
public String getMappingsVersion() {
return "7ecad754373a5fbc43d381d7450c53a5";
throw new UnsupportedOperationException("Use ServerBuildInfo#minecraftVersionId instead.");
}
@Override
public int getDataVersion() {
return SharedConstants.getCurrentVersion().getDataVersion().getVersion();
return SharedConstants.getCurrentVersion().dataVersion().version();
}
@Override
@@ -491,9 +487,14 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override
public byte[] serializeItem(ItemStack item) {
Preconditions.checkNotNull(item, "null cannot be serialized");
Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized");
Preconditions.checkArgument(!item.isEmpty(), "Empty itemstack cannot be serialized");
return serializeNbtToBytes((CompoundTag) (item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(MinecraftServer.getServer().registryAccess()));
return serializeNbtToBytes(
(CompoundTag) net.minecraft.world.item.ItemStack.CODEC.encodeStart(
MinecraftServer.getServer().registryAccess().createSerializationContext(NbtOps.INSTANCE),
CraftItemStack.unwrap(item)
).getOrThrow()
);
}
@Override
@@ -511,7 +512,9 @@ public final class CraftMagicNumbers implements UnsafeValues {
if (compound.getStringOr("id", "minecraft:air").equals("minecraft:air")) {
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.EMPTY);
}
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(CraftRegistry.getMinecraftRegistry(), compound).orElseThrow());
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.CODEC.parse(
CraftRegistry.getMinecraftRegistry().createSerializationContext(NbtOps.INSTANCE), compound
).getOrThrow());
}
@Override
@@ -519,7 +522,10 @@ public final class CraftMagicNumbers implements UnsafeValues {
if (itemStack.isEmpty()) {
return Map.of("id", "minecraft:air", SharedConstants.DATA_VERSION_TAG, this.getDataVersion(), "schema_version", 1);
}
final CompoundTag tag = CraftItemStack.asNMSCopy(itemStack).save(CraftRegistry.getMinecraftRegistry()).asCompound().orElseThrow();
final CompoundTag tag = (CompoundTag) net.minecraft.world.item.ItemStack.CODEC.encodeStart(
CraftRegistry.getMinecraftRegistry().createSerializationContext(NbtOps.INSTANCE),
CraftItemStack.asNMSCopy(itemStack)
).getOrThrow();
NbtUtils.addCurrentDataVersion(tag);
final Map<String, Object> ret = new LinkedHashMap<>();
@@ -677,21 +683,25 @@ public final class CraftMagicNumbers implements UnsafeValues {
}
});
CompoundTag compound = new CompoundTag();
if (serializePassangers) {
if (!nmsEntity.saveAsPassenger(compound, true, includeNonSaveable, forceSerialization)) {
throw new IllegalArgumentException("Couldn't serialize entity");
}
} else {
List<net.minecraft.world.entity.Entity> pass = new ArrayList<>(nmsEntity.getPassengers());
nmsEntity.passengers = com.google.common.collect.ImmutableList.of();
boolean serialized = nmsEntity.saveAsPassenger(compound, true, includeNonSaveable, forceSerialization);
nmsEntity.passengers = com.google.common.collect.ImmutableList.copyOf(pass);
if (!serialized) {
throw new IllegalArgumentException("Couldn't serialize entity");
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "serialiseEntity@" + entity.getUniqueId(), LOGGER
)) {
final TagValueOutput output = TagValueOutput.createWithContext(problemReporter, nmsEntity.registryAccess());
if (serializePassangers) {
if (!nmsEntity.saveAsPassenger(output, true, includeNonSaveable, forceSerialization)) {
throw new IllegalArgumentException("Couldn't serialize entity");
}
} else {
List<net.minecraft.world.entity.Entity> pass = new ArrayList<>(nmsEntity.getPassengers());
nmsEntity.passengers = com.google.common.collect.ImmutableList.of();
boolean serialized = nmsEntity.saveAsPassenger(output, true, includeNonSaveable, forceSerialization);
nmsEntity.passengers = com.google.common.collect.ImmutableList.copyOf(pass);
if (!serialized) {
throw new IllegalArgumentException("Couldn't serialize entity");
}
}
return serializeNbtToBytes(output.buildResult());
}
return serializeNbtToBytes(compound);
}
@Override
@@ -714,8 +724,18 @@ public final class CraftMagicNumbers implements UnsafeValues {
// Generate a new UUID, so we don't have to worry about deserializing the same entity twice
compound.remove("UUID");
}
net.minecraft.world.entity.Entity nmsEntity = net.minecraft.world.entity.EntityType.create(compound, world, net.minecraft.world.entity.EntitySpawnReason.LOAD)
.orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?"));
final net.minecraft.world.entity.Entity nmsEntity;
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "deserialiseEntity", LOGGER
)) {
nmsEntity = net.minecraft.world.entity.EntityType.create(
TagValueInput.create(problemReporter, world.registryAccess(), compound),
world,
net.minecraft.world.entity.EntitySpawnReason.LOAD
).orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?"));
}
compound.getList("Passengers").ifPresent(passengers -> {
for (final Tag tag : passengers) {
if (!(tag instanceof final CompoundTag serializedPassenger)) {
@@ -768,7 +788,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override
public int getProtocolVersion() {
return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion();
return net.minecraft.SharedConstants.getCurrentVersion().protocolVersion();
}
@Override

View File

@@ -1,20 +1,26 @@
package org.bukkit.craftbukkit.util;
import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.storage.TagValueInput;
import org.bukkit.craftbukkit.block.CraftBlockEntityState;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.CraftBlockStates;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class TransformerGeneratorAccess extends DelegatedGeneratorAccess {
private static final Logger LOGGER = LogUtils.getLogger();
private CraftStructureTransformer structureTransformer;
public void setStructureTransformer(CraftStructureTransformer structureTransformer) {
@@ -60,7 +66,13 @@ public class TransformerGeneratorAccess extends DelegatedGeneratorAccess {
}
BlockEntity blockEntity = this.getBlockEntity(position);
if (blockEntity != null && craftBlockState instanceof CraftBlockEntityState<?> craftEntityState) {
blockEntity.loadWithComponents(craftEntityState.getSnapshotNBT(), this.registryAccess());
try (final ProblemReporter.ScopedCollector problemReporter = new ProblemReporter.ScopedCollector(
() -> "TransformerGeneratorAccess@" + position.toShortString(), LOGGER
)) {
blockEntity.loadWithComponents(TagValueInput.create(
problemReporter, this.registryAccess(), craftEntityState.getSnapshotNBT()
));
}
}
return result;
}

View File

@@ -31,8 +31,8 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands);
// Paper start
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to the ban list", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to the ban list", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display the ban list", PermissionDefault.OP, commands);
@@ -44,6 +44,7 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "dialog", "Allows the user to show dialogs", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands);
@@ -52,6 +53,7 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "jfr", "Allows a user to use the vanilla Java FlightRecorder profiling system", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands);
@@ -60,11 +62,14 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon-ip", "Allows the user to remove entries from the ip address ban list", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "perf", "Allows the user to start/stop the vanilla performance metrics capture", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "place", "Allows the user to place features and structures", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ride", "Allows the user to use the /ride command to control passengers", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "random", "Allows the user to generate a random number", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "return", "Allows the user to use the /return command", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ride", "Allows the user to use the /ride command to control passengers", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "rotate", "Allows the user to change the rotation of entities", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands);
@@ -83,17 +88,15 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); // defaults to all players
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "test", "Allows the user to manage and execute GameTests", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tick", "Allows the user to control the tick rate of the server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "transfer", "Allows the user to transfer to another server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "version", "Shows info related to the server version", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "waypoint", "Allows the managment of a waypoints on the server/locator bar", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "place", "Allows the user to place features and structures", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "return", "Allows the user to use the /return command", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "random", "Allows the user to generate a random number", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "rotate", "Allows the user to change the rotation of entities", PermissionDefault.OP, commands);
// Paper end
DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands);