Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: MiniDigger | Martin <admin@minidigger.dev>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com>
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
Nassim Jahnke
2025-04-12 17:26:44 +02:00
parent 0767902699
commit f00727c57e
2092 changed files with 50551 additions and 48729 deletions

View File

@@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.common.list;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.NoSuchElementException;
@@ -21,15 +22,34 @@ public final class IteratorSafeOrderedReferenceSet<E> {
private int iteratorCount;
public IteratorSafeOrderedReferenceSet() {
this(16, 0.75f, 16, 0.2);
this(Object.class);
}
public IteratorSafeOrderedReferenceSet(final Class<? super E> arrComponent) {
this(16, 0.75f, 16, 0.2, arrComponent);
}
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor) {
this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, Object.class);
}
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor, final Class<? super E> arrComponent) {
this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor);
this.indexMap.defaultReturnValue(-1);
this.maxFragFactor = maxFragFactor;
this.listElements = (E[])new Object[arrayCapacity];
this.listElements = (E[])Array.newInstance(arrComponent, arrayCapacity);
}
// includes null (gravestone) elements
public E[] getListRaw() {
return this.listElements;
}
// includes null (gravestone) elements
public int getListSize() {
return this.listSize;
}
/*
@@ -81,7 +101,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
public int createRawIterator() {
++this.iteratorCount;
if (this.indexMap.isEmpty()) {
return -1;
return Integer.MAX_VALUE;
} else {
return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0;
}
@@ -96,7 +116,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
return -1;
return Integer.MAX_VALUE;
}
public void finishRawIterator() {
@@ -205,10 +225,6 @@ public final class IteratorSafeOrderedReferenceSet<E> {
//this.check();
}
public E rawGet(final int index) {
return this.listElements[index];
}
public int size() {
// always returns the correct amount - listSize can be different
return this.indexMap.size();

View File

@@ -1,6 +1,6 @@
package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.concurrentutil.util.IntPairUtil;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
@@ -23,12 +23,16 @@ public final class PositionCountingAreaMap<T> {
return this.positions.size();
}
public boolean hasObjectsNear(final long pos) {
return this.positions.containsKey(pos);
}
public boolean hasObjectsNear(final int toX, final int toZ) {
return this.positions.containsKey(IntPairUtil.key(toX, toZ));
return this.positions.containsKey(CoordinateUtils.getChunkKey(toX, toZ));
}
public int getObjectsNear(final int toX, final int toZ) {
return this.positions.get(IntPairUtil.key(toX, toZ));
return this.positions.get(CoordinateUtils.getChunkKey(toX, toZ));
}
public boolean add(final T parameter, final int toX, final int toZ, final int distance) {
@@ -85,12 +89,12 @@ public final class PositionCountingAreaMap<T> {
@Override
protected void addCallback(final T parameter, final int toX, final int toZ) {
PositionCountingAreaMap.this.positions.addTo(IntPairUtil.key(toX, toZ), 1);
PositionCountingAreaMap.this.positions.addTo(CoordinateUtils.getChunkKey(toX, toZ), 1);
}
@Override
protected void removeCallback(final T parameter, final int toX, final int toZ) {
final long key = IntPairUtil.key(toX, toZ);
final long key = CoordinateUtils.getChunkKey(toX, toZ);
if (PositionCountingAreaMap.this.positions.addTo(key, -1) == 1) {
PositionCountingAreaMap.this.positions.remove(key);
}

View File

@@ -1,7 +1,5 @@
package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.concurrentutil.util.IntegerUtil;
public abstract class SingleUserAreaMap<T> {
public static final int NOT_SET = Integer.MIN_VALUE;
@@ -99,8 +97,8 @@ public abstract class SingleUserAreaMap<T> {
final int dx = toX - fromX;
final int dz = toZ - fromZ;
final int totalX = IntegerUtil.branchlessAbs(fromX - toX);
final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ);
final int totalX = Math.abs(fromX - toX);
final int totalZ = Math.abs(fromZ - toZ);
if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) {
// teleported
@@ -120,7 +118,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) {
// only remove if we're outside the new view distance...
if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) {
if (Math.max(Math.abs(currX - toX), Math.abs(currZ - toZ)) > newViewDistance) {
this.removeCallback(parameter, currX, currZ);
}
}
@@ -136,7 +134,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) {
// only add if we're outside the old view distance...
if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) {
if (Math.max(Math.abs(currX - fromX), Math.abs(currZ - fromZ)) > oldViewDistance) {
this.addCallback(parameter, currX, currZ);
}
}

View File

@@ -5,6 +5,7 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -74,4 +75,6 @@ public interface ChunkSystemHooks {
public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player);
public void updateMaps(final ServerLevel world, final ServerPlayer player);
public long[] getCounterTypesUncached(final TicketType type);
}

View File

@@ -15,6 +15,7 @@ import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
@@ -29,7 +30,7 @@ import java.util.zip.GZIPOutputStream;
/**
* bStats collects some data for plugin authors.
*
* Check out https://bStats.org/ to learn more about bStats!
* Check out https://bstats.org/ to learn more about bStats!
*/
public class Metrics {
@@ -41,7 +42,7 @@ public class Metrics {
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/server-implementation";
private static final String URL = "https://bstats.org/submitData/server-implementation";
// Should failed requests be logged?
private static boolean logFailedRequests = false;
@@ -223,7 +224,7 @@ public class Metrics {
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}

View File

@@ -1,7 +1,6 @@
package com.destroystokyo.paper;
import com.destroystokyo.paper.util.VersionFetcher;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
@@ -15,6 +14,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.StreamSupport;
@@ -87,7 +87,7 @@ public class PaperVersionFetcher implements VersionFetcher {
try {
try (final BufferedReader reader = Resources.asCharSource(
URI.create("https://api.papermc.io/v2/projects/paper/versions/" + build.minecraftVersionId()).toURL(),
Charsets.UTF_8
StandardCharsets.UTF_8
).openBufferedStream()) {
final JsonObject json = new Gson().fromJson(reader, JsonObject.class);
final JsonArray builds = json.getAsJsonArray("builds");
@@ -112,7 +112,7 @@ public class PaperVersionFetcher implements VersionFetcher {
final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.github.com/repos/%s/compare/%s...%s".formatted(repo, branch, hash)).toURL().openConnection();
connection.connect();
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return DISTANCE_UNKNOWN; // Unknown commit
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
final String status = obj.get("status").getAsString();
return switch (status) {

View File

@@ -1,8 +1,9 @@
package com.destroystokyo.paper.entity;
import org.apache.commons.lang.Validate;
import com.google.common.base.Preconditions;
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;
@@ -31,77 +32,78 @@ public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinde
@Override
public void stopPathfinding() {
entity.getNavigation().stop();
this.entity.getNavigation().stop();
}
@Override
public boolean hasPath() {
return entity.getNavigation().getPath() != null && !entity.getNavigation().getPath().isDone();
return this.entity.getNavigation().getPath() != null && !this.entity.getNavigation().getPath().isDone();
}
@Nullable
@Override
public PathResult getCurrentPath() {
Path path = entity.getNavigation().getPath();
Path path = this.entity.getNavigation().getPath();
return path != null && !path.isDone() ? new PaperPathResult(path) : null;
}
@Nullable
@Override
public PathResult findPath(Location loc) {
Validate.notNull(loc, "Location can not be null");
Path path = entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0);
Preconditions.checkArgument(loc != null, "Location can not be null");
Path path = this.entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0);
return path != null ? new PaperPathResult(path) : null;
}
@Nullable
@Override
public PathResult findPath(LivingEntity target) {
Validate.notNull(target, "Target can not be null");
Path path = entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0);
Preconditions.checkArgument(target != null, "Target can not be null");
Path path = this.entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0);
return path != null ? new PaperPathResult(path) : null;
}
@Override
public boolean moveTo(@Nonnull PathResult path, double speed) {
Validate.notNull(path, "PathResult can not be null");
Preconditions.checkArgument(path != null, "PathResult can not be null");
Path pathEntity = ((PaperPathResult) path).path;
return entity.getNavigation().moveTo(pathEntity, speed);
return this.entity.getNavigation().moveTo(pathEntity, speed);
}
@Override
public boolean canOpenDoors() {
return entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors();
return this.entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors();
}
@Override
public void setCanOpenDoors(boolean canOpenDoors) {
entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors);
this.entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors);
}
@Override
public boolean canPassDoors() {
return entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors();
return this.entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors();
}
@Override
public void setCanPassDoors(boolean canPassDoors) {
entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors);
this.entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors);
}
@Override
public boolean canFloat() {
return entity.getNavigation().pathFinder.nodeEvaluator.canFloat();
return this.entity.getNavigation().pathFinder.nodeEvaluator.canFloat();
}
@Override
public void setCanFloat(boolean canFloat) {
entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat);
this.entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat);
}
public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult {
private final Path path;
PaperPathResult(Path path) {
this.path = path;
}
@@ -109,40 +111,36 @@ public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinde
@Nullable
@Override
public Location getFinalPoint() {
Node point = path.getEndNode();
return point != null ? toLoc(point) : null;
Node point = this.path.getEndNode();
return point != null ? CraftLocation.toBukkit(point, PaperPathfinder.this.entity.level()) : null;
}
@Override
public boolean canReachFinalPoint() {
return path.canReach();
return this.path.canReach();
}
@Override
public List<Location> getPoints() {
List<Location> points = new ArrayList<>();
for (Node point : path.nodes) {
points.add(toLoc(point));
for (Node point : this.path.nodes) {
points.add(CraftLocation.toBukkit(point, PaperPathfinder.this.entity.level()));
}
return points;
}
@Override
public int getNextPointIndex() {
return path.getNextNodeIndex();
return this.path.getNextNodeIndex();
}
@Nullable
@Override
public Location getNextPoint() {
if (path.isDone()) {
if (this.path.isDone()) {
return null;
}
return toLoc(path.nodes.get(path.getNextNodeIndex()));
return CraftLocation.toBukkit(this.path.nodes.get(this.path.getNextNodeIndex()), PaperPathfinder.this.entity.level());
}
}
private Location toLoc(Node point) {
return new Location(entity.level().getWorld(), point.x, point.y, point.z);
}
}

View File

@@ -3,6 +3,7 @@ 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 io.papermc.paper.entity.SchoolableFish;
import io.papermc.paper.util.ObfHelper;
import java.lang.reflect.Constructor;
import java.util.EnumSet;
@@ -10,120 +11,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.minecraft.world.entity.FlyingMob;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ambient.AmbientCreature;
import net.minecraft.world.entity.animal.AbstractFish;
import net.minecraft.world.entity.animal.AbstractGolem;
import net.minecraft.world.entity.animal.AbstractSchoolingFish;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.animal.Pufferfish;
import net.minecraft.world.entity.animal.ShoulderRidingEntity;
import net.minecraft.world.entity.animal.SnowGolem;
import net.minecraft.world.entity.animal.WaterAnimal;
import net.minecraft.world.entity.animal.camel.Camel;
import net.minecraft.world.entity.animal.horse.AbstractChestedHorse;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.entity.monster.AbstractIllager;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.entity.monster.PatrollingMonster;
import net.minecraft.world.entity.monster.RangedAttackMob;
import net.minecraft.world.entity.monster.SpellcasterIllager;
import net.minecraft.world.entity.monster.ZombifiedPiglin;
import net.minecraft.world.entity.monster.breeze.Breeze;
import net.minecraft.world.entity.monster.piglin.AbstractPiglin;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.AbstractSkeleton;
import org.bukkit.entity.AbstractVillager;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Bat;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Blaze;
import org.bukkit.entity.Cat;
import org.bukkit.entity.CaveSpider;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cod;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Donkey;
import org.bukkit.entity.Drowned;
import org.bukkit.entity.ElderGuardian;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Endermite;
import org.bukkit.entity.Evoker;
import org.bukkit.entity.Fish;
import org.bukkit.entity.Flying;
import org.bukkit.entity.Fox;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.Giant;
import org.bukkit.entity.Golem;
import org.bukkit.entity.Guardian;
import org.bukkit.entity.Hoglin;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Husk;
import org.bukkit.entity.Illager;
import org.bukkit.entity.Illusioner;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.Llama;
import org.bukkit.entity.MagmaCube;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Mule;
import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Panda;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Phantom;
import org.bukkit.entity.Pig;
import org.bukkit.entity.PigZombie;
import org.bukkit.entity.Piglin;
import org.bukkit.entity.PiglinAbstract;
import org.bukkit.entity.PiglinBrute;
import org.bukkit.entity.Pillager;
import org.bukkit.entity.PolarBear;
import org.bukkit.entity.PufferFish;
import org.bukkit.entity.Rabbit;
import org.bukkit.entity.Raider;
import org.bukkit.entity.Ravager;
import org.bukkit.entity.Salmon;
import org.bukkit.entity.Sheep;
import org.bukkit.entity.Shulker;
import org.bukkit.entity.Silverfish;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.SkeletonHorse;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Snowman;
import org.bukkit.entity.Spellcaster;
import org.bukkit.entity.Spider;
import org.bukkit.entity.Squid;
import org.bukkit.entity.Stray;
import org.bukkit.entity.Strider;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.TraderLlama;
import org.bukkit.entity.TropicalFish;
import org.bukkit.entity.Turtle;
import org.bukkit.entity.Vex;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Vindicator;
import org.bukkit.entity.WanderingTrader;
import org.bukkit.entity.WaterMob;
import org.bukkit.entity.Witch;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkeleton;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.Zoglin;
import org.bukkit.entity.Zombie;
import org.bukkit.entity.ZombieHorse;
import org.bukkit.entity.ZombieVillager;
import org.bukkit.entity.*;
public class MobGoalHelper {
@@ -143,10 +34,13 @@ public class MobGoalHelper {
ignored.add("selector_2");
ignored.add("wrapped");
//<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(AmbientCreature.class, Ambient.class);
bukkitMap.put(Animal.class, Animals.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);
@@ -155,56 +49,56 @@ public class MobGoalHelper {
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(PathfinderMob.class, Creature.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(EnderMan.class, Enderman.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(AbstractFish.class, Fish.class);
bukkitMap.put(AbstractSchoolingFish.class, io.papermc.paper.entity.SchoolableFish.class);
bukkitMap.put(FlyingMob.class, Flying.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(AbstractGolem.class, Golem.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(AbstractChestedHorse.class, ChestedHorse.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(Camel.class, org.bukkit.entity.Camel.class);
bukkitMap.put(AbstractIllager.class, Illager.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(SpellcasterIllager.class, Spellcaster.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(PatrollingMonster.class, Raider.class); // close enough
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(ShoulderRidingEntity.class, Parrot.class); // close enough
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(ZombifiedPiglin.class, PigZombie.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(Pufferfish.class, PufferFish.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.class, Sheep.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);
@@ -212,10 +106,10 @@ public class MobGoalHelper {
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(SnowGolem.class, Snowman.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(TamableAnimal.class, Tameable.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);
@@ -223,32 +117,35 @@ public class MobGoalHelper {
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(WaterAnimal.class, WaterMob.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(WitherBoss.class, Wither.class);
bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.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(AbstractPiglin.class, PiglinAbstract.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, org.bukkit.entity.GlowSquid.class);
bukkitMap.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, org.bukkit.entity.Axolotl.class);
bukkitMap.put(net.minecraft.world.entity.animal.goat.Goat.class, org.bukkit.entity.Goat.class);
bukkitMap.put(net.minecraft.world.entity.animal.frog.Frog.class, org.bukkit.entity.Frog.class);
bukkitMap.put(net.minecraft.world.entity.animal.frog.Tadpole.class, org.bukkit.entity.Tadpole.class);
bukkitMap.put(net.minecraft.world.entity.monster.warden.Warden.class, org.bukkit.entity.Warden.class);
bukkitMap.put(net.minecraft.world.entity.animal.allay.Allay.class, org.bukkit.entity.Allay.class);
bukkitMap.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, org.bukkit.entity.Sniffer.class);
bukkitMap.put(Breeze.class, org.bukkit.entity.Breeze.class);
bukkitMap.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, org.bukkit.entity.Armadillo.class);
bukkitMap.put(net.minecraft.world.entity.monster.Bogged.class, org.bukkit.entity.Bogged.class);
bukkitMap.put(net.minecraft.world.entity.monster.creaking.Creaking.class, org.bukkit.entity.Creaking.class);
bukkitMap.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, org.bukkit.entity.Squid.class); // close enough
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
//</editor-fold>
}
public static String getUsableName(Class<?> clazz) {
@@ -267,7 +164,6 @@ public class MobGoalHelper {
name = cut;
}
}
name = name.replace("PathfinderGoal", "");
name = name.replace("TargetGoal", "");
name = name.replace("Goal", "");
StringBuilder sb = new StringBuilder();
@@ -365,7 +261,7 @@ public class MobGoalHelper {
}
}
}
throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient?
throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return Mob?
});
}

View File

@@ -7,14 +7,14 @@ import org.bukkit.entity.Mob;
/**
* Wraps vanilla in api
*/
public class PaperVanillaGoal<T extends Mob> implements VanillaGoal<T> {
public class PaperGoal<T extends Mob> implements com.destroystokyo.paper.entity.ai.Goal<T> {
private final Goal handle;
private final GoalKey<T> key;
private final EnumSet<GoalType> types;
public PaperVanillaGoal(Goal handle) {
public PaperGoal(Goal handle) {
this.handle = handle;
this.key = MobGoalHelper.getKey(handle.getClass());
this.types = MobGoalHelper.vanillaToPaper(handle);

View File

@@ -20,8 +20,8 @@ public class PaperMobGoals implements MobGoals {
CraftMob craftMob = (CraftMob) mob;
net.minecraft.world.entity.ai.goal.Goal mojangGoal;
if (goal instanceof PaperVanillaGoal vanillaGoal) {
mojangGoal = vanillaGoal.getHandle();
if (goal instanceof PaperGoal<?> paperGoal) {
mojangGoal = paperGoal.getHandle();
} else {
mojangGoal = new PaperCustomGoal<>(goal);
}
@@ -34,8 +34,8 @@ public class PaperMobGoals implements MobGoals {
CraftMob craftMob = (CraftMob) mob;
if (goal instanceof PaperCustomGoal) {
getHandle(craftMob, goal.getTypes()).removeGoal((net.minecraft.world.entity.ai.goal.Goal) goal);
} else if (goal instanceof PaperVanillaGoal) {
getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal<?>) goal).getHandle());
} else if (goal instanceof PaperGoal) {
getHandle(craftMob, goal.getTypes()).removeGoal(((PaperGoal<?>) goal).getHandle());
} else {
List<net.minecraft.world.entity.ai.goal.Goal> toRemove = new LinkedList<>();
for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).getAvailableGoals()) {
@@ -127,7 +127,7 @@ public class PaperMobGoals implements MobGoals {
//noinspection unchecked
goals.add(((PaperCustomGoal<T>) item.getGoal()).getHandle());
} else {
goals.add(item.getGoal().asPaperVanillaGoal());
goals.add(item.getGoal().asPaperGoal());
}
}
return goals;
@@ -150,7 +150,7 @@ public class PaperMobGoals implements MobGoals {
//noinspection unchecked
goals.add(((PaperCustomGoal<T>) item.getGoal()).getHandle());
} else {
goals.add(item.getGoal().asPaperVanillaGoal());
goals.add(item.getGoal().asPaperGoal());
}
}
}
@@ -178,7 +178,7 @@ public class PaperMobGoals implements MobGoals {
//noinspection unchecked
goals.add(((PaperCustomGoal<T>) item.getGoal()).getHandle());
} else {
goals.add(item.getGoal().asPaperVanillaGoal());
goals.add(item.getGoal().asPaperGoal());
}
});
return goals;
@@ -201,7 +201,7 @@ public class PaperMobGoals implements MobGoals {
//noinspection unchecked
goals.add(((PaperCustomGoal<T>) item.getGoal()).getHandle());
} else {
goals.add(item.getGoal().asPaperVanillaGoal());
goals.add(item.getGoal().asPaperGoal());
}
});
}

View File

@@ -5,12 +5,13 @@ import io.papermc.paper.configuration.type.DurationOrDisabled;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import net.minecraft.core.UUIDUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.RandomizableContainer;
import net.minecraft.world.entity.vehicle.ContainerEntity;
import org.bukkit.entity.Player;
@@ -164,30 +165,25 @@ public class PaperLootableInventoryData {
private static final String LOOTED_PLAYERS = "lootedPlayers";
public void loadNbt(final CompoundTag base) {
if (!base.contains(ROOT, Tag.TAG_COMPOUND)) {
final Optional<CompoundTag> compOpt = base.getCompound(ROOT);
if (compOpt.isEmpty()) {
return;
}
final CompoundTag comp = base.getCompound(ROOT);
if (comp.contains(LAST_FILL)) {
this.lastFill = comp.getLong(LAST_FILL);
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());
}
if (comp.contains(NEXT_REFILL)) {
this.nextRefill = comp.getLong(NEXT_REFILL);
}
if (comp.contains(NUM_REFILLS)) {
this.numRefills = comp.getInt(NUM_REFILLS);
}
if (comp.contains(LOOTED_PLAYERS, Tag.TAG_LIST)) {
final ListTag list = comp.getList(LOOTED_PLAYERS, Tag.TAG_COMPOUND);
final int size = list.size();
if (size > 0) {
this.lootedPlayers = new HashMap<>(list.size());
}
for (int i = 0; i < size; i++) {
final CompoundTag cmp = list.getCompound(i);
this.lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time"));
}
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));
});
});
}
}
@@ -206,7 +202,7 @@ public class PaperLootableInventoryData {
final ListTag list = new ListTag();
for (final Map.Entry<UUID, Long> entry : this.lootedPlayers.entrySet()) {
final CompoundTag cmp = new CompoundTag();
cmp.putUUID("UUID", entry.getKey());
cmp.store("UUID", UUIDUtil.CODEC, entry.getKey());
cmp.putLong("Time", entry.getValue());
list.add(cmp);
}

View File

@@ -3,7 +3,6 @@ package com.destroystokyo.paper.profile;
import com.google.common.base.Preconditions;
import com.mojang.authlib.yggdrasil.ProfileResult;
import io.papermc.paper.configuration.GlobalConfiguration;
import com.google.common.base.Charsets;
import com.google.common.collect.Iterables;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
@@ -14,7 +13,6 @@ import net.minecraft.server.players.GameProfileCache;
import net.minecraft.util.StringUtil;
import net.minecraft.world.item.component.ResolvableProfile;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.craftbukkit.configuration.ConfigSerializationUtil;
import org.bukkit.craftbukkit.entity.CraftPlayer;
@@ -25,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@@ -47,7 +46,7 @@ public class CraftPlayerProfile implements PlayerProfile, SharedPlayerProfile {
}
public CraftPlayerProfile(GameProfile profile) {
Validate.notNull(profile, "GameProfile cannot be null!");
Preconditions.checkArgument(profile != null, "GameProfile cannot be null!");
this.profile = profile;
}
@@ -222,7 +221,7 @@ public class CraftPlayerProfile implements PlayerProfile, SharedPlayerProfile {
profile = lookupUUID ? userCache.get(name).orElse(null) : userCache.getProfileIfCached(name);
} else {
// Make an OfflinePlayer using an offline mode UUID since the name has no profile
profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)), name);
}
if (profile != null) {
// if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't

View File

@@ -30,7 +30,7 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi
return result;
}
@Override @io.papermc.paper.annotation.DoNotUse @Deprecated
@Override @Deprecated
public @Nullable ProfileResult fetchProfile(final UUID profileId, final boolean requireSecure) {
return super.fetchProfile(profileId, requireSecure);
}

View File

@@ -1,5 +1,7 @@
package io.papermc.paper;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.craftbukkit.damage.CraftDamageEffect;
import org.bukkit.damage.DamageEffect;
import org.jspecify.annotations.NullMarked;
@@ -12,4 +14,12 @@ public class PaperServerInternalAPIBridge implements InternalAPIBridge {
public DamageEffect getDamageEffect(final String key) {
return CraftDamageEffect.getById(key);
}
@Override
public Biome constructLegacyCustomBiome() {
class Holder {
static final Biome LEGACY_CUSTOM = new CraftBiome.LegacyCustomBiomeImpl();
}
return Holder.LEGACY_CUSTOM;
}
}

View File

@@ -51,7 +51,7 @@ public record PaperAdvancementDisplay(DisplayInfo handle) implements Advancement
@Override
public @Nullable NamespacedKey backgroundPath() {
return this.handle.getBackground().map(CraftNamespacedKey::fromMinecraft).orElse(null);
return this.handle.getBackground().map(asset -> CraftNamespacedKey.fromMinecraft(asset.id())).orElse(null);
}
@Override

View File

