PlayerDeathEvent#getItemsToKeep

Exposes a mutable array on items a player should keep on death

Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4

== AT ==
public net.minecraft.world.entity.player.Inventory compartments
This commit is contained in:
Aikar 2019-03-27 23:01:33 -04:00
parent 8e13bc622b
commit 18f38c3167

View file

@ -114,7 +114,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -258,7 +293,32 @@
@@ -258,6 +293,31 @@
private final CommandSource commandSource;
private int containerCounter;
public boolean wonGame;
@ -124,7 +124,7 @@
+ public boolean queueHealthUpdatePacket;
+ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
+ // Paper end - cancellable death event
+
+ // CraftBukkit start
+ public CraftPlayer.TransferCookieConnection transferCookieConnection;
+ public String displayName;
@ -143,10 +143,9 @@
+ // CraftBukkit end
+ public boolean isRealPlayer; // Paper
+ public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
+
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
this.chatVisibility = ChatVisiblity.FULL;
@@ -266,7 +326,7 @@
this.canChatColor = true;
this.lastActionTime = Util.getMillis();
@ -180,8 +179,8 @@
+ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper
+ this.bukkitPickUpLoot = true;
+ this.maxHealthCache = this.getMaxHealth();
+ }
+
}
+ // Use method to resend items in hands in case of client desync, because the item use got cancelled.
+ // For example, when cancelling the leash event
+ public void resendItemInHands() {
@ -227,9 +226,9 @@
+ }
+
+ return blockposition;
}
+ }
+ // CraftBukkit end
+
@Override
public BlockPos adjustSpawnLocation(ServerLevel world, BlockPos basePos) {
AABB axisalignedbb = this.getDimensions(Pose.STANDING).makeBoundingBox(Vec3.ZERO);
@ -280,16 +279,16 @@
if (this.isSleeping()) {
this.stopSleeping();
}
+ }
+
+ // CraftBukkit start
+ String spawnWorld = nbt.getString("SpawnWorld");
+ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld);
+ if (oldWorld != null) {
+ this.respawnDimension = oldWorld.getHandle().dimension();
+ }
}
+ // CraftBukkit end
+
if (nbt.contains("SpawnX", 99) && nbt.contains("SpawnY", 99) && nbt.contains("SpawnZ", 99)) {
this.respawnPosition = new BlockPos(nbt.getInt("SpawnX"), nbt.getInt("SpawnY"), nbt.getInt("SpawnZ"));
this.respawnForced = nbt.getBoolean("SpawnForced");
@ -390,12 +389,10 @@
Logger logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -684,7 +834,30 @@
}
}
@@ -686,6 +836,29 @@
}
+ }
+
+ // CraftBukkit start - World fallback code, either respawn location or global spawn
+ public void spawnIn(Level world) {
+ this.setLevel(world);
@ -416,11 +413,12 @@
+ this.setPos(position);
+ }
+ this.gameMode.setLevel((ServerLevel) world);
}
+ }
+ // CraftBukkit end
+
public void setExperiencePoints(int points) {
float f = (float) this.getXpNeededForNextLevel();
float f1 = (f - 1.0F) / f;
@@ -744,6 +917,11 @@
@Override
@ -471,17 +469,15 @@
if (this.experienceLevel != this.lastRecordedLevel) {
this.lastRecordedLevel = this.experienceLevel;
this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel));
@@ -863,8 +1051,22 @@
if (this.tickCount % 20 == 0) {
@@ -865,6 +1053,20 @@
CriteriaTriggers.LOCATION.trigger(this);
+ }
+
}
+ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border
+ if (this.oldLevel == -1) {
+ this.oldLevel = this.experienceLevel;
}
+ }
+
+ if (this.oldLevel != this.experienceLevel) {
+ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel);
+ this.oldLevel = this.experienceLevel;
@ -503,7 +499,7 @@
}
float f = this.foodData.getSaturationLevel();
@@ -946,19 +1148,63 @@
@@ -946,19 +1148,103 @@
}
private void updateScoreForCriteria(ObjectiveCriteria criterion, int score) {
@ -514,6 +510,46 @@
});
}
+ // Paper start - PlayerDeathEvent#getItemsToKeep
+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList<ItemStack> inv) {
+ List<org.bukkit.inventory.ItemStack> itemsToKeep = event.getItemsToKeep();
+ if (inv == null) {
+ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot?
+ if (!itemsToKeep.isEmpty()) {
+ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) {
+ event.getEntity().getInventory().addItem(itemStack);
+ }
+ }
+
+ return;
+ }
+
+ for (int i = 0; i < inv.size(); ++i) {
+ ItemStack item = inv.get(i);
+ if (EnchantmentHelper.has(item, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP) || itemsToKeep.isEmpty() || item.isEmpty()) {
+ inv.set(i, ItemStack.EMPTY);
+ continue;
+ }
+
+ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack();
+ boolean keep = false;
+ final Iterator<org.bukkit.inventory.ItemStack> iterator = itemsToKeep.iterator();
+ while (iterator.hasNext()) {
+ final org.bukkit.inventory.ItemStack itemStack = iterator.next();
+ if (bukkitStack.equals(itemStack)) {
+ iterator.remove();
+ keep = true;
+ break;
+ }
+ }
+
+ if (!keep) {
+ inv.set(i, ItemStack.EMPTY);
+ }
+ }
+ }
+ // Paper end - PlayerDeathEvent#getItemsToKeep
+
@Override
public void die(DamageSource damageSource) {
- this.gameEvent(GameEvent.ENTITY_DIE);
@ -538,7 +574,7 @@
+ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
+ this.dropFromLootTable(this.serverLevel(), damageSource, this.lastHurtByPlayerTime > 0);
+ this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag);
+
+ loot.addAll(this.drops);
+ this.drops.clear(); // SPIGOT-5188: make sure to clear
+
@ -564,14 +600,14 @@
+ }
+
+ net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure
+
+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override?
+ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure
+
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> {
boolean flag1 = true;
String s = ichatbasecomponent.getString(256);
@@ -988,12 +1234,18 @@
@@ -988,12 +1274,23 @@
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) {
this.tellNeutralMobsThatIDied();
}
@ -582,7 +618,12 @@
+ this.dropExperience(this.serverLevel(), damageSource.getEntity());
+ // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
+ if (!event.getKeepInventory()) {
+ this.getInventory().clearContent();
+ // Paper start - PlayerDeathEvent#getItemsToKeep
+ for (NonNullList<ItemStack> inv : this.getInventory().compartments) {
+ processKeep(event, inv);
+ }
+ processKeep(event, null);
+ // Paper end - PlayerDeathEvent#getItemsToKeep
}
- this.getScoreboard().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment);
@ -594,7 +635,7 @@
LivingEntity entityliving = this.getKillCredit();
if (entityliving != null) {
@@ -1028,10 +1280,12 @@
@@ -1028,10 +1325,12 @@
public void awardKillScore(Entity entityKilled, DamageSource damageSource) {
if (entityKilled != this) {
super.awardKillScore(entityKilled, damageSource);
@ -610,7 +651,7 @@
} else {
this.awardStat(Stats.MOB_KILLS);
}
@@ -1049,7 +1303,8 @@
@@ -1049,7 +1348,8 @@
int i = scoreboardteam.getColor().getId();
if (i >= 0 && i < criterions.length) {
@ -620,7 +661,7 @@
}
}
@@ -1062,8 +1317,8 @@
@@ -1062,8 +1362,8 @@
} else {
Entity entity = source.getEntity();
@ -631,7 +672,7 @@
if (!this.canHarmPlayer(entityhuman)) {
return false;
@@ -1074,8 +1329,8 @@
@@ -1074,8 +1374,8 @@
AbstractArrow entityarrow = (AbstractArrow) entity;
Entity entity1 = entityarrow.getOwner();
@ -642,7 +683,7 @@
if (!this.canHarmPlayer(entityhuman1)) {
return false;
@@ -1083,38 +1338,78 @@
@@ -1083,38 +1383,78 @@
}
}
@ -729,7 +770,7 @@
}
public static Optional<ServerPlayer.RespawnPosAngle> findRespawnAndUseSpawnBlock(ServerLevel world, BlockPos pos, float spawnAngle, boolean spawnForced, boolean alive) {
@@ -1129,11 +1424,11 @@
@@ -1129,11 +1469,11 @@
}
return optional.map((vec3d) -> {
@ -743,7 +784,7 @@
});
} else if (!spawnForced) {
return Optional.empty();
@@ -1142,7 +1437,7 @@
@@ -1142,7 +1482,7 @@
BlockState iblockdata1 = world.getBlockState(pos.above());
boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1);
@ -752,7 +793,7 @@
}
}
@@ -1160,6 +1455,7 @@
@@ -1160,6 +1500,7 @@
@Nullable
@Override
public ServerPlayer teleport(TeleportTransition teleportTarget) {
@ -760,7 +801,7 @@
if (this.isRemoved()) {
return null;
} else {
@@ -1169,39 +1465,78 @@
@@ -1169,39 +1510,78 @@
ServerLevel worldserver = teleportTarget.newLevel();
ServerLevel worldserver1 = this.serverLevel();
@ -847,7 +888,7 @@
this.connection.resetPosition();
worldserver.addDuringTeleport(this);
gameprofilerfiller.pop();
@@ -1215,12 +1550,30 @@
@@ -1215,12 +1595,30 @@
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@ -878,7 +919,7 @@
public void forceSetRotation(float yaw, float pitch) {
this.connection.send(new ClientboundPlayerRotationPacket(yaw, pitch));
}
@@ -1228,13 +1581,21 @@
@@ -1228,13 +1626,21 @@
public void triggerDimensionChangeTriggers(ServerLevel origin) {
ResourceKey<Level> resourcekey = origin.dimension();
ResourceKey<Level> resourcekey1 = this.level().dimension();
@ -903,7 +944,7 @@
this.enteredNetherPosition = null;
}
@@ -1251,36 +1612,63 @@
@@ -1251,36 +1657,63 @@
this.containerMenu.broadcastChanges();
}
@ -982,7 +1023,7 @@
this.awardStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
@@ -1293,9 +1681,8 @@
@@ -1293,9 +1726,8 @@
return either;
}
}
@ -993,7 +1034,7 @@
}
@Override
@@ -1322,13 +1709,31 @@
@@ -1322,13 +1754,31 @@
@Override
public void stopSleepInBed(boolean skipSleepTimer, boolean updateSleepingPlayers) {
@ -1026,7 +1067,7 @@
}
}
@@ -1387,8 +1792,9 @@
@@ -1387,8 +1837,9 @@
this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front));
}
@ -1037,7 +1078,7 @@
}
@Override
@@ -1396,13 +1802,35 @@
@@ -1396,13 +1847,35 @@
if (factory == null) {
return OptionalInt.empty();
} else {
@ -1051,11 +1092,11 @@
this.nextContainerCounter();
AbstractContainerMenu container = factory.createMenu(this.containerCounter, this.getInventory(), this);
+
+ // CraftBukkit start - Inventory open hook
+ if (container != null) {
+ container.setTitle(factory.getDisplayName());
+
+ boolean cancelled = false;
+ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled);
+ if (container == null && !cancelled) { // Let pre-cancelled events fall through
@ -1073,7 +1114,7 @@
if (container == null) {
if (this.isSpectator()) {
this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true);
@@ -1410,9 +1838,11 @@
@@ -1410,9 +1883,11 @@
return OptionalInt.empty();
} else {
@ -1087,7 +1128,7 @@
return OptionalInt.of(this.containerCounter);
}
}
@@ -1425,15 +1855,26 @@
@@ -1425,15 +1900,26 @@
@Override
public void openHorseInventory(AbstractHorse horse, Container inventory) {
@ -1117,7 +1158,7 @@
this.initMenu(this.containerMenu);
}
@@ -1456,6 +1897,13 @@
@@ -1456,6 +1942,13 @@
@Override
public void closeContainer() {
@ -1131,7 +1172,7 @@
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
this.doCloseContainer();
}
@@ -1485,19 +1933,19 @@
@@ -1485,19 +1978,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);
@ -1154,7 +1195,7 @@
}
} else if (this.onClimbable()) {
if (deltaY > 0.0D) {
@@ -1508,13 +1956,13 @@
@@ -1508,13 +2001,13 @@
if (i > 0) {
if (this.isSprinting()) {
this.awardStat(Stats.SPRINT_ONE_CM, i);
@ -1171,7 +1212,7 @@
}
}
} else if (this.isFallFlying()) {
@@ -1557,7 +2005,7 @@
@@ -1557,7 +2050,7 @@
@Override
public void awardStat(Stat<?> stat, int amount) {
this.stats.increment(this, stat, amount);
@ -1180,7 +1221,7 @@
scoreaccess.add(amount);
});
}
@@ -1565,7 +2013,7 @@
@@ -1565,7 +2058,7 @@
@Override
public void resetStat(Stat<?> stat) {
this.stats.setValue(this, stat, 0);
@ -1189,7 +1230,7 @@
}
@Override
@@ -1597,9 +2045,9 @@
@@ -1597,9 +2090,9 @@
super.jumpFromGround();
this.awardStat(Stats.JUMP);
if (this.isSprinting()) {
@ -1201,7 +1242,7 @@
}
}
@@ -1613,6 +2061,13 @@
@@ -1613,6 +2106,13 @@
public void disconnect() {
this.disconnected = true;
this.ejectPassengers();
@ -1215,7 +1256,7 @@
if (this.isSleeping()) {
this.stopSleepInBed(true, false);
}
@@ -1625,6 +2080,7 @@
@@ -1625,6 +2125,7 @@
public void resetSentInfo() {
this.lastSentHealth = -1.0E8F;
@ -1223,7 +1264,7 @@
}
@Override
@@ -1661,7 +2117,7 @@
@@ -1661,7 +2162,7 @@
this.onUpdateAbilities();
if (alive) {
this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
@ -1232,7 +1273,7 @@
this.setHealth(oldPlayer.getHealth());
this.foodData = oldPlayer.foodData;
Iterator iterator = oldPlayer.getActiveEffects().iterator();
@@ -1669,7 +2125,7 @@
@@ -1669,7 +2170,7 @@
while (iterator.hasNext()) {
MobEffectInstance mobeffect = (MobEffectInstance) iterator.next();
@ -1241,7 +1282,7 @@
}
this.getInventory().replaceWith(oldPlayer.getInventory());
@@ -1680,7 +2136,7 @@
@@ -1680,7 +2181,7 @@
this.portalProcess = oldPlayer.portalProcess;
} else {
this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
@ -1250,7 +1291,7 @@
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || oldPlayer.isSpectator()) {
this.getInventory().replaceWith(oldPlayer.getInventory());
this.experienceLevel = oldPlayer.experienceLevel;
@@ -1696,7 +2152,7 @@
@@ -1696,7 +2197,7 @@
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@ -1259,7 +1300,7 @@
this.seenCredits = oldPlayer.seenCredits;
this.enteredNetherPosition = oldPlayer.enteredNetherPosition;
this.chunkTrackingView = oldPlayer.chunkTrackingView;
@@ -1752,19 +2208,19 @@
@@ -1752,19 +2253,19 @@
}
@Override
@ -1283,7 +1324,7 @@
}
return flag1;
@@ -1861,8 +2317,13 @@
@@ -1861,8 +2362,13 @@
}
public void sendChatMessage(OutgoingChatMessage message, boolean filterMaskEnabled, ChatType.Bound params) {
@ -1298,7 +1339,7 @@
}
}
@@ -1878,7 +2339,18 @@
@@ -1878,7 +2384,18 @@
}
public void updateOptions(ClientInformation clientOptions) {
@ -1317,7 +1358,7 @@
this.requestedViewDistance = clientOptions.viewDistance();
this.chatVisibility = clientOptions.chatVisibility();
this.canChatColor = clientOptions.chatColors();
@@ -1957,12 +2429,27 @@
@@ -1957,12 +2474,27 @@
this.camera = (Entity) (entity == null ? this : entity);
if (entity1 != this.camera) {
@ -1346,7 +1387,7 @@
}
if (entity != null) {
@@ -1999,11 +2486,11 @@
@@ -1999,11 +2531,11 @@
@Nullable
public Component getTabListDisplayName() {
@ -1360,7 +1401,7 @@
}
@Override
@@ -2046,17 +2533,43 @@
@@ -2046,17 +2578,43 @@
}
public void setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) {
@ -1411,7 +1452,7 @@
} else {
this.respawnPosition = null;
this.respawnDimension = Level.OVERWORLD;
@@ -2088,18 +2601,44 @@
@@ -2088,18 +2646,44 @@
}
@Override
@ -1460,7 +1501,7 @@
}
this.awardStat(Stats.DROP);
@@ -2275,9 +2814,15 @@
@@ -2275,9 +2859,15 @@
@Override
public void stopRiding() {
@ -1477,7 +1518,7 @@
if (entity instanceof LivingEntity entityliving) {
Iterator iterator = entityliving.getActiveEffects().iterator();
@@ -2375,16 +2920,161 @@
@@ -2375,10 +2965,12 @@
return TicketType.ENDER_PEARL.timeout();
}
@ -1493,11 +1534,10 @@
}
private static float calculateLookAtYaw(Vec3 respawnPos, BlockPos currentPos) {
Vec3 vec3d1 = Vec3.atBottomCenterOf(currentPos).subtract(respawnPos).normalize();
@@ -2387,4 +2979,147 @@
return (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D);
+ }
+ }
}
}
+
+ // CraftBukkit start - Add per-player time and weather.
+ public long timeOffset = 0;
@ -1510,8 +1550,8 @@
+ } else {
+ // Adds timeOffset to the beginning of this day.
+ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset;
}
}
+ }
+ }
+
+ public WeatherType weather = null;
+