mirror of
https://github.com/PaperMC/Paper.git
synced 2025-07-26 09:42:06 -07:00
Last per file patches
This commit is contained in:
@@ -1,150 +0,0 @@
|
||||
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
|
||||
From: File <noreply+automated@papermc.io>
|
||||
Date: Sun, 20 Apr 1997 15:37:42 +0200
|
||||
Subject: [PATCH] paper File Patches
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index b7965fd610b90f5674aae3571ab9a35e29d3d4f5..bb8b5ca9044ecb33687e7f20cfb0acbf55f887c7 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -73,6 +73,10 @@ public class StructureTemplate {
|
||||
public final List<StructureTemplate.StructureEntityInfo> entityInfoList = Lists.newArrayList();
|
||||
private Vec3i size = Vec3i.ZERO;
|
||||
private String author = "?";
|
||||
+ // CraftBukkit start - data containers
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ public org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(StructureTemplate.DATA_TYPE_REGISTRY);
|
||||
+ // CraftBukkit end
|
||||
|
||||
public Vec3i getSize() {
|
||||
return this.size;
|
||||
@@ -247,6 +251,19 @@ public class StructureTemplate {
|
||||
if (this.palettes.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed
|
||||
+ ServerLevelAccessor wrappedAccess = serverLevel;
|
||||
+ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null;
|
||||
+ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
|
||||
+ serverLevel = transformerAccess.getDelegate();
|
||||
+ structureTransformer = transformerAccess.getStructureTransformer();
|
||||
+ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this
|
||||
+ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) {
|
||||
+ structureTransformer = null;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
List<StructureTemplate.StructureBlockInfo> list = settings.getRandomPalette(this.palettes, offset).blocks();
|
||||
if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty())
|
||||
&& this.size.getX() >= 1
|
||||
@@ -272,6 +289,21 @@ public class StructureTemplate {
|
||||
serverLevel.setBlock(blockPos, Blocks.BARRIER.defaultBlockState(), 820);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ if (structureTransformer != null) {
|
||||
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(serverLevel, blockPos, blockState, null);
|
||||
+ if (structureBlockInfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState<?> entityState) {
|
||||
+ entityState.loadData(structureBlockInfo.nbt);
|
||||
+ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable<?> craftLootable) {
|
||||
+ craftLootable.setSeed(random.nextLong());
|
||||
+ }
|
||||
+ }
|
||||
+ craftBlockState = structureTransformer.transformCraftState(craftBlockState);
|
||||
+ blockState = craftBlockState.getHandle();
|
||||
+ structureBlockInfo = new StructureTemplate.StructureBlockInfo(blockPos, blockState, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState<?> craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (serverLevel.setBlock(blockPos, blockState, flags)) {
|
||||
i = Math.min(i, blockPos.getX());
|
||||
i1 = Math.min(i1, blockPos.getY());
|
||||
@@ -283,7 +315,7 @@ public class StructureTemplate {
|
||||
if (structureBlockInfo.nbt != null) {
|
||||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos);
|
||||
if (blockEntity != null) {
|
||||
- if (blockEntity instanceof RandomizableContainer) {
|
||||
+ if (structureTransformer == null && blockEntity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above
|
||||
structureBlockInfo.nbt.putLong("LootTableSeed", random.nextLong());
|
||||
}
|
||||
|
||||
@@ -366,7 +398,11 @@ public class StructureTemplate {
|
||||
if (pair1.getSecond() != null) {
|
||||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos4);
|
||||
if (blockEntity != null) {
|
||||
- blockEntity.setChanged();
|
||||
+ // Paper start - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
+ if (!(serverLevel instanceof net.minecraft.world.level.WorldGenLevel)) {
|
||||
+ blockEntity.setChanged();
|
||||
+ }
|
||||
+ // Paper end - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,7 +410,7 @@ public class StructureTemplate {
|
||||
|
||||
if (!settings.isIgnoreEntities()) {
|
||||
this.placeEntities(
|
||||
- serverLevel,
|
||||
+ wrappedAccess, // CraftBukkit
|
||||
offset,
|
||||
settings.getMirror(),
|
||||
settings.getRotation(),
|
||||
@@ -488,14 +524,17 @@ public class StructureTemplate {
|
||||
);
|
||||
}
|
||||
}
|
||||
+
|
||||
}
|
||||
|
||||
private static Optional<Entity> createEntityIgnoreException(ServerLevelAccessor level, CompoundTag tag) {
|
||||
- try {
|
||||
- return EntityType.create(tag, level.getLevel(), EntitySpawnReason.STRUCTURE);
|
||||
- } catch (Exception var3) {
|
||||
- return Optional.empty();
|
||||
- }
|
||||
+ // CraftBukkit start
|
||||
+ // try {
|
||||
+ return EntityType.create(tag, level.getLevel(), EntitySpawnReason.STRUCTURE, true); // Paper - Don't fire sync event during generation
|
||||
+ // } catch (Exception var3) {
|
||||
+ // return Optional.empty();
|
||||
+ // }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public Vec3i getSize(Rotation rotation) {
|
||||
@@ -688,6 +727,11 @@ public class StructureTemplate {
|
||||
|
||||
tag.put("entities", listTag3);
|
||||
tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ()));
|
||||
+ // CraftBukkit start - PDC
|
||||
+ if (!this.persistentDataContainer.isEmpty()) {
|
||||
+ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return NbtUtils.addCurrentDataVersion(tag);
|
||||
}
|
||||
|
||||
@@ -718,6 +762,11 @@ public class StructureTemplate {
|
||||
.ifPresent(compoundTag1 -> this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockPos, compoundTag1)));
|
||||
}
|
||||
);
|
||||
+ // CraftBukkit start - PDC
|
||||
+ if (tag.get("BukkitValues") instanceof CompoundTag compoundTag) {
|
||||
+ this.persistentDataContainer.putAll(compoundTag);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private void loadPalette(HolderGetter<Block> blockGetter, ListTag paletteTag, ListTag blocksTag) {
|
||||
@@ -817,7 +866,7 @@ public class StructureTemplate {
|
||||
|
||||
public static final class Palette {
|
||||
private final List<StructureTemplate.StructureBlockInfo> blocks;
|
||||
- private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newHashMap();
|
||||
+ private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newConcurrentMap(); // Paper - Fix CME due to this collection being shared across threads
|
||||
@Nullable
|
||||
private List<StructureTemplate.JigsawBlockInfo> cachedJigsaws;
|
||||
|
@@ -1,14 +1,6 @@
|
||||
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
|
||||
From: File <noreply+automated@papermc.io>
|
||||
Date: Sun, 20 Apr 1997 15:37:42 +0200
|
||||
Subject: [PATCH] paper File Patches
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6a3dc0dd0 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -112,14 +112,16 @@ public abstract class PlayerList {
|
||||
@@ -111,14 +_,16 @@
|
||||
private static final int SEND_PLAYER_INFO_INTERVAL = 600;
|
||||
private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
|
||||
private final MinecraftServer server;
|
||||
@@ -28,7 +20,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
public final PlayerDataStorage playerIo;
|
||||
private boolean doWhiteList;
|
||||
private final LayeredRegistryAccess<RegistryLayer> registries;
|
||||
@@ -130,14 +132,26 @@ public abstract class PlayerList {
|
||||
@@ -129,14 +_,26 @@
|
||||
private static final boolean ALLOW_LOGOUTIVATOR = false;
|
||||
private int sendAllPlayerInfoIn;
|
||||
|
||||
@@ -55,259 +47,264 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
GameProfile gameProfile = player.getGameProfile();
|
||||
GameProfileCache profileCache = this.server.getProfileCache();
|
||||
String string;
|
||||
@@ -150,30 +164,94 @@ public abstract class PlayerList {
|
||||
@@ -149,18 +_,69 @@
|
||||
}
|
||||
|
||||
Optional<CompoundTag> optional = this.load(player);
|
||||
- ResourceKey<Level> resourceKey = optional.<ResourceKey<Level>>flatMap(
|
||||
- compoundTag -> DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error)
|
||||
+ // CraftBukkit start - Better rename detection
|
||||
+ if (optional.isPresent()) {
|
||||
+ string = optional.flatMap(t -> t.getCompound("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
|
||||
+ ResourceKey<Level> resourceKey = null; // Paper
|
||||
+ boolean[] invalidPlayerWorld = {false};
|
||||
+ bukkitData: if (optional.isPresent()) {
|
||||
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
|
||||
+ final org.bukkit.World bWorld;
|
||||
+ final CompoundTag playerData = optional.get();
|
||||
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
|
||||
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
|
||||
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
|
||||
+ final java.util.Optional<String> worldName = playerData.getString("world");
|
||||
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
|
||||
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
|
||||
+ } else {
|
||||
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
|
||||
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), LOGGER)) {
|
||||
- Optional<ValueInput> optional1 = this.load(player, scopedCollector);
|
||||
- ResourceKey<Level> resourceKey = optional1.<ResourceKey<Level>>flatMap(valueInput -> valueInput.read("Dimension", Level.RESOURCE_KEY_CODEC))
|
||||
- .orElse(Level.OVERWORLD);
|
||||
+ Optional<ValueInput> optional1 = this.load(player, scopedCollector); final Optional<ValueInput> loadedPlayerData = optional1; // Paper - OBFHELPER
|
||||
+ // CraftBukkit start - Better rename detection
|
||||
+ if (loadedPlayerData.isPresent()) {
|
||||
+ string = loadedPlayerData.flatMap(t -> t.child("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
|
||||
+ }
|
||||
+ if (bWorld != null) {
|
||||
+ resourceKey = ((org.bukkit.craftbukkit.CraftWorld) bWorld).getHandle().dimension();
|
||||
+ } else {
|
||||
+ resourceKey = Level.OVERWORLD;
|
||||
+ invalidPlayerWorld[0] = true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (resourceKey == null) { // only run the vanilla logic if we haven't found a world from the bukkit data
|
||||
+ // Below is the vanilla way of getting the dimension, this is for migration from vanilla servers
|
||||
+ resourceKey = optional.<ResourceKey<Level>>flatMap(
|
||||
+ compoundTag -> {
|
||||
+ com.mojang.serialization.DataResult<ResourceKey<Level>> dataResult = DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension")));
|
||||
+ final Optional<ResourceKey<Level>> result = dataResult.resultOrPartial(LOGGER::error);
|
||||
+ invalidPlayerWorld[0] = result.isEmpty(); // reset to main world spawn if no valid world is found
|
||||
+ return result;
|
||||
+ }
|
||||
)
|
||||
- .orElse(Level.OVERWORLD);
|
||||
+ .orElse(Level.OVERWORLD); // revert to vanilla default main world, this isn't an "invalid world" since no player data existed
|
||||
+ }
|
||||
+ // Paper end
|
||||
ServerLevel level = this.server.getLevel(resourceKey);
|
||||
ServerLevel serverLevel;
|
||||
if (level == null) {
|
||||
LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey);
|
||||
serverLevel = this.server.overworld();
|
||||
+ invalidPlayerWorld[0] = true; // Paper - reset to main world if no world with parsed value is found
|
||||
} else {
|
||||
serverLevel = level;
|
||||
}
|
||||
|
||||
+ // Paper start - Entity#getEntitySpawnReason
|
||||
+ if (optional.isEmpty()) {
|
||||
+ player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
|
||||
+ // Paper start - reset to main world spawn if first spawn or invalid world
|
||||
+ }
|
||||
+ if (optional.isEmpty() || invalidPlayerWorld[0]) {
|
||||
+ // Paper end - reset to main world spawn if first spawn or invalid world
|
||||
+ player.snapTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
+ }
|
||||
+ // Paper end - Entity#getEntitySpawnReason
|
||||
player.setServerLevel(serverLevel);
|
||||
String loggableAddress = connection.getLoggableAddress(this.server.logIPs());
|
||||
- LOGGER.info(
|
||||
- "{}[{}] logged in with entity id {} at ({}, {}, {})",
|
||||
- player.getName().getString(),
|
||||
- loggableAddress,
|
||||
- player.getId(),
|
||||
- player.getX(),
|
||||
- player.getY(),
|
||||
- player.getZ()
|
||||
- );
|
||||
+ // Spigot start - spawn location event
|
||||
+ org.bukkit.entity.Player spawnPlayer = player.getBukkitEntity();
|
||||
+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
|
||||
+ this.cserver.getPluginManager().callEvent(ev);
|
||||
+
|
||||
+ org.bukkit.Location loc = ev.getSpawnLocation();
|
||||
+ serverLevel = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
|
||||
+
|
||||
+ player.spawnIn(serverLevel);
|
||||
+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
|
||||
+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ());
|
||||
+ player.setRot(loc.getYaw(), loc.getPitch());
|
||||
+ // Paper end - set raw so we aren't fully joined to the world
|
||||
+ // Spigot end
|
||||
+ // LOGGER.info( // CraftBukkit - Moved message to after join
|
||||
+ // "{}[{}] logged in with entity id {} at ({}, {}, {})",
|
||||
+ // player.getName().getString(),
|
||||
+ // loggableAddress,
|
||||
+ // player.getId(),
|
||||
+ // player.getX(),
|
||||
+ // player.getY(),
|
||||
+ // player.getZ()
|
||||
+ // );
|
||||
LevelData levelData = serverLevel.getLevelData();
|
||||
player.loadGameTypes(optional.orElse(null));
|
||||
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
|
||||
@@ -191,8 +269,8 @@ public abstract class PlayerList {
|
||||
levelData.isHardcore(),
|
||||
this.server.levelKeys(),
|
||||
this.getMaxPlayers(),
|
||||
- this.viewDistance,
|
||||
- this.simulationDistance,
|
||||
+ serverLevel.spigotConfig.viewDistance,// Spigot - view distance
|
||||
+ serverLevel.spigotConfig.simulationDistance,
|
||||
_boolean1,
|
||||
!_boolean,
|
||||
_boolean2,
|
||||
@@ -200,6 +278,7 @@ public abstract class PlayerList {
|
||||
this.server.enforceSecureProfile()
|
||||
)
|
||||
);
|
||||
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
@@ -219,26 +298,119 @@ public abstract class PlayerList {
|
||||
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
|
||||
}
|
||||
|
||||
- this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false);
|
||||
+ // CraftBukkit start
|
||||
+ mutableComponent.withStyle(ChatFormatting.YELLOW);
|
||||
+ Component joinMessage = mutableComponent; // Paper - Adventure
|
||||
serverGamePacketListenerImpl.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||
ServerStatus status = this.server.getStatus();
|
||||
if (status != null && !cookie.transferred()) {
|
||||
player.sendServerStatus(status);
|
||||
}
|
||||
|
||||
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players));
|
||||
+ // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
||||
this.players.add(player);
|
||||
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||
this.playersByUUID.put(player.getUUID(), player);
|
||||
- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)));
|
||||
- this.sendLevelInfo(player, serverLevel);
|
||||
+ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
|
||||
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
|
||||
+ player.supressTrackerForLogin = true;
|
||||
serverLevel.addNewPlayer(player);
|
||||
- this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
- this.sendActivePlayerEffects(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
optional.ifPresent(compoundTag -> {
|
||||
player.loadAndSpawnEnderPearls(compoundTag);
|
||||
player.loadAndSpawnParentVehicle(compoundTag);
|
||||
});
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||
+
|
||||
+ // Ensure that player inventory is populated with its viewer
|
||||
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
|
||||
+
|
||||
+ org.bukkit.event.player.PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(bukkitPlayer, io.papermc.paper.adventure.PaperAdventure.asAdventure(mutableComponent)); // Paper - Adventure
|
||||
+ this.cserver.getPluginManager().callEvent(playerJoinEvent);
|
||||
+
|
||||
+ if (!player.connection.isAcceptingMessages()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
+
|
||||
+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
+ joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure
|
||||
+ this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // CraftBukkit start - sendAll above replaced with this loop
|
||||
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
|
||||
+
|
||||
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
|
||||
+
|
||||
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
|
||||
+ // Paper start - Add Listing API for Player
|
||||
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
|
||||
+ // Paper end - Add Listing API for Player
|
||||
+ entityplayer1.connection.send(packet);
|
||||
+ // Paper start - Add Listing API for Player
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
|
||||
+ ResourceKey<Level> resourceKey = null; // Paper
|
||||
+ boolean[] invalidPlayerWorld = {false};
|
||||
+ bukkitData: if (loadedPlayerData.isPresent()) {
|
||||
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
|
||||
+ final org.bukkit.World bWorld;
|
||||
+ final ValueInput playerData = loadedPlayerData.get();
|
||||
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
|
||||
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
|
||||
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
|
||||
+ final java.util.Optional<String> worldName = playerData.getString("world");
|
||||
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
|
||||
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
|
||||
+ } else {
|
||||
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
|
||||
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
|
||||
+ }
|
||||
+ // Paper end - Add Listing API for Player
|
||||
+ if (bWorld != null) {
|
||||
+ resourceKey = ((org.bukkit.craftbukkit.CraftWorld) bWorld).getHandle().dimension();
|
||||
+ } else {
|
||||
+ resourceKey = Level.OVERWORLD;
|
||||
+ invalidPlayerWorld[0] = true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (resourceKey == null) { // only run the vanilla logic if we haven't found a world from the bukkit data
|
||||
+ // Below is the vanilla way of getting the dimension, this is for migration from vanilla servers
|
||||
+ resourceKey = loadedPlayerData.<ResourceKey<Level>>flatMap(
|
||||
+ compoundTag -> {
|
||||
+ Optional<ResourceKey<Level>> result = compoundTag.read("Dimension", Level.RESOURCE_KEY_CODEC);
|
||||
+ invalidPlayerWorld[0] = result.isEmpty(); // reset to main world spawn if no valid world is found
|
||||
+ return result;
|
||||
+ }
|
||||
+ )
|
||||
+ .orElse(Level.OVERWORLD); // revert to vanilla default main world, this isn't an "invalid world" since no player data existed
|
||||
+ }
|
||||
+ // Paper end
|
||||
ServerLevel level = this.server.getLevel(resourceKey);
|
||||
ServerLevel serverLevel;
|
||||
if (level == null) {
|
||||
LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey);
|
||||
serverLevel = this.server.overworld();
|
||||
+ invalidPlayerWorld[0] = true; // Paper - reset to main world if no world with parsed value is found
|
||||
} else {
|
||||
serverLevel = level;
|
||||
}
|
||||
|
||||
+ // Paper start - Entity#getEntitySpawnReason
|
||||
+ if (loadedPlayerData.isEmpty()) {
|
||||
+ player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
|
||||
+ // Paper start - reset to main world spawn if first spawn or invalid world
|
||||
+ }
|
||||
+ if (loadedPlayerData.isEmpty() || invalidPlayerWorld[0]) {
|
||||
+ // Paper end - reset to main world spawn if first spawn or invalid world
|
||||
+ player.snapTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
+ }
|
||||
+ // Paper end - Entity#getEntitySpawnReason
|
||||
player.setServerLevel(serverLevel);
|
||||
if (optional1.isEmpty()) {
|
||||
player.snapTo(
|
||||
@@ -170,15 +_,29 @@
|
||||
|
||||
serverLevel.waitForChunkAndEntities(player.chunkPosition(), 1);
|
||||
String loggableAddress = connection.getLoggableAddress(this.server.logIPs());
|
||||
- LOGGER.info(
|
||||
- "{}[{}] logged in with entity id {} at ({}, {}, {})",
|
||||
- player.getName().getString(),
|
||||
- loggableAddress,
|
||||
- player.getId(),
|
||||
- player.getX(),
|
||||
- player.getY(),
|
||||
- player.getZ()
|
||||
- );
|
||||
+ // Spigot start - spawn location event
|
||||
+ org.bukkit.entity.Player spawnPlayer = player.getBukkitEntity();
|
||||
+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
|
||||
+ this.cserver.getPluginManager().callEvent(ev);
|
||||
+
|
||||
+ org.bukkit.Location loc = ev.getSpawnLocation();
|
||||
+ serverLevel = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
|
||||
+
|
||||
+ player.spawnIn(serverLevel);
|
||||
+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
|
||||
+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ());
|
||||
+ player.setRot(loc.getYaw(), loc.getPitch());
|
||||
+ // Paper end - set raw so we aren't fully joined to the world
|
||||
+ // Spigot end
|
||||
+ // LOGGER.info( // CraftBukkit - Moved message to after join
|
||||
+ // "{}[{}] logged in with entity id {} at ({}, {}, {})",
|
||||
+ // player.getName().getString(),
|
||||
+ // loggableAddress,
|
||||
+ // player.getId(),
|
||||
+ // player.getX(),
|
||||
+ // player.getY(),
|
||||
+ // player.getZ()
|
||||
+ // );
|
||||
LevelData levelData = serverLevel.getLevelData();
|
||||
player.loadGameTypes(optional1.orElse(null));
|
||||
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
|
||||
@@ -196,8 +_,8 @@
|
||||
levelData.isHardcore(),
|
||||
this.server.levelKeys(),
|
||||
this.getMaxPlayers(),
|
||||
- this.viewDistance,
|
||||
- this.simulationDistance,
|
||||
+ serverLevel.spigotConfig.viewDistance,// Spigot - view distance
|
||||
+ serverLevel.spigotConfig.simulationDistance,
|
||||
_boolean1,
|
||||
!_boolean,
|
||||
_boolean2,
|
||||
@@ -205,6 +_,7 @@
|
||||
this.server.enforceSecureProfile()
|
||||
)
|
||||
);
|
||||
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
@@ -224,26 +_,119 @@
|
||||
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
|
||||
}
|
||||
|
||||
- this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false);
|
||||
+ // CraftBukkit start
|
||||
+ mutableComponent.withStyle(ChatFormatting.YELLOW);
|
||||
+ Component joinMessage = mutableComponent; // Paper - Adventure
|
||||
serverGamePacketListenerImpl.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||
ServerStatus status = this.server.getStatus();
|
||||
if (status != null && !cookie.transferred()) {
|
||||
player.sendServerStatus(status);
|
||||
}
|
||||
|
||||
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players));
|
||||
+ // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
||||
this.players.add(player);
|
||||
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||
this.playersByUUID.put(player.getUUID(), player);
|
||||
- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)));
|
||||
- this.sendLevelInfo(player, serverLevel);
|
||||
+ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
|
||||
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
|
||||
+ player.supressTrackerForLogin = true;
|
||||
serverLevel.addNewPlayer(player);
|
||||
- this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
- this.sendActivePlayerEffects(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
optional1.ifPresent(valueInput -> {
|
||||
player.loadAndSpawnEnderPearls(valueInput);
|
||||
player.loadAndSpawnParentVehicle(valueInput);
|
||||
});
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||
+
|
||||
+ // Ensure that player inventory is populated with its viewer
|
||||
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
|
||||
+
|
||||
+ org.bukkit.event.player.PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(bukkitPlayer, io.papermc.paper.adventure.PaperAdventure.asAdventure(mutableComponent)); // Paper - Adventure
|
||||
+ this.cserver.getPluginManager().callEvent(playerJoinEvent);
|
||||
+
|
||||
+ if (!player.connection.isAcceptingMessages()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
|
||||
+ continue;
|
||||
+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
+
|
||||
+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
+ joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure
|
||||
+ this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // CraftBukkit start - sendAll above replaced with this loop
|
||||
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
|
||||
+
|
||||
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
|
||||
+
|
||||
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
|
||||
+ // Paper start - Add Listing API for Player
|
||||
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
|
||||
+ // Paper end - Add Listing API for Player
|
||||
+ entityplayer1.connection.send(packet);
|
||||
+ // Paper start - Add Listing API for Player
|
||||
+ } else {
|
||||
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
|
||||
+ }
|
||||
+ // Paper end - Add Listing API for Player
|
||||
+ }
|
||||
+
|
||||
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
|
||||
+ }
|
||||
+ // Paper start - Use single player info update packet on join
|
||||
+ if (!onlinePlayers.isEmpty()) {
|
||||
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
|
||||
+ }
|
||||
+ // Paper end - Use single player info update packet on join
|
||||
+ player.sentListPacket = true;
|
||||
+ player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
|
||||
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ //player.refreshEntityData(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn // Paper - THIS IS NOT NEEDED ANYMORE
|
||||
+
|
||||
+ this.sendLevelInfo(player, serverLevel);
|
||||
+
|
||||
+ // CraftBukkit start - Only add if the player wasn't moved in the event
|
||||
+ if (player.level() == serverLevel && !serverLevel.players().contains(player)) {
|
||||
+ serverLevel.addNewPlayer(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
+ }
|
||||
+
|
||||
+ onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
|
||||
+ }
|
||||
+ // Paper start - Use single player info update packet on join
|
||||
+ if (!onlinePlayers.isEmpty()) {
|
||||
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
|
||||
+ }
|
||||
+ // Paper end - Use single player info update packet on join
|
||||
+ player.sentListPacket = true;
|
||||
+ player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
|
||||
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ //player.refreshEntityData(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn // Paper - THIS IS NOT NEEDED ANYMORE
|
||||
+
|
||||
+ this.sendLevelInfo(player, serverLevel);
|
||||
+
|
||||
+ // CraftBukkit start - Only add if the player wasn't moved in the event
|
||||
+ if (player.level() == serverLevel && !serverLevel.players().contains(player)) {
|
||||
+ serverLevel.addNewPlayer(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
+ }
|
||||
+
|
||||
+ serverLevel = player.serverLevel(); // CraftBukkit - Update in case join event changed it
|
||||
+ // CraftBukkit end
|
||||
+ this.sendActivePlayerEffects(player);
|
||||
+ // Paper - move loading pearls / parent vehicle up
|
||||
player.initInventoryMenu();
|
||||
+ // CraftBukkit - Moved from above, added world
|
||||
+ // Paper start - Configurable player collision; Add to collideRule team if needed
|
||||
+ final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
|
||||
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) {
|
||||
+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
|
||||
+ }
|
||||
+ // Paper end - Configurable player collision
|
||||
+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
|
||||
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
|
||||
+ if (player.isDeadOrDying()) {
|
||||
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = serverLevel.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
|
||||
+ serverLevel = player.level(); // CraftBukkit - Update in case join event changed it
|
||||
+ // CraftBukkit end
|
||||
+ this.sendActivePlayerEffects(player);
|
||||
+ // Paper - move loading pearls / parent vehicle up
|
||||
player.initInventoryMenu();
|
||||
+ // CraftBukkit - Moved from above, added world
|
||||
+ // Paper start - Configurable player collision; Add to collideRule team if needed
|
||||
+ final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
|
||||
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) {
|
||||
+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
|
||||
+ }
|
||||
+ // Paper end - Configurable player collision
|
||||
+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
|
||||
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
|
||||
+ if (player.isDeadOrDying()) {
|
||||
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = serverLevel.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
|
||||
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, player.chunkPosition(), plains),
|
||||
+ serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null)
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Send empty chunk
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Send empty chunk
|
||||
}
|
||||
}
|
||||
|
||||
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
|
||||
@@ -261,30 +433,31 @@ public abstract class PlayerList {
|
||||
@@ -267,30 +_,31 @@
|
||||
}
|
||||
|
||||
public void addWorldborderListener(ServerLevel level) {
|
||||
@@ -344,7 +341,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -312,56 +485,156 @@ public abstract class PlayerList {
|
||||
@@ -319,56 +_,156 @@
|
||||
}
|
||||
|
||||
protected void save(ServerPlayer player) {
|
||||
@@ -370,7 +367,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ }
|
||||
+ public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
|
||||
+ // Paper end - Fix kick event leave message not being sent
|
||||
ServerLevel serverLevel = player.serverLevel();
|
||||
ServerLevel serverLevel = player.level();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
+ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
|
||||
+ // See SPIGOT-5799, SPIGOT-6145
|
||||
@@ -431,7 +428,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ if (!thrownEnderpearl.level().paperConfig().misc.legacyEnderPearlBehavior) {
|
||||
+ thrownEnderpearl.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER, org.bukkit.event.entity.EntityRemoveEvent.Cause.PLAYER_QUIT); // CraftBukkit - add Bukkit remove cause
|
||||
+ } else {
|
||||
+ thrownEnderpearl.cachedOwner = null;
|
||||
+ thrownEnderpearl.setOwner(null);
|
||||
+ }
|
||||
+ // Paper end - Allow using old ender pearl behavior
|
||||
}
|
||||
@@ -448,13 +445,15 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
this.playersByUUID.remove(uuid);
|
||||
- this.stats.remove(uuid);
|
||||
- this.advancements.remove(uuid);
|
||||
- }
|
||||
-
|
||||
- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID())));
|
||||
+ // CraftBukkit start
|
||||
+ // this.stats.remove(uuid);
|
||||
+ // this.advancements.remove(uuid);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID())));
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID())));
|
||||
+ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
@@ -501,7 +500,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ // depending on the outcome.
|
||||
+ SocketAddress socketAddress = loginlistener.connection.getRemoteAddress();
|
||||
+
|
||||
+ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, ClientInformation.createDefault());
|
||||
+ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, net.minecraft.server.level.ClientInformation.createDefault());
|
||||
+ entity.transferCookieConnection = loginlistener;
|
||||
+ org.bukkit.entity.Player player = entity.getBukkitEntity();
|
||||
+ org.bukkit.event.player.PlayerLoginEvent event = new org.bukkit.event.player.PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketAddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.channel.remoteAddress()).getAddress());
|
||||
@@ -513,7 +512,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason());
|
||||
if (userBanListEntry.getExpires() != null) {
|
||||
mutableComponent.append(
|
||||
@@ -369,10 +642,12 @@ public abstract class PlayerList {
|
||||
@@ -376,10 +_,12 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -530,7 +529,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
|
||||
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
|
||||
if (ipBanListEntry.getExpires() != null) {
|
||||
@@ -381,69 +656,131 @@ public abstract class PlayerList {
|
||||
@@ -388,65 +_,124 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -541,30 +540,9 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)
|
||||
- ? Component.translatable("multiplayer.disconnect.server_full")
|
||||
- : null;
|
||||
+ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)
|
||||
+ // ? Component.translatable("multiplayer.disconnect.server_full")
|
||||
+ // : null;
|
||||
+ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)) {
|
||||
+ event.disallow(org.bukkit.event.player.PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
|
||||
+ }
|
||||
+ }
|
||||
+ this.cserver.getPluginManager().callEvent(event);
|
||||
+ if (event.getResult() != org.bukkit.event.player.PlayerLoginEvent.Result.ALLOWED) {
|
||||
+ loginlistener.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
|
||||
+ return null;
|
||||
}
|
||||
+ return entity;
|
||||
}
|
||||
|
||||
- public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation) {
|
||||
- return new ServerPlayer(this.server, this.server.overworld(), gameProfile, clientInformation);
|
||||
+ // CraftBukkit start - added EntityPlayer
|
||||
+ public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation, ServerPlayer player) {
|
||||
+ player.updateOptions(clientInformation);
|
||||
+ return player;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile) {
|
||||
- UUID id = gameProfile.getId();
|
||||
- Set<ServerPlayer> set = Sets.newIdentityHashSet();
|
||||
@@ -572,8 +550,13 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
- for (ServerPlayer serverPlayer : this.players) {
|
||||
- if (serverPlayer.getUUID().equals(id)) {
|
||||
- set.add(serverPlayer);
|
||||
- }
|
||||
- }
|
||||
+ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)
|
||||
+ // ? Component.translatable("multiplayer.disconnect.server_full")
|
||||
+ // : null;
|
||||
+ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)) {
|
||||
+ event.disallow(org.bukkit.event.player.PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
|
||||
}
|
||||
}
|
||||
-
|
||||
- ServerPlayer serverPlayer1 = this.playersByUUID.get(gameProfile.getId());
|
||||
- if (serverPlayer1 != null) {
|
||||
@@ -583,6 +566,19 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
- for (ServerPlayer serverPlayer2 : set) {
|
||||
- serverPlayer2.connection.disconnect(DUPLICATE_LOGIN_DISCONNECT_MESSAGE);
|
||||
- }
|
||||
-
|
||||
- return !set.isEmpty();
|
||||
- }
|
||||
-
|
||||
- public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason) {
|
||||
+ this.cserver.getPluginManager().callEvent(event);
|
||||
+ if (event.getResult() != org.bukkit.event.player.PlayerLoginEvent.Result.ALLOWED) {
|
||||
+ loginlistener.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
|
||||
+ return null;
|
||||
+ }
|
||||
+ return entity;
|
||||
+ }
|
||||
+
|
||||
+ public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile, ServerPlayer player) { // CraftBukkit - added ServerPlayer
|
||||
+ // CraftBukkit start - Moved up
|
||||
+ // UUID id = gameProfile.getId();
|
||||
@@ -607,19 +603,17 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ return player == null;
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
|
||||
- return !set.isEmpty();
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason) {
|
||||
+ return this.respawn(player, keepInventory, reason, eventReason, null);
|
||||
}
|
||||
|
||||
- public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason) {
|
||||
+ }
|
||||
+
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, @Nullable org.bukkit.Location location) {
|
||||
+ player.stopRiding(); // CraftBukkit
|
||||
this.players.remove(player);
|
||||
+ this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
player.serverLevel().removePlayerImmediately(player, reason);
|
||||
player.level().removePlayerImmediately(player, reason);
|
||||
- TeleportTransition teleportTransition = player.findRespawnPositionAndUseSpawnBlock(!keepInventory, TeleportTransition.DO_NOTHING);
|
||||
- ServerLevel level = teleportTransition.newLevel();
|
||||
- ServerPlayer serverPlayer = new ServerPlayer(this.server, level, player.getGameProfile(), player.clientInformation());
|
||||
@@ -686,7 +680,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
byte b = (byte)(keepInventory ? 1 : 0);
|
||||
ServerLevel serverLevel = serverPlayer.serverLevel();
|
||||
ServerLevel serverLevel = serverPlayer.level();
|
||||
LevelData levelData = serverLevel.getLevelData();
|
||||
serverPlayer.connection.send(new ClientboundRespawnPacket(serverPlayer.createCommonSpawnInfo(serverLevel), b));
|
||||
- serverPlayer.connection.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot());
|
||||
@@ -697,7 +691,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
|
||||
serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
|
||||
serverPlayer.connection
|
||||
@@ -451,10 +788,13 @@ public abstract class PlayerList {
|
||||
@@ -454,10 +_,13 @@
|
||||
this.sendActivePlayerEffects(serverPlayer);
|
||||
this.sendLevelInfo(serverPlayer, level);
|
||||
this.sendPlayerPermissionLevel(serverPlayer);
|
||||
@@ -715,7 +709,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
serverPlayer.setHealth(serverPlayer.getHealth());
|
||||
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
|
||||
if (!keepInventory && respawnConfig != null) {
|
||||
@@ -477,8 +817,52 @@ public abstract class PlayerList {
|
||||
@@ -480,8 +_,52 @@
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -768,7 +762,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
|
||||
return serverPlayer;
|
||||
}
|
||||
@@ -488,24 +872,59 @@ public abstract class PlayerList {
|
||||
@@ -491,24 +_,59 @@
|
||||
}
|
||||
|
||||
public void sendActiveEffects(LivingEntity entity, ServerGamePacketListenerImpl connection) {
|
||||
@@ -831,7 +825,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
public void broadcastAll(Packet<?> packet) {
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
serverPlayer.connection.send(packet);
|
||||
@@ -581,6 +1000,12 @@ public abstract class PlayerList {
|
||||
@@ -584,6 +_,12 @@
|
||||
}
|
||||
|
||||
private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) {
|
||||
@@ -844,7 +838,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
if (player.connection != null) {
|
||||
byte b;
|
||||
if (permLevel <= 0) {
|
||||
@@ -594,11 +1019,33 @@ public abstract class PlayerList {
|
||||
@@ -597,11 +_,33 @@
|
||||
player.connection.send(new ClientboundEntityEventPacket(player, b));
|
||||
}
|
||||
|
||||
@@ -879,7 +873,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
public boolean isOp(GameProfile profile) {
|
||||
@@ -609,21 +1056,17 @@ public abstract class PlayerList {
|
||||
@@ -612,21 +_,17 @@
|
||||
|
||||
@Nullable
|
||||
public ServerPlayer getPlayerByName(String username) {
|
||||
@@ -907,7 +901,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
if (serverPlayer != except && serverPlayer.level().dimension() == dimension) {
|
||||
double d = x - serverPlayer.getX();
|
||||
double d1 = y - serverPlayer.getY();
|
||||
@@ -636,9 +1079,11 @@ public abstract class PlayerList {
|
||||
@@ -639,9 +_,11 @@
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
@@ -919,7 +913,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
public UserWhiteList getWhiteList() {
|
||||
@@ -661,14 +1106,18 @@ public abstract class PlayerList {
|
||||
@@ -664,14 +_,18 @@
|
||||
}
|
||||
|
||||
public void sendLevelInfo(ServerPlayer player, ServerLevel level) {
|
||||
@@ -942,7 +936,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
|
||||
@@ -677,8 +1126,21 @@ public abstract class PlayerList {
|
||||
@@ -680,8 +_,21 @@
|
||||
|
||||
public void sendAllPlayerInfo(ServerPlayer player) {
|
||||
player.inventoryMenu.sendAllDataToRemote();
|
||||
@@ -957,15 +951,15 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
|
||||
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
+ // CraftBukkit start - from GameRules
|
||||
+ int i = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
|
||||
+ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
|
||||
+ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i));
|
||||
+ float immediateRespawn = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F;
|
||||
+ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F;
|
||||
+ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn));
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public int getPlayerCount() {
|
||||
@@ -694,6 +1156,7 @@ public abstract class PlayerList {
|
||||
@@ -697,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setUsingWhiteList(boolean whitelistEnabled) {
|
||||
@@ -973,12 +967,14 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
this.doWhiteList = whitelistEnabled;
|
||||
}
|
||||
|
||||
@@ -731,11 +1194,36 @@ public abstract class PlayerList {
|
||||
@@ -734,10 +_,35 @@
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
- for (int i = 0; i < this.players.size(); i++) {
|
||||
- this.players.get(i).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
||||
- }
|
||||
- }
|
||||
+ // Paper start - Extract method to allow for restarting flag
|
||||
+ this.removeAll(false);
|
||||
+ }
|
||||
@@ -989,7 +985,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ for (ServerPlayer player : this.players) {
|
||||
+ if (isRestarting) player.connection.disconnect(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.restartMessage), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here)
|
||||
+ player.connection.disconnect(java.util.Objects.requireNonNullElseGet(this.server.server.shutdownMessage(), net.kyori.adventure.text.Component::empty)); // CraftBukkit - add custom shutdown message // Paper - Adventure
|
||||
}
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start - Configurable player collision; Remove collideRule team if it exists
|
||||
@@ -999,8 +995,8 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ if (team != null) scoreboard.removePlayerTeam(team);
|
||||
+ }
|
||||
+ // Paper end - Configurable player collision
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public void broadcastMessage(Component[] iChatBaseComponents) {
|
||||
+ for (Component component : iChatBaseComponents) {
|
||||
@@ -1008,11 +1004,10 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) {
|
||||
this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat);
|
||||
}
|
||||
@@ -756,20 +1244,39 @@ public abstract class PlayerList {
|
||||
@@ -759,20 +_,39 @@
|
||||
}
|
||||
|
||||
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) {
|
||||
@@ -1055,7 +1050,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
flag1 |= flag2 && message.isFullyFiltered();
|
||||
}
|
||||
|
||||
@@ -782,14 +1289,21 @@ public abstract class PlayerList {
|
||||
@@ -785,14 +_,21 @@
|
||||
return message.hasSignature() && !message.hasExpiredServer(Instant.now());
|
||||
}
|
||||
|
||||
@@ -1081,7 +1076,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
Path path = file2.toPath();
|
||||
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
|
||||
file2.renameTo(file1);
|
||||
@@ -797,7 +1311,7 @@ public abstract class PlayerList {
|
||||
@@ -800,7 +_,7 @@
|
||||
}
|
||||
|
||||
serverStatsCounter = new ServerStatsCounter(this.server, file1);
|
||||
@@ -1090,7 +1085,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
return serverStatsCounter;
|
||||
@@ -805,11 +1319,11 @@ public abstract class PlayerList {
|
||||
@@ -808,11 +_,11 @@
|
||||
|
||||
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
|
||||
UUID uuid = player.getUUID();
|
||||
@@ -1104,7 +1099,7 @@ index aa7b0ea3f5203aafa86a8d36cd01b661cd16147c..ed23e8e29d08d69ec1d0dca49193a3a6
|
||||
}
|
||||
|
||||
playerAdvancements.setPlayer(player);
|
||||
@@ -852,11 +1366,34 @@ public abstract class PlayerList {
|
||||
@@ -855,11 +_,34 @@
|
||||
}
|
||||
|
||||
public void reloadResources() {
|
@@ -0,0 +1,142 @@
|
||||
--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -79,6 +_,10 @@
|
||||
public final List<StructureTemplate.StructureEntityInfo> entityInfoList = Lists.newArrayList();
|
||||
private Vec3i size = Vec3i.ZERO;
|
||||
private String author = "?";
|
||||
+ // CraftBukkit start - data containers
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ public org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(StructureTemplate.DATA_TYPE_REGISTRY);
|
||||
+ // CraftBukkit end
|
||||
|
||||
public Vec3i getSize() {
|
||||
return this.size;
|
||||
@@ -255,6 +_,19 @@
|
||||
if (this.palettes.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed
|
||||
+ ServerLevelAccessor wrappedAccess = serverLevel;
|
||||
+ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null;
|
||||
+ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
|
||||
+ serverLevel = transformerAccess.getDelegate();
|
||||
+ structureTransformer = transformerAccess.getStructureTransformer();
|
||||
+ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this
|
||||
+ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) {
|
||||
+ structureTransformer = null;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
List<StructureTemplate.StructureBlockInfo> list = settings.getRandomPalette(this.palettes, offset).blocks();
|
||||
if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty())
|
||||
&& this.size.getX() >= 1
|
||||
@@ -282,6 +_,21 @@
|
||||
serverLevel.setBlock(blockPos, Blocks.BARRIER.defaultBlockState(), 820);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ if (structureTransformer != null) {
|
||||
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(serverLevel, blockPos, blockState, null);
|
||||
+ if (structureBlockInfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState<?> entityState) {
|
||||
+ entityState.loadData(structureBlockInfo.nbt);
|
||||
+ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable<?> craftLootable) {
|
||||
+ craftLootable.setSeed(random.nextLong());
|
||||
+ }
|
||||
+ }
|
||||
+ craftBlockState = structureTransformer.transformCraftState(craftBlockState);
|
||||
+ blockState = craftBlockState.getHandle();
|
||||
+ structureBlockInfo = new StructureTemplate.StructureBlockInfo(blockPos, blockState, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState<?> craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (serverLevel.setBlock(blockPos, blockState, flags)) {
|
||||
i = Math.min(i, blockPos.getX());
|
||||
i1 = Math.min(i1, blockPos.getY());
|
||||
@@ -293,7 +_,7 @@
|
||||
if (structureBlockInfo.nbt != null) {
|
||||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos);
|
||||
if (blockEntity != null) {
|
||||
- if (blockEntity instanceof RandomizableContainer) {
|
||||
+ if (structureTransformer == null && blockEntity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above
|
||||
structureBlockInfo.nbt.putLong("LootTableSeed", random.nextLong());
|
||||
}
|
||||
|
||||
@@ -380,7 +_,11 @@
|
||||
if (pair1.getSecond() != null) {
|
||||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos4);
|
||||
if (blockEntity != null) {
|
||||
- blockEntity.setChanged();
|
||||
+ // Paper start - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
+ if (!(serverLevel instanceof net.minecraft.world.level.WorldGenLevel)) {
|
||||
+ blockEntity.setChanged();
|
||||
+ }
|
||||
+ // Paper end - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -388,7 +_,7 @@
|
||||
|
||||
if (!settings.isIgnoreEntities()) {
|
||||
this.placeEntities(
|
||||
- serverLevel,
|
||||
+ wrappedAccess, // CraftBukkit
|
||||
offset,
|
||||
settings.getMirror(),
|
||||
settings.getRotation(),
|
||||
@@ -499,14 +_,17 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
+
|
||||
}
|
||||
|
||||
private static Optional<Entity> createEntityIgnoreException(ProblemReporter problemReporter, ServerLevelAccessor level, CompoundTag tag) {
|
||||
- try {
|
||||
- return EntityType.create(TagValueInput.create(problemReporter, level.registryAccess(), tag), level.getLevel(), EntitySpawnReason.STRUCTURE);
|
||||
- } catch (Exception var4) {
|
||||
- return Optional.empty();
|
||||
- }
|
||||
+ // CraftBukkit start
|
||||
+ // try {
|
||||
+ return EntityType.create(TagValueInput.create(problemReporter, level.registryAccess(), tag), level.getLevel(), EntitySpawnReason.STRUCTURE, true); // Paper - Don't fire sync event during generation
|
||||
+ // } catch (Exception var4) {
|
||||
+ // return Optional.empty();
|
||||
+ // }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public Vec3i getSize(Rotation rotation) {
|
||||
@@ -699,6 +_,11 @@
|
||||
|
||||
tag.put("entities", listTag3);
|
||||
tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ()));
|
||||
+ // CraftBukkit start - PDC
|
||||
+ if (!this.persistentDataContainer.isEmpty()) {
|
||||
+ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return NbtUtils.addCurrentDataVersion(tag);
|
||||
}
|
||||
|
||||
@@ -729,6 +_,11 @@
|
||||
.ifPresent(compoundTag1 -> this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockPos, compoundTag1)));
|
||||
}
|
||||
);
|
||||
+ // CraftBukkit start - PDC
|
||||
+ if (tag.get("BukkitValues") instanceof CompoundTag compoundTag) {
|
||||
+ this.persistentDataContainer.putAll(compoundTag);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private void loadPalette(HolderGetter<Block> blockGetter, ListTag paletteTag, ListTag blocksTag) {
|
||||
@@ -828,7 +_,7 @@
|
||||
|
||||
public static final class Palette {
|
||||
private final List<StructureTemplate.StructureBlockInfo> blocks;
|
||||
- private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newHashMap();
|
||||
+ private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newConcurrentMap(); // Paper - Fix CME due to this collection being shared across threads
|
||||
@Nullable
|
||||
private List<StructureTemplate.JigsawBlockInfo> cachedJigsaws;
|
||||
|
Reference in New Issue
Block a user