@@ -1,24 +1,18 @@
package io.papermc.paper.adventure;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Either;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.Component;
@@ -40,14 +34,9 @@ import net.kyori.adventure.text.format.ShadowColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.minecraft.commands.arguments.selector.SelectorPattern;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.TagParser;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.chat.contents.KeybindContents;
@@ -55,7 +44,6 @@ import net.minecraft.network.chat.contents.ScoreContents;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.RegistryOps;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.Item;
@@ -76,7 +64,7 @@ import static net.kyori.adventure.text.TranslationArgument.numeric;
@DefaultQualifier(NonNull.class)
public final class AdventureCodecs {
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
public static final StreamCodec<RegistryFriendlyByteBuf, Component> STREAM_COMPONENT_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(COMPONENT_CODEC);
static final Codec<ShadowColor> SHADOW_COLOR_CODEC = ExtraCodecs.ARGB_COLOR_CODEC.xmap(ShadowColor::shadowColor, ShadowColor::value);
@@ -101,102 +89,92 @@ public final class AdventureCodecs {
return Key.parseable(s) ? DataResult.success(Key.key(s)) : DataResult.error(() -> "Cannot convert " + s + " to adventure Key");
}, Key::asString);
static final Codec<ClickEvent.Action> CLICK_EVENT_ACTION_CODEC = Codec.STRING.comapFlatMap(s -> {
final ClickEvent.@Nullable Action value = ClickEvent.Action.NAMES.value(s);
return value != null ? DataResult.success(value) : DataResult.error(() -> "Cannot convert " + s + " to adventure ClickEvent$Action");
}, ClickEvent.Action.NAMES::keyOrThrow);
static final Codec<ClickEvent> CLICK_EVENT_CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(
CLICK_EVENT_ACTION_CODEC.fieldOf("action").forGetter(ClickEvent::action),
Codec.STRING.fieldOf("value").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::clickEvent);
/*
* Click
*/
static final MapCodec<ClickEvent> OPEN_URL_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.UNTRUSTED_URI.fieldOf("url").forGetter(a -> URI.create(!a.value().contains("://") ? "https://" + a.value() : a.value()))
).apply(instance, (url) -> ClickEvent.openUrl(url.toString())));
static final MapCodec<ClickEvent> OPEN_FILE_CODEC = mapCodec((instance) -> instance.group(
Codec.STRING.fieldOf("path").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::openFile));
static final MapCodec<ClickEvent> RUN_COMMAND_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::runCommand));
static final MapCodec<ClickEvent> SUGGEST_COMMAND_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::suggestCommand));
static final MapCodec<ClickEvent> CHANGE_PAGE_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.POSITIVE_INT.fieldOf("page").forGetter(a -> Integer.parseInt(a.value()))
).apply(instance, ClickEvent::changePage));
static final MapCodec<ClickEvent> COPY_TO_CLIPBOARD_CODEC = mapCodec((instance) -> instance.group(
Codec.STRING.fieldOf("value").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::copyToClipboard));
static final ClickEventType OPEN_URL_CLICK_EVENT_TYPE = new ClickEventType(OPEN_URL_CODEC, "open_url");
static final ClickEventType OPEN_FILE_CLICK_EVENT_TYPE = new ClickEventType(OPEN_FILE_CODEC, "open_file");
static final ClickEventType RUN_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(RUN_COMMAND_CODEC, "run_command");
static final ClickEventType SUGGEST_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(SUGGEST_COMMAND_CODEC, "suggest_command");
static final ClickEventType CHANGE_PAGE_CLICK_EVENT_TYPE = new ClickEventType(CHANGE_PAGE_CODEC, "change_page");
static final ClickEventType COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE = new ClickEventType(COPY_TO_CLIPBOARD_CODEC, "copy_to_clipboard");
static final Codec<ClickEventType> CLICK_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new ClickEventType[]{OPEN_URL_CLICK_EVENT_TYPE, OPEN_FILE_CLICK_EVENT_TYPE, RUN_COMMAND_CLICK_EVENT_TYPE, SUGGEST_COMMAND_CLICK_EVENT_TYPE, CHANGE_PAGE_CLICK_EVENT_TYPE, COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE});
record ClickEventType(MapCodec<ClickEvent> codec, String id) implements StringRepresentable {
@Override
public String getSerializedName() {
return this.id;
}
}
private static final Function<ClickEvent, ClickEventType> GET_CLICK_EVENT_TYPE = he -> {
if (he.action() == ClickEvent.Action.OPEN_URL) {
return OPEN_URL_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.OPEN_FILE) {
return OPEN_FILE_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.RUN_COMMAND) {
return RUN_COMMAND_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.SUGGEST_COMMAND) {
return SUGGEST_COMMAND_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.CHANGE_PAGE) {
return CHANGE_PAGE_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.COPY_TO_CLIPBOARD) {
return COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE;
} else {
throw new IllegalStateException();
}
};
static final Codec<ClickEvent> CLICK_EVENT_CODEC = CLICK_EVENT_TYPE_CODEC.dispatch("action", GET_CLICK_EVENT_TYPE, ClickEventType::codec);
/*
* HOVER
*/
static final MapCodec<HoverEvent<Component>> SHOW_TEXT_CODEC = mapCodec((instance) -> instance.group(
COMPONENT_CODEC.fieldOf("value").forGetter(HoverEvent::value)
).apply(instance, HoverEvent::showText));
static final MapCodec<HoverEvent<HoverEvent.ShowEntity>> SHOW_ENTITY_CODEC = mapCodec((instance) -> instance.group(
KEY_CODEC.fieldOf("id").forGetter(a -> a.value().type()),
UUIDUtil.LENIENT_CODEC.fieldOf("uuid").forGetter(a -> a.value().id()),
COMPONENT_CODEC.lenientOptionalFieldOf("name").forGetter(a -> Optional.ofNullable(a.value().name()))
).apply(instance, (key, uuid, component) -> HoverEvent.showEntity(key, uuid, component.orElse(null))));
static final MapCodec<HoverEvent<HoverEvent.ShowItem>> SHOW_ITEM_CODEC = net.minecraft.network.chat.HoverEvent.ShowItem.CODEC.xmap(internal -> {
@Subst("key") final String typeKey = internal.item().getItemHolder().unwrapKey().orElseThrow().location().toString();
return HoverEvent.showItem(Key.key(typeKey), internal.item().getCount(), PaperAdventure.asAdventure(internal.item().getComponentsPatch()));
}, adventure -> {
final Item itemType = BuiltInRegistries.ITEM.getValue(PaperAdventure.asVanilla(adventure.value().item()));
final Map<Key, DataComponentValue> dataComponentsMap = adventure.value().dataComponents();
final ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), adventure.value().count(), PaperAdventure.asVanilla(dataComponentsMap));
return new net.minecraft.network.chat.HoverEvent.ShowItem(stack);
});
static Codec<HoverEvent.ShowEntity> showEntityCodec(final Codec<Component> componentCodec) {
return RecordCodecBuilder.create((instance) -> {
return instance.group(
KEY_CODEC.fieldOf("type").forGetter(HoverEvent.ShowEntity::type),
UUIDUtil.LENIENT_CODEC.fieldOf("id").forGetter(HoverEvent.ShowEntity::id),
componentCodec.lenientOptionalFieldOf("name").forGetter(he -> Optional.ofNullable(he.name()))
).apply(instance, (key, uuid, component) -> {
return HoverEvent.ShowEntity.showEntity(key, uuid, component.orElse(null));
});
});
}
static final HoverEventType<HoverEvent.ShowEntity> SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ENTITY_CODEC, "show_entity");
static final HoverEventType<HoverEvent.ShowItem> SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ITEM_CODEC, "show_item");
static final HoverEventType<Component> SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_TEXT_CODEC, "show_text");
static final Codec<HoverEventType<?>> HOVER_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new HoverEventType<?>[]{SHOW_ENTITY_HOVER_EVENT_TYPE, SHOW_ITEM_HOVER_EVENT_TYPE, SHOW_TEXT_HOVER_EVENT_TYPE});
static Codec<HoverEvent.ShowItem> showItemCodec(final Codec<Component> componentCodec) {
return net.minecraft.network.chat.HoverEvent.ItemStackInfo.CODEC.xmap(isi -> {
@Subst("key") final String typeKey = isi.item.unwrapKey().orElseThrow().location().toString();
return HoverEvent.ShowItem.showItem(Key.key(typeKey), isi.count, PaperAdventure.asAdventure(isi.getItemStack().getComponentsPatch()));
}, si -> {
final Item itemType = BuiltInRegistries.ITEM.getValue(PaperAdventure.asVanilla(si.item()));
final Map<Key, DataComponentValue> dataComponentsMap = si.dataComponents();
final ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), PaperAdventure.asVanilla(dataComponentsMap));
return new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack);
});
}
static final HoverEventType<HoverEvent.ShowEntity> SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showEntityCodec, HoverEvent.Action.SHOW_ENTITY, "show_entity", AdventureCodecs::legacyDeserializeEntity);
static final HoverEventType<HoverEvent.ShowItem> SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showItemCodec, HoverEvent.Action.SHOW_ITEM, "show_item", AdventureCodecs::legacyDeserializeItem);
static final HoverEventType<Component> SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(identity(), HoverEvent.Action.SHOW_TEXT, "show_text", (component, registryOps, codec) -> DataResult.success(component));
static final Codec<HoverEventType<?>> HOVER_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new HoverEventType<?>[]{ SHOW_ENTITY_HOVER_EVENT_TYPE, SHOW_ITEM_HOVER_EVENT_TYPE, SHOW_TEXT_HOVER_EVENT_TYPE });
static DataResult<HoverEvent.ShowEntity> legacyDeserializeEntity(final Component component, final @Nullable RegistryOps<?> ops, final Codec<Component> componentCodec) {
try {
final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component));
final DynamicOps<JsonElement> dynamicOps = ops != null ? ops.withParent(JsonOps.INSTANCE) : JsonOps.INSTANCE;
final DataResult<Component> entityNameResult = componentCodec.parse(dynamicOps, JsonParser.parseString(tag.getString("name")));
@Subst("key") final String keyString = tag.getString("type");
final UUID entityUUID = UUID.fromString(tag.getString("id"));
return entityNameResult.map(name -> HoverEvent.ShowEntity.showEntity(Key.key(keyString), entityUUID, name));
} catch (final Exception ex) {
return DataResult.error(() -> "Failed to parse tooltip: " + ex.getMessage());
}
}
static DataResult<HoverEvent.ShowItem> legacyDeserializeItem(final Component component, final @Nullable RegistryOps<?> ops, final Codec<Component> componentCodec) {
try {
final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component));
final DynamicOps<Tag> dynamicOps = ops != null ? ops.withParent(NbtOps.INSTANCE) : NbtOps.INSTANCE;
final DataResult<ItemStack> stackResult = ItemStack.CODEC.parse(dynamicOps, tag);
return stackResult.map(stack -> {
@Subst("key:value") final String location = stack.getItemHolder().unwrapKey().orElseThrow().location().toString();
return HoverEvent.ShowItem.showItem(Key.key(location), stack.getCount(), PaperAdventure.asAdventure(stack.getComponentsPatch()));
});
} catch (final CommandSyntaxException ex) {
return DataResult.error(() -> "Failed to parse item tag: " + ex.getMessage());
}
}
@FunctionalInterface
interface LegacyDeserializer<T> {
DataResult<T> apply(Component component, @Nullable RegistryOps<?> ops, Codec<Component> componentCodec);
}
record HoverEventType<V>(Function<Codec<Component>, MapCodec<HoverEvent<V>>> codec, String id, Function<Codec<Component>, MapCodec<HoverEvent<V>>> legacyCodec) implements StringRepresentable {
HoverEventType(final Function<Codec<Component>, Codec<V>> contentCodec, final HoverEvent.Action<V> action, final String id, final LegacyDeserializer<V> legacyDeserializer) {
this(cc -> contentCodec.apply(cc).xmap(v -> HoverEvent.hoverEvent(action, v), HoverEvent::value).fieldOf("contents"),
id,
codec -> (new Codec<HoverEvent<V>>() {
public <D> DataResult<Pair<HoverEvent<V>, D>> decode(final DynamicOps<D> dynamicOps, final D object) {
return codec.decode(dynamicOps, object).flatMap(pair -> {
final DataResult<V> dataResult;
if (dynamicOps instanceof final RegistryOps<D> registryOps) {
dataResult = legacyDeserializer.apply(pair.getFirst(), registryOps, codec);
} else {
dataResult = legacyDeserializer.apply(pair.getFirst(), null, codec);
}
return dataResult.map(value -> Pair.of(HoverEvent.hoverEvent(action, value), pair.getSecond()));
});
}
public <D> DataResult<D> encode(final HoverEvent<V> hoverEvent, final DynamicOps<D> dynamicOps, final D object) {
return DataResult.error(() -> "Can't encode in legacy format");
}
}).fieldOf("value")
);
}
record HoverEventType<V>(MapCodec<HoverEvent<V>> codec, String id) implements StringRepresentable {
@Override
public String getSerializedName() {
return this.id;
@@ -214,11 +192,12 @@ public final class AdventureCodecs {
throw new IllegalStateException();
}
};
static final Codec<HoverEvent<?>> HOVER_EVENT_CODEC = Codec.withAlternative(
HOVER_EVENT_TYPE_CODEC.<HoverEvent<?>>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.codec.apply(COMPONENT_CODEC)).codec(),
HOVER_EVENT_TYPE_CODEC.<HoverEvent<?>>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.legacyCodec.apply(COMPONENT_CODEC)).codec()
);
static final Codec<HoverEvent<?>> HOVER_EVENT_CODEC = HOVER_EVENT_TYPE_CODEC.dispatch("action", GET_HOVER_EVENT_TYPE, HoverEventType::codec);
/*
* Style
*/
public static final MapCodec<Style> STYLE_MAP_CODEC = mapCodec((instance) -> {
return instance.group(
TEXT_COLOR_CODEC.optionalFieldOf("color").forGetter(nullableGetter(Style::color)),
@@ -228,8 +207,8 @@ public final class AdventureCodecs {
Codec.BOOL.optionalFieldOf("underlined").forGetter(decorationGetter(TextDecoration.UNDERLINED)),
Codec.BOOL.optionalFieldOf("strikethrough").forGetter(decorationGetter(TextDecoration.STRIKETHROUGH)),
Codec.BOOL.optionalFieldOf("obfuscated").forGetter(decorationGetter(TextDecoration.OBFUSCATED)),
CLICK_EVENT_CODEC.optionalFieldOf("clickEvent").forGetter(nullableGetter(Style::clickEvent)),
HOVER_EVENT_CODEC.optionalFieldOf("hoverEvent").forGetter(nullableGetter(Style::hoverEvent)),
CLICK_EVENT_CODEC.optionalFieldOf("click_event").forGetter(nullableGetter(Style::clickEvent)),
HOVER_EVENT_CODEC.optionalFieldOf("hover_event").forGetter(nullableGetter(Style::hoverEvent)),
Codec.STRING.optionalFieldOf("insertion").forGetter(nullableGetter(Style::insertion)),
KEY_CODEC.optionalFieldOf("font").forGetter(nullableGetter(Style::font))
).apply(instance, (textColor, shadowColor, bold, italic, underlined, strikethrough, obfuscated, clickEvent, hoverEvent, insertion, font) -> {
@@ -248,6 +227,10 @@ public final class AdventureCodecs {
});
});
});
/*
* Misc
*/
static Consumer<Boolean> styleBooleanConsumer(final Style.Builder builder, final TextDecoration decoration) {
return b -> builder.decoration(decoration, b);
}

View File

