Update to Minecraft 1.20.5

By: md_5 <git@md-5.net>
This commit is contained in:
CraftBukkit/Spigot
2024-04-24 01:15:00 +10:00
parent 4deda9501f
commit 65bc2541a3
524 changed files with 7788 additions and 6181 deletions

View File

@@ -25,12 +25,12 @@ import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.chunk.ChunkSection;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.DataPaletteBlock;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.chunk.NibbleArray;
import net.minecraft.world.level.chunk.PalettedContainerRO;
import net.minecraft.world.level.chunk.ProtoChunkExtension;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.storage.ChunkRegionLoader;
import net.minecraft.world.level.chunk.storage.EntityStorage;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
@@ -315,8 +315,8 @@ public class CraftChunk implements Chunk {
for (int i = 0; i < cs.length; i++) {
NBTTagCompound data = new NBTTagCompound();
data.put("block_states", ChunkRegionLoader.BLOCK_STATE_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, cs[i].getStates()).get().left().get());
sectionBlockIDs[i] = ChunkRegionLoader.BLOCK_STATE_CODEC.parse(DynamicOpsNBT.INSTANCE, data.getCompound("block_states")).get().left().get();
data.put("block_states", ChunkRegionLoader.BLOCK_STATE_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, cs[i].getStates()).getOrThrow());
sectionBlockIDs[i] = ChunkRegionLoader.BLOCK_STATE_CODEC.parse(DynamicOpsNBT.INSTANCE, data.getCompound("block_states")).getOrThrow(ChunkRegionLoader.a::new);
LevelLightEngine lightengine = worldServer.getLightEngine();
NibbleArray skyLightArray = lightengine.getLayerListener(EnumSkyBlock.SKY).getDataLayerData(SectionPosition.of(x, chunk.getSectionYFromSectionIndex(i), z)); // SPIGOT-7498: Convert section index
@@ -335,8 +335,8 @@ public class CraftChunk implements Chunk {
}
if (biome != null) {
data.put("biomes", biomeCodec.encodeStart(DynamicOpsNBT.INSTANCE, cs[i].getBiomes()).get().left().get());
biome[i] = biomeCodec.parse(DynamicOpsNBT.INSTANCE, data.getCompound("biomes")).get().left().get();
data.put("biomes", biomeCodec.encodeStart(DynamicOpsNBT.INSTANCE, cs[i].getBiomes()).getOrThrow());
biome[i] = biomeCodec.parse(DynamicOpsNBT.INSTANCE, data.getCompound("biomes")).getOrThrow(ChunkRegionLoader.a::new);
}
}
@@ -415,7 +415,7 @@ public class CraftChunk implements Chunk {
empty[i] = true;
if (biome != null) {
biome[i] = (DataPaletteBlock<Holder<BiomeBase>>) biomeCodec.parse(DynamicOpsNBT.INSTANCE, biomeCodec.encodeStart(DynamicOpsNBT.INSTANCE, actual.getSection(i).getBiomes()).get().left().get()).get().left().get();
biome[i] = (DataPaletteBlock<Holder<BiomeBase>>) biomeCodec.parse(DynamicOpsNBT.INSTANCE, biomeCodec.encodeStart(DynamicOpsNBT.INSTANCE, actual.getSection(i).getBiomes()).getOrThrow()).getOrThrow(ChunkRegionLoader.a::new);
}
}

View File

