From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Tue, 21 Sep 2021 23:54:25 +0100 Subject: [PATCH] Visibility API and Command diff --git a/src/main/java/me/samsuik/sakura/command/SakuraCommands.java b/src/main/java/me/samsuik/sakura/command/SakuraCommands.java index c2651cac1dcf85fb67fe981b97efee4e56431de2..d7d0c49cc5d576c594dee16ddba037cd147e11fa 100644 --- a/src/main/java/me/samsuik/sakura/command/SakuraCommands.java +++ b/src/main/java/me/samsuik/sakura/command/SakuraCommands.java @@ -2,6 +2,9 @@ package me.samsuik.sakura.command; import io.papermc.paper.command.PaperPluginsCommand; import me.samsuik.sakura.command.subcommands.ConfigCommand; +import me.samsuik.sakura.command.subcommands.FPSCommand; +import me.samsuik.sakura.command.subcommands.VisualCommand; +import me.samsuik.sakura.player.visibility.Visibility; import net.minecraft.server.MinecraftServer; import org.bukkit.command.Command; @@ -14,6 +17,10 @@ public class SakuraCommands { static { COMMANDS.put("sakura", new SakuraCommand("sakura")); COMMANDS.put("config", new ConfigCommand("config")); + COMMANDS.put("fps", new FPSCommand("fps")); + COMMANDS.put("tntvisibility", new VisualCommand(Visibility.Setting.TNT_VISIBILITY, "tnttoggle")); + COMMANDS.put("sandvisibility", new VisualCommand(Visibility.Setting.SAND_VISIBILITY, "sandtoggle")); + COMMANDS.put("minimal", new VisualCommand(Visibility.Setting.MINIMAL, "minimaltnt", "tntlag")); } public static void registerCommands(final MinecraftServer server) { diff --git a/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java b/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..1dc2a98123d671c945e85b97a898f56e527a81f5 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java @@ -0,0 +1,26 @@ +package me.samsuik.sakura.command.subcommands; + +import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.player.visibility.VisibilityGUI; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public class FPSCommand extends BaseSubCommand { + + private final VisibilityGUI VISIBILITY_GUI = new VisibilityGUI(); + + public FPSCommand(String name) { + super(name); + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (sender instanceof Player player) { + VISIBILITY_GUI.showTo(player); + } + } + +} diff --git a/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java b/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..6027e4741e2de7c6d3bd7b094c196a212e34e2f5 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java @@ -0,0 +1,45 @@ +package me.samsuik.sakura.command.subcommands; + +import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.configuration.GlobalConfiguration; +import me.samsuik.sakura.player.visibility.Visibility; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +import java.util.Arrays; + +@DefaultQualifier(NonNull.class) +public class VisualCommand extends BaseSubCommand { + + private final Visibility.Setting type; + + public VisualCommand(Visibility.Setting type, String... aliases) { + super(type.basicName()); + this.setAliases(Arrays.asList(aliases)); + this.type = type; + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + return; + } + + var visibility = player.getVisibility(); + + // Toggle clicked setting visibility + visibility.toggle(type); + + // Send message to player + var state = visibility.isEnabled(type) ? "Enabled" : "Disabled"; + player.sendMessage(MiniMessage.miniMessage().deserialize(GlobalConfiguration.get().fps.message, + Placeholder.unparsed("name", type.friendlyName()), + Placeholder.unparsed("state", state)) + ); + } + +} diff --git a/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java b/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java new file mode 100644 index 0000000000000000000000000000000000000000..d5bd47426a219a3825deaa0b62386c88d17b4aac --- /dev/null +++ b/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java @@ -0,0 +1,119 @@ +package me.samsuik.sakura.player.visibility; + +import me.samsuik.sakura.configuration.GlobalConfiguration; +import me.samsuik.sakura.player.gui.ItemIcon; +import me.samsuik.sakura.player.gui.PlayerGUI; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.function.BiFunction; + +public class VisibilityGUI extends PlayerGUI { + + private static final BiFunction CREATE_INVENTORY = (player, holder) -> { + Inventory inventory = Bukkit.createInventory(holder, 45, Component.text("FPS GUI")); + + for (int i = 0; i < inventory.getSize(); ++i) { + int column = i % 9; + int row = (i + 1) / 9; + + Material background = column > 0 && column < 8 ? (row > 0 && row < 4 || column > 1 && column < 7) + ? Material.matchMaterial(GlobalConfiguration.get().fps.material) + : Material.WHITE_STAINED_GLASS_PANE + : Material.BLACK_STAINED_GLASS_PANE; + + ItemStack itemstack = new ItemStack(background); + ItemMeta meta = itemstack.getItemMeta(); + meta.displayName(Component.space()); + itemstack.setItemMeta(meta); + + inventory.setItem(i, itemstack); + } + + return inventory; + }; + + public VisibilityGUI() { + super(CREATE_INVENTORY); + } + + @Override + protected void register() { + registerFPSIcon(Visibility.Setting.TNT_VISIBILITY, Material.TNT, NamedTextColor.RED, 12); + registerFPSIcon(Visibility.Setting.SAND_VISIBILITY, Material.SAND, NamedTextColor.YELLOW, 14); + registerFPSIcon(Visibility.Setting.MINIMAL, Material.NETHER_BRICK_SLAB, NamedTextColor.GOLD, 13); + registerFPSIcon(Visibility.Setting.SPAWNERS, Material.SPAWNER, NamedTextColor.DARK_GRAY, 20); + registerFPSIcon(Visibility.Setting.FLASHING_TNT, Material.REDSTONE_LAMP, NamedTextColor.RED, 22); + registerFPSIcon(Visibility.Setting.EXPLOSIONS, Material.COBWEB, NamedTextColor.WHITE, 24); + registerFPSIcon(Visibility.Setting.PISTONS, Material.PISTON, NamedTextColor.GOLD, 30); + registerFPSIcon(Visibility.Setting.REDSTONE, Material.REDSTONE, NamedTextColor.DARK_RED, 31); + registerFPSIcon(Visibility.Setting.ENCHANTMENT_GLINT, Material.ENCHANTED_BOOK, NamedTextColor.DARK_PURPLE, 32); + + registerIcon(new ItemIcon( + (player) -> { + ItemStack itemstack = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); + Component title = Component.text("Toggle all", NamedTextColor.GREEN); + + itemstack.editMeta(meta -> meta.displayName(title.decoration(TextDecoration.ITALIC, false))); + return itemstack; + }, + (player) -> { + player.getVisibility().toggleAll(); + + // refresh icons after toggling + this.refresh(player); + }, + 26 + )); + } + + private void registerFPSIcon(Visibility.Setting setting, Material material, TextColor colour, int slot) { + registerIcon(new ItemIcon((player) -> { + Visibility visibility = player.getVisibility(); + ItemStack itemstack = new ItemStack(material); + + itemstack.editMeta(meta -> { + // Get the current state as a string + String state = visibility.isEnabled(setting) ? "Enabled" : "Disabled"; + + // Friendly name as a component + Component title = Component.text(setting.friendlyName(), colour); + + // Display names are italic by default + title = title.decoration(TextDecoration.ITALIC, false); + + // Set the display name + meta.displayName(title.append(Component.space()) + .append(Component.text(state, NamedTextColor.GRAY))); + }); + + return itemstack; + }, (player) -> { + Visibility visibility = player.getVisibility(); + + // Toggle clicked setting visibility + visibility.toggle(setting); + + // Get the current state as a string + String state = visibility.isEnabled(setting) ? "Enabled" : "Disabled"; + + // Send message to player + player.sendRichMessage(GlobalConfiguration.get().fps.message, + Placeholder.unparsed("name", setting.friendlyName()), + Placeholder.unparsed("state", state) + ); + }, + slot + )); + } + +} diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java index e3f355c85eb7cc8c1683e3009502c10a5ed32daa..349e56d5caad3fc38e83eac6ffff83e2fb30eaa7 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java @@ -16,7 +16,7 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet public public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section) { this.sectionPos = sectionPos; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index b5e2ae560431cd3ecfc780deb25488016c0ad0e7..73dc4f245039805b635f9e89438104e3b7a93e7b 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1745,6 +1745,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop createEntityPacket(Entity entity, ServerPlayer entityplayer) { + if (entity.isPrimedTNT && entityplayer.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) { + return new ClientboundAddEntityPacket(entity.getId(), entity.getUUID(), + entity.getX(), entity.getY(), entity.getZ(), 0, 0, EntityType.FALLING_BLOCK, + Block.getId(Blocks.TNT.defaultBlockState()), entity.getDeltaMovement(), entity.getYHeadRot()); + } else { + return entity.getAddEntityPacket(); + } + } + // Sakura end + public void sendPairingData(ServerPlayer player, Consumer> sender) { if (this.entity.isRemoved()) { // CraftBukkit start - Remove useless error spam, just return @@ -292,12 +311,19 @@ public class ServerEntity { // CraftBukkit end } - Packet packet = this.entity.getAddEntityPacket(); + Packet packet = this.createEntityPacket(this.entity, player); // Sakura - visibility api this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F); sender.accept(packet); if (this.trackedDataValues != null) { - sender.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.trackedDataValues)); + // Sakura start - visibility api + if (this.entity.isPrimedTNT && player.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) { + // Could modifying this break something elsewhere? + trackedDataValues.removeIf((data) -> data.id() == 8); + } + + sender.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), trackedDataValues)); + // Sakura end } boolean flag = this.trackDelta; @@ -367,6 +393,32 @@ public class ServerEntity { } } + + // Sakura start - visibility api + private void broadcastEntityData(List> packedValues) { + Packet packet0 = new ClientboundSetEntityDataPacket(this.entity.getId(), packedValues); + Packet packet1 = null; + + if (this.entity.isPrimedTNT) { + var copyOfDirtyItems = Lists.newArrayList(packedValues); + copyOfDirtyItems.removeIf((data) -> data.id() == 8); + + if (!copyOfDirtyItems.isEmpty()) { + packet1 = new ClientboundSetEntityDataPacket(this.entity.getId(), copyOfDirtyItems); + } + } + + for (var connection : trackedPlayers) { + var player = connection.getPlayer(); + + if (!this.entity.isPrimedTNT || !player.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) { + connection.send(packet0); + } else if (packet1 != null) { + connection.send(packet1); + } + } + } + // Sakura end private void sendDirtyEntityData() { SynchedEntityData datawatcher = this.entity.getEntityData(); @@ -374,7 +426,7 @@ public class ServerEntity { if (list != null) { this.trackedDataValues = datawatcher.getNonDefaultValues(); - this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); + this.broadcastEntityData(list); // Sakura - visibility api } if (this.entity instanceof LivingEntity) { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 1f36015d2e9c433cfe2de079b8eba144f0dad4cf..c33c9cb3a0e574e5284e48ffaf8d0945061ea388 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1956,7 +1956,7 @@ public class ServerLevel extends Level implements WorldGenLevel { while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - if (entityplayer.distanceToSqr(x, y, z) < 4096.0D) { + if (entityplayer.distanceToSqr(x, y, z) < 4096.0D && !entityplayer.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.EXPLOSIONS)) { // Sakura - visibility api entityplayer.connection.send(new ClientboundExplodePacket(x, y, z, power, explosion.getToBlow(), (Vec3) explosion.getHitPlayers().get(entityplayer), explosion.getBlockInteraction(), explosion.getSmallExplosionParticles(), explosion.getLargeExplosionParticles(), explosion.getExplosionSound())); } } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index d1f20a8a3ccea1f074624163eb96da023142a459..29422f36aa5727ae9e8f6728964fda9889986e02 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -261,6 +261,7 @@ public class ServerPlayer extends Player { public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper // Paper end - mob spawning rework public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff + public final me.samsuik.sakura.player.visibility.Visibility visibility = new me.samsuik.sakura.player.visibility.Visibility(); // Sakura - visiblity api // CraftBukkit start public String displayName; @@ -567,6 +568,15 @@ public class ServerPlayer extends Player { this.respawnDimension = (ResourceKey) dataresult1.resultOrPartial(logger1::error).orElse(Level.OVERWORLD); } } + // Sakura start - visibility api + CompoundTag tag = nbt.getCompound("Sakura.Visuals"); + + for (me.samsuik.sakura.player.visibility.Visibility.Setting setting : me.samsuik.sakura.player.visibility.Visibility.Setting.values()) { + if (tag.getBoolean(setting.name())) { + visibility.toggle(setting); + } + } + // Sakura end } @@ -633,6 +643,13 @@ public class ServerPlayer extends Player { }); } this.getBukkitEntity().setExtraData(nbt); // CraftBukkit + // Sakura start - visibility api + CompoundTag tag = new CompoundTag(); + for (me.samsuik.sakura.player.visibility.Visibility.Setting setting : me.samsuik.sakura.player.visibility.Visibility.Setting.values()) { + tag.putBoolean(setting.name(), visibility.isToggled(setting)); + } + nbt.put("Sakura.Visuals", tag); + // Sakura end } diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java index 4a712f5fc4f0b4a4434ae808c989113bee8d8634..c59db7ea7d4dafc6df030c2c4d5f51395fe1c363 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -40,6 +40,23 @@ import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerResourcePackStatusEvent; // CraftBukkit end +// Sakura start +import com.mojang.datafixers.util.Pair; +import me.samsuik.sakura.player.visibility.Visibility.Setting; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.network.protocol.game.ClientboundBlockEventPacket; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData; +import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData.BlockEntityTagOutput; +import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.world.level.block.DiodeBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.RedStoneWireBlock; +import net.minecraft.world.level.block.piston.PistonBaseBlock; +import net.minecraft.world.level.block.piston.PistonHeadBlock; +// Sakura end public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { @@ -234,6 +251,61 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) { ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); + // Sakura start - visibility api + } else if (!player.visibility.isModified()) { + // Skip players that haven't modified their settings + } else if (packet instanceof ClientboundSetEquipmentPacket equipment + && player.visibility.isToggled(Setting.ENCHANTMENT_GLINT)) { + var slots = new java.util.ArrayList>(); + + for (int i = 0; i < equipment.getSlots().size(); i++) { + var pair = equipment.getSlots().get(i); + var itemstack = pair.getSecond(); + + if (itemstack.isEnchanted()) { + var copy = itemstack.copy(); + copy.getTag().remove("ench"); + itemstack = copy; + } + + slots.add(new Pair<>(pair.getFirst(), itemstack)); + } + + packet = new ClientboundSetEquipmentPacket(equipment.getEntity(), slots); + } else if (packet instanceof ClientboundBlockEntityDataPacket blockdata + && player.visibility.isToggled(Setting.SPAWNERS) + && player.level().getBlockIfLoaded(blockdata.getPos()) == Blocks.SPAWNER) { + packet = new ClientboundBlockUpdatePacket(blockdata.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState()); + } else if (packet instanceof ClientboundBlockUpdatePacket updatePacket) { + if (player.visibility.isToggled(Setting.SPAWNERS) && updatePacket.blockState.getBlock() == Blocks.SPAWNER) { + packet = new ClientboundBlockUpdatePacket(updatePacket.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState()); + } else if (player.visibility.isToggled(Setting.REDSTONE) + && (updatePacket.blockState.getBlock() instanceof DiodeBlock + || updatePacket.blockState.getBlock() instanceof RedStoneWireBlock)) { + return; + } else if (player.visibility.isToggled(Setting.PISTONS) + && (updatePacket.blockState.getBlock() instanceof PistonBaseBlock + || updatePacket.blockState.getBlock() instanceof PistonHeadBlock)) { + return; + } + } else if (packet instanceof ClientboundSectionBlocksUpdatePacket sectionPacket) { + for (var state : sectionPacket.states) { + if (player.visibility.isToggled(Setting.REDSTONE) + && (state.getBlock() instanceof DiodeBlock + || state.getBlock() instanceof RedStoneWireBlock)) { + return; + } else if (player.visibility.isToggled(Setting.PISTONS) + && (state.getBlock() instanceof PistonBaseBlock + || state.getBlock() instanceof PistonHeadBlock)) { + return; + } + } + } else if (packet instanceof ClientboundBlockEventPacket blockevent + && player.visibility.isToggled(Setting.PISTONS) + && (blockevent.getBlock() instanceof PistonBaseBlock + || blockevent.getBlock() instanceof PistonHeadBlock)) { + return; + // Sakura end } // CraftBukkit end boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); @@ -244,8 +316,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack CrashReport crashreport = CrashReport.forThrowable(throwable, "Sending packet"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Packet being sent"); + // Sakura start - this has to be effectively final as we're modifying the packet above + var packetFinal = packet; crashreportsystemdetails.setDetail("Packet class", () -> { - return packet.getClass().getCanonicalName(); + return packetFinal.getClass().getCanonicalName(); + // Sakura end }); throw new ReportedException(crashreport); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 30ccbab1586a656e0ae41d7406525fb02d9e025b..187ba90c50256aaa0514f4b2bd79bf30bc04b0af 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -3107,6 +3107,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl event.setCancelled(cancelled); AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 + me.samsuik.sakura.player.gui.PlayerGUI.onWindowClick(event); // Sakura - visibility gui this.cserver.getPluginManager().callEvent(event); if (this.player.containerMenu != oldContainer) { return; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 0c46a4aeafd03fbbfd590b0362d41bf2b1d5ca74..b2d2b6d588572682730a228888b6dcdae2dc5020 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -535,6 +535,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.teleportTo(worldserver, null); } // Paper end - make end portalling safe + public boolean isPrimedTNT; // Sakura + public boolean isFallingBlock; // Sakura public boolean isLegacyTrackingEntity = false; diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java index 45c07733f03b5c11f6d8e820f65dc950c70d9a67..3ec931c9aa9e2857e0c24eeb47c1048ace05f6fe 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java @@ -73,6 +73,7 @@ public class FallingBlockEntity extends Entity { this.blockState = Blocks.SAND.defaultBlockState(); this.dropItem = true; this.fallDamageMax = 40; + this.isFallingBlock = true; // Sakura } public FallingBlockEntity(Level world, double x, double y, double z, BlockState block) { diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java index c3e47426382296d650fa00ce0bc1a82bf23c7877..62a3cd512d473d5ed673386d5c15091a09426945 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java @@ -38,6 +38,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { public PrimedTnt(EntityType type, Level world) { super(type, world); this.blocksBuilding = true; + this.isPrimedTNT = true; // Sakura } public PrimedTnt(Level world, double x, double y, double z, @Nullable LivingEntity igniter) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 512088b5457e5afbc29d2937051fc4dcc4c5aed6..8fd4d63fdbff9c454d903f4797ec9281df7266fc 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -226,6 +226,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract ResourceKey getTypeKey(); + public final it.unimi.dsi.fastutil.longs.Long2IntMap minimalTNT = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); // Sakura - visibility api + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, Supplier sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura // Paper - Async-Anti-Xray - Pass executor this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 3be5e4df190bff0087c8450b16e4e37b07169040..201a5c5652232cfc64c476d066225df6bb1690d3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -494,6 +494,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().displayName = name == null ? this.getName() : name; } + // Sakura start - visiblity api + @Override + public me.samsuik.sakura.player.visibility.Visibility getVisibility() { + return getHandle().visibility; + } + // Sakura end + // Paper start @Override public void playerListName(net.kyori.adventure.text.Component name) {