@@ -81,34 +81,34 @@ public final class ChatProcessor {
final boolean listenersOnSyncEvent = canYouHearMe(PlayerChatEvent.getHandlerList());
if (listenersOnAsyncEvent || listenersOnSyncEvent) {
final CraftPlayer player = this.player.getBukkitEntity();
final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.craftbukkit$originalMessage, new LazyPlayerSet(this.server));
this.post(ae);
final AsyncPlayerChatEvent asyncChatEvent = new AsyncPlayerChatEvent(this.async, player, this.craftbukkit$originalMessage, new LazyPlayerSet(this.server));
this.post(asyncChatEvent);
if (listenersOnSyncEvent) {
final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients());
se.setCancelled(ae.isCancelled()); // propagate cancelled state
this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
final PlayerChatEvent chatEvent = new PlayerChatEvent(player, asyncChatEvent.getMessage(), asyncChatEvent.getFormat(), asyncChatEvent.getRecipients());
chatEvent.setCancelled(asyncChatEvent.isCancelled()); // propagate cancelled state
this.queueIfAsyncOrRunImmediately(new Waitable<>() {
@Override
protected Void evaluate() {
ChatProcessor.this.post(se);
ChatProcessor.this.post(chatEvent);
return null;
}
});
this.readLegacyModifications(se.getMessage(), se.getFormat(), se.getPlayer());
this.readLegacyModifications(chatEvent.getMessage(), chatEvent.getFormat(), chatEvent.getPlayer());
this.processModern(
this.modernRenderer(se.getFormat()),
this.viewersFromLegacy(se.getRecipients()),
this.modernMessage(se.getMessage()),
se.getPlayer(),
se.isCancelled()
this.modernRenderer(chatEvent.getFormat()),
this.viewersFromLegacy(chatEvent.getRecipients()),
this.modernMessage(chatEvent.getMessage()),
chatEvent.getPlayer(),
chatEvent.isCancelled()
);
} else {
this.readLegacyModifications(ae.getMessage(), ae.getFormat(), ae.getPlayer());
this.readLegacyModifications(asyncChatEvent.getMessage(), asyncChatEvent.getFormat(), asyncChatEvent.getPlayer());
this.processModern(
this.modernRenderer(ae.getFormat()),
this.viewersFromLegacy(ae.getRecipients()),
this.modernMessage(ae.getMessage()),
ae.getPlayer(),
ae.isCancelled()
this.modernRenderer(asyncChatEvent.getFormat()),
this.viewersFromLegacy(asyncChatEvent.getRecipients()),
this.modernMessage(asyncChatEvent.getMessage()),
asyncChatEvent.getPlayer(),
asyncChatEvent.isCancelled()
);
}
} else {
@@ -151,14 +151,14 @@ public final class ChatProcessor {
this.post(ae);
final boolean listenersOnSyncEvent = canYouHearMe(ChatEvent.getHandlerList());
if (listenersOnSyncEvent) {
this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
this.queueIfAsyncOrRunImmediately(new Waitable<>() {
@Override
protected Void evaluate() {
final ChatEvent se = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.paper$originalMessage/*, ae.usePreviewComponent()*/, signedMessage);
se.setCancelled(ae.isCancelled()); // propagate cancelled state
ChatProcessor.this.post(se);
ChatProcessor.this.readModernModifications(se, renderer);
ChatProcessor.this.complete(se);
final ChatEvent chatEvent = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.paper$originalMessage/*, ae.usePreviewComponent()*/, signedMessage);
chatEvent.setCancelled(ae.isCancelled()); // propagate cancelled state
ChatProcessor.this.post(chatEvent);
ChatProcessor.this.readModernModifications(chatEvent, renderer);
ChatProcessor.this.complete(chatEvent);
return null;
}
});

View File

@@ -1,6 +1,5 @@
package io.papermc.paper.adventure;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.serialization.JavaOps;
import io.netty.util.AttributeKey;
@@ -134,7 +133,7 @@ public final class PaperAdventure {
public static final Codec<Tag, String, CommandSyntaxException, RuntimeException> NBT_CODEC = new Codec<>() {
@Override
public @NotNull Tag decode(final @NotNull String encoded) throws CommandSyntaxException {
return new TagParser(new StringReader(encoded)).readValue();
return TagParser.parseCompoundFully(encoded);
}
@Override

View File

@@ -17,7 +17,7 @@ import org.intellij.lang.annotations.Subst;
final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer {
public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer();
private static final Codec<CompoundTag, String, CommandSyntaxException, RuntimeException> SNBT_CODEC = Codec.codec(TagParser::parseTag, Tag::toString);
private static final Codec<CompoundTag, String, CommandSyntaxException, RuntimeException> SNBT_CODEC = Codec.codec(TagParser::parseCompoundFully, Tag::toString);
static final String ITEM_TYPE = "id";
static final String ITEM_COUNT = "Count";
@@ -35,11 +35,11 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
try {
final CompoundTag contents = SNBT_CODEC.decode(raw);
final CompoundTag tag = contents.getCompound(ITEM_TAG);
@Subst("key") final String keyString = contents.getString(ITEM_TYPE);
final CompoundTag tag = contents.getCompoundOrEmpty(ITEM_TAG);
@Subst("key") final String keyString = contents.getStringOr(ITEM_TYPE, "");
return HoverEvent.ShowItem.showItem(
Key.key(keyString),
contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1,
contents.getByteOr(ITEM_COUNT, (byte) 1),
tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
);
} catch (final CommandSyntaxException ex) {
@@ -52,11 +52,11 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
try {
final CompoundTag contents = SNBT_CODEC.decode(raw);
@Subst("key") final String keyString = contents.getString(ENTITY_TYPE);
@Subst("key") final String keyString = contents.getStringOr(ENTITY_TYPE, "");
return HoverEvent.ShowEntity.showEntity(
Key.key(keyString),
UUID.fromString(contents.getString(ENTITY_ID)),
componentCodec.decode(contents.getString(ENTITY_NAME))
UUID.fromString(contents.getStringOr(ENTITY_ID, "")),
componentCodec.decode(contents.getStringOr(ENTITY_NAME, ""))
);
} catch (final CommandSyntaxException ex) {
throw new IOException(ex);

View File

@@ -134,8 +134,8 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (blockState != null) {
solidGlobal[i] = blockState.isRedstoneConductor(emptyChunk, zeroPos)
&& blockState.getBlock() != Blocks.SPAWNER && blockState.getBlock() != Blocks.BARRIER && blockState.getBlock() != Blocks.SHULKER_BOX && blockState.getBlock() != Blocks.SLIME_BLOCK && blockState.getBlock() != Blocks.MANGROVE_ROOTS || paperWorldConfig.lavaObscures && blockState == Blocks.LAVA.defaultBlockState();
// Comparing blockState == Blocks.LAVA.defaultBlockState() instead of blockState.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used
&& !blockState.is(Blocks.SPAWNER) && !blockState.is(Blocks.BARRIER) && !blockState.is(Blocks.SHULKER_BOX) && !blockState.is(Blocks.SLIME_BLOCK) && !blockState.is(Blocks.MANGROVE_ROOTS) || paperWorldConfig.lavaObscures && blockState == Blocks.LAVA.defaultBlockState();
// Comparing blockState == Blocks.LAVA.defaultBlockState() instead of blockState.is(Blocks.LAVA) ensures that only "stationary lava" is used
// shulker box checks TE.
}
}

View File

@@ -3,17 +3,12 @@ package io.papermc.paper.block.fluid;
import com.google.common.base.Preconditions;
import io.papermc.paper.block.fluid.type.PaperFallingFluidData;
import io.papermc.paper.block.fluid.type.PaperFlowingFluidData;
import io.papermc.paper.util.MCUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.LavaFluid;
import net.minecraft.world.level.material.WaterFluid;
import org.bukkit.Fluid;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftFluid;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.CraftVector;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +48,7 @@ public class PaperFluidData implements FluidData {
Preconditions.checkArgument(location.getWorld() != null, "Cannot compute flow direction on world-less location");
return CraftVector.toBukkit(this.state.getFlow(
((CraftWorld) location.getWorld()).getHandle(),
MCUtil.toBlockPosition(location)
CraftLocation.toBlockPosition(location)
));
}
@@ -65,7 +60,7 @@ public class PaperFluidData implements FluidData {
@Override
public float computeHeight(@NotNull final Location location) {
Preconditions.checkArgument(location.getWorld() != null, "Cannot compute height on world-less location");
return this.state.getHeight(((CraftWorld) location.getWorld()).getHandle(), MCUtil.toBlockPos(location));
return this.state.getHeight(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toBlockPosition(location));
}
@Override
@@ -88,23 +83,10 @@ public class PaperFluidData implements FluidData {
return "PaperFluidData{" + this.state + "}";
}
/* Registry */
private static final Map<Class<? extends net.minecraft.world.level.material.Fluid>, Function<FluidState, PaperFluidData>> MAP = new HashMap<>();
static {
//<editor-fold desc="PaperFluidData Registration" defaultstate="collapsed">
register(LavaFluid.Source.class, PaperFallingFluidData::new);
register(WaterFluid.Source.class, PaperFallingFluidData::new);
register(LavaFluid.Flowing.class, PaperFlowingFluidData::new);
register(WaterFluid.Flowing.class, PaperFlowingFluidData::new);
//</editor-fold>
}
static void register(final Class<? extends net.minecraft.world.level.material.Fluid> fluid, final Function<FluidState, PaperFluidData> creator) {
Preconditions.checkState(MAP.put(fluid, creator) == null, "Duplicate mapping %s->%s", fluid, creator);
MAP.put(fluid, creator);
}
public static PaperFluidData createData(final FluidState state) {
return MAP.getOrDefault(state.getType().getClass(), PaperFluidData::new).apply(state);
if (state.isEmpty()) {
return new PaperFluidData(state);
}
return state.isSource() ? new PaperFallingFluidData(state) : new PaperFlowingFluidData(state);
}
}

View File

@@ -37,7 +37,7 @@ public final class PaperBrigadier {
final PluginCommandMeta meta;
if ((meta = node.pluginCommandMeta) == null) {
return new VanillaCommandWrapper(null, node);
return new VanillaCommandWrapper(node);
}
CommandNode<CommandSourceStack> argumentCommandNode = node;
if (argumentCommandNode.getRedirect() != null) {

View File

@@ -2,7 +2,6 @@ package io.papermc.paper.command.brigadier;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
@@ -15,17 +14,17 @@ import java.util.List;
public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implements PluginIdentifiableCommand {
private final Plugin plugin;
private final List<String> alises;
private final List<String> aliases;
public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand, Plugin plugin) {
super(name, description, usageMessage, aliases, vanillaCommand);
this.plugin = plugin;
this.alises = aliases;
this.aliases = aliases;
}
@Override
public @NotNull List<String> getAliases() {
return this.alises;
return this.aliases;
}
@Override
@@ -37,10 +36,4 @@ public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implement
public @NotNull Plugin getPlugin() {
return this.plugin;
}
// Show in help menu!
@Override
public boolean isRegistered() {
return true;
}
}

View File

@@ -12,9 +12,9 @@ import org.checkerframework.framework.qual.DefaultQualifier;
public final class VersionCommand implements PaperSubcommand {
@Override
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
if (ver != null) {
ver.execute(sender, "paper", new String[0]);
final @Nullable Command redirect = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
if (redirect != null) {
redirect.execute(sender, "paper", new String[0]);
}
return true;
}

View File

@@ -5,7 +5,7 @@ import io.papermc.paper.FeatureHooks;
import io.papermc.paper.configuration.constraint.Constraints;
import io.papermc.paper.configuration.type.number.DoubleOr;
import io.papermc.paper.configuration.type.number.IntOr;
import io.papermc.paper.util.ItemObfuscationBinding;
import io.papermc.paper.util.sanitizer.ItemObfuscationBinding;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.core.component.DataComponents;

View File

@@ -52,6 +52,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.NaturalSpawner;
import net.minecraft.world.level.block.BambooStalkBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
@@ -169,7 +170,7 @@ public class WorldConfiguration extends ConfigurationPart {
public ArrowDespawnRate nonPlayerArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
public ArrowDespawnRate creativeArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
public boolean filterBadTileEntityNbtFromFallingBlocks = true;
public List<NbtPathArgument.NbtPath> filteredEntityTagNbtPaths = NbtPathSerializer.fromString(List.of("Pos", "Motion", "SleepingX", "SleepingY", "SleepingZ"));
public List<NbtPathArgument.NbtPath> filteredEntityTagNbtPaths = NbtPathSerializer.fromString(List.of("Pos", "Motion", "sleeping_pos"));
public boolean disableMobSpawnerSpawnEggTransformation = false;
public boolean perPlayerMobSpawns = true;
public boolean scanForLegacyEnderDragon = true;
@@ -236,7 +237,7 @@ public class WorldConfiguration extends ConfigurationPart {
public class WanderingTrader extends ConfigurationPart {
public int spawnMinuteLength = 1200;
public int spawnDayLength = 24000;
public int spawnDayLength = net.minecraft.world.entity.npc.WanderingTraderSpawner.DEFAULT_SPAWN_DELAY;
public int spawnChanceFailureIncrement = 25;
public int spawnChanceMin = 25;
public int spawnChanceMax = 75;
@@ -389,7 +390,7 @@ public class WorldConfiguration extends ConfigurationPart {
public Bamboo bamboo;
public class Bamboo extends ConfigurationPart {
public int max = 16;
public int max = BambooStalkBlock.MAX_HEIGHT;
public int min = 11;
}
}

View File

@@ -3,6 +3,7 @@ package io.papermc.paper.datacomponent;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.datacomponent.item.PaperBannerPatternLayers;
import io.papermc.paper.datacomponent.item.PaperBlockItemDataProperties;
import io.papermc.paper.datacomponent.item.PaperBlocksAttacks;
import io.papermc.paper.datacomponent.item.PaperBundleContents;
import io.papermc.paper.datacomponent.item.PaperChargedProjectiles;
import io.papermc.paper.datacomponent.item.PaperConsumable;
@@ -33,14 +34,16 @@ import io.papermc.paper.datacomponent.item.PaperRepairable;
import io.papermc.paper.datacomponent.item.PaperResolvableProfile;
import io.papermc.paper.datacomponent.item.PaperSeededContainerLoot;
import io.papermc.paper.datacomponent.item.PaperSuspiciousStewEffects;
import io.papermc.paper.datacomponent.item.PaperUnbreakable;
import io.papermc.paper.datacomponent.item.PaperTooltipDisplay;
import io.papermc.paper.datacomponent.item.PaperUseCooldown;
import io.papermc.paper.datacomponent.item.PaperUseRemainder;
import io.papermc.paper.datacomponent.item.PaperWeapon;
import io.papermc.paper.datacomponent.item.PaperWritableBookContent;
import io.papermc.paper.datacomponent.item.PaperWrittenBookContent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import io.papermc.paper.registry.PaperRegistries;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -50,9 +53,27 @@ import net.minecraft.util.Unit;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.component.MapPostProcessing;
import org.bukkit.DyeColor;
import org.bukkit.craftbukkit.CraftArt;
import org.bukkit.craftbukkit.CraftMusicInstrument;
import org.bukkit.craftbukkit.entity.CraftAxolotl;
import org.bukkit.craftbukkit.entity.CraftCat;
import org.bukkit.craftbukkit.entity.CraftChicken;
import org.bukkit.craftbukkit.entity.CraftCow;
import org.bukkit.craftbukkit.entity.CraftFrog;
import org.bukkit.craftbukkit.entity.CraftPainting;
import org.bukkit.craftbukkit.entity.CraftPig;
import org.bukkit.craftbukkit.entity.CraftVillager;
import org.bukkit.craftbukkit.entity.CraftWolf;
import org.bukkit.craftbukkit.inventory.CraftMetaFirework;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Axolotl;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Llama;
import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Rabbit;
import org.bukkit.entity.Salmon;
import org.bukkit.entity.TropicalFish;
import org.bukkit.inventory.ItemRarity;
import static io.papermc.paper.util.MCUtil.transformUnmodifiable;
@@ -73,7 +94,8 @@ public final class DataComponentAdapters {
registerIdentity(DataComponents.MAX_STACK_SIZE);
registerIdentity(DataComponents.MAX_DAMAGE);
registerIdentity(DataComponents.DAMAGE);
register(DataComponents.UNBREAKABLE, PaperUnbreakable::new);
registerUntyped(DataComponents.UNBREAKABLE);
registerIdentity(DataComponents.POTION_DURATION_SCALE);
register(DataComponents.CUSTOM_NAME, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
register(DataComponents.ITEM_NAME, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
register(DataComponents.ITEM_MODEL, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
@@ -84,8 +106,6 @@ public final class DataComponentAdapters {
register(DataComponents.CAN_BREAK, PaperItemAdventurePredicate::new);
register(DataComponents.ATTRIBUTE_MODIFIERS, PaperItemAttributeModifiers::new);
register(DataComponents.CUSTOM_MODEL_DATA, PaperCustomModelData::new);
registerUntyped(DataComponents.HIDE_ADDITIONAL_TOOLTIP);
registerUntyped(DataComponents.HIDE_TOOLTIP);
registerIdentity(DataComponents.REPAIR_COST);
// registerUntyped(DataComponents.CREATIVE_SLOT_LOCK);
registerIdentity(DataComponents.ENCHANTMENT_GLINT_OVERRIDE);
@@ -119,9 +139,12 @@ public final class DataComponentAdapters {
// entity data
// bucket entity data
// block entity data
register(DataComponents.INSTRUMENT, CraftMusicInstrument::minecraftHolderToBukkit, CraftMusicInstrument::bukkitToMinecraftHolder);
//register(DataComponents.INSTRUMENT, CraftMusicInstrument::minecraftHolderToBukkit, CraftMusicInstrument::bukkitToMinecraftHolder); // TODO
registerIdentity(DataComponents.INSTRUMENT);
registerIdentity(DataComponents.PROVIDES_TRIM_MATERIAL); // TODO
register(DataComponents.OMINOUS_BOTTLE_AMPLIFIER, PaperOminousBottleAmplifier::new);
register(DataComponents.JUKEBOX_PLAYABLE, PaperJukeboxPlayable::new);
register(DataComponents.PROVIDES_BANNER_PATTERNS, PaperRegistries::fromNms, PaperRegistries::toNms);
register(DataComponents.RECIPES,
nms -> transformUnmodifiable(nms, PaperAdventure::asAdventureKey),
api -> transformUnmodifiable(api, key -> PaperAdventure.asVanilla(Registries.RECIPE, key))
@@ -139,6 +162,37 @@ public final class DataComponentAdapters {
// bees
// register(DataComponents.LOCK, PaperLockCode::new);
register(DataComponents.CONTAINER_LOOT, PaperSeededContainerLoot::new);
register(DataComponents.BREAK_SOUND, nms -> PaperAdventure.asAdventureKey(nms.unwrapKey().get()), api -> BuiltInRegistries.SOUND_EVENT.getOrThrow(PaperAdventure.asVanilla(Registries.SOUND_EVENT, api)));
// TODO break_sound, provides_, entity data
register(DataComponents.TOOLTIP_DISPLAY, PaperTooltipDisplay::new);
register(DataComponents.WEAPON, PaperWeapon::new);
register(DataComponents.BLOCKS_ATTACKS, PaperBlocksAttacks::new);
register(DataComponents.VILLAGER_VARIANT, CraftVillager.CraftType::minecraftHolderToBukkit, CraftVillager.CraftType::bukkitToMinecraftHolder);
register(DataComponents.WOLF_VARIANT, CraftWolf.CraftVariant::minecraftHolderToBukkit, CraftWolf.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.WOLF_COLLAR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.WOLF_SOUND_VARIANT, CraftWolf.CraftSoundVariant::minecraftHolderToBukkit, CraftWolf.CraftSoundVariant::bukkitToMinecraftHolder);
register(DataComponents.FOX_VARIANT, nms -> org.bukkit.entity.Fox.Type.values()[nms.ordinal()], api -> net.minecraft.world.entity.animal.Fox.Variant.byId(api.ordinal()));
register(DataComponents.SALMON_SIZE, (nms) -> Salmon.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.Salmon.Variant.values()[api.ordinal()]);
register(DataComponents.PARROT_VARIANT, (nms) -> Parrot.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.Parrot.Variant.byId(api.ordinal()));
register(DataComponents.TROPICAL_FISH_PATTERN, (nms) -> TropicalFish.Pattern.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.TropicalFish.Pattern.byId(api.ordinal()));
register(DataComponents.TROPICAL_FISH_BASE_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.TROPICAL_FISH_PATTERN_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.MOOSHROOM_VARIANT, (nms) -> MushroomCow.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.MushroomCow.Variant.values()[api.ordinal()]);
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 cleaner pattern for handling this which retains the EitherHolder, this does kinda suck in terms of exposure, however
register(DataComponents.CHICKEN_VARIANT, CraftChicken.CraftVariant::minecraftEitherHolderToBukkit, CraftChicken.CraftVariant::bukkitToMinecraftEitherHolder);
register(DataComponents.FROG_VARIANT, CraftFrog.CraftVariant::minecraftHolderToBukkit, CraftFrog.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.HORSE_VARIANT, (nms) -> Horse.Style.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.horse.Variant.byId(api.ordinal()));
register(DataComponents.PAINTING_VARIANT, CraftArt::minecraftHolderToBukkit, CraftArt::bukkitToMinecraftHolder);
register(DataComponents.LLAMA_VARIANT, (nms) -> Llama.Color.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.horse.Llama.Variant.byId(api.ordinal()));
register(DataComponents.AXOLOTL_VARIANT, (nms) -> Axolotl.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.axolotl.Axolotl.Variant.byId(api.ordinal()));
register(DataComponents.CAT_VARIANT, CraftCat.CraftType::minecraftHolderToBukkit, CraftCat.CraftType::bukkitToMinecraftHolder);
register(DataComponents.CAT_COLLAR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.SHEEP_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.SHULKER_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
for (final Map.Entry<ResourceKey<DataComponentType<?>>, DataComponentType<?>> componentType : BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet()) {
if (!ADAPTERS.containsKey(componentType.getKey())) {

View File

@@ -35,11 +35,6 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
return new PaperPotDecorations.BuilderImpl();
}
@Override
public Unbreakable.Builder unbreakable() {
return new PaperUnbreakable.BuilderImpl();
}
@Override
public ItemLore.Builder lore() {
return new PaperItemLore.BuilderImpl();
@@ -236,4 +231,19 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
new OminousBottleAmplifier(amplifier)
);
}
@Override
public BlocksAttacks.Builder blocksAttacks() {
return new PaperBlocksAttacks.BuilderImpl();
}
@Override
public TooltipDisplay.Builder tooltipDisplay() {
return new PaperTooltipDisplay.BuilderImpl();
}
@Override
public Weapon.Builder weapon() {
return new PaperWeapon.BuilderImpl();
}
}

View File

@@ -0,0 +1,119 @@
package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.tag.TagKey;
import java.util.List;
import java.util.Optional;
import net.kyori.adventure.key.Key;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.damage.DamageType;
import org.jetbrains.annotations.Nullable;
public record PaperBlocksAttacks(
net.minecraft.world.item.component.BlocksAttacks impl
) implements BlocksAttacks, Handleable<net.minecraft.world.item.component.BlocksAttacks> {
@Override
public net.minecraft.world.item.component.BlocksAttacks getHandle() {
return this.impl;
}
@Override
public float blockDelaySeconds() {
return this.impl.blockDelaySeconds();
}
@Override
public float disableCooldownScale() {
return this.impl.disableCooldownScale();
}
@Override
public @Nullable TagKey<DamageType> bypassedBy() {
final Optional<TagKey<DamageType>> tagKey = this.impl.bypassedBy().map(PaperRegistries::fromNms);
return tagKey.orElse(null);
}
@Override
public @Nullable Key blockSound() {
return this.impl.blockSound().map(holder -> PaperAdventure.asAdventure(holder.value().location())).orElse(null);
}
@Override
public @Nullable Key disableSound() {
return this.impl.disableSound().map(holder -> PaperAdventure.asAdventure(holder.value().location())).orElse(null);
}
static final class BuilderImpl implements Builder {
private float blockDelaySeconds;
private float disableCooldownScale = 1.0F;
//private List<DamageReduction> damageReductions = List.of();
//private ItemDamageFunction itemDamage = ItemDamageFunction.DEFAULT;
private @Nullable TagKey<DamageType> bypassedBy;
private @Nullable Key blockSound;
private @Nullable Key disableSound;
@Override
public Builder blockDelaySeconds(final float delay) {
Preconditions.checkArgument(delay >= 0, "delay must be non-negative, was %s", delay);
this.blockDelaySeconds = delay;
return this;
}
@Override
public Builder disableCooldownScale(final float scale) {
Preconditions.checkArgument(scale >= 0, "scale must be non-negative, was %s", scale);
this.disableCooldownScale = scale;
return this;
}
//@Override
//public Builder addDamageReduction(final DamageReduction reduction) {
// return null;
//}
//@Override
//public Builder itemDamage(final ItemDamageFunction function) {
// return null;
//}
@Override
public Builder bypassedBy(@Nullable final TagKey<DamageType> bypassedBy) {
this.bypassedBy = bypassedBy;
return this;
}
@Override
public Builder blockSound(@Nullable final Key sound) {
this.blockSound = sound;
return this;
}
@Override
public Builder disableSound(@Nullable final Key sound) {
this.disableSound = sound;
return this;
}
//@Override
//public Builder damageReductions(final List<DamageReduction> reductions) {
// return null;
//}
@Override
public BlocksAttacks build() {
return new PaperBlocksAttacks(new net.minecraft.world.item.component.BlocksAttacks(
this.blockDelaySeconds,
this.disableCooldownScale,
List.of(), // TODO
net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction.DEFAULT, // TODO
Optional.ofNullable(this.bypassedBy).map(PaperRegistries::toNms),
Optional.ofNullable(this.blockSound).map(PaperAdventure::resolveSound),
Optional.ofNullable(this.disableSound).map(PaperAdventure::resolveSound)
));
}
}
}

View File

@@ -17,20 +17,9 @@ public record PaperDyedItemColor(
return Color.fromRGB(this.impl.rgb() & 0x00FFFFFF); // skip alpha channel
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public DyedItemColor showInTooltip(final boolean showInTooltip) {
return new PaperDyedItemColor(this.impl.withTooltip(showInTooltip));
}
static final class BuilderImpl implements DyedItemColor.Builder {
private Color color = Color.WHITE;
private boolean showInToolTip = true;
@Override
public DyedItemColor.Builder color(final Color color) {
@@ -38,15 +27,11 @@ public record PaperDyedItemColor(
return this;
}
@Override
public DyedItemColor.Builder showInTooltip(final boolean showInTooltip) {
this.showInToolTip = showInTooltip;
return this;
}
@Override
public DyedItemColor build() {
return new PaperDyedItemColor(new net.minecraft.world.item.component.DyedItemColor(this.color.asRGB(), this.showInToolTip));
return new PaperDyedItemColor(new net.minecraft.world.item.component.DyedItemColor(
this.color.asRGB())
);
}
}
}

View File

@@ -1,12 +1,10 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import java.util.Optional;
import java.util.function.Function;
import net.kyori.adventure.key.Key;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
@@ -16,7 +14,6 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.datafix.fixes.EquippableAssetRenameFix;
import net.minecraft.world.item.equipment.EquipmentAsset;
import net.minecraft.world.item.equipment.EquipmentAssets;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
@@ -80,6 +77,11 @@ public record PaperEquippable(
return this.impl.damageOnHurt();
}
@Override
public boolean equipOnInteract() {
return this.impl.equipOnInteract();
}
@Override
public Builder toBuilder() {
return new BuilderImpl(this.slot())
@@ -89,7 +91,8 @@ public record PaperEquippable(
.allowedEntities(this.allowedEntities())
.dispensable(this.dispensable())
.swappable(this.swappable())
.damageOnHurt(this.damageOnHurt());
.damageOnHurt(this.damageOnHurt())
.equipOnInteract(this.equipOnInteract());
}
@@ -103,6 +106,7 @@ public record PaperEquippable(
private boolean dispensable = true;
private boolean swappable = true;
private boolean damageOnHurt = true;
private boolean equipOnInteract;
BuilderImpl(final EquipmentSlot equipmentSlot) {
this.equipmentSlot = CraftEquipmentSlot.getNMS(equipmentSlot);
@@ -155,6 +159,12 @@ public record PaperEquippable(
return this;
}
@Override
public Builder equipOnInteract(final boolean equipOnInteract) {
this.equipOnInteract = equipOnInteract;
return this;
}
@Override
public Equippable build() {
return new PaperEquippable(
@@ -166,7 +176,8 @@ public record PaperEquippable(
this.allowedEntities,
this.dispensable,
this.swappable,
this.damageOnHurt
this.damageOnHurt,
this.equipOnInteract
)
);
}

View File

@@ -7,6 +7,7 @@ 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;
@@ -24,17 +25,6 @@ public record PaperItemAdventurePredicate(
public net.minecraft.world.item.AdventureModePredicate getHandle() {
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public PaperItemAdventurePredicate showInTooltip(final boolean showInTooltip) {
return new PaperItemAdventurePredicate(this.impl.withTooltip(showInTooltip));
}
@Override
public List<BlockPredicate> predicates() {
return convert(this.impl);
@@ -43,13 +33,12 @@ public record PaperItemAdventurePredicate(
static final class BuilderImpl implements ItemAdventurePredicate.Builder {
private final List<net.minecraft.advancements.critereon.BlockPredicate> predicates = new ObjectArrayList<>();
private boolean showInTooltip = true;
@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)
), Optional.empty(), Optional.empty()));
), Optional.empty(), Optional.empty(), DataComponentMatchers.ANY)); // TODO DataComponentMatchers
return this;
}
@@ -61,15 +50,11 @@ public record PaperItemAdventurePredicate(
return this;
}
@Override
public ItemAdventurePredicate.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemAdventurePredicate build() {
return new PaperItemAdventurePredicate(new net.minecraft.world.item.AdventureModePredicate(new ObjectArrayList<>(this.predicates), this.showInTooltip));
return new PaperItemAdventurePredicate(new net.minecraft.world.item.AdventureModePredicate(
new ObjectArrayList<>(this.predicates))
);
}
}
}

View File

@@ -14,16 +14,6 @@ public record PaperItemArmorTrim(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public ItemArmorTrim showInTooltip(final boolean showInTooltip) {
return new PaperItemArmorTrim(this.impl.withTooltip(showInTooltip));
}
@Override
public ArmorTrim armorTrim() {
return new ArmorTrim(CraftTrimMaterial.minecraftHolderToBukkit(this.impl.material()), CraftTrimPattern.minecraftHolderToBukkit(this.impl.pattern()));
@@ -32,18 +22,10 @@ public record PaperItemArmorTrim(
static final class BuilderImpl implements ItemArmorTrim.Builder {
private ArmorTrim armorTrim;
private boolean showInTooltip = true;
BuilderImpl(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;
}
@Override
public ItemArmorTrim.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemArmorTrim.Builder armorTrim(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;
@@ -54,8 +36,7 @@ public record PaperItemArmorTrim(
public ItemArmorTrim build() {
return new PaperItemArmorTrim(new net.minecraft.world.item.equipment.trim.ArmorTrim(
CraftTrimMaterial.bukkitToMinecraftHolder(this.armorTrim.getMaterial()),
CraftTrimPattern.bukkitToMinecraftHolder(this.armorTrim.getPattern()),
this.showInTooltip
CraftTrimPattern.bukkitToMinecraftHolder(this.armorTrim.getPattern())
));
}
}

View File

@@ -30,16 +30,6 @@ public record PaperItemAttributeModifiers(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public ItemAttributeModifiers showInTooltip(final boolean showInTooltip) {
return new PaperItemAttributeModifiers(this.impl.withTooltip(showInTooltip));
}
@Override
public @Unmodifiable List<Entry> modifiers() {
return convert(this.impl);
@@ -51,7 +41,6 @@ public record PaperItemAttributeModifiers(
static final class BuilderImpl implements ItemAttributeModifiers.Builder {
private final List<net.minecraft.world.item.component.ItemAttributeModifiers.Entry> entries = new ObjectArrayList<>();
private boolean showInTooltip = net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY.showInTooltip();
@Override
public Builder addModifier(final Attribute attribute, final AttributeModifier modifier) {
@@ -76,21 +65,14 @@ public record PaperItemAttributeModifiers(
return this;
}
@Override
public ItemAttributeModifiers.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemAttributeModifiers build() {
if (this.entries.isEmpty()) {
return new PaperItemAttributeModifiers(net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY.withTooltip(this.showInTooltip));
return new PaperItemAttributeModifiers(net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY);
}
return new PaperItemAttributeModifiers(new net.minecraft.world.item.component.ItemAttributeModifiers(
new ObjectArrayList<>(this.entries),
this.showInTooltip
new ObjectArrayList<>(this.entries)
));
}
}

View File

@@ -31,16 +31,6 @@ public record PaperItemEnchantments(
return Collections.unmodifiableMap(map); // TODO look into making a "transforming" map maybe?
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip;
}
@Override
public ItemEnchantments showInTooltip(final boolean showInTooltip) {
return new PaperItemEnchantments(this.impl.withTooltip(showInTooltip), this.enchantments);
}
@Override
public net.minecraft.world.item.enchantment.ItemEnchantments getHandle() {
return this.impl;
@@ -49,7 +39,6 @@ public record PaperItemEnchantments(
static final class BuilderImpl implements ItemEnchantments.Builder {
private final Map<Enchantment, Integer> enchantments = new Object2ObjectOpenHashMap<>();
private boolean showInTooltip = true;
@Override
public ItemEnchantments.Builder add(final Enchantment enchantment, final int level) {
@@ -69,15 +58,9 @@ public record PaperItemEnchantments(
return this;
}
@Override
public ItemEnchantments.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemEnchantments build() {
final net.minecraft.world.item.enchantment.ItemEnchantments initialEnchantments = net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY.withTooltip(this.showInTooltip);
final net.minecraft.world.item.enchantment.ItemEnchantments initialEnchantments = net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY;
if (this.enchantments.isEmpty()) {
return new PaperItemEnchantments(initialEnchantments);
}

View File

@@ -49,6 +49,11 @@ public record PaperItemTool(
return this.impl.damagePerBlock();
}
@Override
public boolean canDestroyBlocksInCreative() {
return this.impl.canDestroyBlocksInCreative();
}
record PaperRule(RegistryKeySet<BlockType> blocks, @Nullable Float speed, TriState correctForDrops) implements Rule {
public static PaperRule fromUnsafe(final RegistryKeySet<BlockType> blocks, final @Nullable Float speed, final TriState correctForDrops) {
@@ -62,6 +67,7 @@ public record PaperItemTool(
private final List<net.minecraft.world.item.component.Tool.Rule> rules = new ObjectArrayList<>();
private int damage = 1;
private float miningSpeed = 1.0F;
private boolean canDestroyBlocksInCreative = true;
@Override
public Builder damagePerBlock(final int damage) {
@@ -86,6 +92,12 @@ public record PaperItemTool(
return this;
}
@Override
public Builder canDestroyBlocksInCreative(final boolean canDestroyBlocksInCreative) {
this.canDestroyBlocksInCreative = canDestroyBlocksInCreative;
return this;
}
@Override
public Builder addRules(final Collection<Rule> rules) {
rules.forEach(this::addRule);
@@ -94,7 +106,9 @@ public record PaperItemTool(
@Override
public Tool build() {
return new PaperItemTool(new net.minecraft.world.item.component.Tool(new ObjectArrayList<>(this.rules), this.miningSpeed, this.damage));
return new PaperItemTool(new net.minecraft.world.item.component.Tool(
new ObjectArrayList<>(this.rules), this.miningSpeed, this.damage, this.canDestroyBlocksInCreative
));
}
}
}

View File

@@ -15,16 +15,6 @@ public record PaperJukeboxPlayable(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public PaperJukeboxPlayable showInTooltip(final boolean showInTooltip) {
return new PaperJukeboxPlayable(this.impl.withTooltip(showInTooltip));
}
@Override
public JukeboxSong jukeboxSong() {
return this.impl.song()
@@ -36,18 +26,11 @@ public record PaperJukeboxPlayable(
static final class BuilderImpl implements JukeboxPlayable.Builder {
private JukeboxSong song;
private boolean showInTooltip = true;
BuilderImpl(final JukeboxSong song) {
this.song = song;
}
@Override
public JukeboxPlayable.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public JukeboxPlayable.Builder jukeboxSong(final JukeboxSong song) {
this.song = song;
@@ -56,7 +39,9 @@ public record PaperJukeboxPlayable(
@Override
public JukeboxPlayable build() {
return new PaperJukeboxPlayable(new net.minecraft.world.item.JukeboxPlayable(new EitherHolder<>(CraftJukeboxSong.bukkitToMinecraftHolder(this.song)), this.showInTooltip));
return new PaperJukeboxPlayable(new net.minecraft.world.item.JukeboxPlayable(
new EitherHolder<>(CraftJukeboxSong.bukkitToMinecraftHolder(this.song))
));
}
}
}

View File

@@ -0,0 +1,63 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.PaperDataComponentType;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperTooltipDisplay(
net.minecraft.world.item.component.TooltipDisplay impl
) implements TooltipDisplay, Handleable<net.minecraft.world.item.component.TooltipDisplay> {
@Override
public net.minecraft.world.item.component.TooltipDisplay getHandle() {
return this.impl;
}
@Override
public boolean hideTooltip() {
return this.impl.hideTooltip();
}
@Override
public Set<DataComponentType> hiddenComponents() {
return this.impl.hiddenComponents().stream()
.map(PaperDataComponentType::minecraftToBukkit)
.collect(Collectors.toCollection(ReferenceLinkedOpenHashSet::new));
}
static final class BuilderImpl implements Builder {
private final Set<DataComponentType> hiddenComponents = new ReferenceLinkedOpenHashSet<>();
private boolean hideTooltip;
@Override
public Builder hideTooltip(final boolean hide) {
this.hideTooltip = hide;
return this;
}
@Override
public Builder addHiddenComponents(final DataComponentType... components) {
this.hiddenComponents.addAll(Arrays.asList(components));
return this;
}
@Override
public Builder hiddenComponents(final Set<DataComponentType> components) {
this.hiddenComponents.addAll(components);
return this;
}
@Override
public TooltipDisplay build() {
return new PaperTooltipDisplay(new net.minecraft.world.item.component.TooltipDisplay(
this.hideTooltip,
this.hiddenComponents.stream().map(PaperDataComponentType::bukkitToMinecraft).collect(Collectors.toCollection(ReferenceLinkedOpenHashSet::new))
));
}
}
}

View File

@@ -1,39 +0,0 @@
package io.papermc.paper.datacomponent.item;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperUnbreakable(
net.minecraft.world.item.component.Unbreakable impl
) implements Unbreakable, Handleable<net.minecraft.world.item.component.Unbreakable> {
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public Unbreakable showInTooltip(final boolean showInTooltip) {
return new PaperUnbreakable(this.impl.withTooltip(showInTooltip));
}
@Override
public net.minecraft.world.item.component.Unbreakable getHandle() {
return this.impl;
}
static final class BuilderImpl implements Unbreakable.Builder {
private boolean showInTooltip = true;
@Override
public Unbreakable.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public Unbreakable build() {
return new PaperUnbreakable(new net.minecraft.world.item.component.Unbreakable(this.showInTooltip));
}
}
}

View File

@@ -0,0 +1,52 @@
package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperWeapon(
net.minecraft.world.item.component.Weapon impl
) implements Weapon, Handleable<net.minecraft.world.item.component.Weapon> {
@Override
public net.minecraft.world.item.component.Weapon getHandle() {
return this.impl;
}
@Override
public int itemDamagePerAttack() {
return this.impl.itemDamagePerAttack();
}
@Override
public float disableBlockingForSeconds() {
return this.impl.disableBlockingForSeconds();
}
static final class BuilderImpl implements Builder {
private int itemDamagePerAttack = 1;
private float disableBlockingForSeconds;
@Override
public Builder itemDamagePerAttack(final int damage) {
Preconditions.checkArgument(damage >= 0, "damage must be non-negative, was %s", damage);
this.itemDamagePerAttack = damage;
return this;
}
@Override
public Builder disableBlockingForSeconds(final float seconds) {
Preconditions.checkArgument(seconds >= 0, "seconds must be non-negative, was %s", seconds);
this.disableBlockingForSeconds = seconds;
return this;
}
@Override
public Weapon build() {
return new PaperWeapon(new net.minecraft.world.item.component.Weapon(
this.itemDamagePerAttack,
this.disableBlockingForSeconds
));
}
}
}

View File

@@ -20,10 +20,10 @@ import net.kyori.adventure.text.Component;
import net.minecraft.server.packs.PackLocationInfo;
import net.minecraft.server.packs.PackSelectionConfig;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.VanillaPackResourcesBuilder;
import net.minecraft.server.packs.repository.FolderRepositorySource;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackDetector;
import net.minecraft.util.FileSystemUtil;
import net.minecraft.world.level.validation.ContentValidationException;
import net.minecraft.world.level.validation.DirectoryValidator;
import net.minecraft.world.level.validation.ForbiddenSymlinkInfo;
@@ -92,7 +92,7 @@ public class PaperDatapackRegistrar implements PaperRegistrar<BootstrapContext>,
@Override
public @Nullable DiscoveredDatapack discoverPack(final PluginMeta pluginMeta, final URI uri, final String id, final Consumer<Configurer> configurer) throws IOException {
return this.discoverPack(pluginMeta, VanillaPackResourcesBuilder.safeGetPath(uri), id, configurer);
return this.discoverPack(pluginMeta, FileSystemUtil.safeGetPath(uri), id, configurer);
}
@Override

View File

@@ -75,7 +75,7 @@ public abstract class PaperPersistentDataContainerView implements PersistentData
@Override
public Set<NamespacedKey> getKeys() {
final Set<String> names = this.toTagCompound().getAllKeys();
final Set<String> names = this.toTagCompound().keySet();
final Set<NamespacedKey> keys = new HashSet<>(names.size());
names.forEach(key -> {
final String[] keyPart = key.split(":", 2);
@@ -96,7 +96,7 @@ public abstract class PaperPersistentDataContainerView implements PersistentData
Preconditions.checkArgument(other != null, "The target container cannot be null");
final CraftPersistentDataContainer target = (CraftPersistentDataContainer) other;
final CompoundTag tag = this.toTagCompound();
for (final String key : tag.getAllKeys()) {
for (final String key : tag.keySet()) {
if (replace || !target.getRaw().containsKey(key)) {
target.getRaw().put(key, tag.get(key).copy());
}

View File

@@ -0,0 +1,39 @@
package io.papermc.paper.registry;
import io.papermc.paper.util.Holderable;
import net.minecraft.core.Holder;
import org.bukkit.NamespacedKey;
public abstract class HolderableBase<M> implements Holderable<M> {
protected final Holder<M> holder;
protected HolderableBase(final Holder<M> holder) {
this.holder = holder;
}
@Override
public final Holder<M> getHolder() {
return this.holder;
}
@Override
public final int hashCode() {
return Holderable.super.implHashCode();
}
@Override
public final boolean equals(final Object obj) {
return Holderable.super.implEquals(obj);
}
@Override
public final String toString() {
return Holderable.super.implToString();
}
@Override
public final NamespacedKey getKey() {
return Holderable.super.getKey();
}
}

View File

@@ -44,7 +44,10 @@ import org.bukkit.craftbukkit.block.banner.CraftPatternType;
import org.bukkit.craftbukkit.damage.CraftDamageType;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.entity.CraftCat;
import org.bukkit.craftbukkit.entity.CraftChicken;
import org.bukkit.craftbukkit.entity.CraftCow;
import org.bukkit.craftbukkit.entity.CraftFrog;
import org.bukkit.craftbukkit.entity.CraftPig;
import org.bukkit.craftbukkit.entity.CraftVillager;
import org.bukkit.craftbukkit.entity.CraftWolf;
import org.bukkit.craftbukkit.generator.structure.CraftStructure;
@@ -60,10 +63,12 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.memory.MemoryKey;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemType;
@@ -83,14 +88,14 @@ public final class PaperRegistries {
private static final Map<ResourceKey<?>, RegistryEntry<?, ?>> BY_RESOURCE_KEY;
static {
REGISTRY_ENTRIES = List.of(
// built-ins
// Start generate - RegistryDefinitions
// @GeneratedFrom 1.21.5
// 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(),
start(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT).craft(PotionEffectType.class, CraftPotionEffectType::new).build(),
start(Registries.BLOCK, RegistryKey.BLOCK).craft(BlockType.class, CraftBlockType::new).build(),
start(Registries.ITEM, RegistryKey.ITEM).craft(ItemType.class, CraftItemType::new).build(),
start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).build(),
start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build(),
start(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION).craft(Villager.Profession.class, CraftVillager.CraftProfession::new).build(),
start(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE).craft(Villager.Type.class, CraftVillager.CraftType::new).build(),
start(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE).craft(MapCursor.Type.class, CraftMapCursor.CraftType::new).build(),
@@ -100,24 +105,31 @@ public final class PaperRegistries {
start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new, true).build(),
start(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE).craft(DataComponentTypes.class, PaperDataComponentType::of).build(),
// data-drivens
// data-driven
start(Registries.BIOME, RegistryKey.BIOME).craft(Biome.class, CraftBiome::new).build().delayed(),
start(Registries.STRUCTURE, RegistryKey.STRUCTURE).craft(Structure.class, CraftStructure::new).build().delayed(),
start(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL).craft(TrimMaterial.class, CraftTrimMaterial::new, true).build().delayed(),
start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new, true).build().delayed(),
start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).writable(PaperDamageTypeRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().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.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.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).build().delayed(),
start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build().delayed(),
start(Registries.CHICKEN_VARIANT, RegistryKey.CHICKEN_VARIANT).craft(Chicken.Variant.class, CraftChicken.CraftVariant::new).build(),
start(Registries.COW_VARIANT, RegistryKey.COW_VARIANT).craft(Cow.Variant.class, CraftCow.CraftVariant::new).build(),
start(Registries.PIG_VARIANT, RegistryKey.PIG_VARIANT).craft(Pig.Variant.class, CraftPig.CraftVariant::new).build(),
// api-only
start(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE).apiOnly(PaperSimpleRegistry::entityType),
start(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE).apiOnly(PaperSimpleRegistry::particleType),
start(Registries.POTION, RegistryKey.POTION).apiOnly(PaperSimpleRegistry::potion),
start(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE).apiOnly(() -> (org.bukkit.Registry<MemoryKey<?>>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE)
start(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE).apiOnly(() -> org.bukkit.Registry.MEMORY_MODULE_TYPE)
// End generate - RegistryDefinitions
);
final Map<RegistryKey<?>, RegistryEntry<?, ?>> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
final Map<ResourceKey<?>, RegistryEntry<?, ?>> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());

View File

@@ -126,7 +126,7 @@ public class PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry {
@Override
public List<org.bukkit.inventory.EquipmentSlotGroup> activeSlots() {
return Collections.unmodifiableList(Lists.transform(asConfigured(this.activeSlots, "activeSlots"), CraftEquipmentSlot::getSlot));
return Collections.unmodifiableList(Lists.transform(asConfigured(this.activeSlots, "activeSlots"), CraftEquipmentSlot::getSlotGroup));
}
@Override

View File

@@ -140,18 +140,6 @@ public final class MCUtil {
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
}
public static Location toLocation(Level world, double x, double y, double z) {
return new Location(world.getWorld(), x, y, z);
}
public static Location toLocation(Level world, BlockPos pos) {
return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ());
}
public static BlockPos toBlockPosition(Location loc) {
return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
public static BlockPos toBlockPos(Position pos) {
return new BlockPos(pos.blockX(), pos.blockY(), pos.blockZ());
}

View File

@@ -11,7 +11,7 @@ import org.checkerframework.framework.qual.DefaultQualifier;
@DefaultQualifier(NonNull.class)
public final class MappingEnvironment {
public static final boolean DISABLE_PLUGIN_REMAPPING = Boolean.getBoolean("paper.disablePluginRemapping");
public static final String LEGACY_CB_VERSION = "v1_21_R3";
public static final String LEGACY_CB_VERSION = "v1_21_R4";
private static final @Nullable String MAPPINGS_HASH = readMappingsHash();
private static final boolean REOBF = checkReobf();

View File

@@ -1,4 +1,4 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import com.google.common.collect.ImmutableMap;
import io.papermc.paper.configuration.GlobalConfiguration;

View File

@@ -1,4 +1,4 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import io.papermc.paper.configuration.GlobalConfiguration;
import java.util.Collections;
@@ -97,8 +97,7 @@ public final class ItemObfuscationBinding {
DataComponents.CAN_PLACE_ON,
DataComponents.CAN_BREAK,
DataComponents.ATTRIBUTE_MODIFIERS,
DataComponents.HIDE_ADDITIONAL_TOOLTIP,
DataComponents.HIDE_TOOLTIP,
DataComponents.TOOLTIP_DISPLAY,
DataComponents.REPAIR_COST,
DataComponents.USE_REMAINDER,
DataComponents.FOOD,

View File

@@ -1,7 +1,8 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import java.util.function.UnaryOperator;
import com.google.common.base.Preconditions;
import io.papermc.paper.util.SafeAutoClosable;
import net.minecraft.world.item.ItemStack;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

View File

@@ -1,5 +1,6 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import io.papermc.paper.util.SafeAutoClosable;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

View File

@@ -1,17 +1,17 @@
package io.papermc.paper.world.flag;
import io.papermc.paper.util.Holderable;
import java.util.Set;
import net.minecraft.world.flag.FeatureElement;
import org.bukkit.FeatureFlag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
public interface PaperFeatureDependent extends FeatureDependant {
<M extends FeatureElement> M getHandle();
@NullMarked
public interface PaperFeatureDependent<M extends FeatureElement> extends FeatureDependant, Holderable<M> {
@Override
default @Unmodifiable @NonNull Set<FeatureFlag> requiredFeatures() {
default @Unmodifiable Set<FeatureFlag> requiredFeatures() {
return PaperFeatureFlagProviderImpl.fromNms(this.getHandle().requiredFeatures());
}
}

View File

@@ -19,10 +19,13 @@ import org.bukkit.potion.PotionType;
public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
public static final BiMap<FeatureFlag, net.minecraft.world.flag.FeatureFlag> FLAGS = ImmutableBiMap.of(
FeatureFlag.VANILLA, FeatureFlags.VANILLA,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
// Start generate - PaperFeatureFlagProviderImpl#FLAGS
// @GeneratedFrom 1.21.5
FeatureFlag.MINECART_IMPROVEMENTS, FeatureFlags.MINECART_IMPROVEMENTS,
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
FeatureFlag.VANILLA, FeatureFlags.VANILLA
// End generate - PaperFeatureFlagProviderImpl#FLAGS
);
@Override

View File

@@ -42,7 +42,6 @@ public class CraftArt extends OldEnumHolderable<Art, PaintingVariant> implements
return this.getHandle().height();
}
// Paper start - Expand Art API
@Override
public Component title() {
return this.getHandle().title().map(PaperAdventure::asAdventure).orElse(null);
@@ -53,10 +52,10 @@ public class CraftArt extends OldEnumHolderable<Art, PaintingVariant> implements
return this.getHandle().author().map(PaperAdventure::asAdventure).orElse(null);
}
@Override
public net.kyori.adventure.key.Key assetId() {
return PaperAdventure.asAdventure(this.getHandle().assetId());
}
// Paper end - Expand Art API
@Override
public int getId() {

View File

@@ -4,25 +4,21 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.mojang.serialization.Codec;
import io.papermc.paper.FeatureHooks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BooleanSupplier;
import java.util.List;
import java.util.function.Predicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.thread.ConsecutiveExecutor;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.ImposterProtoChunk;
@@ -30,9 +26,7 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.PalettedContainerRO;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.storage.EntityStorage;
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.lighting.LevelLightEngine;
@@ -54,7 +48,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin;
public class CraftChunk implements Chunk {
private final ServerLevel worldServer;
private final ServerLevel level;
private final int x;
private final int z;
private static final PalettedContainer<net.minecraft.world.level.block.state.BlockState> emptyBlockIDs = FeatureHooks.emptyPalettedBlockContainer();
@@ -62,20 +56,20 @@ public class CraftChunk implements Chunk {
private static final byte[] EMPTY_LIGHT = new byte[2048];
public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) {
this.worldServer = chunk.level;
this.level = chunk.level;
this.x = chunk.getPos().x;
this.z = chunk.getPos().z;
}
public CraftChunk(ServerLevel worldServer, int x, int z) {
this.worldServer = worldServer;
public CraftChunk(ServerLevel level, int x, int z) {
this.level = level;
this.x = x;
this.z = z;
}
@Override
public World getWorld() {
return this.worldServer.getWorld();
return this.level.getWorld();
}
public CraftWorld getCraftWorld() {
@@ -84,12 +78,12 @@ public class CraftChunk implements Chunk {
public ChunkAccess getHandle(ChunkStatus chunkStatus) {
// Paper start - chunk system
net.minecraft.world.level.chunk.LevelChunk full = this.worldServer.getChunkIfLoaded(this.x, this.z);
net.minecraft.world.level.chunk.LevelChunk full = this.level.getChunkIfLoaded(this.x, this.z);
if (full != null) {
return full;
}
// Paper end - chunk system
ChunkAccess chunkAccess = this.worldServer.getChunk(this.x, this.z, chunkStatus);
ChunkAccess chunkAccess = this.level.getChunk(this.x, this.z, chunkStatus);
// SPIGOT-7332: Get unwrapped extension
if (chunkAccess instanceof ImposterProtoChunk extension) {
@@ -116,9 +110,9 @@ public class CraftChunk implements Chunk {
@Override
public Block getBlock(int x, int y, int z) {
CraftChunk.validateChunkCoordinates(this.worldServer.getMinY(), this.worldServer.getMaxY(), x, y, z);
CraftChunk.validateChunkCoordinates(this.level.getMinY(), this.level.getMaxY(), x, y, z);
return new CraftBlock(this.worldServer, new BlockPos((this.x << 4) | x, y, (this.z << 4) | z));
return new CraftBlock(this.level, new BlockPos((this.x << 4) | x, y, (this.z << 4) | z));
}
@Override
@@ -128,53 +122,49 @@ public class CraftChunk implements Chunk {
@Override
public Entity[] getEntities() {
return FeatureHooks.getChunkEntities(this.worldServer, this.x, this.z); // Paper - chunk system
return FeatureHooks.getChunkEntities(this.level, this.x, this.z); // Paper - chunk system
}
@Override
public BlockState[] getTileEntities() {
// Paper start
return getTileEntities(true);
return this.getTileEntities(true);
}
@Override
public BlockState[] getTileEntities(boolean useSnapshot) {
// Paper end
if (!this.isLoaded()) {
this.getWorld().getChunkAt(this.x, this.z); // Transient load for this tick
}
int index = 0;
ChunkAccess chunk = this.getHandle(ChunkStatus.FULL);
BlockState[] entities = new BlockState[chunk.blockEntities.size()];
for (BlockPos position : chunk.blockEntities.keySet()) {
// Paper start
entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot);
BlockState[] states = new BlockState[chunk.blockEntities.size()];
for (BlockPos pos : chunk.blockEntities.keySet()) {
states[index++] = CraftBlock.at(this.level, pos).getState(useSnapshot);
}
return entities;
return states;
}
@Override
public Collection<BlockState> getTileEntities(Predicate<? super Block> blockPredicate, boolean useSnapshot) {
Preconditions.checkNotNull(blockPredicate, "blockPredicate");
Preconditions.checkArgument(blockPredicate != null, "blockPredicate cannot be null");
if (!this.isLoaded()) {
this.getWorld().getChunkAt(this.x, this.z); // Transient load for this tick
}
ChunkAccess chunk = this.getHandle(ChunkStatus.FULL);
java.util.List<BlockState> entities = new java.util.ArrayList<>();
for (BlockPos position : chunk.blockEntities.keySet()) {
Block block = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ());
List<BlockState> states = new ArrayList<>();
for (BlockPos pos : chunk.blockEntities.keySet()) {
Block block = CraftBlock.at(this.level, pos);
if (blockPredicate.test(block)) {
entities.add(block.getState(useSnapshot));
states.add(block.getState(useSnapshot));
}
// Paper end
}
return entities;
return states;
}
@Override
@@ -205,8 +195,8 @@ public class CraftChunk implements Chunk {
@Override
public boolean isSlimeChunk() {
// 987234911L is deterimined in EntitySlime when seeing if a slime can spawn in a chunk
return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
// 987234911L is taken from Slime when seeing if a slime can spawn in a chunk
return this.level.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), level.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
}
@Override
@@ -255,9 +245,9 @@ public class CraftChunk implements Chunk {
public boolean contains(BlockData block) {
Preconditions.checkArgument(block != null, "Block cannot be null");
Predicate<net.minecraft.world.level.block.state.BlockState> nms = Predicates.equalTo(((CraftBlockData) block).getState());
Predicate<net.minecraft.world.level.block.state.BlockState> filter = Predicates.equalTo(((CraftBlockData) block).getState());
for (LevelChunkSection section : this.getHandle(ChunkStatus.FULL).getSections()) {
if (section != null && section.getStates().maybeHas(nms)) {
if (section != null && section.getStates().maybeHas(filter)) {
return true;
}
}
@@ -270,9 +260,9 @@ public class CraftChunk implements Chunk {
Preconditions.checkArgument(biome != null, "Biome cannot be null");
ChunkAccess chunk = this.getHandle(ChunkStatus.BIOMES);
Predicate<Holder<net.minecraft.world.level.biome.Biome>> nms = Predicates.equalTo(CraftBiome.bukkitToMinecraftHolder(biome));
Predicate<Holder<net.minecraft.world.level.biome.Biome>> filter = Predicates.equalTo(CraftBiome.bukkitToMinecraftHolder(biome));
for (LevelChunkSection section : chunk.getSections()) {
if (section != null && section.getBiomes().maybeHas(nms)) {
if (section != null && section.getBiomes().maybeHas(filter)) {
return true;
}
}
@@ -287,26 +277,20 @@ public class CraftChunk implements Chunk {
@Override
public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain) {
// Paper start - Add getChunkSnapshot includeLightData parameter
return getChunkSnapshot(includeMaxBlockY, includeBiome, includeBiomeTempRain, true);
}
@Override
public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain, boolean includeLightData) {
// Paper end - Add getChunkSnapshot includeLightData parameter
ChunkAccess chunk = this.getHandle(ChunkStatus.FULL);
LevelChunkSection[] cs = chunk.getSections();
PalettedContainer[] sectionBlockIDs = new PalettedContainer[cs.length];
// Paper start - Add getChunkSnapshot includeLightData parameter
byte[][] sectionSkyLights = includeLightData ? new byte[cs.length][] : null;
byte[][] sectionEmitLights = includeLightData ? new byte[cs.length][] : null;
// Paper end - Add getChunkSnapshot includeLightData parameter
boolean[] sectionEmpty = new boolean[cs.length];
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
Registry<net.minecraft.world.level.biome.Biome> iregistry = this.worldServer.registryAccess().lookupOrThrow(Registries.BIOME);
for (int i = 0; i < cs.length; i++) {
// Paper start - Fix ChunkSnapshot#isSectionEmpty(int); and remove codec usage
@@ -318,38 +302,39 @@ public class CraftChunk implements Chunk {
}
// Paper end - Fix ChunkSnapshot#isSectionEmpty(int)
if (includeLightData) { // Paper - Add getChunkSnapshot includeLightData parameter
LevelLightEngine lightengine = this.worldServer.getLightEngine();
DataLayer skyLightArray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
if (skyLightArray == null) {
sectionSkyLights[i] = this.worldServer.dimensionType().hasSkyLight() ? CraftChunk.FULL_LIGHT : CraftChunk.EMPTY_LIGHT;
} else {
sectionSkyLights[i] = new byte[2048];
System.arraycopy(skyLightArray.getData(), 0, sectionSkyLights[i], 0, 2048);
if (includeLightData) {
LevelLightEngine lightEngine = this.level.getLightEngine();
DataLayer skyLightArray = lightEngine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
if (skyLightArray == null) {
sectionSkyLights[i] = this.level.dimensionType().hasSkyLight() ? CraftChunk.FULL_LIGHT : CraftChunk.EMPTY_LIGHT;
} else {
sectionSkyLights[i] = new byte[2048];
System.arraycopy(skyLightArray.getData(), 0, sectionSkyLights[i], 0, 2048);
}
DataLayer emitLightArray = lightEngine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
if (emitLightArray == null) {
sectionEmitLights[i] = CraftChunk.EMPTY_LIGHT;
} else {
sectionEmitLights[i] = new byte[2048];
System.arraycopy(emitLightArray.getData(), 0, sectionEmitLights[i], 0, 2048);
}
}
DataLayer emitLightArray = lightengine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
if (emitLightArray == null) {
sectionEmitLights[i] = CraftChunk.EMPTY_LIGHT;
} else {
sectionEmitLights[i] = new byte[2048];
System.arraycopy(emitLightArray.getData(), 0, sectionEmitLights[i], 0, 2048);
}
} // Paper - Add getChunkSnapshot includeLightData parameter
if (biome != null) {
biome[i] = ((PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>) cs[i].getBiomes()).copy(); // Paper - Perf: use copy instead of round tripping with codecs
biome[i] = cs[i].getBiomes().copy(); // Paper - Perf: use copy instead of round tripping with codecs
}
}
Heightmap hmap = null;
Heightmap heightmap = null;
if (includeMaxBlockY) {
hmap = new Heightmap(chunk, Heightmap.Types.MOTION_BLOCKING);
hmap.setRawData(chunk, Heightmap.Types.MOTION_BLOCKING, chunk.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).getRawData());
heightmap = new Heightmap(chunk, Heightmap.Types.MOTION_BLOCKING);
heightmap.setRawData(chunk, Heightmap.Types.MOTION_BLOCKING, chunk.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).getRawData());
}
World world = this.getWorld();
return new CraftChunkSnapshot(this.getX(), this.getZ(), chunk.getMinY(), chunk.getMaxY(), world.getSeaLevel(), world.getName(), world.getFullTime(), sectionBlockIDs, sectionSkyLights, sectionEmitLights, sectionEmpty, hmap, iregistry, biome);
return new CraftChunkSnapshot(this.getX(), this.getZ(), chunk.getMinY(), chunk.getMaxY(), world.getSeaLevel(), world.getName(), world.getFullTime(), sectionBlockIDs, sectionSkyLights, sectionEmitLights, sectionEmpty, heightmap, biome);
}
@Override
@@ -359,7 +344,7 @@ public class CraftChunk implements Chunk {
@Override
public LoadLevel getLoadLevel() {
net.minecraft.world.level.chunk.LevelChunk chunk = this.worldServer.getChunkIfLoaded(this.getX(), this.getZ());
net.minecraft.world.level.chunk.LevelChunk chunk = this.level.getChunkIfLoaded(this.getX(), this.getZ());
if (chunk == null) {
return LoadLevel.UNLOADED;
}
@@ -390,12 +375,12 @@ public class CraftChunk implements Chunk {
if (this.x != that.x) return false;
if (this.z != that.z) return false;
return this.worldServer.equals(that.worldServer);
return this.level.equals(that.level);
}
@Override
public int hashCode() {
int result = this.worldServer.hashCode();
int result = this.level.hashCode();
result = 31 * result + this.x;
result = 31 * result + this.z;
return result;
@@ -410,9 +395,9 @@ public class CraftChunk implements Chunk {
byte[][] skyLight = new byte[hSection][];
byte[][] emitLight = new byte[hSection][];
boolean[] empty = new boolean[hSection];
Registry<net.minecraft.world.level.biome.Biome> iregistry = world.getHandle().registryAccess().lookupOrThrow(Registries.BIOME);
Registry<net.minecraft.world.level.biome.Biome> registry = world.getHandle().registryAccess().lookupOrThrow(Registries.BIOME);
PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[hSection] : null;
Codec<PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>> biomeCodec = PalettedContainer.codecRO(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
Codec<PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>> biomeCodec = PalettedContainer.codecRO(registry.asHolderIdMap(), registry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, registry.getOrThrow(Biomes.PLAINS));
for (int i = 0; i < hSection; i++) {
blockIDs[i] = CraftChunk.emptyBlockIDs;
@@ -425,7 +410,7 @@ public class CraftChunk implements Chunk {
}
}
return new CraftChunkSnapshot(x, z, world.getMinHeight(), world.getMaxY(), world.getSeaLevel(), world.getName(), world.getFullTime(), blockIDs, skyLight, emitLight, empty, new Heightmap(actual, Heightmap.Types.MOTION_BLOCKING), iregistry, biome);
return new CraftChunkSnapshot(x, z, world.getMinHeight(), world.getMaxY(), world.getSeaLevel(), world.getName(), world.getFullTime(), blockIDs, skyLight, emitLight, empty, new Heightmap(actual, Heightmap.Types.MOTION_BLOCKING), biome);
}
static void validateChunkCoordinates(int minY, int maxY, int x, int y, int z) {

View File

@@ -5,7 +5,6 @@ import com.google.common.base.Predicates;
import java.util.function.Predicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.PalettedContainerRO;
@@ -15,7 +14,6 @@ import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
@@ -26,30 +24,28 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers;
public class CraftChunkSnapshot implements ChunkSnapshot {
private final int x, z;
private final int minHeight, maxHeight, seaLevel;
private final String worldname;
private final PalettedContainer<BlockState>[] blockids;
private final String worldName;
private final PalettedContainer<BlockState>[] blockIds;
private final byte[][] skylight;
private final byte[][] emitlight;
private final byte[][] emitLight;
private final boolean[] empty;
private final Heightmap hmap; // Height map
private final long captureFulltime;
private final Registry<net.minecraft.world.level.biome.Biome> biomeRegistry;
private final Heightmap heightmap; // Height map
private final long captureFullTime;
private final PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome;
CraftChunkSnapshot(int x, int z, int minHeight, int maxHeight, int seaLevel, String wname, long wtime, PalettedContainer<BlockState>[] sectionBlockIDs, byte[][] sectionSkyLights, byte[][] sectionEmitLights, boolean[] sectionEmpty, Heightmap hmap, Registry<net.minecraft.world.level.biome.Biome> biomeRegistry, PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome) {
CraftChunkSnapshot(int x, int z, int minHeight, int maxHeight, int seaLevel, String worldName, long fullTime, PalettedContainer<BlockState>[] sectionBlockIDs, byte[][] sectionSkyLights, byte[][] sectionEmitLights, boolean[] sectionEmpty, Heightmap heightmap, PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome) {
this.x = x;
this.z = z;
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.seaLevel = seaLevel;
this.worldname = wname;
this.captureFulltime = wtime;
this.blockids = sectionBlockIDs;
this.worldName = worldName;
this.captureFullTime = fullTime;
this.blockIds = sectionBlockIDs;
this.skylight = sectionSkyLights;
this.emitlight = sectionEmitLights;
this.emitLight = sectionEmitLights;
this.empty = sectionEmpty;
this.hmap = hmap;
this.biomeRegistry = biomeRegistry;
this.heightmap = heightmap;
this.biome = biome;
}
@@ -65,16 +61,16 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
@Override
public String getWorldName() {
return this.worldname;
return this.worldName;
}
@Override
public boolean contains(BlockData block) {
Preconditions.checkArgument(block != null, "Block cannot be null");
Predicate<BlockState> nms = Predicates.equalTo(((CraftBlockData) block).getState());
for (PalettedContainer<BlockState> palette : this.blockids) {
if (palette.maybeHas(nms)) {
Predicate<BlockState> filter = Predicates.equalTo(((CraftBlockData) block).getState());
for (PalettedContainer<BlockState> palette : this.blockIds) {
if (palette.maybeHas(filter)) {
return true;
}
}
@@ -86,9 +82,9 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public boolean contains(Biome biome) {
Preconditions.checkArgument(biome != null, "Biome cannot be null");
Predicate<Holder<net.minecraft.world.level.biome.Biome>> nms = Predicates.equalTo(CraftBiome.bukkitToMinecraftHolder(biome));
Predicate<Holder<net.minecraft.world.level.biome.Biome>> filter = Predicates.equalTo(CraftBiome.bukkitToMinecraftHolder(biome));
for (PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>> palette : this.biome) {
if (palette.maybeHas(nms)) {
if (palette.maybeHas(filter)) {
return true;
}
}
@@ -100,21 +96,21 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public Material getBlockType(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls
return this.blockIds[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise get calls
}
@Override
public final BlockData getBlockData(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
return CraftBlockData.fromData(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z));
return CraftBlockData.fromData(this.blockIds[this.getSectionIndex(y)].get(x, y & 0xF, z));
}
@Override
public final int getData(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
return CraftMagicNumbers.toLegacyData(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z));
return CraftMagicNumbers.toLegacyData(this.blockIds[this.getSectionIndex(y)].get(x, y & 0xF, z));
}
@Override
@@ -128,19 +124,19 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
@Override
public final int getBlockEmittedLight(int x, int y, int z) {
Preconditions.checkState(this.emitlight != null, "ChunkSnapshot created without light data. Please call getSnapshot with includeLightData=true"); // Paper - Add getChunkSnapshot includeLightData parameter
Preconditions.checkState(this.emitLight != null, "ChunkSnapshot created without light data. Please call getSnapshot with includeLightData=true"); // Paper - Add getChunkSnapshot includeLightData parameter
this.validateChunkCoordinates(x, y, z);
int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1);
return (this.emitlight[this.getSectionIndex(y)][off] >> ((x & 1) << 2)) & 0xF;
return (this.emitLight[this.getSectionIndex(y)][off] >> ((x & 1) << 2)) & 0xF;
}
@Override
public final int getHighestBlockYAt(int x, int z) {
Preconditions.checkState(this.hmap != null, "ChunkSnapshot created without height map. Please call getSnapshot with includeMaxblocky=true");
Preconditions.checkState(this.heightmap != null, "ChunkSnapshot created without height map. Please call getSnapshot with includeMaxblocky=true");
this.validateChunkCoordinates(x, 0, z);
return this.hmap.getHighestTaken(x, z);
return this.heightmap.getHighestTaken(x, z);
}
@Override
@@ -173,7 +169,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
@Override
public final long getCaptureFullTime() {
return this.captureFulltime;
return this.captureFullTime;
}
@Override

View File

@@ -18,10 +18,10 @@ public class CraftCrashReport implements Supplier<String> {
@Override
public String get() {
final io.papermc.paper.ServerBuildInfo build = io.papermc.paper.ServerBuildInfo.buildInfo(); // Paper
final io.papermc.paper.ServerBuildInfo build = io.papermc.paper.ServerBuildInfo.buildInfo();
StringWriter value = new StringWriter();
try {
value.append("\n BrandInfo: ").append(String.format("%s (%s) version %s", build.brandName(), build.brandId(), build.asString(io.papermc.paper.ServerBuildInfo.StringRepresentation.VERSION_FULL))); // Paper
value.append("\n BrandInfo: ").append(String.format("%s (%s) version %s", build.brandName(), build.brandId(), build.asString(io.papermc.paper.ServerBuildInfo.StringRepresentation.VERSION_FULL)));
value.append("\n Running: ").append(Bukkit.getName()).append(" version ").append(Bukkit.getVersion()).append(" (Implementing API version ").append(Bukkit.getBukkitVersion()).append(") ").append(String.valueOf(MinecraftServer.getServer().usesAuthentication()));
value.append("\n Plugins: {");
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {

View File

@@ -1,54 +1,55 @@
package org.bukkit.craftbukkit;
import java.util.Locale;
import com.google.common.collect.BiMap;
import com.google.common.collect.EnumBiMap;
import net.minecraft.Util;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EquipmentSlotGroup;
import org.bukkit.inventory.EquipmentSlot;
public class CraftEquipmentSlot {
public final class CraftEquipmentSlot {
private static final net.minecraft.world.entity.EquipmentSlot[] slots = new net.minecraft.world.entity.EquipmentSlot[EquipmentSlot.values().length];
private static final EquipmentSlot[] enums = new EquipmentSlot[net.minecraft.world.entity.EquipmentSlot.values().length];
static {
set(EquipmentSlot.HAND, net.minecraft.world.entity.EquipmentSlot.MAINHAND);
set(EquipmentSlot.OFF_HAND, net.minecraft.world.entity.EquipmentSlot.OFFHAND);
set(EquipmentSlot.FEET, net.minecraft.world.entity.EquipmentSlot.FEET);
set(EquipmentSlot.LEGS, net.minecraft.world.entity.EquipmentSlot.LEGS);
set(EquipmentSlot.CHEST, net.minecraft.world.entity.EquipmentSlot.CHEST);
set(EquipmentSlot.HEAD, net.minecraft.world.entity.EquipmentSlot.HEAD);
set(EquipmentSlot.BODY, net.minecraft.world.entity.EquipmentSlot.BODY);
private CraftEquipmentSlot() {
}
private static void set(EquipmentSlot type, net.minecraft.world.entity.EquipmentSlot value) {
CraftEquipmentSlot.slots[type.ordinal()] = value;
CraftEquipmentSlot.enums[value.ordinal()] = type;
private static final BiMap<net.minecraft.world.entity.EquipmentSlot, EquipmentSlot> BRIDGE =
Util.make(EnumBiMap.create(net.minecraft.world.entity.EquipmentSlot.class, EquipmentSlot.class), data -> {
data.put(net.minecraft.world.entity.EquipmentSlot.MAINHAND, EquipmentSlot.HAND);
data.put(net.minecraft.world.entity.EquipmentSlot.OFFHAND, EquipmentSlot.OFF_HAND);
data.put(net.minecraft.world.entity.EquipmentSlot.FEET, EquipmentSlot.FEET);
data.put(net.minecraft.world.entity.EquipmentSlot.LEGS, EquipmentSlot.LEGS);
data.put(net.minecraft.world.entity.EquipmentSlot.CHEST, EquipmentSlot.CHEST);
data.put(net.minecraft.world.entity.EquipmentSlot.HEAD, EquipmentSlot.HEAD);
data.put(net.minecraft.world.entity.EquipmentSlot.BODY, EquipmentSlot.BODY);
data.put(net.minecraft.world.entity.EquipmentSlot.SADDLE, EquipmentSlot.SADDLE);
});
public static EquipmentSlot getSlot(net.minecraft.world.entity.EquipmentSlot slot) {
return BRIDGE.get(slot);
}
public static EquipmentSlot getSlot(net.minecraft.world.entity.EquipmentSlot nms) {
return CraftEquipmentSlot.enums[nms.ordinal()];
}
public static org.bukkit.inventory.EquipmentSlotGroup getSlot(EquipmentSlotGroup nms) {
return org.bukkit.inventory.EquipmentSlotGroup.getByName(nms.getSerializedName());
public static org.bukkit.inventory.EquipmentSlotGroup getSlotGroup(EquipmentSlotGroup slotGroup) {
return org.bukkit.inventory.EquipmentSlotGroup.getByName(slotGroup.getSerializedName());
}
public static net.minecraft.world.entity.EquipmentSlot getNMS(EquipmentSlot slot) {
return CraftEquipmentSlot.slots[slot.ordinal()];
return BRIDGE.inverse().get(slot);
}
public static EquipmentSlotGroup getNMSGroup(org.bukkit.inventory.EquipmentSlotGroup slot) {
return EquipmentSlotGroup.valueOf(slot.toString().toUpperCase(Locale.ROOT));
}
public static EquipmentSlot getHand(InteractionHand enumhand) {
return (enumhand == InteractionHand.MAIN_HAND) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND;
public static EquipmentSlot getHand(InteractionHand hand) {
return hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND;
}
public static InteractionHand getHand(EquipmentSlot hand) {
if (hand == EquipmentSlot.HAND) {
return InteractionHand.MAIN_HAND;
} else if (hand == EquipmentSlot.OFF_HAND) {
}
if (hand == EquipmentSlot.OFF_HAND) {
return InteractionHand.OFF_HAND;
}

View File

@@ -8,20 +8,14 @@ public final class CraftExplosionResult {
private CraftExplosionResult() {}
public static ExplosionResult toBukkit(Explosion.BlockInteraction effect) {
public static ExplosionResult toExplosionResult(Explosion.BlockInteraction effect) {
Preconditions.checkArgument(effect != null, "explosion effect cannot be null");
switch (effect) {
case KEEP:
return ExplosionResult.KEEP;
case DESTROY:
return ExplosionResult.DESTROY;
case DESTROY_WITH_DECAY:
return ExplosionResult.DESTROY_WITH_DECAY;
case TRIGGER_BLOCK:
return ExplosionResult.TRIGGER_BLOCK;
default:
throw new IllegalArgumentException("There is no ExplosionResult which matches " + effect);
}
return switch (effect) {
case KEEP -> ExplosionResult.KEEP;
case DESTROY -> ExplosionResult.DESTROY;
case DESTROY_WITH_DECAY -> ExplosionResult.DESTROY_WITH_DECAY;
case TRIGGER_BLOCK -> ExplosionResult.TRIGGER_BLOCK;
};
}
}

View File

@@ -1,13 +1,13 @@
package org.bukkit.craftbukkit;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.Fluid;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
public class CraftFluid implements Fluid, Handleable<net.minecraft.world.level.material.Fluid> {
@NullMarked
public class CraftFluid extends OldEnumHolderable<Fluid, net.minecraft.world.level.material.Fluid> implements Fluid {
private static int count = 0;
@@ -19,74 +19,7 @@ public class CraftFluid implements Fluid, Handleable<net.minecraft.world.level.m
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final net.minecraft.world.level.material.Fluid fluidType;
private final String name;
private final int ordinal;
public CraftFluid(NamespacedKey key, net.minecraft.world.level.material.Fluid fluidType) {
this.key = key;
this.fluidType = fluidType;
// For backwards compatibility, minecraft values will stile return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive fluid specific values.
// Custom fluids will return the key with namespace. For a plugin this should look than like a new fluid
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftFluid.count++;
}
@Override
public net.minecraft.world.level.material.Fluid getHandle() {
return this.fluidType;
}
@NotNull
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(@NotNull Fluid fluid) {
return this.ordinal - fluid.ordinal();
}
@NotNull
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftFluid otherFluid)) {
return false;
}
return this.getKey().equals(otherFluid.getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftFluid(final Holder<net.minecraft.world.level.material.Fluid> holder) {
super(holder, count++);
}
}

View File

@@ -7,18 +7,13 @@ public final class CraftFluidCollisionMode {
private CraftFluidCollisionMode() {}
public static Fluid toNMS(FluidCollisionMode fluidCollisionMode) {
public static Fluid toFluid(FluidCollisionMode fluidCollisionMode) {
if (fluidCollisionMode == null) return null;
switch (fluidCollisionMode) {
case ALWAYS:
return Fluid.ANY;
case SOURCE_ONLY:
return Fluid.SOURCE_ONLY;
case NEVER:
return Fluid.NONE;
default:
return null;
}
return switch (fluidCollisionMode) {
case ALWAYS -> Fluid.ANY;
case SOURCE_ONLY -> Fluid.SOURCE_ONLY;
case NEVER -> Fluid.NONE;
};
}
}

View File

@@ -31,7 +31,6 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
return this.handle;
}
// Paper start
@Override
public int getRange() {
return this.handle.notificationRadius();
@@ -41,7 +40,6 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
public int getVibrationLevel() {
return net.minecraft.world.level.gameevent.vibrations.VibrationSystem.getGameEventFrequency(this.handleKey);
}
// Paper end
@NotNull
@Override

View File

@@ -8,40 +8,25 @@ public final class CraftHeightMap {
}
public static net.minecraft.world.level.levelgen.Heightmap.Types toNMS(HeightMap bukkitHeightMap) {
switch (bukkitHeightMap) {
case MOTION_BLOCKING_NO_LEAVES:
return net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES;
case OCEAN_FLOOR:
return net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR;
case OCEAN_FLOOR_WG:
return net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR_WG;
case WORLD_SURFACE:
return net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE;
case WORLD_SURFACE_WG:
return net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE_WG;
case MOTION_BLOCKING:
return net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING;
default:
throw new EnumConstantNotPresentException(net.minecraft.world.level.levelgen.Heightmap.Types.class, bukkitHeightMap.name());
}
return switch (bukkitHeightMap) {
case MOTION_BLOCKING_NO_LEAVES ->
net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES;
case OCEAN_FLOOR -> net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR;
case OCEAN_FLOOR_WG -> net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR_WG;
case WORLD_SURFACE -> net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE;
case WORLD_SURFACE_WG -> net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE_WG;
case MOTION_BLOCKING -> net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING;
};
}
public static HeightMap fromNMS(net.minecraft.world.level.levelgen.Heightmap.Types nmsHeightMapType) {
switch (nmsHeightMapType) {
case WORLD_SURFACE_WG:
return HeightMap.WORLD_SURFACE_WG;
case WORLD_SURFACE:
return HeightMap.WORLD_SURFACE;
case OCEAN_FLOOR_WG:
return HeightMap.OCEAN_FLOOR_WG;
case OCEAN_FLOOR:
return HeightMap.OCEAN_FLOOR;
case MOTION_BLOCKING_NO_LEAVES:
return HeightMap.MOTION_BLOCKING_NO_LEAVES;
case MOTION_BLOCKING:
return HeightMap.MOTION_BLOCKING;
default:
throw new EnumConstantNotPresentException(HeightMap.class, nmsHeightMapType.name());
}
return switch (nmsHeightMapType) {
case WORLD_SURFACE_WG -> HeightMap.WORLD_SURFACE_WG;
case WORLD_SURFACE -> HeightMap.WORLD_SURFACE;
case OCEAN_FLOOR_WG -> HeightMap.OCEAN_FLOOR_WG;
case OCEAN_FLOOR -> HeightMap.OCEAN_FLOOR;
case MOTION_BLOCKING_NO_LEAVES -> HeightMap.MOTION_BLOCKING_NO_LEAVES;
case MOTION_BLOCKING -> HeightMap.MOTION_BLOCKING;
};
}
}

View File

@@ -1,55 +1,54 @@
package org.bukkit.craftbukkit;
import java.util.Objects;
import org.bukkit.Input;
public class CraftInput implements Input {
private final net.minecraft.world.entity.player.Input handle;
private final net.minecraft.world.entity.player.Input input;
public CraftInput(net.minecraft.world.entity.player.Input handle) {
this.handle = handle;
public CraftInput(net.minecraft.world.entity.player.Input input) {
this.input = input;
}
@Override
public boolean isForward() {
return this.handle.forward();
return this.input.forward();
}
@Override
public boolean isBackward() {
return this.handle.backward();
return this.input.backward();
}
@Override
public boolean isLeft() {
return this.handle.left();
return this.input.left();
}
@Override
public boolean isRight() {
return this.handle.right();
return this.input.right();
}
@Override
public boolean isJump() {
return this.handle.jump();
return this.input.jump();
}
@Override
public boolean isSneak() {
return this.handle.shift();
return this.input.shift();
}
@Override
public boolean isSprint() {
return this.handle.sprint();
return this.input.sprint();
}
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + Objects.hashCode(this.handle);
hash = 89 * hash + this.input.hashCode();
return hash;
}
@@ -58,18 +57,16 @@ public class CraftInput implements Input {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
final CraftInput other = (CraftInput) obj;
return Objects.equals(this.handle, other.handle);
return this.input.equals(other.input);
}
@Override
public String toString() {
return "CraftInput{" + this.handle + '}';
return "CraftInput{" + this.input + '}';
}
}

View File

@@ -107,7 +107,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
ServerLevel handle = ((CraftWorld) loc.getWorld()).getHandle();
LootParams.Builder builder = new LootParams.Builder(handle);
this.setMaybe(builder, LootContextParams.ORIGIN, CraftLocation.toVec3D(loc));
this.setMaybe(builder, LootContextParams.ORIGIN, CraftLocation.toVec3(loc));
if (this.getHandle() != LootTable.EMPTY) {
builder.withLuck(context.getLuck());
@@ -128,7 +128,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
}
}
// SPIGOT-5603 - Avoid IllegalArgumentException in LootTableInfo#build()
// SPIGOT-5603 - Avoid IllegalArgumentException in ContextKeySet.Builder#create
ContextKeySet.Builder nmsBuilder = new ContextKeySet.Builder();
for (ContextKey<?> param : this.getHandle().getParamSet().required()) {
nmsBuilder.required(param);
@@ -151,7 +151,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
public static LootContext convertContext(net.minecraft.world.level.storage.loot.LootContext info) {
Vec3 position = info.getOptionalParameter(LootContextParams.ORIGIN);
if (position == null) {
position = info.getOptionalParameter(LootContextParams.THIS_ENTITY).position(); // Every vanilla context has origin or this_entity, see LootContextParameterSets
position = info.getOptionalParameter(LootContextParams.THIS_ENTITY).position(); // Every vanilla context has origin or this_entity, see LootContextParamSets
}
Location location = CraftLocation.toBukkit(position, info.getLevel().getWorld());
LootContext.Builder contextBuilder = new LootContext.Builder(location);
@@ -173,7 +173,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
@Override
public String toString() {
return this.getKey().toString();
return this.key.toString();
}
@Override
@@ -183,13 +183,11 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
}
org.bukkit.loot.LootTable table = (org.bukkit.loot.LootTable) obj;
return table.getKey().equals(this.getKey());
return table.getKey().equals(this.key);
}
// Paper start - satisfy equals/hashCode contract
@Override
public int hashCode() {
return java.util.Objects.hash(key);
return this.key.hashCode();
}
// Paper end
}

View File

@@ -41,7 +41,6 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc.
return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(string, Instrument.CODEC, RegistryKey.INSTRUMENT); // Paper - switch to Holder
}
// Paper start - switch to Holder
@Override
public boolean equals(final Object o) {
return this.implEquals(o);
@@ -58,9 +57,9 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc.
}
private final Holder<Instrument> holder;
public CraftMusicInstrument(Holder<Instrument> holder) {
this.holder = holder;
// Paper end - switch to Holder
}
@Override
@@ -74,7 +73,6 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc.
return Holderable.super.getKey();
}
// Paper start - add translationKey methods
@Override
public @NotNull String translationKey() {
if (!(this.getHandle().description().getContents() instanceof final net.minecraft.network.chat.contents.TranslatableContents translatableContents)) {
@@ -82,7 +80,4 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc.
}
return translatableContents.getKey();
}
// Paper end - add translationKey methods
// Paper - switch to Holder
}

View File

@@ -11,11 +11,13 @@ import java.util.Map;
import java.util.UUID;
import net.minecraft.core.GlobalPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
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.world.level.storage.PlayerDataStorage;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.bukkit.BanEntry;
import org.bukkit.BanList;
import org.bukkit.Bukkit;
@@ -24,20 +26,18 @@ import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.Statistic;
import org.bukkit.World;
import org.bukkit.ban.ProfileBanList;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.profile.PlayerProfile;
@SerializableAs("Player")
public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializable {
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
private final GameProfile profile;
private final CraftServer server;
private final PlayerDataStorage storage;
@@ -46,7 +46,6 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
this.server = server;
this.profile = profile;
this.storage = server.console.playerDataStorage;
}
@Override
@@ -54,12 +53,10 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
return this.getPlayer() != null;
}
// Paper start
@Override
public boolean isConnected() {
return false;
}
// Paper end
@Override
public String getName() {
@@ -76,9 +73,7 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
CompoundTag data = this.getBukkitData();
if (data != null) {
if (data.contains("lastKnownName")) {
return data.getString("lastKnownName");
}
return data.getString("lastKnownName").orElse(null);
}
return null;
@@ -192,17 +187,14 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
return false;
}
if ((this.getUniqueId() == null) || (other.getUniqueId() == null)) {
return false;
}
return this.getUniqueId().equals(other.getUniqueId());
}
@Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + (this.getUniqueId() != null ? this.getUniqueId().hashCode() : 0);
hash = 97 * hash + this.getUniqueId().hashCode();
return hash;
}
@@ -214,10 +206,7 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
CompoundTag result = this.getData();
if (result != null) {
if (!result.contains("bukkit")) {
result.put("bukkit", new CompoundTag());
}
result = result.getCompound("bukkit");
result = result.getCompound("bukkit").orElse(null);
}
return result;
@@ -235,12 +224,10 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
CompoundTag data = this.getBukkitData();
if (data != null) {
if (data.contains("firstPlayed")) {
return data.getLong("firstPlayed");
} else {
return data.getLong("firstPlayed").orElseGet(() -> {
File file = this.getDataFile();
return file.lastModified();
}
});
} else {
return 0;
}
@@ -254,12 +241,10 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
CompoundTag data = this.getBukkitData();
if (data != null) {
if (data.contains("lastPlayed")) {
return data.getLong("lastPlayed");
} else {
return data.getLong("lastPlayed").orElseGet(() -> {
File file = this.getDataFile();
return file.lastModified();
}
});
} else {
return 0;
}
@@ -270,22 +255,19 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
return this.getData() != null;
}
// Paper start
@Override
public long getLastLogin() {
Player player = getPlayer();
Player player = this.getPlayer();
if (player != null) return player.getLastLogin();
CompoundTag data = getPaperData();
CompoundTag data = this.getPaperData();
if (data != null) {
if (data.contains("LastLogin")) {
return data.getLong("LastLogin");
} else {
return data.getLong("LastLogin").orElseGet(() -> {
// if the player file cannot provide accurate data, this is probably the closest we can approximate
File file = getDataFile();
return file.lastModified();
}
});
} else {
return 0;
}
@@ -293,39 +275,32 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
@Override
public long getLastSeen() {
Player player = getPlayer();
Player player = this.getPlayer();
if (player != null) return player.getLastSeen();
CompoundTag data = getPaperData();
CompoundTag data = this.getPaperData();
if (data != null) {
if (data.contains("LastSeen")) {
return data.getLong("LastSeen");
} else {
return data.getLong("LastSeen").orElseGet(() -> {
// if the player file cannot provide accurate data, this is probably the closest we can approximate
File file = getDataFile();
return file.lastModified();
}
});
} else {
return 0;
}
}
private CompoundTag getPaperData() {
CompoundTag result = getData();
CompoundTag result = this.getData();
if (result != null) {
if (!result.contains("Paper")) {
result.put("Paper", new CompoundTag());
}
result = result.getCompound("Paper");
result = result.getCompound("Paper").orElse(null);
}
return result;
}
// Paper end
// Paper start - Add Offline PDC API
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
private io.papermc.paper.persistence.@org.checkerframework.checker.nullness.qual.MonotonicNonNull PersistentDataContainerView persistentDataContainerView;
@@ -335,7 +310,7 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
this.persistentDataContainerView = new io.papermc.paper.persistence.PaperPersistentDataContainerView(DATA_TYPE_REGISTRY) {
private CompoundTag getPersistentTag() {
return net.minecraft.Optionull.map(CraftOfflinePlayer.this.getData(), data -> data.getCompound("BukkitValues"));
return net.minecraft.Optionull.map(CraftOfflinePlayer.this.getData(), data -> data.getCompound("BukkitValues").orElse(null));
}
@Override
@@ -351,14 +326,15 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
}
return this.persistentDataContainerView;
}
// Paper end - Add Offline PDC API
@Override
public Location getLastDeathLocation() {
if (this.getData().contains("LastDeathLocation", 10)) {
return GlobalPos.CODEC.parse(NbtOps.INSTANCE, this.getData().get("LastDeathLocation")).result().map(CraftMemoryMapper::fromNms).orElse(null);
CompoundTag data = this.getData();
if (data == null) {
return null;
}
return null;
return data.read("LastDeathLocation", GlobalPos.CODEC).map(CraftLocation::fromGlobalPos).orElse(null);
}
@Override
@@ -368,69 +344,38 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
return null;
}
if (data.contains("Pos") && data.contains("Rotation")) {
ListTag position = (ListTag) data.get("Pos");
ListTag rotation = (ListTag) data.get("Rotation");
Vec3 pos = data.read("Pos", Vec3.CODEC).orElse(null);
Vec2 rot = data.read("Rotation", Vec2.CODEC).orElse(null);
if (pos != null && rot != null) {
Long msb = data.getLong("WorldUUIDMost").orElse(null);
Long lsb = data.getLong("WorldUUIDLeast").orElse(null);
World world = msb != null && lsb != null ? this.server.getWorld(new UUID(msb, lsb)) : null;
UUID uuid = new UUID(data.getLong("WorldUUIDMost"), data.getLong("WorldUUIDLeast"));
return new Location(this.server.getWorld(uuid),
position.getDouble(0),
position.getDouble(1),
position.getDouble(2),
rotation.getFloat(0),
rotation.getFloat(1)
return new Location(
world,
pos.x(), pos.y(), pos.z(),
rot.x, rot.y
);
}
return null;
}
@Override
public Location getBedSpawnLocation() {
return this.getRespawnLocation();
}
@Override
public Location getRespawnLocation() {
CompoundTag data = this.getData();
if (data == null) return null;
if (data.contains("SpawnX") && data.contains("SpawnY") && data.contains("SpawnZ")) {
// Paper start - fix wrong world
final float respawnAngle = data.getFloat("SpawnAngle");
org.bukkit.World spawnWorld = this.server.getWorld(data.getString("SpawnWorld")); // legacy
if (data.contains("SpawnDimension")) {
com.mojang.serialization.DataResult<net.minecraft.resources.ResourceKey<net.minecraft.world.level.Level>> result = net.minecraft.world.level.Level.RESOURCE_KEY_CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, data.get("SpawnDimension"));
net.minecraft.resources.ResourceKey<net.minecraft.world.level.Level> levelKey = result.resultOrPartial(LOGGER::error).orElse(net.minecraft.world.level.Level.OVERWORLD);
net.minecraft.server.level.ServerLevel level = this.server.console.getLevel(levelKey);
spawnWorld = level != null ? level.getWorld() : spawnWorld;
final ServerPlayer.RespawnConfig respawnConfig = data.read("respawn", ServerPlayer.RespawnConfig.CODEC).orElse(null);
if (respawnConfig != null) {
final ServerLevel level = this.server.console.getLevel(respawnConfig.dimension());
if (level != null) {
return CraftLocation.toBukkit(respawnConfig.pos(), level.getWorld(), respawnConfig.angle(), 0);
}
if (spawnWorld == null) {
return null;
}
return new Location(spawnWorld, data.getInt("SpawnX"), data.getInt("SpawnY"), data.getInt("SpawnZ"), respawnAngle, 0);
// Paper end
}
return null;
}
public void setMetadata(String metadataKey, MetadataValue metadataValue) {
this.server.getPlayerMetadata().setMetadata(this, metadataKey, metadataValue);
}
public List<MetadataValue> getMetadata(String metadataKey) {
return this.server.getPlayerMetadata().getMetadata(this, metadataKey);
}
public boolean hasMetadata(String metadataKey) {
return this.server.getPlayerMetadata().hasMetadata(this, metadataKey);
}
public void removeMetadata(String metadataKey, Plugin plugin) {
this.server.getPlayerMetadata().removeMetadata(this, metadataKey, plugin);
}
private ServerStatsCounter getStatisticManager() {
return this.server.getHandle().getPlayerStats(this.getUniqueId(), this.getName());
}

View File

@@ -192,7 +192,7 @@ public abstract class CraftParticle<D> implements Keyed {
BiFunction<NamespacedKey, net.minecraft.core.particles.ParticleType<?>, CraftParticle<?>> trailFunction = (name, particle) -> new CraftParticle<>(name, particle, Particle.Trail.class) {
@Override
public ParticleOptions createParticleParam(Particle.Trail data) {
return new TrailParticleOption(CraftLocation.toVec3D(data.getTarget()), data.getColor().asRGB(), data.getDuration());
return new TrailParticleOption(CraftLocation.toVec3(data.getTarget()), data.getColor().asRGB(), data.getDuration());
}
};
@@ -206,6 +206,7 @@ public abstract class CraftParticle<D> implements Keyed {
add("shriek", integerFunction);
add("block_marker", blockDataFunction);
add("entity_effect", colorFunction);
add("tinted_leaves", colorFunction);
add("dust_pillar", blockDataFunction);
add("block_crumble", blockDataFunction);
add("trail", trailFunction);

View File

@@ -11,16 +11,17 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import org.bukkit.Location;
import org.bukkit.Raid;
import org.bukkit.Raid.RaidStatus;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.Raider;
public final class CraftRaid implements Raid {
private final net.minecraft.world.entity.raid.Raid handle;
private final Level level;
public CraftRaid(net.minecraft.world.entity.raid.Raid handle) {
public CraftRaid(net.minecraft.world.entity.raid.Raid handle, Level level) {
this.handle = handle;
this.level = level;
}
@Override
@@ -48,8 +49,7 @@ public final class CraftRaid implements Raid {
@Override
public Location getLocation() {
BlockPos pos = this.handle.getCenter();
Level world = this.handle.getLevel();
return CraftLocation.toBukkit(pos, world.getWorld());
return CraftLocation.toBukkit(pos, this.level.getWorld());
}
@Override
@@ -104,10 +104,9 @@ public final class CraftRaid implements Raid {
return this.handle;
}
// Paper start - more Raid API
@Override
public int getId() {
return this.handle.getId();
return this.handle.idOrNegativeOne;
}
@Override
@@ -132,5 +131,4 @@ public final class CraftRaid implements Raid {
public int hashCode() {
return this.handle.hashCode();
}
// Paper end - more Raid API
}

View File

@@ -12,12 +12,13 @@ import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.features.TreeFeatures;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ChorusFlowerBlock;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
@@ -35,19 +36,19 @@ import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftEntityTypes;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.BlockStateListPopulator;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.RandomSourceWrapper;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.AbstractCow;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Horse;
import org.bukkit.entity.LargeFireball;
import org.bukkit.entity.LingeringPotion;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.SizedFireball;
@@ -56,7 +57,6 @@ import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.TippedArrow;
import org.bukkit.entity.minecart.RideableMinecart;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionType;
public abstract class CraftRegionAccessor implements RegionAccessor {
@@ -77,12 +77,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return CraftBiome.minecraftHolderToBukkit(this.getHandle().getNoiseBiome(x >> 2, y >> 2, z >> 2));
}
// Paper start
@Override
public Biome getComputedBiome(int x, int y, int z) {
return CraftBiome.minecraftHolderToBukkit(this.getHandle().getBiome(new BlockPos(x, y, z)));
}
// Paper end
@Override
public void setBiome(Location location, Biome biome) {
@@ -108,12 +106,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return CraftBlock.at(this.getHandle(), new BlockPos(x, y, z)).getState();
}
// Paper start - FluidState API
@Override
public io.papermc.paper.block.fluid.FluidData getFluidData(final int x, final int y, final int z) {
return io.papermc.paper.block.fluid.PaperFluidData.createData(getHandle().getFluidState(new BlockPos(x, y, z)));
}
// Paper end
@Override
public BlockData getBlockData(Location location) {
@@ -150,7 +146,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
BlockPos pos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState old = this.getHandle().getBlockState(pos);
CraftBlock.setTypeAndData(world, pos, old, ((CraftBlockData) blockData).getState(), true);
CraftBlock.setBlockState(world, pos, old, ((CraftBlockData) blockData).getState(), true);
}
@Override
@@ -203,13 +199,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
BlockStateListPopulator populator = new BlockStateListPopulator(this.getHandle());
boolean result = this.generateTree(populator, this.getHandle().getMinecraftWorld().getChunkSource().getGenerator(), pos, new RandomSourceWrapper(random), treeType);
populator.refreshTiles();
for (BlockState blockState : populator.getList()) {
if (predicate == null || predicate.test(blockState)) {
blockState.update(true, true);
}
}
populator.placeSomeBlocks(predicate == null ? ($ -> true) : predicate);
return result;
}
@@ -265,7 +255,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
gen = TreeFeatures.SUPER_BIRCH_BEES_0002;
break;
case CHORUS_PLANT:
((ChorusFlowerBlock) Blocks.CHORUS_FLOWER).generatePlant(access, pos, random, 8);
ChorusFlowerBlock.generatePlant(access, pos, random, 8);
return true;
case CRIMSON_FUNGUS:
gen = this.isNormalWorld() ? TreeFeatures.CRIMSON_FUNGUS_PLANTED : TreeFeatures.CRIMSON_FUNGUS; // Paper - Fix async entity add due to fungus trees; if world gen, don't use planted version
@@ -298,7 +288,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
}
Holder<ConfiguredFeature<?, ?>> holder = access.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).get(gen).orElse(null);
return (holder != null) ? holder.value().place(access, chunkGenerator, random, pos) : false;
return holder != null && holder.value().place(access, chunkGenerator, random, pos);
}
@Override
@@ -313,7 +303,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
@Override
public List<Entity> getEntities() {
List<Entity> list = new ArrayList<Entity>();
List<Entity> list = new ArrayList<>();
this.getNMSEntities().forEach(entity -> {
Entity bukkitEntity = entity.getBukkitEntity();
@@ -329,13 +319,13 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
@Override
public List<LivingEntity> getLivingEntities() {
List<LivingEntity> list = new ArrayList<LivingEntity>();
List<LivingEntity> list = new ArrayList<>();
this.getNMSEntities().forEach(entity -> {
Entity bukkitEntity = entity.getBukkitEntity();
// Assuming that bukkitEntity isn't null
if (bukkitEntity != null && bukkitEntity instanceof LivingEntity && (!this.isNormalWorld() || bukkitEntity.isValid())) {
if (bukkitEntity instanceof LivingEntity && (!this.isNormalWorld() || bukkitEntity.isValid())) {
list.add((LivingEntity) bukkitEntity);
}
});
@@ -367,7 +357,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
@Override
public Collection<Entity> getEntitiesByClasses(Class<?>... classes) {
Collection<Entity> list = new ArrayList<Entity>();
Collection<Entity> list = new ArrayList<>();
this.getNMSEntities().forEach(entity -> {
Entity bukkitEntity = entity.getBukkitEntity();
@@ -472,11 +462,6 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
public abstract void addEntityWithPassengers(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason);
@SuppressWarnings("unchecked")
public net.minecraft.world.entity.Entity makeEntity(Location location, Class<? extends Entity> clazz) throws IllegalArgumentException {
return this.createEntity(location, clazz, true);
}
@SuppressWarnings("unchecked")
public net.minecraft.world.entity.Entity createEntity(Location location, Class<? extends Entity> clazz, boolean randomizeData) throws IllegalArgumentException {
Preconditions.checkArgument(location != null, "Location cannot be null");
@@ -488,17 +473,16 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
clazz = Arrow.class;
} else if (clazz == AbstractHorse.class) {
clazz = Horse.class;
} else if (clazz == AbstractCow.class) {
clazz = Cow.class;
} else if (clazz == Fireball.class) {
clazz = LargeFireball.class;
} else if (clazz == LingeringPotion.class) {
clazz = ThrownPotion.class;
runOld = other -> ((net.minecraft.world.entity.projectile.ThrownPotion) other).setItem(CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1)));
} else if (clazz == ThrownPotion.class) {
clazz = SplashPotion.class;
} else if (clazz == Minecart.class) {
clazz = RideableMinecart.class;
} else if (clazz == SizedFireball.class) {
clazz = LargeFireball.class;
} else if (clazz == SplashPotion.class) {
clazz = ThrownPotion.class;
} else if (clazz == TippedArrow.class) {
clazz = Arrow.class;
runOld = other -> ((Arrow) other.getBukkitEntity()).setBasePotionType(PotionType.WATER);
@@ -530,10 +514,9 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
throw new IllegalArgumentException("Cannot spawn an entity for " + clazz.getName());
}
// Paper start
@Override
public io.papermc.paper.world.MoonPhase getMoonPhase() {
return io.papermc.paper.world.MoonPhase.getPhase(this.getHandle().dayTime() / 24000L);
return io.papermc.paper.world.MoonPhase.getPhase(this.getHandle().dayTime() / Level.TICKS_PER_DAY);
}
@Override
@@ -550,7 +533,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
net.minecraft.world.phys.Vec3 start = new net.minecraft.world.phys.Vec3(from.getX(), from.getY(), from.getZ());
net.minecraft.world.phys.Vec3 end = new net.minecraft.world.phys.Vec3(to.getX(), to.getY(), to.getZ());
if (end.distanceToSqr(start) > 128D * 128D) {
if (end.distanceToSqr(start) > Mth.square(128D)) {
return false; // Return early if the distance is greater than 128 blocks
}
@@ -563,12 +546,9 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return !this.getHandle().noCollision(aabb);
}
// Paper end
// Paper start - feature flag API
@Override
public java.util.Set<org.bukkit.FeatureFlag> getFeatureFlags() {
return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.getHandle().enabledFeatures());
}
// Paper end - feature flag API
}

View File

@@ -124,7 +124,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
}
// Paper start - fixup upstream being dum
public static <T extends Keyed, M> Optional<T> unwrapAndConvertHolder(final RegistryKey<T> registryKey, final Holder<M> value) {
public static <T extends Keyed, M> Optional<T> unwrapAndConvertHolder(final RegistryKey<T> registryKey, final Holder<M> value) { // todo recheck usage with holderable support
final Registry<T> registry = RegistryAccess.registryAccess().getRegistry(registryKey);
if (registry instanceof final CraftRegistry<?,?> craftRegistry && craftRegistry.supportsDirectHolders() && value.kind() == Holder.Kind.DIRECT) {
return Optional.of(((CraftRegistry<T, M>) registry).createBukkit(value));
@@ -255,7 +255,6 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return this.minecraftToBukkit.supportsDirectHolders();
}
// Paper start - improve Registry
@Override
public NamespacedKey getKey(final B value) {
if (value instanceof Holderable<?> holderable) {
@@ -263,7 +262,6 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
}
return value.getKey();
}
// Paper end - improve Registry
// Paper start - RegistrySet API
@Override

View File

@@ -61,7 +61,6 @@ public class CraftServerLinks implements ServerLinks {
return link;
}
// Paper start - Adventure
@Override
public ServerLink addLink(net.kyori.adventure.text.Component displayName, URI url) {
Preconditions.checkArgument(displayName != null, "displayName cannot be null");
@@ -72,7 +71,6 @@ public class CraftServerLinks implements ServerLinks {
return link;
}
// Paper end - Adventure
@Override
public ServerLink addLink(String displayName, URI url) {
@@ -147,12 +145,10 @@ public class CraftServerLinks implements ServerLinks {
return CraftChatMessage.fromComponent(this.handle.displayName());
}
// Paper start - Adventure
@Override
public net.kyori.adventure.text.Component displayName() {
return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.handle.displayName());
}
// Paper end - Adventure
@Override
public URI getUrl() {

View File

@@ -25,10 +25,4 @@ public class CraftSound extends OldEnumHolderable<Sound, SoundEvent> implements
public CraftSound(Holder<SoundEvent> soundEffect) {
super(soundEffect, count++);
}
// Paper start
public static String getSound(Sound sound) {
return sound.getKey().getKey();
}
// Paper end
}

View File

@@ -34,7 +34,7 @@ public class CraftSoundGroup implements SoundGroup {
@Override
public Sound getBreakSound() {
return CraftSound.minecraftToBukkit(this.getHandle().breakSound);
return CraftSound.minecraftToBukkit(this.getHandle().getBreakSound());
}
@Override
@@ -49,7 +49,7 @@ public class CraftSoundGroup implements SoundGroup {
@Override
public Sound getHitSound() {
return CraftSound.minecraftToBukkit(this.getHandle().hitSound);
return CraftSound.minecraftToBukkit(this.getHandle().getHitSound());
}
@Override

View File

@@ -20,89 +20,95 @@ import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.entity.EntityType;
public enum CraftStatistic {
DAMAGE_DEALT(Stats.DAMAGE_DEALT),
DAMAGE_TAKEN(Stats.DAMAGE_TAKEN),
DEATHS(Stats.DEATHS),
MOB_KILLS(Stats.MOB_KILLS),
PLAYER_KILLS(Stats.PLAYER_KILLS),
FISH_CAUGHT(Stats.FISH_CAUGHT),
// Start generate - CraftStatisticCustom
// @GeneratedFrom 1.21.5
ANIMALS_BRED(Stats.ANIMALS_BRED),
LEAVE_GAME(Stats.LEAVE_GAME),
JUMP(Stats.JUMP),
DROP_COUNT(Stats.DROP),
DROP(ResourceLocation.withDefaultNamespace("dropped")),
PICKUP(ResourceLocation.withDefaultNamespace("picked_up")),
PLAY_ONE_MINUTE(Stats.PLAY_TIME),
TOTAL_WORLD_TIME(Stats.TOTAL_WORLD_TIME),
WALK_ONE_CM(Stats.WALK_ONE_CM),
WALK_ON_WATER_ONE_CM(Stats.WALK_ON_WATER_ONE_CM),
FALL_ONE_CM(Stats.FALL_ONE_CM),
SNEAK_TIME(Stats.CROUCH_TIME),
CLIMB_ONE_CM(Stats.CLIMB_ONE_CM),
FLY_ONE_CM(Stats.FLY_ONE_CM),
WALK_UNDER_WATER_ONE_CM(Stats.WALK_UNDER_WATER_ONE_CM),
MINECART_ONE_CM(Stats.MINECART_ONE_CM),
BOAT_ONE_CM(Stats.BOAT_ONE_CM),
PIG_ONE_CM(Stats.PIG_ONE_CM),
HORSE_ONE_CM(Stats.HORSE_ONE_CM),
SPRINT_ONE_CM(Stats.SPRINT_ONE_CM),
CROUCH_ONE_CM(Stats.CROUCH_ONE_CM),
AVIATE_ONE_CM(Stats.AVIATE_ONE_CM),
MINE_BLOCK(ResourceLocation.withDefaultNamespace("mined")),
USE_ITEM(ResourceLocation.withDefaultNamespace("used")),
BREAK_ITEM(ResourceLocation.withDefaultNamespace("broken")),
CRAFT_ITEM(ResourceLocation.withDefaultNamespace("crafted")),
KILL_ENTITY(ResourceLocation.withDefaultNamespace("killed")),
ENTITY_KILLED_BY(ResourceLocation.withDefaultNamespace("killed_by")),
TIME_SINCE_DEATH(Stats.TIME_SINCE_DEATH),
TALKED_TO_VILLAGER(Stats.TALKED_TO_VILLAGER),
TRADED_WITH_VILLAGER(Stats.TRADED_WITH_VILLAGER),
CAKE_SLICES_EATEN(Stats.EAT_CAKE_SLICE),
CAULDRON_FILLED(Stats.FILL_CAULDRON),
CAULDRON_USED(Stats.USE_CAULDRON),
BELL_RING(Stats.BELL_RING),
BOAT_ONE_CM(Stats.BOAT_ONE_CM),
ARMOR_CLEANED(Stats.CLEAN_ARMOR),
BANNER_CLEANED(Stats.CLEAN_BANNER),
BREWINGSTAND_INTERACTION(Stats.INTERACT_WITH_BREWINGSTAND),
BEACON_INTERACTION(Stats.INTERACT_WITH_BEACON),
DROPPER_INSPECTED(Stats.INSPECT_DROPPER),
HOPPER_INSPECTED(Stats.INSPECT_HOPPER),
DISPENSER_INSPECTED(Stats.INSPECT_DISPENSER),
NOTEBLOCK_PLAYED(Stats.PLAY_NOTEBLOCK),
NOTEBLOCK_TUNED(Stats.TUNE_NOTEBLOCK),
FLOWER_POTTED(Stats.POT_FLOWER),
TRAPPED_CHEST_TRIGGERED(Stats.TRIGGER_TRAPPED_CHEST),
ENDERCHEST_OPENED(Stats.OPEN_ENDERCHEST),
ITEM_ENCHANTED(Stats.ENCHANT_ITEM),
RECORD_PLAYED(Stats.PLAY_RECORD),
FURNACE_INTERACTION(Stats.INTERACT_WITH_FURNACE),
CRAFTING_TABLE_INTERACTION(Stats.INTERACT_WITH_CRAFTING_TABLE),
CHEST_OPENED(Stats.OPEN_CHEST),
SLEEP_IN_BED(Stats.SLEEP_IN_BED),
SHULKER_BOX_OPENED(Stats.OPEN_SHULKER_BOX),
TIME_SINCE_REST(Stats.TIME_SINCE_REST),
SWIM_ONE_CM(Stats.SWIM_ONE_CM),
CLEAN_SHULKER_BOX(Stats.CLEAN_SHULKER_BOX),
CLIMB_ONE_CM(Stats.CLIMB_ONE_CM),
CROUCH_ONE_CM(Stats.CROUCH_ONE_CM),
DAMAGE_ABSORBED(Stats.DAMAGE_ABSORBED),
DAMAGE_BLOCKED_BY_SHIELD(Stats.DAMAGE_BLOCKED_BY_SHIELD),
DAMAGE_DEALT(Stats.DAMAGE_DEALT),
DAMAGE_DEALT_ABSORBED(Stats.DAMAGE_DEALT_ABSORBED),
DAMAGE_DEALT_RESISTED(Stats.DAMAGE_DEALT_RESISTED),
DAMAGE_BLOCKED_BY_SHIELD(Stats.DAMAGE_BLOCKED_BY_SHIELD),
DAMAGE_ABSORBED(Stats.DAMAGE_ABSORBED),
DAMAGE_RESISTED(Stats.DAMAGE_RESISTED),
CLEAN_SHULKER_BOX(Stats.CLEAN_SHULKER_BOX),
OPEN_BARREL(Stats.OPEN_BARREL),
DAMAGE_TAKEN(Stats.DAMAGE_TAKEN),
DEATHS(Stats.DEATHS),
DROP_COUNT(Stats.DROP),
CAKE_SLICES_EATEN(Stats.EAT_CAKE_SLICE),
ITEM_ENCHANTED(Stats.ENCHANT_ITEM),
FALL_ONE_CM(Stats.FALL_ONE_CM),
CAULDRON_FILLED(Stats.FILL_CAULDRON),
FISH_CAUGHT(Stats.FISH_CAUGHT),
FLY_ONE_CM(Stats.FLY_ONE_CM),
HORSE_ONE_CM(Stats.HORSE_ONE_CM),
DISPENSER_INSPECTED(Stats.INSPECT_DISPENSER),
DROPPER_INSPECTED(Stats.INSPECT_DROPPER),
HOPPER_INSPECTED(Stats.INSPECT_HOPPER),
INTERACT_WITH_ANVIL(Stats.INTERACT_WITH_ANVIL),
BEACON_INTERACTION(Stats.INTERACT_WITH_BEACON),
INTERACT_WITH_BLAST_FURNACE(Stats.INTERACT_WITH_BLAST_FURNACE),
INTERACT_WITH_SMOKER(Stats.INTERACT_WITH_SMOKER),
INTERACT_WITH_LECTERN(Stats.INTERACT_WITH_LECTERN),
BREWINGSTAND_INTERACTION(Stats.INTERACT_WITH_BREWINGSTAND),
INTERACT_WITH_CAMPFIRE(Stats.INTERACT_WITH_CAMPFIRE),
INTERACT_WITH_CARTOGRAPHY_TABLE(Stats.INTERACT_WITH_CARTOGRAPHY_TABLE),
CRAFTING_TABLE_INTERACTION(Stats.INTERACT_WITH_CRAFTING_TABLE),
FURNACE_INTERACTION(Stats.INTERACT_WITH_FURNACE),
INTERACT_WITH_GRINDSTONE(Stats.INTERACT_WITH_GRINDSTONE),
INTERACT_WITH_LECTERN(Stats.INTERACT_WITH_LECTERN),
INTERACT_WITH_LOOM(Stats.INTERACT_WITH_LOOM),
INTERACT_WITH_SMITHING_TABLE(Stats.INTERACT_WITH_SMITHING_TABLE),
INTERACT_WITH_SMOKER(Stats.INTERACT_WITH_SMOKER),
INTERACT_WITH_STONECUTTER(Stats.INTERACT_WITH_STONECUTTER),
BELL_RING(Stats.BELL_RING),
JUMP(Stats.JUMP),
LEAVE_GAME(Stats.LEAVE_GAME),
MINECART_ONE_CM(Stats.MINECART_ONE_CM),
MOB_KILLS(Stats.MOB_KILLS),
OPEN_BARREL(Stats.OPEN_BARREL),
CHEST_OPENED(Stats.OPEN_CHEST),
ENDERCHEST_OPENED(Stats.OPEN_ENDERCHEST),
SHULKER_BOX_OPENED(Stats.OPEN_SHULKER_BOX),
PIG_ONE_CM(Stats.PIG_ONE_CM),
NOTEBLOCK_PLAYED(Stats.PLAY_NOTEBLOCK),
RECORD_PLAYED(Stats.PLAY_RECORD),
PLAY_ONE_MINUTE(Stats.PLAY_TIME),
PLAYER_KILLS(Stats.PLAYER_KILLS),
FLOWER_POTTED(Stats.POT_FLOWER),
RAID_TRIGGER(Stats.RAID_TRIGGER),
RAID_WIN(Stats.RAID_WIN),
INTERACT_WITH_ANVIL(Stats.INTERACT_WITH_ANVIL),
INTERACT_WITH_GRINDSTONE(Stats.INTERACT_WITH_GRINDSTONE),
SLEEP_IN_BED(Stats.SLEEP_IN_BED),
SNEAK_TIME(Stats.CROUCH_TIME),
SPRINT_ONE_CM(Stats.SPRINT_ONE_CM),
STRIDER_ONE_CM(Stats.STRIDER_ONE_CM),
SWIM_ONE_CM(Stats.SWIM_ONE_CM),
TALKED_TO_VILLAGER(Stats.TALKED_TO_VILLAGER),
TARGET_HIT(Stats.TARGET_HIT),
INTERACT_WITH_SMITHING_TABLE(Stats.INTERACT_WITH_SMITHING_TABLE),
STRIDER_ONE_CM(Stats.STRIDER_ONE_CM);
TIME_SINCE_DEATH(Stats.TIME_SINCE_DEATH),
TIME_SINCE_REST(Stats.TIME_SINCE_REST),
TOTAL_WORLD_TIME(Stats.TOTAL_WORLD_TIME),
TRADED_WITH_VILLAGER(Stats.TRADED_WITH_VILLAGER),
TRAPPED_CHEST_TRIGGERED(Stats.TRIGGER_TRAPPED_CHEST),
NOTEBLOCK_TUNED(Stats.TUNE_NOTEBLOCK),
CAULDRON_USED(Stats.USE_CAULDRON),
WALK_ON_WATER_ONE_CM(Stats.WALK_ON_WATER_ONE_CM),
WALK_ONE_CM(Stats.WALK_ONE_CM),
WALK_UNDER_WATER_ONE_CM(Stats.WALK_UNDER_WATER_ONE_CM),
// End generate - CraftStatisticCustom
// Start generate - CraftStatisticType
// @GeneratedFrom 1.21.5
BREAK_ITEM(ResourceLocation.withDefaultNamespace("broken")),
CRAFT_ITEM(ResourceLocation.withDefaultNamespace("crafted")),
DROP(ResourceLocation.withDefaultNamespace("dropped")),
KILL_ENTITY(ResourceLocation.withDefaultNamespace("killed")),
ENTITY_KILLED_BY(ResourceLocation.withDefaultNamespace("killed_by")),
MINE_BLOCK(ResourceLocation.withDefaultNamespace("mined")),
PICKUP(ResourceLocation.withDefaultNamespace("picked_up")),
USE_ITEM(ResourceLocation.withDefaultNamespace("used"));
// End generate - CraftStatisticType
private final ResourceLocation minecraftKey;
private final org.bukkit.Statistic bukkit;
private static final BiMap<ResourceLocation, org.bukkit.Statistic> statistics;

View File

@@ -47,7 +47,6 @@ import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LightningBolt;
@@ -58,9 +57,11 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ImposterProtoChunk;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.storage.LevelResource;
@@ -213,7 +214,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public int getTileEntityCount() {
// We don't use the full world tile entity list, so we must iterate chunks
// We don't use the full world block entity list, so we must iterate chunks
int size = 0;
for (ChunkHolder playerchunk : ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.world)) {
net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk();
@@ -448,7 +449,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public boolean unloadChunkRequest(int x, int z) {
org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
if (this.isChunkLoaded(x, z)) {
this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE);
this.world.getChunkSource().removeTicketWithRadius(TicketType.PLUGIN, new ChunkPos(x, z), 1);
}
return true;
@@ -532,8 +533,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
chunk = this.world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true);
}
if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) {
this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE);
if (chunk instanceof LevelChunk) {
this.world.getChunkSource().addTicketWithRadius(TicketType.PLUGIN, new ChunkPos(x, z), 1);
return true;
}
@@ -561,7 +562,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Preconditions.checkArgument(plugin.isEnabled(), "plugin is not enabled");
final DistanceManager distanceManager = this.world.getChunkSource().chunkMap.distanceManager;
if (distanceManager.addPluginRegionTicket(new ChunkPos(x, z), plugin)) {
if (distanceManager.ticketStorage.addPluginRegionTicket(new ChunkPos(x, z), plugin)) {
this.getChunkAt(x, z); // ensure it's loaded
return true;
}
@@ -574,7 +575,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Preconditions.checkNotNull(plugin, "null plugin");
final DistanceManager distanceManager = this.world.getChunkSource().chunkMap.distanceManager;
return distanceManager.removePluginRegionTicket(new ChunkPos(x, z), plugin);
return distanceManager.ticketStorage.removePluginRegionTicket(new ChunkPos(x, z), plugin);
}
@Override
@@ -582,7 +583,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Preconditions.checkNotNull(plugin, "null plugin");
DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager;
chunkDistanceManager.removeAllTicketsFor(TicketType.PLUGIN_TICKET, 31, plugin); // keep in-line with force loading, remove at level 31
chunkDistanceManager.ticketStorage.removeAllPluginRegionTickets(TicketType.PLUGIN_TICKET, ChunkMap.FORCED_TICKET_LEVEL, plugin);
}
@Override
@@ -616,7 +617,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean isChunkForceLoaded(int x, int z) {
return this.getHandle().getForcedChunks().contains(ChunkPos.asLong(x, z));
return this.getHandle().getForceLoadedChunks().contains(ChunkPos.asLong(x, z));
}
@Override
@@ -629,7 +630,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public Collection<Chunk> getForceLoadedChunks() {
Set<Chunk> chunks = new HashSet<>();
for (long coord : this.getHandle().getForcedChunks()) {
for (long coord : this.getHandle().getForceLoadedChunks()) {
chunks.add(this.getChunkAt(ChunkPos.getX(coord), ChunkPos.getZ(coord)));
}
@@ -700,7 +701,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
arrow = EntityType.ARROW.create(this.world, EntitySpawnReason.COMMAND);
}
arrow.moveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
arrow.snapTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
arrow.shoot(velocity.getX(), velocity.getY(), velocity.getZ(), speed, spread);
this.world.addFreshEntity(arrow);
return (T) arrow.getBukkitEntity();
@@ -720,7 +721,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Preconditions.checkArgument(loc != null, "Location cannot be null");
LightningBolt lightning = EntityType.LIGHTNING_BOLT.create(this.world, EntitySpawnReason.COMMAND);
lightning.moveTo(loc.getX(), loc.getY(), loc.getZ());
lightning.snapTo(loc.getX(), loc.getY(), loc.getZ());
lightning.isEffect = isVisual; // Paper - Properly handle lightning effects api
this.world.strikeLightning(lightning, LightningStrikeEvent.Cause.CUSTOM);
return (LightningStrike) lightning.getBukkitEntity();
@@ -729,8 +730,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// Paper start - Add methods to find targets for lightning strikes
@Override
public Location findLightningRod(Location location) {
return this.world.findLightningRod(io.papermc.paper.util.MCUtil.toBlockPosition(location))
.map(blockPos -> io.papermc.paper.util.MCUtil.toLocation(this.world, blockPos)
return this.world.findLightningRod(CraftLocation.toBlockPosition(location))
.map(blockPos -> CraftLocation.toBukkit(blockPos, this.world)
// get the actual rod pos
.subtract(0, 1, 0))
.orElse(null);
@@ -738,8 +739,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public Location findLightningTarget(Location location) {
final BlockPos pos = this.world.findLightningTargetAround(io.papermc.paper.util.MCUtil.toBlockPosition(location), true);
return pos == null ? null : io.papermc.paper.util.MCUtil.toLocation(this.world, pos);
final BlockPos pos = this.world.findLightningTargetAround(CraftLocation.toBlockPosition(location), true);
return pos == null ? null : CraftLocation.toBukkit(pos, this.world);
}
// Paper end - Add methods to find targets for lightning strikes
@@ -759,10 +760,10 @@ public class CraftWorld extends CraftRegionAccessor implements World {
for (BlockState blockstate : this.world.capturedBlockStates.values()) {
BlockPos position = ((CraftBlockState) blockstate).getPosition();
net.minecraft.world.level.block.state.BlockState oldBlock = this.world.getBlockState(position);
int flag = ((CraftBlockState) blockstate).getFlag();
int flags = ((CraftBlockState) blockstate).getFlags();
delegate.setBlockData(blockstate.getX(), blockstate.getY(), blockstate.getZ(), blockstate.getBlockData());
net.minecraft.world.level.block.state.BlockState newBlock = this.world.getBlockState(position);
this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flag, 512);
this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flags, net.minecraft.world.level.block.Block.UPDATE_LIMIT);
}
this.world.capturedBlockStates.clear();
return true;
@@ -794,15 +795,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public long getTime() {
long time = this.getFullTime() % 24000;
if (time < 0) time += 24000;
long time = this.getFullTime() % Level.TICKS_PER_DAY;
if (time < 0) time += Level.TICKS_PER_DAY;
return time;
}
@Override
public void setTime(long time) {
long margin = (time - this.getFullTime()) % 24000;
if (margin < 0) margin += 24000;
long margin = (time - this.getFullTime()) % Level.TICKS_PER_DAY;
if (margin < 0) margin += Level.TICKS_PER_DAY;
this.setFullTime(this.getFullTime() + margin);
}
@@ -834,7 +835,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// Paper start
@Override
public boolean isDayTime() {
return getHandle().isDay();
return getHandle().isBrightOutside();
}
// Paper end
@@ -1177,9 +1178,9 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Vector dir = direction.clone().normalize().multiply(maxDistance);
Vec3 startPos = io.papermc.paper.util.MCUtil.toVec3(start); // Paper - Add predicate for blocks when raytracing
Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing
HitResult hitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toFluid(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
return CraftRayTraceResult.convertFromInternal(this.getHandle(), hitResult);
}
@Override
@@ -2314,7 +2315,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return null;
}
return new CraftBiomeSearchResult(CraftBiome.minecraftHolderToBukkit(found.getSecond()), new Location(this, found.getFirst().getX(), found.getFirst().getY(), found.getFirst().getZ()));
return new CraftBiomeSearchResult(CraftBiome.minecraftHolderToBukkit(found.getSecond()), CraftLocation.toBukkit(found.getFirst(), this));
}
@Override
@@ -2324,21 +2325,21 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Raids persistentRaid = this.world.getRaids();
net.minecraft.world.entity.raid.Raid raid = persistentRaid.getNearbyRaid(CraftLocation.toBlockPosition(location), radius * radius);
return (raid == null) ? null : new CraftRaid(raid);
return (raid == null) ? null : new CraftRaid(raid, this.world);
}
// Paper start - more Raid API
@Override
public @Nullable Raid getRaid(final int id) {
final net.minecraft.world.entity.raid.@Nullable Raid nmsRaid = this.world.getRaids().raidMap.get(id);
return nmsRaid != null ? new CraftRaid(nmsRaid) : null;
return nmsRaid != null ? new CraftRaid(nmsRaid, this.world) : null;
}
// Paper end - more Raid API
@Override
public List<Raid> getRaids() {
Raids persistentRaid = this.world.getRaids();
return persistentRaid.raidMap.values().stream().map(CraftRaid::new).collect(Collectors.toList());
return persistentRaid.raidMap.values().stream().map(raid -> new CraftRaid(raid, this.world)).collect(Collectors.toList());
}
@Override
@@ -2390,24 +2391,20 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
// Spigot start
private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot()
{
private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() {
@Override
public LightningStrike strikeLightning(Location loc, boolean isSilent)
{
public LightningStrike strikeLightning(Location loc, boolean isSilent) {
return CraftWorld.this.strikeLightning(loc);
}
@Override
public LightningStrike strikeLightningEffect(Location loc, boolean isSilent)
{
public LightningStrike strikeLightningEffect(Location loc, boolean isSilent) {
return CraftWorld.this.strikeLightningEffect(loc);
}
};
public org.bukkit.World.Spigot spigot()
{
public org.bukkit.World.Spigot spigot() {
return this.spigot;
}
// Spigot end

View File

@@ -7,7 +7,6 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import joptsimple.OptionParser;
@@ -26,12 +25,6 @@ public class Main {
// Paper end - Reset loggers after shutdown
public static void main(String[] args) {
// Paper start
final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected");
if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) {
System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true));
}
// Paper end
// 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() {
@@ -149,15 +142,12 @@ public class Main {
this.acceptsAll(Main.asList("initSettings"), "Only create configuration files and then exit"); // SPIGOT-5761: Add initSettings option
// Spigot start
this.acceptsAll(Main.asList("S", "spigot-settings"), "File for spigot settings")
.withRequiredArg()
.ofType(File.class)
.defaultsTo(new File("spigot.yml"))
.describedAs("Yml file");
// Spigot end
// Paper start
acceptsAll(asList("paper-dir", "paper-settings-directory"), "Directory for Paper settings")
.withRequiredArg()
.ofType(File.class)
@@ -174,15 +164,12 @@ public class Main {
.ofType(File.class)
.defaultsTo(new File[] {})
.describedAs("Jar file");
// Paper end
// Paper start
acceptsAll(asList("server-name"), "Name of the server")
.withRequiredArg()
.ofType(String.class)
.defaultsTo("Unknown Server")
.describedAs("Name");
// Paper end
}
};
@@ -226,32 +213,10 @@ public class Main {
// Paper end - Improve java version check
try {
// Paper start - Handled by TerminalConsoleAppender
/*
// This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals
String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'});
String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'});
Main.useJline = !(jline_UnsupportedTerminal).equals(System.getProperty(jline_terminal));
if (options.has("nojline")) {
System.setProperty("user.language", "en");
Main.useJline = false;
}
if (Main.useJline) {
AnsiConsole.systemInstall();
} else {
// This ensures the terminal literal will always match the jline implementation
System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName());
}
*/
if (options.has("nojline")) {
System.setProperty(net.minecrell.terminalconsole.TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false");
useJline = false;
}
// Paper end
if (options.has("noconsole")) {
Main.useConsole = false;
@@ -267,17 +232,14 @@ public class Main {
if (buildDate.before(deadline.getTime())) {
// Paper start - This is some stupid bullshit
System.err.println("*** Warning, you've not updated in a while! ***");
System.err.println("*** Please download a new build from https://papermc.io/downloads/paper ***"); // Paper
//System.err.println("*** Server will start in 20 seconds ***");
//Thread.sleep(TimeUnit.SECONDS.toMillis(20));
System.err.println("*** Please download a new build from https://papermc.io/downloads/paper ***");
// Paper end
}
}
System.setProperty("library.jansi.version", "Paper"); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows
System.setProperty("jdk.console", "java.base"); // Paper - revert default console provider back to java.base so we can have our own jline
//System.out.println("Loading libraries, please wait...");
//net.minecraft.server.Main.main(options);
io.papermc.paper.PaperBootstrap.boot(options);
} catch (Throwable t) {
t.printStackTrace();

View File

@@ -35,14 +35,12 @@ public class CraftAdvancement implements org.bukkit.advancement.Advancement {
return new CraftAdvancementRequirements(this.handle.value().requirements());
}
// Paper start - Add more advancement API
@Override
public io.papermc.paper.advancement.AdvancementDisplay getDisplay() {
return this.handle.value().display().map(d -> d.paper).orElse(null);
}
@Deprecated
@io.papermc.paper.annotation.DoNotUse
public AdvancementDisplay getDisplay0() { // May be called by plugins via Commodore
return this.handle.value().display().map(CraftAdvancementDisplay::new).orElse(null);
}
@@ -62,7 +60,7 @@ public class CraftAdvancement implements org.bukkit.advancement.Advancement {
@Override
public Collection<org.bukkit.advancement.Advancement> getChildren() {
final com.google.common.collect.ImmutableList.Builder<org.bukkit.advancement.Advancement> children = com.google.common.collect.ImmutableList.<org.bukkit.advancement.Advancement>builder();
final com.google.common.collect.ImmutableList.Builder<org.bukkit.advancement.Advancement> children = com.google.common.collect.ImmutableList.builder();
final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle);
if (advancementNode != null) {
for (final net.minecraft.advancements.AdvancementNode child : advancementNode.children()) {
@@ -77,5 +75,4 @@ public class CraftAdvancement implements org.bukkit.advancement.Advancement {
final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle);
return java.util.Objects.requireNonNull(advancementNode, "could not find internal advancement node for advancement " + this.handle.id()).root().holder().toBukkit();
}
// Paper end - Add more advancement API
}

View File

@@ -6,7 +6,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.inventory.ItemStack;
@Deprecated // Paper
@Deprecated
public class CraftAdvancementDisplay implements org.bukkit.advancement.AdvancementDisplay {
private final DisplayInfo handle;

View File

@@ -6,7 +6,6 @@ import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.attribute.Attribute;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.legacy.FieldRename;

View File

@@ -8,7 +8,6 @@ import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.EquipmentSlot;
public class CraftAttributeInstance implements AttributeInstance {
@@ -45,7 +44,6 @@ public class CraftAttributeInstance implements AttributeInstance {
return result;
}
// Paper start
@Override
public AttributeModifier getModifier(final net.kyori.adventure.key.Key key) {
Preconditions.checkArgument(key != null, "Key cannot be null");
@@ -70,7 +68,6 @@ public class CraftAttributeInstance implements AttributeInstance {
Preconditions.checkArgument(uuid != null, "UUID cannot be null");
this.removeModifier(AttributeMappings.uuidToKey(uuid));
}
// Paper end
@Override
public void addModifier(AttributeModifier modifier) {
@@ -78,13 +75,11 @@ public class CraftAttributeInstance implements AttributeInstance {
this.handle.addPermanentModifier(CraftAttributeInstance.convert(modifier));
}
// Paper start - Transient modifier API
@Override
public void addTransientModifier(AttributeModifier modifier) {
Preconditions.checkArgument(modifier != null, "modifier");
this.handle.addTransientModifier(CraftAttributeInstance.convert(modifier));
}
// Paper end
@Override
public void removeModifier(AttributeModifier modifier) {
@@ -111,6 +106,6 @@ public class CraftAttributeInstance implements AttributeInstance {
}
public static AttributeModifier convert(net.minecraft.world.entity.ai.attributes.AttributeModifier nms, net.minecraft.world.entity.EquipmentSlotGroup slot) { // Paper
return new AttributeModifier(CraftNamespacedKey.fromMinecraft(nms.id()), nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()], org.bukkit.craftbukkit.CraftEquipmentSlot.getSlot(slot)); // Paper
return new AttributeModifier(CraftNamespacedKey.fromMinecraft(nms.id()), nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()], org.bukkit.craftbukkit.CraftEquipmentSlot.getSlotGroup(slot)); // Paper
}
}

View File

@@ -9,20 +9,36 @@ import org.bukkit.attribute.AttributeInstance;
public class CraftAttributeMap implements Attributable {
private final AttributeMap handle;
// Paper start - convert legacy attributes
private static final com.google.common.collect.ImmutableMap<String, String> legacyNMS = com.google.common.collect.ImmutableMap.<String, String>builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build();
// convert legacy attributes
private static final com.google.common.collect.ImmutableMap<String, String> LEGACY_ATTRIBUTE_MAP = com.google.common.collect.ImmutableMap.<String, String>builder()
.put("generic.maxHealth", "generic.max_health")
.put("Max Health", "generic.max_health")
.put("zombie.spawnReinforcements", "zombie.spawn_reinforcements")
.put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements")
.put("horse.jumpStrength", "horse.jump_strength")
.put("Jump Strength", "horse.jump_strength")
.put("generic.followRange", "generic.follow_range")
.put("Follow Range", "generic.follow_range")
.put("generic.knockbackResistance", "generic.knockback_resistance")
.put("Knockback Resistance", "generic.knockback_resistance")
.put("generic.movementSpeed", "generic.movement_speed")
.put("Movement Speed", "generic.movement_speed")
.put("generic.flyingSpeed", "generic.flying_speed")
.put("Flying Speed", "generic.flying_speed")
.put("generic.attackDamage", "generic.attack_damage")
.put("generic.attackKnockback", "generic.attack_knockback")
.put("generic.attackSpeed", "generic.attack_speed")
.put("generic.armorToughness", "generic.armor_toughness")
.buildOrThrow();
public static String convertIfNeeded(String nms) {
if (nms == null) {
return null;
}
nms = legacyNMS.getOrDefault(nms, nms);
nms = LEGACY_ATTRIBUTE_MAP.getOrDefault(nms, nms);
if (!nms.toLowerCase(java.util.Locale.ROOT).equals(nms) || nms.indexOf(' ') != -1) {
return null;
}
return nms;
}
// Paper end
public CraftAttributeMap(AttributeMap handle) {
this.handle = handle;
@@ -35,11 +51,10 @@ public class CraftAttributeMap implements Attributable {
return (nms == null) ? null : new CraftAttributeInstance(nms, attribute);
}
// Paper start - living entity allow attribute registration
@Override
public void registerAttribute(Attribute attribute) {
Preconditions.checkArgument(attribute != null, "attribute");
handle.registerAttribute(CraftAttribute.bukkitToMinecraftHolder(attribute));
this.handle.registerAttribute(CraftAttribute.bukkitToMinecraftHolder(attribute));
}
// Paper end - living entity allow attribute registration
}

View File

@@ -6,8 +6,6 @@ import java.util.Date;
import net.minecraft.server.players.UserBanList;
import net.minecraft.server.players.UserBanListEntry;
import org.bukkit.BanEntry;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.profile.PlayerProfile;
public final class CraftProfileBanEntry implements BanEntry<com.destroystokyo.paper.profile.PlayerProfile> { // Paper
private static final Date minorDate = Date.from(Instant.parse("1899-12-31T04:00:00Z"));

View File

@@ -13,7 +13,6 @@ import net.minecraft.server.players.UserBanList;
import net.minecraft.server.players.UserBanListEntry;
import org.bukkit.BanEntry;
import org.bukkit.ban.ProfileBanList;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.profile.PlayerProfile;
public class CraftProfileBanList implements ProfileBanList {
@@ -36,7 +35,7 @@ public class CraftProfileBanList implements ProfileBanList {
return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile()); // Paper
}
// Paper start - fix ban list API
@Override
public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(final com.destroystokyo.paper.profile.PlayerProfile target) {
Preconditions.checkArgument(target != null, "target cannot be null");
@@ -73,7 +72,6 @@ public class CraftProfileBanList implements ProfileBanList {
Instant instant = duration != null ? Instant.now().plus(duration) : null;
return this.addBan(target, reason, instant, source);
}
// Paper end - fix ban list API
@Override
public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper - fix ban list API
@@ -126,11 +124,10 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public boolean isBanned(PlayerProfile target) {
// Paper start
return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
}
private boolean isBanned(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
// Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
return this.isBanned(target.buildGameProfile()); // Paper
@@ -145,11 +142,10 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public void pardon(PlayerProfile target) {
// Paper start
this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
}
private void pardon(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
// Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
this.pardon(target.buildGameProfile()); // Paper

View File

@@ -5,24 +5,23 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.util.CraftLocation;
@Deprecated(forRemoval = true)
public final class CapturedBlockState extends CraftBlockState {
private final boolean treeBlock;
public CapturedBlockState(Block block, int flag, boolean treeBlock) {
super(block, flag);
public CapturedBlockState(Block block, int capturedFlags, boolean treeBlock) {
super(block, capturedFlags);
this.treeBlock = treeBlock;
}
protected CapturedBlockState(CapturedBlockState state, Location location) {
private CapturedBlockState(CapturedBlockState state, Location location) {
super(state, location);
this.treeBlock = state.treeBlock;
}
@@ -31,39 +30,39 @@ public final class CapturedBlockState extends CraftBlockState {
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
// Probably no longer needed with the extra #updatedTree method,
// but leave if here for now in case a plugin for whatever reason relies on this.
this.addBees();
if (result) {
this.addBees();
}
return result;
}
private void updatedTree() {
// SPIGOT-7248 - Manual update to avoid physics where appropriate
// SPIGOT-7572 - Move SPIGOT-7248 fix from nms ItemStack to here, to allow bee generation in nests
this.world.getHandle().setBlock(CraftLocation.toBlockPosition(this.getLocation()), this.getHandle(), this.getFlag());
@Override
public boolean place(int flags) {
boolean result = super.place(flags);
this.addBees();
if (result) {
this.addBees();
}
return result;
}
private void addBees() {
// SPIGOT-5537: Horrible hack to manually add bees given World.captureTreeGeneration does not support tiles
// SPIGOT-5537: Horrible hack to manually add bees given Level#captureTreeGeneration does not support block entities
if (this.treeBlock && this.getType() == Material.BEE_NEST) {
WorldGenLevel generatoraccessseed = this.world.getHandle();
BlockPos blockposition1 = this.getPosition();
RandomSource random = generatoraccessseed.getRandom();
WorldGenLevel worldGenLevel = this.world.getHandle();
BlockPos pos = this.getPosition();
RandomSource randomSource = worldGenLevel.getRandom();
// Begin copied block from WorldGenFeatureTreeBeehive
BlockEntity tileentity = generatoraccessseed.getBlockEntity(blockposition1);
// Begin copied block from BeehiveDecorator
worldGenLevel.getBlockEntity(pos, BlockEntityType.BEEHIVE).ifPresent(beehiveBlockEntity -> {
int i1 = 2 + randomSource.nextInt(2);
if (tileentity instanceof BeehiveBlockEntity) {
BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity;
int j = 2 + random.nextInt(2);
for (int k = 0; k < j; ++k) {
tileentitybeehive.storeBee(BeehiveBlockEntity.Occupant.create(random.nextInt(599)));
for (int i2 = 0; i2 < i1; i2++) {
beehiveBlockEntity.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)));
}
}
});
// End copied block
}
}
@@ -78,19 +77,7 @@ public final class CapturedBlockState extends CraftBlockState {
return new CapturedBlockState(this, location);
}
public static CapturedBlockState getBlockState(Level world, BlockPos pos, int flag) {
return new CapturedBlockState(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), flag, false);
}
public static CapturedBlockState getTreeBlockState(Level world, BlockPos pos, int flag) {
return new CapturedBlockState(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), flag, true);
}
public static void setBlockState(BlockState blockState) {
if (blockState instanceof CapturedBlockState capturedBlockState) {
capturedBlockState.updatedTree();
} else {
blockState.update(true);
}
return new CapturedBlockState(CraftBlock.at(world, pos), flag, true);
}
}

View File

@@ -19,8 +19,8 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
private DyeColor base;
private List<Pattern> patterns;
public CraftBanner(World world, BannerBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBanner(World world, BannerBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBanner(CraftBanner state, Location location) {
@@ -30,21 +30,19 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
}
@Override
public void load(BannerBlockEntity banner) {
super.load(banner);
public void load(BannerBlockEntity blockEntity) {
super.load(blockEntity);
this.base = DyeColor.getByWoolData((byte) ((AbstractBannerBlock) this.data.getBlock()).getColor().getId());
this.patterns = new ArrayList<Pattern>();
this.patterns = new ArrayList<>();
if (banner.getPatterns() != null) {
for (int i = 0; i < banner.getPatterns().layers().size(); i++) {
BannerPatternLayers.Layer p = banner.getPatterns().layers().get(i);
// Paper start - fix upstream not handling inlined banner pattern
java.util.Optional<org.bukkit.block.banner.PatternType> type = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(RegistryKey.BANNER_PATTERN, p.pattern());
if (type.isEmpty()) continue;
this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), type.get()));
// Paper end - fix upstream not handling inlined banner pattern
}
for (int i = 0; i < blockEntity.getPatterns().layers().size(); i++) {
BannerPatternLayers.Layer p = blockEntity.getPatterns().layers().get(i);
// Paper start - fix upstream not handling inlined banner pattern
java.util.Optional<org.bukkit.block.banner.PatternType> type = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(RegistryKey.BANNER_PATTERN, p.pattern());
if (type.isEmpty()) continue;
this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), type.get()));
// Paper end - fix upstream not handling inlined banner pattern
}
}
@@ -95,17 +93,17 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
}
@Override
public void applyTo(BannerBlockEntity banner) {
super.applyTo(banner);
public void applyTo(BannerBlockEntity blockEntity) {
super.applyTo(blockEntity);
banner.baseColor = net.minecraft.world.item.DyeColor.byId(this.base.getWoolData());
blockEntity.baseColor = net.minecraft.world.item.DyeColor.byId(this.base.getWoolData());
List<BannerPatternLayers.Layer> newPatterns = new ArrayList<>();
for (Pattern p : this.patterns) {
newPatterns.add(new net.minecraft.world.level.block.entity.BannerPatternLayers.Layer(CraftPatternType.bukkitToMinecraftHolder(p.getPattern()), net.minecraft.world.item.DyeColor.byId(p.getColor().getWoolData())));
}
banner.setPatterns(new BannerPatternLayers(newPatterns));
blockEntity.setPatterns(new BannerPatternLayers(newPatterns));
}
@Override
@@ -118,15 +116,14 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
return new CraftBanner(this, location);
}
// Paper start
@Override
public net.kyori.adventure.text.Component customName() {
return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getSnapshot().getCustomName());
return this.getSnapshot().name == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getSnapshot().name);
}
@Override
public void customName(net.kyori.adventure.text.Component customName) {
this.getSnapshot().name = io.papermc.paper.adventure.PaperAdventure.asVanilla(customName);
this.getSnapshot().name = customName == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(customName);
}
@Override
@@ -138,5 +135,4 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
public void setCustomName(String name) {
this.customName(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(name));
}
// Paper end
}

View File

@@ -12,8 +12,8 @@ import org.bukkit.inventory.Inventory;
public class CraftBarrel extends CraftLootable<BarrelBlockEntity> implements Barrel {
public CraftBarrel(World world, BarrelBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBarrel(World world, BarrelBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBarrel(CraftBarrel state, Location location) {
@@ -31,37 +31,37 @@ public class CraftBarrel extends CraftLootable<BarrelBlockEntity> implements Bar
return this.getSnapshotInventory();
}
return new CraftInventory(this.getTileEntity());
return new CraftInventory(this.getBlockEntity());
}
@Override
public void open() {
this.requirePlaced();
if (!this.getTileEntity().openersCounter.opened) {
BlockState blockData = this.getTileEntity().getBlockState();
boolean open = blockData.getValue(BarrelBlock.OPEN);
if (!this.getBlockEntity().openersCounter.opened) {
BlockState state = this.getBlockEntity().getBlockState();
boolean open = state.getValue(BarrelBlock.OPEN);
if (!open) {
this.getTileEntity().updateBlockState(blockData, true);
this.getBlockEntity().updateBlockState(state, true);
if (this.getWorldHandle() instanceof net.minecraft.world.level.Level) {
this.getTileEntity().playSound(blockData, SoundEvents.BARREL_OPEN);
this.getBlockEntity().playSound(state, SoundEvents.BARREL_OPEN);
}
}
}
this.getTileEntity().openersCounter.opened = true;
this.getBlockEntity().openersCounter.opened = true;
}
@Override
public void close() {
this.requirePlaced();
if (this.getTileEntity().openersCounter.opened) {
BlockState blockData = this.getTileEntity().getBlockState();
this.getTileEntity().updateBlockState(blockData, false);
if (this.getBlockEntity().openersCounter.opened) {
BlockState state = this.getBlockEntity().getBlockState();
this.getBlockEntity().updateBlockState(state, false);
if (this.getWorldHandle() instanceof net.minecraft.world.level.Level) {
this.getTileEntity().playSound(blockData, SoundEvents.BARREL_CLOSE);
this.getBlockEntity().playSound(state, SoundEvents.BARREL_CLOSE);
}
}
this.getTileEntity().openersCounter.opened = false;
this.getBlockEntity().openersCounter.opened = false;
}
@Override
@@ -77,7 +77,7 @@ public class CraftBarrel extends CraftLootable<BarrelBlockEntity> implements Bar
// Paper start - More Lidded Block API
@Override
public boolean isOpen() {
return getTileEntity().openersCounter.opened;
return getBlockEntity().openersCounter.opened;
}
// Paper end - More Lidded Block API
}

View File

@@ -4,9 +4,10 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import net.minecraft.advancements.critereon.DataComponentMatchers;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.advancements.critereon.MinMaxBounds;
import net.minecraft.core.component.DataComponentPredicate;
import net.minecraft.core.component.DataComponentExactPredicate;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.world.LockCode;
@@ -26,8 +27,8 @@ import org.bukkit.potion.PotionEffectType;
public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implements Beacon {
public CraftBeacon(World world, BeaconBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBeacon(World world, BeaconBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBeacon(CraftBeacon state, Location location) {
@@ -38,12 +39,12 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
public Collection<LivingEntity> getEntitiesInRange() {
this.ensureNoWorldGeneration();
BlockEntity tileEntity = this.getTileEntityFromWorld();
if (tileEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) tileEntity;
BlockEntity blockEntity = this.getBlockEntityFromWorld();
if (blockEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) blockEntity;
Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels, beacon); // Paper - Custom beacon ranges
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
Collection<LivingEntity> bukkit = new ArrayList<>(nms.size());
for (Player human : nms) {
bukkit.add(human.getBukkitEntity());
@@ -53,7 +54,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
}
// block is no longer a beacon
return new ArrayList<LivingEntity>();
return new ArrayList<>();
}
@Override
@@ -81,18 +82,16 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
this.getSnapshot().secondaryPower = (effect != null) ? CraftPotionEffectType.bukkitToMinecraftHolder(effect) : null;
}
// Paper start
@Override
public net.kyori.adventure.text.Component customName() {
final BeaconBlockEntity be = this.getSnapshot();
return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null;
final BeaconBlockEntity beacon = this.getSnapshot();
return beacon.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(beacon.name) : null;
}
@Override
public void customName(final net.kyori.adventure.text.Component customName) {
this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null);
}
// Paper end
@Override
public String getCustomName() {
@@ -112,7 +111,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
@Override
public String getLock() {
Optional<? extends Component> customName = this.getSnapshot().lockKey.predicate().components().asPatch().get(DataComponents.CUSTOM_NAME);
Optional<? extends Component> customName = this.getSnapshot().lockKey.predicate().components().exact().asPatch().get(DataComponents.CUSTOM_NAME);
return (customName != null) ? customName.map(CraftChatMessage::fromComponent).orElse("") : "";
}
@@ -122,8 +121,8 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
if (key == null) {
this.getSnapshot().lockKey = LockCode.NO_LOCK;
} else {
DataComponentPredicate predicate = DataComponentPredicate.builder().expect(DataComponents.CUSTOM_NAME, CraftChatMessage.fromStringOrNull(key)).build();
this.getSnapshot().lockKey = new LockCode(new ItemPredicate(Optional.empty(), MinMaxBounds.Ints.ANY, predicate, Collections.emptyMap()));
DataComponentExactPredicate predicate = DataComponentExactPredicate.builder().expect(DataComponents.CUSTOM_NAME, CraftChatMessage.fromStringOrNull(key)).build();
this.getSnapshot().lockKey = new LockCode(new ItemPredicate(Optional.empty(), MinMaxBounds.Ints.ANY, new DataComponentMatchers(predicate, Collections.emptyMap())));
}
}

View File

@@ -8,8 +8,8 @@ import org.bukkit.block.Bed;
public class CraftBed extends CraftBlockEntityState<BedBlockEntity> implements Bed {
public CraftBed(World world, BedBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBed(World world, BedBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBed(CraftBed state, Location location) {
@@ -18,42 +18,25 @@ public class CraftBed extends CraftBlockEntityState<BedBlockEntity> implements B
@Override
public DyeColor getColor() {
switch (this.getType()) {
case BLACK_BED:
return DyeColor.BLACK;
case BLUE_BED:
return DyeColor.BLUE;
case BROWN_BED:
return DyeColor.BROWN;
case CYAN_BED:
return DyeColor.CYAN;
case GRAY_BED:
return DyeColor.GRAY;
case GREEN_BED:
return DyeColor.GREEN;
case LIGHT_BLUE_BED:
return DyeColor.LIGHT_BLUE;
case LIGHT_GRAY_BED:
return DyeColor.LIGHT_GRAY;
case LIME_BED:
return DyeColor.LIME;
case MAGENTA_BED:
return DyeColor.MAGENTA;
case ORANGE_BED:
return DyeColor.ORANGE;
case PINK_BED:
return DyeColor.PINK;
case PURPLE_BED:
return DyeColor.PURPLE;
case RED_BED:
return DyeColor.RED;
case WHITE_BED:
return DyeColor.WHITE;
case YELLOW_BED:
return DyeColor.YELLOW;
default:
throw new IllegalArgumentException("Unknown DyeColor for " + this.getType());
}
return switch (this.getType()) {
case BLACK_BED -> DyeColor.BLACK;
case BLUE_BED -> DyeColor.BLUE;
case BROWN_BED -> DyeColor.BROWN;
case CYAN_BED -> DyeColor.CYAN;
case GRAY_BED -> DyeColor.GRAY;
case GREEN_BED -> DyeColor.GREEN;
case LIGHT_BLUE_BED -> DyeColor.LIGHT_BLUE;
case LIGHT_GRAY_BED -> DyeColor.LIGHT_GRAY;
case LIME_BED -> DyeColor.LIME;
case MAGENTA_BED -> DyeColor.MAGENTA;
case ORANGE_BED -> DyeColor.ORANGE;
case PINK_BED -> DyeColor.PINK;
case PURPLE_BED -> DyeColor.PURPLE;
case RED_BED -> DyeColor.RED;
case WHITE_BED -> DyeColor.WHITE;
case YELLOW_BED -> DyeColor.YELLOW;
default -> throw new IllegalArgumentException("Unknown DyeColor for " + this.getType());
};
}
@Override

View File

@@ -16,8 +16,8 @@ import org.bukkit.entity.Bee;
public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> implements Beehive {
public CraftBeehive(World world, BeehiveBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBeehive(World world, BeehiveBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBeehive(CraftBeehive state, Location location) {
@@ -43,7 +43,7 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
@Override
public boolean isSedated() {
return this.isPlaced() && this.getTileEntity().isSedated();
return this.isPlaced() && this.getBlockEntity().isSedated();
}
@Override
@@ -70,7 +70,7 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
List<Bee> bees = new ArrayList<>();
if (this.isPlaced()) {
BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getTileEntityFromWorld());
BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getBlockEntityFromWorld());
for (Entity bee : beehive.releaseBees(this.getHandle(), BeeReleaseStatus.BEE_RELEASED, true)) {
bees.add((Bee) bee.getBukkitEntity());
}

View File

@@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.BellBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BellBlockEntity;
@@ -15,8 +14,8 @@ import org.bukkit.entity.Entity;
public class CraftBell extends CraftBlockEntityState<BellBlockEntity> implements Bell {
public CraftBell(World world, BellBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBell(World world, BellBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBell(CraftBell state, Location location) {
@@ -27,30 +26,13 @@ public class CraftBell extends CraftBlockEntityState<BellBlockEntity> implements
public boolean ring(Entity entity, BlockFace direction) {
Preconditions.checkArgument(direction == null || direction.isCartesian(), "direction must be cartesian, given %s", direction);
BlockEntity tileEntity = this.getTileEntityFromWorld();
if (tileEntity == null) {
BlockEntity blockEntity = this.getBlockEntityFromWorld();
if (blockEntity == null) {
return false;
}
net.minecraft.world.entity.Entity nmsEntity = (entity != null) ? ((CraftEntity) entity).getHandle() : null;
Direction enumDirection = CraftBlock.blockFaceToNotch(direction);
return ((BellBlock) Blocks.BELL).attemptToRing(nmsEntity, this.world.getHandle(), this.getPosition(), enumDirection);
}
@Override
public boolean ring(Entity entity) {
return this.ring(entity, null);
}
@Override
public boolean ring(BlockFace direction) {
return this.ring(null, direction);
}
@Override
public boolean ring() {
return this.ring(null, null);
return ((BellBlock) Blocks.BELL).attemptToRing(nmsEntity, this.world.getHandle(), this.getPosition(), CraftBlock.blockFaceToNotch(direction));
}
@Override

View File

@@ -1,15 +1,19 @@
package org.bukkit.craftbukkit.block;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.Objects;
public class CraftBiome implements Biome, Handleable<net.minecraft.world.level.biome.Biome> {
@NullMarked
public class CraftBiome extends OldEnumHolderable<Biome, net.minecraft.world.level.biome.Biome> implements Biome {
private static int count = 0;
@@ -18,10 +22,10 @@ public class CraftBiome implements Biome, Handleable<net.minecraft.world.level.b
}
public static Biome minecraftHolderToBukkit(Holder<net.minecraft.world.level.biome.Biome> minecraft) {
return CraftBiome.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.BIOME);
}
public static net.minecraft.world.level.biome.Biome bukkitToMinecraft(Biome bukkit) {
public static net.minecraft.world.level.biome.@Nullable Biome bukkitToMinecraft(Biome bukkit) {
if (bukkit == Biome.CUSTOM) {
return null;
}
@@ -29,89 +33,68 @@ public class CraftBiome implements Biome, Handleable<net.minecraft.world.level.b
return CraftRegistry.bukkitToMinecraft(bukkit);
}
public static Holder<net.minecraft.world.level.biome.Biome> bukkitToMinecraftHolder(Biome bukkit) {
public static @Nullable Holder<net.minecraft.world.level.biome.Biome> bukkitToMinecraftHolder(Biome bukkit) {
if (bukkit == Biome.CUSTOM) {
return null;
}
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.BIOME);
}
net.minecraft.core.Registry<net.minecraft.world.level.biome.Biome> registry = CraftRegistry.getMinecraftRegistry(Registries.BIOME);
public CraftBiome(final Holder<net.minecraft.world.level.biome.Biome> holder) {
super(holder, count++);
}
if (registry.wrapAsHolder(CraftBiome.bukkitToMinecraft(bukkit)) instanceof Holder.Reference<net.minecraft.world.level.biome.Biome> holder) {
return holder;
/**
* Implementation for the deprecated, API only, CUSTOM biome.
* As per {@link #bukkitToMinecraft(Biome)} and {@link #bukkitToMinecraftHolder(Biome)} it cannot be
* converted into an internal biome and only serves backwards compatibility reasons.
*/
@Deprecated(forRemoval = true, since = "1.21.5")
@ApiStatus.ScheduledForRemoval(inVersion = "1.22")
public static class LegacyCustomBiomeImpl implements Biome {
private static final NamespacedKey LEGACY_CUSTOM_KEY = new NamespacedKey("minecraft", "custom");
private final int ordinal;
public LegacyCustomBiomeImpl() {
this.ordinal = count++;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own biome base with out properly registering it.");
}
private final NamespacedKey key;
private final net.minecraft.world.level.biome.Biome biomeBase;
private final String name;
private final int ordinal;
public CraftBiome(NamespacedKey key, net.minecraft.world.level.biome.Biome biomeBase) {
this.key = key;
this.biomeBase = biomeBase;
// For backwards compatibility, minecraft values will stile return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive biome specific values.
// Custom biomes will return the key with namespace. For a plugin this should look than like a new biome
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftBiome.count++;
}
@Override
public net.minecraft.world.level.biome.Biome getHandle() {
return this.biomeBase;
}
@NotNull
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(@NotNull Biome biome) {
return this.ordinal - biome.ordinal();
}
@NotNull
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
@Override
public @NotNull NamespacedKey getKey() {
return LEGACY_CUSTOM_KEY;
}
if (!(other instanceof CraftBiome otherBiome)) {
return false;
@Override
public int compareTo(@NotNull final Biome other) {
return this.ordinal - other.ordinal();
}
return this.getKey().equals(otherBiome.getKey());
}
@Override
public @NotNull String name() {
return "CUSTOM";
}
@Override
public int hashCode() {
return this.getKey().hashCode();
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public boolean equals(final Object object) {
if (object == null || getClass() != object.getClass()) return false;
final LegacyCustomBiomeImpl that = (LegacyCustomBiomeImpl) object;
return ordinal == that.ordinal;
}
@Override
public int hashCode() {
return Objects.hashCode(ordinal);
}
@Override
public String toString() {
return "CUSTOM";
}
}
}

View File

@@ -7,8 +7,8 @@ import org.bukkit.block.BlastFurnace;
public class CraftBlastFurnace extends CraftFurnace<BlastFurnaceBlockEntity> implements BlastFurnace {
public CraftBlastFurnace(World world, BlastFurnaceBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBlastFurnace(World world, BlastFurnaceBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBlastFurnace(CraftBlastFurnace state, Location location) {

View File

@@ -78,11 +78,9 @@ public class CraftBlock implements Block {
return this.world.getBlockState(this.position);
}
// Paper start
public net.minecraft.world.level.material.FluidState getNMSFluid() {
return this.world.getFluidState(this.position);
}
// Paper end
public BlockPos getPosition() {
return this.position;
@@ -145,25 +143,25 @@ public class CraftBlock implements Block {
}
public void setData(final byte data) {
this.setData(data, 3);
this.setData(data, net.minecraft.world.level.block.Block.UPDATE_ALL);
}
public void setData(final byte data, boolean applyPhysics) {
if (applyPhysics) {
this.setData(data, 3);
this.setData(data, net.minecraft.world.level.block.Block.UPDATE_ALL);
} else {
this.setData(data, 2);
this.setData(data, net.minecraft.world.level.block.Block.UPDATE_CLIENTS);
}
}
private void setData(final byte data, int flag) {
this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flag);
private void setData(final byte data, int flags) {
this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flags);
}
@Override
public byte getData() {
net.minecraft.world.level.block.state.BlockState blockData = this.world.getBlockState(this.position);
return CraftMagicNumbers.toLegacyData(blockData);
net.minecraft.world.level.block.state.BlockState state = this.world.getBlockState(this.position);
return CraftMagicNumbers.toLegacyData(state);
}
@Override
@@ -190,34 +188,37 @@ public class CraftBlock implements Block {
@Override
public void setBlockData(BlockData data, boolean applyPhysics) {
Preconditions.checkArgument(data != null, "BlockData cannot be null");
this.setTypeAndData(((CraftBlockData) data).getState(), applyPhysics);
this.setBlockState(((CraftBlockData) data).getState(), applyPhysics);
}
boolean setTypeAndData(final net.minecraft.world.level.block.state.BlockState blockData, final boolean applyPhysics) {
return CraftBlock.setTypeAndData(this.world, this.position, this.getNMS(), blockData, applyPhysics);
boolean setBlockState(final net.minecraft.world.level.block.state.BlockState state, final boolean applyPhysics) {
return CraftBlock.setBlockState(this.world, this.position, this.getNMS(), state, applyPhysics);
}
public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) {
// SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup
if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes
public static boolean setBlockState(LevelAccessor world, BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, boolean applyPhysics) {
// SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in block entity cleanup
if (oldState.hasBlockEntity() && newState.getBlock() != oldState.getBlock()) { // SPIGOT-3725 remove old block entity if block changes
// SPIGOT-4612: faster - just clear tile
if (world instanceof net.minecraft.world.level.Level) {
((net.minecraft.world.level.Level) world).removeBlockEntity(position);
((net.minecraft.world.level.Level) world).removeBlockEntity(pos);
} else {
world.setBlock(position, Blocks.AIR.defaultBlockState(), 0);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 0);
}
}
if (applyPhysics) {
return world.setBlock(position, blockData, 3);
return world.setBlock(pos, newState, net.minecraft.world.level.block.Block.UPDATE_ALL);
} else {
boolean success = world.setBlock(position, blockData, 2 | 16 | 1024); // NOTIFY | NO_OBSERVER | NO_PLACE (custom)
boolean success = world.setBlock(pos, newState,
net.minecraft.world.level.block.Block.UPDATE_CLIENTS |
net.minecraft.world.level.block.Block.UPDATE_KNOWN_SHAPE |
net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE);
if (success && world instanceof net.minecraft.world.level.Level) {
world.getMinecraftWorld().sendBlockUpdated(
position,
old,
blockData,
3
pos,
oldState,
newState,
net.minecraft.world.level.block.Block.UPDATE_ALL
);
}
return success;
@@ -282,7 +283,7 @@ public class CraftBlock implements Block {
@Override
public String toString() {
return "CraftBlock{pos=" + this.position + ",type=" + this.getType() + ",data=" + this.getNMS() + ",fluid=" + this.world.getFluidState(this.position) + '}';
return "CraftBlock{pos=" + this.position + ",type=" + this.getType() + ",data=" + this.getNMS() + ",fluid=" + this.getNMSFluid() + '}';
}
public static BlockFace notchToBlockFace(Direction notch) {
@@ -406,7 +407,7 @@ public class CraftBlock implements Block {
Block relative = this.getRelative(face);
if (relative.getType() == Material.REDSTONE_WIRE) {
return Math.max(power, relative.getData()) > 0;
return Math.max(power, relative.getData()) > 0; // todo remove legacy usage
}
return power > 0;
@@ -428,13 +429,11 @@ public class CraftBlock implements Block {
return power > 0 ? power : (face == BlockFace.SELF ? this.isBlockIndirectlyPowered() : this.isBlockFaceIndirectlyPowered(face)) ? 15 : 0;
}
private static int getPower(int i, net.minecraft.world.level.block.state.BlockState iblockdata) {
if (!iblockdata.is(Blocks.REDSTONE_WIRE)) {
return i;
private static int getPower(int power, net.minecraft.world.level.block.state.BlockState state) {
if (!state.is(Blocks.REDSTONE_WIRE)) {
return power;
} else {
int j = iblockdata.getValue(RedStoneWireBlock.POWER);
return j > i ? j : i;
return Math.max(state.getValue(RedStoneWireBlock.POWER), power);
}
}
@@ -502,39 +501,39 @@ public class CraftBlock implements Block {
public boolean breakNaturally(ItemStack item, boolean triggerEffect, boolean dropExperience) {
// Paper end
// Order matters here, need to drop before setting to air so skulls can get their data
net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS();
net.minecraft.world.level.block.Block block = iblockdata.getBlock();
net.minecraft.world.level.block.state.BlockState state = this.getNMS();
net.minecraft.world.level.block.Block block = state.getBlock();
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
boolean result = false;
// Modelled off EntityHuman#hasBlock
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem, false); // Paper - Properly handle xp dropping
// Paper start - improve Block#breanNaturally
// Modelled off Player#hasCorrectToolForDrops
if (block != Blocks.AIR && (item == null || !state.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(state))) {
net.minecraft.world.level.block.Block.dropResources(state, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem, false); // Paper - Properly handle xp dropping
// Paper start - improve Block#breakNaturally
if (triggerEffect) {
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
if (state.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.SOUND_EXTINGUISH_FIRE, this.position, 0);
} else {
this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK, this.position, net.minecraft.world.level.block.Block.getId(iblockdata));
this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK, this.position, net.minecraft.world.level.block.Block.getId(state));
}
}
if (dropExperience) block.popExperience(this.world.getMinecraftWorld(), this.position, block.getExpDrop(iblockdata, this.world.getMinecraftWorld(), this.position, nmsItem, true));
if (dropExperience) block.popExperience(this.world.getMinecraftWorld(), this.position, block.getExpDrop(state, this.world.getMinecraftWorld(), this.position, nmsItem, true));
// Paper end
result = true;
}
// SPIGOT-6778: Directly call setBlock instead of setTypeAndData, so that the tile entiy is not removed and custom remove logic is run.
// SPIGOT-6778: Directly call setBlock instead of setBlockState, so that the block entity is not removed and custom remove logic is run.
// Paper start - improve breakNaturally
boolean destroyed = this.world.removeBlock(this.position, false);
if (destroyed) {
block.destroy(this.world, this.position, iblockdata);
block.destroy(this.world, this.position, state);
}
if (result) {
// special cases
if (block instanceof net.minecraft.world.level.block.IceBlock iceBlock) {
iceBlock.afterDestroy(this.world.getMinecraftWorld(), this.position, nmsItem);
} else if (block instanceof net.minecraft.world.level.block.TurtleEggBlock turtleEggBlock) {
turtleEggBlock.decreaseEggs(this.world.getMinecraftWorld(), this.position, iblockdata);
turtleEggBlock.decreaseEggs(this.world.getMinecraftWorld(), this.position, state);
}
}
return destroyed && result;
@@ -553,26 +552,27 @@ public class CraftBlock implements Block {
InteractionResult result = BoneMealItem.applyBonemeal(context);
world.captureTreeGeneration = false;
if (world.capturedBlockStates.size() > 0) {
if (!world.capturedBlockStates.isEmpty()) {
TreeType treeType = SaplingBlock.treeType;
SaplingBlock.treeType = null;
List<BlockState> blocks = new ArrayList<>(world.capturedBlockStates.values());
List<BlockState> states = new ArrayList<>(world.capturedBlockStates.values());
world.capturedBlockStates.clear();
StructureGrowEvent structureEvent = null;
if (treeType != null) {
structureEvent = new StructureGrowEvent(this.getLocation(), treeType, true, null, blocks);
structureEvent = new StructureGrowEvent(this.getLocation(), treeType, true, null, states);
Bukkit.getPluginManager().callEvent(structureEvent);
}
event = new BlockFertilizeEvent(CraftBlock.at(world, this.getPosition()), null, blocks);
event = new BlockFertilizeEvent(CraftBlock.at(world, this.getPosition()), null, states);
event.setCancelled(structureEvent != null && structureEvent.isCancelled());
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
for (BlockState blockstate : blocks) {
blockstate.update(true);
world.checkCapturedTreeStateForObserverNotify(this.position, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
for (BlockState state : states) {
CraftBlockState craftBlockState = (CraftBlockState) state;
craftBlockState.place(craftBlockState.getFlags());
world.checkCapturedTreeStateForObserverNotify(this.position, craftBlockState); // Paper - notify observers even if grow failed
}
}
}
@@ -592,12 +592,12 @@ public class CraftBlock implements Block {
@Override
public Collection<ItemStack> getDrops(ItemStack item, Entity entity) {
net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS();
net.minecraft.world.level.block.state.BlockState state = this.getNMS();
net.minecraft.world.item.ItemStack nms = CraftItemStack.asNMSCopy(item);
// Modelled off EntityHuman#hasBlock
if (item == null || CraftBlockData.isPreferredTool(iblockdata, nms)) {
return net.minecraft.world.level.block.Block.getDrops(iblockdata, (ServerLevel) this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), entity == null ? null : ((CraftEntity) entity).getHandle(), nms)
// Modelled off Player#hasCorrectToolForDrops
if (item == null || CraftBlockData.isPreferredTool(state, nms)) {
return net.minecraft.world.level.block.Block.getDrops(state, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), entity == null ? null : ((CraftEntity) entity).getHandle(), nms)
.stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
} else {
return Collections.emptyList();
@@ -606,9 +606,9 @@ public class CraftBlock implements Block {
@Override
public boolean isPreferredTool(ItemStack item) {
net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS();
net.minecraft.world.level.block.state.BlockState state = this.getNMS();
net.minecraft.world.item.ItemStack nms = CraftItemStack.asNMSCopy(item);
return CraftBlockData.isPreferredTool(iblockdata, nms);
return CraftBlockData.isPreferredTool(state, nms);
}
@Override
@@ -658,11 +658,11 @@ public class CraftBlock implements Block {
}
Vector dir = direction.clone().normalize().multiply(maxDistance);
Vec3 startPos = CraftLocation.toVec3D(start);
Vec3 startPos = CraftLocation.toVec3(start);
Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
HitResult nmsHitResult = this.world.clip(new ClipContext(startPos, endPos, ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), this.position);
return CraftRayTraceResult.fromNMS(this.getWorld(), nmsHitResult);
HitResult hitResult = this.world.clip(new ClipContext(startPos, endPos, ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toFluid(fluidCollisionMode), CollisionContext.empty()), this.position);
return CraftRayTraceResult.convertFromInternal(this.world, hitResult);
}
@Override

View File

@@ -9,12 +9,12 @@ 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.server.MinecraftServer;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.TileState;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;
@@ -22,25 +22,25 @@ import org.jetbrains.annotations.Nullable;
public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
private final T tileEntity;
private final T blockEntity;
private final T snapshot;
public boolean snapshotDisabled; // Paper
public static boolean DISABLE_SNAPSHOT = false; // Paper
public CraftBlockEntityState(World world, T tileEntity) {
super(world, tileEntity.getBlockPos(), tileEntity.getBlockState());
public CraftBlockEntityState(World world, T blockEntity) {
super(world, blockEntity.getBlockPos(), blockEntity.getBlockState());
this.tileEntity = tileEntity;
this.blockEntity = blockEntity;
try { // Paper - Show blockstate location if we failed to read it
// Paper start
this.snapshotDisabled = DISABLE_SNAPSHOT;
if (DISABLE_SNAPSHOT) {
this.snapshot = this.tileEntity;
this.snapshot = this.blockEntity;
} else {
this.snapshot = this.createSnapshot(tileEntity);
this.snapshot = this.createSnapshot(blockEntity);
}
// copy tile entity data:
// copy block entity data:
if (this.snapshot != null) {
this.load(this.snapshot);
}
@@ -62,29 +62,27 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
protected CraftBlockEntityState(CraftBlockEntityState<T> state, Location location) {
super(state, location);
this.tileEntity = this.createSnapshot(state.snapshot);
this.snapshot = this.tileEntity;
this.blockEntity = this.createSnapshot(state.snapshot);
this.snapshot = this.blockEntity;
this.loadData(state.getSnapshotNBT());
}
public void refreshSnapshot() {
this.load(this.tileEntity);
this.load(this.blockEntity);
}
private RegistryAccess getRegistryAccess() {
LevelAccessor worldHandle = this.getWorldHandle();
return (worldHandle != null) ? worldHandle.registryAccess() : MinecraftServer.getDefaultRegistryAccess();
return (worldHandle != null) ? worldHandle.registryAccess() : CraftRegistry.getMinecraftRegistry();
}
private T createSnapshot(T tileEntity) {
if (tileEntity == null) {
private T createSnapshot(T from) {
if (from == null) {
return null;
}
CompoundTag nbtTagCompound = tileEntity.saveWithFullMetadata(this.getRegistryAccess());
T snapshot = (T) BlockEntity.loadStatic(this.getPosition(), this.getHandle(), nbtTagCompound, this.getRegistryAccess());
return snapshot;
CompoundTag tag = from.saveWithFullMetadata(this.getRegistryAccess());
return (T) BlockEntity.loadStatic(this.getPosition(), this.getHandle(), tag, this.getRegistryAccess());
}
public Set<DataComponentType<?>> applyComponents(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) {
@@ -97,36 +95,36 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
return this.snapshot.collectComponents();
}
// Loads the specified data into the snapshot TileEntity.
public void loadData(CompoundTag nbtTagCompound) {
this.snapshot.loadWithComponents(nbtTagCompound, this.getRegistryAccess());
// Loads the specified data into the snapshot BlockEntity.
public void loadData(CompoundTag tag) {
this.snapshot.loadWithComponents(tag, this.getRegistryAccess());
this.load(this.snapshot);
}
// copies the TileEntity-specific data, retains the position
// copies the BlockEntity-specific data, retains the position
private void copyData(T from, T to) {
CompoundTag nbtTagCompound = from.saveWithFullMetadata(this.getRegistryAccess());
to.loadWithComponents(nbtTagCompound, this.getRegistryAccess());
CompoundTag tag = from.saveWithFullMetadata(this.getRegistryAccess());
to.loadWithComponents(tag, this.getRegistryAccess());
}
// gets the wrapped TileEntity
public T getTileEntity() {
return this.tileEntity;
// gets the wrapped BlockEntity
public T getBlockEntity() {
return this.blockEntity;
}
// gets the cloned TileEntity which is used to store the captured data
// gets the cloned BlockEntity which is used to store the captured data
protected T getSnapshot() {
return this.snapshot;
}
// gets the current TileEntity from the world at this position
protected BlockEntity getTileEntityFromWorld() {
// gets the current BlockEntity from the world at this position
protected BlockEntity getBlockEntityFromWorld() {
this.requirePlaced();
return this.getWorldHandle().getBlockEntity(this.getPosition());
}
// gets the NBT data of the TileEntity represented by this block state
// gets the NBT data of the BlockEntity represented by this block state
public CompoundTag getSnapshotNBT() {
// update snapshot
this.applyTo(this.snapshot);
@@ -134,21 +132,7 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
return this.snapshot.saveWithFullMetadata(this.getRegistryAccess());
}
public CompoundTag getItemNBT() {
// update snapshot
this.applyTo(this.snapshot);
// See TileEntity#saveToItem
CompoundTag nbt = this.snapshot.saveCustomOnly(this.getRegistryAccess());
this.snapshot.removeComponentsFromTag(nbt);
return nbt;
}
public void addEntityType(CompoundTag nbt) {
BlockEntity.addEntityType(nbt, this.snapshot.getType());
}
// gets the packet data of the TileEntity represented by this block state
// gets the packet data of the BlockEntity represented by this block state
public CompoundTag getUpdateNBT() {
// update snapshot
this.applyTo(this.snapshot);
@@ -169,40 +153,47 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
}
// Paper end
// copies the data of the given tile entity to this block state
protected void load(T tileEntity) {
if (tileEntity != null && tileEntity != this.snapshot) {
this.copyData(tileEntity, this.snapshot);
// copies the data of the given block entity to this block state
protected void load(T blockEntity) {
if (blockEntity != null && blockEntity != this.snapshot) {
this.copyData(blockEntity, this.snapshot);
}
}
// applies the TileEntity data of this block state to the given TileEntity
protected void applyTo(T tileEntity) {
if (tileEntity != null && tileEntity != this.snapshot) {
this.copyData(this.snapshot, tileEntity);
// applies the BlockEntity data of this block state to the given BlockEntity
protected void applyTo(T blockEntity) {
if (blockEntity != null && blockEntity != this.snapshot) {
this.copyData(this.snapshot, blockEntity);
}
}
protected boolean isApplicable(BlockEntity tileEntity) {
return tileEntity != null && this.tileEntity.getClass() == tileEntity.getClass();
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result && this.isPlaced()) {
BlockEntity tile = this.getTileEntityFromWorld();
if (this.isApplicable(tile)) {
this.applyTo((T) tile);
tile.setChanged();
}
this.getWorldHandle().getBlockEntity(this.getPosition(), this.blockEntity.getType()).ifPresent(blockEntity -> {
this.applyTo((T) blockEntity);
blockEntity.setChanged();
});
}
return result;
}
@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;
}
return false;
}
@Override
public PersistentDataContainer getPersistentDataContainer() {
return this.getSnapshot().persistentDataContainer;

View File

@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelAccessor;
@@ -27,26 +28,27 @@ public class CraftBlockState implements BlockState {
protected final CraftWorld world;
private final BlockPos position;
protected net.minecraft.world.level.block.state.BlockState data;
protected int flag;
protected int capturedFlags; // todo move out of this class
private WeakReference<LevelAccessor> weakWorld;
protected CraftBlockState(final Block block) {
this(block.getWorld(), ((CraftBlock) block).getPosition(), ((CraftBlock) block).getNMS());
this.flag = 3;
this.capturedFlags = net.minecraft.world.level.block.Block.UPDATE_ALL;
this.setWorldHandle(((CraftBlock) block).getHandle());
}
protected CraftBlockState(final Block block, int flag) {
@Deprecated
protected CraftBlockState(final Block block, int capturedFlags) {
this(block);
this.flag = flag;
this.capturedFlags = capturedFlags;
}
// world can be null for non-placed BlockStates.
protected CraftBlockState(@Nullable World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData) {
protected CraftBlockState(@Nullable World world, BlockPos pos, net.minecraft.world.level.block.state.BlockState data) {
this.world = (CraftWorld) world;
this.position = blockPosition;
this.data = blockData;
this.position = pos;
this.data = data;
}
// Creates an unplaced copy of the given CraftBlockState at the given location
@@ -59,7 +61,7 @@ public class CraftBlockState implements BlockState {
this.position = CraftLocation.toBlockPosition(location);
}
this.data = state.data;
this.flag = state.flag;
this.capturedFlags = state.capturedFlags;
this.setWorldHandle(state.getWorldHandle());
}
@@ -178,12 +180,12 @@ public class CraftBlockState implements BlockState {
return this.data.getBukkitMaterial(); // Paper - optimise getType calls
}
public void setFlag(int flag) {
this.flag = flag;
public void setFlags(int flags) {
this.capturedFlags = flags;
}
public int getFlag() {
return this.flag;
public int getFlags() {
return this.capturedFlags;
}
@Override
@@ -222,13 +224,13 @@ public class CraftBlockState implements BlockState {
}
net.minecraft.world.level.block.state.BlockState newBlock = this.data;
block.setTypeAndData(newBlock, applyPhysics);
block.setBlockState(newBlock, applyPhysics);
if (access instanceof net.minecraft.world.level.Level) {
this.world.getHandle().sendBlockUpdated(
this.position,
block.getNMS(),
newBlock,
3
this.position,
block.getNMS(),
newBlock,
net.minecraft.world.level.block.Block.UPDATE_ALL
);
}
@@ -240,6 +242,26 @@ public class CraftBlockState implements BlockState {
return true;
}
// used when the flags matter for non API usage
public boolean place(int flags) {
if (!this.isPlaced()) {
return false;
}
return this.getWorldHandle().setBlock(this.position, this.data, flags);
}
// used to revert a block placement due to an event being cancelled for example
public boolean revertPlace() {
return this.place(
net.minecraft.world.level.block.Block.UPDATE_CLIENTS |
net.minecraft.world.level.block.Block.UPDATE_KNOWN_SHAPE |
net.minecraft.world.level.block.Block.UPDATE_SUPPRESS_DROPS |
net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE |
net.minecraft.world.level.block.Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS
);
}
@Override
public byte getRawData() {
return CraftMagicNumbers.toLegacyData(this.data);
@@ -278,16 +300,9 @@ public class CraftBlockState implements BlockState {
return false;
}
final CraftBlockState other = (CraftBlockState) obj;
if (this.world != other.world && (this.world == null || !this.world.equals(other.world))) {
return false;
}
if (this.position != other.position && (this.position == null || !this.position.equals(other.position))) {
return false;
}
if (this.data != other.data && (this.data == null || !this.data.equals(other.data))) {
return false;
}
return true;
return Objects.equals(this.world, other.world) &&
Objects.equals(this.position, other.position) &&
Objects.equals(this.data, other.data);
}
@Override
@@ -353,13 +368,13 @@ public class CraftBlockState implements BlockState {
this.requirePlaced();
net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item);
// Modelled off EntityHuman#hasBlock
if (item == null || !data.requiresCorrectToolForDrops() || nms.isCorrectToolForDrops(data)) {
// Modelled off Player#hasCorrectToolForDrops
if (item == null || !data.requiresCorrectToolForDrops() || nms.isCorrectToolForDrops(this.data)) {
return net.minecraft.world.level.block.Block.getDrops(
data,
world.getHandle(),
position,
world.getHandle().getBlockEntity(position), entity == null ? null :
this.data,
this.world.getHandle(),
this.position,
this.world.getHandle().getBlockEntity(this.position), entity == null ? null :
((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle(), nms
).stream().map(org.bukkit.craftbukkit.inventory.CraftItemStack::asBukkitCopy).toList();
} else {

View File

@@ -1,70 +1,22 @@
package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BarrelBlockEntity;
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.entity.BedBlockEntity;
import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
import net.minecraft.world.level.block.entity.BellBlockEntity;
import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.entity.ChiseledBookShelfBlockEntity;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.block.entity.ComparatorBlockEntity;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.level.block.entity.CrafterBlockEntity;
import net.minecraft.world.level.block.entity.CreakingHeartBlockEntity;
import net.minecraft.world.level.block.entity.DaylightDetectorBlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
import net.minecraft.world.level.block.entity.DropperBlockEntity;
import net.minecraft.world.level.block.entity.EnchantingTableBlockEntity;
import net.minecraft.world.level.block.entity.EnderChestBlockEntity;
import net.minecraft.world.level.block.entity.FurnaceBlockEntity;
import net.minecraft.world.level.block.entity.HangingSignBlockEntity;
import net.minecraft.world.level.block.entity.HopperBlockEntity;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.world.level.block.entity.JukeboxBlockEntity;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
import net.minecraft.world.level.block.entity.SculkCatalystBlockEntity;
import net.minecraft.world.level.block.entity.SculkSensorBlockEntity;
import net.minecraft.world.level.block.entity.SculkShriekerBlockEntity;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.entity.SmokerBlockEntity;
import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity;
import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity;
import net.minecraft.world.level.block.entity.TrappedChestBlockEntity;
import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity;
import net.minecraft.world.level.block.entity.vault.VaultBlockEntity;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftWorld;
public final class CraftBlockStates {
@@ -78,108 +30,110 @@ public final class CraftBlockStates {
}
// The given world can be null for unplaced BlockStates.
// If the world is not null and the given block data is a tile entity, the given tile entity is expected to not be null.
// Otherwise, the given tile entity may or may not be null.
// If the given tile entity is not null, its position and block data are expected to match the given block position and block data.
// In some situations, such as during chunk generation, the tile entity's world may be null, even if the given world is not null.
// If the tile entity's world is not null, it is expected to match the given world.
public abstract B createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity);
// If the world is not null and the given block data is a block entity, the given block entity is expected to not be null.
// Otherwise, the given block entity may or may not be null.
// If the given block entity is not null, its position and block data are expected to match the given block position and block data.
// In some situations, such as during chunk generation, the block entity's world may be null, even if the given world is not null.
// If the block entity's world is not null, it is expected to match the given world.
public abstract B createBlockState(World world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, BlockEntity blockEntity);
}
private static class BlockEntityStateFactory<T extends BlockEntity, B extends CraftBlockEntityState<T>> extends BlockStateFactory<B> {
private final BiFunction<World, T, B> blockStateConstructor;
private final BlockEntityType<? extends T> tileEntityConstructor; // Paper
private final BlockEntityType<? extends T> blockEntityType;
protected BlockEntityStateFactory(Class<B> blockStateType, BiFunction<World, T, B> blockStateConstructor, BlockEntityType<? extends T> tileEntityConstructor) { // Paper
protected BlockEntityStateFactory(Class<B> blockStateType, BiFunction<World, T, B> blockStateConstructor, BlockEntityType<? extends T> blockEntityType) {
super(blockStateType);
this.blockStateConstructor = blockStateConstructor;
this.tileEntityConstructor = tileEntityConstructor;
this.blockEntityType = blockEntityType;
}
@Override
public final B createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
public final B createBlockState(World world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, BlockEntity blockEntity) {
if (world != null) {
Preconditions.checkState(tileEntity != null, "Tile is null, asynchronous access? %s", CraftBlock.at(((CraftWorld) world).getHandle(), blockPosition));
} else if (tileEntity == null) {
tileEntity = this.createTileEntity(blockPosition, blockData);
Preconditions.checkState(blockEntity != null, "Block entity is null, asynchronous access? %s", CraftBlock.at(((CraftWorld) world).getHandle(), pos));
} else if (blockEntity == null) {
blockEntity = this.createBlockEntity(pos, state);
}
return this.createBlockState(world, (T) tileEntity);
return this.createBlockState(world, (T) blockEntity);
}
private T createTileEntity(BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData) {
return this.tileEntityConstructor.create(blockPosition, blockData); // Paper
private T createBlockEntity(BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
return this.blockEntityType.create(pos, state);
}
private B createBlockState(World world, T tileEntity) {
return this.blockStateConstructor.apply(world, tileEntity);
private B createBlockState(World world, T blockEntity) {
return this.blockStateConstructor.apply(world, blockEntity);
}
}
private static final Map<Material, BlockStateFactory<?>> FACTORIES = new HashMap<>();
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<>(CraftBlockState.class) {
@Override
public CraftBlockState createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
public CraftBlockState createBlockState(World world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, BlockEntity blockEntity) {
// Paper - revert upstream's revert of the block state changes. Block entities that have already had the block type set to AIR are still valid, upstream decided to ignore them
Preconditions.checkState(tileEntity == null, "Unexpected BlockState for %s", CraftBlockType.minecraftToBukkit(blockData.getBlock()));
return new CraftBlockState(world, blockPosition, blockData);
Preconditions.checkState(blockEntity == null, "Unexpected BlockState for %s", CraftBlockType.minecraftToBukkit(state.getBlock()));
return new CraftBlockState(world, pos, state);
}
};
// Paper start
private static final Map<BlockEntityType<?>, BlockStateFactory<?>> FACTORIES_BY_BLOCK_ENTITY_TYPE = new HashMap<>();
private static void register(BlockEntityType<?> type, BlockStateFactory<?> factory) {
FACTORIES_BY_BLOCK_ENTITY_TYPE.put(type, factory);
}
// Paper end
static {
// Paper start - simplify
register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
register(BlockEntityType.HANGING_SIGN, CraftHangingSign.class, CraftHangingSign::new);
register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
// Start generate - CraftBlockEntityStates
// @GeneratedFrom 1.21.5
register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);
register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
register(BlockEntityType.BELL, CraftBell.class, CraftBell::new);
register(BlockEntityType.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new);
register(BlockEntityType.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new);
register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new);
register(BlockEntityType.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new);
register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
register(BlockEntityType.CHEST, CraftChest.class, CraftChest::new);
register(BlockEntityType.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new);
register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
register(BlockEntityType.COMPARATOR, CraftComparator.class, CraftComparator::new);
register(BlockEntityType.CONDUIT, CraftConduit.class, CraftConduit::new);
register(BlockEntityType.CRAFTER, CraftCrafter.class, CraftCrafter::new);
register(BlockEntityType.CREAKING_HEART, CraftCreakingHeart.class, CraftCreakingHeart::new);
register(BlockEntityType.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new);
register(BlockEntityType.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new);
register(BlockEntityType.DISPENSER, CraftDispenser.class, CraftDispenser::new);
register(BlockEntityType.DROPPER, CraftDropper.class, CraftDropper::new);
register(BlockEntityType.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new);
register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
register(BlockEntityType.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new);
register(BlockEntityType.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new);
register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
register(BlockEntityType.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new);
register(BlockEntityType.HANGING_SIGN, CraftHangingSign.class, CraftHangingSign::new);
register(BlockEntityType.HOPPER, CraftHopper.class, CraftHopper::new);
register(BlockEntityType.JIGSAW, CraftJigsaw.class, CraftJigsaw::new);
register(BlockEntityType.JUKEBOX, CraftJukebox.class, CraftJukebox::new);
register(BlockEntityType.LECTERN, CraftLectern.class, CraftLectern::new);
register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
register(BlockEntityType.PISTON, CraftMovingPiston.class, CraftMovingPiston::new);
register(BlockEntityType.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new);
register(BlockEntityType.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new);
register(BlockEntityType.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new);
register(BlockEntityType.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new);
register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new); // note: spigot still uses CraftSuspiciousSand impl for that block type
register(BlockEntityType.TEST_BLOCK, CraftTestBlock.class, CraftTestBlock::new);
register(BlockEntityType.TEST_INSTANCE_BLOCK, CraftTestInstanceBlock.class, CraftTestInstanceBlock::new);
register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new);
register(BlockEntityType.CRAFTER, CraftCrafter.class, CraftCrafter::new);
register(BlockEntityType.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new);
register(BlockEntityType.VAULT, CraftVault.class, CraftVault::new);
// Paper end
// End generate - CraftBlockEntityStates
}
private static void register(Material blockType, BlockStateFactory<?> factory) {
@@ -187,24 +141,21 @@ public final class CraftBlockStates {
}
private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType, // Paper
net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType,
Class<B> blockStateType,
BiFunction<World, T, B> blockStateConstructor // Paper
BiFunction<World, T, B> blockStateConstructor
) {
// Paper start
BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType); // Paper
BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType);
for (net.minecraft.world.level.block.Block block : blockEntityType.validBlocks) {
CraftBlockStates.register(CraftBlockType.minecraftToBukkit(block), factory);
}
CraftBlockStates.register(blockEntityType, factory);
// Paper end
}
private static BlockStateFactory<?> getFactory(Material material) {
return CraftBlockStates.FACTORIES.getOrDefault(material, CraftBlockStates.DEFAULT_FACTORY);
}
// Paper start
private static BlockStateFactory<?> getFactory(Material material, BlockEntityType<?> type) {
if (type != null) {
return CraftBlockStates.FACTORIES_BY_BLOCK_ENTITY_TYPE.getOrDefault(type, getFactory(material));
@@ -212,123 +163,108 @@ public final class CraftBlockStates {
return getFactory(material);
}
}
// Paper end
public static Class<? extends CraftBlockState> getBlockStateType(Material material) {
Preconditions.checkNotNull(material, "material is null");
return CraftBlockStates.getFactory(material).blockStateType;
}
public static BlockEntity createNewTileEntity(Material material) {
public static BlockEntity createNewBlockEntity(Material material) {
BlockStateFactory<?> factory = CraftBlockStates.getFactory(material);
if (factory instanceof BlockEntityStateFactory) {
return ((BlockEntityStateFactory<?, ?>) factory).createTileEntity(BlockPos.ZERO, CraftBlockType.bukkitToMinecraft(material).defaultBlockState());
return ((BlockEntityStateFactory<?, ?>) factory).createBlockEntity(BlockPos.ZERO, CraftBlockType.bukkitToMinecraft(material).defaultBlockState());
}
return null;
}
// Paper start
public static Class<? extends CraftBlockState> getBlockStateType(BlockEntityType<?> blockEntityType) {
Preconditions.checkNotNull(blockEntityType, "blockEntityType is null");
return CraftBlockStates.getFactory(null, blockEntityType).blockStateType;
}
// Paper end
public static BlockState getBlockState(Block block) {
// Paper start
return CraftBlockStates.getBlockState(block, true);
}
public static BlockState getBlockState(Block block, boolean useSnapshot) {
// Paper end
Preconditions.checkNotNull(block, "block is null");
CraftBlock craftBlock = (CraftBlock) block;
CraftWorld world = (CraftWorld) block.getWorld();
BlockPos blockPosition = craftBlock.getPosition();
net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS();
BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition);
// Paper start - block state snapshots
BlockPos pos = craftBlock.getPosition();
net.minecraft.world.level.block.state.BlockState state = craftBlock.getNMS();
BlockEntity blockEntity = craftBlock.getHandle().getBlockEntity(pos);
boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
try {
// Paper end
CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity);
blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access
return blockState;
// Paper start
CraftBlockState blockState = CraftBlockStates.getBlockState(world, pos, state, blockEntity);
blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access
return blockState;
} finally {
CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
}
// Paper end
}
@Deprecated
public static BlockState getBlockState(BlockPos blockPosition, Material material, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(MinecraftServer.getDefaultRegistryAccess(), blockPosition, material, blockEntityTag);
public static BlockState getBlockState(BlockPos pos, Material material, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(CraftRegistry.getMinecraftRegistry(), pos, material, blockEntityTag);
}
public static BlockState getBlockState(LevelReader world, BlockPos blockPosition, Material material, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(world.registryAccess(), blockPosition, material, blockEntityTag);
public static BlockState getBlockState(LevelReader world, BlockPos pos, Material material, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(world.registryAccess(), pos, material, blockEntityTag);
}
public static BlockState getBlockState(RegistryAccess registry, BlockPos blockPosition, Material material, @Nullable CompoundTag blockEntityTag) {
public static BlockState getBlockState(RegistryAccess registry, BlockPos pos, Material material, @Nullable CompoundTag blockEntityTag) {
Preconditions.checkNotNull(material, "material is null");
net.minecraft.world.level.block.state.BlockState blockData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState();
return CraftBlockStates.getBlockState(registry, blockPosition, blockData, blockEntityTag);
return CraftBlockStates.getBlockState(registry, pos, blockData, blockEntityTag);
}
@Deprecated
public static BlockState getBlockState(net.minecraft.world.level.block.state.BlockState blockData, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(MinecraftServer.getDefaultRegistryAccess(), BlockPos.ZERO, blockData, blockEntityTag);
public static BlockState getBlockState(net.minecraft.world.level.block.state.BlockState state, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(CraftRegistry.getMinecraftRegistry(), BlockPos.ZERO, state, blockEntityTag);
}
public static BlockState getBlockState(LevelReader world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(world.registryAccess(), blockPosition, blockData, blockEntityTag);
public static BlockState getBlockState(LevelReader level, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState state, @Nullable CompoundTag blockEntityTag) {
return CraftBlockStates.getBlockState(level.registryAccess(), blockPosition, state, blockEntityTag);
}
public static BlockState getBlockState(RegistryAccess registry, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, @Nullable CompoundTag blockEntityTag) {
Preconditions.checkNotNull(blockPosition, "blockPosition is null");
Preconditions.checkNotNull(blockData, "blockData is null");
BlockEntity tileEntity = (blockEntityTag == null) ? null : BlockEntity.loadStatic(blockPosition, blockData, blockEntityTag, registry);
return CraftBlockStates.getBlockState(null, blockPosition, blockData, tileEntity);
public static BlockState getBlockState(RegistryAccess registry, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, @Nullable CompoundTag blockEntityTag) {
Preconditions.checkNotNull(pos, "pos is null");
Preconditions.checkNotNull(state, "state is null");
BlockEntity blockEntity = (blockEntityTag == null) ? null : BlockEntity.loadStatic(pos, state, blockEntityTag, registry); // todo create block entity from the state
return CraftBlockStates.getBlockState(null, pos, state, blockEntity);
}
// See BlockStateFactory#createBlockState(World, BlockPosition, IBlockData, TileEntity)
public static CraftBlockState getBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
Material material = CraftBlockType.minecraftToBukkit(blockData.getBlock());
// See BlockStateFactory#createBlockState(World, BlockPos, BlockState, BlockEntity)
public static CraftBlockState getBlockState(World world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, BlockEntity blockEntity) {
Material material = CraftBlockType.minecraftToBukkit(state.getBlock());
BlockStateFactory<?> factory;
// For some types of TileEntity blocks (eg. moving pistons), Minecraft may in some situations (eg. when using Block#setType or the
// setBlock command) not create a corresponding TileEntity in the world. We return a normal BlockState in this case.
if (world != null && tileEntity == null && CraftBlockStates.isTileEntityOptional(material)) {
// For some types of BlockEntity blocks (e.g. moving pistons), Minecraft may in some situations (e.g. when using Block#setType or the
// setBlock command) not create a corresponding BlockEntity in the world. We return a normal BlockState in this case.
if (world != null && blockEntity == null && CraftBlockStates.isBlockEntityOptional(material)) {
factory = CraftBlockStates.DEFAULT_FACTORY;
} else {
factory = CraftBlockStates.getFactory(material, tileEntity != null ? tileEntity.getType() : null); // Paper
factory = CraftBlockStates.getFactory(material, blockEntity != null ? blockEntity.getType() : null); // Paper
}
return factory.createBlockState(world, blockPosition, blockData, tileEntity);
return factory.createBlockState(world, pos, state, blockEntity);
}
public static boolean isTileEntityOptional(Material material) {
public static boolean isBlockEntityOptional(Material material) {
return material == Material.MOVING_PISTON;
}
// This ignores tile entity data.
// This ignores block entity data.
public static CraftBlockState getBlockState(LevelAccessor world, BlockPos pos) {
return new CraftBlockState(CraftBlock.at(world, pos));
}
// This ignores tile entity data.
public static CraftBlockState getBlockState(LevelAccessor world, BlockPos pos, int flag) {
return new CraftBlockState(CraftBlock.at(world, pos), flag);
}
// Paper start
@Nullable
public static BlockEntityType<?> getBlockEntityType(final Material material) {
final BlockStateFactory<?> factory = org.bukkit.craftbukkit.block.CraftBlockStates.FACTORIES.get(material);
return factory instanceof final BlockEntityStateFactory<?,?> blockEntityStateFactory ? blockEntityStateFactory.tileEntityConstructor : null;
return factory instanceof final BlockEntityStateFactory<?,?> blockEntityStateFactory ? blockEntityStateFactory.blockEntityType : null;
}
// Paper end
private CraftBlockStates() {
}

View File

@@ -1,12 +1,16 @@
package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import io.papermc.paper.registry.HolderableBase;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableList;
import java.util.function.Supplier;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
@@ -21,7 +25,6 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.World;
import org.bukkit.block.BlockType;
@@ -31,16 +34,14 @@ import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.inventory.ItemType;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
@NullMarked
public class CraftBlockType<B extends @NonNull BlockData> extends HolderableBase<Block> implements BlockType.Typed<B>, io.papermc.paper.world.flag.PaperFeatureDependent<Block> { // Paper - feature flag API
private final NamespacedKey key;
private final Block block;
private final Class<B> blockDataClass;
private final boolean interactable;
public static Material minecraftToBukkit(Block block) {
return CraftMagicNumbers.getMaterial(block);
@@ -92,30 +93,26 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return hasMethod;
}
public CraftBlockType(NamespacedKey key, Block block) {
this.key = key;
this.block = block;
this.blockDataClass = (Class<B>) CraftBlockData.fromData(block.defaultBlockState()).getClass().getInterfaces()[0];
this.interactable = CraftBlockType.isInteractable(block);
private final Supplier<Class<B>> blockDataClass;
private final Supplier<Boolean> interactable;
@SuppressWarnings("unchecked")
public CraftBlockType(final Holder<Block> holder) {
super(holder);
this.blockDataClass = Suppliers.memoize(() -> (Class<B>) CraftBlockData.fromData(this.getHandle().defaultBlockState()).getClass().getInterfaces()[0]);
this.interactable = Suppliers.memoize(() -> CraftBlockType.isInteractable(this.getHandle()));
}
@Override
public Block getHandle() {
return this.block;
}
@NotNull
@Override
public Typed<BlockData> typed() {
return this.typed(BlockData.class);
}
@NotNull
@Override
@SuppressWarnings("unchecked")
public <Other extends BlockData> Typed<Other> typed(@NotNull Class<Other> blockDataType) {
if (blockDataType.isAssignableFrom(this.blockDataClass)) return (Typed<Other>) this;
throw new IllegalArgumentException("Cannot type block type " + this.key.toString() + " to blockdata type " + blockDataType.getSimpleName());
public <Other extends BlockData> Typed<Other> typed(final Class<Other> blockDataType) {
if (blockDataType.isAssignableFrom(this.blockDataClass.get())) return (Typed<Other>) this;
throw new IllegalArgumentException("Cannot type block type " + this + " to blockdata type " + blockDataType.getSimpleName());
}
@Override
@@ -124,24 +121,23 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return true;
}
return this.block.asItem() != Items.AIR;
return this.getHandle().asItem() != Items.AIR;
}
@NotNull
@Override
public ItemType getItemType() {
if (this == AIR) {
return ItemType.AIR;
}
Item item = this.block.asItem();
Item item = this.getHandle().asItem();
Preconditions.checkArgument(item != Items.AIR, "The block type %s has no corresponding item type", this.getKey());
return CraftItemType.minecraftToBukkitNew(item);
}
@Override
public Class<B> getBlockDataClass() {
return this.blockDataClass;
return this.blockDataClass.get();
}
@Override
@@ -150,17 +146,17 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
}
@Override
public @NotNull Collection<B> createBlockDataStates() {
final ImmutableList<BlockState> possibleStates = this.block.getStateDefinition().getPossibleStates();
public Collection<B> createBlockDataStates() {
final ImmutableList<BlockState> possibleStates = this.getHandle().getStateDefinition().getPossibleStates();
final ImmutableList.Builder<B> builder = ImmutableList.builderWithExpectedSize(possibleStates.size());
for (final BlockState possibleState : possibleStates) {
builder.add(this.blockDataClass.cast(possibleState.createCraftBlockData()));
builder.add(this.blockDataClass.get().cast(possibleState.createCraftBlockData()));
}
return builder.build();
}
@Override
public B createBlockData(Consumer<? super B> consumer) {
public B createBlockData(final @Nullable Consumer<? super B> consumer) {
B data = this.createBlockData();
if (consumer != null) {
@@ -170,94 +166,89 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return data;
}
@SuppressWarnings("unchecked")
@Override
public B createBlockData(String data) {
public B createBlockData(final @Nullable String data) {
return (B) CraftBlockData.newData(this, data);
}
@Override
public boolean isSolid() {
return this.block.defaultBlockState().blocksMotion();
return this.getHandle().defaultBlockState().blocksMotion();
}
@Override
public boolean isAir() {
return this.block.defaultBlockState().isAir();
return this.getHandle().defaultBlockState().isAir();
}
@Override
public boolean isEnabledByFeature(@NotNull World world) {
public boolean isEnabledByFeature(final World world) {
Preconditions.checkNotNull(world, "World cannot be null");
return this.getHandle().isEnabled(((CraftWorld) world).getHandle().enabledFeatures());
}
@Override
public boolean isFlammable() {
return this.block.defaultBlockState().ignitedByLava();
return this.getHandle().defaultBlockState().ignitedByLava();
}
@Override
public boolean isBurnable() {
return ((FireBlock) Blocks.FIRE).igniteOdds.getOrDefault(this.block, 0) > 0;
return ((FireBlock) Blocks.FIRE).igniteOdds.getOrDefault(this.getHandle(), 0) > 0;
}
@Override
public boolean isOccluding() {
return this.block.defaultBlockState().isRedstoneConductor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
return this.getHandle().defaultBlockState().isRedstoneConductor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
}
@Override
public boolean hasGravity() {
return this.block instanceof Fallable;
return this.getHandle() instanceof Fallable;
}
@Override
public boolean isInteractable() {
return this.interactable;
return this.interactable.get();
}
@Override
public float getHardness() {
return this.block.defaultBlockState().destroySpeed;
return this.getHandle().defaultBlockState().destroySpeed;
}
@Override
public float getBlastResistance() {
return this.block.getExplosionResistance();
return this.getHandle().getExplosionResistance();
}
@Override
public float getSlipperiness() {
return this.block.getFriction();
return this.getHandle().getFriction();
}
@NotNull
@Override
public String getTranslationKey() {
return this.block.getDescriptionId();
return this.getHandle().getDescriptionId();
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public Material asMaterial() {
return Registry.MATERIAL.get(this.key);
public @Nullable Material asMaterial() {
return Registry.MATERIAL.get(this.getKey());
}
// Paper start - add Translatable
@Override
public String translationKey() {
return this.block.getDescriptionId();
return this.getHandle().getDescriptionId();
}
// Paper end - add Translatable
// Paper start - hasCollision API
@Override
public boolean hasCollision() {
return this.block.hasCollision;
return this.getHandle().hasCollision;
}
// Paper end - hasCollision API
}

View File

@@ -9,8 +9,8 @@ import org.bukkit.inventory.BrewerInventory;
public class CraftBrewingStand extends CraftContainer<BrewingStandBlockEntity> implements BrewingStand {
public CraftBrewingStand(World world, BrewingStandBlockEntity tileEntity) {
super(world, tileEntity);
public CraftBrewingStand(World world, BrewingStandBlockEntity blockEntity) {
super(world, blockEntity);
}
protected CraftBrewingStand(CraftBrewingStand state, Location location) {
@@ -28,7 +28,7 @@ public class CraftBrewingStand extends CraftContainer<BrewingStandBlockEntity> i
return this.getSnapshotInventory();
}
return new CraftInventoryBrewer(this.getTileEntity());
return new CraftInventoryBrewer(this.getBlockEntity());
}
@Override

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