@@ -10,7 +10,6 @@ import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.potion.Potion;
public class CraftEffect {
public static <T> int getDataValue(Effect effect, T data) {
@@ -20,8 +19,6 @@ public class CraftEffect {
datavalue = (Integer) data;
break;
case POTION_BREAK:
datavalue = ((Potion) data).toDamageValue() & 0x3F;
break;
case INSTANT_POTION_BREAK:
datavalue = ((Color) data).asRGB();
break;

View File

@@ -1,7 +1,9 @@
package org.bukkit.craftbukkit;
import java.util.Locale;
import net.minecraft.world.EnumHand;
import net.minecraft.world.entity.EnumItemSlot;
import net.minecraft.world.entity.EquipmentSlotGroup;
import org.bukkit.inventory.EquipmentSlot;
public class CraftEquipmentSlot {
@@ -16,6 +18,7 @@ public class CraftEquipmentSlot {
set(EquipmentSlot.LEGS, EnumItemSlot.LEGS);
set(EquipmentSlot.CHEST, EnumItemSlot.CHEST);
set(EquipmentSlot.HEAD, EnumItemSlot.HEAD);
set(EquipmentSlot.BODY, EnumItemSlot.BODY);
}
private static void set(EquipmentSlot type, EnumItemSlot value) {
@@ -27,10 +30,18 @@ public class CraftEquipmentSlot {
return enums[nms.ordinal()];
}
public static org.bukkit.inventory.EquipmentSlotGroup getSlot(EquipmentSlotGroup nms) {
return org.bukkit.inventory.EquipmentSlotGroup.getByName(nms.getSerializedName());
}
public static EnumItemSlot getNMS(EquipmentSlot slot) {
return slots[slot.ordinal()];
}
public static EquipmentSlotGroup getNMSGroup(org.bukkit.inventory.EquipmentSlotGroup slot) {
return EquipmentSlotGroup.valueOf(slot.toString().toUpperCase(Locale.ROOT));
}
public static EquipmentSlot getHand(EnumHand enumhand) {
return (enumhand == EnumHand.MAIN_HAND) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND;
}

View File

@@ -5,6 +5,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.IInventory;
import net.minecraft.world.entity.Entity;
@@ -16,6 +19,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameter;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSet;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameters;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.entity.CraftEntity;
@@ -23,12 +27,33 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
public class CraftLootTable implements org.bukkit.loot.LootTable {
public static org.bukkit.loot.LootTable minecraftToBukkit(MinecraftKey minecraft) {
return (minecraft == null) ? null : Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(minecraft));
}
public static org.bukkit.loot.LootTable minecraftToBukkit(ResourceKey<LootTable> minecraft) {
return (minecraft == null) ? null : Bukkit.getLootTable(minecraftToBukkitKey(minecraft));
}
public static NamespacedKey minecraftToBukkitKey(ResourceKey<LootTable> minecraft) {
return (minecraft == null) ? null : CraftNamespacedKey.fromMinecraft(minecraft.location());
}
public static ResourceKey<LootTable> bukkitToMinecraft(org.bukkit.loot.LootTable table) {
return (table == null) ? null : bukkitKeyToMinecraft(table.getKey());
}
public static ResourceKey<LootTable> bukkitKeyToMinecraft(NamespacedKey key) {
return (key == null) ? null : ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(key));
}
private final LootTable handle;
private final NamespacedKey key;

View File

@@ -1,5 +1,8 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.Instrument;
import org.bukkit.MusicInstrument;
@@ -14,10 +17,27 @@ public class CraftMusicInstrument extends MusicInstrument implements Handleable<
return CraftRegistry.minecraftToBukkit(minecraft, Registries.INSTRUMENT, Registry.INSTRUMENT);
}
public static MusicInstrument minecraftHolderToBukkit(Holder<Instrument> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static Instrument bukkitToMinecraft(MusicInstrument bukkit) {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
public static Holder<Instrument> bukkitToMinecraftHolder(MusicInstrument bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<Instrument> registry = CraftRegistry.getMinecraftRegistry(Registries.INSTRUMENT);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<Instrument> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own instrument without properly registering it.");
}
private final NamespacedKey key;
private final Instrument handle;

View File

@@ -199,7 +199,7 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
}
private NBTTagCompound getData() {
return storage.getPlayerData(getUniqueId().toString());
return storage.load(profile.getName(), profile.getId().toString()).orElse(null);
}
private NBTTagCompound getBukkitData() {

View File

@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import net.minecraft.core.IRegistry;
import net.minecraft.core.particles.ColorParticleOption;
import net.minecraft.core.particles.DustColorTransitionOptions;
import net.minecraft.core.particles.ParticleParam;
import net.minecraft.core.particles.ParticleParamBlock;
@@ -182,6 +183,13 @@ public abstract class CraftParticle<D> implements Keyed {
}
};
BiFunction<NamespacedKey, net.minecraft.core.particles.Particle<?>, CraftParticle<?>> colorFunction = (name, particle) -> new CraftParticle<>(name, particle, Color.class) {
@Override
public ParticleParam createParticleParam(Color color) {
return ColorParticleOption.create((net.minecraft.core.particles.Particle<ColorParticleOption>) particle, color.asARGB());
}
};
add("dust", dustOptionsFunction);
add("item", itemStackFunction);
add("block", blockDataFunction);
@@ -191,6 +199,8 @@ public abstract class CraftParticle<D> implements Keyed {
add("sculk_charge", floatFunction);
add("shriek", integerFunction);
add("block_marker", blockDataFunction);
add("entity_effect", colorFunction);
add("dust_pillar", blockDataFunction);
}
private static void add(String name, BiFunction<NamespacedKey, net.minecraft.core.particles.Particle<?>, CraftParticle<?>> function) {

View File

@@ -36,14 +36,14 @@ public final class CraftRaid implements Raid {
@Override
public int getBadOmenLevel() {
return handle.badOmenLevel;
return handle.raidOmenLevel;
}
@Override
public void setBadOmenLevel(int badOmenLevel) {
int max = handle.getMaxBadOmenLevel();
int max = handle.getMaxRaidOmenLevel();
Preconditions.checkArgument(0 <= badOmenLevel && badOmenLevel <= max, "Bad Omen level must be between 0 and %s", max);
handle.badOmenLevel = badOmenLevel;
handle.raidOmenLevel = badOmenLevel;
}
@Override
@@ -73,7 +73,7 @@ public final class CraftRaid implements Raid {
@Override
public int getTotalGroups() {
return handle.numGroups + (handle.badOmenLevel > 1 ? 1 : 0);
return handle.numGroups + (handle.raidOmenLevel > 1 ? 1 : 0);
}
@Override

View File

@@ -432,7 +432,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
Preconditions.checkArgument(entity != null, "Cannot spawn null entity");
if (randomizeData && entity instanceof EntityInsentient) {
((EntityInsentient) entity).finalizeSpawn(getHandle(), getHandle().getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, null);
((EntityInsentient) entity).finalizeSpawn(getHandle(), getHandle().getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.COMMAND, (GroupDataEntity) null);
}
if (!isNormalWorld()) {

View File

@@ -6,6 +6,7 @@ import java.util.Iterator;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -85,6 +86,19 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return ((Handleable<M>) bukkit).getHandle();
}
public static <B extends Keyed, M> Holder<M> bukkitToMinecraftHolder(B bukkit, ResourceKey<IRegistry<M>> registryKey) {
Preconditions.checkArgument(bukkit != null);
IRegistry<M> registry = CraftRegistry.getMinecraftRegistry(registryKey);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<M> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own registry entry with out properly registering it.");
}
/**
* Note: Newly added registries should also be added to RegistriesArgumentProvider in the test package
*

View File

@@ -49,6 +49,7 @@ import net.minecraft.commands.CommandListenerWrapper;
import net.minecraft.commands.arguments.ArgumentEntity;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
@@ -57,6 +58,7 @@ import net.minecraft.nbt.ReportedNbtException;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ReloadableServerRegistries;
import net.minecraft.server.ServerCommand;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.bossevents.BossBattleCustom;
@@ -105,13 +107,12 @@ import net.minecraft.world.level.levelgen.MobSpawnerPhantom;
import net.minecraft.world.level.levelgen.WorldDimensions;
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.material.FluidType;
import net.minecraft.world.level.saveddata.maps.MapIcon;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import net.minecraft.world.level.storage.Convertable;
import net.minecraft.world.level.storage.LevelDataAndDimensions;
import net.minecraft.world.level.storage.WorldDataServer;
import net.minecraft.world.level.storage.WorldNBTStorage;
import net.minecraft.world.level.storage.loot.LootDataManager;
import net.minecraft.world.level.validation.ContentValidationException;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.BanList;
@@ -178,13 +179,13 @@ import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe;
import org.bukkit.craftbukkit.inventory.RecipeIterator;
import org.bukkit.craftbukkit.inventory.util.CraftInventoryCreator;
import org.bukkit.craftbukkit.map.CraftMapColorCache;
import org.bukkit.craftbukkit.map.CraftMapCursor;
import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.craftbukkit.metadata.EntityMetadataStore;
import org.bukkit.craftbukkit.metadata.PlayerMetadataStore;
import org.bukkit.craftbukkit.metadata.WorldMetadataStore;
import org.bukkit.craftbukkit.packs.CraftDataPackManager;
import org.bukkit.craftbukkit.packs.CraftResourcePack;
import org.bukkit.craftbukkit.potion.CraftPotionBrewer;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.craftbukkit.scheduler.CraftScheduler;
import org.bukkit.craftbukkit.scoreboard.CraftCriteria;
@@ -250,7 +251,6 @@ import org.bukkit.plugin.SimpleServicesManager;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.bukkit.plugin.messaging.Messenger;
import org.bukkit.plugin.messaging.StandardMessenger;
import org.bukkit.potion.Potion;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.scheduler.BukkitWorker;
import org.bukkit.scoreboard.Criteria;
@@ -316,7 +316,7 @@ public final class CraftServer implements Server {
}
}));
this.serverVersion = CraftServer.class.getPackage().getImplementationVersion();
this.structureManager = new CraftStructureManager(console.getStructureManager());
this.structureManager = new CraftStructureManager(console.getStructureManager(), console.registryAccess());
this.dataPackManager = new CraftDataPackManager(this.getServer().getPackRepository());
this.serverTickManager = new CraftServerTickManager(console.tickRateManager());
@@ -324,9 +324,6 @@ public final class CraftServer implements Server {
CraftRegistry.setMinecraftRegistry(console.registryAccess());
Potion.setPotionBrewer(new CraftPotionBrewer());
// Ugly hack :(
if (!Main.useConsole) {
getLogger().info("Console input is disabled due to --noconsole command argument");
}
@@ -1131,12 +1128,13 @@ public final class CraftServer implements Server {
WorldDataServer worlddata;
WorldLoader.a worldloader_a = console.worldLoader;
IRegistry<WorldDimension> iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
IRegistryCustom.Dimension iregistrycustom_dimension = worldloader_a.datapackDimensions();
IRegistry<WorldDimension> iregistry = iregistrycustom_dimension.registryOrThrow(Registries.LEVEL_STEM);
if (dynamic != null) {
LevelDataAndDimensions leveldataanddimensions = Convertable.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen());
worlddata = (WorldDataServer) leveldataanddimensions.worldData();
iregistry = leveldataanddimensions.dimensions().dimensions();
iregistrycustom_dimension = leveldataanddimensions.dimensions().dimensionsRegistryAccess();
} else {
WorldSettings worldsettings;
WorldOptions worldoptions = new WorldOptions(creator.seed(), creator.generateStructures(), false);
@@ -1151,14 +1149,15 @@ public final class CraftServer implements Server {
Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle());
worlddata = new WorldDataServer(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle);
iregistry = worlddimensions_b.dimensions();
iregistrycustom_dimension = worlddimensions_b.dimensionsRegistryAccess();
}
iregistry = iregistrycustom_dimension.registryOrThrow(Registries.LEVEL_STEM);
worlddata.customDimensions = iregistry;
worlddata.checkName(name);
worlddata.setModdedInfo(console.getServerModName(), console.getModdedStatus().shouldReportAsModified());
if (console.options.has("forceUpgrade")) {
net.minecraft.server.Main.forceUpgrade(worldSession, DataConverterRegistry.getDataFixer(), console.options.has("eraseCache"), () -> true, iregistry);
net.minecraft.server.Main.forceUpgrade(worldSession, DataConverterRegistry.getDataFixer(), console.options.has("eraseCache"), () -> true, iregistrycustom_dimension, console.options.has("recreateRegionFiles"));
}
long j = BiomeManager.obfuscateSeed(creator.seed());
@@ -1180,9 +1179,12 @@ public final class CraftServer implements Server {
worldKey = ResourceKey.create(Registries.DIMENSION, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH)));
}
WorldServer internal = (WorldServer) new WorldServer(console, console.executor, worldSession, worlddata, worldKey, worlddimension, getServer().progressListenerFactory.create(11),
// If set to not keep spawn in memory (changed from default) then adjust rule accordingly
if (!creator.keepSpawnInMemory()) {
worlddata.getGameRules().getRule(GameRules.RULE_SPAWN_CHUNK_RADIUS).set(0, null);
}
WorldServer internal = (WorldServer) new WorldServer(console, console.executor, worldSession, worlddata, worldKey, worlddimension, getServer().progressListenerFactory.create(worlddata.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)),
worlddata.isDebugWorld(), j, creator.environment() == Environment.NORMAL ? list : ImmutableList.of(), true, console.overworld().getRandomSequences(), creator.environment(), generator, biomeProvider);
internal.keepSpawnInMemory = creator.keepSpawnInMemory();
if (!(worlds.containsKey(name.toLowerCase(java.util.Locale.ENGLISH)))) {
return null;
@@ -1476,7 +1478,7 @@ public final class CraftServer implements Server {
if (!itemstack2.isEmpty()) {
if (itemstack1.isEmpty()) {
inventoryCrafting.setItem(i, itemstack2);
} else if (net.minecraft.world.item.ItemStack.isSameItemSameTags(itemstack1, itemstack2)) {
} else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack1, itemstack2)) {
itemstack2.grow(itemstack1.getCount());
inventoryCrafting.setItem(i, itemstack2);
} else {
@@ -1584,6 +1586,11 @@ public final class CraftServer implements Server {
return this.getServer().enforceSecureProfile();
}
@Override
public boolean isAcceptingTransfers() {
return this.getServer().acceptsTransfers();
}
@Override
public boolean getHideOnlinePlayers() {
return console.hidesOnlinePlayers();
@@ -1679,7 +1686,7 @@ public final class CraftServer implements Server {
@Override
@Deprecated
public CraftMapView getMap(int id) {
WorldMap worldmap = console.getLevel(net.minecraft.world.level.World.OVERWORLD).getMapData("map_" + id);
WorldMap worldmap = console.getLevel(net.minecraft.world.level.World.OVERWORLD).getMapData(new MapId(id));
if (worldmap == null) {
return null;
}
@@ -1692,8 +1699,9 @@ public final class CraftServer implements Server {
net.minecraft.world.level.World minecraftWorld = ((CraftWorld) world).getHandle();
// creates a new map at world spawn with the scale of 3, with out tracking position and unlimited tracking
int newId = ItemWorldMap.createNewSavedData(minecraftWorld, minecraftWorld.getLevelData().getXSpawn(), minecraftWorld.getLevelData().getZSpawn(), 3, false, false, minecraftWorld.dimension());
return minecraftWorld.getMapData(ItemWorldMap.makeKey(newId)).mapView;
BlockPosition spawn = minecraftWorld.getLevelData().getSpawnPos();
MapId newId = ItemWorldMap.createNewSavedData(minecraftWorld, spawn.getX(), spawn.getZ(), 3, false, false, minecraftWorld.dimension());
return minecraftWorld.getMapData(newId).mapView;
}
@Override
@@ -1715,7 +1723,7 @@ public final class CraftServer implements Server {
net.minecraft.world.item.ItemStack stack = ItemWorldMap.create(worldServer, structurePosition.getX(), structurePosition.getZ(), MapView.Scale.NORMAL.getValue(), true, true);
ItemWorldMap.renderBiomePreviewMap(worldServer, stack);
// "+" map ID taken from EntityVillager
ItemWorldMap.getSavedData(stack, worldServer).addTargetDecoration(stack, structurePosition, "+", MapIcon.Type.byIcon(structureType.getMapIcon().getValue()));
ItemWorldMap.getSavedData(stack, worldServer).addTargetDecoration(stack, structurePosition, "+", CraftMapCursor.CraftType.bukkitToMinecraftHolder(structureType.getMapIcon()));
return CraftItemStack.asBukkitCopy(stack);
}
@@ -2435,8 +2443,8 @@ public final class CraftServer implements Server {
public LootTable getLootTable(NamespacedKey key) {
Preconditions.checkArgument(key != null, "NamespacedKey key cannot be null");
LootDataManager registry = getServer().getLootData();
return new CraftLootTable(key, registry.getLootTable(CraftNamespacedKey.toMinecraft(key)));
ReloadableServerRegistries.b registry = getServer().reloadableRegistries();
return new CraftLootTable(key, registry.getLootTable(CraftLootTable.bukkitKeyToMinecraft(key)));
}
@Override

View File

@@ -61,9 +61,9 @@ import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.RayTrace;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunkExtension;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.storage.SavedFile;
import net.minecraft.world.phys.AxisAlignedBB;
@@ -334,7 +334,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
if (playerChunk == null) return false;
playerChunk.getTickingChunkFuture().thenAccept(either -> {
either.left().ifPresent(chunk -> {
either.ifSuccess(chunk -> {
List<EntityPlayer> playersInRange = playerChunk.playerProvider.getPlayers(playerChunk.getPos(), false);
if (playersInRange.isEmpty()) return;
@@ -1318,19 +1318,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean getKeepSpawnInMemory() {
return world.keepSpawnInMemory;
return getGameRuleValue(GameRule.SPAWN_RADIUS) > 0;
}
@Override
public void setKeepSpawnInMemory(boolean keepLoaded) {
world.keepSpawnInMemory = keepLoaded;
// Grab the worlds spawn chunk
BlockPosition chunkcoordinates = this.world.getSharedSpawnPos();
if (keepLoaded) {
world.getChunkSource().addRegionTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE);
setGameRule(GameRule.SPAWN_CHUNK_RADIUS, getGameRuleDefault(GameRule.SPAWN_CHUNK_RADIUS));
} else {
// TODO: doesn't work well if spawn changed....
world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE);
setGameRule(GameRule.SPAWN_CHUNK_RADIUS, 0);
}
}

View File

@@ -122,6 +122,7 @@ public class Main {
acceptsAll(asList("forceUpgrade"), "Whether to force a world upgrade");
acceptsAll(asList("eraseCache"), "Whether to force cache erase during world upgrade");
acceptsAll(asList("recreateRegionFiles"), "Whether to recreate region files during world upgrade");
acceptsAll(asList("nogui"), "Disables the graphical console");
acceptsAll(asList("nojline"), "Disables jline and emulates the vanilla console");
@@ -200,11 +201,11 @@ public class Main {
useConsole = false;
}
if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) {
if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) {
Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L);
Calendar deadline = Calendar.getInstance();
deadline.add(Calendar.DAY_OF_YEAR, -28);
deadline.add(Calendar.DAY_OF_YEAR, -3);
if (buildDate.before(deadline.getTime())) {
System.err.println("*** Error, this build is outdated ***");
System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***");

View File

@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.attribute;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.ai.attributes.AttributeBase;
@@ -23,6 +24,10 @@ public class CraftAttribute {
return bukkit;
}
public static Attribute minecraftHolderToBukkit(Holder<AttributeBase> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static Attribute stringToBukkit(String bukkit) {
Preconditions.checkArgument(bukkit != null);
@@ -35,4 +40,17 @@ public class CraftAttribute {
return CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE)
.getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
}
public static Holder<AttributeBase> bukkitToMinecraftHolder(Attribute bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<AttributeBase> registry = CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<AttributeBase> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own sound effect with out properly registering it.");
}
}

View File

@@ -63,7 +63,7 @@ public class CraftAttributeInstance implements AttributeInstance {
@Override
public double getDefaultValue() {
return handle.getAttribute().getDefaultValue();
return handle.getAttribute().value().getDefaultValue();
}
public static net.minecraft.world.entity.ai.attributes.AttributeModifier convert(AttributeModifier bukkit) {
@@ -71,10 +71,10 @@ public class CraftAttributeInstance implements AttributeInstance {
}
public static AttributeModifier convert(net.minecraft.world.entity.ai.attributes.AttributeModifier nms) {
return new AttributeModifier(nms.getId(), nms.name, nms.getAmount(), AttributeModifier.Operation.values()[nms.getOperation().ordinal()]);
return new AttributeModifier(nms.id(), nms.name, nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()]);
}
public static AttributeModifier convert(net.minecraft.world.entity.ai.attributes.AttributeModifier nms, EquipmentSlot slot) {
return new AttributeModifier(nms.getId(), nms.name, nms.getAmount(), AttributeModifier.Operation.values()[nms.getOperation().ordinal()], slot);
return new AttributeModifier(nms.id(), nms.name, nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()], slot);
}
}

View File

@@ -17,7 +17,7 @@ public class CraftAttributeMap implements Attributable {
@Override
public AttributeInstance getAttribute(Attribute attribute) {
Preconditions.checkArgument(attribute != null, "attribute");
net.minecraft.world.entity.ai.attributes.AttributeModifiable nms = handle.getInstance(CraftAttribute.bukkitToMinecraft(attribute));
net.minecraft.world.entity.ai.attributes.AttributeModifiable nms = handle.getInstance(CraftAttribute.bukkitToMinecraftHolder(attribute));
return (nms == null) ? null : new CraftAttributeInstance(nms, attribute);
}

View File

@@ -2,8 +2,6 @@ package org.bukkit.craftbukkit.block;
import net.minecraft.core.BlockPosition;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.animal.EntityBee;
import net.minecraft.world.level.GeneratorAccessSeed;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.entity.TileEntity;
@@ -63,9 +61,7 @@ public final class CapturedBlockState extends CraftBlockState {
int j = 2 + random.nextInt(2);
for (int k = 0; k < j; ++k) {
EntityBee entitybee = new EntityBee(EntityTypes.BEE, generatoraccessseed.getMinecraftWorld());
tileentitybeehive.addOccupantWithPresetTicks(entitybee, false, random.nextInt(599));
tileentitybeehive.storeBee(TileEntityBeehive.c.create(random.nextInt(599)));
}
}
// End copied block

View File

@@ -3,17 +3,16 @@ package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.item.EnumColor;
import net.minecraft.world.level.block.BlockBannerAbstract;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.TileEntityBanner;
import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Banner;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.craftbukkit.block.banner.CraftPatternType;
public class CraftBanner extends CraftBlockEntityState<TileEntityBanner> implements Banner {
@@ -35,10 +34,10 @@ public class CraftBanner extends CraftBlockEntityState<TileEntityBanner> impleme
base = DyeColor.getByWoolData((byte) ((BlockBannerAbstract) this.data.getBlock()).getColor().getId());
patterns = new ArrayList<Pattern>();
if (banner.itemPatterns != null) {
for (int i = 0; i < banner.itemPatterns.size(); i++) {
NBTTagCompound p = (NBTTagCompound) banner.itemPatterns.get(i);
patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.getInt("Color")), PatternType.getByIdentifier(p.getString("Pattern"))));
if (banner.getPatterns() != null) {
for (int i = 0; i < banner.getPatterns().layers().size(); i++) {
BannerPatternLayers.b p = banner.getPatterns().layers().get(i);
patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), CraftPatternType.minecraftHolderToBukkit(p.pattern())));
}
}
}
@@ -95,15 +94,12 @@ public class CraftBanner extends CraftBlockEntityState<TileEntityBanner> impleme
banner.baseColor = EnumColor.byId(base.getWoolData());
NBTTagList newPatterns = new NBTTagList();
List<BannerPatternLayers.b> newPatterns = new ArrayList<>();
for (Pattern p : patterns) {
NBTTagCompound compound = new NBTTagCompound();
compound.putInt("Color", p.getColor().getWoolData());
compound.putString("Pattern", p.getPattern().getIdentifier());
newPatterns.add(compound);
newPatterns.add(new net.minecraft.world.level.block.entity.BannerPatternLayers.b(CraftPatternType.bukkitToMinecraftHolder(p.getPattern()), EnumColor.byId(p.getColor().getWoolData())));
}
banner.itemPatterns = newPatterns;
banner.setPatterns(new BannerPatternLayers(newPatterns));
}
@Override

View File

@@ -59,7 +59,7 @@ public class CraftBeacon extends CraftBlockEntityState<TileEntityBeacon> impleme
@Override
public void setPrimaryEffect(PotionEffectType effect) {
this.getSnapshot().primaryPower = (effect != null) ? CraftPotionEffectType.bukkitToMinecraft(effect) : null;
this.getSnapshot().primaryPower = (effect != null) ? CraftPotionEffectType.bukkitToMinecraftHolder(effect) : null;
}
@Override
@@ -69,7 +69,7 @@ public class CraftBeacon extends CraftBlockEntityState<TileEntityBeacon> impleme
@Override
public void setSecondaryEffect(PotionEffectType effect) {
this.getSnapshot().secondaryPower = (effect != null) ? CraftPotionEffectType.bukkitToMinecraft(effect) : null;
this.getSnapshot().secondaryPower = (effect != null) ? CraftPotionEffectType.bukkitToMinecraftHolder(effect) : null;
}
@Override
@@ -85,12 +85,12 @@ public class CraftBeacon extends CraftBlockEntityState<TileEntityBeacon> impleme
@Override
public boolean isLocked() {
return !this.getSnapshot().lockKey.key.isEmpty();
return !this.getSnapshot().lockKey.key().isEmpty();
}
@Override
public String getLock() {
return this.getSnapshot().lockKey.key;
return this.getSnapshot().lockKey.key();
}
@Override

View File

@@ -83,7 +83,7 @@ public class CraftBeehive extends CraftBlockEntityState<TileEntityBeehive> imple
public void addEntity(Bee entity) {
Preconditions.checkArgument(entity != null, "Entity must not be null");
getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false);
getSnapshot().addOccupant(((CraftBee) entity).getHandle());
}
@Override

View File

@@ -1,9 +1,14 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.PacketListenerPlayOut;
import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GeneratorAccess;
import net.minecraft.world.level.block.entity.TileEntity;
import org.bukkit.Location;
import org.bukkit.World;
@@ -39,27 +44,40 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
this.load(tileEntity);
}
private IRegistryCustom getRegistryAccess() {
GeneratorAccess worldHandle = getWorldHandle();
return (worldHandle != null) ? worldHandle.registryAccess() : MinecraftServer.getDefaultRegistryAccess();
}
private T createSnapshot(T tileEntity) {
if (tileEntity == null) {
return null;
}
NBTTagCompound nbtTagCompound = tileEntity.saveWithFullMetadata();
T snapshot = (T) TileEntity.loadStatic(getPosition(), getHandle(), nbtTagCompound);
NBTTagCompound nbtTagCompound = tileEntity.saveWithFullMetadata(getRegistryAccess());
T snapshot = (T) TileEntity.loadStatic(getPosition(), getHandle(), nbtTagCompound, getRegistryAccess());
return snapshot;
}
public void applyComponents(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) {
snapshot.applyComponents(datacomponentmap, datacomponentpatch);
}
public DataComponentMap collectComponents() {
return snapshot.collectComponents();
}
// Loads the specified data into the snapshot TileEntity.
public void loadData(NBTTagCompound nbtTagCompound) {
snapshot.load(nbtTagCompound);
snapshot.loadWithComponents(nbtTagCompound, getRegistryAccess());
load(snapshot);
}
// copies the TileEntity-specific data, retains the position
private void copyData(T from, T to) {
NBTTagCompound nbtTagCompound = from.saveWithFullMetadata();
to.load(nbtTagCompound);
NBTTagCompound nbtTagCompound = from.saveWithFullMetadata(getRegistryAccess());
to.loadWithComponents(nbtTagCompound, getRegistryAccess());
}
// gets the wrapped TileEntity
@@ -84,7 +102,13 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
// update snapshot
applyTo(snapshot);
return snapshot.saveWithFullMetadata();
return snapshot.saveWithFullMetadata(getRegistryAccess());
}
public NBTTagCompound getSnapshotNBTWithoutComponents() {
NBTTagCompound nbt = getSnapshotNBT();
snapshot.removeComponentsFromTag(nbt);
return nbt;
}
// copies the data of the given tile entity to this block state
@@ -128,7 +152,7 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
@Nullable
public Packet<PacketListenerPlayOut> getUpdatePacket(@NotNull Location location) {
T vanillaTileEntitiy = (T) TileEntity.loadStatic(CraftLocation.toBlockPosition(location), getHandle(), getSnapshotNBT());
T vanillaTileEntitiy = (T) TileEntity.loadStatic(CraftLocation.toBlockPosition(location), getHandle(), getSnapshotNBT(), getRegistryAccess());
return PacketPlayOutTileEntityData.create(vanillaTileEntitiy);
}

View File

@@ -9,8 +9,11 @@ import java.util.Map;
import java.util.function.BiFunction;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GeneratorAccess;
import net.minecraft.world.level.IWorldReader;
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
import net.minecraft.world.level.block.entity.ChiseledBookShelfBlockEntity;
@@ -54,6 +57,7 @@ import net.minecraft.world.level.block.entity.TileEntitySkull;
import net.minecraft.world.level.block.entity.TileEntitySmoker;
import net.minecraft.world.level.block.entity.TileEntityStructure;
import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity;
import net.minecraft.world.level.block.entity.vault.VaultBlockEntity;
import net.minecraft.world.level.block.piston.TileEntityPiston;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Material;
@@ -336,6 +340,7 @@ public final class CraftBlockStates {
register(Material.TRAPPED_CHEST, CraftChest.class, CraftChest::new, TileEntityChestTrapped::new);
register(Material.CRAFTER, CraftCrafter.class, CraftCrafter::new, CrafterBlockEntity::new);
register(Material.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new, TrialSpawnerBlockEntity::new);
register(Material.VAULT, CraftVault.class, CraftVault::new, VaultBlockEntity::new);
}
private static void register(Material blockType, BlockStateFactory<?> factory) {
@@ -394,24 +399,34 @@ public final class CraftBlockStates {
return blockState;
}
@Deprecated
public static BlockState getBlockState(Material material, @Nullable NBTTagCompound blockEntityTag) {
return getBlockState(BlockPosition.ZERO, material, blockEntityTag);
return getBlockState(MinecraftServer.getDefaultRegistryAccess(), BlockPosition.ZERO, material, blockEntityTag);
}
public static BlockState getBlockState(BlockPosition blockPosition, Material material, @Nullable NBTTagCompound blockEntityTag) {
public static BlockState getBlockState(IWorldReader world, BlockPosition blockPosition, Material material, @Nullable NBTTagCompound blockEntityTag) {
return getBlockState(world.registryAccess(), blockPosition, material, blockEntityTag);
}
public static BlockState getBlockState(IRegistryCustom registry, BlockPosition blockPosition, Material material, @Nullable NBTTagCompound blockEntityTag) {
Preconditions.checkNotNull(material, "material is null");
IBlockData blockData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState();
return getBlockState(blockPosition, blockData, blockEntityTag);
return getBlockState(registry, blockPosition, blockData, blockEntityTag);
}
@Deprecated
public static BlockState getBlockState(IBlockData blockData, @Nullable NBTTagCompound blockEntityTag) {
return getBlockState(BlockPosition.ZERO, blockData, blockEntityTag);
return getBlockState(MinecraftServer.getDefaultRegistryAccess(), BlockPosition.ZERO, blockData, blockEntityTag);
}
public static BlockState getBlockState(BlockPosition blockPosition, IBlockData blockData, @Nullable NBTTagCompound blockEntityTag) {
public static BlockState getBlockState(IWorldReader world, BlockPosition blockPosition, IBlockData blockData, @Nullable NBTTagCompound blockEntityTag) {
return getBlockState(world.registryAccess(), blockPosition, blockData, blockEntityTag);
}
public static BlockState getBlockState(IRegistryCustom registry, BlockPosition blockPosition, IBlockData blockData, @Nullable NBTTagCompound blockEntityTag) {
Preconditions.checkNotNull(blockPosition, "blockPosition is null");
Preconditions.checkNotNull(blockData, "blockData is null");
TileEntity tileEntity = (blockEntityTag == null) ? null : TileEntity.loadStatic(blockPosition, blockData, blockEntityTag);
TileEntity tileEntity = (blockEntityTag == null) ? null : TileEntity.loadStatic(blockPosition, blockData, blockEntityTag, registry);
return getBlockState(null, blockPosition, blockData, tileEntity);
}

View File

@@ -1,13 +1,11 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BrushableBlock;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootTable;
@@ -36,18 +34,13 @@ public class CraftBrushableBlock extends CraftBlockEntityState<BrushableBlockEnt
super.applyTo(lootable);
if (this.getSnapshot().lootTable == null) {
lootable.setLootTable((MinecraftKey) null, 0L);
lootable.setLootTable(null, 0L);
}
}
@Override
public LootTable getLootTable() {
if (getSnapshot().lootTable == null) {
return null;
}
MinecraftKey key = getSnapshot().lootTable;
return Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(key));
return CraftLootTable.minecraftToBukkit(getSnapshot().lootTable);
}
@Override
@@ -66,8 +59,7 @@ public class CraftBrushableBlock extends CraftBlockEntityState<BrushableBlockEnt
}
private void setLootTable(LootTable table, long seed) {
MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
getSnapshot().setLootTable(key, seed);
getSnapshot().setLootTable(CraftLootTable.bukkitToMinecraft(table), seed);
}
@Override

View File

@@ -70,7 +70,14 @@ public class CraftChiseledBookshelf extends CraftBlockEntityState<ChiseledBookSh
return -1;
}
return ChiseledBookShelfBlock.getHitSlot(faceVector);
return getHitSlot(faceVector);
}
private static int getHitSlot(Vec2F vec2f) {
int i = vec2f.y >= 0.5F ? 0 : 1;
int j = ChiseledBookShelfBlock.getSection(vec2f.x);
return j + i * 3;
}
@Override

View File

@@ -33,7 +33,7 @@ public class CraftCommandBlock extends CraftBlockEntityState<TileEntityCommand>
@Override
public void setName(String name) {
getSnapshot().getCommandBlock().setName(CraftChatMessage.fromStringOrNull(name != null ? name : "@"));
getSnapshot().getCommandBlock().setCustomName(CraftChatMessage.fromStringOrNull(name != null ? name : "@"));
}
@Override

View File

@@ -19,12 +19,12 @@ public abstract class CraftContainer<T extends TileEntityContainer> extends Craf
@Override
public boolean isLocked() {
return !this.getSnapshot().lockKey.key.isEmpty();
return !this.getSnapshot().lockKey.key().isEmpty();
}
@Override
public String getLock() {
return this.getSnapshot().lockKey.key;
return this.getSnapshot().lockKey.key();
}
@Override
@@ -40,7 +40,7 @@ public abstract class CraftContainer<T extends TileEntityContainer> extends Craf
@Override
public void setCustomName(String name) {
this.getSnapshot().setCustomName(CraftChatMessage.fromStringOrNull(name));
this.getSnapshot().name = CraftChatMessage.fromStringOrNull(name);
}
@Override
@@ -48,7 +48,7 @@ public abstract class CraftContainer<T extends TileEntityContainer> extends Craf
super.applyTo(container);
if (this.getSnapshot().name == null) {
container.setCustomName(null);
container.name = null;
}
}

View File

@@ -3,14 +3,18 @@ package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.InclusiveRange;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.util.random.WeightedEntry.b;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EquipmentTable;
import net.minecraft.world.level.MobSpawnerData;
import net.minecraft.world.level.block.entity.TileEntityMobSpawner;
import org.bukkit.Location;
@@ -18,6 +22,8 @@ import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.spawner.SpawnRule;
import org.bukkit.block.spawner.SpawnerEntry;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.entity.CraftEntitySnapshot;
import org.bukkit.craftbukkit.entity.CraftEntityType;
import org.bukkit.entity.EntitySnapshot;
@@ -72,7 +78,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
NBTTagCompound compoundTag = ((CraftEntitySnapshot) snapshot).getData();
this.getSnapshot().getSpawner().spawnPotentials = SimpleWeightedRandomList.empty();
this.getSnapshot().getSpawner().nextSpawnData = new MobSpawnerData(compoundTag, Optional.empty());
this.getSnapshot().getSpawner().nextSpawnData = new MobSpawnerData(compoundTag, Optional.empty(), Optional.empty());
}
@Override
@@ -80,8 +86,8 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
NBTTagCompound compoundTag = ((CraftEntitySnapshot) snapshot).getData();
SimpleWeightedRandomList.a<MobSpawnerData> builder = SimpleWeightedRandomList.builder(); // PAIL rename Builder
this.getSnapshot().getSpawner().spawnPotentials.unwrap().forEach(entry -> builder.add(entry.getData(), entry.getWeight().asInt()));
builder.add(new MobSpawnerData(compoundTag, Optional.ofNullable(toMinecraftRule(spawnRule))), weight);
this.getSnapshot().getSpawner().spawnPotentials.unwrap().forEach(entry -> builder.add(entry.data(), entry.getWeight().asInt()));
builder.add(new MobSpawnerData(compoundTag, Optional.ofNullable(toMinecraftRule(spawnRule)), Optional.empty()), weight);
this.getSnapshot().getSpawner().spawnPotentials = builder.build();
}
@@ -95,7 +101,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
SimpleWeightedRandomList.a<MobSpawnerData> builder = SimpleWeightedRandomList.builder();
for (SpawnerEntry spawnerEntry : entries) {
NBTTagCompound compoundTag = ((CraftEntitySnapshot) spawnerEntry.getSnapshot()).getData();
builder.add(new MobSpawnerData(compoundTag, Optional.ofNullable(toMinecraftRule(spawnerEntry.getSpawnRule()))), spawnerEntry.getSpawnWeight());
builder.add(new MobSpawnerData(compoundTag, Optional.ofNullable(toMinecraftRule(spawnerEntry.getSpawnRule())), getEquipment(spawnerEntry.getEquipment())), spawnerEntry.getSpawnWeight());
}
this.getSnapshot().getSpawner().spawnPotentials = builder.build();
}
@@ -105,11 +111,11 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
List<SpawnerEntry> entries = new ArrayList<>();
for (b<MobSpawnerData> entry : this.getSnapshot().getSpawner().spawnPotentials.unwrap()) { // PAIL rename Wrapper
CraftEntitySnapshot snapshot = CraftEntitySnapshot.create(entry.getData().getEntityToSpawn());
CraftEntitySnapshot snapshot = CraftEntitySnapshot.create(entry.data().getEntityToSpawn());
if (snapshot != null) {
SpawnRule rule = entry.getData().customSpawnRules().map(this::fromMinecraftRule).orElse(null);
entries.add(new SpawnerEntry(snapshot, entry.getWeight().asInt(), rule));
SpawnRule rule = entry.data().customSpawnRules().map(this::fromMinecraftRule).orElse(null);
entries.add(new SpawnerEntry(snapshot, entry.getWeight().asInt(), rule, getEquipment(entry.data().equipment())));
}
}
return entries;
@@ -123,10 +129,10 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
}
private SpawnRule fromMinecraftRule(MobSpawnerData.a rule) {
InclusiveRange<Integer> blockLight = rule.blockLightLimit();
InclusiveRange<Integer> skyLight = rule.skyLightLimit();
InclusiveRange<Integer> blockLight = rule.blockLightLimit();
InclusiveRange<Integer> skyLight = rule.skyLightLimit();
return new SpawnRule(blockLight.maxInclusive(), blockLight.maxInclusive(), skyLight.minInclusive(), skyLight.maxInclusive());
return new SpawnRule(blockLight.maxInclusive(), blockLight.maxInclusive(), skyLight.minInclusive(), skyLight.maxInclusive());
}
@Override
@@ -233,4 +239,22 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpa
public CraftCreatureSpawner copy(Location location) {
return new CraftCreatureSpawner(this, location);
}
private static Optional<EquipmentTable> getEquipment(SpawnerEntry.Equipment bukkit) {
if (bukkit == null) {
return Optional.empty();
}
return Optional.of(new EquipmentTable(
CraftLootTable.bukkitToMinecraft(bukkit.getEquipmentLootTable()),
bukkit.getDropChances().entrySet().stream().collect(Collectors.toMap((entry) -> CraftEquipmentSlot.getNMS(entry.getKey()), Map.Entry::getValue)))
);
}
private static SpawnerEntry.Equipment getEquipment(Optional<EquipmentTable> optional) {
return optional.map((nms) -> new SpawnerEntry.Equipment(
CraftLootTable.minecraftToBukkit(nms.lootTable()),
new HashMap<>(nms.slotDropChances().entrySet().stream().collect(Collectors.toMap((entry) -> CraftEquipmentSlot.getSlot(entry.getKey()), Map.Entry::getValue)))
)).orElse(null);
}
}

View File

@@ -4,10 +4,12 @@ import com.google.common.base.Preconditions;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.block.entity.PotDecorations;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
@@ -46,14 +48,14 @@ public class CraftDecoratedPot extends CraftBlockEntityState<DecoratedPotBlockEn
Preconditions.checkArgument(face != null, "face must not be null");
Preconditions.checkArgument(sherd == null || sherd == Material.BRICK || Tag.ITEMS_DECORATED_POT_SHERDS.isTagged(sherd), "sherd is not a valid sherd material: %s", sherd);
Item sherdItem = (sherd != null) ? CraftItemType.bukkitToMinecraft(sherd) : Items.BRICK;
DecoratedPotBlockEntity.Decoration decorations = getSnapshot().getDecorations();
Optional<Item> sherdItem = (sherd != null) ? Optional.of(CraftItemType.bukkitToMinecraft(sherd)) : Optional.of(Items.BRICK);
PotDecorations decorations = getSnapshot().getDecorations();
switch (face) {
case BACK -> getSnapshot().decorations = new DecoratedPotBlockEntity.Decoration(sherdItem, decorations.left(), decorations.right(), decorations.front());
case LEFT -> getSnapshot().decorations = new DecoratedPotBlockEntity.Decoration(decorations.back(), sherdItem, decorations.right(), decorations.front());
case RIGHT -> getSnapshot().decorations = new DecoratedPotBlockEntity.Decoration(decorations.back(), decorations.left(), sherdItem, decorations.front());
case FRONT -> getSnapshot().decorations = new DecoratedPotBlockEntity.Decoration(decorations.back(), decorations.left(), decorations.right(), sherdItem);
case BACK -> getSnapshot().decorations = new PotDecorations(sherdItem, decorations.left(), decorations.right(), decorations.front());
case LEFT -> getSnapshot().decorations = new PotDecorations(decorations.back(), sherdItem, decorations.right(), decorations.front());
case RIGHT -> getSnapshot().decorations = new PotDecorations(decorations.back(), decorations.left(), sherdItem, decorations.front());
case FRONT -> getSnapshot().decorations = new PotDecorations(decorations.back(), decorations.left(), decorations.right(), sherdItem);
default -> throw new IllegalArgumentException("Unexpected value: " + face);
}
}
@@ -62,8 +64,8 @@ public class CraftDecoratedPot extends CraftBlockEntityState<DecoratedPotBlockEn
public Material getSherd(Side face) {
Preconditions.checkArgument(face != null, "face must not be null");
DecoratedPotBlockEntity.Decoration decorations = getSnapshot().getDecorations();
Item sherdItem = switch (face) {
PotDecorations decorations = getSnapshot().getDecorations();
Optional<Item> sherdItem = switch (face) {
case BACK -> decorations.back();
case LEFT -> decorations.left();
case RIGHT -> decorations.right();
@@ -71,24 +73,24 @@ public class CraftDecoratedPot extends CraftBlockEntityState<DecoratedPotBlockEn
default -> throw new IllegalArgumentException("Unexpected value: " + face);
};
return CraftItemType.minecraftToBukkit(sherdItem);
return CraftItemType.minecraftToBukkit(sherdItem.orElse(Items.BRICK));
}
@Override
public Map<Side, Material> getSherds() {
DecoratedPotBlockEntity.Decoration decorations = getSnapshot().getDecorations();
PotDecorations decorations = getSnapshot().getDecorations();
Map<Side, Material> sherds = new EnumMap<>(Side.class);
sherds.put(Side.BACK, CraftItemType.minecraftToBukkit(decorations.back()));
sherds.put(Side.LEFT, CraftItemType.minecraftToBukkit(decorations.left()));
sherds.put(Side.RIGHT, CraftItemType.minecraftToBukkit(decorations.right()));
sherds.put(Side.FRONT, CraftItemType.minecraftToBukkit(decorations.front()));
sherds.put(Side.BACK, CraftItemType.minecraftToBukkit(decorations.back().orElse(Items.BRICK)));
sherds.put(Side.LEFT, CraftItemType.minecraftToBukkit(decorations.left().orElse(Items.BRICK)));
sherds.put(Side.RIGHT, CraftItemType.minecraftToBukkit(decorations.right().orElse(Items.BRICK)));
sherds.put(Side.FRONT, CraftItemType.minecraftToBukkit(decorations.front().orElse(Items.BRICK)));
return sherds;
}
@Override
public List<Material> getShards() {
return getSnapshot().getDecorations().sorted().map(CraftItemType::minecraftToBukkit).collect(Collectors.toUnmodifiableList());
return getSnapshot().getDecorations().ordered().stream().map(CraftItemType::minecraftToBukkit).collect(Collectors.toUnmodifiableList());
}
@Override

View File

@@ -1,12 +1,10 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.level.block.entity.TileEntityLootable;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Nameable;
import org.bukkit.World;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.Lootable;
@@ -25,18 +23,13 @@ public abstract class CraftLootable<T extends TileEntityLootable> extends CraftC
super.applyTo(lootable);
if (this.getSnapshot().lootTable == null) {
lootable.setLootTable((MinecraftKey) null, 0L);
lootable.setLootTable(null, 0L);
}
}
@Override
public LootTable getLootTable() {
if (getSnapshot().lootTable == null) {
return null;
}
MinecraftKey key = getSnapshot().lootTable;
return Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(key));
return CraftLootTable.minecraftToBukkit(getSnapshot().lootTable);
}
@Override
@@ -55,8 +48,7 @@ public abstract class CraftLootable<T extends TileEntityLootable> extends CraftC
}
private void setLootTable(LootTable table, long seed) {
MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
getSnapshot().setLootTable(key, seed);
getSnapshot().setLootTable(CraftLootTable.bukkitToMinecraft(table), seed);
}
@Override

View File

@@ -5,6 +5,7 @@ import com.mojang.authlib.GameProfile;
import net.minecraft.SystemUtils;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.block.entity.TileEntitySkull;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -40,24 +41,9 @@ public class CraftSkull extends CraftBlockEntityState<TileEntitySkull> implement
public void load(TileEntitySkull skull) {
super.load(skull);
profile = skull.owner;
}
static int getSkullType(SkullType type) {
switch (type) {
default:
case SKELETON:
return 0;
case WITHER:
return 1;
case ZOMBIE:
return 2;
case PLAYER:
return 3;
case CREEPER:
return 4;
case DRAGON:
return 5;
ResolvableProfile owner = skull.getOwnerProfile();
if (owner != null) {
profile = owner.gameProfile();
}
}
@@ -201,7 +187,7 @@ public class CraftSkull extends CraftBlockEntityState<TileEntitySkull> implement
super.applyTo(skull);
if (getSkullType() == SkullType.PLAYER) {
skull.setOwner(profile);
skull.setOwner(new ResolvableProfile(profile));
}
}

View File

@@ -0,0 +1,27 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.world.level.block.entity.vault.VaultBlockEntity;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.TrialSpawner;
public class CraftVault extends CraftBlockEntityState<VaultBlockEntity> implements TrialSpawner {
public CraftVault(World world, VaultBlockEntity tileEntity) {
super(world, tileEntity);
}
protected CraftVault(CraftVault state, Location location) {
super(state, location);
}
@Override
public CraftVault copy() {
return new CraftVault(this, null);
}
@Override
public CraftVault copy(Location location) {
return new CraftVault(this, location);
}
}

View File

@@ -0,0 +1,49 @@
package org.bukkit.craftbukkit.block.banner;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.block.entity.EnumBannerPatternType;
import org.bukkit.Registry;
import org.bukkit.block.banner.PatternType;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
public class CraftPatternType {
public static PatternType minecraftToBukkit(EnumBannerPatternType minecraft) {
Preconditions.checkArgument(minecraft != null);
IRegistry<EnumBannerPatternType> registry = CraftRegistry.getMinecraftRegistry(Registries.BANNER_PATTERN);
PatternType bukkit = Registry.BANNER_PATTERN.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location()));
Preconditions.checkArgument(bukkit != null);
return bukkit;
}
public static PatternType minecraftHolderToBukkit(Holder<EnumBannerPatternType> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static EnumBannerPatternType bukkitToMinecraft(PatternType bukkit) {
Preconditions.checkArgument(bukkit != null);
return CraftRegistry.getMinecraftRegistry(Registries.BANNER_PATTERN)
.getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
}
public static Holder<EnumBannerPatternType> bukkitToMinecraftHolder(PatternType bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<EnumBannerPatternType> registry = CraftRegistry.getMinecraftRegistry(Registries.BANNER_PATTERN);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<EnumBannerPatternType> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own banner pattern without properly registering it.");
}
}

View File

@@ -13,7 +13,6 @@ import net.minecraft.commands.arguments.blocks.ArgumentBlock;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.EnumDirection;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.INamable;
import net.minecraft.world.level.BlockAccessAir;
import net.minecraft.world.level.block.Block;
@@ -251,13 +250,13 @@ public class CraftBlockData implements BlockData {
return stateString.toString();
}
public NBTTagCompound toStates() {
NBTTagCompound compound = new NBTTagCompound();
public Map<String, String> toStates() {
Map<String, String> compound = new HashMap<>();
for (Map.Entry<IBlockState<?>, Comparable<?>> entry : state.getValues().entrySet()) {
IBlockState iblockstate = (IBlockState) entry.getKey();
compound.putString(iblockstate.getName(), iblockstate.getName(entry.getValue()));
compound.put(iblockstate.getName(), iblockstate.getName(entry.getValue()));
}
return compound;
@@ -501,6 +500,7 @@ public class CraftBlockData implements BlockData {
register(net.minecraft.world.level.block.EquipableCarvedPumpkinBlock.class, org.bukkit.craftbukkit.block.impl.CraftEquipableCarvedPumpkin::new);
register(net.minecraft.world.level.block.GlowLichenBlock.class, org.bukkit.craftbukkit.block.impl.CraftGlowLichen::new);
register(net.minecraft.world.level.block.HangingRootsBlock.class, org.bukkit.craftbukkit.block.impl.CraftHangingRoots::new);
register(net.minecraft.world.level.block.HeavyCoreBlock.class, org.bukkit.craftbukkit.block.impl.CraftHeavyCore::new);
register(net.minecraft.world.level.block.InfestedRotatedPillarBlock.class, org.bukkit.craftbukkit.block.impl.CraftInfestedRotatedPillar::new);
register(net.minecraft.world.level.block.LayeredCauldronBlock.class, org.bukkit.craftbukkit.block.impl.CraftLayeredCauldron::new);
register(net.minecraft.world.level.block.LightBlock.class, org.bukkit.craftbukkit.block.impl.CraftLight::new);
@@ -521,6 +521,7 @@ public class CraftBlockData implements BlockData {
register(net.minecraft.world.level.block.TallSeagrassBlock.class, org.bukkit.craftbukkit.block.impl.CraftTallSeagrass::new);
register(net.minecraft.world.level.block.TorchflowerCropBlock.class, org.bukkit.craftbukkit.block.impl.CraftTorchflowerCrop::new);
register(net.minecraft.world.level.block.TrialSpawnerBlock.class, org.bukkit.craftbukkit.block.impl.CraftTrialSpawner::new);
register(net.minecraft.world.level.block.VaultBlock.class, org.bukkit.craftbukkit.block.impl.CraftVault::new);
register(net.minecraft.world.level.block.WallHangingSignBlock.class, org.bukkit.craftbukkit.block.impl.CraftWallHangingSign::new);
register(net.minecraft.world.level.block.WaterloggedTransparentBlock.class, org.bukkit.craftbukkit.block.impl.CraftWaterloggedTransparent::new);
register(net.minecraft.world.level.block.WeatheringCopperBulbBlock.class, org.bukkit.craftbukkit.block.impl.CraftWeatheringCopperBulb::new);

View File

@@ -6,6 +6,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData;
public abstract class CraftTrialSpawner extends CraftBlockData implements TrialSpawner {
private static final net.minecraft.world.level.block.state.properties.BlockStateEnum<?> TRIAL_SPAWNER_STATE = getEnum("trial_spawner_state");
private static final net.minecraft.world.level.block.state.properties.BlockStateBoolean OMINOUS = getBoolean("ominous");
@Override
public org.bukkit.block.data.type.TrialSpawner.State getTrialSpawnerState() {
@@ -16,4 +17,14 @@ public abstract class CraftTrialSpawner extends CraftBlockData implements TrialS
public void setTrialSpawnerState(org.bukkit.block.data.type.TrialSpawner.State state) {
set(TRIAL_SPAWNER_STATE, state);
}
@Override
public boolean isOminous() {
return get(OMINOUS);
}
@Override
public void setOminous(boolean ominous) {
set(OMINOUS, ominous);
}
}

View File

@@ -0,0 +1,30 @@
package org.bukkit.craftbukkit.block.data.type;
import org.bukkit.block.data.type.Vault;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
public abstract class CraftVault extends CraftBlockData implements Vault {
private static final net.minecraft.world.level.block.state.properties.BlockStateEnum<?> VAULT_STATE = getEnum("vault_state");
private static final net.minecraft.world.level.block.state.properties.BlockStateBoolean OMINOUS = getBoolean("ominous");
@Override
public org.bukkit.block.data.type.Vault.State getTrialSpawnerState() {
return get(VAULT_STATE, org.bukkit.block.data.type.Vault.State.class);
}
@Override
public void setTrialSpawnerState(org.bukkit.block.data.type.Vault.State state) {
set(VAULT_STATE, state);
}
@Override
public boolean isOminous() {
return get(OMINOUS);
}
@Override
public void setOminous(boolean ominous) {
set(OMINOUS, ominous);
}
}

View File

@@ -0,0 +1,29 @@
/**
* Automatically generated file, changes will be lost.
*/
package org.bukkit.craftbukkit.block.impl;
public final class CraftHeavyCore extends org.bukkit.craftbukkit.block.data.CraftBlockData implements org.bukkit.block.data.Waterlogged {
public CraftHeavyCore() {
super();
}
public CraftHeavyCore(net.minecraft.world.level.block.state.IBlockData state) {
super(state);
}
// org.bukkit.craftbukkit.block.data.CraftWaterlogged
private static final net.minecraft.world.level.block.state.properties.BlockStateBoolean WATERLOGGED = getBoolean(net.minecraft.world.level.block.HeavyCoreBlock.class, "waterlogged");
@Override
public boolean isWaterlogged() {
return get(WATERLOGGED);
}
@Override
public void setWaterlogged(boolean waterlogged) {
set(WATERLOGGED, waterlogged);
}
}

View File

@@ -16,6 +16,7 @@ public final class CraftTrialSpawner extends org.bukkit.craftbukkit.block.data.C
// org.bukkit.craftbukkit.block.data.type.CraftTrialSpawner
private static final net.minecraft.world.level.block.state.properties.BlockStateEnum<?> TRIAL_SPAWNER_STATE = getEnum(net.minecraft.world.level.block.TrialSpawnerBlock.class, "trial_spawner_state");
private static final net.minecraft.world.level.block.state.properties.BlockStateBoolean OMINOUS = getBoolean(net.minecraft.world.level.block.TrialSpawnerBlock.class, "ominous");
@Override
public org.bukkit.block.data.type.TrialSpawner.State getTrialSpawnerState() {
@@ -26,4 +27,14 @@ public final class CraftTrialSpawner extends org.bukkit.craftbukkit.block.data.C
public void setTrialSpawnerState(org.bukkit.block.data.type.TrialSpawner.State state) {
set(TRIAL_SPAWNER_STATE, state);
}
@Override
public boolean isOminous() {
return get(OMINOUS);
}
@Override
public void setOminous(boolean ominous) {
set(OMINOUS, ominous);
}
}

View File

@@ -0,0 +1,59 @@
/**
* Automatically generated file, changes will be lost.
*/
package org.bukkit.craftbukkit.block.impl;
public final class CraftVault extends org.bukkit.craftbukkit.block.data.CraftBlockData implements org.bukkit.block.data.type.Vault, org.bukkit.block.data.Directional {
public CraftVault() {
super();
}
public CraftVault(net.minecraft.world.level.block.state.IBlockData state) {
super(state);
}
// org.bukkit.craftbukkit.block.data.type.CraftVault
private static final net.minecraft.world.level.block.state.properties.BlockStateEnum<?> VAULT_STATE = getEnum(net.minecraft.world.level.block.VaultBlock.class, "vault_state");
private static final net.minecraft.world.level.block.state.properties.BlockStateBoolean OMINOUS = getBoolean(net.minecraft.world.level.block.VaultBlock.class, "ominous");
@Override
public org.bukkit.block.data.type.Vault.State getTrialSpawnerState() {
return get(VAULT_STATE, org.bukkit.block.data.type.Vault.State.class);
}
@Override
public void setTrialSpawnerState(org.bukkit.block.data.type.Vault.State state) {
set(VAULT_STATE, state);
}
@Override
public boolean isOminous() {
return get(OMINOUS);
}
@Override
public void setOminous(boolean ominous) {
set(OMINOUS, ominous);
}
// org.bukkit.craftbukkit.block.data.CraftDirectional
private static final net.minecraft.world.level.block.state.properties.BlockStateEnum<?> FACING = getEnum(net.minecraft.world.level.block.VaultBlock.class, "facing");
@Override
public org.bukkit.block.BlockFace getFacing() {
return get(FACING, org.bukkit.block.BlockFace.class);
}
@Override
public void setFacing(org.bukkit.block.BlockFace facing) {
set(FACING, facing);
}
@Override
public java.util.Set<org.bukkit.block.BlockFace> getFaces() {
return getValues(FACING, org.bukkit.block.BlockFace.class);
}
}

View File

@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.enchantments;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.enchantment.EnchantmentBinding;
@@ -20,6 +21,10 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
return CraftRegistry.minecraftToBukkit(minecraft, Registries.ENCHANTMENT, Registry.ENCHANTMENT);
}
public static Enchantment minecraftHolderToBukkit(Holder<net.minecraft.world.item.enchantment.Enchantment> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static net.minecraft.world.item.enchantment.Enchantment bukkitToMinecraft(Enchantment bukkit) {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
@@ -56,22 +61,7 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
@Override
public EnchantmentTarget getItemTarget() {
return switch (handle.category) {
case ARMOR -> EnchantmentTarget.ARMOR;
case ARMOR_FEET -> EnchantmentTarget.ARMOR_FEET;
case ARMOR_HEAD -> EnchantmentTarget.ARMOR_HEAD;
case ARMOR_LEGS -> EnchantmentTarget.ARMOR_LEGS;
case ARMOR_CHEST -> EnchantmentTarget.ARMOR_TORSO;
case DIGGER -> EnchantmentTarget.TOOL;
case WEAPON -> EnchantmentTarget.WEAPON;
case BOW -> EnchantmentTarget.BOW;
case FISHING_ROD -> EnchantmentTarget.FISHING_ROD;
case BREAKABLE -> EnchantmentTarget.BREAKABLE;
case WEARABLE -> EnchantmentTarget.WEARABLE;
case TRIDENT -> EnchantmentTarget.TRIDENT;
case CROSSBOW -> EnchantmentTarget.CROSSBOW;
case VANISHABLE -> EnchantmentTarget.VANISHABLE;
};
throw new UnsupportedOperationException("Method longer applicable. Use Tags instead.");
}
@Override
@@ -130,8 +120,11 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
case 34 -> "MULTISHOT";
case 35 -> "QUICK_CHARGE";
case 36 -> "PIERCING";
case 37 -> "MENDING";
case 38 -> "VANISHING_CURSE";
case 37 -> "DENSITY";
case 38 -> "BREACH";
case 39 -> "WIND_BURST";
case 40 -> "MENDING";
case 41 -> "VANISHING_CURSE";
default -> getKey().toString();
};
}

View File

@@ -51,7 +51,7 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac
@Override
public double getJumpStrength() {
return getHandle().getCustomJump();
return getHandle().getAttributeValue(GenericAttributes.JUMP_STRENGTH);
}
@Override

View File

@@ -0,0 +1,27 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.AbstractWindCharge;
import org.bukkit.event.entity.EntityRemoveEvent;
public abstract class CraftAbstractWindCharge extends CraftFireball implements AbstractWindCharge {
public CraftAbstractWindCharge(CraftServer server, net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge entity) {
super(server, entity);
}
@Override
public void explode() {
this.getHandle().explode();
this.getHandle().discard(EntityRemoveEvent.Cause.EXPLODE); // SPIGOT-7577 - explode doesn't discard the entity, this happens only in tick and onHitBlock
}
@Override
public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge getHandle() {
return (net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge) this.entity;
}
@Override
public String toString() {
return "CraftAbstractWindCharge";
}
}

View File

@@ -3,10 +3,13 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.Holder;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectList;
import net.minecraft.world.entity.EntityAreaEffectCloud;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.item.alchemy.PotionContents;
import org.bukkit.Color;
import org.bukkit.Particle;
import org.bukkit.craftbukkit.CraftParticle;
@@ -16,12 +19,10 @@ import org.bukkit.craftbukkit.potion.CraftPotionType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.LivingEntity;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.bukkit.projectiles.ProjectileSource;
import org.jetbrains.annotations.NotNull;
public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud {
@@ -131,28 +132,22 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public Color getColor() {
return Color.fromRGB(getHandle().getColor());
return Color.fromRGB(getHandle().potionContents.getColor());
}
@Override
public void setColor(Color color) {
getHandle().setFixedColor(color.asRGB());
PotionContents old = getHandle().potionContents;
getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(color.asRGB()), old.customEffects()));
}
@Override
public boolean addCustomEffect(PotionEffect effect, boolean override) {
MobEffectList minecraft = CraftPotionEffectType.bukkitToMinecraft(effect.getType());
MobEffect existing = null;
for (MobEffect mobEffect : getHandle().effects) {
if (mobEffect.getEffect() == minecraft) {
existing = mobEffect;
}
}
if (existing != null) {
if (hasCustomEffect(effect.getType())) {
if (!override) {
return false;
}
getHandle().effects.remove(existing);
removeCustomEffect(effect.getType());
}
getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
getHandle().updateColor();
@@ -161,14 +156,15 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public void clearCustomEffects() {
getHandle().effects.clear();
PotionContents old = getHandle().potionContents;
getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of()));
getHandle().updateColor();
}
@Override
public List<PotionEffect> getCustomEffects() {
ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
for (MobEffect effect : getHandle().effects) {
for (MobEffect effect : getHandle().potionContents.customEffects()) {
builder.add(CraftPotionUtil.toBukkit(effect));
}
return builder.build();
@@ -176,7 +172,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public boolean hasCustomEffect(PotionEffectType type) {
for (MobEffect effect : getHandle().effects) {
for (MobEffect effect : getHandle().potionContents.customEffects()) {
if (CraftPotionUtil.equals(effect.getEffect(), type)) {
return true;
}
@@ -186,50 +182,34 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public boolean hasCustomEffects() {
return !getHandle().effects.isEmpty();
return !getHandle().potionContents.customEffects().isEmpty();
}
@Override
public boolean removeCustomEffect(PotionEffectType effect) {
MobEffectList minecraft = CraftPotionEffectType.bukkitToMinecraft(effect);
MobEffect existing = null;
for (MobEffect mobEffect : getHandle().effects) {
if (mobEffect.getEffect() == minecraft) {
existing = mobEffect;
}
}
if (existing == null) {
if (!hasCustomEffect(effect)) {
return false;
}
getHandle().effects.remove(existing);
getHandle().updateColor();
Holder<MobEffectList> minecraft = CraftPotionEffectType.bukkitToMinecraftHolder(effect);
PotionContents old = getHandle().potionContents;
getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), old.customEffects().stream().filter((mobEffect) -> !mobEffect.getEffect().equals(minecraft)).toList()));
return true;
}
@Override
public void setBasePotionData(PotionData data) {
Preconditions.checkArgument(data != null, "PotionData cannot be null");
getHandle().setPotion(CraftPotionType.bukkitToMinecraft(CraftPotionUtil.fromBukkit(data)));
public void setBasePotionType(PotionType potionType) {
if (potionType != null) {
getHandle().setPotionContents(getHandle().potionContents.withPotion(CraftPotionType.bukkitToMinecraftHolder(potionType)));
} else {
PotionContents old = getHandle().potionContents;
getHandle().setPotionContents(new PotionContents(Optional.empty(), old.customColor(), old.customEffects()));
}
}
@Override
public PotionData getBasePotionData() {
return CraftPotionUtil.toBukkit(CraftPotionType.minecraftToBukkit(getHandle().getPotion()));
}
@Override
public void setBasePotionType(@NotNull PotionType potionType) {
// TODO: 10/6/23 Change PotionType.UNCRAFTABLE to PotionType.EMPTY in error message
Preconditions.checkArgument(potionType != null, "PotionType cannot be null use PotionType.UNCRAFTABLE to represent no effect instead.");
getHandle().setPotion(CraftPotionType.bukkitToMinecraft(potionType));
}
@NotNull
@Override
public PotionType getBasePotionType() {
return CraftPotionType.minecraftToBukkit(getHandle().getPotion());
return getHandle().potionContents.potion().map(CraftPotionType::minecraftHolderToBukkit).orElse(null);
}
@Override

View File

@@ -0,0 +1,21 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Armadillo;
public class CraftArmadillo extends CraftAnimals implements Armadillo {
public CraftArmadillo(CraftServer server, net.minecraft.world.entity.animal.armadillo.Armadillo entity) {
super(server, entity);
}
@Override
public net.minecraft.world.entity.animal.armadillo.Armadillo getHandle() {
return (net.minecraft.world.entity.animal.armadillo.Armadillo) super.getHandle();
}
@Override
public String toString() {
return "CraftArmadillo";
}
}

View File

@@ -0,0 +1,27 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Bogged;
import org.bukkit.entity.Skeleton;
public class CraftBogged extends CraftAbstractSkeleton implements Bogged {
public CraftBogged(CraftServer server, net.minecraft.world.entity.monster.Bogged entity) {
super(server, entity);
}
@Override
public net.minecraft.world.entity.monster.Bogged getHandle() {
return (net.minecraft.world.entity.monster.Bogged) entity;
}
@Override
public String toString() {
return "CraftBogged";
}
@Override
public Skeleton.SkeletonType getSkeletonType() {
return Skeleton.SkeletonType.BOGGED;
}
}

View File

@@ -0,0 +1,20 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.BreezeWindCharge;
public class CraftBreezeWindCharge extends CraftAbstractWindCharge implements BreezeWindCharge {
public CraftBreezeWindCharge(CraftServer server, net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge entity) {
super(server, entity);
}
@Override
public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge getHandle() {
return (net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge) this.entity;
}
@Override
public String toString() {
return "CraftBreezeWindCharge";
}
}

View File

@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.CatVariant;
@@ -31,14 +32,14 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
@Override
public Type getCatType() {
return CraftType.minecraftToBukkit(getHandle().getVariant());
return CraftType.minecraftHolderToBukkit(getHandle().getVariant());
}
@Override
public void setCatType(Type type) {
Preconditions.checkArgument(type != null, "Cannot have null Type");
getHandle().setVariant(CraftType.bukkitToMinecraft(type));
getHandle().setVariant(CraftType.bukkitToMinecraftHolder(type));
}
@Override
@@ -61,6 +62,10 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
return Registry.CAT_VARIANT.get(CraftNamespacedKey.fromMinecraft(registry.getKey(minecraft)));
}
public static Type minecraftHolderToBukkit(Holder<CatVariant> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static CatVariant bukkitToMinecraft(Type bukkit) {
Preconditions.checkArgument(bukkit != null);
@@ -68,5 +73,18 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
return registry.get(CraftNamespacedKey.toMinecraft(bukkit.getKey()));
}
public static Holder<CatVariant> bukkitToMinecraftHolder(Type bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<CatVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.CAT_VARIANT);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<CatVariant> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own cat variant with out properly registering it.");
}
}
}

View File

@@ -1,12 +1,9 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.entity.vehicle.ChestBoat;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.Inventory;
import org.bukkit.loot.LootTable;
@@ -41,13 +38,7 @@ public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.Chest
@Override
public LootTable getLootTable() {
MinecraftKey nmsTable = getHandle().getLootTable();
if (nmsTable == null) {
return null; // return empty loot table?
}
NamespacedKey key = CraftNamespacedKey.fromMinecraft(nmsTable);
return Bukkit.getLootTable(key);
return CraftLootTable.minecraftToBukkit(getHandle().getLootTable());
}
@Override
@@ -61,8 +52,7 @@ public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.Chest
}
private void setLootTable(LootTable table, long seed) {
MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
getHandle().setLootTable(newKey);
getHandle().setLootTable(CraftLootTable.bukkitToMinecraft(table));
getHandle().setLootTableSeed(seed);
}
}

View File

@@ -50,6 +50,7 @@ import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.Allay;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.Armadillo;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Axolotl;
@@ -58,7 +59,9 @@ import org.bukkit.entity.Bee;
import org.bukkit.entity.Blaze;
import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Bogged;
import org.bukkit.entity.Breeze;
import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Camel;
import org.bukkit.entity.Cat;
import org.bukkit.entity.CaveSpider;
@@ -115,6 +118,7 @@ import org.bukkit.entity.Marker;
import org.bukkit.entity.Mule;
import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.OminousItemSpawner;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Panda;
import org.bukkit.entity.Parrot;
@@ -223,7 +227,7 @@ public final class CraftEntityTypes {
private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> MOVE_EMPTY_ROT = (spawnData, entity) -> entity.moveTo(spawnData.x(), spawnData.y(), spawnData.z(), 0, 0);
private static final BiConsumer<SpawnData, EntityFireball> DIRECTION = (spawnData, entity) -> {
Vector direction = spawnData.location().getDirection().multiply(10);
entity.setDirection(direction.getX(), direction.getY(), direction.getZ());
entity.assignPower(direction.getX(), direction.getY(), direction.getZ());
};
private static final Map<Class<?>, EntityTypeData<?, ?>> CLASS_TYPE_DATA = new HashMap<>();
private static final Map<EntityType, EntityTypeData<?, ?>> ENTITY_TYPE_DATA = new HashMap<>();
@@ -233,6 +237,7 @@ public final class CraftEntityTypes {
register(new EntityTypeData<>(EntityType.ELDER_GUARDIAN, ElderGuardian.class, CraftElderGuardian::new, createLiving(EntityTypes.ELDER_GUARDIAN)));
register(new EntityTypeData<>(EntityType.WITHER_SKELETON, WitherSkeleton.class, CraftWitherSkeleton::new, createLiving(EntityTypes.WITHER_SKELETON)));
register(new EntityTypeData<>(EntityType.STRAY, Stray.class, CraftStray::new, createLiving(EntityTypes.STRAY)));
register(new EntityTypeData<>(EntityType.BOGGED, Bogged.class, CraftBogged::new, createLiving(EntityTypes.BOGGED)));
register(new EntityTypeData<>(EntityType.HUSK, Husk.class, CraftHusk::new, createLiving(EntityTypes.HUSK)));
register(new EntityTypeData<>(EntityType.ZOMBIE_VILLAGER, ZombieVillager.class, CraftVillagerZombie::new, createLiving(EntityTypes.ZOMBIE_VILLAGER)));
register(new EntityTypeData<>(EntityType.SKELETON_HORSE, SkeletonHorse.class, CraftSkeletonHorse::new, createLiving(EntityTypes.SKELETON_HORSE)));
@@ -310,6 +315,7 @@ public final class CraftEntityTypes {
register(new EntityTypeData<>(EntityType.CAMEL, Camel.class, CraftCamel::new, createLiving(EntityTypes.CAMEL)));
register(new EntityTypeData<>(EntityType.SNIFFER, Sniffer.class, CraftSniffer::new, createLiving(EntityTypes.SNIFFER)));
register(new EntityTypeData<>(EntityType.BREEZE, Breeze.class, CraftBreeze::new, createLiving(EntityTypes.BREEZE)));
register(new EntityTypeData<>(EntityType.ARMADILLO, Armadillo.class, CraftArmadillo::new, createLiving(EntityTypes.ARMADILLO)));
Function<SpawnData, EntityEnderDragon> dragonFunction = createLiving(EntityTypes.ENDER_DRAGON);
register(new EntityTypeData<>(EntityType.ENDER_DRAGON, EnderDragon.class, CraftEnderDragon::new, spawnData -> {
@@ -323,6 +329,7 @@ public final class CraftEntityTypes {
register(new EntityTypeData<>(EntityType.WITHER_SKULL, WitherSkull.class, CraftWitherSkull::new, createFireball(EntityTypes.WITHER_SKULL)));
register(new EntityTypeData<>(EntityType.DRAGON_FIREBALL, DragonFireball.class, CraftDragonFireball::new, createFireball(EntityTypes.DRAGON_FIREBALL)));
register(new EntityTypeData<>(EntityType.WIND_CHARGE, WindCharge.class, CraftWindCharge::new, createFireball(EntityTypes.WIND_CHARGE)));
register(new EntityTypeData<>(EntityType.BREEZE_WIND_CHARGE, BreezeWindCharge.class, CraftBreezeWindCharge::new, createFireball(EntityTypes.BREEZE_WIND_CHARGE)));
// Hanging
register(new EntityTypeData<>(EntityType.PAINTING, Painting.class, CraftPainting::new, createHanging(Painting.class, (spawnData, hangingData) -> {
@@ -353,6 +360,7 @@ public final class CraftEntityTypes {
register(new EntityTypeData<>(EntityType.BOAT, Boat.class, CraftBoat::new, createAndMove(EntityTypes.BOAT)));
register(new EntityTypeData<>(EntityType.LLAMA_SPIT, LlamaSpit.class, CraftLlamaSpit::new, createAndMove(EntityTypes.LLAMA_SPIT)));
register(new EntityTypeData<>(EntityType.CHEST_BOAT, ChestBoat.class, CraftChestBoat::new, createAndMove(EntityTypes.CHEST_BOAT)));
register(new EntityTypeData<>(EntityType.OMINOUS_ITEM_SPAWNER, OminousItemSpawner.class, CraftOminousItemSpawner::new, createAndMove(EntityTypes.OMINOUS_ITEM_SPAWNER)));
// Set pos
register(new EntityTypeData<>(EntityType.MARKER, Marker.class, CraftMarker::new, createAndSetPos(EntityTypes.MARKER)));

View File

@@ -55,7 +55,7 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
@Override
public void setDirection(Vector direction) {
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
getHandle().setDirection(direction.getX(), direction.getY(), direction.getZ());
getHandle().assignPower(direction.getX(), direction.getY(), direction.getZ());
update(); // SPIGOT-6579
}

View File

@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.FrogVariant;
@@ -43,14 +44,14 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
@Override
public Variant getVariant() {
return CraftVariant.minecraftToBukkit(getHandle().getVariant());
return CraftVariant.minecraftHolderToBukkit(getHandle().getVariant());
}
@Override
public void setVariant(Variant variant) {
Preconditions.checkArgument(variant != null, "variant");
getHandle().setVariant(CraftVariant.bukkitToMinecraft(variant));
getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant));
}
public static class CraftVariant {
@@ -66,11 +67,28 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
return bukkit;
}
public static Variant minecraftHolderToBukkit(Holder<FrogVariant> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static FrogVariant bukkitToMinecraft(Variant bukkit) {
Preconditions.checkArgument(bukkit != null);
return CraftRegistry.getMinecraftRegistry(Registries.FROG_VARIANT)
.getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
}
public static Holder<FrogVariant> bukkitToMinecraftHolder(Variant bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<FrogVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.FROG_VARIANT);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<FrogVariant> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own frog variant with out properly registering it.");
}
}
}

View File

@@ -26,8 +26,6 @@ import net.minecraft.world.item.crafting.CraftingManager;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.trading.IMerchant;
import net.minecraft.world.level.block.BlockBed;
import net.minecraft.world.level.block.BlockEnchantmentTable;
import net.minecraft.world.level.block.BlockWorkbench;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.TileEntity;
import net.minecraft.world.level.block.state.IBlockData;
@@ -342,7 +340,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
return null;
}
}
getHandle().openMenu(((BlockWorkbench) Blocks.CRAFTING_TABLE).getMenuProvider(null, getHandle().level(), CraftLocation.toBlockPosition(location)));
getHandle().openMenu(Blocks.CRAFTING_TABLE.defaultBlockState().getMenuProvider(getHandle().level(), CraftLocation.toBlockPosition(location)));
if (force) {
getHandle().containerMenu.checkReachable = false;
}
@@ -363,7 +361,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
// If there isn't an enchant table we can force create one, won't be very useful though.
BlockPosition pos = CraftLocation.toBlockPosition(location);
getHandle().openMenu(((BlockEnchantmentTable) Blocks.ENCHANTING_TABLE).getMenuProvider(null, getHandle().level(), pos));
getHandle().openMenu(Blocks.ENCHANTING_TABLE.defaultBlockState().getMenuProvider(getHandle().level(), pos));
if (force) {
getHandle().containerMenu.checkReachable = false;

View File

@@ -17,7 +17,6 @@ import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.EntityInsentient;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMonsterType;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.boss.wither.EntityWither;
import net.minecraft.world.entity.decoration.EntityArmorStand;
@@ -159,7 +158,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public void resetMaxHealth() {
setMaxHealth(getHandle().getAttribute(GenericAttributes.MAX_HEALTH).getAttribute().getDefaultValue());
setMaxHealth(getHandle().getAttribute(GenericAttributes.MAX_HEALTH).getAttribute().value().getDefaultValue());
}
@Override
@@ -401,7 +400,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public boolean addPotionEffect(PotionEffect effect, boolean force) {
getHandle().addEffect(new MobEffect(CraftPotionEffectType.bukkitToMinecraft(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN);
getHandle().addEffect(new MobEffect(CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN);
return true;
}
@@ -416,25 +415,25 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public boolean hasPotionEffect(PotionEffectType type) {
return getHandle().hasEffect(CraftPotionEffectType.bukkitToMinecraft(type));
return getHandle().hasEffect(CraftPotionEffectType.bukkitToMinecraftHolder(type));
}
@Override
public PotionEffect getPotionEffect(PotionEffectType type) {
MobEffect handle = getHandle().getEffect(CraftPotionEffectType.bukkitToMinecraft(type));
return (handle == null) ? null : new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible());
MobEffect handle = getHandle().getEffect(CraftPotionEffectType.bukkitToMinecraftHolder(type));
return (handle == null) ? null : new PotionEffect(CraftPotionEffectType.minecraftHolderToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible());
}
@Override
public void removePotionEffect(PotionEffectType type) {
getHandle().removeEffect(CraftPotionEffectType.bukkitToMinecraft(type), EntityPotionEffectEvent.Cause.PLUGIN);
getHandle().removeEffect(CraftPotionEffectType.bukkitToMinecraftHolder(type), EntityPotionEffectEvent.Cause.PLUGIN);
}
@Override
public Collection<PotionEffect> getActivePotionEffects() {
List<PotionEffect> effects = new ArrayList<PotionEffect>();
for (MobEffect handle : getHandle().activeEffects.values()) {
effects.add(new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible()));
effects.add(new PotionEffect(CraftPotionEffectType.minecraftHolderToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible()));
}
return effects;
}
@@ -499,8 +498,8 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
launch = new EntityDragonFireball(world, getHandle(), direction.getX(), direction.getY(), direction.getZ());
} else if (WindCharge.class.isAssignableFrom(projectile)) {
launch = EntityTypes.WIND_CHARGE.create(world);
((net.minecraft.world.entity.projectile.WindCharge) launch).setOwner(getHandle());
((net.minecraft.world.entity.projectile.WindCharge) launch).setDirection(direction.getX(), direction.getY(), direction.getZ());
((net.minecraft.world.entity.projectile.windcharge.WindCharge) launch).setOwner(getHandle());
((net.minecraft.world.entity.projectile.windcharge.WindCharge) launch).assignPower(direction.getX(), direction.getY(), direction.getZ());
} else {
launch = new EntityLargeFireball(world, getHandle(), direction.getX(), direction.getY(), direction.getZ(), 1);
}
@@ -795,21 +794,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public EntityCategory getCategory() {
EnumMonsterType type = getHandle().getMobType(); // Not actually an enum?
if (type == EnumMonsterType.UNDEFINED) {
return EntityCategory.NONE;
} else if (type == EnumMonsterType.UNDEAD) {
return EntityCategory.UNDEAD;
} else if (type == EnumMonsterType.ARTHROPOD) {
return EntityCategory.ARTHROPOD;
} else if (type == EnumMonsterType.ILLAGER) {
return EntityCategory.ILLAGER;
} else if (type == EnumMonsterType.WATER) {
return EntityCategory.WATER;
}
throw new UnsupportedOperationException("Unsupported monster type: " + type + ". This is a bug, report this to Spigot.");
throw new UnsupportedOperationException("Method longer applicable. Use Tags instead.");
}
@Override

View File

@@ -38,7 +38,7 @@ public class CraftMinecartCommand extends CraftMinecart implements CommandMineca
@Override
public void setName(String name) {
getHandle().getCommandBlock().setName(CraftChatMessage.fromStringOrNull(name));
getHandle().getCommandBlock().setCustomName(CraftChatMessage.fromStringOrNull(name));
}
@Override

View File

@@ -1,12 +1,9 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.entity.vehicle.EntityMinecartAbstract;
import net.minecraft.world.entity.vehicle.EntityMinecartContainer;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.Lootable;
@@ -28,13 +25,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo
@Override
public LootTable getLootTable() {
MinecraftKey nmsTable = getHandle().lootTable;
if (nmsTable == null) {
return null; // return empty loot table?
}
NamespacedKey key = CraftNamespacedKey.fromMinecraft(nmsTable);
return Bukkit.getLootTable(key);
return CraftLootTable.minecraftToBukkit(getHandle().lootTable);
}
@Override
@@ -48,7 +39,6 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo
}
private void setLootTable(LootTable table, long seed) {
MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
getHandle().setLootTable(newKey, seed);
getHandle().setLootTable(CraftLootTable.bukkitToMinecraft(table), seed);
}
}

View File

@@ -3,12 +3,10 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.world.entity.EntityInsentient;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftSound;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.loot.LootTable;
@@ -65,13 +63,12 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
@Override
public void setLootTable(LootTable table) {
getHandle().lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
getHandle().lootTable = CraftLootTable.bukkitToMinecraft(table);
}
@Override
public LootTable getLootTable() {
NamespacedKey key = CraftNamespacedKey.fromMinecraft(getHandle().getLootTable());
return Bukkit.getLootTable(key);
return CraftLootTable.minecraftToBukkit(getHandle().getLootTable());
}
@Override

View File

@@ -2,12 +2,12 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.core.Holder;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectList;
import net.minecraft.world.entity.animal.EntityMushroomCow;
import net.minecraft.world.level.block.SuspiciousEffectHolder;
import net.minecraft.world.item.component.SuspiciousStewEffects;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
@@ -22,13 +22,15 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow {
@Override
public boolean hasEffectsForNextStew() {
return this.getHandle().stewEffects != null && !this.getHandle().stewEffects.isEmpty();
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
return stewEffects != null && !stewEffects.effects().isEmpty();
}
@Override
public List<PotionEffect> getEffectsForNextStew() {
if (this.hasEffectsForNextStew()) {
return this.getHandle().stewEffects.stream().map(recordSuspiciousEffect -> CraftPotionUtil.toBukkit(recordSuspiciousEffect.createEffectInstance())).toList();
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
if (stewEffects != null) {
return stewEffects.effects().stream().map(recordSuspiciousEffect -> CraftPotionUtil.toBukkit(recordSuspiciousEffect.createEffectInstance())).toList();
}
return ImmutableList.of();
}
@@ -40,32 +42,42 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow {
if (!overwrite && this.hasEffectForNextStew(potionEffect.getType())) {
return false;
}
if (this.getHandle().stewEffects == null) {
this.getHandle().stewEffects = new ArrayList<>();
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
if (stewEffects == null) {
stewEffects = SuspiciousStewEffects.EMPTY;
}
SuspiciousEffectHolder.a recordSuspiciousEffect = new SuspiciousEffectHolder.a(minecraftPotionEffect.getEffect(), minecraftPotionEffect.getDuration());
SuspiciousStewEffects.a recordSuspiciousEffect = new SuspiciousStewEffects.a(minecraftPotionEffect.getEffect(), minecraftPotionEffect.getDuration());
this.removeEffectFromNextStew(potionEffect.getType()); // Avoid duplicates of effects
return this.getHandle().stewEffects.add(recordSuspiciousEffect);
getHandle().stewEffects = stewEffects.withEffectAdded(recordSuspiciousEffect);
return true;
}
@Override
public boolean removeEffectFromNextStew(PotionEffectType potionEffectType) {
Preconditions.checkArgument(potionEffectType != null, "potionEffectType cannot be null");
if (!this.hasEffectsForNextStew()) {
if (!hasEffectForNextStew(potionEffectType)) {
return false;
}
MobEffectList minecraftPotionEffectType = CraftPotionEffectType.bukkitToMinecraft(potionEffectType);
return this.getHandle().stewEffects.removeIf(recordSuspiciousEffect -> recordSuspiciousEffect.effect().equals(minecraftPotionEffectType));
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
if (stewEffects == null) {
return false;
}
Holder<MobEffectList> minecraftPotionEffectType = CraftPotionEffectType.bukkitToMinecraftHolder(potionEffectType);
getHandle().stewEffects = new SuspiciousStewEffects(stewEffects.effects().stream().filter((effect) -> !effect.effect().equals(minecraftPotionEffectType)).toList());
return true;
}
@Override
public boolean hasEffectForNextStew(PotionEffectType potionEffectType) {
Preconditions.checkArgument(potionEffectType != null, "potionEffectType cannot be null");
if (!this.hasEffectsForNextStew()) {
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
if (stewEffects == null) {
return false;
}
MobEffectList minecraftPotionEffectType = CraftPotionEffectType.bukkitToMinecraft(potionEffectType);
return this.getHandle().stewEffects.stream().anyMatch(recordSuspiciousEffect -> recordSuspiciousEffect.effect().equals(minecraftPotionEffectType));
Holder<MobEffectList> minecraftPotionEffectType = CraftPotionEffectType.bukkitToMinecraftHolder(potionEffectType);
return stewEffects.effects().stream().anyMatch(recordSuspiciousEffect -> recordSuspiciousEffect.effect().equals(minecraftPotionEffectType));
}
@Override

View File

@@ -0,0 +1,43 @@
package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.OminousItemSpawner;
import org.bukkit.inventory.ItemStack;
public class CraftOminousItemSpawner extends CraftEntity implements OminousItemSpawner {
public CraftOminousItemSpawner(CraftServer server, net.minecraft.world.entity.OminousItemSpawner entity) {
super(server, entity);
}
@Override
public net.minecraft.world.entity.OminousItemSpawner getHandle() {
return (net.minecraft.world.entity.OminousItemSpawner) entity;
}
@Override
public String toString() {
return "CraftOminousItemSpawner";
}
@Override
public ItemStack getItem() {
return CraftItemStack.asBukkitCopy(getHandle().getItem());
}
@Override
public void setItem(ItemStack item) {
getHandle().setItem(CraftItemStack.asNMSCopy(item));
}
@Override
public long getSpawnItemAfterTicks() {
return getHandle().spawnItemAfterTicks;
}
@Override
public void setSpawnItemAfterTicks(long ticks) {
getHandle().spawnItemAfterTicks = ticks;
}
}

View File

@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.io.BaseEncoding;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Pair;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.shorts.ShortArraySet;
import it.unimi.dsi.fastutil.shorts.ShortSet;
import java.io.ByteArrayOutputStream;
@@ -22,12 +23,15 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
@@ -36,13 +40,18 @@ import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.SectionPosition;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketDataSerializer;
import net.minecraft.network.EnumProtocol;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.chat.PlayerChatMessage;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
import net.minecraft.network.protocol.common.ClientboundResourcePackPopPacket;
import net.minecraft.network.protocol.common.ClientboundResourcePackPushPacket;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.network.protocol.common.ClientboundStoreCookiePacket;
import net.minecraft.network.protocol.common.ClientboundTransferPacket;
import net.minecraft.network.protocol.common.custom.DiscardedPayload;
import net.minecraft.network.protocol.cookie.ClientboundCookieRequestPacket;
import net.minecraft.network.protocol.cookie.ServerboundCookieResponsePacket;
import net.minecraft.network.protocol.game.ClientboundClearTitlesPacket;
import net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket;
import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket;
@@ -99,6 +108,7 @@ import net.minecraft.world.level.block.entity.TileEntitySign;
import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.border.IWorldBorderListener;
import net.minecraft.world.level.saveddata.maps.MapIcon;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.BanEntry;
@@ -148,6 +158,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.conversations.ConversationTracker;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.map.CraftMapCursor;
import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.craftbukkit.map.RenderData;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
@@ -244,7 +255,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public InetSocketAddress getAddress() {
if (getHandle().connection == null) return null;
if (getHandle().connection.protocol() == null) return null;
SocketAddress addr = getHandle().connection.getRemoteAddress();
if (addr instanceof InetSocketAddress) {
@@ -254,6 +265,74 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
}
public interface TransferCookieConnection {
boolean isTransferred();
EnumProtocol protocol();
void send(Packet<?> packet);
}
public record CookieFuture(MinecraftKey key, CompletableFuture<byte[]> future) {
}
private final Queue<CookieFuture> requestedCookies = new LinkedList<>();
public boolean isAwaitingCookies() {
return !requestedCookies.isEmpty();
}
public boolean handleCookieResponse(ServerboundCookieResponsePacket response) {
CookieFuture future = requestedCookies.peek();
if (future != null) {
if (future.key.equals(response.key())) {
Preconditions.checkState(future == requestedCookies.poll(), "requestedCookies queue mismatch");
future.future().complete(response.payload());
return true;
}
}
return false;
}
@Override
public boolean isTransferred() {
return getHandle().transferCookieConnection.isTransferred();
}
@Override
public CompletableFuture<byte[]> retrieveCookie(NamespacedKey key) {
Preconditions.checkArgument(key != null, "Cookie key cannot be null");
CompletableFuture<byte[]> future = new CompletableFuture<>();
MinecraftKey nms = CraftNamespacedKey.toMinecraft(key);
requestedCookies.add(new CookieFuture(nms, future));
getHandle().transferCookieConnection.send(new ClientboundCookieRequestPacket(nms));
return future;
}
@Override
public void storeCookie(NamespacedKey key, byte[] value) {
Preconditions.checkArgument(key != null, "Cookie key cannot be null");
Preconditions.checkArgument(value != null, "Cookie value cannot be null");
Preconditions.checkArgument(value.length <= 5120, "Cookie value too large, must be smaller than 5120 bytes");
Preconditions.checkState(getHandle().transferCookieConnection.protocol() == EnumProtocol.CONFIGURATION || getHandle().transferCookieConnection.protocol() == EnumProtocol.PLAY, "Can only store cookie in CONFIGURATION or PLAY protocol.");
getHandle().transferCookieConnection.send(new ClientboundStoreCookiePacket(CraftNamespacedKey.toMinecraft(key), value));
}
@Override
public void transfer(String host, int port) {
Preconditions.checkArgument(host != null, "Host cannot be null");
Preconditions.checkState(getHandle().transferCookieConnection.protocol() == EnumProtocol.CONFIGURATION || getHandle().transferCookieConnection.protocol() == EnumProtocol.PLAY, "Can only transfer in CONFIGURATION or PLAY protocol.");
getHandle().transferCookieConnection.send(new ClientboundTransferPacket(host, port));
}
@Override
public double getEyeHeight(boolean ignorePose) {
if (ignorePose) {
@@ -777,7 +856,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return;
}
getHandle().connection.send(new PacketPlayOutEntityEffect(entity.getEntityId(), CraftPotionUtil.fromBukkit(effect)));
getHandle().connection.send(new PacketPlayOutEntityEffect(entity.getEntityId(), CraftPotionUtil.fromBukkit(effect), true));
}
@Override
@@ -789,7 +868,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return;
}
getHandle().connection.send(new PacketPlayOutRemoveEntityEffect(entity.getEntityId(), CraftPotionEffectType.bukkitToMinecraft(type)));
getHandle().connection.send(new PacketPlayOutRemoveEntityEffect(entity.getEntityId(), CraftPotionEffectType.bukkitToMinecraftHolder(type)));
}
@Override
@@ -876,11 +955,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Collection<MapIcon> icons = new ArrayList<MapIcon>();
for (MapCursor cursor : data.cursors) {
if (cursor.isVisible()) {
icons.add(new MapIcon(MapIcon.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption())));
icons.add(new MapIcon(CraftMapCursor.CraftType.bukkitToMinecraftHolder(cursor.getType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrOptional(cursor.getCaption())));
}
}
PacketPlayOutMap packet = new PacketPlayOutMap(map.getId(), map.getScale().getValue(), map.isLocked(), icons, new WorldMap.b(0, 0, 128, 128, data.buffer));
PacketPlayOutMap packet = new PacketPlayOutMap(new MapId(map.getId()), map.getScale().getValue(), map.isLocked(), icons, new WorldMap.b(0, 0, 128, 128, data.buffer));
getHandle().connection.send(packet);
}
@@ -1716,17 +1795,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
private void sendCustomPayload(MinecraftKey id, byte[] message) {
ClientboundCustomPayloadPacket packet = new ClientboundCustomPayloadPacket(new CustomPacketPayload() {
@Override
public void write(PacketDataSerializer pds) {
pds.writeBytes(message);
}
@Override
public MinecraftKey id() {
return id;
}
});
ClientboundCustomPayloadPacket packet = new ClientboundCustomPayloadPacket(new DiscardedPayload(id, Unpooled.wrappedBuffer(message)));
getHandle().connection.send(packet);
}
@@ -1773,7 +1842,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
hashStr = BaseEncoding.base16().lowerCase().encode(hash);
}
this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrNull(prompt, true)), true);
this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrOptional(prompt, true)), true);
}
@Override
@@ -1786,7 +1855,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
hashStr = BaseEncoding.base16().lowerCase().encode(hash);
}
this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrNull(prompt, true)), false);
this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrOptional(prompt, true)), false);
}
@Override

