1.21.6 dev

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

View File

@@ -1,17 +1,17 @@
package com.destroystokyo.paper.entity;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.world.level.pathfinder.Node;
import net.minecraft.world.level.pathfinder.Path;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.world.level.pathfinder.Node;
import net.minecraft.world.level.pathfinder.Path;
import java.util.ArrayList;
import java.util.List;
public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder {
@@ -23,7 +23,7 @@ public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinde
@Override
public Mob getEntity() {
return (Mob) entity.getBukkitEntity();
return (Mob) this.entity.getBukkitEntity();
}
public void setHandle(net.minecraft.world.entity.Mob entity) {

View File

@@ -1,189 +1,211 @@
package com.destroystokyo.paper.entity.ai;
import com.destroystokyo.paper.entity.RangedEntity;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.base.CaseFormat;
import io.papermc.paper.entity.SchoolableFish;
import io.papermc.paper.util.ObfHelper;
import it.unimi.dsi.fastutil.ints.Int2BooleanFunction;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import net.minecraft.Util;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.monster.RangedAttackMob;
import org.apache.commons.lang3.math.NumberUtils;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.*;
public class MobGoalHelper {
private static final BiMap<String, String> deobfuscationMap = HashBiMap.create();
private static final Map<Class<? extends Goal>, Class<? extends Mob>> entityClassCache = new HashMap<>();
private static final Map<Class<? extends net.minecraft.world.entity.Mob>, Class<? extends Mob>> bukkitMap = new HashMap<>();
static final Set<String> ignored = new HashSet<>();
static {
// TODO these kinda should be checked on each release, in case obfuscation changes
deobfuscationMap.put("abstract_skeleton_1", "abstract_skeleton_melee");
ignored.add("goal_selector_1");
ignored.add("goal_selector_2");
ignored.add("selector_1");
ignored.add("selector_2");
ignored.add("wrapped");
private static final Map<Class<? extends Goal>, Class<? extends Mob>> GENERIC_TYPE_CACHE = new HashMap<>();
public static final Map<Class<? extends net.minecraft.world.entity.Mob>, Class<? extends Mob>> BUKKIT_BRIDGE = Util.make(new LinkedHashMap<>(), map -> {
//<editor-fold defaultstate="collapsed" desc="bukkitMap Entities">
// Start generate - MobGoalHelper#bukkitMap
// @GeneratedFrom 1.21.5
bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class);
bukkitMap.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class);
bukkitMap.put(net.minecraft.world.entity.ambient.AmbientCreature.class, Ambient.class);
bukkitMap.put(net.minecraft.world.entity.animal.Animal.class, Animals.class);
bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class);
bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class);
bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class);
bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class);
bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class);
bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class);
bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class);
bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class);
bukkitMap.put(net.minecraft.world.entity.PathfinderMob.class, Creature.class);
bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class);
bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class);
bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class);
bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class);
bukkitMap.put(net.minecraft.world.entity.monster.EnderMan.class, Enderman.class);
bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class);
bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class);
bukkitMap.put(net.minecraft.world.entity.animal.AbstractFish.class, Fish.class);
bukkitMap.put(net.minecraft.world.entity.animal.AbstractSchoolingFish.class, SchoolableFish.class);
bukkitMap.put(net.minecraft.world.entity.FlyingMob.class, Flying.class);
bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class);
bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class);
bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class);
bukkitMap.put(net.minecraft.world.entity.animal.AbstractGolem.class, Golem.class);
bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class);
bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractChestedHorse.class, ChestedHorse.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class);
bukkitMap.put(net.minecraft.world.entity.animal.camel.Camel.class, Camel.class);
bukkitMap.put(net.minecraft.world.entity.monster.AbstractIllager.class, Illager.class);
bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class);
bukkitMap.put(net.minecraft.world.entity.monster.SpellcasterIllager.class, Spellcaster.class);
bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class);
bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class);
bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class);
bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class);
bukkitMap.put(net.minecraft.world.entity.monster.PatrollingMonster.class, Raider.class);
bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class);
bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class);
bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class);
bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class);
bukkitMap.put(net.minecraft.world.entity.animal.ShoulderRidingEntity.class, Parrot.class);
bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class);
bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class);
bukkitMap.put(net.minecraft.world.entity.monster.ZombifiedPiglin.class, PigZombie.class);
bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class);
bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class);
bukkitMap.put(net.minecraft.world.entity.animal.Pufferfish.class, PufferFish.class);
bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class);
bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class);
bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class);
bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class);
bukkitMap.put(net.minecraft.world.entity.animal.sheep.Sheep.class, Sheep.class);
bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class);
bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class);
bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class);
bukkitMap.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class);
bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class);
bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class);
bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class);
bukkitMap.put(net.minecraft.world.entity.animal.SnowGolem.class, Snowman.class);
bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class);
bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class);
bukkitMap.put(net.minecraft.world.entity.TamableAnimal.class, Tameable.class);
bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class);
bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class);
bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class);
bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class);
bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class);
bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class);
bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class);
bukkitMap.put(net.minecraft.world.entity.animal.WaterAnimal.class, WaterMob.class);
bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class);
bukkitMap.put(net.minecraft.world.entity.boss.wither.WitherBoss.class, Wither.class);
bukkitMap.put(net.minecraft.world.entity.animal.wolf.Wolf.class, Wolf.class);
bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class);
bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class);
bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class);
bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class);
bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class);
bukkitMap.put(net.minecraft.world.entity.monster.piglin.AbstractPiglin.class, PiglinAbstract.class);
bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class);
bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class);
bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class);
bukkitMap.put(net.minecraft.world.entity.GlowSquid.class, GlowSquid.class);
bukkitMap.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, Axolotl.class);
bukkitMap.put(net.minecraft.world.entity.animal.goat.Goat.class, Goat.class);
bukkitMap.put(net.minecraft.world.entity.animal.frog.Frog.class, Frog.class);
bukkitMap.put(net.minecraft.world.entity.animal.frog.Tadpole.class, Tadpole.class);
bukkitMap.put(net.minecraft.world.entity.monster.warden.Warden.class, Warden.class);
bukkitMap.put(net.minecraft.world.entity.animal.allay.Allay.class, Allay.class);
bukkitMap.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, Sniffer.class);
bukkitMap.put(net.minecraft.world.entity.monster.breeze.Breeze.class, Breeze.class);
bukkitMap.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, Armadillo.class);
bukkitMap.put(net.minecraft.world.entity.monster.Bogged.class, Bogged.class);
bukkitMap.put(net.minecraft.world.entity.monster.creaking.Creaking.class, Creaking.class);
bukkitMap.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, Squid.class);
bukkitMap.put(net.minecraft.world.entity.animal.AbstractCow.class, AbstractCow.class);
// End generate - MobGoalHelper#bukkitMap
// Start generate - MobGoalHelper#BUKKIT_BRIDGE
// @GeneratedFrom 1.21.6-rc1
map.put(net.minecraft.world.entity.Mob.class, Mob.class);
map.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class);
map.put(net.minecraft.world.entity.ambient.AmbientCreature.class, Ambient.class);
map.put(net.minecraft.world.entity.animal.Animal.class, Animals.class);
map.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class);
map.put(net.minecraft.world.entity.animal.Bee.class, Bee.class);
map.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class);
map.put(net.minecraft.world.entity.animal.Cat.class, Cat.class);
map.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class);
map.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class);
map.put(net.minecraft.world.entity.animal.Cod.class, Cod.class);
map.put(net.minecraft.world.entity.animal.Cow.class, Cow.class);
map.put(net.minecraft.world.entity.PathfinderMob.class, Creature.class);
map.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class);
map.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class);
map.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class);
map.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class);
map.put(net.minecraft.world.entity.monster.EnderMan.class, Enderman.class);
map.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class);
map.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class);
map.put(net.minecraft.world.entity.animal.AbstractFish.class, Fish.class);
map.put(net.minecraft.world.entity.animal.AbstractSchoolingFish.class, SchoolableFish.class);
map.put(net.minecraft.world.entity.animal.Fox.class, Fox.class);
map.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class);
map.put(net.minecraft.world.entity.monster.Giant.class, Giant.class);
map.put(net.minecraft.world.entity.animal.AbstractGolem.class, Golem.class);
map.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class);
map.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class);
map.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class);
map.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class);
map.put(net.minecraft.world.entity.animal.horse.AbstractChestedHorse.class, ChestedHorse.class);
map.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class);
map.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class);
map.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class);
map.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class);
map.put(net.minecraft.world.entity.animal.camel.Camel.class, Camel.class);
map.put(net.minecraft.world.entity.monster.AbstractIllager.class, Illager.class);
map.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class);
map.put(net.minecraft.world.entity.monster.SpellcasterIllager.class, Spellcaster.class);
map.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class);
map.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class);
map.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class);
map.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class);
map.put(net.minecraft.world.entity.monster.Monster.class, Monster.class);
map.put(net.minecraft.world.entity.monster.PatrollingMonster.class, Raider.class);
map.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class);
map.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class);
map.put(net.minecraft.world.entity.animal.Panda.class, Panda.class);
map.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class);
map.put(net.minecraft.world.entity.animal.ShoulderRidingEntity.class, Parrot.class);
map.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class);
map.put(net.minecraft.world.entity.animal.Pig.class, Pig.class);
map.put(net.minecraft.world.entity.monster.ZombifiedPiglin.class, PigZombie.class);
map.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class);
map.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class);
map.put(net.minecraft.world.entity.animal.Pufferfish.class, PufferFish.class);
map.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class);
map.put(net.minecraft.world.entity.raid.Raider.class, Raider.class);
map.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class);
map.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class);
map.put(net.minecraft.world.entity.animal.sheep.Sheep.class, Sheep.class);
map.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class);
map.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class);
map.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class);
map.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class);
map.put(net.minecraft.world.entity.monster.Stray.class, Stray.class);
map.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class);
map.put(net.minecraft.world.entity.monster.Slime.class, Slime.class);
map.put(net.minecraft.world.entity.animal.SnowGolem.class, Snowman.class);
map.put(net.minecraft.world.entity.monster.Spider.class, Spider.class);
map.put(net.minecraft.world.entity.animal.Squid.class, Squid.class);
map.put(net.minecraft.world.entity.TamableAnimal.class, Tameable.class);
map.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class);
map.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class);
map.put(net.minecraft.world.entity.monster.Vex.class, Vex.class);
map.put(net.minecraft.world.entity.npc.Villager.class, Villager.class);
map.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class);
map.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class);
map.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class);
map.put(net.minecraft.world.entity.animal.WaterAnimal.class, WaterMob.class);
map.put(net.minecraft.world.entity.monster.Witch.class, Witch.class);
map.put(net.minecraft.world.entity.boss.wither.WitherBoss.class, Wither.class);
map.put(net.minecraft.world.entity.animal.wolf.Wolf.class, Wolf.class);
map.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class);
map.put(net.minecraft.world.entity.monster.Husk.class, Husk.class);
map.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class);
map.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class);
map.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class);
map.put(net.minecraft.world.entity.monster.piglin.AbstractPiglin.class, PiglinAbstract.class);
map.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class);
map.put(net.minecraft.world.entity.monster.Strider.class, Strider.class);
map.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class);
map.put(net.minecraft.world.entity.GlowSquid.class, GlowSquid.class);
map.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, Axolotl.class);
map.put(net.minecraft.world.entity.animal.goat.Goat.class, Goat.class);
map.put(net.minecraft.world.entity.animal.frog.Frog.class, Frog.class);
map.put(net.minecraft.world.entity.animal.frog.Tadpole.class, Tadpole.class);
map.put(net.minecraft.world.entity.monster.warden.Warden.class, Warden.class);
map.put(net.minecraft.world.entity.animal.allay.Allay.class, Allay.class);
map.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, Sniffer.class);
map.put(net.minecraft.world.entity.monster.breeze.Breeze.class, Breeze.class);
map.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, Armadillo.class);
map.put(net.minecraft.world.entity.monster.Bogged.class, Bogged.class);
map.put(net.minecraft.world.entity.monster.creaking.Creaking.class, Creaking.class);
map.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, Squid.class);
map.put(net.minecraft.world.entity.animal.AbstractCow.class, AbstractCow.class);
map.put(net.minecraft.world.entity.animal.HappyGhast.class, HappyGhast.class);
// End generate - MobGoalHelper#BUKKIT_BRIDGE
//</editor-fold>
}
});
// TODO these kinda should be checked on each release, in case nested classes changes
private static final Map<String, String> NESTED_CLASS_NAMES = Util.make(new HashMap<>(), map -> {
map.put("AbstractSkeleton$1", "AbstractSkeletonMelee");
// remove duplicate
map.put("TraderLlama$TraderLlamaDefendWanderingTraderGoal", "TraderLlamaDefendWanderingTraderGoal");
map.put("AbstractIllager$RaiderOpenDoorGoal", "RaiderOpenDoorGoal");
// weird enderman case
map.put("EnderMan.EndermanFreezeWhenLookedAt", "EndermanFreezeWhenLookedAt");
map.put("EnderMan.EndermanLeaveBlockGoal", "EndermanLeaveBlockGoal");
map.put("EnderMan.EndermanTakeBlockGoal", "EndermanTakeBlockGoal");
map.put("EnderMan.EndermanLookForPlayerGoal", "EndermanLookForPlayerGoal");
});
private static final Set<Class<? extends Mob>> NO_SPECIFIER = Set.of(
Mob.class,
Creature.class,
Animals.class,
RangedEntity.class,
Tameable.class,
Monster.class,
PufferFish.class // weird case
);
private static String getPathName(Class<? extends Mob> type, Class<?> holderClass, String name) {
String pathName = name.substring(name.lastIndexOf('.') + 1);
boolean needRename = false;
public static String getUsableName(Class<?> clazz) {
String name = io.papermc.paper.util.MappingEnvironment.reobf() ? ObfHelper.INSTANCE.deobfClassName(clazz.getName()) : clazz.getName();
name = name.substring(name.lastIndexOf(".") + 1);
boolean flag = false;
// inner classes
if (name.contains("$")) {
String cut = name.substring(name.indexOf("$") + 1);
if (cut.length() <= 2) {
name = name.replace("Entity", "");
name = name.replace("$", "_");
flag = true;
} else {
// mapped, wooo
name = cut;
int firstInnerDelimiter = pathName.indexOf('$');
if (firstInnerDelimiter != -1) {
String innerClassNames = pathName.substring(firstInnerDelimiter + 1);
for (String innerClassName : innerClassNames.split("\\$")) {
if (NumberUtils.isDigits(innerClassName)) {
needRename = true;
break;
}
}
if (!needRename && !NESTED_CLASS_NAMES.containsKey(pathName)) {
pathName = innerClassNames;
}
}
name = name.replace("TargetGoal", "");
name = name.replace("Goal", "");
StringBuilder sb = new StringBuilder();
for (char c : name.toCharArray()) {
if (c >= 'A' && c <= 'Z') {
sb.append("_");
sb.append(Character.toLowerCase(c));
} else {
sb.append(c);
if (!NESTED_CLASS_NAMES.containsKey(pathName)) {
if (needRename) {
throw new IllegalStateException("need to map " + name + " (" + pathName + ")");
}
}
name = sb.toString();
name = name.replaceFirst("_", "");
if (flag && !deobfuscationMap.containsKey(name.toLowerCase(java.util.Locale.ROOT)) && !ignored.contains(name)) {
System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase(java.util.Locale.ROOT) + ")");
String prefix = null;
if (!NO_SPECIFIER.contains(type)) {
prefix = type.getSimpleName();
} else if (!net.minecraft.world.entity.Mob.class.isAssignableFrom(holderClass)) {
prefix = holderClass.getSimpleName();
}
if (prefix != null && !pathName.startsWith(prefix)) {
pathName = prefix + pathName;
}
} else {
pathName = NESTED_CLASS_NAMES.get(pathName);
}
// did we rename this key?
return deobfuscationMap.getOrDefault(name, name);
pathName = pathName.replace("TargetGoal", ""); // replace last? reverse search?
pathName = pathName.replace("Goal", "");
pathName = pathName.replace("Abstract", "");
pathName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, pathName);
return pathName;
}
public static EnumSet<GoalType> vanillaToPaper(Goal goal) {
@@ -197,20 +219,13 @@ public class MobGoalHelper {
}
public static GoalType vanillaToPaper(Goal.Flag type) {
switch (type) {
case MOVE:
return GoalType.MOVE;
case LOOK:
return GoalType.LOOK;
case JUMP:
return GoalType.JUMP;
case UNKNOWN_BEHAVIOR:
return GoalType.UNKNOWN_BEHAVIOR;
case TARGET:
return GoalType.TARGET;
default:
throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name());
}
return switch (type) {
case MOVE -> GoalType.MOVE;
case LOOK -> GoalType.LOOK;
case JUMP -> GoalType.JUMP;
case UNKNOWN_BEHAVIOR -> GoalType.UNKNOWN_BEHAVIOR;
case TARGET -> GoalType.TARGET;
};
}
public static EnumSet<Goal.Flag> paperToVanilla(EnumSet<GoalType> types) {
@@ -222,41 +237,57 @@ public class MobGoalHelper {
}
public static Goal.Flag paperToVanilla(GoalType type) {
switch (type) {
case MOVE:
return Goal.Flag.MOVE;
case LOOK:
return Goal.Flag.LOOK;
case JUMP:
return Goal.Flag.JUMP;
case UNKNOWN_BEHAVIOR:
return Goal.Flag.UNKNOWN_BEHAVIOR;
case TARGET:
return Goal.Flag.TARGET;
default:
throw new IllegalArgumentException("Unknown paper mob goal type " + type.name());
}
return switch (type) {
case MOVE -> Goal.Flag.MOVE;
case LOOK -> Goal.Flag.LOOK;
case JUMP -> Goal.Flag.JUMP;
case UNKNOWN_BEHAVIOR -> Goal.Flag.UNKNOWN_BEHAVIOR;
case TARGET -> Goal.Flag.TARGET;
};
}
public static <T extends Mob> GoalKey<T> getKey(Class<? extends Goal> goalClass) {
String name = getUsableName(goalClass);
if (ignored.contains(name)) {
//noinspection unchecked
return (GoalKey<T>) GoalKey.of(Mob.class, NamespacedKey.minecraft(name));
Class<T> type = getGenericType(goalClass);
String name = goalClass.getName();
if (io.papermc.paper.util.MappingEnvironment.reobf()) {
name = ObfHelper.INSTANCE.deobfClassName(name);
}
return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name));
Class<?> holderClass = getTopLevelClass(goalClass);
name = getPathName(type, holderClass, name);
return GoalKey.of(type, NamespacedKey.minecraft(name));
}
public static <T extends Mob> Class<T> getEntity(Class<? extends Goal> goalClass) {
private static final Int2BooleanFunction[] VISIBILITY_SEARCH_STEP = {
Modifier::isPublic,
Modifier::isProtected,
mod -> (mod & 0b111) == 0, // package-private
Modifier::isPrivate,
};
private static final Comparator<Constructor<?>> VISIBILITY_ORDER = Comparator.comparingInt(constructor -> {
int mod = constructor.getModifiers();
for (int i = 0; i < VISIBILITY_SEARCH_STEP.length; i++) {
Int2BooleanFunction visibility = VISIBILITY_SEARCH_STEP[i];
if (visibility.test(mod)) {
return i;
}
}
throw new UnsupportedOperationException("Unknown visibility: " + mod);
});
private static <T extends Mob> Class<T> getGenericType(Class<? extends Goal> goalClass) {
//noinspection unchecked
return (Class<T>) entityClassCache.computeIfAbsent(goalClass, key -> {
for (Constructor<?> ctor : key.getDeclaredConstructors()) {
for (int i = 0; i < ctor.getParameterCount(); i++) {
Class<?> param = ctor.getParameterTypes()[i];
if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) {
return (Class<T>) GENERIC_TYPE_CACHE.computeIfAbsent(goalClass, key -> {
Constructor<?>[] constructors = key.getDeclaredConstructors();
Arrays.sort(constructors, VISIBILITY_ORDER);
for (Constructor<?> constructor : constructors) {
for (Class<?> paramType : constructor.getParameterTypes()) {
if (net.minecraft.world.entity.Mob.class.isAssignableFrom(paramType)) {
//noinspection unchecked
return toBukkitClass((Class<? extends net.minecraft.world.entity.Mob>) param);
} else if (RangedAttackMob.class.isAssignableFrom(param)) {
return toBukkitClass((Class<? extends net.minecraft.world.entity.Mob>) paramType);
} else if (RangedAttackMob.class.isAssignableFrom(paramType)) {
return RangedEntity.class;
}
}
@@ -265,10 +296,24 @@ public class MobGoalHelper {
});
}
public static Class<? extends Mob> toBukkitClass(Class<? extends net.minecraft.world.entity.Mob> nmsClass) {
Class<? extends Mob> bukkitClass = bukkitMap.get(nmsClass);
private static Class<?> getTopLevelClass(Class<?> clazz) {
Class<?> topLevelClass = clazz;
Class<?> upperClass = clazz;
while(true) {
upperClass = upperClass.getEnclosingClass();
if (upperClass == null) {
return topLevelClass;
}
topLevelClass = upperClass;
}
}
public static Class<? extends Mob> toBukkitClass(Class<? extends net.minecraft.world.entity.Mob> internalClass) {
Class<? extends Mob> bukkitClass = BUKKIT_BRIDGE.get(internalClass);
if (bukkitClass == null) {
throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob?
throw new RuntimeException("Can't figure out applicable bukkit entity for internal entity " + internalClass); // maybe just return Mob?
}
return bukkitClass;
}

View File

@@ -21,41 +21,45 @@ public class PaperGoal<T extends Mob> implements com.destroystokyo.paper.entity.
}
public Goal getHandle() {
return handle;
return this.handle;
}
@Override
public boolean shouldActivate() {
return handle.canUse();
return this.handle.canUse();
}
@Override
public boolean shouldStayActive() {
return handle.canContinueToUse();
return this.handle.canContinueToUse();
}
@Override
public void start() {
handle.start();
this.handle.start();
}
@Override
public void stop() {
handle.stop();
this.handle.stop();
}
@Override
public void tick() {
handle.tick();
this.handle.tick();
}
@Override
public GoalKey<T> getKey() {
return key;
return this.key;
}
@Override
public EnumSet<GoalType> getTypes() {
return types;
return this.types;
}
public String toString() {
return this.key.toString();
}
}

View File

@@ -1,5 +1,7 @@
package com.destroystokyo.paper.loottable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.papermc.paper.configuration.WorldConfiguration;
import io.papermc.paper.configuration.type.DurationOrDisabled;
import java.util.HashMap;
@@ -14,6 +16,8 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.RandomizableContainer;
import net.minecraft.world.entity.vehicle.ContainerEntity;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -164,53 +168,38 @@ public class PaperLootableInventoryData {
private static final String NUM_REFILLS = "numRefills";
private static final String LOOTED_PLAYERS = "lootedPlayers";
public void loadNbt(final CompoundTag base) {
final Optional<CompoundTag> compOpt = base.getCompound(ROOT);
if (compOpt.isEmpty()) {
return;
}
CompoundTag comp = compOpt.get();
this.lastFill = comp.getLongOr(LAST_FILL, -1);
this.nextRefill = comp.getLongOr(NEXT_REFILL, -1);
this.numRefills = comp.getIntOr(NUM_REFILLS, 0);
final ListTag list = comp.getListOrEmpty(LOOTED_PLAYERS);
final int size = list.size();
if (size > 0) {
this.lootedPlayers = new HashMap<>(list.size());
}
for (int i = 0; i < size; i++) {
list.getCompound(i).ifPresent(tag -> {
tag.read("UUID", UUIDUtil.CODEC).ifPresent(uuid -> {
this.lootedPlayers.put(uuid, tag.getLongOr("Time", 0));
});
});
public void loadNbt(final ValueInput input) {
final ValueInput data = input.childOrEmpty(ROOT);
this.lastFill = data.getLongOr(LAST_FILL, -1);
this.nextRefill = data.getLongOr(NEXT_REFILL, -1);
this.numRefills = data.getIntOr(NUM_REFILLS, 0);
final ValueInput.TypedInputList<SerializedLootedPlayerEntry> list = data.listOrEmpty(LOOTED_PLAYERS, SerializedLootedPlayerEntry.CODEC);
if (!list.isEmpty()) {
this.lootedPlayers = new HashMap<>();
list.forEach(serializedLootedPlayerEntry -> lootedPlayers.put(serializedLootedPlayerEntry.uuid, serializedLootedPlayerEntry.time));
}
}
public void saveNbt(final CompoundTag base) {
final CompoundTag comp = new CompoundTag();
public void saveNbt(final ValueOutput output) {
final ValueOutput data = output.child(ROOT);
if (this.nextRefill != -1) {
comp.putLong(NEXT_REFILL, this.nextRefill);
data.putLong(NEXT_REFILL, this.nextRefill);
}
if (this.lastFill != -1) {
comp.putLong(LAST_FILL, this.lastFill);
data.putLong(LAST_FILL, this.lastFill);
}
if (this.numRefills != 0) {
comp.putInt(NUM_REFILLS, this.numRefills);
data.putInt(NUM_REFILLS, this.numRefills);
}
if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) {
final ListTag list = new ListTag();
final ValueOutput.TypedOutputList<SerializedLootedPlayerEntry> list = data.list(LOOTED_PLAYERS, SerializedLootedPlayerEntry.CODEC);
for (final Map.Entry<UUID, Long> entry : this.lootedPlayers.entrySet()) {
final CompoundTag cmp = new CompoundTag();
cmp.store("UUID", UUIDUtil.CODEC, entry.getKey());
cmp.putLong("Time", entry.getValue());
list.add(cmp);
list.add(new SerializedLootedPlayerEntry(entry.getKey(), entry.getValue()));
}
comp.put(LOOTED_PLAYERS, list);
}
if (!comp.isEmpty()) {
base.put(ROOT, comp);
if (data.isEmpty()) {
output.discard(ROOT);
}
}
@@ -242,4 +231,14 @@ public class PaperLootableInventoryData {
@Nullable Long getLastLooted(final UUID player) {
return this.lootedPlayers != null ? this.lootedPlayers.get(player) : null;
}
record SerializedLootedPlayerEntry(UUID uuid, long time) {
public static final Codec<SerializedLootedPlayerEntry> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
UUIDUtil.CODEC.fieldOf("UUID").forGetter(SerializedLootedPlayerEntry::uuid),
Codec.LONG.optionalFieldOf("Time", 0L).forGetter(SerializedLootedPlayerEntry::time)
)
.apply(instance, SerializedLootedPlayerEntry::new)
);
}
}

View File

@@ -45,8 +45,8 @@ public record ServerBuildInfoImpl(
.orElse(BRAND_PAPER_ID),
getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME)
.orElse(BRAND_PAPER_NAME),
SharedConstants.getCurrentVersion().getId(),
SharedConstants.getCurrentVersion().getName(),
SharedConstants.getCurrentVersion().id(),
SharedConstants.getCurrentVersion().name(),
getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER)
.map(Integer::parseInt)
.map(OptionalInt::of)

View File

@@ -10,10 +10,10 @@ import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public record APICommandMeta(@Nullable PluginMeta pluginMeta, @Nullable String description, List<String> aliases, @Nullable String helpCommandNamespace, boolean serverSideOnly) {
public record APICommandMeta(@Nullable PluginMeta pluginMeta, @Nullable String description, List<String> aliases, @Nullable String helpCommandNamespace) {
public APICommandMeta(final @Nullable PluginMeta pluginMeta, final @Nullable String description) {
this(pluginMeta, description, Collections.emptyList(), null, false);
this(pluginMeta, description, Collections.emptyList(), null);
}
public APICommandMeta {
@@ -26,6 +26,6 @@ public record APICommandMeta(@Nullable PluginMeta pluginMeta, @Nullable String d
}
public APICommandMeta withAliases(List<String> registeredAliases) {
return new APICommandMeta(this.pluginMeta, this.description, List.copyOf(registeredAliases), this.helpCommandNamespace, this.serverSideOnly);
return new APICommandMeta(this.pluginMeta, this.description, List.copyOf(registeredAliases), this.helpCommandNamespace);
}
}

View File

@@ -95,7 +95,7 @@ public class PaperCommands implements Commands, PaperRegistrar<LifecycleEventOwn
}
public @Unmodifiable Set<String> registerWithFlagsInternal(final @Nullable PluginMeta pluginMeta, final String namespace, final @Nullable String helpNamespaceOverride, final LiteralCommandNode<CommandSourceStack> node, final @Nullable String description, final Collection<String> aliases, final Set<CommandRegistrationFlag> flags) {
final APICommandMeta meta = new APICommandMeta(pluginMeta, description, List.of(), helpNamespaceOverride, flags.contains(CommandRegistrationFlag.SERVER_ONLY));
final APICommandMeta meta = new APICommandMeta(pluginMeta, description, List.of(), helpNamespaceOverride);
final String literal = node.getLiteral();
final LiteralCommandNode<CommandSourceStack> pluginLiteral = PaperBrigadier.copyLiteral(namespace + ":" + literal, node);

View File

@@ -162,7 +162,7 @@ public final class MobcapsCommand implements PaperSubcommand {
}
final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
final ServerLevel level = serverPlayer.serverLevel();
final ServerLevel level = serverPlayer.level();
if (!level.paperConfig().entities.spawning.perPlayerMobSpawns) {
sender.sendMessage(Component.text("Use '/paper mobcaps' for worlds where per-player mob spawning is disabled.", NamedTextColor.RED));

View File

@@ -184,7 +184,6 @@ public final class DataComponentAdapters {
register(DataComponents.RABBIT_VARIANT, nms -> Rabbit.Type.values()[nms.ordinal()], api -> net.minecraft.world.entity.animal.Rabbit.Variant.byId(api.ordinal()));
register(DataComponents.PIG_VARIANT, CraftPig.CraftVariant::minecraftHolderToBukkit, CraftPig.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.COW_VARIANT, CraftCow.CraftVariant::minecraftHolderToBukkit, CraftCow.CraftVariant::bukkitToMinecraftHolder);
// TODO: We should probably find a better pattern for handling this which retains the EitherHolder, this does kinda suck in terms of exposure, however
register(DataComponents.CHICKEN_VARIANT, nms -> CraftChicken.CraftVariant.minecraftHolderToBukkit(nms.unwrap(CraftRegistry.getMinecraftRegistry()).orElseThrow()), api -> new EitherHolder<>(CraftChicken.CraftVariant.bukkitToMinecraftHolder(api)));
register(DataComponents.FROG_VARIANT, CraftFrog.CraftVariant::minecraftHolderToBukkit, CraftFrog.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.HORSE_VARIANT, nms -> Horse.Color.values()[nms.ordinal()], api -> net.minecraft.world.entity.animal.horse.Variant.byId(api.ordinal()));

View File

@@ -3,13 +3,13 @@ package io.papermc.paper.datacomponent.item;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import io.papermc.paper.registry.tag.TagKey;
import io.papermc.paper.text.Filtered;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.util.TriState;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.component.OminousBottleAmplifier;
import org.bukkit.JukeboxSong;
@@ -171,11 +171,11 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
}
@Override
public UseRemainder useRemainder(final ItemStack itemStack) {
Preconditions.checkArgument(itemStack != null, "Item cannot be null");
Preconditions.checkArgument(!itemStack.isEmpty(), "Remaining item cannot be empty!");
public UseRemainder useRemainder(final ItemStack stack) {
Preconditions.checkArgument(stack != null, "Item cannot be null");
Preconditions.checkArgument(!stack.isEmpty(), "Remaining item cannot be empty!");
return new PaperUseRemainder(
new net.minecraft.world.item.component.UseRemainder(CraftItemStack.asNMSCopy(itemStack))
new net.minecraft.world.item.component.UseRemainder(CraftItemStack.asNMSCopy(stack))
);
}
@@ -203,7 +203,7 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
@Override
public Repairable repairable(final RegistryKeySet<ItemType> types) {
return new PaperRepairable(new net.minecraft.world.item.enchantment.Repairable(
PaperRegistrySets.convertToNms(Registries.ITEM, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), types)
PaperRegistrySets.convertToNms(Registries.ITEM, Conversions.global().lookup(), types)
));
}

View File

@@ -8,13 +8,13 @@ import io.papermc.paper.datacomponent.item.blocksattacks.PaperDamageReduction;
import io.papermc.paper.datacomponent.item.blocksattacks.PaperItemDamageFunction;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.tag.TagKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.kyori.adventure.key.Key;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.damage.DamageType;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.Nullable;
public record PaperBlocksAttacks(
net.minecraft.world.item.component.BlocksAttacks impl
@@ -65,7 +65,7 @@ public record PaperBlocksAttacks(
private float blockDelaySeconds;
private float disableCooldownScale = 1.0F;
private List<DamageReduction> damageReductions = new ArrayList<>();
private List<DamageReduction> damageReductions = new ObjectArrayList<>();
private ItemDamageFunction itemDamage = new PaperItemDamageFunction(net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction.DEFAULT);
private @Nullable TagKey<DamageType> bypassedBy;
private @Nullable Key blockSound;
@@ -87,11 +87,16 @@ public record PaperBlocksAttacks(
@Override
public Builder addDamageReduction(final DamageReduction reduction) {
Preconditions.checkArgument(reduction.horizontalBlockingAngle() >= 0, "horizontalBlockingAngle must be non-negative, was %s", reduction.horizontalBlockingAngle());
this.damageReductions.add(reduction);
return this;
}
@Override
public Builder damageReductions(final List<DamageReduction> reductions) {
this.damageReductions = new ObjectArrayList<>(reductions);
return this;
}
@Override
public Builder itemDamage(final ItemDamageFunction function) {
this.itemDamage = function;
@@ -105,30 +110,24 @@ public record PaperBlocksAttacks(
}
@Override
public Builder blockSound(@Nullable final Key sound) {
public Builder blockSound(final @Nullable Key sound) {
this.blockSound = sound;
return this;
}
@Override
public Builder disableSound(@Nullable final Key sound) {
public Builder disableSound(final @Nullable Key sound) {
this.disableSound = sound;
return this;
}
@Override
public Builder damageReductions(final List<DamageReduction> reductions) {
this.damageReductions = new ArrayList<>(reductions);
return this;
}
@Override
public BlocksAttacks build() {
return new PaperBlocksAttacks(new net.minecraft.world.item.component.BlocksAttacks(
this.blockDelaySeconds,
this.disableCooldownScale,
this.damageReductions.stream().map(damageReduction -> ((PaperDamageReduction) damageReduction).getHandle()).toList(),
((PaperItemDamageFunction) itemDamage).getHandle(),
((PaperItemDamageFunction) this.itemDamage).getHandle(),
Optional.ofNullable(this.bypassedBy).map(PaperRegistries::toNms),
Optional.ofNullable(this.blockSound).map(PaperAdventure::resolveSound),
Optional.ofNullable(this.disableSound).map(PaperAdventure::resolveSound)

View File

@@ -4,7 +4,7 @@ import com.google.common.base.Preconditions;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
import io.papermc.paper.datacomponent.item.consumable.PaperConsumableEffects;
import io.papermc.paper.datacomponent.item.consumable.PaperConsumableEffect;
import io.papermc.paper.util.MCUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
@@ -49,7 +49,7 @@ public record PaperConsumable(
@Override
public @Unmodifiable List<ConsumeEffect> consumeEffects() {
return MCUtil.transformUnmodifiable(this.impl.onConsumeEffects(), PaperConsumableEffects::fromNms);
return MCUtil.transformUnmodifiable(this.impl.onConsumeEffects(), PaperConsumableEffect::fromNms);
}
@Override
@@ -98,14 +98,14 @@ public record PaperConsumable(
@Override
public Builder addEffect(final ConsumeEffect effect) {
this.effects.add(PaperConsumableEffects.toNms(effect));
this.effects.add(PaperConsumableEffect.toNms(effect));
return this;
}
@Override
public Builder addEffects(final List<ConsumeEffect> effects) {
for (final ConsumeEffect effect : effects) {
this.effects.add(PaperConsumableEffects.toNms(effect));
this.effects.add(PaperConsumableEffect.toNms(effect));
}
return this;
}

View File

@@ -1,7 +1,7 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.datacomponent.item.consumable.PaperConsumableEffects;
import io.papermc.paper.datacomponent.item.consumable.PaperConsumableEffect;
import io.papermc.paper.util.MCUtil;
import java.util.ArrayList;
import java.util.List;
@@ -19,7 +19,7 @@ public record PaperDeathProtection(
@Override
public @Unmodifiable List<ConsumeEffect> deathEffects() {
return MCUtil.transformUnmodifiable(this.impl.deathEffects(), PaperConsumableEffects::fromNms);
return MCUtil.transformUnmodifiable(this.impl.deathEffects(), PaperConsumableEffect::fromNms);
}
static final class BuilderImpl implements Builder {
@@ -28,14 +28,14 @@ public record PaperDeathProtection(
@Override
public Builder addEffect(final ConsumeEffect effect) {
this.effects.add(PaperConsumableEffects.toNms(effect));
this.effects.add(PaperConsumableEffect.toNms(effect));
return this;
}
@Override
public Builder addEffects(final List<ConsumeEffect> effects) {
for (final ConsumeEffect effect : effects) {
this.effects.add(PaperConsumableEffects.toNms(effect));
this.effects.add(PaperConsumableEffect.toNms(effect));
}
return this;
}

View File

@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import java.util.Optional;
@@ -20,7 +21,7 @@ import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.EquipmentSlot;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jspecify.annotations.Nullable;
public record PaperEquippable(
net.minecraft.world.item.equipment.Equippable impl
@@ -82,6 +83,16 @@ public record PaperEquippable(
return this.impl.equipOnInteract();
}
@Override
public boolean canBeSheared() {
return this.impl.canBeSheared();
}
@Override
public Key shearSound() {
return PaperAdventure.asAdventure(this.impl.shearingSound().value().location());
}
@Override
public Builder toBuilder() {
return new BuilderImpl(this.slot())
@@ -92,7 +103,9 @@ public record PaperEquippable(
.dispensable(this.dispensable())
.swappable(this.swappable())
.damageOnHurt(this.damageOnHurt())
.equipOnInteract(this.equipOnInteract());
.equipOnInteract(this.equipOnInteract())
.shearSound(this.shearSound())
.canBeSheared(this.canBeSheared());
}
@@ -107,6 +120,8 @@ public record PaperEquippable(
private boolean swappable = true;
private boolean damageOnHurt = true;
private boolean equipOnInteract;
private boolean canBeSheared = false;
private Holder<SoundEvent> shearSound = BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvents.SHEARS_SNIP);
BuilderImpl(final EquipmentSlot equipmentSlot) {
this.equipmentSlot = CraftEquipmentSlot.getNMS(equipmentSlot);
@@ -137,7 +152,7 @@ public record PaperEquippable(
@Override
public Builder allowedEntities(final @Nullable RegistryKeySet<EntityType> allowedEntities) {
this.allowedEntities = Optional.ofNullable(allowedEntities)
.map((set) -> PaperRegistrySets.convertToNms(Registries.ENTITY_TYPE, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), set));
.map((set) -> PaperRegistrySets.convertToNms(Registries.ENTITY_TYPE, Conversions.global().lookup(), set));
return this;
}
@@ -165,6 +180,18 @@ public record PaperEquippable(
return this;
}
@Override
public Builder canBeSheared(final boolean canBeSheared) {
this.canBeSheared = canBeSheared;
return this;
}
@Override
public Builder shearSound(final Key shearSound) {
this.shearSound = PaperAdventure.resolveSound(shearSound);
return this;
}
@Override
public Equippable build() {
return new PaperEquippable(
@@ -177,7 +204,9 @@ public record PaperEquippable(
this.dispensable,
this.swappable,
this.damageOnHurt,
this.equipOnInteract
this.equipOnInteract,
this.canBeSheared,
this.shearSound
)
);
}

View File

@@ -2,13 +2,13 @@ package io.papermc.paper.datacomponent.item;
import io.papermc.paper.block.BlockPredicate;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.util.MCUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.advancements.critereon.DataComponentMatchers;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import org.bukkit.craftbukkit.util.Handleable;
@@ -25,6 +25,7 @@ public record PaperItemAdventurePredicate(
public net.minecraft.world.item.AdventureModePredicate getHandle() {
return this.impl;
}
@Override
public List<BlockPredicate> predicates() {
return convert(this.impl);
@@ -37,7 +38,7 @@ public record PaperItemAdventurePredicate(
@Override
public ItemAdventurePredicate.Builder addPredicate(final BlockPredicate predicate) {
this.predicates.add(new net.minecraft.advancements.critereon.BlockPredicate(Optional.ofNullable(predicate.blocks()).map(
blocks -> PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), blocks)
blocks -> PaperRegistrySets.convertToNms(Registries.BLOCK, Conversions.global().lookup(), blocks)
), Optional.empty(), Optional.empty(), DataComponentMatchers.ANY)); // TODO DataComponentMatchers
return this;
}

View File

@@ -26,6 +26,7 @@ public record PaperItemArmorTrim(
BuilderImpl(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;
}
@Override
public ItemArmorTrim.Builder armorTrim(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;

View File

@@ -1,6 +1,8 @@
package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import io.papermc.paper.datacomponent.item.attribute.AttributeModifierDisplay;
import io.papermc.paper.datacomponent.item.attribute.PaperAttributeModifierDisplay;
import io.papermc.paper.util.MCUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
@@ -21,7 +23,8 @@ public record PaperItemAttributeModifiers(
private static List<Entry> convert(final net.minecraft.world.item.component.ItemAttributeModifiers nmsModifiers) {
return MCUtil.transformUnmodifiable(nmsModifiers.modifiers(), nms -> new PaperEntry(
CraftAttribute.minecraftHolderToBukkit(nms.attribute()),
CraftAttributeInstance.convert(nms.modifier(), nms.slot())
CraftAttributeInstance.convert(nms.modifier(), nms.slot()),
PaperAttributeModifierDisplay.fromNms(nms.display())
));
}
@@ -35,7 +38,7 @@ public record PaperItemAttributeModifiers(
return convert(this.impl);
}
public record PaperEntry(Attribute attribute, AttributeModifier modifier) implements ItemAttributeModifiers.Entry {
public record PaperEntry(Attribute attribute, AttributeModifier modifier, AttributeModifierDisplay display) implements ItemAttributeModifiers.Entry {
}
static final class BuilderImpl implements ItemAttributeModifiers.Builder {
@@ -43,12 +46,7 @@ public record PaperItemAttributeModifiers(
private final List<net.minecraft.world.item.component.ItemAttributeModifiers.Entry> entries = new ObjectArrayList<>();
@Override
public Builder addModifier(final Attribute attribute, final AttributeModifier modifier) {
return this.addModifier(attribute, modifier, modifier.getSlotGroup());
}
@Override
public ItemAttributeModifiers.Builder addModifier(final Attribute attribute, final AttributeModifier modifier, final EquipmentSlotGroup equipmentSlotGroup) {
public ItemAttributeModifiers.Builder addModifier(final Attribute attribute, final AttributeModifier modifier, final EquipmentSlotGroup equipmentSlotGroup, final AttributeModifierDisplay display) {
Preconditions.checkArgument(
this.entries.stream().noneMatch(e ->
e.modifier().id().equals(CraftNamespacedKey.toMinecraft(modifier.getKey())) && e.attribute().is(CraftNamespacedKey.toMinecraft(attribute.getKey()))
@@ -60,7 +58,8 @@ public record PaperItemAttributeModifiers(
this.entries.add(new net.minecraft.world.item.component.ItemAttributeModifiers.Entry(
CraftAttribute.bukkitToMinecraftHolder(attribute),
CraftAttributeInstance.convert(modifier),
CraftEquipmentSlot.getNMSGroup(equipmentSlotGroup)
CraftEquipmentSlot.getNMSGroup(equipmentSlotGroup),
PaperAttributeModifierDisplay.toNms(display)
));
return this;
}

View File

@@ -48,7 +48,7 @@ public record PaperItemContainerContents(
this.items.size() + stacks.size()
);
MCUtil.addAndConvert(this.items, stacks, stack -> {
Preconditions.checkArgument(stack != null, "Cannot pass null itemstacks!");
Preconditions.checkArgument(stack != null, "Cannot pass null item!");
return CraftItemStack.asNMSCopy(stack);
});
return this;

View File

@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import io.papermc.paper.util.MCUtil;
@@ -10,12 +11,11 @@ import java.util.Collection;
import java.util.List;
import java.util.Optional;
import net.kyori.adventure.util.TriState;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import org.bukkit.block.BlockType;
import org.bukkit.craftbukkit.util.Handleable;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.Nullable;
public record PaperItemTool(
net.minecraft.world.item.component.Tool impl
@@ -85,7 +85,7 @@ public record PaperItemTool(
@Override
public Builder addRule(final Rule rule) {
this.rules.add(new net.minecraft.world.item.component.Tool.Rule(
PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), rule.blocks()),
PaperRegistrySets.convertToNms(Registries.BLOCK, Conversions.global().lookup(), rule.blocks()),
Optional.ofNullable(rule.speed()),
Optional.ofNullable(rule.correctForDrops().toBoolean())
));

View File

@@ -14,8 +14,8 @@ import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.Nullable;
public record PaperPotionContents(
net.minecraft.world.item.alchemy.PotionContents impl

View File

@@ -13,8 +13,10 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import net.minecraft.util.StringUtil;
import org.bukkit.craftbukkit.util.Handleable;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.intellij.lang.annotations.Pattern;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.Nullable;
public record PaperResolvableProfile(
net.minecraft.world.item.component.ResolvableProfile impl

View File

@@ -28,7 +28,6 @@ public record PaperUseCooldown(
.orElse(null);
}
static final class BuilderImpl implements Builder {
private final float seconds;

View File

@@ -0,0 +1,25 @@
package io.papermc.paper.datacomponent.item.attribute;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.text.ComponentLike;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import org.jspecify.annotations.NullMarked;
@NullMarked
public class AttributeModifierDisplayBridgeImpl implements AttributeModifierDisplayBridge {
@Override
public AttributeModifierDisplay.Default reset() {
return new PaperDefaultDisplay(new ItemAttributeModifiers.Display.Default());
}
@Override
public AttributeModifierDisplay.Hidden hidden() {
return new PaperHiddenDisplay(new ItemAttributeModifiers.Display.Hidden());
}
@Override
public AttributeModifierDisplay.OverrideText override(final ComponentLike text) {
return new PaperOverrideTextDisplay(new ItemAttributeModifiers.Display.OverrideText(PaperAdventure.asVanilla(text.asComponent())));
}
}

View File

@@ -0,0 +1,24 @@
package io.papermc.paper.datacomponent.item.attribute;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import org.bukkit.craftbukkit.util.Handleable;
public interface PaperAttributeModifierDisplay<T extends ItemAttributeModifiers.Display> extends Handleable<T> {
static AttributeModifierDisplay fromNms(ItemAttributeModifiers.Display display) {
return switch (display) {
case ItemAttributeModifiers.Display.Default def -> new PaperDefaultDisplay(def);
case ItemAttributeModifiers.Display.Hidden hidden -> new PaperHiddenDisplay(hidden);
case ItemAttributeModifiers.Display.OverrideText override -> new PaperOverrideTextDisplay(override);
default -> throw new UnsupportedOperationException("Don't know how to convert " + display.getClass());
};
}
static ItemAttributeModifiers.Display toNms(AttributeModifierDisplay display) {
if (display instanceof PaperAttributeModifierDisplay<?> modifierDisplay) {
return modifierDisplay.getHandle();
} else {
throw new UnsupportedOperationException("Must implement handleable!");
}
}
}

View File

@@ -0,0 +1,13 @@
package io.papermc.paper.datacomponent.item.attribute;
import net.minecraft.world.item.component.ItemAttributeModifiers;
public record PaperDefaultDisplay(
ItemAttributeModifiers.Display.Default impl
) implements AttributeModifierDisplay.Default, PaperAttributeModifierDisplay<ItemAttributeModifiers.Display.Default> {
@Override
public ItemAttributeModifiers.Display.Default getHandle() {
return this.impl;
}
}

View File

@@ -0,0 +1,13 @@
package io.papermc.paper.datacomponent.item.attribute;
import net.minecraft.world.item.component.ItemAttributeModifiers;
public record PaperHiddenDisplay(
ItemAttributeModifiers.Display.Hidden impl
) implements AttributeModifierDisplay.Hidden, PaperAttributeModifierDisplay<ItemAttributeModifiers.Display.Hidden> {
@Override
public ItemAttributeModifiers.Display.Hidden getHandle() {
return this.impl;
}
}

View File

@@ -0,0 +1,20 @@
package io.papermc.paper.datacomponent.item.attribute;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.text.Component;
import net.minecraft.world.item.component.ItemAttributeModifiers;
public record PaperOverrideTextDisplay(
ItemAttributeModifiers.Display.OverrideText impl
) implements AttributeModifierDisplay.OverrideText, PaperAttributeModifierDisplay<ItemAttributeModifiers.Display.OverrideText> {
@Override
public Component text() {
return PaperAdventure.asAdventure(this.impl.component());
}
@Override
public ItemAttributeModifiers.Display.OverrideText getHandle() {
return this.impl;
}
}

View File

@@ -0,0 +1,7 @@
/**
* Relating to attribute modifier display for components.
*/
@NullMarked
package io.papermc.paper.datacomponent.item.attribute;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,9 +1,7 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@ApiStatus.Internal
@NullMarked
public class BlocksAttacksBridgeImpl implements BlocksAttacksBridge {

View File

@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item.blocksattacks;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import net.minecraft.core.HolderSet;
@@ -9,7 +10,7 @@ import net.minecraft.core.registries.Registries;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.damage.DamageType;
import org.checkerframework.checker.index.qual.Positive;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.Nullable;
import java.util.Optional;
public record PaperDamageReduction(
@@ -44,19 +45,19 @@ public record PaperDamageReduction(
static final class BuilderImpl implements Builder {
private Optional<HolderSet<net.minecraft.world.damagesource.DamageType>> type = Optional.empty();
private float horizontalBlockingAngle = 90f;
private float base = 0;
private float factor = 0;
private float horizontalBlockingAngle = 90.0F;
private float base = 0.0F;
private float factor = 1.0F;
@Override
public Builder type(final @Nullable RegistryKeySet<DamageType> type) {
this.type = Optional.ofNullable(type)
.map((set) -> PaperRegistrySets.convertToNms(Registries.DAMAGE_TYPE, net.minecraft.server.MinecraftServer.getServer().registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE).lookupProvider, set));
.map((set) -> PaperRegistrySets.convertToNms(Registries.DAMAGE_TYPE, Conversions.global().lookup(), set));
return this;
}
@Override
public Builder horizontalBlockingAngle(@Positive final float horizontalBlockingAngle) {
public Builder horizontalBlockingAngle(final @Positive float horizontalBlockingAngle) {
Preconditions.checkArgument(horizontalBlockingAngle > 0, "horizontalBlockingAngle must be positive and not zero, was %s", horizontalBlockingAngle);
this.horizontalBlockingAngle = horizontalBlockingAngle;
return this;

View File

@@ -1,6 +1,7 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import com.google.common.base.Preconditions;
import net.minecraft.world.item.component.BlocksAttacks;
import org.bukkit.craftbukkit.util.Handleable;
import org.checkerframework.checker.index.qual.NonNegative;
@@ -35,12 +36,12 @@ public record PaperItemDamageFunction(
static final class BuilderImpl implements Builder {
private float threshold;
private float base;
private float factor;
private float threshold = BlocksAttacks.ItemDamageFunction.DEFAULT.threshold();
private float base = BlocksAttacks.ItemDamageFunction.DEFAULT.base();
private float factor = BlocksAttacks.ItemDamageFunction.DEFAULT.factor();
@Override
public Builder threshold(@NonNegative final float threshold) {
public Builder threshold(final @NonNegative float threshold) {
Preconditions.checkArgument(threshold >= 0, "threshold must be non-negative, was %s", threshold);
this.threshold = threshold;
return this;

View File

@@ -3,20 +3,18 @@ package io.papermc.paper.datacomponent.item.consumable;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import java.util.ArrayList;
import java.util.List;
import net.kyori.adventure.key.Key;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@ApiStatus.Internal
@NullMarked
public class ConsumableTypesBridgeImpl implements ConsumableTypesBridge {
@@ -35,7 +33,7 @@ public class ConsumableTypesBridgeImpl implements ConsumableTypesBridge {
public ConsumeEffect.RemoveStatusEffects removeStatusEffects(final RegistryKeySet<PotionEffectType> effectTypes) {
return new PaperRemoveStatusEffects(
new net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect(
PaperRegistrySets.convertToNms(Registries.MOB_EFFECT, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), effectTypes)
PaperRegistrySets.convertToNms(Registries.MOB_EFFECT, Conversions.global().lookup(), effectTypes)
)
);
}

View File

@@ -9,7 +9,7 @@ import static io.papermc.paper.util.MCUtil.transformUnmodifiable;
public record PaperApplyStatusEffects(
ApplyStatusEffectsConsumeEffect impl
) implements ConsumeEffect.ApplyStatusEffects, PaperConsumableEffectImpl<ApplyStatusEffectsConsumeEffect> {
) implements ConsumeEffect.ApplyStatusEffects, PaperConsumableEffect<ApplyStatusEffectsConsumeEffect> {
@Override
public List<PotionEffect> effects() {

View File

@@ -1,8 +1,10 @@
package io.papermc.paper.datacomponent.item.consumable;
import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect;
public record PaperClearAllStatusEffects(
net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect impl
) implements ConsumeEffect.ClearAllStatusEffects, PaperConsumableEffectImpl<net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect> {
) implements ConsumeEffect.ClearAllStatusEffects, PaperConsumableEffect<ClearAllStatusEffectsConsumeEffect> {
@Override
public net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect getHandle() {

View File

@@ -2,16 +2,15 @@ package io.papermc.paper.datacomponent.item.consumable;
import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.ConsumeEffect;
import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect;
import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect;
import org.bukkit.craftbukkit.util.Handleable;
public final class PaperConsumableEffects {
public interface PaperConsumableEffect<T extends ConsumeEffect> extends Handleable<T> {
private PaperConsumableEffects() {
}
public static ConsumeEffect fromNms(net.minecraft.world.item.consume_effects.ConsumeEffect consumable) {
static io.papermc.paper.datacomponent.item.consumable.ConsumeEffect fromNms(net.minecraft.world.item.consume_effects.ConsumeEffect consumable) {
return switch (consumable) {
case ApplyStatusEffectsConsumeEffect effect -> new PaperApplyStatusEffects(effect);
case ClearAllStatusEffectsConsumeEffect effect -> new PaperClearAllStatusEffects(effect);
@@ -22,8 +21,8 @@ public final class PaperConsumableEffects {
};
}
public static net.minecraft.world.item.consume_effects.ConsumeEffect toNms(ConsumeEffect effect) {
if (effect instanceof PaperConsumableEffectImpl<?> consumableEffect) {
static net.minecraft.world.item.consume_effects.ConsumeEffect toNms(io.papermc.paper.datacomponent.item.consumable.ConsumeEffect effect) {
if (effect instanceof PaperConsumableEffect<?> consumableEffect) {
return consumableEffect.getHandle();
} else {
throw new UnsupportedOperationException("Must implement handleable!");

View File

@@ -1,7 +0,0 @@
package io.papermc.paper.datacomponent.item.consumable;
import net.minecraft.world.item.consume_effects.ConsumeEffect;
import org.bukkit.craftbukkit.util.Handleable;
public interface PaperConsumableEffectImpl<T extends ConsumeEffect> extends Handleable<T> {
}

View File

@@ -6,7 +6,7 @@ import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect;
public record PaperPlaySound(
PlaySoundConsumeEffect impl
) implements ConsumeEffect.PlaySound, PaperConsumableEffectImpl<PlaySoundConsumeEffect> {
) implements ConsumeEffect.PlaySound, PaperConsumableEffect<PlaySoundConsumeEffect> {
@Override
public Key sound() {

View File

@@ -3,11 +3,12 @@ package io.papermc.paper.datacomponent.item.consumable;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect;
import org.bukkit.potion.PotionEffectType;
public record PaperRemoveStatusEffects(
net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect impl
) implements ConsumeEffect.RemoveStatusEffects, PaperConsumableEffectImpl<net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect> {
) implements ConsumeEffect.RemoveStatusEffects, PaperConsumableEffect<RemoveStatusEffectsConsumeEffect> {
@Override
public RegistryKeySet<PotionEffectType> removeEffects() {

View File

@@ -1,8 +1,10 @@
package io.papermc.paper.datacomponent.item.consumable;
import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect;
public record PaperTeleportRandomly(
net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect impl
) implements ConsumeEffect.TeleportRandomly, PaperConsumableEffectImpl<net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect> {
) implements ConsumeEffect.TeleportRandomly, PaperConsumableEffect<TeleportRandomlyConsumeEffect> {
@Override
public float diameter() {
return this.impl.diameter();

View File

@@ -1,12 +1,13 @@
package io.papermc.paper.entity.activation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.FlyingMob;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.ambient.AmbientCreature;
import net.minecraft.world.entity.animal.AgeableWaterCreature;
import net.minecraft.world.entity.animal.WaterAnimal;
import net.minecraft.world.entity.monster.Enemy;
import net.minecraft.world.entity.monster.Ghast;
import net.minecraft.world.entity.monster.Phantom;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.raid.Raider;
import net.minecraft.world.phys.AABB;
@@ -33,7 +34,7 @@ public enum ActivationType {
return ActivationType.WATER;
} else if (entity instanceof Villager) {
return ActivationType.VILLAGER;
} else if (entity instanceof FlyingMob && entity instanceof Enemy) {
} else if (entity instanceof Ghast || entity instanceof Phantom) { // TODO: some kind of better distinction here?
return ActivationType.FLYING_MONSTER;
} else if (entity instanceof Raider) {
return ActivationType.RAIDER;

View File

@@ -320,7 +320,6 @@ class PaperPluginInstanceManager {
}
// TODO: Implement event part in future patch (paper patch move up, this patch is lower)
private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
Bukkit.getServer().getLogger().log(Level.SEVERE, msg, ex);
this.pluginManager.callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));

View File

@@ -12,8 +12,10 @@ import io.papermc.paper.registry.data.PaperDamageTypeRegistryEntry;
import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry;
import io.papermc.paper.registry.data.PaperFrogVariantRegistryEntry;
import io.papermc.paper.registry.data.PaperGameEventRegistryEntry;
import io.papermc.paper.registry.data.PaperJukeboxSongRegistryEntry;
import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry;
import io.papermc.paper.registry.data.PaperPigVariantRegistryEntry;
import io.papermc.paper.registry.data.PaperSoundEventRegistryEntry;
import io.papermc.paper.registry.data.PaperWolfVariantRegistryEntry;
import io.papermc.paper.registry.entry.RegistryEntry;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
@@ -95,7 +97,7 @@ public final class PaperRegistries {
static {
REGISTRY_ENTRIES = List.of(
// Start generate - RegistryDefinitions
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
// built-in
start(Registries.GAME_EVENT, RegistryKey.GAME_EVENT).craft(GameEvent.class, CraftGameEvent::new).writable(PaperGameEventRegistryEntry.PaperBuilder::new),
start(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE).craft(StructureType.class, CraftStructureType::new).build(),
@@ -108,7 +110,7 @@ public final class PaperRegistries {
start(Registries.MENU, RegistryKey.MENU).craft(MenuType.class, CraftMenuType::new).build(),
start(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE).craft(Attribute.class, CraftAttribute::new).serializationUpdater(FieldRename.ATTRIBUTE_RENAME).build(),
start(Registries.FLUID, RegistryKey.FLUID).craft(Fluid.class, CraftFluid::new).build(),
start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new, true).build(),
start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new, true).create(PaperSoundEventRegistryEntry.PaperBuilder::new, RegistryEntryMeta.RegistryModificationApiSupport.NONE),
start(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE).craft(DataComponentTypes.class, PaperDataComponentType::of).build(),
// data-driven
@@ -120,9 +122,9 @@ public final class PaperRegistries {
start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).writable(PaperWolfVariantRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.WOLF_SOUND_VARIANT, RegistryKey.WOLF_SOUND_VARIANT).craft(Wolf.SoundVariant.class, CraftWolf.CraftSoundVariant::new).build(),
start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(),
start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).writable(PaperJukeboxSongRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new, true).writable(PaperBannerPatternRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new, true).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new, true).build().delayed(),
start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).writable(PaperCatTypeRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).writable(PaperFrogVariantRegistryEntry.PaperBuilder::new).delayed(),

View File

@@ -97,12 +97,12 @@ public class PaperRegistryAccess implements RegistryAccess {
return registry;
}
public <M> void registerReloadableRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
this.registerRegistry(resourceKey, registry, true);
public <M> void registerReloadableRegistry(final net.minecraft.core.Registry<M> registry) {
this.registerRegistry(registry, true);
}
public <M> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
this.registerRegistry(resourceKey, registry, false);
public <M> void registerRegistry(final net.minecraft.core.Registry<M> registry) {
this.registerRegistry(registry, false);
}
public <M> void lockReferenceHolders(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey) {
@@ -115,8 +115,8 @@ public class PaperRegistryAccess implements RegistryAccess {
}
@SuppressWarnings("unchecked") // this method should be called right after any new MappedRegistry instances are created to later be used by the server.
private <M, B extends Keyed, R extends Registry<B>> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry, final boolean replace) {
final RegistryEntry<M, B> entry = PaperRegistries.getEntry(resourceKey);
private <M, B extends Keyed, R extends Registry<B>> void registerRegistry(final net.minecraft.core.Registry<M> registry, final boolean replace) {
final RegistryEntry<M, B> entry = PaperRegistries.getEntry(registry.key());
if (entry == null) { // skip registries that don't have API entries
return;
}
@@ -129,7 +129,7 @@ public class PaperRegistryAccess implements RegistryAccess {
// if the registry holder is delayed, and the entry is marked as "delayed", then load the holder with the CraftRegistry instance that wraps the actual nms Registry.
((RegistryHolder.Delayed<B, R>) registryHolder).loadFrom(delayedEntry, registry);
} else {
throw new IllegalArgumentException(resourceKey + " has already been created");
throw new IllegalArgumentException(registry.key() + " has already been created");
}
}
}

View File

@@ -2,19 +2,28 @@ package io.papermc.paper.registry;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.data.util.Conversions;
import java.util.Optional;
import java.util.function.Function;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import org.bukkit.Keyed;
import org.jspecify.annotations.Nullable;
public class PaperRegistryBuilderFactory<M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> implements RegistryBuilderFactory<A, B> { // TODO remove Keyed
private final ResourceKey<? extends Registry<M>> registryKey;
private final Conversions conversions;
private final PaperRegistryBuilder.Filler<M, A, B> builderFiller;
private final Function<? super ResourceLocation, ? extends @Nullable M> existingValueGetter;
private final Function<ResourceKey<M>, Optional<M>> existingValueGetter;
private @Nullable B builder;
public PaperRegistryBuilderFactory(final Conversions conversions, final PaperRegistryBuilder.Filler<M, A, B> builderFiller, final Function<? super ResourceLocation, ? extends @Nullable M> existingValueGetter) {
public PaperRegistryBuilderFactory(
final ResourceKey<? extends Registry<M>> registryKey,
final Conversions conversions,
final PaperRegistryBuilder.Filler<M, A, B> builderFiller,
final Function<ResourceKey<M>, Optional<M>> existingValueGetter
) {
this.registryKey = registryKey;
this.conversions = conversions;
this.builderFiller = builderFiller;
this.existingValueGetter = existingValueGetter;
@@ -42,10 +51,10 @@ public class PaperRegistryBuilderFactory<M, A extends Keyed, B extends PaperRegi
@Override
public B copyFrom(final TypedKey<A> key) {
this.validate();
final M existing = this.existingValueGetter.apply(PaperAdventure.asVanilla(key));
if (existing == null) {
final Optional<M> existing = this.existingValueGetter.apply(PaperAdventure.asVanilla(this.registryKey, key));
if (existing.isEmpty()) {
throw new IllegalArgumentException("Key " + key + " doesn't exist");
}
return this.builder = this.builderFiller.fill(this.conversions, existing);
return this.builder = this.builderFiller.fill(this.conversions, existing.get());
}
}

View File

@@ -10,11 +10,12 @@ import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.entry.RegistryEntry;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
import io.papermc.paper.registry.event.RegistryEntryAddEvent;
import io.papermc.paper.registry.event.RegistryEntryAddEventImpl;
import io.papermc.paper.registry.event.RegistryEventMap;
import io.papermc.paper.registry.event.RegistryEventProvider;
import io.papermc.paper.registry.event.RegistryFreezeEvent;
import io.papermc.paper.registry.event.RegistryFreezeEventImpl;
import io.papermc.paper.registry.event.RegistryComposeEventImpl;
import io.papermc.paper.registry.event.RegistryComposeEvent;
import io.papermc.paper.registry.event.type.RegistryEntryAddEventType;
import io.papermc.paper.registry.event.type.RegistryEntryAddEventTypeImpl;
import io.papermc.paper.registry.event.type.RegistryLifecycleEventType;
@@ -37,7 +38,7 @@ public class PaperRegistryListenerManager {
public static final PaperRegistryListenerManager INSTANCE = new PaperRegistryListenerManager();
public final RegistryEventMap valueAddEventTypes = new RegistryEventMap("value add");
public final RegistryEventMap freezeEventTypes = new RegistryEventMap("freeze");
public final RegistryEventMap composeEventType = new RegistryEventMap("compose");
private PaperRegistryListenerManager() {
}
@@ -60,7 +61,7 @@ public class PaperRegistryListenerManager {
* For {@link Registry#register(Registry, ResourceKey, Object)}
*/
public <M> M registerWithListeners(final Registry<M> registry, final ResourceKey<M> key, final M nms) {
return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, PaperRegistryListenerManager::registerWithInstance, BuiltInRegistries.BUILT_IN_CONVERSIONS);
return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, PaperRegistryListenerManager::registerWithInstance, BuiltInRegistries.STATIC_ACCESS_CONVERSIONS);
}
/**
@@ -74,7 +75,7 @@ public class PaperRegistryListenerManager {
* For {@link Registry#registerForHolder(Registry, ResourceKey, Object)}
*/
public <M> Holder.Reference<M> registerForHolderWithListeners(final Registry<M> registry, final ResourceKey<M> key, final M nms) {
return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, WritableRegistry::register, BuiltInRegistries.BUILT_IN_CONVERSIONS);
return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, WritableRegistry::register, BuiltInRegistries.STATIC_ACCESS_CONVERSIONS);
}
public <M> void registerWithListeners(
@@ -157,28 +158,28 @@ public class PaperRegistryListenerManager {
public <M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> void runFreezeListeners(final ResourceKey<? extends Registry<M>> resourceKey, final Conversions conversions) {
final RegistryEntry<M, T> entry = PaperRegistries.getEntry(resourceKey);
if (entry == null || !entry.meta().modificationApiSupport().canAdd() || !this.freezeEventTypes.hasHandlers(entry.apiKey())) {
if (entry == null || !entry.meta().modificationApiSupport().canAdd() || !this.composeEventType.hasHandlers(entry.apiKey())) {
return;
}
final RegistryEntryMeta.Buildable<M, T, B> writableEntry = (RegistryEntryMeta.Buildable<M, T, B>) entry.meta();
final WritableCraftRegistry<M, T, B> writableRegistry = PaperRegistryAccess.instance().getWritableRegistry(entry.apiKey());
final RegistryFreezeEventImpl<T, B> event = writableEntry.createFreezeEvent(writableRegistry, conversions);
LifecycleEventRunner.INSTANCE.callEvent(this.freezeEventTypes.getEventType(entry.apiKey()), event);
final RegistryComposeEventImpl<T, B> event = writableEntry.createPostLoadEvent(writableRegistry, conversions);
LifecycleEventRunner.INSTANCE.callEvent(this.composeEventType.getEventType(entry.apiKey()), event);
}
public <T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> getRegistryValueAddEventType(final RegistryEventProvider<T, B> type) {
final RegistryEntry<?, ?> entry = PaperRegistries.getEntry(type.registryKey());
if (entry == null || !entry.meta().modificationApiSupport().canModify()) {
throw new IllegalArgumentException(type.registryKey() + " does not support RegistryEntryAddEvent");
throw new IllegalArgumentException(type.registryKey() + " does not support " + RegistryEntryAddEvent.class.getSimpleName());
}
return this.valueAddEventTypes.getOrCreate(type.registryKey(), RegistryEntryAddEventTypeImpl::new);
}
public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> getRegistryFreezeEventType(final RegistryEventProvider<T, B> type) {
public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<T, B>> getRegistryComposeEventType(final RegistryEventProvider<T, B> type) {
final RegistryEntry<?, ?> entry = PaperRegistries.getEntry(type.registryKey());
if (entry == null || !entry.meta().modificationApiSupport().canAdd()) {
throw new IllegalArgumentException(type.registryKey() + " does not support RegistryFreezeEvent");
throw new IllegalArgumentException(type.registryKey() + " does not support " + RegistryComposeEvent.class.getSimpleName());
}
return this.freezeEventTypes.getOrCreate(type.registryKey(), RegistryLifecycleEventType::new);
return this.composeEventType.getOrCreate(type.registryKey(), RegistryLifecycleEventType::new);
}
}

View File

@@ -31,7 +31,7 @@ public class WritableCraftRegistry<M, T extends Keyed, B extends PaperRegistryBu
public void register(final TypedKey<T> key, final Consumer<RegistryBuilderFactory<T, B>> value, final Conversions conversions) {
final ResourceKey<M> resourceKey = PaperRegistries.toNms(key);
this.registry.validateWrite(resourceKey);
final PaperRegistryBuilderFactory<M, T, B> builderFactory = new PaperRegistryBuilderFactory<>(conversions, this.meta.builderFiller(), this.registry.temporaryUnfrozenMap::get);
final PaperRegistryBuilderFactory<M, T, B> builderFactory = new PaperRegistryBuilderFactory<>(this.registry.key(), conversions, this.meta.builderFiller(), this.registry::getValueForCopying);
value.accept(builderFactory);
PaperRegistryListenerManager.INSTANCE.registerWithListeners(
this.registry,

View File

@@ -1,34 +1,4 @@
package io.papermc.paper.registry.data;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.PaperRegistryBuilder;
import io.papermc.paper.registry.PaperRegistryBuilderFactory;
import io.papermc.paper.registry.RegistryBuilderFactory;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import org.bukkit.Art;
import org.bukkit.Keyed;
import org.bukkit.craftbukkit.CraftRegistry;
@SuppressWarnings("BoundedWildcard")
public final class InlinedRegistryBuilderProviderImpl implements InlinedRegistryBuilderProvider {
private static <M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> A create(final ResourceKey<? extends Registry<M>> registryKey, final Consumer<PaperRegistryBuilderFactory<M, A, B>> value) {
final RegistryEntryMeta.Buildable<M, A, B> buildableMeta = PaperRegistries.getBuildableMeta(registryKey);
Preconditions.checkArgument(buildableMeta.registryTypeMapper().supportsDirectHolders(), "Registry type mapper must support direct holders");
final PaperRegistryBuilderFactory<M, A, B> builderFactory = new PaperRegistryBuilderFactory<>(Conversions.global(), buildableMeta.builderFiller(), CraftRegistry.getMinecraftRegistry(buildableMeta.mcKey())::getValue);
value.accept(builderFactory);
return buildableMeta.registryTypeMapper().createBukkit(Holder.direct(builderFactory.requireBuilder().build()));
}
@Override
public Art createPaintingVariant(final Consumer<RegistryBuilderFactory<Art, ? extends PaintingVariantRegistryEntry.Builder>> value) {
return create(Registries.PAINTING_VARIANT, value::accept);
}
}

View File

@@ -0,0 +1,121 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.PaperRegistryBuilder;
import io.papermc.paper.registry.RegistryBuilderFactory;
import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.holder.PaperRegistryHolders;
import io.papermc.paper.registry.holder.RegistryHolder;
import java.util.OptionalInt;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.item.JukeboxSong;
import net.minecraft.world.level.redstone.Redstone;
import org.bukkit.Sound;
import org.checkerframework.checker.index.qual.Positive;
import org.jetbrains.annotations.Range;
import org.jspecify.annotations.Nullable;
import static io.papermc.paper.registry.data.util.Checks.asArgument;
import static io.papermc.paper.registry.data.util.Checks.asArgumentMinExclusive;
import static io.papermc.paper.registry.data.util.Checks.asArgumentRange;
import static io.papermc.paper.registry.data.util.Checks.asConfigured;
public class PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry {
protected final Conversions conversions;
protected @Nullable Holder<SoundEvent> soundEvent;
protected @Nullable Component description;
protected @Nullable Float lengthInSeconds;
protected OptionalInt comparatorOutput = OptionalInt.empty();
public PaperJukeboxSongRegistryEntry(final Conversions conversions, final @Nullable JukeboxSong internal) {
this.conversions = conversions;
if (internal == null) {
return;
}
this.soundEvent = internal.soundEvent();
this.description = internal.description();
this.lengthInSeconds = internal.lengthInSeconds();
this.comparatorOutput = OptionalInt.of(internal.comparatorOutput());
}
@Override
public RegistryHolder<Sound, SoundEventRegistryEntry> soundEvent() {
final Holder<SoundEvent> current = asConfigured(this.soundEvent, "soundEvent");
return PaperRegistryHolders.create(current, e -> new PaperSoundEventRegistryEntry(this.conversions, e));
}
@Override
public net.kyori.adventure.text.Component description() {
return this.conversions.asAdventure(asConfigured(this.description, "description"));
}
@Override
public float lengthInSeconds() {
return asConfigured(this.lengthInSeconds, "lengthInSeconds");
}
@Override
public int comparatorOutput() {
return asConfigured(this.comparatorOutput, "comparatorOutput");
}
public static final class PaperBuilder extends PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry.Builder, PaperRegistryBuilder<JukeboxSong, org.bukkit.JukeboxSong> {
public PaperBuilder(final Conversions conversions, final @Nullable JukeboxSong internal) {
super(conversions, internal);
}
@Override
public JukeboxSongRegistryEntry.Builder soundEvent(final TypedKey<Sound> soundEvent) {
this.soundEvent = this.conversions.getReferenceHolder(PaperRegistries.toNms(asArgument(soundEvent, "soundEvent")));
return this;
}
@Override
public JukeboxSongRegistryEntry.Builder soundEvent(final Consumer<RegistryBuilderFactory<Sound, ? extends SoundEventRegistryEntry.Builder>> soundEvent) {
this.soundEvent = this.conversions.createHolderFromBuilder(Registries.SOUND_EVENT, asArgument(soundEvent, "soundEvent"));
return this;
}
@Override
public Builder soundEvent(final RegistryHolder<Sound, SoundEventRegistryEntry> soundEvent) {
this.soundEvent = PaperRegistryHolders.convert(soundEvent, this.conversions);
return this;
}
@Override
public JukeboxSongRegistryEntry.Builder description(final net.kyori.adventure.text.Component description) {
this.description = this.conversions.asVanilla(asArgument(description, "description"));
return this;
}
@Override
public JukeboxSongRegistryEntry.Builder lengthInSeconds(final @Positive float lengthInSeconds) {
this.lengthInSeconds = asArgumentMinExclusive(lengthInSeconds, "lengthInSeconds", 0);
return this;
}
@Override
public JukeboxSongRegistryEntry.Builder comparatorOutput(final @Range(from = 0, to = 15) int comparatorOutput) {
this.comparatorOutput = OptionalInt.of(asArgumentRange(comparatorOutput, "comparatorOutput", Redstone.SIGNAL_MIN, Redstone.SIGNAL_MAX));
return this;
}
@Override
public JukeboxSong build() {
return new JukeboxSong(
asConfigured(this.soundEvent, "soundEvent"),
asConfigured(this.description, "description"),
this.lengthInSeconds(),
this.comparatorOutput()
);
}
}
}

View File

@@ -0,0 +1,69 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.PaperRegistryBuilder;
import io.papermc.paper.registry.data.util.Conversions;
import java.util.Optional;
import net.kyori.adventure.key.Key;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import org.bukkit.Sound;
import org.jspecify.annotations.Nullable;
import static io.papermc.paper.registry.data.util.Checks.asArgument;
import static io.papermc.paper.registry.data.util.Checks.asConfigured;
/**
* Not actually used for modifying {@link net.minecraft.core.registries.Registries#SOUND_EVENT}
* but for creating direct holders for other registries and direct {@link org.bukkit.craftbukkit.CraftSound}s.
*/
public class PaperSoundEventRegistryEntry implements SoundEventRegistryEntry {
protected final Conversions conversions;
protected @Nullable ResourceLocation location;
protected @Nullable Float fixedRange;
public PaperSoundEventRegistryEntry(final Conversions conversions, final @Nullable SoundEvent soundEvent) {
this.conversions = conversions;
if (soundEvent == null) {
return;
}
this.location = soundEvent.location();
this.fixedRange = soundEvent.fixedRange().orElse(null);
}
@Override
public Key location() {
return PaperAdventure.asAdventure(asConfigured(this.location, "location"));
}
@Override
public @Nullable Float fixedRange() {
return this.fixedRange;
}
public static final class PaperBuilder extends PaperSoundEventRegistryEntry implements SoundEventRegistryEntry.Builder, PaperRegistryBuilder<SoundEvent, Sound> {
public PaperBuilder(final Conversions conversions, final @Nullable SoundEvent soundEvent) {
super(conversions, soundEvent);
}
@Override
public SoundEventRegistryEntry.Builder location(final Key location) {
this.location = PaperAdventure.asVanilla(asArgument(location, "location"));
return this;
}
@Override
public SoundEventRegistryEntry.Builder fixedRange(final @Nullable Float fixedRange) {
this.fixedRange = fixedRange;
return this;
}
@Override
public SoundEvent build() {
return new SoundEvent(asConfigured(this.location, "location"), Optional.ofNullable(this.fixedRange));
}
}
}

View File

@@ -40,6 +40,13 @@ public final class Checks {
return value;
}
public static float asArgumentMinExclusive(final float value, final String field, final float min) {
if (value <= min) {
throw new IllegalArgumentException("argument " + field + " must be (" + min + ",+inf)");
}
return value;
}
private Checks() {
}
}

View File

@@ -4,13 +4,20 @@ import com.google.common.base.Preconditions;
import com.mojang.serialization.JavaOps;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.adventure.WrapperAwareSerializer;
import java.util.Optional;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.PaperRegistryBuilder;
import io.papermc.paper.registry.PaperRegistryBuilderFactory;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import org.bukkit.Keyed;
import org.bukkit.craftbukkit.CraftRegistry;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.Nullable;
@@ -22,15 +29,7 @@ public class Conversions {
if (globalInstance == null) {
final RegistryAccess globalAccess = CraftRegistry.getMinecraftRegistry();
Preconditions.checkState(globalAccess != null, "Global registry access is not available");
globalInstance = new Conversions(new RegistryOps.RegistryInfoLookup() {
@Override
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(final ResourceKey<? extends Registry<? extends T>> registryRef) {
final Registry<T> registry = globalAccess.lookupOrThrow(registryRef);
return Optional.of(
new RegistryOps.RegistryInfo<>(registry, registry, registry.registryLifecycle())
);
}
});
globalInstance = new Conversions(new RegistryOps.HolderLookupAdapter(globalAccess));
}
return globalInstance;
}
@@ -47,6 +46,10 @@ public class Conversions {
return this.lookup;
}
public <M> Holder.Reference<M> getReferenceHolder(final ResourceKey<M> key) {
return this.lookup.lookup(key.registryKey()).orElseThrow().getter().getOrThrow(key);
}
@Contract("null -> null; !null -> !null")
public net.minecraft.network.chat.@Nullable Component asVanilla(final @Nullable Component adventure) {
if (adventure == null) return null;
@@ -70,4 +73,33 @@ public class Conversions {
PaperAdventure.asVanilla(clientTextureAsset.texturePath())
);
}
private static <M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> RegistryEntryMeta.Buildable<M, A, B> getDirectHolderBuildableMeta(final ResourceKey<? extends Registry<M>> registryKey) {
final RegistryEntryMeta.Buildable<M, A, B> buildableMeta = PaperRegistries.getBuildableMeta(registryKey);
Preconditions.checkArgument(buildableMeta.registryTypeMapper().supportsDirectHolders(), "Registry type mapper must support direct holders");
return buildableMeta;
}
public <M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> A createApiInstanceFromBuilder(final ResourceKey<? extends Registry<M>> registryKey, final Consumer<? super PaperRegistryBuilderFactory<M, A, B>> value) {
final RegistryEntryMeta.Buildable<M, A, B> meta = getDirectHolderBuildableMeta(registryKey);
final PaperRegistryBuilderFactory<M, A, B> builderFactory = this.createRegistryBuilderFactory(registryKey, meta);
value.accept(builderFactory);
return meta.registryTypeMapper().createBukkit(Holder.direct(builderFactory.requireBuilder().build()));
}
public <M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> Holder<M> createHolderFromBuilder(final ResourceKey<? extends Registry<M>> registryKey, final Consumer<? super PaperRegistryBuilderFactory<M, A, B>> value) {
final RegistryEntryMeta.Buildable<M, A, B> meta = getDirectHolderBuildableMeta(registryKey);
final PaperRegistryBuilderFactory<M, A, B> builderFactory = this.createRegistryBuilderFactory(registryKey, meta);
value.accept(builderFactory);
return Holder.direct(builderFactory.requireBuilder().build());
}
private <M, A extends Keyed, B extends PaperRegistryBuilder<M, A>> PaperRegistryBuilderFactory<M, A, B> createRegistryBuilderFactory(
final ResourceKey<? extends Registry<M>> registryKey,
final RegistryEntryMeta.Buildable<M, A, B> buildableMeta
) {
final HolderLookup.RegistryLookup<M> lookupForBuilders = this.lookup.lookupForValueCopyViaBuilders().lookupOrThrow(registryKey);
return new PaperRegistryBuilderFactory<>(registryKey, this, buildableMeta.builderFiller(), lookupForBuilders::getValueForCopying);
}
}

View File

@@ -89,7 +89,7 @@ public class RegistryEntryBuilder<M, A extends Keyed> { // TODO remove Keyed
return this.create(filler, WRITABLE);
}
private <B extends PaperRegistryBuilder<M, A>> RegistryEntry<M, A> create(final PaperRegistryBuilder.Filler<M, A, B> filler, final RegistryEntryMeta.RegistryModificationApiSupport support) {
public <B extends PaperRegistryBuilder<M, A>> RegistryEntry<M, A> create(final PaperRegistryBuilder.Filler<M, A, B> filler, final RegistryEntryMeta.RegistryModificationApiSupport support) {
return new RegistryEntryImpl<>(new RegistryEntryMeta.Buildable<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit, this.serializationUpdater, filler, support));
}
}

View File

@@ -7,7 +7,7 @@ import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.WritableCraftRegistry;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.event.RegistryEntryAddEventImpl;
import io.papermc.paper.registry.event.RegistryFreezeEventImpl;
import io.papermc.paper.registry.event.RegistryComposeEventImpl;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import net.minecraft.core.MappedRegistry;
@@ -106,8 +106,8 @@ public sealed interface RegistryEntryMeta<M, A extends Keyed> permits RegistryEn
return new RegistryEntryAddEventImpl<>(key, initialBuilder, this.apiKey(), conversions);
}
public RegistryFreezeEventImpl<A, B> createFreezeEvent(final WritableCraftRegistry<M, A, B> writableRegistry, final Conversions conversions) {
return new RegistryFreezeEventImpl<>(this.apiKey(), writableRegistry.createApiWritableRegistry(conversions), conversions);
public RegistryComposeEventImpl<A, B> createPostLoadEvent(final WritableCraftRegistry<M, A, B> writableRegistry, final Conversions conversions) {
return new RegistryComposeEventImpl<>(this.apiKey(), writableRegistry.createApiWritableRegistry(conversions), conversions);
}
@Override

View File

@@ -12,7 +12,7 @@ import net.minecraft.core.HolderSet;
import net.minecraft.resources.RegistryOps;
import org.bukkit.Keyed;
public record RegistryFreezeEventImpl<T, B extends RegistryBuilder<T>>(
public record RegistryComposeEventImpl<T, B extends RegistryBuilder<T>>(
RegistryKey<T> registryKey,
WritableRegistry<T, B> registry,
Conversions conversions

View File

@@ -18,7 +18,7 @@ public class RegistryEventTypeProviderImpl implements RegistryEventTypeProvider
}
@Override
public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> registryFreeze(final RegistryEventProvider<T, B> type) {
return PaperRegistryListenerManager.INSTANCE.getRegistryFreezeEventType(type);
public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<T, B>> registryCompose(final RegistryEventProvider<T, B> type) {
return PaperRegistryListenerManager.INSTANCE.getRegistryComposeEventType(type);
}
}

View File

@@ -0,0 +1,8 @@
package io.papermc.paper.registry.holder;
import net.minecraft.core.Holder;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
record InlinedRegistryHolderImpl<API, ENTRY, M>(ENTRY entry, Holder.Direct<M> holder) implements RegistryHolder.Inlined<API, ENTRY> {
}

View File

@@ -0,0 +1,26 @@
package io.papermc.paper.registry.holder;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.data.util.Conversions;
import java.util.function.Function;
import net.minecraft.core.Holder;
public final class PaperRegistryHolders {
public static <API, ENTRY, M> RegistryHolder<API, ENTRY> create(final Holder<M> holder, final Function<M, ENTRY> entryCreator) {
return switch (holder) {
case final Holder.Direct<M> direct -> new InlinedRegistryHolderImpl<>(entryCreator.apply(direct.value()), direct);
case final Holder.Reference<M> reference -> new ReferenceRegistryHolderImpl<>(PaperRegistries.fromNms(reference.key()));
default -> throw new IllegalArgumentException("Unsupported holder type: " + holder.getClass().getName());
};
}
public static <API, ENTRY, M> Holder<M> convert(final RegistryHolder<API, ENTRY> holder, final Conversions conversions) {
return switch (holder) {
case final RegistryHolder.Reference<API, ENTRY> ref -> conversions.getReferenceHolder(PaperRegistries.toNms(ref.key()));
case final RegistryHolder.Inlined<API, ENTRY> inlined -> ((InlinedRegistryHolderImpl<API, ENTRY, M>) inlined).holder();
};
}
private PaperRegistryHolders() {}
}

View File

@@ -0,0 +1,8 @@
package io.papermc.paper.registry.holder;
import io.papermc.paper.registry.TypedKey;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
record ReferenceRegistryHolderImpl<API, ENTRY>(TypedKey<API> key) implements RegistryHolder.Reference<API, ENTRY> {
}

View File

@@ -21,7 +21,7 @@ public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
public static final BiMap<FeatureFlag, net.minecraft.world.flag.FeatureFlag> FLAGS = ImmutableBiMap.of(
// Start generate - PaperFeatureFlagProviderImpl#FLAGS
// @GeneratedFrom 1.21.5
// @GeneratedFrom 1.21.6-rc1
FeatureFlag.MINECART_IMPROVEMENTS, FeatureFlags.MINECART_IMPROVEMENTS,
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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