mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-24 01:19:25 +00:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@5e2a3bc0 Call EntityChangeBlockEvent with correct block when waxing (#12154) PaperMC/Paper@ab984a07 Always pass event block to damage source (#12158) PaperMC/Paper@7b4d44f5 Revert "Always pass event block to damage source (#12158)" PaperMC/Paper@e5a8ee84 Hide soul speed particles for vanished players (#12152) PaperMC/Paper@fcb2e815 Clear lastSection on game event listener removal PaperMC/Paper@636ae0cd Add missing Paper comments to player movement patch PaperMC/Paper@9be4e07a Pin snapshot dependencies (#12185) PaperMC/Paper@f12d33f0 Track codec writing PaperMC/Paper@1d9b3994 Add config option for failed beehive release cooldowns (#12186) PaperMC/Paper@5f2ee83e Fix first execution of async delayed/repeating tasks being sync (#12166) PaperMC/Paper@b00875f8 Add a method on Registry to get the size (#12182) PaperMC/Paper@ca261090 Don't process empty rcon commands (#12188) PaperMC/Paper@a501c459 Deprecate server config getters (#12189) PaperMC/Paper@7f3d3591 Use MiniMessage#deserialize(String, Pointered) in sendRichMessage for send messages (#12177) PaperMC/Paper@9b9f046f Remove broken code (#12171) PaperMC/Paper@fc56c728 Add methods for Creaking (#12094) PaperMC/Paper@f63dbeaf Fix cancelled HangingPlaceEvent inventory desync (#12161) PaperMC/Paper@9421f223 Make CustomArgumentType use parse(reader,source) (#12191) PaperMC/Paper@0a6e7435 Fix invulnerability damage and armour (#12190) Gale Changes: Dreeam-qwq/Gale@b2c11564 Updated Upstream (Paper) Dreeam-qwq/Gale@a9e4baae Updated Upstream (Paper) Dreeam-qwq/Gale@32a291bc [ci/skip] Update comment Purpur Changes: PurpurMC/Purpur@62cbd47a Updated Upstream (Paper) PurpurMC/Purpur@d41aaca1 Updated Upstream (Paper) PurpurMC/Purpur@3f8e6134 Fix EntityTameEvent not being called when `always-tame-in-creative` option is enabled (#1645) PurpurMC/Purpur@b34d675f fix `zombie_horse.spawn-chance` option not working
394 lines
25 KiB
Diff
394 lines
25 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
Date: Thu, 3 Aug 2023 20:36:38 +0800
|
|
Subject: [PATCH] Leaves: Replay Mod API
|
|
|
|
Co-authored-by: alazeprt <nono135246@126.com>
|
|
|
|
Original license: GPLv3
|
|
Original project: https://github.com/LeavesMC/Leaves
|
|
|
|
This patch is Powered by ReplayMod(https://github.com/ReplayMod)
|
|
|
|
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
|
|
index 59c70c567051bc7dba0d308387352d1b15f3c842..e654387167cf3e9a88f0e62be940fe398387cffa 100644
|
|
--- a/net/minecraft/commands/CommandSourceStack.java
|
|
+++ b/net/minecraft/commands/CommandSourceStack.java
|
|
@@ -626,7 +626,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
|
|
|
|
@Override
|
|
public Collection<String> getOnlinePlayerNames() {
|
|
- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
|
|
+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
|
index b305ba9bab617bf4e52d0e6ddf160bacc5751a94..c9b4f00d5ccde83898ecf69efdbfee7a3f91b96d 100644
|
|
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
|
|
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
|
@@ -128,11 +128,12 @@ public class EntitySelector {
|
|
return this.findPlayers(source);
|
|
} else if (this.playerName != null) {
|
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
|
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
|
return playerByName == null ? List.of() : List.of(playerByName);
|
|
} else if (this.entityUUID != null) {
|
|
for (ServerLevel serverLevel : source.getServer().getAllLevels()) {
|
|
Entity entity = serverLevel.getEntity(this.entityUUID);
|
|
- if (entity != null) {
|
|
+ if (entity != null && !(entity instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // Leaves - skip photographer
|
|
if (entity.getType().isEnabled(source.enabledFeatures())) {
|
|
return List.of(entity);
|
|
}
|
|
@@ -146,7 +147,7 @@ public class EntitySelector {
|
|
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
|
|
if (this.currentEntity) {
|
|
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
|
|
- return source.getEntity() != null && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of();
|
|
+ return source.getEntity() != null && !(source.getEntity() instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of(); // Leaves - skip photographer
|
|
} else {
|
|
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, source.enabledFeatures());
|
|
List<Entity> list = new ObjectArrayList<>();
|
|
@@ -157,6 +158,7 @@ public class EntitySelector {
|
|
this.addEntities(list, serverLevel1, absoluteAabb, predicate);
|
|
}
|
|
}
|
|
+ list.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
|
|
|
|
return this.sortAndLimit(vec3, list);
|
|
}
|
|
@@ -192,27 +194,30 @@ public class EntitySelector {
|
|
this.checkPermissions(source);
|
|
if (this.playerName != null) {
|
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
|
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
|
return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
|
|
} else if (this.entityUUID != null) {
|
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID);
|
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
|
return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
|
|
} else {
|
|
Vec3 vec3 = this.position.apply(source.getPosition());
|
|
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
|
|
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
|
|
if (this.currentEntity) {
|
|
+ //return source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer) && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && canSee(source, serverPlayer) ? List.of(serverPlayer) : List.of(); // Purpur - Hide hidden players from entity selector // Leaves - skip photographer
|
|
return source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer) && canSee(source, serverPlayer) ? List.of(serverPlayer) : List.of(); // Purpur - Hide hidden players from entity selector
|
|
} else {
|
|
int resultLimit = this.getResultLimit();
|
|
List<ServerPlayer> players;
|
|
if (this.isWorldLimited()) {
|
|
players = source.getLevel().getPlayers(predicate, resultLimit);
|
|
- players.removeIf(entityplayer3 -> !canSee(source, entityplayer3)); // Purpur - Hide hidden players from entity selector
|
|
+ players.removeIf(entityplayer3 -> entityplayer3 instanceof org.leavesmc.leaves.replay.ServerPhotographer || !canSee(source, entityplayer3)); // Purpur - Hide hidden players from entity selector // Leaves - skip photographer
|
|
} else {
|
|
players = new ObjectArrayList<>();
|
|
|
|
for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) {
|
|
- if (predicate.test(serverPlayer1) && canSee(source, serverPlayer1)) { // Purpur - Hide hidden players from entity selector
|
|
+ if (!(serverPlayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(serverPlayer1) && canSee(source, serverPlayer1)) { // Purpur - Hide hidden players from entity selector // Leaves - skip photographer
|
|
players.add(serverPlayer1);
|
|
if (players.size() >= resultLimit) {
|
|
return players;
|
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
index dddbb18992348fb7e8a6552423d134809cd7fdbc..0e6e71030e3fd1335fff796b861524a48cb0a507 100644
|
|
--- a/net/minecraft/server/MinecraftServer.java
|
|
+++ b/net/minecraft/server/MinecraftServer.java
|
|
@@ -1650,7 +1650,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
}
|
|
|
|
private ServerStatus.Players buildPlayerStatus() {
|
|
- List<ServerPlayer> players = this.playerList.getPlayers();
|
|
+ List<ServerPlayer> players = this.playerList.realPlayers; // Leaves - only real player
|
|
int maxPlayers = this.getMaxPlayers();
|
|
if (this.hidesOnlinePlayers()) {
|
|
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
|
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
|
index 792ba93b531e9586e26aafa00830022a8996fc04..e4ea26ae84efde7ce54e08a246a6ea2ae2a17151 100644
|
|
--- a/net/minecraft/server/PlayerAdvancements.java
|
|
+++ b/net/minecraft/server/PlayerAdvancements.java
|
|
@@ -168,6 +168,11 @@ public class PlayerAdvancements {
|
|
}
|
|
|
|
public boolean award(AdvancementHolder advancement, String criterionKey) {
|
|
+ // Leaves start - photographer can't get advancement
|
|
+ if (player instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
|
|
+ return false;
|
|
+ }
|
|
+ // Leaves end - photographer can't get advancement
|
|
boolean flag = false;
|
|
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
|
|
boolean isDone = orStartProgress.isDone();
|
|
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
|
|
index 5c0a04db38821dbb0cba2bb6f0787f113d167efd..cd153db93f709c3142942fac88ae3ca2226a65b3 100644
|
|
--- a/net/minecraft/server/commands/OpCommand.java
|
|
+++ b/net/minecraft/server/commands/OpCommand.java
|
|
@@ -25,7 +25,7 @@ public class OpCommand {
|
|
(context, builder) -> {
|
|
PlayerList playerList = context.getSource().getServer().getPlayerList();
|
|
return SharedSuggestionProvider.suggest(
|
|
- playerList.getPlayers()
|
|
+ playerList.realPlayers // Leaves - only real player
|
|
.stream()
|
|
.filter(player -> !playerList.isOp(player.getGameProfile()))
|
|
.map(player -> player.getGameProfile().getName()),
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index e3f8a469042636e4e49456d3bff862384d8ea1b8..d6f68208e4d487950eecc12edb197322cd80a4ad 100644
|
|
--- a/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
|
@@ -216,6 +216,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
|
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
|
|
public boolean hasRidableMoveEvent = false; // Purpur - Ridables
|
|
+ final List<ServerPlayer> realPlayers; // Leaves - skip
|
|
|
|
public LevelChunk getChunkIfLoaded(int x, int z) {
|
|
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
|
@@ -700,6 +701,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
// Paper end - rewrite chunk system
|
|
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
|
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
|
+ this.realPlayers = Lists.newArrayList(); // Leaves - skip
|
|
}
|
|
|
|
// Paper start
|
|
@@ -2671,6 +2673,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
|
if (entity instanceof ServerPlayer serverPlayer) {
|
|
ServerLevel.this.players.add(serverPlayer);
|
|
+ // Leaves start - skip
|
|
+ if (!(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
|
|
+ ServerLevel.this.realPlayers.add(serverPlayer);
|
|
+ }
|
|
+ // Leaves end - skip
|
|
ServerLevel.this.updateSleepingPlayerList();
|
|
}
|
|
|
|
@@ -2741,6 +2748,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
ServerLevel.this.getChunkSource().removeEntity(entity);
|
|
if (entity instanceof ServerPlayer serverPlayer) {
|
|
ServerLevel.this.players.remove(serverPlayer);
|
|
+ // Leaves start - skip
|
|
+ if (!(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
|
|
+ ServerLevel.this.realPlayers.remove(serverPlayer);
|
|
+ }
|
|
+ // Leaves end - skip
|
|
ServerLevel.this.updateSleepingPlayerList();
|
|
}
|
|
|
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
|
index 622257dbbe572de33e15abef9055016268730261..dfb4524d80f642eff1b146dd2fbfa07f21d844c6 100644
|
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -195,7 +195,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
);
|
|
public ServerGamePacketListenerImpl connection;
|
|
public final MinecraftServer server;
|
|
- public final ServerPlayerGameMode gameMode;
|
|
+ public ServerPlayerGameMode gameMode; // Leaves - final -> null
|
|
private final PlayerAdvancements advancements;
|
|
private final ServerStatsCounter stats;
|
|
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
|
index e3d09d5f4efb32bb276e001e5ee747a775b502ee..78b15d750d75e5d4c2318a3a18e83afdd5f4fbe1 100644
|
|
--- a/net/minecraft/server/players/PlayerList.java
|
|
+++ b/net/minecraft/server/players/PlayerList.java
|
|
@@ -132,6 +132,7 @@ public abstract class PlayerList {
|
|
private boolean allowCommandsForAllPlayers;
|
|
private static final boolean ALLOW_LOGOUTIVATOR = false;
|
|
private int sendAllPlayerInfoIn;
|
|
+ public final List<ServerPlayer> realPlayers = new java.util.concurrent.CopyOnWriteArrayList(); // Leaves - replay api
|
|
|
|
// CraftBukkit start
|
|
private org.bukkit.craftbukkit.CraftServer cserver;
|
|
@@ -150,6 +151,106 @@ public abstract class PlayerList {
|
|
|
|
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
|
|
|
|
+ // Leaves start - replay mod api
|
|
+ public void placeNewPhotographer(Connection connection, org.leavesmc.leaves.replay.ServerPhotographer player, ServerLevel worldserver) {
|
|
+ player.isRealPlayer = true; // Paper
|
|
+ player.loginTime = System.currentTimeMillis(); // Paper
|
|
+
|
|
+ ServerLevel worldserver1 = worldserver;
|
|
+
|
|
+ player.setServerLevel(worldserver1);
|
|
+ player.spawnIn(worldserver1);
|
|
+ player.gameMode.setLevel((ServerLevel) player.level());
|
|
+
|
|
+ LevelData worlddata = worldserver1.getLevelData();
|
|
+
|
|
+ player.loadGameTypes(null);
|
|
+ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, CommonListenerCookie.createInitial(player.gameProfile, false));
|
|
+ GameRules gamerules = worldserver1.getGameRules();
|
|
+ boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN);
|
|
+ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
|
|
+ boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
|
|
+
|
|
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1), this.server.enforceSecureProfile())); // Paper - replace old player chunk management
|
|
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
|
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
|
|
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
|
+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
|
|
+ RecipeManager craftingmanager = this.server.getRecipeManager();
|
|
+ playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes()));
|
|
+
|
|
+ this.sendPlayerPermissionLevel(player);
|
|
+ player.getStats().markAllDirty();
|
|
+ player.getRecipeBook().sendInitialRecipeBook(player);
|
|
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
|
|
+ this.server.invalidateStatus();
|
|
+
|
|
+ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
|
+ ServerStatus serverping = this.server.getStatus();
|
|
+
|
|
+ if (serverping != null) {
|
|
+ player.sendServerStatus(serverping);
|
|
+ }
|
|
+
|
|
+ this.players.add(player);
|
|
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
|
+ this.playersByUUID.put(player.getUUID(), player);
|
|
+
|
|
+ player.supressTrackerForLogin = true;
|
|
+ worldserver1.addNewPlayer(player);
|
|
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
|
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
|
+
|
|
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
|
|
+ if (!player.connection.isAcceptingMessages()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
|
+
|
|
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
|
|
+ for (int i = 0; i < this.players.size(); ++i) {
|
|
+ ServerPlayer entityplayer1 = this.players.get(i);
|
|
+
|
|
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ onlinePlayers.add(entityplayer1);
|
|
+ }
|
|
+ if (!onlinePlayers.isEmpty()) {
|
|
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
|
|
+ }
|
|
+
|
|
+ player.sentListPacket = true;
|
|
+ player.supressTrackerForLogin = false;
|
|
+ ((ServerLevel) player.level()).getChunkSource().chunkMap.addEntity(player);
|
|
+
|
|
+ this.sendLevelInfo(player, worldserver1);
|
|
+
|
|
+ if (player.level() == worldserver1 && !worldserver1.players().contains(player)) {
|
|
+ worldserver1.addNewPlayer(player);
|
|
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
|
+ }
|
|
+
|
|
+ worldserver1 = player.serverLevel();
|
|
+ java.util.Iterator<MobEffectInstance> iterator = player.getActiveEffects().iterator();
|
|
+ while (iterator.hasNext()) {
|
|
+ MobEffectInstance mobeffect = iterator.next();
|
|
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect, false));
|
|
+ }
|
|
+
|
|
+ if (player.isDeadOrDying()) {
|
|
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.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(
|
|
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
|
|
+ worldserver1.getLightEngine(), null, null, false)
|
|
+ );
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - replay mod api
|
|
+
|
|
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
|
|
player.isRealPlayer = true; // Paper
|
|
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
|
|
@@ -315,6 +416,7 @@ public abstract class PlayerList {
|
|
|
|
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
|
this.players.add(player);
|
|
+ this.realPlayers.add(player); // Leaves - replay api
|
|
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
|
this.playersByUUID.put(player.getUUID(), player);
|
|
this.addToSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
|
|
@@ -374,6 +476,12 @@ public abstract class PlayerList {
|
|
continue;
|
|
}
|
|
|
|
+ // Leaves start - skip photographer
|
|
+ if (entityplayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
|
|
+ continue;
|
|
+ }
|
|
+ // Leaves end - skip photographer
|
|
+
|
|
onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
|
|
}
|
|
// Paper start - Use single player info update packet on join
|
|
@@ -515,6 +623,43 @@ public abstract class PlayerList {
|
|
}
|
|
}
|
|
|
|
+ // Leaves start - replay mod api
|
|
+ public void removePhotographer(org.leavesmc.leaves.replay.ServerPhotographer entityplayer) {
|
|
+ ServerLevel worldserver = entityplayer.serverLevel();
|
|
+
|
|
+ entityplayer.awardStat(Stats.LEAVE_GAME);
|
|
+
|
|
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
|
|
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT);
|
|
+ }
|
|
+
|
|
+ if (server.isSameThread()) entityplayer.doTick();
|
|
+
|
|
+ if (this.collideRuleTeamName != null) {
|
|
+ final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
|
|
+ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
|
|
+ if (entityplayer.getTeam() == team && team != null) {
|
|
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
|
+ entityplayer.retireScheduler();
|
|
+ entityplayer.getAdvancements().stopListening();
|
|
+ this.players.remove(entityplayer);
|
|
+ this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT));
|
|
+ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer);
|
|
+ UUID uuid = entityplayer.getUUID();
|
|
+ ServerPlayer entityplayer1 = this.playersByUUID.get(uuid);
|
|
+
|
|
+ if (entityplayer1 == entityplayer) {
|
|
+ this.playersByUUID.remove(uuid);
|
|
+ }
|
|
+
|
|
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
|
|
+ }
|
|
+ // Leaves stop - replay mod api
|
|
+
|
|
public net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
|
|
// Paper start - Fix kick event leave message not being sent
|
|
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
|
|
@@ -591,6 +736,7 @@ public abstract class PlayerList {
|
|
player.retireScheduler(); // Paper - Folia schedulers
|
|
player.getAdvancements().stopListening();
|
|
this.players.remove(player);
|
|
+ this.realPlayers.remove(player); // Leaves - replay api
|
|
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
|
this.removeFromSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
|
|
this.server.getCustomBossEvents().onPlayerDisconnect(player);
|
|
@@ -688,7 +834,7 @@ public abstract class PlayerList {
|
|
// return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)
|
|
// ? Component.translatable("multiplayer.disconnect.server_full")
|
|
// : null;
|
|
- if (this.players.size() >= this.maxPlayers && !(player.hasPermission("purpur.joinfullserver") || this.canBypassPlayerLimit(gameProfile))) { // Purpur - Allow player join full server by permission
|
|
+ if (this.realPlayers.size() >= this.maxPlayers && !(player.hasPermission("purpur.joinfullserver") || this.canBypassPlayerLimit(gameProfile))) { // Purpur - Allow player join full server by permission // Leaves - only real player
|
|
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
|
|
}
|
|
}
|