--- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -422,6 +_,10 @@ + public boolean purpurClient = false; // Purpur - Purpur client support + private boolean tpsBar = false; // Purpur - Implement TPSBar + private boolean compassBar = false; // Purpur - Add compass command + private boolean ramBar = false; // Purpur - Implement rambar commands public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) { super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); @@ -525,6 +_,10 @@ this.respawnConfig = compound.read("respawn", ServerPlayer.RespawnConfig.CODEC).orElse(null); this.spawnExtraParticlesOnFall = compound.getBooleanOr("spawn_extra_particles_on_fall", false); this.raidOmenPosition = compound.read("raid_omen_position", BlockPos.CODEC).orElse(null); + + this.tpsBar = compound.getBooleanOr("Purpur.TPSBar", false); // Purpur - Implement TPSBar + this.compassBar = compound.getBooleanOr("Purpur.CompassBar", false); // Purpur - Add compass command + this.ramBar = compound.getBooleanOr("Purpur.RamBar", false); // Purpur - Implement rambar command } @Override @@ -542,6 +_,9 @@ compound.storeNullable("raid_omen_position", BlockPos.CODEC, this.raidOmenPosition); this.saveEnderPearls(compound); this.getBukkitEntity().setExtraData(compound); // CraftBukkit + compound.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur - Implement TPSBar + compound.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur - Add compass command + compound.putBoolean("Purpur.RamBar", this.ramBar); // Purpur - Add rambar command } private void saveParentVehicle(CompoundTag tag) { @@ -1024,6 +_,7 @@ ) ); Team team = this.getTeam(); + if (org.purpurmc.purpur.PurpurConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendSystemMessage(deathMessage); else // Purpur - Configurable broadcast settings if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) { this.server.getPlayerList().broadcastSystemMessage(deathMessage, false); } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { @@ -1130,6 +_,13 @@ if (this.isInvulnerableTo(level, damageSource)) { return false; } else { + // Purpur start - Add boat fall damage config + if (damageSource.is(net.minecraft.tags.DamageTypeTags.IS_FALL)) { + if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.Boat && !level().purpurConfig.boatsDoFallDamage) { + return false; + } + } + // Purpur end - Add boat fall damage config Entity entity = damageSource.getEntity(); !(entity instanceof Player player && !this.canHarmPlayer(player)) @@ -1360,6 +_,7 @@ serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); this.unsetRemoved(); // CraftBukkit end + this.portalPos = org.bukkit.craftbukkit.util.CraftLocation.toBlockPosition(exit); // Purpur - Fix stuck in portals this.setServerLevel(level); this.connection.internalTeleport(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); // CraftBukkit - use internal teleport without event this.connection.resetPosition(); @@ -1477,7 +_,7 @@ new AABB(vec3.x() - 8.0, vec3.y() - 5.0, vec3.z() - 8.0, vec3.x() + 8.0, vec3.y() + 5.0, vec3.z() + 8.0), monster -> monster.isPreventingPlayerRest(this.serverLevel(), this) ); - if (!entitiesOfClass.isEmpty()) { + if (!this.level().purpurConfig.playerSleepNearMonsters && !entitiesOfClass.isEmpty()) { // Purpur - Config to ignore nearby mobs when sleeping return Either.left(Player.BedSleepingProblem.NOT_SAFE); } } @@ -1514,7 +_,19 @@ CriteriaTriggers.SLEPT_IN_BED.trigger(this); }); if (!this.serverLevel().canSleepThroughNights()) { - this.displayClientMessage(Component.translatable("sleep.not_possible"), true); + // Purpur start - Customizable sleeping actionbar messages + Component clientMessage; + if (org.purpurmc.purpur.PurpurConfig.sleepNotPossible.isBlank()) { + clientMessage = null; + } else if (!org.purpurmc.purpur.PurpurConfig.sleepNotPossible.equalsIgnoreCase("default")) { + clientMessage = + } else { + clientMessage = Component.translatable("sleep.not_possible"); + } + if (clientMessage != null) { + this.displayClientMessage(clientMessage, true); + } + // Purpur end - Customizable sleeping actionbar messages } ((ServerLevel)this.level()).updateSleepingPlayerList(); @@ -1606,6 +_,7 @@ @Override public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) { + if (level().purpurConfig.signAllowColors) this.connection.send(signEntity.getTranslatedUpdatePacket(textFilteringEnabled, isFrontText)); // Purpur - Signs allow color codes this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signEntity.getBlockPos())); this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); } @@ -1908,6 +_,26 @@ this.lastSentExp = -1; // CraftBukkit - Added to reset } + // Purpur start - Component related conveniences + public void sendActionBarMessage(@Nullable String message) { + if (message != null && !message.isEmpty()) { + sendActionBarMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message)); + } + } + + public void sendActionBarMessage(@Nullable net.kyori.adventure.text.Component message) { + if (message != null) { + sendActionBarMessage(+ } + } + + public void sendActionBarMessage(@Nullable Component message) { + if (message != null) { + displayClientMessage(message, true); + } + } + // Purpur end - Component related conveniences + @Override public void displayClientMessage(Component chatComponent, boolean actionBar) { this.sendSystemMessage(chatComponent, actionBar); @@ -2125,6 +_,20 @@ ); } + // Purpur start - Component related conveniences + public void sendMiniMessage(@Nullable String message) { + if (message != null && !message.isEmpty()) { + this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message)); + } + } + + public void sendMessage(@Nullable net.kyori.adventure.text.Component message) { + if (message != null) { + this.sendSystemMessage(+ } + } + // Purpur end - Component related conveniences + public void sendSystemMessage(Component mesage) { this.sendSystemMessage(mesage, false); } @@ -2263,7 +_,67 @@ public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); - } + this.setAfk(false); // Purpur - AFK API + } + + // Purpur start - AFK API + private boolean isAfk = false; + + @Override + public void setAfk(boolean afk) { + if (this.isAfk == afk) { + return; + } + + String msg = afk ? org.purpurmc.purpur.PurpurConfig.afkBroadcastAway : org.purpurmc.purpur.PurpurConfig.afkBroadcastBack; + + org.purpurmc.purpur.event.PlayerAFKEvent event = new org.purpurmc.purpur.event.PlayerAFKEvent(this.getBukkitEntity(), afk, this.level().purpurConfig.idleTimeoutKick, msg, !org.bukkit.Bukkit.isPrimaryThread()); + if (!event.callEvent() || event.shouldKick()) { + return; + } + + this.isAfk = afk; + + if (!afk) { + resetLastActionTime(); + } + + msg = event.getBroadcastMsg(); + if (msg != null && !msg.isEmpty()) { + String playerName = this.getGameProfile().getName(); + if (org.purpurmc.purpur.PurpurConfig.afkBroadcastUseDisplayName) { + net.kyori.adventure.text.Component playerDisplayNameComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getBukkitEntity().getDisplayName()); + playerName = net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(playerDisplayNameComponent); + } + server.getPlayerList().broadcastMiniMessage(String.format(msg, playerName), false); + } + + if (this.level().purpurConfig.idleTimeoutUpdateTabList) { + String scoreboardName = getScoreboardName(); + String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName()); + String[] split = playerListName.split(scoreboardName); + String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, ""); + String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, ""); + if (afk) { + getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true); + } else { + getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix, true); + } + } + + ((ServerLevel) this.level()).updateSleepingPlayerList(); + } + + @Override + public boolean isAfk() { + return this.isAfk; + } + + @Override + public boolean canBeCollidedWith() { + return !this.isAfk() && super.canBeCollidedWith(); + } + // Purpur end - AFK API public ServerStatsCounter getStats() { return this.stats; @@ -2891,4 +_,56 @@ return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end + + // Purpur start - Add option to teleport to spawn if outside world border + public void teleport(org.bukkit.Location to) { + this.ejectPassengers(); + this.stopRiding(true); + + if (this.isSleeping()) { + this.stopSleepInBed(true, false); + } + + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); + } + + ServerLevel toLevel = ((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle(); + if (this.level() == toLevel) { + this.connection.teleport(to); + } else { + this.server.getPlayerList().respawn(this, true, RemovalReason.KILLED, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.DEATH, to); + } + } + // Purpur end - Add option to teleport to spawn if outside world border + + // Purpur start - Implement TPSBar + public boolean tpsBar() { + return this.tpsBar; + } + + public void tpsBar(boolean tpsBar) { + this.tpsBar = tpsBar; + } + // Purpur end - Implement TPSBar + + // Purpur start - Add compass command + public boolean compassBar() { + return this.compassBar; + } + + public void compassBar(boolean compassBar) { + this.compassBar = compassBar; + } + // Purpur end - Add compass command + + // Purpur start - Add rambar command + public boolean ramBar() { + return this.ramBar; + } + + public void ramBar(boolean ramBar) { + this.ramBar = ramBar; + } + // Purpur end - Add rambar command }