diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index 38efdaf501..a1b868e603 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -114,11 +114,12 @@ @Nullable private Vec3 startingToFallPosition; @Nullable -@@ -258,7 +293,31 @@ +@@ -258,7 +293,32 @@ private final CommandSource commandSource; private int containerCounter; public boolean wonGame; + private int containerUpdateDelay; // Paper - Configurable container update tick rate ++ public long loginTime; // Paper - Replace OfflinePlayer#getLastPlayed + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; @@ -146,7 +147,7 @@ public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); this.chatVisibility = ChatVisiblity.FULL; -@@ -266,7 +325,7 @@ +@@ -266,7 +326,7 @@ this.canChatColor = true; this.lastActionTime = Util.getMillis(); this.requestedViewDistance = 2; @@ -155,7 +156,7 @@ this.lastSectionPos = SectionPos.of(0, 0, 0); this.chunkTrackingView = ChunkTrackingView.EMPTY; this.respawnDimension = Level.OVERWORLD; -@@ -340,6 +399,13 @@ +@@ -340,6 +400,13 @@ public void sendSystemMessage(Component message) { ServerPlayer.this.sendSystemMessage(message); } @@ -169,7 +170,7 @@ }; this.textFilter = server.createTextFilterForPlayer(this); this.gameMode = server.createGameModeForPlayer(this); -@@ -352,14 +418,68 @@ +@@ -352,14 +419,68 @@ this.moveTo(this.adjustSpawnLocation(world, world.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F); this.updateOptions(clientOptions); this.object = null; @@ -239,7 +240,7 @@ int i = Math.max(0, this.server.getSpawnRadius(world)); int j = Mth.floor(world.getWorldBorder().getDistanceToBorder((double) basePos.getX(), (double) basePos.getZ())); -@@ -395,14 +515,20 @@ +@@ -395,14 +516,20 @@ Objects.requireNonNull(basePos); crashreportsystemdetails.setDetail("Origin", basePos::toString); @@ -262,7 +263,7 @@ }); throw new ReportedException(crashreport); } -@@ -440,7 +566,7 @@ +@@ -440,7 +567,7 @@ dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(NbtOps.INSTANCE, nbt.get("warden_spawn_tracker"))); logger = ServerPlayer.LOGGER; Objects.requireNonNull(logger); @@ -271,7 +272,7 @@ this.wardenSpawnTracker = wardenspawntracker; }); } -@@ -457,17 +583,26 @@ +@@ -457,17 +584,26 @@ return this.server.getRecipeManager().byKey(resourcekey).isPresent(); }); } @@ -299,7 +300,7 @@ Logger logger1 = ServerPlayer.LOGGER; Objects.requireNonNull(logger1); -@@ -482,7 +617,7 @@ +@@ -482,7 +618,7 @@ dataresult = BlockPos.CODEC.parse(NbtOps.INSTANCE, nbtbase); logger = ServerPlayer.LOGGER; Objects.requireNonNull(logger); @@ -308,7 +309,7 @@ this.raidOmenPosition = blockposition; }); } -@@ -492,7 +627,7 @@ +@@ -492,7 +628,7 @@ @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); @@ -317,7 +318,7 @@ Logger logger = ServerPlayer.LOGGER; Objects.requireNonNull(logger); -@@ -526,6 +661,7 @@ +@@ -526,6 +662,7 @@ nbt.put("SpawnDimension", nbtbase); }); } @@ -325,7 +326,7 @@ nbt.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall); if (this.raidOmenPosition != null) { -@@ -544,7 +680,20 @@ +@@ -544,7 +681,20 @@ Entity entity = this.getRootVehicle(); Entity entity1 = this.getVehicle(); @@ -347,7 +348,7 @@ CompoundTag nbttagcompound1 = new CompoundTag(); CompoundTag nbttagcompound2 = new CompoundTag(); -@@ -598,12 +747,12 @@ +@@ -598,12 +748,12 @@ if (!this.isPassenger()) { ServerPlayer.LOGGER.warn("Couldn't reattach entity to player"); @@ -362,7 +363,7 @@ } } } -@@ -625,7 +774,7 @@ +@@ -625,7 +775,7 @@ CompoundTag nbttagcompound1 = new CompoundTag(); entityenderpearl.save(nbttagcompound1); @@ -371,7 +372,7 @@ Logger logger = ServerPlayer.LOGGER; Objects.requireNonNull(logger); -@@ -651,7 +800,7 @@ +@@ -651,7 +801,7 @@ nbttaglist.forEach((nbtbase1) -> { if (nbtbase1 instanceof CompoundTag nbttagcompound) { if (nbttagcompound.contains("ender_pearl_dimension")) { @@ -380,7 +381,7 @@ Logger logger = ServerPlayer.LOGGER; Objects.requireNonNull(logger); -@@ -684,7 +833,30 @@ +@@ -684,7 +834,30 @@ } } @@ -411,7 +412,7 @@ public void setExperiencePoints(int points) { float f = (float) this.getXpNeededForNextLevel(); -@@ -744,6 +916,11 @@ +@@ -744,6 +917,11 @@ @Override public void tick() { @@ -423,7 +424,7 @@ this.tickClientLoadTimeout(); this.gameMode.tick(); this.wardenSpawnTracker.tick(); -@@ -751,9 +928,13 @@ +@@ -751,9 +929,13 @@ --this.invulnerableTime; } @@ -439,7 +440,7 @@ this.containerMenu = this.inventoryMenu; } -@@ -820,7 +1001,7 @@ +@@ -820,7 +1002,7 @@ } if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { @@ -448,7 +449,7 @@ this.lastSentHealth = this.getHealth(); this.lastSentFood = this.foodData.getFoodLevel(); this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; -@@ -851,6 +1032,12 @@ +@@ -851,6 +1033,12 @@ this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float) this.lastRecordedExperience)); } @@ -461,7 +462,7 @@ if (this.experienceLevel != this.lastRecordedLevel) { this.lastRecordedLevel = this.experienceLevel; this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel)); -@@ -865,6 +1052,20 @@ +@@ -865,6 +1053,20 @@ CriteriaTriggers.LOCATION.trigger(this); } @@ -482,7 +483,7 @@ } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked"); -@@ -893,7 +1094,7 @@ +@@ -893,7 +1095,7 @@ if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { if (this.tickCount % 20 == 0) { if (this.getHealth() < this.getMaxHealth()) { @@ -491,7 +492,7 @@ } float f = this.foodData.getSaturationLevel(); -@@ -946,19 +1147,63 @@ +@@ -946,19 +1148,63 @@ } private void updateScoreForCriteria(ObjectiveCriteria criterion, int score) { @@ -559,7 +560,7 @@ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> { boolean flag1 = true; String s = ichatbasecomponent.getString(256); -@@ -988,12 +1233,18 @@ +@@ -988,12 +1234,18 @@ if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { this.tellNeutralMobsThatIDied(); } @@ -582,7 +583,7 @@ LivingEntity entityliving = this.getKillCredit(); if (entityliving != null) { -@@ -1028,10 +1279,12 @@ +@@ -1028,10 +1280,12 @@ public void awardKillScore(Entity entityKilled, DamageSource damageSource) { if (entityKilled != this) { super.awardKillScore(entityKilled, damageSource); @@ -598,7 +599,7 @@ } else { this.awardStat(Stats.MOB_KILLS); } -@@ -1049,7 +1302,8 @@ +@@ -1049,7 +1303,8 @@ int i = scoreboardteam.getColor().getId(); if (i >= 0 && i < criterions.length) { @@ -608,7 +609,7 @@ } } -@@ -1062,8 +1316,8 @@ +@@ -1062,8 +1317,8 @@ } else { Entity entity = source.getEntity(); @@ -619,7 +620,7 @@ if (!this.canHarmPlayer(entityhuman)) { return false; -@@ -1074,8 +1328,8 @@ +@@ -1074,8 +1329,8 @@ AbstractArrow entityarrow = (AbstractArrow) entity; Entity entity1 = entityarrow.getOwner(); @@ -630,7 +631,7 @@ if (!this.canHarmPlayer(entityhuman1)) { return false; -@@ -1083,38 +1337,78 @@ +@@ -1083,38 +1338,78 @@ } } @@ -717,7 +718,7 @@ } public static Optional findRespawnAndUseSpawnBlock(ServerLevel world, BlockPos pos, float spawnAngle, boolean spawnForced, boolean alive) { -@@ -1129,11 +1423,11 @@ +@@ -1129,11 +1424,11 @@ } return optional.map((vec3d) -> { @@ -731,7 +732,7 @@ }); } else if (!spawnForced) { return Optional.empty(); -@@ -1142,7 +1436,7 @@ +@@ -1142,7 +1437,7 @@ BlockState iblockdata1 = world.getBlockState(pos.above()); boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1); @@ -740,7 +741,7 @@ } } -@@ -1160,6 +1454,7 @@ +@@ -1160,6 +1455,7 @@ @Nullable @Override public ServerPlayer teleport(TeleportTransition teleportTarget) { @@ -748,7 +749,7 @@ if (this.isRemoved()) { return null; } else { -@@ -1169,39 +1464,78 @@ +@@ -1169,39 +1465,78 @@ ServerLevel worldserver = teleportTarget.newLevel(); ServerLevel worldserver1 = this.serverLevel(); @@ -835,7 +836,7 @@ this.connection.resetPosition(); worldserver.addDuringTeleport(this); gameprofilerfiller.pop(); -@@ -1215,10 +1549,28 @@ +@@ -1215,12 +1550,30 @@ this.lastSentExp = -1; this.lastSentHealth = -1.0F; this.lastSentFood = -1; @@ -847,10 +848,10 @@ return this; } } -+ } -+ + } + + // CraftBukkit start -+ @Override + @Override + public CraftPortalEvent callPortalEvent(Entity entity, Location exit, TeleportCause cause, int searchRadius, int creationRadius) { + Location enter = this.getBukkitEntity().getLocation(); + PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); @@ -859,12 +860,14 @@ + return null; + } + return new CraftPortalEvent(event); - } ++ } + // CraftBukkit end - - @Override ++ ++ @Override public void forceSetRotation(float yaw, float pitch) { -@@ -1228,13 +1580,21 @@ + this.connection.send(new ClientboundPlayerRotationPacket(yaw, pitch)); + } +@@ -1228,13 +1581,21 @@ public void triggerDimensionChangeTriggers(ServerLevel origin) { ResourceKey resourcekey = origin.dimension(); ResourceKey resourcekey1 = this.level().dimension(); @@ -889,7 +892,7 @@ this.enteredNetherPosition = null; } -@@ -1251,36 +1611,63 @@ +@@ -1251,36 +1612,63 @@ this.containerMenu.broadcastChanges(); } @@ -968,7 +971,7 @@ this.awardStat(Stats.SLEEP_IN_BED); CriteriaTriggers.SLEPT_IN_BED.trigger(this); }); -@@ -1293,9 +1680,8 @@ +@@ -1293,9 +1681,8 @@ return either; } } @@ -979,7 +982,7 @@ } @Override -@@ -1322,13 +1708,31 @@ +@@ -1322,13 +1709,31 @@ @Override public void stopSleepInBed(boolean skipSleepTimer, boolean updateSleepingPlayers) { @@ -1012,7 +1015,7 @@ } } -@@ -1387,8 +1791,9 @@ +@@ -1387,8 +1792,9 @@ this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front)); } @@ -1023,7 +1026,7 @@ } @Override -@@ -1396,13 +1801,35 @@ +@@ -1396,13 +1802,35 @@ if (factory == null) { return OptionalInt.empty(); } else { @@ -1059,7 +1062,7 @@ if (container == null) { if (this.isSpectator()) { this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true); -@@ -1410,9 +1837,11 @@ +@@ -1410,9 +1838,11 @@ return OptionalInt.empty(); } else { @@ -1073,7 +1076,7 @@ return OptionalInt.of(this.containerCounter); } } -@@ -1425,15 +1854,26 @@ +@@ -1425,15 +1855,26 @@ @Override public void openHorseInventory(AbstractHorse horse, Container inventory) { @@ -1103,7 +1106,7 @@ this.initMenu(this.containerMenu); } -@@ -1456,6 +1896,13 @@ +@@ -1456,6 +1897,13 @@ @Override public void closeContainer() { @@ -1117,7 +1120,7 @@ this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); this.doCloseContainer(); } -@@ -1485,19 +1932,19 @@ +@@ -1485,19 +1933,19 @@ i = Math.round((float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * 100.0F); if (i > 0) { this.awardStat(Stats.SWIM_ONE_CM, i); @@ -1140,7 +1143,7 @@ } } else if (this.onClimbable()) { if (deltaY > 0.0D) { -@@ -1508,13 +1955,13 @@ +@@ -1508,13 +1956,13 @@ if (i > 0) { if (this.isSprinting()) { this.awardStat(Stats.SPRINT_ONE_CM, i); @@ -1157,7 +1160,7 @@ } } } else if (this.isFallFlying()) { -@@ -1557,7 +2004,7 @@ +@@ -1557,7 +2005,7 @@ @Override public void awardStat(Stat stat, int amount) { this.stats.increment(this, stat, amount); @@ -1166,7 +1169,7 @@ scoreaccess.add(amount); }); } -@@ -1565,7 +2012,7 @@ +@@ -1565,7 +2013,7 @@ @Override public void resetStat(Stat stat) { this.stats.setValue(this, stat, 0); @@ -1175,7 +1178,7 @@ } @Override -@@ -1597,9 +2044,9 @@ +@@ -1597,9 +2045,9 @@ super.jumpFromGround(); this.awardStat(Stats.JUMP); if (this.isSprinting()) { @@ -1187,7 +1190,7 @@ } } -@@ -1625,6 +2072,7 @@ +@@ -1625,6 +2073,7 @@ public void resetSentInfo() { this.lastSentHealth = -1.0E8F; @@ -1195,7 +1198,7 @@ } @Override -@@ -1661,7 +2109,7 @@ +@@ -1661,7 +2110,7 @@ this.onUpdateAbilities(); if (alive) { this.getAttributes().assignBaseValues(oldPlayer.getAttributes()); @@ -1204,7 +1207,7 @@ this.setHealth(oldPlayer.getHealth()); this.foodData = oldPlayer.foodData; Iterator iterator = oldPlayer.getActiveEffects().iterator(); -@@ -1669,7 +2117,7 @@ +@@ -1669,7 +2118,7 @@ while (iterator.hasNext()) { MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); @@ -1213,7 +1216,7 @@ } this.getInventory().replaceWith(oldPlayer.getInventory()); -@@ -1680,7 +2128,7 @@ +@@ -1680,7 +2129,7 @@ this.portalProcess = oldPlayer.portalProcess; } else { this.getAttributes().assignBaseValues(oldPlayer.getAttributes()); @@ -1222,7 +1225,7 @@ if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || oldPlayer.isSpectator()) { this.getInventory().replaceWith(oldPlayer.getInventory()); this.experienceLevel = oldPlayer.experienceLevel; -@@ -1696,7 +2144,7 @@ +@@ -1696,7 +2145,7 @@ this.lastSentExp = -1; this.lastSentHealth = -1.0F; this.lastSentFood = -1; @@ -1231,7 +1234,7 @@ this.seenCredits = oldPlayer.seenCredits; this.enteredNetherPosition = oldPlayer.enteredNetherPosition; this.chunkTrackingView = oldPlayer.chunkTrackingView; -@@ -1752,19 +2200,19 @@ +@@ -1752,19 +2201,19 @@ } @Override @@ -1255,7 +1258,7 @@ } return flag1; -@@ -1861,8 +2309,13 @@ +@@ -1861,8 +2310,13 @@ } public void sendChatMessage(OutgoingChatMessage message, boolean filterMaskEnabled, ChatType.Bound params) { @@ -1270,7 +1273,7 @@ } } -@@ -1878,7 +2331,18 @@ +@@ -1878,7 +2332,18 @@ } public void updateOptions(ClientInformation clientOptions) { @@ -1289,7 +1292,7 @@ this.requestedViewDistance = clientOptions.viewDistance(); this.chatVisibility = clientOptions.chatVisibility(); this.canChatColor = clientOptions.chatColors(); -@@ -1957,12 +2421,27 @@ +@@ -1957,12 +2422,27 @@ this.camera = (Entity) (entity == null ? this : entity); if (entity1 != this.camera) { @@ -1318,7 +1321,7 @@ } if (entity != null) { -@@ -1999,11 +2478,11 @@ +@@ -1999,11 +2479,11 @@ @Nullable public Component getTabListDisplayName() { @@ -1332,7 +1335,7 @@ } @Override -@@ -2046,17 +2525,43 @@ +@@ -2046,17 +2526,43 @@ } public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) { @@ -1383,7 +1386,7 @@ } else { this.respawnPosition = null; this.respawnDimension = Level.OVERWORLD; -@@ -2088,18 +2593,44 @@ +@@ -2088,18 +2594,44 @@ } @Override @@ -1432,7 +1435,7 @@ } this.awardStat(Stats.DROP); -@@ -2275,9 +2806,15 @@ +@@ -2275,9 +2807,15 @@ @Override public void stopRiding() { @@ -1449,7 +1452,7 @@ if (entity instanceof LivingEntity entityliving) { Iterator iterator = entityliving.getActiveEffects().iterator(); -@@ -2375,16 +2912,161 @@ +@@ -2375,16 +2913,161 @@ return TicketType.ENDER_PEARL.timeout(); } diff --git a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch index 9ae3e3ffee..f85d4644f4 100644 --- a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -90,11 +90,12 @@ this.server = server; this.registries = registryManager; this.maxPlayers = maxPlayers; -@@ -148,27 +181,37 @@ +@@ -148,27 +181,38 @@ } public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) { + player.isRealPlayer = true; // Paper ++ player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameprofile = player.getGameProfile(); GameProfileCache usercache = this.server.getProfileCache(); - Optional optional; @@ -133,7 +134,7 @@ ServerLevel worldserver = this.server.getLevel(resourcekey); ServerLevel worldserver1; -@@ -182,10 +225,27 @@ +@@ -182,10 +226,27 @@ player.setServerLevel(worldserver1); String s1 = connection.getLoggableAddress(this.server.logIPs()); @@ -163,7 +164,7 @@ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, clientData); connection.setupInboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection); -@@ -194,7 +254,9 @@ +@@ -194,7 +255,9 @@ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); @@ -174,7 +175,7 @@ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities())); playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected)); -@@ -213,8 +275,10 @@ +@@ -213,8 +276,10 @@ } else { ichatmutablecomponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), s); } @@ -186,7 +187,7 @@ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot()); ServerStatus serverping = this.server.getStatus(); -@@ -222,17 +286,77 @@ +@@ -222,17 +287,77 @@ player.sendServerStatus(serverping); } @@ -268,7 +269,7 @@ } public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { -@@ -269,30 +393,31 @@ +@@ -269,30 +394,31 @@ } public void addWorldborderListener(ServerLevel world) { @@ -305,7 +306,7 @@ } @Override -@@ -319,14 +444,15 @@ +@@ -319,14 +445,15 @@ } protected void save(ServerPlayer player) { @@ -323,7 +324,7 @@ if (advancementdataplayer != null) { advancementdataplayer.save(); -@@ -334,95 +460,186 @@ +@@ -334,95 +461,186 @@ } @@ -548,7 +549,7 @@ if (entityplayer1 != null) { set.add(entityplayer1); -@@ -431,30 +648,50 @@ +@@ -431,30 +649,50 @@ Iterator iterator1 = set.iterator(); while (iterator1.hasNext()) { @@ -612,7 +613,7 @@ while (iterator.hasNext()) { String s = (String) iterator.next(); -@@ -462,41 +699,88 @@ +@@ -462,41 +700,88 @@ entityplayer1.addTag(s); } @@ -709,7 +710,7 @@ return entityplayer1; } -@@ -516,15 +800,32 @@ +@@ -516,15 +801,32 @@ } public void sendPlayerPermissionLevel(ServerPlayer player) { @@ -744,7 +745,7 @@ this.sendAllPlayerInfoIn = 0; } -@@ -541,6 +842,25 @@ +@@ -541,6 +843,25 @@ } @@ -770,7 +771,7 @@ public void broadcastAll(Packet packet, ResourceKey dimension) { Iterator iterator = this.players.iterator(); -@@ -554,7 +874,7 @@ +@@ -554,7 +875,7 @@ } @@ -779,7 +780,7 @@ PlayerTeam scoreboardteam = source.getTeam(); if (scoreboardteam != null) { -@@ -573,7 +893,7 @@ +@@ -573,7 +894,7 @@ } } @@ -788,7 +789,7 @@ PlayerTeam scoreboardteam = source.getTeam(); if (scoreboardteam == null) { -@@ -619,7 +939,7 @@ +@@ -619,7 +940,7 @@ } public void deop(GameProfile profile) { @@ -797,7 +798,7 @@ ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { -@@ -643,36 +963,51 @@ +@@ -643,11 +964,30 @@ player.connection.send(new ClientboundEntityEventPacket(player, b0)); } @@ -809,12 +810,12 @@ - return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); + // Paper start - ProfileWhitelistVerifyEvent + return this.isWhiteListed(profile, null); - } ++ } + public boolean isWhiteListed(GameProfile gameprofile, @Nullable org.bukkit.event.player.PlayerLoginEvent loginEvent) { + boolean isOp = this.ops.contains(gameprofile); + boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); + final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; - ++ + final net.kyori.adventure.text.Component configuredMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage); + event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(gameprofile), this.doWhiteList, isWhitelisted, isOp, configuredMessage); + event.callEvent(); @@ -826,12 +827,11 @@ + } + return true; + // Paper end - ProfileWhitelistVerifyEvent -+ } -+ - public boolean isOp(GameProfile profile) { - return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().isAllowCommands() || this.allowCommandsForAllPlayers; } + public boolean isOp(GameProfile profile) { +@@ -656,23 +996,19 @@ + @Nullable public ServerPlayer getPlayerByName(String name) { - int i = this.players.size(); @@ -862,7 +862,7 @@ if (entityplayer != player && entityplayer.level().dimension() == worldKey) { double d4 = x - entityplayer.getX(); double d5 = y - entityplayer.getY(); -@@ -687,10 +1022,12 @@ +@@ -687,10 +1023,12 @@ } public void saveAll() { @@ -875,7 +875,7 @@ } public UserWhiteList getWhiteList() { -@@ -712,15 +1049,19 @@ +@@ -712,15 +1050,19 @@ public void reloadWhiteList() {} public void sendLevelInfo(ServerPlayer player, ServerLevel world) { @@ -899,7 +899,7 @@ } player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); -@@ -729,8 +1070,16 @@ +@@ -729,8 +1071,16 @@ public void sendAllPlayerInfo(ServerPlayer player) { player.inventoryMenu.sendAllDataToRemote(); @@ -917,7 +917,7 @@ } public int getPlayerCount() { -@@ -786,11 +1135,35 @@ +@@ -786,11 +1136,35 @@ } public void removeAll() { @@ -955,7 +955,7 @@ public void broadcastSystemMessage(Component message, boolean overlay) { this.broadcastSystemMessage(message, (entityplayer) -> { -@@ -819,24 +1192,43 @@ +@@ -819,24 +1193,43 @@ } public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params) { @@ -1002,7 +1002,7 @@ } if (flag1 && sender != null) { -@@ -845,20 +1237,27 @@ +@@ -845,20 +1238,27 @@ } @@ -1035,7 +1035,7 @@ Path path = file2.toPath(); if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { -@@ -867,7 +1266,7 @@ +@@ -867,7 +1267,7 @@ } serverstatisticmanager = new ServerStatsCounter(this.server, file1); @@ -1044,7 +1044,7 @@ } return serverstatisticmanager; -@@ -875,13 +1274,13 @@ +@@ -875,13 +1275,13 @@ public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { UUID uuid = player.getUUID(); @@ -1060,7 +1060,7 @@ } advancementdataplayer.setPlayer(player); -@@ -932,15 +1331,28 @@ +@@ -932,15 +1332,28 @@ } public void reloadResources() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java index f6b2ca92fd..e0d342a0dd 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -262,6 +262,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa return this.getData() != null; } + // Paper start + @Override + public long getLastLogin() { + Player player = getPlayer(); + if (player != null) return player.getLastLogin(); + + CompoundTag data = getPaperData(); + + if (data != null) { + if (data.contains("LastLogin")) { + return data.getLong("LastLogin"); + } else { + // 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; + } + } + + @Override + public long getLastSeen() { + Player player = getPlayer(); + if (player != null) return player.getLastSeen(); + + CompoundTag data = getPaperData(); + + if (data != null) { + if (data.contains("LastSeen")) { + return data.getLong("LastSeen"); + } else { + // 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(); + + if (result != null) { + if (!result.contains("Paper")) { + result.put("Paper", new CompoundTag()); + } + result = result.getCompound("Paper"); + } + + return result; + } + // Paper end + @Override public Location getLastDeathLocation() { if (this.getData().contains("LastDeathLocation", 10)) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 63cc339b42..d5f89783d1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -215,6 +215,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private BorderChangeListener clientWorldBorderListener = this.createWorldBorderListener(); public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; // Paper - more resource pack API private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit + private long lastSaveTime; // Paper - getLastPlayed replacement API public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); @@ -2064,6 +2065,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.firstPlayed = firstPlayed; } + // Paper start - getLastPlayed replacement API + @Override + public long getLastLogin() { + return this.getHandle().loginTime; + } + + @Override + public long getLastSeen() { + return this.isOnline() ? System.currentTimeMillis() : this.lastSaveTime; + } + // Paper end - getLastPlayed replacement API + public void readExtraData(CompoundTag nbttagcompound) { this.hasPlayedBefore = true; if (nbttagcompound.contains("bukkit")) { @@ -2086,6 +2099,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setExtraData(CompoundTag nbttagcompound) { + this.lastSaveTime = System.currentTimeMillis(); // Paper + if (!nbttagcompound.contains("bukkit")) { nbttagcompound.put("bukkit", new CompoundTag()); } @@ -2100,6 +2115,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { data.putLong("firstPlayed", this.getFirstPlayed()); data.putLong("lastPlayed", System.currentTimeMillis()); data.putString("lastKnownName", handle.getScoreboardName()); + + // Paper start - persist for use in offline save data + if (!nbttagcompound.contains("Paper")) { + nbttagcompound.put("Paper", new CompoundTag()); + } + + CompoundTag paper = nbttagcompound.getCompound("Paper"); + paper.putLong("LastLogin", handle.loginTime); + paper.putLong("LastSeen", System.currentTimeMillis()); + // Paper end } @Override