View File

@@ -15,10 +15,10 @@ public class CraftSizedFireball extends CraftFireball implements SizedFireball {
@Override
public ItemStack getDisplayItem() {
if (getHandle().getItemRaw().isEmpty()) {
if (getHandle().getItem().isEmpty()) {
return new ItemStack(Material.FIRE_CHARGE);
} else {
return CraftItemStack.asBukkitCopy(getHandle().getItemRaw());
return CraftItemStack.asBukkitCopy(getHandle().getItem());
}
}

View File

@@ -62,7 +62,7 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat
@Override
public void setTamed(boolean tame) {
getHandle().setTame(tame);
getHandle().setTame(tame, true);
if (!tame) {
setOwnerUUID(null);
}

View File

@@ -14,10 +14,10 @@ public abstract class CraftThrowableProjectile extends CraftProjectile implement
@Override
public ItemStack getItem() {
if (getHandle().getItemRaw().isEmpty()) {
if (getHandle().getItem().isEmpty()) {
return CraftItemStack.asBukkitCopy(new net.minecraft.world.item.ItemStack(getHandle().getDefaultItemPublic()));
} else {
return CraftItemStack.asBukkitCopy(getHandle().getItemRaw());
return CraftItemStack.asBukkitCopy(getHandle().getItem());
}
}

View File

@@ -3,9 +3,10 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.projectile.EntityPotion;
import net.minecraft.world.item.alchemy.PotionUtil;
import net.minecraft.world.item.alchemy.PotionContents;
import org.bukkit.Material;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
@@ -22,7 +23,7 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
@Override
public Collection<PotionEffect> getEffects() {
ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
for (MobEffect effect : PotionUtil.getMobEffects(getHandle().getItemRaw())) {
for (MobEffect effect : getHandle().getItem().getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).customEffects()) {
builder.add(CraftPotionUtil.toBukkit(effect));
}
return builder.build();
@@ -30,7 +31,7 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
@Override
public ItemStack getItem() {
return CraftItemStack.asBukkitCopy(getHandle().getItemRaw());
return CraftItemStack.asBukkitCopy(getHandle().getItem());
}
@Override

View File

@@ -1,22 +1,22 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.Holder;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectList;
import net.minecraft.world.entity.projectile.EntityTippedArrow;
import net.minecraft.world.item.alchemy.PotionContents;
import org.bukkit.Color;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.craftbukkit.potion.CraftPotionType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.Arrow;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
public class CraftTippedArrow extends CraftArrow implements Arrow {
@@ -36,18 +36,11 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
@Override
public boolean addCustomEffect(PotionEffect effect, boolean override) {
MobEffectList minecraft = CraftPotionEffectType.bukkitToMinecraft(effect.getType());
MobEffect existing = null;
for (MobEffect mobEffect : getHandle().effects) {
if (mobEffect.getEffect() == minecraft) {
existing = mobEffect;
}
}
if (existing != null) {
if (hasCustomEffect(effect.getType())) {
if (!override) {
return false;
}
getHandle().effects.remove(existing);
removeCustomEffect(effect.getType());
}
getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
getHandle().updateColor();
@@ -56,14 +49,15 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
@Override
public void clearCustomEffects() {
getHandle().effects.clear();
PotionContents old = getHandle().getPotionContents();
getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of()));
getHandle().updateColor();
}
@Override
public List<PotionEffect> getCustomEffects() {
ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
for (MobEffect effect : getHandle().effects) {
for (MobEffect effect : getHandle().getPotionContents().customEffects()) {
builder.add(CraftPotionUtil.toBukkit(effect));
}
return builder.build();
@@ -71,7 +65,7 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
@Override
public boolean hasCustomEffect(PotionEffectType type) {
for (MobEffect effect : getHandle().effects) {
for (MobEffect effect : getHandle().getPotionContents().customEffects()) {
if (CraftPotionUtil.equals(effect.getEffect(), type)) {
return true;
}
@@ -81,55 +75,41 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
@Override
public boolean hasCustomEffects() {
return !getHandle().effects.isEmpty();
return !getHandle().getPotionContents().customEffects().isEmpty();
}
@Override
public boolean removeCustomEffect(PotionEffectType effect) {
MobEffectList minecraft = CraftPotionEffectType.bukkitToMinecraft(effect);
MobEffect existing = null;
for (MobEffect mobEffect : getHandle().effects) {
if (mobEffect.getEffect() == minecraft) {
existing = mobEffect;
}
}
if (existing == null) {
if (!hasCustomEffect(effect)) {
return false;
}
getHandle().effects.remove(existing);
getHandle().updateColor();
Holder<MobEffectList> minecraft = CraftPotionEffectType.bukkitToMinecraftHolder(effect);
PotionContents old = getHandle().getPotionContents();
getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), old.customEffects().stream().filter((mobEffect) -> !mobEffect.getEffect().equals(minecraft)).toList()));
return true;
}
@Override
public void setBasePotionData(PotionData data) {
Preconditions.checkArgument(data != null, "PotionData cannot be null");
this.getHandle().potion = CraftPotionType.bukkitToMinecraft(CraftPotionUtil.fromBukkit(data));
public void setBasePotionType(PotionType potionType) {
if (potionType != null) {
getHandle().setPotionContents(getHandle().getPotionContents().withPotion(CraftPotionType.bukkitToMinecraftHolder(potionType)));
} else {
PotionContents old = getHandle().getPotionContents();
getHandle().setPotionContents(new PotionContents(Optional.empty(), old.customColor(), old.customEffects()));
}
}
@Override
public PotionData getBasePotionData() {
return CraftPotionUtil.toBukkit(CraftPotionType.minecraftToBukkit(getHandle().potion));
}
@Override
public void setBasePotionType(@NotNull PotionType potionType) {
// TODO: 10/6/23 Change PotionType.UNCRAFTABLE to PotionType.EMPTY in error message
Preconditions.checkArgument(potionType != null, "PotionType cannot be null use PotionType.UNCRAFTABLE to represent no effect instead.");
getHandle().potion = CraftPotionType.bukkitToMinecraft(potionType);
}
@NotNull
@Override
public PotionType getBasePotionType() {
return CraftPotionType.minecraftToBukkit(getHandle().potion);
return getHandle().getPotionContents().potion().map(CraftPotionType::minecraftHolderToBukkit).orElse(null);
}
@Override
public void setColor(Color color) {
int colorRGB = (color == null) ? -1 : color.asRGB();
getHandle().setFixedColor(colorRGB);
PotionContents old = getHandle().getPotionContents();
getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(colorRGB), old.customEffects()));
}
@Override

View File

@@ -2,22 +2,15 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.WindCharge;
import org.bukkit.event.entity.EntityRemoveEvent;
public class CraftWindCharge extends CraftFireball implements WindCharge {
public CraftWindCharge(CraftServer server, net.minecraft.world.entity.projectile.WindCharge entity) {
public class CraftWindCharge extends CraftAbstractWindCharge implements WindCharge {
public CraftWindCharge(CraftServer server, net.minecraft.world.entity.projectile.windcharge.WindCharge entity) {
super(server, entity);
}
@Override
public void explode() {
this.getHandle().explode();
this.getHandle().discard(EntityRemoveEvent.Cause.EXPLODE); // SPIGOT-7577 - explode doesn't discard the entity, this happens only in tick and onHitBlock
}
@Override
public net.minecraft.world.entity.projectile.WindCharge getHandle() {
return (net.minecraft.world.entity.projectile.WindCharge) this.entity;
public net.minecraft.world.entity.projectile.windcharge.WindCharge getHandle() {
return (net.minecraft.world.entity.projectile.windcharge.WindCharge) this.entity;
}
@Override

View File

@@ -1,9 +1,17 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.EntityWolf;
import net.minecraft.world.entity.animal.WolfVariant;
import net.minecraft.world.item.EnumColor;
import org.bukkit.DyeColor;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.entity.Wolf;
public class CraftWolf extends CraftTameableAnimal implements Wolf {
@@ -59,4 +67,54 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
public void setInterested(boolean flag) {
getHandle().setIsInterested(flag);
}
@Override
public Variant getVariant() {
return CraftVariant.minecraftHolderToBukkit(getHandle().getVariant());
}
@Override
public void setVariant(Variant variant) {
Preconditions.checkArgument(variant != null, "variant");
getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant));
}
public static class CraftVariant {
public static Variant minecraftToBukkit(WolfVariant minecraft) {
Preconditions.checkArgument(minecraft != null);
IRegistry<WolfVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.WOLF_VARIANT);
Variant bukkit = Registry.WOLF_VARIANT.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location()));
Preconditions.checkArgument(bukkit != null);
return bukkit;
}
public static Variant minecraftHolderToBukkit(Holder<WolfVariant> minecraft) {
return minecraftToBukkit(minecraft.value());
}
public static WolfVariant bukkitToMinecraft(Variant bukkit) {
Preconditions.checkArgument(bukkit != null);
return CraftRegistry.getMinecraftRegistry(Registries.WOLF_VARIANT)
.getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
}
public static Holder<WolfVariant> bukkitToMinecraftHolder(Variant bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<WolfVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.WOLF_VARIANT);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<WolfVariant> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own wolf variant with out properly registering it.");
}
}
}

View File

@@ -103,7 +103,6 @@ import org.bukkit.craftbukkit.entity.CraftSpellcaster;
import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.craftbukkit.inventory.CraftMetaBook;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.CraftVector;
@@ -1422,7 +1421,7 @@ public class CraftEventFactory {
if (editBookEvent.isSigning()) {
itemInHand.setItem(Items.WRITTEN_BOOK);
}
CraftMetaBook meta = (CraftMetaBook) editBookEvent.getNewBookMeta();
BookMeta meta = editBookEvent.getNewBookMeta();
CraftItemStack.setItemMeta(itemInHand, meta);
} else {
player.getBukkitEntity().updateInventory(); // SPIGOT-7484

View File

@@ -14,9 +14,9 @@ import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.level.ChunkCoordIntPair;
import net.minecraft.world.level.GeneratorAccessSeed;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.bukkit.HeightMap;
import org.bukkit.Location;
import org.bukkit.Material;

View File

@@ -1,7 +1,7 @@
package org.bukkit.craftbukkit.generator;
import com.google.common.base.Preconditions;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
@@ -334,7 +334,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
}
@Override
protected Codec<? extends net.minecraft.world.level.chunk.ChunkGenerator> codec() {
return Codec.unit(null);
protected MapCodec<? extends net.minecraft.world.level.chunk.ChunkGenerator> codec() {
return MapCodec.unit(null);
}
}

View File

@@ -1,7 +1,7 @@
package org.bukkit.craftbukkit.generator;
import com.google.common.base.Preconditions;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
@@ -39,7 +39,7 @@ public class CustomWorldChunkManager extends WorldChunkManager {
}
@Override
protected Codec<? extends WorldChunkManager> codec() {
protected MapCodec<? extends WorldChunkManager> codec() {
throw new UnsupportedOperationException("Cannot serialize CustomWorldChunkManager");
}

View File

@@ -4,8 +4,8 @@ import com.google.common.base.Preconditions;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.arguments.item.ArgumentParserItemStack;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.item.Item;
@@ -18,6 +18,7 @@ import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftEntityType;
import org.bukkit.craftbukkit.inventory.components.CraftFoodComponent;
import org.bukkit.craftbukkit.util.CraftLegacy;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -32,7 +33,9 @@ public final class CraftItemFactory implements ItemFactory {
static {
instance = new CraftItemFactory();
ConfigurationSerialization.registerClass(CraftMetaItem.SerializableMeta.class);
ConfigurationSerialization.registerClass(SerializableMeta.class);
ConfigurationSerialization.registerClass(CraftFoodComponent.class);
ConfigurationSerialization.registerClass(CraftFoodComponent.CraftFoodEffect.class);
}
private CraftItemFactory() {
@@ -114,6 +117,7 @@ public final class CraftItemFactory implements ItemFactory {
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
case WOLF_ARMOR:
return meta instanceof CraftMetaColorableArmor ? meta : new CraftMetaColorableArmor(meta);
case LEATHER_HORSE_ARMOR:
return meta instanceof CraftMetaLeatherArmor ? meta : new CraftMetaLeatherArmor(meta);
@@ -163,11 +167,13 @@ public final class CraftItemFactory implements ItemFactory {
case YELLOW_BANNER:
case YELLOW_WALL_BANNER:
return meta instanceof CraftMetaBanner ? meta : new CraftMetaBanner(meta);
case ARMADILLO_SPAWN_EGG:
case ALLAY_SPAWN_EGG:
case AXOLOTL_SPAWN_EGG:
case BAT_SPAWN_EGG:
case BEE_SPAWN_EGG:
case BLAZE_SPAWN_EGG:
case BOGGED_SPAWN_EGG:
case BREEZE_SPAWN_EGG:
case CAT_SPAWN_EGG:
case CAMEL_SPAWN_EGG:
@@ -346,6 +352,7 @@ public final class CraftItemFactory implements ItemFactory {
case SUSPICIOUS_GRAVEL:
case CRAFTER:
case TRIAL_SPAWNER:
case VAULT:
return new CraftMetaBlockState(meta, material);
case TROPICAL_FISH_BUCKET:
return meta instanceof CraftMetaTropicalFishBucket ? meta : new CraftMetaTropicalFishBucket(meta);
@@ -368,6 +375,8 @@ public final class CraftItemFactory implements ItemFactory {
return meta instanceof CraftMetaBundle ? meta : new CraftMetaBundle(meta);
case GOAT_HORN:
return meta instanceof CraftMetaMusicInstrument ? meta : new CraftMetaMusicInstrument(meta);
case OMINOUS_BOTTLE:
return meta instanceof CraftMetaOminousBottle ? meta : new CraftMetaOminousBottle(meta);
default:
return new CraftMetaItem(meta);
}
@@ -431,14 +440,14 @@ public final class CraftItemFactory implements ItemFactory {
@Override
public ItemStack createItemStack(String input) throws IllegalArgumentException {
try {
ArgumentParserItemStack.a arg = ArgumentParserItemStack.parseForItem(BuiltInRegistries.ITEM.asLookup(), new StringReader(input));
ArgumentParserItemStack.a arg = new ArgumentParserItemStack(MinecraftServer.getDefaultRegistryAccess()).parse(new StringReader(input));
Item item = arg.item().value();
net.minecraft.world.item.ItemStack nmsItemStack = new net.minecraft.world.item.ItemStack(item);
NBTTagCompound nbt = arg.nbt();
DataComponentMap nbt = arg.components();
if (nbt != null) {
nmsItemStack.setTag(nbt);
nmsItemStack.applyComponents(nbt);
}
return CraftItemStack.asCraftMirror(nmsItemStack);
@@ -491,6 +500,6 @@ public final class CraftItemFactory implements ItemFactory {
Preconditions.checkArgument(!itemStack.getType().isAir(), "ItemStack must not be air");
itemStack = CraftItemStack.asCraftCopy(itemStack);
CraftItemStack craft = (CraftItemStack) itemStack;
return CraftItemStack.asCraftMirror(EnchantmentManager.enchantItem(source, craft.handle, level, allowTreasures));
return CraftItemStack.asCraftMirror(EnchantmentManager.enchantItem(MinecraftServer.getServer().getWorldData().enabledFeatures(), source, craft.handle, level, allowTreasures));
}
}

View File

@@ -1,20 +1,19 @@
package org.bukkit.craftbukkit.inventory;
import static org.bukkit.craftbukkit.inventory.CraftMetaItem.*;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.enchantment.EnchantmentManager;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.util.CraftLegacy;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@@ -171,7 +170,7 @@ public final class CraftItemStack extends ItemStack {
@Override
public int getMaxStackSize() {
return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize();
return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getMaxStackSize();
}
@Override
@@ -181,25 +180,13 @@ public final class CraftItemStack extends ItemStack {
if (!makeTag(handle)) {
return;
}
NBTTagList list = getEnchantmentList(handle);
ItemEnchantments list = getEnchantmentList(handle);
if (list == null) {
list = new NBTTagList();
handle.getTag().put(ENCHANTMENTS.NBT, list);
list = ItemEnchantments.EMPTY;
}
int size = list.size();
for (int i = 0; i < size; i++) {
NBTTagCompound tag = (NBTTagCompound) list.get(i);
String id = tag.getString(ENCHANTMENTS_ID.NBT);
if (ench.getKey().equals(NamespacedKey.fromString(id))) {
tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level);
return;
}
}
NBTTagCompound tag = new NBTTagCompound();
tag.putString(ENCHANTMENTS_ID.NBT, ench.getKey().toString());
tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level);
list.add(tag);
ItemEnchantments.a listCopy = new ItemEnchantments.a(list);
listCopy.set(CraftEnchantment.bukkitToMinecraft(ench), level);
handle.set(DataComponents.ENCHANTMENTS, listCopy.toImmutable());
}
static boolean makeTag(net.minecraft.world.item.ItemStack item) {
@@ -207,10 +194,6 @@ public final class CraftItemStack extends ItemStack {
return false;
}
if (item.getTag() == null) {
item.setTag(new NBTTagCompound());
}
return true;
}
@@ -232,50 +215,31 @@ public final class CraftItemStack extends ItemStack {
public int removeEnchantment(Enchantment ench) {
Preconditions.checkArgument(ench != null, "Enchantment cannot be null");
NBTTagList list = getEnchantmentList(handle), listCopy;
ItemEnchantments list = getEnchantmentList(handle);
if (list == null) {
return 0;
}
int index = Integer.MIN_VALUE;
int level = Integer.MIN_VALUE;
int size = list.size();
for (int i = 0; i < size; i++) {
NBTTagCompound enchantment = (NBTTagCompound) list.get(i);
String id = enchantment.getString(ENCHANTMENTS_ID.NBT);
if (ench.getKey().equals(NamespacedKey.fromString(id))) {
index = i;
level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT);
break;
}
}
if (index == Integer.MIN_VALUE) {
int level = getEnchantmentLevel(ench);
if (level <= 0) {
return 0;
}
int size = list.size();
if (size == 1) {
handle.getTag().remove(ENCHANTMENTS.NBT);
if (handle.getTag().isEmpty()) {
handle.setTag(null);
}
handle.remove(DataComponents.ENCHANTMENTS);
return level;
}
// This is workaround for not having an index removal
listCopy = new NBTTagList();
for (int i = 0; i < size; i++) {
if (i != index) {
listCopy.add(list.get(i));
}
}
handle.getTag().put(ENCHANTMENTS.NBT, listCopy);
ItemEnchantments.a listCopy = new ItemEnchantments.a(list);
listCopy.set(CraftEnchantment.bukkitToMinecraft(ench), -1); // Negative to remove
handle.set(DataComponents.ENCHANTMENTS, listCopy.toImmutable());
return level;
}
@Override
public void removeEnchantments() {
handle.getTag().remove(ENCHANTMENTS.NBT);
handle.remove(DataComponents.ENCHANTMENTS);
}
@Override
@@ -284,7 +248,7 @@ public final class CraftItemStack extends ItemStack {
}
static Map<Enchantment, Integer> getEnchantments(net.minecraft.world.item.ItemStack item) {
NBTTagList list = (item != null && item.isEnchanted()) ? item.getEnchantmentTags() : null;
ItemEnchantments list = (item != null && item.isEnchanted()) ? item.get(DataComponents.ENCHANTMENTS) : null;
if (list == null || list.size() == 0) {
return ImmutableMap.of();
@@ -292,21 +256,21 @@ public final class CraftItemStack extends ItemStack {
ImmutableMap.Builder<Enchantment, Integer> result = ImmutableMap.builder();
for (int i = 0; i < list.size(); i++) {
String id = ((NBTTagCompound) list.get(i)).getString(ENCHANTMENTS_ID.NBT);
int level = 0xffff & ((NBTTagCompound) list.get(i)).getShort(ENCHANTMENTS_LVL.NBT);
list.entrySet().forEach((entry) -> {
Holder<net.minecraft.world.item.enchantment.Enchantment> id = entry.getKey();
int level = entry.getIntValue();
Enchantment enchant = Enchantment.getByKey(CraftNamespacedKey.fromStringOrNull(id));
Enchantment enchant = CraftEnchantment.minecraftHolderToBukkit(id);
if (enchant != null) {
result.put(enchant, level);
}
}
});
return result.build();
}
static NBTTagList getEnchantmentList(net.minecraft.world.item.ItemStack item) {
return (item != null && item.isEnchanted()) ? item.getEnchantmentTags() : null;
static ItemEnchantments getEnchantmentList(net.minecraft.world.item.ItemStack item) {
return (item != null && item.isEnchanted()) ? item.get(DataComponents.ENCHANTMENTS) : null;
}
@Override
@@ -329,9 +293,9 @@ public final class CraftItemStack extends ItemStack {
}
switch (getType(item)) {
case WRITTEN_BOOK:
return new CraftMetaBookSigned(item.getTag());
return new CraftMetaBookSigned(item.getComponentsPatch());
case WRITABLE_BOOK:
return new CraftMetaBook(item.getTag());
return new CraftMetaBook(item.getComponentsPatch());
case CREEPER_HEAD:
case CREEPER_WALL_HEAD:
case DRAGON_HEAD:
@@ -346,7 +310,7 @@ public final class CraftItemStack extends ItemStack {
case WITHER_SKELETON_WALL_SKULL:
case ZOMBIE_HEAD:
case ZOMBIE_WALL_HEAD:
return new CraftMetaSkull(item.getTag());
return new CraftMetaSkull(item.getComponentsPatch());
case CHAINMAIL_HELMET:
case CHAINMAIL_CHESTPLATE:
case CHAINMAIL_LEGGINGS:
@@ -368,27 +332,28 @@ public final class CraftItemStack extends ItemStack {
case NETHERITE_LEGGINGS:
case NETHERITE_BOOTS:
case TURTLE_HELMET:
return new CraftMetaArmor(item.getTag());
return new CraftMetaArmor(item.getComponentsPatch());
case LEATHER_HELMET:
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
return new CraftMetaColorableArmor(item.getTag());
case WOLF_ARMOR:
return new CraftMetaColorableArmor(item.getComponentsPatch());
case LEATHER_HORSE_ARMOR:
return new CraftMetaLeatherArmor(item.getTag());
return new CraftMetaLeatherArmor(item.getComponentsPatch());
case POTION:
case SPLASH_POTION:
case LINGERING_POTION:
case TIPPED_ARROW:
return new CraftMetaPotion(item.getTag());
return new CraftMetaPotion(item.getComponentsPatch());
case FILLED_MAP:
return new CraftMetaMap(item.getTag());
return new CraftMetaMap(item.getComponentsPatch());
case FIREWORK_ROCKET:
return new CraftMetaFirework(item.getTag());
return new CraftMetaFirework(item.getComponentsPatch());
case FIREWORK_STAR:
return new CraftMetaCharge(item.getTag());
return new CraftMetaCharge(item.getComponentsPatch());
case ENCHANTED_BOOK:
return new CraftMetaEnchantedBook(item.getTag());
return new CraftMetaEnchantedBook(item.getComponentsPatch());
case BLACK_BANNER:
case BLACK_WALL_BANNER:
case BLUE_BANNER:
@@ -421,12 +386,14 @@ public final class CraftItemStack extends ItemStack {
case WHITE_WALL_BANNER:
case YELLOW_BANNER:
case YELLOW_WALL_BANNER:
return new CraftMetaBanner(item.getTag());
return new CraftMetaBanner(item.getComponentsPatch());
case ARMADILLO_SPAWN_EGG:
case ALLAY_SPAWN_EGG:
case AXOLOTL_SPAWN_EGG:
case BAT_SPAWN_EGG:
case BEE_SPAWN_EGG:
case BLAZE_SPAWN_EGG:
case BOGGED_SPAWN_EGG:
case BREEZE_SPAWN_EGG:
case CAT_SPAWN_EGG:
case CAMEL_SPAWN_EGG:
@@ -500,11 +467,11 @@ public final class CraftItemStack extends ItemStack {
case ZOMBIE_SPAWN_EGG:
case ZOMBIE_VILLAGER_SPAWN_EGG:
case ZOMBIFIED_PIGLIN_SPAWN_EGG:
return new CraftMetaSpawnEgg(item.getTag());
return new CraftMetaSpawnEgg(item.getComponentsPatch());
case ARMOR_STAND:
return new CraftMetaArmorStand(item.getTag());
return new CraftMetaArmorStand(item.getComponentsPatch());
case KNOWLEDGE_BOOK:
return new CraftMetaKnowledgeBook(item.getTag());
return new CraftMetaKnowledgeBook(item.getComponentsPatch());
case FURNACE:
case CHEST:
case TRAPPED_CHEST:
@@ -605,30 +572,33 @@ public final class CraftItemStack extends ItemStack {
case SUSPICIOUS_GRAVEL:
case CRAFTER:
case TRIAL_SPAWNER:
return new CraftMetaBlockState(item.getTag(), CraftItemType.minecraftToBukkit(item.getItem()));
case VAULT:
return new CraftMetaBlockState(item.getComponentsPatch(), CraftItemType.minecraftToBukkit(item.getItem()));
case TROPICAL_FISH_BUCKET:
return new CraftMetaTropicalFishBucket(item.getTag());
return new CraftMetaTropicalFishBucket(item.getComponentsPatch());
case AXOLOTL_BUCKET:
return new CraftMetaAxolotlBucket(item.getTag());
return new CraftMetaAxolotlBucket(item.getComponentsPatch());
case CROSSBOW:
return new CraftMetaCrossbow(item.getTag());
return new CraftMetaCrossbow(item.getComponentsPatch());
case SUSPICIOUS_STEW:
return new CraftMetaSuspiciousStew(item.getTag());
return new CraftMetaSuspiciousStew(item.getComponentsPatch());
case COD_BUCKET:
case PUFFERFISH_BUCKET:
case SALMON_BUCKET:
case ITEM_FRAME:
case GLOW_ITEM_FRAME:
case PAINTING:
return new CraftMetaEntityTag(item.getTag());
return new CraftMetaEntityTag(item.getComponentsPatch());
case COMPASS:
return new CraftMetaCompass(item.getTag());
return new CraftMetaCompass(item.getComponentsPatch());
case BUNDLE:
return new CraftMetaBundle(item.getTag());
return new CraftMetaBundle(item.getComponentsPatch());
case GOAT_HORN:
return new CraftMetaMusicInstrument(item.getTag());
return new CraftMetaMusicInstrument(item.getComponentsPatch());
case OMINOUS_BOTTLE:
return new CraftMetaOminousBottle(item.getComponentsPatch());
default:
return new CraftMetaItem(item.getTag());
return new CraftMetaItem(item.getComponentsPatch());
}
}
@@ -646,7 +616,7 @@ public final class CraftItemStack extends ItemStack {
return false;
}
if (CraftItemFactory.instance().equals(itemMeta, null)) {
item.setTag(null);
item.applyComponents(DataComponentMap.EMPTY);
return true;
}
if (!CraftItemFactory.instance().isApplicable(itemMeta, getType(item))) {
@@ -662,13 +632,14 @@ public final class CraftItemStack extends ItemStack {
item.setItem(newItem);
}
NBTTagCompound tag = new NBTTagCompound();
item.setTag(tag);
if (!((CraftMetaItem) itemMeta).isEmpty()) {
CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator();
((CraftMetaItem) itemMeta).applyToItem(tag);
item.convertStack(((CraftMetaItem) itemMeta).getVersion());
((CraftMetaItem) itemMeta).applyToItem(tag);
item.applyComponents(tag.build());
}
// SpigotCraft#463 this is required now by the Vanilla client, so mimic ItemStack constructor in ensuring it
if (item.getItem() != null && item.getItem().canBeDepleted()) {
if (item.getItem() != null && item.getMaxDamage() > 0) {
item.setDamageValue(item.getDamageValue());
}
@@ -698,7 +669,7 @@ public final class CraftItemStack extends ItemStack {
if (!(comparisonType == getType() && getDurability() == that.getDurability())) {
return false;
}
return hasItemMeta() ? that.hasItemMeta() && handle.getTag().equals(that.handle.getTag()) : !that.hasItemMeta();
return hasItemMeta() ? that.hasItemMeta() && handle.getComponents().equals(that.handle.getComponents()) : !that.hasItemMeta();
}
@Override
@@ -707,6 +678,6 @@ public final class CraftItemStack extends ItemStack {
}
static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) {
return !(item == null || item.getTag() == null || item.getTag().isEmpty());
return !(item == null || item.getComponentsPatch().isEmpty());
}
}

View File

@@ -2,6 +2,10 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.component.DataComponentPredicate;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.ItemCost;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
@@ -12,8 +16,8 @@ public class CraftMerchantRecipe extends MerchantRecipe {
public CraftMerchantRecipe(net.minecraft.world.item.trading.MerchantRecipe merchantRecipe) {
super(CraftItemStack.asBukkitCopy(merchantRecipe.result), 0);
this.handle = merchantRecipe;
addIngredient(CraftItemStack.asBukkitCopy(merchantRecipe.baseCostA));
addIngredient(CraftItemStack.asBukkitCopy(merchantRecipe.costB));
addIngredient(CraftItemStack.asBukkitCopy(merchantRecipe.baseCostA.itemStack()));
merchantRecipe.costB.ifPresent((costB) -> addIngredient(CraftItemStack.asBukkitCopy(costB.itemStack())));
}
@Deprecated
@@ -24,8 +28,8 @@ public class CraftMerchantRecipe extends MerchantRecipe {
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice) {
super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice);
this.handle = new net.minecraft.world.item.trading.MerchantRecipe(
net.minecraft.world.item.ItemStack.EMPTY,
net.minecraft.world.item.ItemStack.EMPTY,
new ItemCost(Items.AIR),
Optional.empty(),
CraftItemStack.asNMSCopy(result),
uses,
maxUses,
@@ -111,9 +115,11 @@ public class CraftMerchantRecipe extends MerchantRecipe {
public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() {
List<ItemStack> ingredients = getIngredients();
Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients");
handle.baseCostA = CraftItemStack.asNMSCopy(ingredients.get(0));
net.minecraft.world.item.ItemStack baseCostA = CraftItemStack.asNMSCopy(ingredients.get(0));
handle.baseCostA = new ItemCost(baseCostA.getItemHolder(), baseCostA.getCount(), DataComponentPredicate.allOf(baseCostA.getComponents()), baseCostA);
if (ingredients.size() > 1) {
handle.costB = CraftItemStack.asNMSCopy(ingredients.get(1));
net.minecraft.world.item.ItemStack costB = CraftItemStack.asNMSCopy(ingredients.get(1));
handle.costB = Optional.of(new ItemCost(costB.getItemHolder(), costB.getCount(), DataComponentPredicate.allOf(costB.getComponents()), costB));
}
return handle;
}

View File

@@ -6,17 +6,21 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial;
import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.meta.ArmorMeta;
import org.bukkit.inventory.meta.trim.ArmorTrim;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
private static final Set<Material> ARMOR_MATERIALS = Sets.newHashSet(
@@ -47,7 +51,7 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
Material.TURTLE_HELMET
);
static final ItemMetaKey TRIM = new ItemMetaKey("Trim", "trim");
static final ItemMetaKeyType<net.minecraft.world.item.armortrim.ArmorTrim> TRIM = new ItemMetaKeyType<>(DataComponents.TRIM, "trim");
static final ItemMetaKey TRIM_MATERIAL = new ItemMetaKey("material");
static final ItemMetaKey TRIM_PATTERN = new ItemMetaKey("pattern");
@@ -61,19 +65,19 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
}
}
CraftMetaArmor(NBTTagCompound tag) {
CraftMetaArmor(DataComponentPatch tag) {
super(tag);
if (tag.contains(TRIM.NBT)) {
NBTTagCompound trimCompound = tag.getCompound(TRIM.NBT);
getOrEmpty(tag, TRIM).ifPresent((trimCompound) -> {
TrimMaterial trimMaterial = CraftTrimMaterial.minecraftHolderToBukkit(trimCompound.material());
TrimPattern trimPattern = CraftTrimPattern.minecraftHolderToBukkit(trimCompound.pattern());
if (trimCompound.contains(TRIM_MATERIAL.NBT) && trimCompound.contains(TRIM_PATTERN.NBT)) {
TrimMaterial trimMaterial = Registry.TRIM_MATERIAL.get(NamespacedKey.fromString(trimCompound.getString(TRIM_MATERIAL.NBT)));
TrimPattern trimPattern = Registry.TRIM_PATTERN.get(NamespacedKey.fromString(trimCompound.getString(TRIM_PATTERN.NBT)));
this.trim = new ArmorTrim(trimMaterial, trimPattern);
this.trim = new ArmorTrim(trimMaterial, trimPattern);
if (!trimCompound.showInTooltip) {
addItemFlags(ItemFlag.HIDE_ARMOR_TRIM);
}
}
});
}
CraftMetaArmor(Map<String, Object> map) {
@@ -101,14 +105,11 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
if (hasTrim()) {
NBTTagCompound trimCompound = new NBTTagCompound();
trimCompound.putString(TRIM_MATERIAL.NBT, trim.getMaterial().getKey().toString());
trimCompound.putString(TRIM_PATTERN.NBT, trim.getPattern().getKey().toString());
itemTag.put(TRIM.NBT, trimCompound);
itemTag.put(TRIM, new net.minecraft.world.item.armortrim.ArmorTrim(CraftTrimMaterial.bukkitToMinecraftHolder(trim.getMaterial()), CraftTrimPattern.bukkitToMinecraftHolder(trim.getPattern()), !hasItemFlag(ItemFlag.HIDE_ARMOR_TRIM)));
}
}

View File

@@ -2,15 +2,18 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Map;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaArmorStand extends CraftMetaItem {
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.ENTITY_DATA, "entity-tag");
NBTTagCompound entityTag;
CraftMetaArmorStand(CraftMetaItem meta) {
@@ -24,12 +27,12 @@ public class CraftMetaArmorStand extends CraftMetaItem {
this.entityTag = armorStand.entityTag;
}
CraftMetaArmorStand(NBTTagCompound tag) {
CraftMetaArmorStand(DataComponentPatch tag) {
super(tag);
if (tag.contains(ENTITY_TAG.NBT)) {
entityTag = tag.getCompound(ENTITY_TAG.NBT).copy();
}
getOrEmpty(tag, ENTITY_TAG).ifPresent((nbt) -> {
entityTag = nbt.copyTag();
});
}
CraftMetaArmorStand(Map<String, Object> map) {
@@ -53,11 +56,11 @@ public class CraftMetaArmorStand extends CraftMetaItem {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (entityTag != null) {
tag.put(ENTITY_TAG.NBT, entityTag);
tag.put(ENTITY_TAG, CustomData.of(entityTag));
}
}

View File

@@ -2,19 +2,22 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.Axolotl;
import org.bukkit.inventory.meta.AxolotlBucketMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaAxolotlBucket extends CraftMetaItem implements AxolotlBucketMeta {
static final ItemMetaKey VARIANT = new ItemMetaKey("Variant", "axolotl-variant");
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
static final ItemMetaKey VARIANT = new ItemMetaKey("axolotl-variant");
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.BUCKET_ENTITY_DATA, "entity-tag");
private Integer variant;
private NBTTagCompound entityTag;
@@ -31,16 +34,16 @@ public class CraftMetaAxolotlBucket extends CraftMetaItem implements AxolotlBuck
this.entityTag = bucket.entityTag;
}
CraftMetaAxolotlBucket(NBTTagCompound tag) {
CraftMetaAxolotlBucket(DataComponentPatch tag) {
super(tag);
if (tag.contains(VARIANT.NBT, CraftMagicNumbers.NBT.TAG_INT)) {
this.variant = tag.getInt(VARIANT.NBT);
}
getOrEmpty(tag, ENTITY_TAG).ifPresent((nbt) -> {
entityTag = nbt.copyTag();
if (tag.contains(ENTITY_TAG.NBT)) {
entityTag = tag.getCompound(ENTITY_TAG.NBT).copy();
}
if (entityTag.contains("Variant", CraftMagicNumbers.NBT.TAG_INT)) {
this.variant = entityTag.getInt("Variant");
}
});
}
CraftMetaAxolotlBucket(Map<String, Object> map) {
@@ -69,15 +72,18 @@ public class CraftMetaAxolotlBucket extends CraftMetaItem implements AxolotlBuck
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (hasVariant()) {
tag.putInt(VARIANT.NBT, variant);
if (entityTag == null) {
entityTag = new NBTTagCompound();
}
entityTag.putInt("Variant", variant);
}
if (entityTag != null) {
tag.put(ENTITY_TAG.NBT, entityTag);
tag.put(ENTITY_TAG, CustomData.of(entityTag));
}
}

View File

@@ -8,17 +8,19 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.EnumColor;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.block.banner.CraftPatternType;
import org.bukkit.inventory.meta.BannerMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
private static final Set<Material> BANNER_MATERIALS = Sets.newHashSet(
@@ -56,12 +58,8 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
Material.YELLOW_WALL_BANNER
);
static final ItemMetaKey BASE = new ItemMetaKey("Base", "base-color");
static final ItemMetaKey PATTERNS = new ItemMetaKey("Patterns", "patterns");
static final ItemMetaKey COLOR = new ItemMetaKey("Color", "color");
static final ItemMetaKey PATTERN = new ItemMetaKey("Pattern", "pattern");
static final ItemMetaKeyType<BannerPatternLayers> PATTERNS = new ItemMetaKeyType<>(DataComponents.BANNER_PATTERNS, "patterns");
private DyeColor base;
private List<Pattern> patterns = new ArrayList<Pattern>();
CraftMetaBanner(CraftMetaItem meta) {
@@ -72,43 +70,29 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
}
CraftMetaBanner banner = (CraftMetaBanner) meta;
base = banner.base;
patterns = new ArrayList<Pattern>(banner.patterns);
}
CraftMetaBanner(NBTTagCompound tag) {
CraftMetaBanner(DataComponentPatch tag) {
super(tag);
if (!tag.contains("BlockEntityTag")) {
return;
}
NBTTagCompound entityTag = tag.getCompound("BlockEntityTag");
base = entityTag.contains(BASE.NBT) ? DyeColor.getByWoolData((byte) entityTag.getInt(BASE.NBT)) : null;
if (entityTag.contains(PATTERNS.NBT)) {
NBTTagList patterns = entityTag.getList(PATTERNS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
getOrEmpty(tag, PATTERNS).ifPresent((entityTag) -> {
List<BannerPatternLayers.b> patterns = entityTag.layers();
for (int i = 0; i < Math.min(patterns.size(), 20); i++) {
NBTTagCompound p = patterns.getCompound(i);
DyeColor color = DyeColor.getByWoolData((byte) p.getInt(COLOR.NBT));
PatternType pattern = PatternType.getByIdentifier(p.getString(PATTERN.NBT));
BannerPatternLayers.b p = patterns.get(i);
DyeColor color = DyeColor.getByWoolData((byte) p.color().getId());
PatternType pattern = CraftPatternType.minecraftHolderToBukkit(p.pattern());
if (color != null && pattern != null) {
this.patterns.add(new Pattern(color, pattern));
}
}
}
});
}
CraftMetaBanner(Map<String, Object> map) {
super(map);
String baseStr = SerializableMeta.getString(map, BASE.BUKKIT, true);
if (baseStr != null) {
base = DyeColor.legacyValueOf(baseStr);
}
Iterable<?> rawPatternList = SerializableMeta.getObject(Iterable.class, map, PATTERNS.BUKKIT, true);
if (rawPatternList == null) {
return;
@@ -119,36 +103,18 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
addPattern((Pattern) obj);
}
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
NBTTagCompound entityTag = new NBTTagCompound();
if (base != null) {
entityTag.putInt(BASE.NBT, base.getWoolData());
}
NBTTagList newPatterns = new NBTTagList();
List<BannerPatternLayers.b> newPatterns = new ArrayList<>();
for (Pattern p : patterns) {
NBTTagCompound compound = new NBTTagCompound();
compound.putInt(COLOR.NBT, p.getColor().getWoolData());
compound.putString(PATTERN.NBT, p.getPattern().getIdentifier());
newPatterns.add(compound);
newPatterns.add(new BannerPatternLayers.b(CraftPatternType.bukkitToMinecraftHolder(p.getPattern()), EnumColor.byId(p.getColor().getWoolData())));
}
entityTag.put(PATTERNS.NBT, newPatterns);
tag.put("BlockEntityTag", entityTag);
}
@Override
public DyeColor getBaseColor() {
return base;
}
@Override
public void setBaseColor(DyeColor color) {
base = color;
tag.put(PATTERNS, new BannerPatternLayers(newPatterns));
}
@Override
@@ -190,10 +156,6 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
super.serialize(builder);
if (base != null) {
builder.put(BASE.BUKKIT, base.toString());
}
if (!patterns.isEmpty()) {
builder.put(PATTERNS.BUKKIT, ImmutableList.copyOf(patterns));
}
@@ -205,9 +167,6 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
int applyHash() {
final int original;
int hash = original = super.applyHash();
if (base != null) {
hash = 31 * hash + base.hashCode();
}
if (!patterns.isEmpty()) {
hash = 31 * hash + patterns.hashCode();
}
@@ -222,19 +181,19 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
if (meta instanceof CraftMetaBanner) {
CraftMetaBanner that = (CraftMetaBanner) meta;
return base == that.base && patterns.equals(that.patterns);
return patterns.equals(that.patterns);
}
return true;
}
@Override
boolean notUncommon(CraftMetaItem meta) {
return super.notUncommon(meta) && (meta instanceof CraftMetaBanner || (patterns.isEmpty() && base == null));
return super.notUncommon(meta) && (meta instanceof CraftMetaBanner || patterns.isEmpty());
}
@Override
boolean isEmpty() {
return super.isEmpty() && patterns.isEmpty() && base == null;
return super.isEmpty() && patterns.isEmpty();
}
@Override

View File

@@ -4,20 +4,28 @@ import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.component.PatchedDataComponentMap;
import net.minecraft.core.component.TypedDataComponent;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.block.CraftBanner;
import org.bukkit.craftbukkit.block.CraftBlockEntityState;
import org.bukkit.craftbukkit.block.CraftBlockStates;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.BlockStateMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta {
private static final Set<Material> SHULKER_BOX_MATERIALS = Sets.newHashSet(
@@ -123,19 +131,46 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
Material.SUSPICIOUS_SAND,
Material.SUSPICIOUS_GRAVEL,
Material.TRIAL_SPAWNER,
Material.CRAFTER
Material.CRAFTER,
Material.VAULT
);
private static final class TrackedDataComponentMap implements DataComponentMap {
private final Set<DataComponentType<?>> seen = new HashSet<>();
private final DataComponentMap handle;
public TrackedDataComponentMap(DataComponentMap map) {
this.handle = map;
}
@Override
public <T> T get(DataComponentType<? extends T> type) {
seen.add(type);
return handle.get(type);
}
@Override
public Set<DataComponentType<?>> keySet() {
return handle.keySet();
}
@Override
public Iterator<TypedDataComponent<?>> iterator() {
return handle.iterator();
}
}
static {
// Add shulker boxes to the list of block state materials too
BLOCK_STATE_MATERIALS.addAll(SHULKER_BOX_MATERIALS);
}
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKey BLOCK_ENTITY_TAG = new ItemMetaKey("BlockEntityTag");
static final ItemMetaKeyType<CustomData> BLOCK_ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.BLOCK_ENTITY_DATA, "BlockEntityTag");
final Material material;
NBTTagCompound blockEntityTag;
private CraftBlockEntityState<?> blockEntityTag;
CraftMetaBlockState(CraftMetaItem meta, Material material) {
super(meta);
@@ -151,14 +186,30 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
this.blockEntityTag = te.blockEntityTag;
}
CraftMetaBlockState(NBTTagCompound tag, Material material) {
CraftMetaBlockState(DataComponentPatch tag, Material material) {
super(tag);
this.material = material;
if (tag.contains(BLOCK_ENTITY_TAG.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
blockEntityTag = tag.getCompound(BLOCK_ENTITY_TAG.NBT).copy();
} else {
blockEntityTag = null;
getOrEmpty(tag, BLOCK_ENTITY_TAG).ifPresent((nbt) -> {
blockEntityTag = getBlockState(material, nbt.copyTag());
});
if (!tag.isEmpty()) {
if (blockEntityTag == null) {
blockEntityTag = getBlockState(material, null);
}
// Convert to map
PatchedDataComponentMap map = new PatchedDataComponentMap(DataComponentMap.EMPTY);
map.applyPatch(tag);
// Setup tracking
TrackedDataComponentMap track = new TrackedDataComponentMap(map);
// Apply
blockEntityTag.applyComponents(track, tag);
// Mark applied components as handled
for (DataComponentType<?> seen : track.seen) {
unhandledTags.clear(seen);
}
}
}
@@ -171,14 +222,19 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
} else {
material = Material.AIR;
}
blockEntityTag = getBlockState(material, null);
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (blockEntityTag != null) {
tag.put(BLOCK_ENTITY_TAG.NBT, blockEntityTag);
tag.put(BLOCK_ENTITY_TAG, CustomData.of(blockEntityTag.getSnapshotNBTWithoutComponents()));
for (TypedDataComponent<?> component : blockEntityTag.collectComponents()) {
tag.builder.set(component);
}
}
}
@@ -187,14 +243,14 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
super.deserializeInternal(tag, context);
if (tag.contains(BLOCK_ENTITY_TAG.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
blockEntityTag = tag.getCompound(BLOCK_ENTITY_TAG.NBT);
blockEntityTag = getBlockState(material, tag.getCompound(BLOCK_ENTITY_TAG.NBT));
}
}
@Override
void serializeInternal(final Map<String, NBTBase> internalTags) {
if (blockEntityTag != null) {
internalTags.put(BLOCK_ENTITY_TAG.NBT, blockEntityTag);
internalTags.put(BLOCK_ENTITY_TAG.NBT, blockEntityTag.getSnapshotNBT());
}
}
@@ -259,7 +315,11 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
@Override
public BlockState getBlockState() {
Material stateMaterial = (material != Material.SHIELD) ? material : shieldToBannerHack(blockEntityTag); // Only actually used for jigsaws
return (blockEntityTag != null) ? blockEntityTag.copy() : getBlockState(material, null);
}
private static CraftBlockEntityState<?> getBlockState(Material material, NBTTagCompound blockEntityTag) {
Material stateMaterial = (material != Material.SHIELD) ? material : shieldToBannerHack(); // Only actually used for jigsaws
if (blockEntityTag != null) {
if (material == Material.SHIELD) {
blockEntityTag.putString("id", "minecraft:banner");
@@ -271,64 +331,21 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
}
// This is expected to always return a CraftBlockEntityState for the passed material:
return CraftBlockStates.getBlockState(stateMaterial, blockEntityTag);
return (CraftBlockEntityState<?>) CraftBlockStates.getBlockState(stateMaterial, blockEntityTag);
}
@Override
public void setBlockState(BlockState blockState) {
Preconditions.checkArgument(blockState != null, "blockState must not be null");
Material stateMaterial = (material != Material.SHIELD) ? material : shieldToBannerHack(blockEntityTag);
Material stateMaterial = (material != Material.SHIELD) ? material : shieldToBannerHack();
Class<?> blockStateType = CraftBlockStates.getBlockStateType(stateMaterial);
Preconditions.checkArgument(blockStateType == blockState.getClass() && blockState instanceof CraftBlockEntityState, "Invalid blockState for " + material);
blockEntityTag = ((CraftBlockEntityState) blockState).getSnapshotNBT();
// Set shield base
if (material == Material.SHIELD) {
blockEntityTag.putInt(CraftMetaBanner.BASE.NBT, ((CraftBanner) blockState).getBaseColor().getWoolData());
}
this.blockEntityTag = (CraftBlockEntityState<?>) blockState;
}
private static Material shieldToBannerHack(NBTTagCompound tag) {
if (tag == null || !tag.contains(CraftMetaBanner.BASE.NBT, CraftMagicNumbers.NBT.TAG_INT)) {
return Material.WHITE_BANNER;
}
switch (tag.getInt(CraftMetaBanner.BASE.NBT)) {
case 0:
return Material.WHITE_BANNER;
case 1:
return Material.ORANGE_BANNER;
case 2:
return Material.MAGENTA_BANNER;
case 3:
return Material.LIGHT_BLUE_BANNER;
case 4:
return Material.YELLOW_BANNER;
case 5:
return Material.LIME_BANNER;
case 6:
return Material.PINK_BANNER;
case 7:
return Material.GRAY_BANNER;
case 8:
return Material.LIGHT_GRAY_BANNER;
case 9:
return Material.CYAN_BANNER;
case 10:
return Material.PURPLE_BANNER;
case 11:
return Material.BLUE_BANNER;
case 12:
return Material.BROWN_BANNER;
case 13:
return Material.GREEN_BANNER;
case 14:
return Material.RED_BANNER;
case 15:
return Material.BLACK_BANNER;
default:
throw new IllegalArgumentException("Unknown banner colour");
}
private static Material shieldToBannerHack() {
return Material.WHITE_BANNER;
}
}

View File

@@ -9,177 +9,94 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.world.item.ItemWrittenBook;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.network.Filterable;
import net.minecraft.server.network.FilteredText;
import net.minecraft.world.item.component.WritableBookContent;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.WritableBookMeta;
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaBook extends CraftMetaItem implements BookMeta {
static final ItemMetaKey BOOK_TITLE = new ItemMetaKey("title");
static final ItemMetaKey BOOK_AUTHOR = new ItemMetaKey("author");
public class CraftMetaBook extends CraftMetaItem implements BookMeta, WritableBookMeta {
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKeyType<WritableBookContent> BOOK_CONTENT = new ItemMetaKeyType<>(DataComponents.WRITABLE_BOOK_CONTENT);
static final ItemMetaKey BOOK_PAGES = new ItemMetaKey("pages");
static final ItemMetaKey RESOLVED = new ItemMetaKey("resolved");
static final ItemMetaKey GENERATION = new ItemMetaKey("generation");
static final int MAX_PAGES = ItemWrittenBook.MAX_PAGES; // SPIGOT-6911: Use Minecraft limits
static final int MAX_PAGE_LENGTH = ItemWrittenBook.PAGE_EDIT_LENGTH; // SPIGOT-6911: Use Minecraft limits
static final int MAX_TITLE_LENGTH = ItemWrittenBook.TITLE_MAX_LENGTH; // SPIGOT-6911: Use Minecraft limits
static final int MAX_PAGES = Integer.MAX_VALUE; // SPIGOT-6911: Use Minecraft limits
static final int MAX_PAGE_LENGTH = WritableBookContent.PAGE_EDIT_LENGTH; // SPIGOT-6911: Use Minecraft limits
protected String title;
protected String author;
// We store the pages in their raw original text representation. See SPIGOT-5063, SPIGOT-5350, SPIGOT-3206
// For writable books (CraftMetaBook) the pages are stored as plain Strings.
// For written books (CraftMetaBookSigned) the pages are stored in Minecraft's JSON format.
protected List<String> pages; // null and empty are two different states internally
protected Boolean resolved = null;
protected Integer generation;
CraftMetaBook(CraftMetaItem meta) {
super(meta);
if (meta instanceof CraftMetaBook) {
CraftMetaBook bookMeta = (CraftMetaBook) meta;
this.title = bookMeta.title;
this.author = bookMeta.author;
this.resolved = bookMeta.resolved;
this.generation = bookMeta.generation;
if (bookMeta.pages != null) {
this.pages = new ArrayList<String>(bookMeta.pages.size());
if (meta instanceof CraftMetaBookSigned) {
if (this instanceof CraftMetaBookSigned) {
pages.addAll(bookMeta.pages);
} else {
// Convert from JSON to plain Strings:
pages.addAll(Lists.transform(bookMeta.pages, CraftChatMessage::fromJSONComponent));
}
} else {
if (this instanceof CraftMetaBookSigned) {
// Convert from plain Strings to JSON:
// This happens for example during book signing.
for (String page : bookMeta.pages) {
// We don't insert any non-plain text features (such as clickable links) during this conversion.
IChatBaseComponent component = CraftChatMessage.fromString(page, true, true)[0];
pages.add(CraftChatMessage.toJSON(component));
}
} else {
pages.addAll(bookMeta.pages);
}
}
pages.addAll(bookMeta.pages);
}
} else if (meta instanceof CraftMetaBookSigned) {
CraftMetaBookSigned bookMeta = (CraftMetaBookSigned) meta;
if (bookMeta.pages != null) {
this.pages = new ArrayList<String>(bookMeta.pages.size());
// Convert from JSON to plain Strings:
pages.addAll(Lists.transform(bookMeta.pages, CraftChatMessage::fromComponent));
}
}
}
CraftMetaBook(NBTTagCompound tag) {
CraftMetaBook(DataComponentPatch tag) {
super(tag);
if (tag.contains(BOOK_TITLE.NBT)) {
this.title = tag.getString(BOOK_TITLE.NBT);
}
if (tag.contains(BOOK_AUTHOR.NBT)) {
this.author = tag.getString(BOOK_AUTHOR.NBT);
}
if (tag.contains(RESOLVED.NBT)) {
this.resolved = tag.getBoolean(RESOLVED.NBT);
}
if (tag.contains(GENERATION.NBT)) {
generation = tag.getInt(GENERATION.NBT);
}
if (tag.contains(BOOK_PAGES.NBT)) {
NBTTagList pages = tag.getList(BOOK_PAGES.NBT, CraftMagicNumbers.NBT.TAG_STRING);
getOrEmpty(tag, BOOK_CONTENT).ifPresent((writable) -> {
List<Filterable<String>> pages = writable.pages();
this.pages = new ArrayList<String>(pages.size());
boolean expectJson = (this instanceof CraftMetaBookSigned);
// Note: We explicitly check for and truncate oversized books and pages,
// because they can come directly from clients when handling book edits.
for (int i = 0; i < Math.min(pages.size(), MAX_PAGES); i++) {
String page = pages.getString(i);
// There was an issue on previous Spigot versions which would
// result in book items with pages in the wrong text
// representation. See SPIGOT-182, SPIGOT-164
if (expectJson) {
page = CraftChatMessage.fromJSONOrStringToJSON(page, false, true, MAX_PAGE_LENGTH, false);
} else {
page = validatePage(page);
}
String page = pages.get(i).raw();
page = validatePage(page);
this.pages.add(page);
}
}
});
}
CraftMetaBook(Map<String, Object> map) {
super(map);
setAuthor(SerializableMeta.getString(map, BOOK_AUTHOR.BUKKIT, true));
setTitle(SerializableMeta.getString(map, BOOK_TITLE.BUKKIT, true));
Iterable<?> pages = SerializableMeta.getObject(Iterable.class, map, BOOK_PAGES.BUKKIT, true);
if (pages != null) {
this.pages = new ArrayList<String>();
for (Object page : pages) {
if (page instanceof String) {
internalAddPage(deserializePage((String) page));
internalAddPage(validatePage((String) page));
}
}
}
resolved = SerializableMeta.getObject(Boolean.class, map, RESOLVED.BUKKIT, true);
generation = SerializableMeta.getObject(Integer.class, map, GENERATION.BUKKIT, true);
}
protected String deserializePage(String pageData) {
// We expect the page data to already be a plain String.
return validatePage(pageData);
}
protected String convertPlainPageToData(String page) {
// Writable books store their data as plain Strings, so we don't need to convert anything.
return page;
}
protected String convertDataToPlainPage(String pageData) {
// pageData is expected to already be a plain String.
return pageData;
}
@Override
void applyToItem(NBTTagCompound itemData) {
void applyToItem(CraftMetaItem.Applicator itemData) {
super.applyToItem(itemData);
if (hasTitle()) {
itemData.putString(BOOK_TITLE.NBT, this.title);
}
if (hasAuthor()) {
itemData.putString(BOOK_AUTHOR.NBT, this.author);
}
if (pages != null) {
NBTTagList list = new NBTTagList();
List<Filterable<String>> list = new ArrayList<>();
for (String page : pages) {
list.add(NBTTagString.valueOf(page));
list.add(Filterable.from(FilteredText.passThrough(page)));
}
itemData.put(BOOK_PAGES.NBT, list);
}
if (resolved != null) {
itemData.putBoolean(RESOLVED.NBT, resolved);
}
if (generation != null) {
itemData.putInt(GENERATION.NBT, generation);
itemData.put(BOOK_CONTENT, new WritableBookContent(list));
}
}
@@ -189,22 +106,22 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
}
boolean isBookEmpty() {
return !((pages != null) || hasAuthor() || hasTitle() || hasGeneration() || (resolved != null));
return !(pages != null);
}
@Override
boolean applicableTo(Material type) {
return type == Material.WRITTEN_BOOK || type == Material.WRITABLE_BOOK;
return type == Material.WRITABLE_BOOK;
}
@Override
public boolean hasAuthor() {
return this.author != null;
return false;
}
@Override
public boolean hasTitle() {
return this.title != null;
return false;
}
@Override
@@ -214,52 +131,42 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
@Override
public boolean hasGeneration() {
return generation != null;
return false;
}
@Override
public String getTitle() {
return this.title;
return null;
}
@Override
public boolean setTitle(final String title) {
if (title == null) {
this.title = null;
return true;
} else if (title.length() > MAX_TITLE_LENGTH) {
return false;
}
this.title = title;
return true;
return false;
}
@Override
public String getAuthor() {
return this.author;
return null;
}
@Override
public void setAuthor(final String author) {
this.author = author;
}
@Override
public Generation getGeneration() {
return (generation == null) ? null : Generation.values()[generation];
return null;
}
@Override
public void setGeneration(Generation generation) {
this.generation = (generation == null) ? null : generation.ordinal();
}
@Override
public String getPage(final int page) {
Preconditions.checkArgument(isValidPage(page), "Invalid page number (%s)", page);
// assert: pages != null
return convertDataToPlainPage(pages.get(page - 1));
return pages.get(page - 1);
}
@Override
@@ -268,7 +175,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
// assert: pages != null
String newText = validatePage(text);
pages.set(page - 1, convertPlainPageToData(newText));
pages.set(page - 1, newText);
}
@Override
@@ -280,7 +187,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
public void addPage(final String... pages) {
for (String page : pages) {
page = validatePage(page);
internalAddPage(convertPlainPageToData(page));
internalAddPage(page);
}
}
@@ -311,7 +218,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
@Override
public List<String> getPages() {
if (pages == null) return ImmutableList.of();
return pages.stream().map(this::convertDataToPlainPage).collect(ImmutableList.toImmutableList());
return pages.stream().collect(ImmutableList.toImmutableList());
}
@Override
@@ -333,15 +240,6 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
return page > 0 && page <= getPageCount();
}
// TODO Expose this attribute in Bukkit?
public boolean isResolved() {
return (resolved == null) ? false : resolved;
}
public void setResolved(boolean resolved) {
this.resolved = resolved;
}
@Override
public CraftMetaBook clone() {
CraftMetaBook meta = (CraftMetaBook) super.clone();
@@ -355,21 +253,9 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
int applyHash() {
final int original;
int hash = original = super.applyHash();
if (hasTitle()) {
hash = 61 * hash + this.title.hashCode();
}
if (hasAuthor()) {
hash = 61 * hash + 13 * this.author.hashCode();
}
if (this.pages != null) {
hash = 61 * hash + 17 * this.pages.hashCode();
}
if (this.resolved != null) {
hash = 61 * hash + 17 * this.resolved.hashCode();
}
if (hasGeneration()) {
hash = 61 * hash + 19 * this.generation.hashCode();
}
return original != hash ? CraftMetaBook.class.hashCode() ^ hash : hash;
}
@@ -380,11 +266,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
}
if (meta instanceof CraftMetaBook that) {
return (hasTitle() ? that.hasTitle() && this.title.equals(that.title) : !that.hasTitle())
&& (hasAuthor() ? that.hasAuthor() && this.author.equals(that.author) : !that.hasAuthor())
&& (Objects.equals(this.pages, that.pages))
&& (Objects.equals(this.resolved, that.resolved))
&& (hasGeneration() ? that.hasGeneration() && this.generation.equals(that.generation) : !that.hasGeneration());
return (Objects.equals(this.pages, that.pages));
}
return true;
}
@@ -398,26 +280,10 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
if (hasTitle()) {
builder.put(BOOK_TITLE.BUKKIT, title);
}
if (hasAuthor()) {
builder.put(BOOK_AUTHOR.BUKKIT, author);
}
if (pages != null) {
builder.put(BOOK_PAGES.BUKKIT, ImmutableList.copyOf(pages));
}
if (resolved != null) {
builder.put(RESOLVED.BUKKIT, resolved);
}
if (generation != null) {
builder.put(GENERATION.BUKKIT, generation);
}
return builder;
}
}

View File

@@ -1,62 +1,297 @@
package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import java.util.Objects;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.server.network.Filterable;
import net.minecraft.server.network.FilteredText;
import net.minecraft.world.item.component.WritableBookContent;
import net.minecraft.world.item.component.WrittenBookContent;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.inventory.meta.BookMeta;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaBookSigned extends CraftMetaBook implements BookMeta {
public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta {
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKeyType<WrittenBookContent> BOOK_CONTENT = new ItemMetaKeyType<>(DataComponents.WRITTEN_BOOK_CONTENT);
static final ItemMetaKey BOOK_TITLE = new ItemMetaKey("title");
static final ItemMetaKey BOOK_AUTHOR = new ItemMetaKey("author");
static final ItemMetaKey BOOK_PAGES = new ItemMetaKey("pages");
static final ItemMetaKey RESOLVED = new ItemMetaKey("resolved");
static final ItemMetaKey GENERATION = new ItemMetaKey("generation");
static final int MAX_PAGES = Integer.MAX_VALUE; // SPIGOT-6911: Use Minecraft limits
static final int MAX_PAGE_LENGTH = WritableBookContent.PAGE_EDIT_LENGTH; // SPIGOT-6911: Use Minecraft limits
static final int MAX_TITLE_LENGTH = WrittenBookContent.TITLE_MAX_LENGTH; // SPIGOT-6911: Use Minecraft limits
protected String title;
protected String author;
// We store the pages in their raw original text representation. See SPIGOT-5063, SPIGOT-5350, SPIGOT-3206
// For written books (CraftMetaBookSigned) the pages are stored in Minecraft's JSON format.
protected List<IChatBaseComponent> pages; // null and empty are two different states internally
protected boolean resolved;
protected int generation;
CraftMetaBookSigned(CraftMetaItem meta) {
super(meta);
if (meta instanceof CraftMetaBookSigned) {
CraftMetaBookSigned bookMeta = (CraftMetaBookSigned) meta;
this.title = bookMeta.title;
this.author = bookMeta.author;
this.resolved = bookMeta.resolved;
this.generation = bookMeta.generation;
if (bookMeta.pages != null) {
this.pages = new ArrayList<IChatBaseComponent>(bookMeta.pages.size());
pages.addAll(bookMeta.pages);
}
} else if (meta instanceof CraftMetaBook) {
CraftMetaBook bookMeta = (CraftMetaBook) meta;
if (bookMeta.pages != null) {
this.pages = new ArrayList<IChatBaseComponent>(bookMeta.pages.size());
// Convert from plain Strings to JSON:
// This happens for example during book signing.
for (String page : bookMeta.pages) {
// We don't insert any non-plain text features (such as clickable links) during this conversion.
IChatBaseComponent component = CraftChatMessage.fromString(page, true, true)[0];
pages.add(component);
}
}
}
}
CraftMetaBookSigned(NBTTagCompound tag) {
CraftMetaBookSigned(DataComponentPatch tag) {
super(tag);
getOrEmpty(tag, BOOK_CONTENT).ifPresent((written) -> {
this.title = written.title().raw();
this.author = written.author();
this.resolved = written.resolved();
this.generation = written.generation();
List<Filterable<IChatBaseComponent>> pages = written.pages();
this.pages = new ArrayList<IChatBaseComponent>(pages.size());
// Note: We explicitly check for and truncate oversized books and pages,
// because they can come directly from clients when handling book edits.
for (int i = 0; i < Math.min(pages.size(), MAX_PAGES); i++) {
IChatBaseComponent page = pages.get(i).raw();
this.pages.add(page);
}
});
}
CraftMetaBookSigned(Map<String, Object> map) {
super(map);
setAuthor(SerializableMeta.getString(map, BOOK_AUTHOR.BUKKIT, true));
setTitle(SerializableMeta.getString(map, BOOK_TITLE.BUKKIT, true));
Iterable<?> pages = SerializableMeta.getObject(Iterable.class, map, BOOK_PAGES.BUKKIT, true);
if (pages != null) {
this.pages = new ArrayList<IChatBaseComponent>();
for (Object page : pages) {
if (page instanceof String) {
internalAddPage(CraftChatMessage.fromJSON(CraftChatMessage.fromJSONOrStringToJSON((String) page, false, true, MAX_PAGE_LENGTH, false)));
}
}
}
resolved = SerializableMeta.getObject(Boolean.class, map, RESOLVED.BUKKIT, true);
generation = SerializableMeta.getObject(Integer.class, map, GENERATION.BUKKIT, true);
}
@Override
protected String deserializePage(String pageData) {
return CraftChatMessage.fromJSONOrStringToJSON(pageData, false, true, MAX_PAGE_LENGTH, false);
}
@Override
protected String convertPlainPageToData(String page) {
return CraftChatMessage.fromStringToJSON(page, true);
}
@Override
protected String convertDataToPlainPage(String pageData) {
return CraftChatMessage.fromJSONComponent(pageData);
}
@Override
void applyToItem(NBTTagCompound itemData) {
void applyToItem(CraftMetaItem.Applicator itemData) {
super.applyToItem(itemData);
if (pages != null) {
List<Filterable<IChatBaseComponent>> list = new ArrayList<>();
for (IChatBaseComponent page : pages) {
list.add(Filterable.passThrough(page));
}
itemData.put(BOOK_CONTENT, new WrittenBookContent(Filterable.from(FilteredText.passThrough(title)), this.author, this.generation, list, this.resolved));
}
}
@Override
boolean isEmpty() {
return super.isEmpty();
return super.isEmpty() && isBookEmpty();
}
boolean isBookEmpty() {
return !((pages != null) || hasAuthor() || hasTitle() || hasGeneration() || resolved);
}
@Override
boolean applicableTo(Material type) {
return type == Material.WRITTEN_BOOK || type == Material.WRITABLE_BOOK;
return type == Material.WRITTEN_BOOK;
}
@Override
public boolean hasAuthor() {
return this.author != null;
}
@Override
public boolean hasTitle() {
return this.title != null;
}
@Override
public boolean hasPages() {
return (pages != null) && !pages.isEmpty();
}
@Override
public boolean hasGeneration() {
return generation != 0;
}
@Override
public String getTitle() {
return this.title;
}
@Override
public boolean setTitle(final String title) {
if (title == null) {
this.title = null;
return true;
} else if (title.length() > MAX_TITLE_LENGTH) {
return false;
}
this.title = title;
return true;
}
@Override
public String getAuthor() {
return this.author;
}
@Override
public void setAuthor(final String author) {
this.author = author;
}
@Override
public Generation getGeneration() {
return Generation.values()[generation];
}
@Override
public void setGeneration(Generation generation) {
this.generation = (generation == null) ? 0 : generation.ordinal();
}
@Override
public String getPage(final int page) {
Preconditions.checkArgument(isValidPage(page), "Invalid page number (%s)", page);
// assert: pages != null
return CraftChatMessage.fromComponent(pages.get(page - 1));
}
@Override
public void setPage(final int page, final String text) {
Preconditions.checkArgument(isValidPage(page), "Invalid page number (%s/%s)", page, getPageCount());
// assert: pages != null
String newText = validatePage(text);
pages.set(page - 1, CraftChatMessage.fromStringOrNull(newText, true));
}
@Override
public void setPages(final String... pages) {
setPages(Arrays.asList(pages));
}
@Override
public void addPage(final String... pages) {
for (String page : pages) {
page = validatePage(page);
internalAddPage(CraftChatMessage.fromStringOrNull(page, true));
}
}
String validatePage(String page) {
if (page == null) {
page = "";
} else if (page.length() > MAX_PAGE_LENGTH) {
page = page.substring(0, MAX_PAGE_LENGTH);
}
return page;
}
private void internalAddPage(IChatBaseComponent page) {
// asserted: page != null
if (this.pages == null) {
this.pages = new ArrayList<IChatBaseComponent>();
} else if (this.pages.size() >= MAX_PAGES) {
return;
}
this.pages.add(page);
}
@Override
public int getPageCount() {
return (pages == null) ? 0 : pages.size();
}
@Override
public List<String> getPages() {
if (pages == null) return ImmutableList.of();
return pages.stream().map(CraftChatMessage::fromComponent).collect(ImmutableList.toImmutableList());
}
@Override
public void setPages(List<String> pages) {
if (pages.isEmpty()) {
this.pages = null;
return;
}
if (this.pages != null) {
this.pages.clear();
}
for (String page : pages) {
addPage(page);
}
}
private boolean isValidPage(int page) {
return page > 0 && page <= getPageCount();
}
// TODO Expose this attribute in Bukkit?
public boolean isResolved() {
return resolved;
}
public void setResolved(boolean resolved) {
this.resolved = resolved;
}
@Override
public CraftMetaBookSigned clone() {
CraftMetaBookSigned meta = (CraftMetaBookSigned) super.clone();
if (this.pages != null) {
meta.pages = new ArrayList<IChatBaseComponent>(this.pages);
}
return meta;
}
@@ -64,12 +299,34 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta {
int applyHash() {
final int original;
int hash = original = super.applyHash();
return original != hash ? CraftMetaBookSigned.class.hashCode() ^ hash : hash;
if (hasTitle()) {
hash = 61 * hash + this.title.hashCode();
}
if (hasAuthor()) {
hash = 61 * hash + 13 * this.author.hashCode();
}
if (this.pages != null) {
hash = 61 * hash + 17 * this.pages.hashCode();
}
hash = 61 * hash + 17 * Boolean.hashCode(resolved);
hash = 61 * hash + 19 * Integer.hashCode(generation);
return original != hash ? CraftMetaBook.class.hashCode() ^ hash : hash;
}
@Override
boolean equalsCommon(CraftMetaItem meta) {
return super.equalsCommon(meta);
if (!super.equalsCommon(meta)) {
return false;
}
if (meta instanceof CraftMetaBookSigned that) {
return (hasTitle() ? that.hasTitle() && this.title.equals(that.title) : !that.hasTitle())
&& (hasAuthor() ? that.hasAuthor() && this.author.equals(that.author) : !that.hasAuthor())
&& (Objects.equals(this.pages, that.pages))
&& (Objects.equals(this.resolved, that.resolved))
&& (Objects.equals(this.generation, that.generation));
}
return true;
}
@Override
@@ -80,6 +337,27 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta {
@Override
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
if (hasTitle()) {
builder.put(BOOK_TITLE.BUKKIT, title);
}
if (hasAuthor()) {
builder.put(BOOK_AUTHOR.BUKKIT, author);
}
if (pages != null) {
builder.put(BOOK_PAGES.BUKKIT, ImmutableList.copyOf(pages));
}
if (resolved) {
builder.put(RESOLVED.BUKKIT, resolved);
}
if (generation != 0) {
builder.put(GENERATION.BUKKIT, generation);
}
return builder;
}
}

View File

@@ -6,18 +6,18 @@ import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.BundleContents;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BundleMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaBundle extends CraftMetaItem implements BundleMeta {
static final ItemMetaKey ITEMS = new ItemMetaKey("Items", "items");
static final ItemMetaKeyType<BundleContents> ITEMS = new ItemMetaKeyType<>(DataComponents.BUNDLE_CONTENTS, "items");
//
private List<ItemStack> items;
@@ -35,25 +35,18 @@ public class CraftMetaBundle extends CraftMetaItem implements BundleMeta {
}
}
CraftMetaBundle(NBTTagCompound tag) {
CraftMetaBundle(DataComponentPatch tag) {
super(tag);
if (tag.contains(ITEMS.NBT, CraftMagicNumbers.NBT.TAG_LIST)) {
NBTTagList list = tag.getList(ITEMS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
getOrEmpty(tag, ITEMS).ifPresent((bundle) -> {
bundle.items().forEach((item) -> {
ItemStack itemStack = CraftItemStack.asCraftMirror(item);
if (list != null && !list.isEmpty()) {
items = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
NBTTagCompound nbttagcompound1 = list.getCompound(i);
ItemStack itemStack = CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(nbttagcompound1));
if (!itemStack.getType().isAir()) { // SPIGOT-7174 - Avoid adding air
addItem(itemStack);
}
if (!itemStack.getType().isAir()) { // SPIGOT-7174 - Avoid adding air
addItem(itemStack);
}
}
}
});
});
}
CraftMetaBundle(Map<String, Object> map) {
@@ -70,19 +63,17 @@ public class CraftMetaBundle extends CraftMetaItem implements BundleMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (hasItems()) {
NBTTagList list = new NBTTagList();
List<net.minecraft.world.item.ItemStack> list = new ArrayList<>();
for (ItemStack item : items) {
NBTTagCompound saved = new NBTTagCompound();
CraftItemStack.asNMSCopy(item).save(saved);
list.add(saved);
list.add(CraftItemStack.asNMSCopy(item));
}
tag.put(ITEMS.NBT, list);
tag.put(ITEMS, new BundleContents(list));
}
}

View File

@@ -2,16 +2,17 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.FireworkExplosion;
import org.bukkit.FireworkEffect;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.inventory.meta.FireworkEffectMeta;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaCharge extends CraftMetaItem implements FireworkEffectMeta {
static final ItemMetaKey EXPLOSION = new ItemMetaKey("Explosion", "firework-effect");
static final ItemMetaKeyType<FireworkExplosion> EXPLOSION = new ItemMetaKeyType<>(DataComponents.FIREWORK_EXPLOSION, "firework-effect");
private FireworkEffect effect;
@@ -29,16 +30,16 @@ class CraftMetaCharge extends CraftMetaItem implements FireworkEffectMeta {
setEffect(SerializableMeta.getObject(FireworkEffect.class, map, EXPLOSION.BUKKIT, true));
}
CraftMetaCharge(NBTTagCompound tag) {
CraftMetaCharge(DataComponentPatch tag) {
super(tag);
if (tag.contains(EXPLOSION.NBT)) {
getOrEmpty(tag, EXPLOSION).ifPresent((f) -> {
try {
effect = CraftMetaFirework.getEffect(tag.getCompound(EXPLOSION.NBT));
effect = CraftMetaFirework.getEffect(f);
} catch (IllegalArgumentException ex) {
// Ignore invalid effects
}
}
});
}
@Override
@@ -57,11 +58,11 @@ class CraftMetaCharge extends CraftMetaItem implements FireworkEffectMeta {
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
if (hasEffect()) {
itemTag.put(EXPLOSION.NBT, CraftMetaFirework.getExplosion(effect));
itemTag.put(EXPLOSION, CraftMetaFirework.getExplosion(effect));
}
}

View File

@@ -5,13 +5,13 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.component.DataComponentPatch;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.inventory.meta.ColorableArmorMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaColorableArmor extends CraftMetaArmor implements ColorableArmorMeta {
private static final Set<Material> LEATHER_ARMOR_MATERIALS = Sets.newHashSet(
@@ -28,7 +28,7 @@ public class CraftMetaColorableArmor extends CraftMetaArmor implements Colorable
CraftMetaLeatherArmor.readColor(this, meta);
}
CraftMetaColorableArmor(NBTTagCompound tag) {
CraftMetaColorableArmor(DataComponentPatch tag) {
super(tag);
CraftMetaLeatherArmor.readColor(this, tag);
}
@@ -39,7 +39,7 @@ public class CraftMetaColorableArmor extends CraftMetaArmor implements Colorable
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
CraftMetaLeatherArmor.applyColor(this, itemTag);
}

View File

@@ -2,16 +2,18 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap.Builder;
import com.mojang.serialization.DataResult;
import java.util.Map;
import java.util.Optional;
import net.minecraft.nbt.DynamicOpsNBT;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.item.component.LodestoneTracker;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@@ -19,22 +21,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.inventory.meta.CompassMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
static final ItemMetaKey LODESTONE_DIMENSION = new ItemMetaKey("LodestoneDimension");
static final ItemMetaKey LODESTONE_POS = new ItemMetaKey("LodestonePos", "lodestone");
static final ItemMetaKeyType<LodestoneTracker> LODESTONE_TARGET = new ItemMetaKeyType<>(DataComponents.LODESTONE_TRACKER, "LodestoneDimension");
static final ItemMetaKey LODESTONE_POS = new ItemMetaKey("lodestone");
static final ItemMetaKey LODESTONE_POS_WORLD = new ItemMetaKey("LodestonePosWorld");
static final ItemMetaKey LODESTONE_POS_X = new ItemMetaKey("LodestonePosX");
static final ItemMetaKey LODESTONE_POS_Y = new ItemMetaKey("LodestonePosY");
static final ItemMetaKey LODESTONE_POS_Z = new ItemMetaKey("LodestonePosZ");
static final ItemMetaKey LODESTONE_TRACKED = new ItemMetaKey("LodestoneTracked");
private NBTTagString lodestoneWorld;
private ResourceKey<net.minecraft.world.level.World> lodestoneWorld;
private int lodestoneX;
private int lodestoneY;
private int lodestoneZ;
private Boolean tracked;
private boolean tracked = true;
CraftMetaCompass(CraftMetaItem meta) {
super(meta);
@@ -49,25 +51,25 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
tracked = compassMeta.tracked;
}
CraftMetaCompass(NBTTagCompound tag) {
CraftMetaCompass(DataComponentPatch tag) {
super(tag);
if (tag.contains(LODESTONE_DIMENSION.NBT) && tag.contains(LODESTONE_POS.NBT)) {
lodestoneWorld = (NBTTagString) tag.get(LODESTONE_DIMENSION.NBT);
NBTTagCompound pos = tag.getCompound(LODESTONE_POS.NBT);
lodestoneX = pos.getInt("X");
lodestoneY = pos.getInt("Y");
lodestoneZ = pos.getInt("Z");
}
if (tag.contains(LODESTONE_TRACKED.NBT)) {
tracked = tag.getBoolean(LODESTONE_TRACKED.NBT);
}
getOrEmpty(tag, LODESTONE_TARGET).ifPresent((lodestoneTarget) -> {
lodestoneTarget.target().ifPresent((target) -> {
lodestoneWorld = target.dimension();
BlockPosition pos = target.pos();
lodestoneX = pos.getX();
lodestoneY = pos.getY();
lodestoneZ = pos.getZ();
});
tracked = lodestoneTarget.tracked();
});
}
CraftMetaCompass(Map<String, Object> map) {
super(map);
String lodestoneWorldString = SerializableMeta.getString(map, LODESTONE_POS_WORLD.BUKKIT, true);
if (lodestoneWorldString != null) {
lodestoneWorld = NBTTagString.valueOf(lodestoneWorldString);
lodestoneWorld = ResourceKey.create(Registries.DIMENSION, MinecraftKey.tryParse(lodestoneWorldString));
lodestoneX = (Integer) map.get(LODESTONE_POS_X.BUKKIT);
lodestoneY = (Integer) map.get(LODESTONE_POS_Y.BUKKIT);
lodestoneZ = (Integer) map.get(LODESTONE_POS_Z.BUKKIT);
@@ -82,20 +84,16 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
Optional<GlobalPos> target = Optional.empty();
if (lodestoneWorld != null) {
NBTTagCompound pos = new NBTTagCompound();
pos.putInt("X", lodestoneX);
pos.putInt("Y", lodestoneY);
pos.putInt("Z", lodestoneZ);
tag.put(LODESTONE_POS.NBT, pos);
tag.put(LODESTONE_DIMENSION.NBT, lodestoneWorld);
target = Optional.of(new GlobalPos(lodestoneWorld, new BlockPosition(lodestoneX, lodestoneY, lodestoneZ)));
}
if (tracked != null) {
tag.putBoolean(LODESTONE_TRACKED.NBT, tracked);
if (target.isPresent() || hasLodestoneTracked()) {
tag.put(LODESTONE_TARGET, new LodestoneTracker(target, tracked));
}
}
@@ -129,8 +127,7 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
if (lodestoneWorld == null) {
return null;
}
Optional<ResourceKey<net.minecraft.world.level.World>> key = net.minecraft.world.level.World.RESOURCE_KEY_CODEC.parse(DynamicOpsNBT.INSTANCE, lodestoneWorld).result();
WorldServer worldServer = key.isPresent() ? MinecraftServer.getServer().getLevel(key.get()) : null;
WorldServer worldServer = MinecraftServer.getServer().getLevel(lodestoneWorld);
World world = worldServer != null ? worldServer.getWorld() : null;
return new Location(world, lodestoneX, lodestoneY, lodestoneZ); // world may be null here, if the referenced world is not loaded
}
@@ -141,9 +138,7 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
if (lodestone == null) {
this.lodestoneWorld = null;
} else {
ResourceKey<net.minecraft.world.level.World> key = ((CraftWorld) lodestone.getWorld()).getHandle().dimension();
DataResult<NBTBase> dataresult = net.minecraft.world.level.World.RESOURCE_KEY_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, key);
this.lodestoneWorld = (NBTTagString) dataresult.get().orThrow();
this.lodestoneWorld = ((CraftWorld) lodestone.getWorld()).getHandle().dimension();
this.lodestoneX = lodestone.getBlockX();
this.lodestoneY = lodestone.getBlockY();
this.lodestoneZ = lodestone.getBlockZ();
@@ -151,12 +146,12 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
}
boolean hasLodestoneTracked() {
return tracked != null;
return !tracked;
}
@Override
public boolean isLodestoneTracked() {
return hasLodestoneTracked() && tracked;
return tracked;
}
@Override
@@ -174,9 +169,7 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
hash = 73 * hash + lodestoneY;
hash = 73 * hash + lodestoneZ;
}
if (hasLodestoneTracked()) {
hash = 73 * hash + (isLodestoneTracked() ? 1231 : 1237);
}
hash = 73 * hash + (isLodestoneTracked() ? 1231 : 1237);
return original != hash ? CraftMetaCompass.class.hashCode() ^ hash : hash;
}
@@ -189,7 +182,7 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
if (meta instanceof CraftMetaCompass) {
CraftMetaCompass that = (CraftMetaCompass) meta;
return (this.hasLodestone() ? that.hasLodestone() && this.lodestoneWorld.getAsString().equals(that.lodestoneWorld.getAsString())
return (this.hasLodestone() ? that.hasLodestone() && this.lodestoneWorld.equals(that.lodestoneWorld)
&& this.lodestoneX == that.lodestoneX && this.lodestoneY == that.lodestoneY
&& this.lodestoneZ == that.lodestoneZ : !that.hasLodestone())
&& this.tracked == that.tracked;
@@ -207,14 +200,12 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
super.serialize(builder);
if (hasLodestone()) {
builder.put(LODESTONE_POS_WORLD.BUKKIT, lodestoneWorld.getAsString());
builder.put(LODESTONE_POS_WORLD.BUKKIT, lodestoneWorld.location().toString());
builder.put(LODESTONE_POS_X.BUKKIT, lodestoneX);
builder.put(LODESTONE_POS_Y.BUKKIT, lodestoneY);
builder.put(LODESTONE_POS_Z.BUKKIT, lodestoneZ);
}
if (hasLodestoneTracked()) {
builder.put(LODESTONE_TRACKED.BUKKIT, tracked);
}
builder.put(LODESTONE_TRACKED.BUKKIT, tracked);
return builder;
}

View File

@@ -6,22 +6,21 @@ import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.ItemArrow;
import net.minecraft.world.item.component.ChargedProjectiles;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.CrossbowMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
static final ItemMetaKey CHARGED = new ItemMetaKey("Charged", "charged");
static final ItemMetaKey CHARGED_PROJECTILES = new ItemMetaKey("ChargedProjectiles", "charged-projectiles");
static final ItemMetaKey CHARGED = new ItemMetaKey("charged");
static final ItemMetaKeyType<ChargedProjectiles> CHARGED_PROJECTILES = new ItemMetaKeyType<>(DataComponents.CHARGED_PROJECTILES, "charged-projectiles");
//
private boolean charged;
private List<ItemStack> chargedProjectiles;
CraftMetaCrossbow(CraftMetaItem meta) {
@@ -32,41 +31,32 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
}
CraftMetaCrossbow crossbow = (CraftMetaCrossbow) meta;
this.charged = crossbow.charged;
if (crossbow.hasChargedProjectiles()) {
this.chargedProjectiles = new ArrayList<>(crossbow.chargedProjectiles);
}
}
CraftMetaCrossbow(NBTTagCompound tag) {
CraftMetaCrossbow(DataComponentPatch tag) {
super(tag);
charged = tag.getBoolean(CHARGED.NBT);
if (tag.contains(CHARGED_PROJECTILES.NBT, CraftMagicNumbers.NBT.TAG_LIST)) {
NBTTagList list = tag.getList(CHARGED_PROJECTILES.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
getOrEmpty(tag, CHARGED_PROJECTILES).ifPresent((p) -> {
List<net.minecraft.world.item.ItemStack> list = p.getItems();
if (list != null && !list.isEmpty()) {
chargedProjectiles = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
NBTTagCompound nbttagcompound1 = list.getCompound(i);
net.minecraft.world.item.ItemStack nbttagcompound1 = list.get(i);
chargedProjectiles.add(CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(nbttagcompound1)));
chargedProjectiles.add(CraftItemStack.asCraftMirror(nbttagcompound1));
}
}
}
});
}
CraftMetaCrossbow(Map<String, Object> map) {
super(map);
Boolean charged = SerializableMeta.getObject(Boolean.class, map, CHARGED.BUKKIT, true);
if (charged != null) {
this.charged = charged;
}
Iterable<?> projectiles = SerializableMeta.getObject(Iterable.class, map, CHARGED_PROJECTILES.BUKKIT, true);
if (projectiles != null) {
for (Object stack : projectiles) {
@@ -78,20 +68,17 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
tag.putBoolean(CHARGED.NBT, charged);
if (hasChargedProjectiles()) {
NBTTagList list = new NBTTagList();
List<net.minecraft.world.item.ItemStack> list = new ArrayList<>();
for (ItemStack item : chargedProjectiles) {
NBTTagCompound saved = new NBTTagCompound();
CraftItemStack.asNMSCopy(item).save(saved);
list.add(saved);
list.add(CraftItemStack.asNMSCopy(item));
}
tag.put(CHARGED_PROJECTILES.NBT, list);
tag.put(CHARGED_PROJECTILES, ChargedProjectiles.of(list));
}
}
@@ -122,7 +109,6 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
@Override
public void setChargedProjectiles(List<ItemStack> projectiles) {
chargedProjectiles = null;
charged = false;
if (projectiles == null) {
return;
@@ -142,7 +128,6 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
chargedProjectiles = new ArrayList<>();
}
charged = true;
chargedProjectiles.add(item);
}
@@ -154,8 +139,7 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
if (meta instanceof CraftMetaCrossbow) {
CraftMetaCrossbow that = (CraftMetaCrossbow) meta;
return this.charged == that.charged
&& (hasChargedProjectiles() ? that.hasChargedProjectiles() && this.chargedProjectiles.equals(that.chargedProjectiles) : !that.hasChargedProjectiles());
return (hasChargedProjectiles() ? that.hasChargedProjectiles() && this.chargedProjectiles.equals(that.chargedProjectiles) : !that.hasChargedProjectiles());
}
return true;
}
@@ -171,7 +155,6 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
int hash = original = super.applyHash();
if (hasChargedProjectiles()) {
hash = 61 * hash + (this.charged ? 1 : 0);
hash = 61 * hash + chargedProjectiles.hashCode();
}
@@ -187,7 +170,6 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
super.serialize(builder);
builder.put(CHARGED.BUKKIT, charged);
if (hasChargedProjectiles()) {
builder.put(CHARGED_PROJECTILES.BUKKIT, chargedProjectiles);
}

View File

@@ -4,16 +4,18 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.LinkedHashMap;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorageMeta {
static final ItemMetaKey STORED_ENCHANTMENTS = new ItemMetaKey("StoredEnchantments", "stored-enchants");
static final ItemMetaKeyType<ItemEnchantments> STORED_ENCHANTMENTS = new ItemMetaKeyType<>(DataComponents.STORED_ENCHANTMENTS, "stored-enchants");
private Map<Enchantment, Integer> enchantments;
@@ -31,14 +33,15 @@ class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorage
}
}
CraftMetaEnchantedBook(NBTTagCompound tag) {
CraftMetaEnchantedBook(DataComponentPatch tag) {
super(tag);
if (!tag.contains(STORED_ENCHANTMENTS.NBT)) {
return;
}
enchantments = buildEnchantments(tag, STORED_ENCHANTMENTS);
getOrEmpty(tag, STORED_ENCHANTMENTS).ifPresent((itemEnchantments) -> {
enchantments = buildEnchantments(itemEnchantments);
if (!itemEnchantments.showInTooltip) {
addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
}
});
}
CraftMetaEnchantedBook(Map<String, Object> map) {
@@ -48,10 +51,10 @@ class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorage
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
applyEnchantments(enchantments, itemTag, STORED_ENCHANTMENTS);
applyEnchantments(enchantments, itemTag, STORED_ENCHANTMENTS, ItemFlag.HIDE_POTION_EFFECTS);
}
@Override

View File

@@ -4,12 +4,15 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaEntityTag extends CraftMetaItem {
private static final Set<Material> ENTITY_TAGGABLE_MATERIALS = Sets.newHashSet(
@@ -21,7 +24,7 @@ public class CraftMetaEntityTag extends CraftMetaItem {
Material.PAINTING
);
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.ENTITY_DATA, "EntityTag", "entity-tag");
NBTTagCompound entityTag;
CraftMetaEntityTag(CraftMetaItem meta) {
@@ -35,12 +38,12 @@ public class CraftMetaEntityTag extends CraftMetaItem {
this.entityTag = entity.entityTag;
}
CraftMetaEntityTag(NBTTagCompound tag) {
CraftMetaEntityTag(DataComponentPatch tag) {
super(tag);
if (tag.contains(ENTITY_TAG.NBT)) {
entityTag = tag.getCompound(ENTITY_TAG.NBT).copy();
}
getOrEmpty(tag, ENTITY_TAG).ifPresent((nbt) -> {
entityTag = nbt.copyTag();
});
}
CraftMetaEntityTag(Map<String, Object> map) {
@@ -64,11 +67,11 @@ public class CraftMetaEntityTag extends CraftMetaItem {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (entityTag != null) {
tag.put(ENTITY_TAG.NBT, entityTag);
tag.put(ENTITY_TAG, CustomData.of(entityTag));
}
}

View File

@@ -3,12 +3,15 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap.Builder;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.FireworkExplosion;
import net.minecraft.world.item.component.Fireworks;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.FireworkEffect.Type;
@@ -16,8 +19,6 @@ import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific.To;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.FireworkMeta;
@DelegateDeserialization(SerializableMeta.class)
@@ -38,22 +39,12 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
*/
@Specific(To.NBT)
static final ItemMetaKey FIREWORKS = new ItemMetaKey("Fireworks");
static final ItemMetaKey FLIGHT = new ItemMetaKey("Flight", "power");
static final ItemMetaKey EXPLOSIONS = new ItemMetaKey("Explosions", "firework-effects");
@Specific(To.NBT)
static final ItemMetaKey EXPLOSION_COLORS = new ItemMetaKey("Colors");
@Specific(To.NBT)
static final ItemMetaKey EXPLOSION_TYPE = new ItemMetaKey("Type");
@Specific(To.NBT)
static final ItemMetaKey EXPLOSION_TRAIL = new ItemMetaKey("Trail");
@Specific(To.NBT)
static final ItemMetaKey EXPLOSION_FLICKER = new ItemMetaKey("Flicker");
@Specific(To.NBT)
static final ItemMetaKey EXPLOSION_FADE = new ItemMetaKey("FadeColors");
static final ItemMetaKeyType<Fireworks> FIREWORKS = new ItemMetaKeyType<>(DataComponents.FIREWORKS, "Fireworks");
static final ItemMetaKey FLIGHT = new ItemMetaKey("power");
static final ItemMetaKey EXPLOSIONS = new ItemMetaKey("firework-effects");
private List<FireworkEffect> effects;
private Integer power;
private int power;
CraftMetaFirework(CraftMetaItem meta) {
super(meta);
@@ -69,44 +60,36 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
}
}
CraftMetaFirework(NBTTagCompound tag) {
CraftMetaFirework(DataComponentPatch tag) {
super(tag);
if (!tag.contains(FIREWORKS.NBT)) {
return;
}
getOrEmpty(tag, FIREWORKS).ifPresent((fireworks) -> {
power = fireworks.flightDuration();
NBTTagCompound fireworks = tag.getCompound(FIREWORKS.NBT);
List<FireworkExplosion> fireworkEffects = fireworks.explosions();
List<FireworkEffect> effects = this.effects = new ArrayList<FireworkEffect>(fireworkEffects.size());
power = (int) fireworks.getByte(FLIGHT.NBT);
if (!fireworks.contains(EXPLOSIONS.NBT)) {
return;
}
NBTTagList fireworkEffects = fireworks.getList(EXPLOSIONS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
List<FireworkEffect> effects = this.effects = new ArrayList<FireworkEffect>(fireworkEffects.size());
for (int i = 0; i < fireworkEffects.size(); i++) {
try {
effects.add(getEffect((NBTTagCompound) fireworkEffects.get(i)));
} catch (IllegalArgumentException ex) {
// Ignore invalid effects
for (int i = 0; i < fireworkEffects.size(); i++) {
try {
effects.add(getEffect(fireworkEffects.get(i)));
} catch (IllegalArgumentException ex) {
// Ignore invalid effects
}
}
}
});
}
static FireworkEffect getEffect(NBTTagCompound explosion) {
static FireworkEffect getEffect(FireworkExplosion explosion) {
FireworkEffect.Builder effect = FireworkEffect.builder()
.flicker(explosion.getBoolean(EXPLOSION_FLICKER.NBT))
.trail(explosion.getBoolean(EXPLOSION_TRAIL.NBT))
.with(getEffectType(0xff & explosion.getByte(EXPLOSION_TYPE.NBT)));
.flicker(explosion.hasTwinkle())
.trail(explosion.hasTrail())
.with(getEffectType(explosion.shape()));
int[] colors = explosion.getIntArray(EXPLOSION_COLORS.NBT);
IntList colors = explosion.colors();
// People using buggy command generators specify a list rather than an int here, so recover with dummy data.
// Wrong: Colors: [1234]
// Right: Colors: [I;1234]
if (colors.length == 0) {
if (colors.isEmpty()) {
effect.withColor(Color.WHITE);
}
@@ -114,60 +97,48 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
effect.withColor(Color.fromRGB(color));
}
for (int color : explosion.getIntArray(EXPLOSION_FADE.NBT)) {
for (int color : explosion.fadeColors()) {
effect.withFade(Color.fromRGB(color));
}
return effect.build();
}
static NBTTagCompound getExplosion(FireworkEffect effect) {
NBTTagCompound explosion = new NBTTagCompound();
static FireworkExplosion getExplosion(FireworkEffect effect) {
IntList colors = addColors(effect.getColors());
IntList fadeColors = addColors(effect.getFadeColors());
if (effect.hasFlicker()) {
explosion.putBoolean(EXPLOSION_FLICKER.NBT, true);
}
if (effect.hasTrail()) {
explosion.putBoolean(EXPLOSION_TRAIL.NBT, true);
}
addColors(explosion, EXPLOSION_COLORS, effect.getColors());
addColors(explosion, EXPLOSION_FADE, effect.getFadeColors());
explosion.putByte(EXPLOSION_TYPE.NBT, (byte) getNBT(effect.getType()));
return explosion;
return new FireworkExplosion(getNBT(effect.getType()), colors, fadeColors, effect.hasTrail(), effect.hasFlicker());
}
static int getNBT(Type type) {
static FireworkExplosion.a getNBT(Type type) {
switch (type) {
case BALL:
return 0;
return FireworkExplosion.a.SMALL_BALL;
case BALL_LARGE:
return 1;
return FireworkExplosion.a.LARGE_BALL;
case STAR:
return 2;
return FireworkExplosion.a.STAR;
case CREEPER:
return 3;
return FireworkExplosion.a.CREEPER;
case BURST:
return 4;
return FireworkExplosion.a.BURST;
default:
throw new IllegalArgumentException("Unknown effect type " + type);
}
}
static Type getEffectType(int nbt) {
static Type getEffectType(FireworkExplosion.a nbt) {
switch (nbt) {
case 0:
case SMALL_BALL:
return Type.BALL;
case 1:
case LARGE_BALL:
return Type.BALL_LARGE;
case 2:
case STAR:
return Type.STAR;
case 3:
case CREEPER:
return Type.CREEPER;
case 4:
case BURST:
return Type.BURST;
default:
throw new IllegalArgumentException("Unknown effect type " + nbt);
@@ -208,34 +179,23 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
if (isFireworkEmpty()) {
return;
}
NBTTagCompound fireworks = itemTag.getCompound(FIREWORKS.NBT);
itemTag.put(FIREWORKS.NBT, fireworks);
if (hasEffects()) {
NBTTagList effects = new NBTTagList();
for (FireworkEffect effect : this.effects) {
effects.add(getExplosion(effect));
}
if (effects.size() > 0) {
fireworks.put(EXPLOSIONS.NBT, effects);
}
List<FireworkExplosion> effects = new ArrayList<>();
for (FireworkEffect effect : this.effects) {
effects.add(getExplosion(effect));
}
if (hasPower()) {
fireworks.putByte(FLIGHT.NBT, power.byteValue());
}
itemTag.put(FIREWORKS, new Fireworks(power, effects));
}
static void addColors(NBTTagCompound compound, ItemMetaKey key, List<Color> colors) {
static IntList addColors(List<Color> colors) {
if (colors.isEmpty()) {
return;
return IntList.of();
}
final int[] colorArray = new int[colors.size()];
@@ -244,7 +204,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
colorArray[i++] = color.asRGB();
}
compound.putIntArray(key.NBT, colorArray);
return IntList.of(colorArray);
}
@Override
@@ -262,7 +222,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
}
boolean hasPower() {
return power != null && power != 0;
return power != 0;
}
@Override

View File

@@ -5,20 +5,19 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.MinecraftKey;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.meta.KnowledgeBookMeta;
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaKnowledgeBook extends CraftMetaItem implements KnowledgeBookMeta {
static final ItemMetaKey BOOK_RECIPES = new ItemMetaKey("Recipes");
static final ItemMetaKeyType<List<MinecraftKey>> BOOK_RECIPES = new ItemMetaKeyType<>(DataComponents.RECIPES, "Recipes");
static final int MAX_RECIPES = Short.MAX_VALUE;
protected List<NamespacedKey> recipes = new ArrayList<NamespacedKey>();
@@ -32,18 +31,16 @@ public class CraftMetaKnowledgeBook extends CraftMetaItem implements KnowledgeBo
}
}
CraftMetaKnowledgeBook(NBTTagCompound tag) {
CraftMetaKnowledgeBook(DataComponentPatch tag) {
super(tag);
if (tag.contains(BOOK_RECIPES.NBT)) {
NBTTagList pages = tag.getList(BOOK_RECIPES.NBT, 8);
getOrEmpty(tag, BOOK_RECIPES).ifPresent((pages) -> {
for (int i = 0; i < pages.size(); i++) {
String recipe = pages.getString(i);
MinecraftKey recipe = pages.get(i);
addRecipe(CraftNamespacedKey.fromString(recipe));
addRecipe(CraftNamespacedKey.fromMinecraft(recipe));
}
}
});
}
CraftMetaKnowledgeBook(Map<String, Object> map) {
@@ -60,15 +57,15 @@ public class CraftMetaKnowledgeBook extends CraftMetaItem implements KnowledgeBo
}
@Override
void applyToItem(NBTTagCompound itemData) {
void applyToItem(CraftMetaItem.Applicator itemData) {
super.applyToItem(itemData);
if (hasRecipes()) {
NBTTagList list = new NBTTagList();
List<MinecraftKey> list = new ArrayList<>();
for (NamespacedKey recipe : this.recipes) {
list.add(NBTTagString.valueOf(recipe.toString()));
list.add(CraftNamespacedKey.toMinecraft(recipe));
}
itemData.put(BOOK_RECIPES.NBT, list);
itemData.put(BOOK_RECIPES, list);
}
}

View File

@@ -5,12 +5,13 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.DyedItemColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.meta.LeatherArmorMeta;
@DelegateDeserialization(SerializableMeta.class)
@@ -21,10 +22,11 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
Material.LEATHER_HORSE_ARMOR,
Material.LEATHER_CHESTPLATE,
Material.LEATHER_LEGGINGS,
Material.LEATHER_BOOTS
Material.LEATHER_BOOTS,
Material.WOLF_ARMOR
);
static final ItemMetaKey COLOR = new ItemMetaKey("color");
static final ItemMetaKeyType<DyedItemColor> COLOR = new ItemMetaKeyType<>(DataComponents.DYED_COLOR, "color");
private Color color = DEFAULT_LEATHER_COLOR;
@@ -33,7 +35,7 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
readColor(this, meta);
}
CraftMetaLeatherArmor(NBTTagCompound tag) {
CraftMetaLeatherArmor(DataComponentPatch tag) {
super(tag);
readColor(this, tag);
}
@@ -44,7 +46,7 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
}
@Override
void applyToItem(NBTTagCompound itemTag) {
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
applyColor(this, itemTag);
}
@@ -127,17 +129,18 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
meta.setColor(armorMeta.color);
}
static void readColor(LeatherArmorMeta meta, NBTTagCompound tag) {
if (tag.contains(DISPLAY.NBT)) {
NBTTagCompound display = tag.getCompound(DISPLAY.NBT);
if (display.contains(COLOR.NBT)) {
try {
meta.setColor(Color.fromRGB(display.getInt(COLOR.NBT)));
} catch (IllegalArgumentException ex) {
// Invalid colour
}
static void readColor(LeatherArmorMeta meta, DataComponentPatch tag) {
getOrEmpty(tag, COLOR).ifPresent((dyedItemColor) -> {
if (!dyedItemColor.showInTooltip()) {
meta.addItemFlags(ItemFlag.HIDE_DYE);
}
}
try {
meta.setColor(Color.fromRGB(dyedItemColor.rgb()));
} catch (IllegalArgumentException ex) {
// Invalid colour
}
});
}
static void readColor(LeatherArmorMeta meta, Map<String, Object> map) {
@@ -148,9 +151,9 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
return !DEFAULT_LEATHER_COLOR.equals(meta.getColor());
}
static void applyColor(LeatherArmorMeta meta, NBTTagCompound tag) {
static void applyColor(LeatherArmorMeta meta, CraftMetaItem.Applicator tag) {
if (hasColor(meta)) {
((CraftMetaItem) meta).setDisplayTag(tag, COLOR.NBT, NBTTagInt.valueOf(meta.getColor().asRGB()));
tag.put(COLOR, new DyedItemColor(meta.getColor().asRGB(), !meta.hasItemFlag(ItemFlag.HIDE_DYE)));
}
}

View File

@@ -3,25 +3,27 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.MapItemColor;
import net.minecraft.world.item.component.MapPostProcessing;
import net.minecraft.world.level.saveddata.maps.MapId;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.map.MapView;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaMap extends CraftMetaItem implements MapMeta {
static final ItemMetaKey MAP_SCALING = new ItemMetaKey("map_is_scaling", "scaling");
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKeyType<MapPostProcessing> MAP_POST_PROCESSING = new ItemMetaKeyType<>(DataComponents.MAP_POST_PROCESSING);
static final ItemMetaKey MAP_SCALING = new ItemMetaKey("scaling");
@Deprecated // SPIGOT-6308
static final ItemMetaKey MAP_LOC_NAME = new ItemMetaKey("LocName", "display-loc-name");
static final ItemMetaKey MAP_COLOR = new ItemMetaKey("MapColor", "display-map-color");
static final ItemMetaKey MAP_ID = new ItemMetaKey("map", "map-id");
static final ItemMetaKey MAP_LOC_NAME = new ItemMetaKey("display-loc-name");
static final ItemMetaKeyType<MapItemColor> MAP_COLOR = new ItemMetaKeyType<>(DataComponents.MAP_COLOR, "display-map-color");
static final ItemMetaKeyType<MapId> MAP_ID = new ItemMetaKeyType<>(DataComponents.MAP_ID, "map-id");
static final byte SCALING_EMPTY = (byte) 0;
static final byte SCALING_TRUE = (byte) 1;
static final byte SCALING_FALSE = (byte) 2;
@@ -43,28 +45,24 @@ class CraftMetaMap extends CraftMetaItem implements MapMeta {
this.color = map.color;
}
CraftMetaMap(NBTTagCompound tag) {
CraftMetaMap(DataComponentPatch tag) {
super(tag);
if (tag.contains(MAP_ID.NBT, CraftMagicNumbers.NBT.TAG_ANY_NUMBER)) {
this.mapId = tag.getInt(MAP_ID.NBT);
}
getOrEmpty(tag, MAP_ID).ifPresent((mapId) -> {
this.mapId = mapId.id();
});
if (tag.contains(MAP_SCALING.NBT)) {
this.scaling = tag.getBoolean(MAP_SCALING.NBT) ? SCALING_TRUE : SCALING_FALSE;
}
getOrEmpty(tag, MAP_POST_PROCESSING).ifPresent((mapPostProcessing) -> {
this.scaling = (mapPostProcessing == MapPostProcessing.SCALE) ? SCALING_TRUE : SCALING_FALSE;
});
if (tag.contains(DISPLAY.NBT)) {
NBTTagCompound display = tag.getCompound(DISPLAY.NBT);
if (display.contains(MAP_COLOR.NBT)) {
try {
color = Color.fromRGB(display.getInt(MAP_COLOR.NBT));
} catch (IllegalArgumentException ex) {
// Invalid colour
}
getOrEmpty(tag, MAP_COLOR).ifPresent((mapColor) -> {
try {
color = Color.fromRGB(mapColor.rgb());
} catch (IllegalArgumentException ex) {
// Invalid colour
}
}
});
}
CraftMetaMap(Map<String, Object> map) {
@@ -92,23 +90,19 @@ class CraftMetaMap extends CraftMetaItem implements MapMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (hasMapId()) {
tag.putInt(MAP_ID.NBT, getMapId());
tag.put(MAP_ID, new MapId(getMapId()));
}
if (hasScaling()) {
tag.putBoolean(MAP_SCALING.NBT, isScaling());
}
if (hasLocationName()) {
setDisplayTag(tag, MAP_LOC_NAME.NBT, NBTTagString.valueOf(getLocationName()));
tag.put(MAP_POST_PROCESSING, (isScaling()) ? MapPostProcessing.SCALE : MapPostProcessing.LOCK);
}
if (hasColor()) {
setDisplayTag(tag, MAP_COLOR.NBT, NBTTagInt.valueOf(color.asRGB()));
tag.put(MAP_COLOR, new MapItemColor(color.asRGB()));
}
}

View File

@@ -2,18 +2,22 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.Instrument;
import org.bukkit.Material;
import org.bukkit.MusicInstrument;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.CraftMusicInstrument;
import org.bukkit.inventory.meta.MusicInstrumentMeta;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInstrumentMeta {
static final ItemMetaKey GOAT_HORN_INSTRUMENT = new ItemMetaKey("instrument");
static final ItemMetaKeyType<Holder<Instrument>> GOAT_HORN_INSTRUMENT = new ItemMetaKeyType<>(DataComponents.INSTRUMENT, "instrument");
private MusicInstrument instrument;
CraftMetaMusicInstrument(CraftMetaItem meta) {
@@ -25,13 +29,12 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst
}
}
CraftMetaMusicInstrument(NBTTagCompound tag) {
CraftMetaMusicInstrument(DataComponentPatch tag) {
super(tag);
if (tag.contains(GOAT_HORN_INSTRUMENT.NBT)) {
String string = tag.getString(GOAT_HORN_INSTRUMENT.NBT);
this.instrument = Registry.INSTRUMENT.get(NamespacedKey.fromString(string));
}
getOrEmpty(tag, GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> {
this.instrument = CraftMusicInstrument.minecraftHolderToBukkit(instrument);
});
}
CraftMetaMusicInstrument(Map<String, Object> map) {
@@ -44,11 +47,11 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (instrument != null) {
tag.putString(GOAT_HORN_INSTRUMENT.NBT, instrument.getKey().toString());
tag.put(GOAT_HORN_INSTRUMENT, CraftMusicInstrument.bukkitToMinecraftHolder(instrument));
}
}

View File

@@ -0,0 +1,126 @@
package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Map;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.inventory.meta.OminousBottleMeta;
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaOminousBottle extends CraftMetaItem implements OminousBottleMeta {
static final ItemMetaKeyType<Integer> OMINOUS_BOTTLE_AMPLIFIER = new ItemMetaKeyType<>(DataComponents.OMINOUS_BOTTLE_AMPLIFIER, "ominous-bottle-amplifier");
private Integer ominousBottleAmplifier;
CraftMetaOminousBottle(CraftMetaItem meta) {
super(meta);
if (!(meta instanceof CraftMetaOminousBottle)) {
return;
}
CraftMetaOminousBottle bottleMeta = (CraftMetaOminousBottle) meta;
ominousBottleAmplifier = bottleMeta.ominousBottleAmplifier;
}
CraftMetaOminousBottle(DataComponentPatch tag) {
super(tag);
getOrEmpty(tag, OMINOUS_BOTTLE_AMPLIFIER).ifPresent((amplifier) -> {
ominousBottleAmplifier = amplifier;
});
}
CraftMetaOminousBottle(Map<String, Object> map) {
super(map);
Integer ominousBottleAmplifier = SerializableMeta.getObject(Integer.class, map, OMINOUS_BOTTLE_AMPLIFIER.BUKKIT, true);
if (ominousBottleAmplifier != null) {
setAmplifier(ominousBottleAmplifier);
}
}
@Override
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (hasAmplifier()) {
tag.put(OMINOUS_BOTTLE_AMPLIFIER, ominousBottleAmplifier);
}
}
@Override
boolean isEmpty() {
return super.isEmpty() && isBottleEmpty();
}
boolean isBottleEmpty() {
return !(hasAmplifier());
}
@Override
boolean applicableTo(Material type) {
return type == Material.OMINOUS_BOTTLE;
}
@Override
public CraftMetaOminousBottle clone() {
CraftMetaOminousBottle clone = ((CraftMetaOminousBottle) super.clone());
return clone;
}
@Override
public boolean hasAmplifier() {
return ominousBottleAmplifier != null;
}
@Override
public int getAmplifier() {
return ominousBottleAmplifier;
}
@Override
public void setAmplifier(int amplifier) {
Preconditions.checkArgument(0 <= amplifier && amplifier <= 4, "Amplifier must be in range [0, 4]");
this.ominousBottleAmplifier = amplifier;
}
@Override
int applyHash() {
final int original;
int hash = original = super.applyHash();
if (hasAmplifier()) {
hash = 61 * hash + ominousBottleAmplifier.hashCode();
}
return original != hash ? CraftMetaOminousBottle.class.hashCode() ^ hash : hash;
}
@Override
boolean equalsCommon(CraftMetaItem meta) {
if (!super.equalsCommon(meta)) {
return false;
}
if (meta instanceof CraftMetaOminousBottle) {
CraftMetaOminousBottle that = (CraftMetaOminousBottle) meta;
return (hasAmplifier() ? that.hasAmplifier() && this.ominousBottleAmplifier.equals(that.ominousBottleAmplifier) : !that.hasAmplifier());
}
return true;
}
@Override
boolean notUncommon(CraftMetaItem meta) {
return super.notUncommon(meta) && (meta instanceof CraftMetaOminousBottle || isBottleEmpty());
}
@Override
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
if (hasAmplifier()) {
builder.put(OMINOUS_BOTTLE_AMPLIFIER.BUKKIT, ominousBottleAmplifier);
}
return builder;
}
}

View File

@@ -8,23 +8,24 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.alchemy.PotionRegistry;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.craftbukkit.potion.CraftPotionType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@@ -36,19 +37,13 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
Material.TIPPED_ARROW
);
static final ItemMetaKey AMPLIFIER = new ItemMetaKey("amplifier", "amplifier");
static final ItemMetaKey AMBIENT = new ItemMetaKey("ambient", "ambient");
static final ItemMetaKey DURATION = new ItemMetaKey("duration", "duration");
static final ItemMetaKey SHOW_PARTICLES = new ItemMetaKey("show_particles", "has-particles");
static final ItemMetaKey SHOW_ICON = new ItemMetaKey("show_icon", "has-icon");
static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("custom_potion_effects", "custom-effects");
static final ItemMetaKey POTION_COLOR = new ItemMetaKey("CustomPotionColor", "custom-color");
static final ItemMetaKey ID = new ItemMetaKey("id", "potion-id");
static final ItemMetaKey DEFAULT_POTION = new ItemMetaKey("Potion", "potion-type");
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKeyType<PotionContents> POTION_CONTENTS = new ItemMetaKeyType<>(DataComponents.POTION_CONTENTS);
static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("custom-effects");
static final ItemMetaKey POTION_COLOR = new ItemMetaKey("custom-color");
static final ItemMetaKey DEFAULT_POTION = new ItemMetaKey("potion-type");
// Having an initial "state" in ItemMeta seems bit dirty but the UNCRAFTABLE potion type
// is treated as the empty form of the meta because it represents an empty potion with no effect
private PotionType type = PotionType.UNCRAFTABLE;
private PotionType type;
private List<PotionEffect> customEffects;
private Color color;
@@ -64,42 +59,41 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
}
CraftMetaPotion(NBTTagCompound tag) {
CraftMetaPotion(DataComponentPatch tag) {
super(tag);
if (tag.contains(DEFAULT_POTION.NBT)) {
type = CraftPotionType.stringToBukkit(tag.getString(DEFAULT_POTION.NBT));
if (type == null) {
type = PotionType.UNCRAFTABLE;
}
}
if (tag.contains(POTION_COLOR.NBT)) {
try {
color = Color.fromRGB(tag.getInt(POTION_COLOR.NBT));
} catch (IllegalArgumentException ex) {
// Invalid colour
}
}
if (tag.contains(POTION_EFFECTS.NBT)) {
NBTTagList list = tag.getList(POTION_EFFECTS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
getOrEmpty(tag, POTION_CONTENTS).ifPresent((potionContents) -> {
potionContents.potion().ifPresent((potion) -> {
type = CraftPotionType.minecraftHolderToBukkit(potion);
});
potionContents.customColor().ifPresent((customColor) -> {
try {
color = Color.fromRGB(customColor);
} catch (IllegalArgumentException ex) {
// Invalid colour
}
});
List<MobEffect> list = potionContents.customEffects();
int length = list.size();
customEffects = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
NBTTagCompound effect = list.getCompound(i);
PotionEffectType type = PotionEffectType.getByKey(NamespacedKey.fromString(effect.getString(ID.NBT)));
MobEffect effect = list.get(i);
PotionEffectType type = CraftPotionEffectType.minecraftHolderToBukkit(effect.getEffect());
// SPIGOT-4047: Vanilla just disregards these
if (type == null) {
continue;
}
int amp = effect.getByte(AMPLIFIER.NBT);
int duration = effect.getInt(DURATION.NBT);
boolean ambient = effect.getBoolean(AMBIENT.NBT);
boolean particles = effect.contains(SHOW_PARTICLES.NBT, CraftMagicNumbers.NBT.TAG_BYTE) ? effect.getBoolean(SHOW_PARTICLES.NBT) : true;
boolean icon = effect.contains(SHOW_ICON.NBT, CraftMagicNumbers.NBT.TAG_BYTE) ? effect.getBoolean(SHOW_ICON.NBT) : particles;
int amp = effect.getAmplifier();
int duration = effect.getDuration();
boolean ambient = effect.isAmbient();
boolean particles = effect.isVisible();
boolean icon = effect.showIcon();
customEffects.add(new PotionEffect(type, duration, amp, ambient, particles, icon));
}
}
});
}
CraftMetaPotion(Map<String, Object> map) {
@@ -108,9 +102,6 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
if (typeString != null) {
type = CraftPotionType.stringToBukkit(typeString);
}
if (type == null) {
type = PotionType.UNCRAFTABLE;
}
Color color = SerializableMeta.getObject(Color.class, map, POTION_COLOR.BUKKIT, true);
if (color != null) {
@@ -129,30 +120,20 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
tag.putString(DEFAULT_POTION.NBT, CraftPotionType.bukkitToString(type));
if (hasColor()) {
tag.putInt(POTION_COLOR.NBT, color.asRGB());
}
Optional<Holder<PotionRegistry>> defaultPotion = (hasBasePotionType()) ? Optional.of(CraftPotionType.bukkitToMinecraftHolder(type)) : Optional.empty();
Optional<Integer> potionColor = (hasColor()) ? Optional.of(this.color.asRGB()) : Optional.empty();
List<MobEffect> effectList = new ArrayList<>();
if (customEffects != null) {
NBTTagList effectList = new NBTTagList();
tag.put(POTION_EFFECTS.NBT, effectList);
for (PotionEffect effect : customEffects) {
NBTTagCompound effectData = new NBTTagCompound();
effectData.putString(ID.NBT, effect.getType().getKey().toString());
effectData.putByte(AMPLIFIER.NBT, (byte) effect.getAmplifier());
effectData.putInt(DURATION.NBT, effect.getDuration());
effectData.putBoolean(AMBIENT.NBT, effect.isAmbient());
effectData.putBoolean(SHOW_PARTICLES.NBT, effect.hasParticles());
effectData.putBoolean(SHOW_ICON.NBT, effect.hasIcon());
effectList.add(effectData);
effectList.add(new MobEffect(CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()));
}
}
tag.put(POTION_CONTENTS, new PotionContents(defaultPotion, potionColor, effectList));
}
@Override
@@ -161,7 +142,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
boolean isPotionEmpty() {
return (type == PotionType.UNCRAFTABLE) && !(hasCustomEffects() || hasColor());
return (type == null) && !(hasCustomEffects() || hasColor());
}
@Override
@@ -180,30 +161,20 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
@Override
public void setBasePotionData(PotionData data) {
Preconditions.checkArgument(data != null, "PotionData cannot be null");
this.type = CraftPotionUtil.fromBukkit(data);
}
@Override
public PotionData getBasePotionData() {
return CraftPotionUtil.toBukkit(type);
}
@Override
public void setBasePotionType(@NotNull PotionType potionType) {
// TODO: 10/6/23 Change PotionType.UNCRAFTABLE to PotionType.EMPTY in error message
Preconditions.checkArgument(potionType != null, "PotionType cannot be null use PotionType.UNCRAFTABLE to represent no effect instead.");
public void setBasePotionType(PotionType potionType) {
type = potionType;
}
@NotNull
@Override
public PotionType getBasePotionType() {
return type;
}
@Override
public boolean hasBasePotionType() {
return type != null;
}
@Override
public boolean hasCustomEffects() {
return customEffects != null;
@@ -324,7 +295,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
int applyHash() {
final int original;
int hash = original = super.applyHash();
if (type != PotionType.UNCRAFTABLE) {
if (type != null) {
hash = 73 * hash + type.hashCode();
}
if (hasColor()) {
@@ -344,7 +315,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
if (meta instanceof CraftMetaPotion) {
CraftMetaPotion that = (CraftMetaPotion) meta;
return type.equals(that.type)
return Objects.equals(type, that.type)
&& (this.hasCustomEffects() ? that.hasCustomEffects() && this.customEffects.equals(that.customEffects) : !that.hasCustomEffects())
&& (this.hasColor() ? that.hasColor() && this.color.equals(that.color) : !that.hasColor());
}
@@ -359,7 +330,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@Override
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
if (type != PotionType.UNCRAFTABLE) {
if (type != null) {
builder.put(DEFAULT_POTION.BUKKIT, CraftPotionType.bukkitToString(type));
}

View File

@@ -8,16 +8,18 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import net.minecraft.SystemUtils;
import net.minecraft.nbt.GameProfileSerializer;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.DynamicOpsNBT;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.item.component.ResolvableProfile;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
@@ -45,17 +47,16 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
);
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKey SKULL_PROFILE = new ItemMetaKey("SkullProfile");
static final ItemMetaKeyType<ResolvableProfile> SKULL_PROFILE = new ItemMetaKeyType<>(DataComponents.PROFILE, "SkullProfile");
static final ItemMetaKey SKULL_OWNER = new ItemMetaKey("SkullOwner", "skull-owner");
static final ItemMetaKey SKULL_OWNER = new ItemMetaKey("skull-owner");
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKey BLOCK_ENTITY_TAG = new ItemMetaKey("BlockEntityTag");
static final ItemMetaKey NOTE_BLOCK_SOUND = new ItemMetaKey("note_block_sound");
static final ItemMetaKeyType<MinecraftKey> NOTE_BLOCK_SOUND = new ItemMetaKeyType<>(DataComponents.NOTE_BLOCK_SOUND, "note_block_sound");
static final int MAX_OWNER_LENGTH = 16;
private GameProfile profile;
private NBTTagCompound serializedProfile;
private MinecraftKey noteBlockSound;
CraftMetaSkull(CraftMetaItem meta) {
@@ -68,21 +69,16 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
this.noteBlockSound = skullMeta.noteBlockSound;
}
CraftMetaSkull(NBTTagCompound tag) {
CraftMetaSkull(DataComponentPatch tag) {
super(tag);
if (tag.contains(SKULL_OWNER.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
this.setProfile(GameProfileSerializer.readGameProfile(tag.getCompound(SKULL_OWNER.NBT)));
} else if (tag.contains(SKULL_OWNER.NBT, CraftMagicNumbers.NBT.TAG_STRING) && !tag.getString(SKULL_OWNER.NBT).isEmpty()) {
this.setProfile(new GameProfile(SystemUtils.NIL_UUID, tag.getString(SKULL_OWNER.NBT)));
}
getOrEmpty(tag, SKULL_PROFILE).ifPresent((resolvableProfile) -> {
this.setProfile(resolvableProfile.gameProfile());
});
if (tag.contains(BLOCK_ENTITY_TAG.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
NBTTagCompound nbtTagCompound = tag.getCompound(BLOCK_ENTITY_TAG.NBT).copy();
if (nbtTagCompound.contains(NOTE_BLOCK_SOUND.NBT, 8)) {
this.noteBlockSound = MinecraftKey.tryParse(nbtTagCompound.getString(NOTE_BLOCK_SOUND.NBT));
}
}
getOrEmpty(tag, NOTE_BLOCK_SOUND).ifPresent((minecraftKey) -> {
this.noteBlockSound = minecraftKey;
});
}
CraftMetaSkull(Map<String, Object> map) {
@@ -116,7 +112,7 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
skullTag.putUUID("Id", uuid);
}
this.setProfile(GameProfileSerializer.readGameProfile(skullTag));
this.setProfile(ResolvableProfile.CODEC.parse(DynamicOpsNBT.INSTANCE, skullTag).result().get().gameProfile());
}
if (tag.contains(BLOCK_ENTITY_TAG.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
@@ -129,32 +125,27 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
private void setProfile(GameProfile profile) {
this.profile = profile;
this.serializedProfile = (profile == null) ? null : GameProfileSerializer.writeGameProfile(new NBTTagCompound(), profile);
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (profile != null) {
checkForInconsistency();
// SPIGOT-6558: Set initial textures
tag.put(SKULL_OWNER.NBT, serializedProfile);
tag.put(SKULL_PROFILE, new ResolvableProfile(profile));
// Fill in textures
PlayerProfile ownerProfile = new CraftPlayerProfile(profile); // getOwnerProfile may return null
if (ownerProfile.getTextures().isEmpty()) {
ownerProfile.update().thenAccept((filledProfile) -> {
setOwnerProfile(filledProfile);
tag.put(SKULL_OWNER.NBT, serializedProfile);
tag.put(SKULL_PROFILE, new ResolvableProfile(profile));
});
}
}
if (noteBlockSound != null) {
NBTTagCompound nbtTagCompound = new NBTTagCompound();
nbtTagCompound.putString(NOTE_BLOCK_SOUND.NBT, this.noteBlockSound.toString());
tag.put(BLOCK_ENTITY_TAG.NBT, nbtTagCompound);
tag.put(NOTE_BLOCK_SOUND, this.noteBlockSound);
}
}
@@ -283,9 +274,8 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
if (meta instanceof CraftMetaSkull) {
CraftMetaSkull that = (CraftMetaSkull) meta;
checkForInconsistency();
// SPIGOT-5403: equals does not check properties
return (this.profile != null ? that.profile != null && this.serializedProfile.equals(that.serializedProfile) : that.profile == null) && Objects.equals(this.noteBlockSound, that.noteBlockSound);
return (this.profile != null ? that.profile != null && this.profile.equals(that.profile) && this.profile.getProperties().equals(that.profile.getProperties()) : that.profile == null) && Objects.equals(this.noteBlockSound, that.noteBlockSound);
}
return true;
}
@@ -307,15 +297,4 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
}
return builder;
}
private void checkForInconsistency() {
if (profile != null && serializedProfile == null) {
// SPIGOT-7510: Fix broken reflection usage from plugins
Bukkit.getLogger().warning("""
Found inconsistent skull meta, this should normally not happen and is not a Bukkit / Spigot issue, but one from a plugin you are using.
Bukkit will attempt to fix it this time for you, but may not be able to do this every time.
If you see this message after typing a command from a plugin, please report this to the plugin developer, they should use the api instead of relying on reflection (and doing it the wrong way).""");
serializedProfile = GameProfileSerializer.writeGameProfile(new NBTTagCompound(), profile);
}
}
}

View File

@@ -5,9 +5,12 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.entity.CraftEntitySnapshot;
@@ -17,15 +20,17 @@ import org.bukkit.entity.EntityType;
import org.bukkit.inventory.meta.SpawnEggMeta;
import org.bukkit.material.MaterialData;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
private static final Set<Material> SPAWN_EGG_MATERIALS = Sets.newHashSet(
Material.ARMADILLO_SPAWN_EGG,
Material.ALLAY_SPAWN_EGG,
Material.AXOLOTL_SPAWN_EGG,
Material.BAT_SPAWN_EGG,
Material.BEE_SPAWN_EGG,
Material.BLAZE_SPAWN_EGG,
Material.BOGGED_SPAWN_EGG,
Material.BREEZE_SPAWN_EGG,
Material.CAT_SPAWN_EGG,
Material.CAMEL_SPAWN_EGG,
@@ -101,7 +106,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
Material.ZOMBIFIED_PIGLIN_SPAWN_EGG
);
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.ENTITY_DATA, "entity-tag");
@ItemMetaKey.Specific(ItemMetaKey.Specific.To.NBT)
static final ItemMetaKey ENTITY_ID = new ItemMetaKey("id");
@@ -120,12 +125,12 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
updateMaterial(null); // Trigger type population
}
CraftMetaSpawnEgg(NBTTagCompound tag) {
CraftMetaSpawnEgg(DataComponentPatch tag) {
super(tag);
if (tag.contains(ENTITY_TAG.NBT)) {
entityTag = tag.getCompound(ENTITY_TAG.NBT).copy();
}
getOrEmpty(tag, ENTITY_TAG).ifPresent((nbt) -> {
entityTag = nbt.copyTag();
});
}
CraftMetaSpawnEgg(Map<String, Object> map) {
@@ -180,7 +185,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (!isSpawnEggEmpty() && entityTag == null) {
@@ -188,7 +193,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
}
if (entityTag != null) {
tag.put(ENTITY_TAG.NBT, entityTag);
tag.put(ENTITY_TAG, CustomData.of(entityTag));
}
}
@@ -294,7 +299,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
if (spawnedType != null) {
if (entityTag != null) {
// Remove ID tag as it is now in the material
entityTag.remove(ENTITY_ID.NBT);
entityTag.remove("id");
}
return CraftLegacy.fromLegacy(new MaterialData(Material.LEGACY_MONSTER_EGG, (byte) spawnedType.getTypeId()));

View File

@@ -7,22 +7,20 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.SuspiciousStewEffects;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.inventory.meta.SuspiciousStewMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaSuspiciousStew extends CraftMetaItem implements SuspiciousStewMeta {
static final ItemMetaKey DURATION = new ItemMetaKey("duration", "duration");
static final ItemMetaKey EFFECTS = new ItemMetaKey("effects", "effects");
static final ItemMetaKey ID = new ItemMetaKey("id", "id");
static final ItemMetaKeyType<SuspiciousStewEffects> EFFECTS = new ItemMetaKeyType<>(DataComponents.SUSPICIOUS_STEW_EFFECTS, "effects");
private List<PotionEffect> customEffects;
@@ -36,23 +34,23 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
}
}
CraftMetaSuspiciousStew(NBTTagCompound tag) {
CraftMetaSuspiciousStew(DataComponentPatch tag) {
super(tag);
if (tag.contains(EFFECTS.NBT)) {
NBTTagList list = tag.getList(EFFECTS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND);
getOrEmpty(tag, EFFECTS).ifPresent((suspiciousStewEffects) -> {
List<SuspiciousStewEffects.a> list = suspiciousStewEffects.effects();
int length = list.size();
customEffects = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
NBTTagCompound effect = list.getCompound(i);
PotionEffectType type = PotionEffectType.getByKey(NamespacedKey.fromString(effect.getString(ID.NBT)));
SuspiciousStewEffects.a effect = list.get(i);
PotionEffectType type = CraftPotionEffectType.minecraftHolderToBukkit(effect.effect());
if (type == null) {
continue;
}
int duration = effect.getInt(DURATION.NBT);
int duration = effect.duration();
customEffects.add(new PotionEffect(type, duration, 0));
}
}
});
}
CraftMetaSuspiciousStew(Map<String, Object> map) {
@@ -70,19 +68,16 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (customEffects != null) {
NBTTagList effectList = new NBTTagList();
tag.put(EFFECTS.NBT, effectList);
List<SuspiciousStewEffects.a> effectList = new ArrayList<>();
for (PotionEffect effect : customEffects) {
NBTTagCompound effectData = new NBTTagCompound();
effectData.putString(ID.NBT, effect.getType().getKey().toString());
effectData.putInt(DURATION.NBT, effect.getDuration());
effectList.add(effectData);
effectList.add(new net.minecraft.world.item.component.SuspiciousStewEffects.a(CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()), effect.getDuration()));
}
tag.put(EFFECTS, new SuspiciousStewEffects(effectList));
}
}

View File

@@ -2,13 +2,15 @@ package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.item.component.CustomData;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.entity.CraftTropicalFish;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.TropicalFish;
import org.bukkit.inventory.meta.TropicalFishBucketMeta;
@@ -16,7 +18,7 @@ import org.bukkit.inventory.meta.TropicalFishBucketMeta;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishBucketMeta {
static final ItemMetaKey VARIANT = new ItemMetaKey("BucketVariantTag", "fish-variant");
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.ENTITY_DATA, "entity-tag");
private Integer variant;
private NBTTagCompound entityTag;
@@ -33,16 +35,16 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
this.entityTag = bucket.entityTag;
}
CraftMetaTropicalFishBucket(NBTTagCompound tag) {
CraftMetaTropicalFishBucket(DataComponentPatch tag) {
super(tag);
if (tag.contains(VARIANT.NBT, CraftMagicNumbers.NBT.TAG_INT)) {
this.variant = tag.getInt(VARIANT.NBT);
}
getOrEmpty(tag, ENTITY_TAG).ifPresent((nbt) -> {
entityTag = nbt.copyTag();
if (tag.contains(ENTITY_TAG.NBT)) {
entityTag = tag.getCompound(ENTITY_TAG.NBT).copy();
}
if (entityTag.contains(VARIANT.NBT, CraftMagicNumbers.NBT.TAG_INT)) {
this.variant = entityTag.getInt(VARIANT.NBT);
}
});
}
CraftMetaTropicalFishBucket(Map<String, Object> map) {
@@ -71,15 +73,18 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
}
@Override
void applyToItem(NBTTagCompound tag) {
void applyToItem(CraftMetaItem.Applicator tag) {
super.applyToItem(tag);
if (hasVariant()) {
tag.putInt(VARIANT.NBT, variant);
if (entityTag == null) {
entityTag = new NBTTagCompound();
}
entityTag.putInt(VARIANT.NBT, variant);
}
if (entityTag != null) {
tag.put(ENTITY_TAG.NBT, entityTag);
tag.put(ENTITY_TAG, CustomData.of(entityTag));
}
}

View File

@@ -1,50 +1,31 @@
package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import java.util.Iterator;
import java.util.Map;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.Recipes;
import org.bukkit.inventory.Recipe;
public class RecipeIterator implements Iterator<Recipe> {
private final Iterator<Map.Entry<Recipes<?>, Object2ObjectLinkedOpenHashMap<MinecraftKey, RecipeHolder<?>>>> recipes;
private Iterator<RecipeHolder<?>> current;
private final Iterator<Map.Entry<Recipes<?>, RecipeHolder<?>>> recipes;
public RecipeIterator() {
this.recipes = MinecraftServer.getServer().getRecipeManager().recipes.entrySet().iterator();
this.recipes = MinecraftServer.getServer().getRecipeManager().byType.entries().iterator();
}
@Override
public boolean hasNext() {
if (current != null && current.hasNext()) {
return true;
}
if (recipes.hasNext()) {
current = recipes.next().getValue().values().iterator();
return hasNext();
}
return false;
return recipes.hasNext();
}
@Override
public Recipe next() {
if (current == null || !current.hasNext()) {
current = recipes.next().getValue().values().iterator();
return next();
}
return current.next().toBukkitRecipe();
return recipes.next().getValue().toBukkitRecipe();
}
@Override
public void remove() {
Preconditions.checkState(current != null, "next() not yet called");
current.remove();
recipes.remove();
}
}

View File

@@ -0,0 +1,113 @@
package org.bukkit.craftbukkit.inventory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.NoSuchElementException;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.inventory.meta.ItemMeta;
@SerializableAs("ItemMeta")
public final class SerializableMeta implements ConfigurationSerializable {
static final String TYPE_FIELD = "meta-type";
static final ImmutableMap<Class<? extends CraftMetaItem>, String> classMap;
static final ImmutableMap<String, Constructor<? extends CraftMetaItem>> constructorMap;
static {
classMap = ImmutableMap.<Class<? extends CraftMetaItem>, String>builder()
.put(CraftMetaArmor.class, "ARMOR")
.put(CraftMetaArmorStand.class, "ARMOR_STAND")
.put(CraftMetaBanner.class, "BANNER")
.put(CraftMetaBlockState.class, "TILE_ENTITY")
.put(CraftMetaBook.class, "BOOK")
.put(CraftMetaBookSigned.class, "BOOK_SIGNED")
.put(CraftMetaSkull.class, "SKULL")
.put(CraftMetaLeatherArmor.class, "LEATHER_ARMOR")
.put(CraftMetaColorableArmor.class, "COLORABLE_ARMOR")
.put(CraftMetaMap.class, "MAP")
.put(CraftMetaPotion.class, "POTION")
.put(CraftMetaSpawnEgg.class, "SPAWN_EGG")
.put(CraftMetaEnchantedBook.class, "ENCHANTED")
.put(CraftMetaFirework.class, "FIREWORK")
.put(CraftMetaCharge.class, "FIREWORK_EFFECT")
.put(CraftMetaKnowledgeBook.class, "KNOWLEDGE_BOOK")
.put(CraftMetaTropicalFishBucket.class, "TROPICAL_FISH_BUCKET")
.put(CraftMetaAxolotlBucket.class, "AXOLOTL_BUCKET")
.put(CraftMetaCrossbow.class, "CROSSBOW")
.put(CraftMetaSuspiciousStew.class, "SUSPICIOUS_STEW")
.put(CraftMetaEntityTag.class, "ENTITY_TAG")
.put(CraftMetaCompass.class, "COMPASS")
.put(CraftMetaBundle.class, "BUNDLE")
.put(CraftMetaMusicInstrument.class, "MUSIC_INSTRUMENT")
.put(CraftMetaOminousBottle.class, "OMINOUS_BOTTLE")
.put(CraftMetaItem.class, "UNSPECIFIC")
.build();
final ImmutableMap.Builder<String, Constructor<? extends CraftMetaItem>> classConstructorBuilder = ImmutableMap.builder();
for (Map.Entry<Class<? extends CraftMetaItem>, String> mapping : classMap.entrySet()) {
try {
classConstructorBuilder.put(mapping.getValue(), mapping.getKey().getDeclaredConstructor(Map.class));
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
constructorMap = classConstructorBuilder.build();
}
private SerializableMeta() {
}
public static ItemMeta deserialize(Map<String, Object> map) throws Throwable {
Preconditions.checkArgument(map != null, "Cannot deserialize null map");
String type = getString(map, TYPE_FIELD, false);
Constructor<? extends CraftMetaItem> constructor = constructorMap.get(type);
if (constructor == null) {
throw new IllegalArgumentException(type + " is not a valid " + TYPE_FIELD);
}
try {
return constructor.newInstance(map);
} catch (final InstantiationException e) {
throw new AssertionError(e);
} catch (final IllegalAccessException e) {
throw new AssertionError(e);
} catch (final InvocationTargetException e) {
throw e.getCause();
}
}
@Override
public Map<String, Object> serialize() {
throw new AssertionError();
}
public static String getString(Map<?, ?> map, Object field, boolean nullable) {
return getObject(String.class, map, field, nullable);
}
public static boolean getBoolean(Map<?, ?> map, Object field) {
Boolean value = getObject(Boolean.class, map, field, true);
return value != null && value;
}
public static <T> T getObject(Class<T> clazz, Map<?, ?> map, Object field, boolean nullable) {
final Object object = map.get(field);
if (clazz.isInstance(object)) {
return clazz.cast(object);
}
if (object == null) {
if (!nullable) {
throw new NoSuchElementException(map + " does not contain " + field);
}
return null;
}
throw new IllegalArgumentException(field + "(" + object + ") is not a valid " + clazz);
}
}

Some files were not shown because too many files have changed in this diff Show More