Apply some feature patches to files instead

They're small and/or really shouldn't be left unapplied
This commit is contained in:
Nassim Jahnke 2024-12-21 13:21:47 +01:00
parent e0593e9286
commit 82216a59fe
No known key found for this signature in database
GPG key ID: EF6771C01F6EF02F
16 changed files with 424 additions and 578 deletions

View file

@ -1,98 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 3 Mar 2016 02:07:55 -0600
Subject: [PATCH] Optimize isInWorldBounds and getBlockState for inlining
Hot methods, so reduce # of instructions for the method.
Move is valid location test to the BlockPosition class so that it can access local variables.
Replace all calls to the new place to the unnecessary forward.
Optimize getType and getBlockData to manually inline and optimize the calls
diff --git a/net/minecraft/core/Vec3i.java b/net/minecraft/core/Vec3i.java
index 03e2178430849d26c9826517e34ad069c94fc00a..11555ce7159ca6c8ddfe9691f86d3720c07cb086 100644
--- a/net/minecraft/core/Vec3i.java
+++ b/net/minecraft/core/Vec3i.java
@@ -28,6 +28,12 @@ public class Vec3i implements Comparable<Vec3i> {
);
}
+ // Paper start
+ public final boolean isInsideBuildHeightAndWorldBoundsHorizontal(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY());
+ }
+ // Paper end
+
public Vec3i(int x, int y, int z) {
this.x = x;
this.y = y;
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index e0239091729f6be138c037951fd5c138497ee358..691fee2e2097244126f4fac0f5d00bf6916b9766 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -350,7 +350,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper end
public boolean isInWorldBounds(BlockPos pos) {
- return !this.isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos);
+ return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - use better/optimized check
}
public static boolean isInSpawnableBounds(BlockPos pos) {
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index f68f3f5e8ef39a0dc371e75110227a39791c04c8..12d9b532e466ec4e46920d409b5f1b3ae60b80f8 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -130,6 +130,7 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
return GameEventListenerRegistry.NOOP;
}
+ public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
@Nullable
public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving);
diff --git a/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/net/minecraft/world/level/chunk/ImposterProtoChunk.java
index 6c43e5e685871289968db8171342fd84189edcba..e7c0f4da8508fbca467326f475668d66454d7b77 100644
--- a/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -56,6 +56,12 @@ public class ImposterProtoChunk extends ProtoChunk {
public BlockState getBlockState(BlockPos pos) {
return this.wrapped.getBlockState(pos);
}
+ // Paper start
+ @Override
+ public final BlockState getBlockState(final int x, final int y, final int z) {
+ return this.wrapped.getBlockStateFinal(x, y, z);
+ }
+ // Paper end
@Override
public FluidState getFluidState(BlockPos pos) {
diff --git a/net/minecraft/world/level/chunk/ProtoChunk.java b/net/minecraft/world/level/chunk/ProtoChunk.java
index e359b5f694210f05e5675a995dbfc1a95cec76db..8c333d7f390d823a7c7f303e2f444f52ec16f799 100644
--- a/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -99,12 +99,18 @@ public class ProtoChunk extends ChunkAccess {
@Override
public BlockState getBlockState(BlockPos pos) {
- int y = pos.getY();
+ // Paper start
+ return getBlockState(pos.getX(), pos.getY(), pos.getZ());
+ }
+ public BlockState getBlockState(final int x, final int y, final int z) {
+ // Paper end
if (this.isOutsideBuildHeight(y)) {
return Blocks.VOID_AIR.defaultBlockState();
} else {
- LevelChunkSection section = this.getSection(this.getSectionIndex(y));
- return section.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : section.getBlockState(pos.getX() & 15, y & 15, pos.getZ() & 15);
+ // Paper start
+ LevelChunkSection section = this.getSections()[this.getSectionIndex(y)];
+ return section.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : section.getBlockState(x & 15, y & 15, z & 15);
+ // Paper end
}
}

View file

@ -1,135 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Fri, 29 Apr 2016 20:02:00 -0400
Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes
Maps used a modified version of rendering to support plugin controlled
imaging on maps. The Craft Map Renderer is much slower than Vanilla,
causing maps in item frames to cause a noticeable hit on server performance.
This updates the map system to not use the Craft system if we detect that no
custom renderers are in use, defaulting to the much simpler Vanilla system.
Additionally, numerous issues to player position tracking on maps has been fixed.
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 1f66adcd70aae7eac3d9f9539163905695581631..34a53bf34d10c56e6f53ce9aab2fc2780509f2f1 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2282,7 +2282,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
map.carriedByPlayers.remove(player);
- map.carriedBy.removeIf(holdingPlayer -> holdingPlayer.player == player);
+ if (map.carriedBy.removeIf(holdingPlayer -> holdingPlayer.player == player)) {
+ map.decorations.remove(player.getName().getString()); // Paper
+ }
}
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 36e0d3f225a71b75ece7bf3fceeba47af948a6df..ff5889f8fed0707a6654d9d21862e32e2ebc866d 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2594,6 +2594,14 @@ public class ServerPlayer extends Player {
this.awardStat(Stats.DROP);
}
+ // Paper start - remove player from map on drop
+ if (item.getItem() == net.minecraft.world.item.Items.FILLED_MAP) {
+ final MapItemSavedData mapData = MapItem.getSavedData(item, this.level());
+ if (mapData != null) {
+ mapData.tickCarriedBy(this, item);
+ }
+ }
+ // Paper end - remove player from map on drop
return itemEntity;
}
}
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index fd50bd77e4dc7b18240afe5505c6e6f0f869c127..f60c2f3a3dfc69f50225b6ee7333ada5e9dfd090 100644
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -67,6 +67,7 @@ public class MapItemSavedData extends SavedData {
public final Map<String, MapDecoration> decorations = Maps.newLinkedHashMap();
private final Map<String, MapFrame> frameMarkers = Maps.newHashMap();
private int trackedDecorationCount;
+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper
// CraftBukkit start
public final org.bukkit.craftbukkit.map.CraftMapView mapView;
@@ -92,6 +93,7 @@ public class MapItemSavedData extends SavedData {
// CraftBukkit start
this.mapView = new org.bukkit.craftbukkit.map.CraftMapView(this);
this.server = (org.bukkit.craftbukkit.CraftServer) org.bukkit.Bukkit.getServer();
+ this.vanillaRender.buffer = colors; // Paper
// CraftBukkit end
}
@@ -163,6 +165,7 @@ public class MapItemSavedData extends SavedData {
if (byteArray.length == 16384) {
mapItemSavedData.colors = byteArray;
}
+ mapItemSavedData.vanillaRender.buffer = byteArray; // Paper
RegistryOps<Tag> registryOps = levelRegistry.createSerializationContext(NbtOps.INSTANCE);
@@ -337,7 +340,7 @@ public class MapItemSavedData extends SavedData {
this.trackedDecorationCount--;
}
- this.setDecorationsDirty();
+ if (mapDecoration != null) this.setDecorationsDirty(); // Paper - only mark dirty if a change occurs
}
public static void addTargetDecoration(ItemStack stack, BlockPos pos, String type, Holder<MapDecorationType> mapDecorationType) {
@@ -610,7 +613,16 @@ public class MapItemSavedData extends SavedData {
@Nullable
Packet<?> nextUpdatePacket(MapId mapId) {
MapItemSavedData.MapPatch mapPatch;
- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit
+ // Paper start
+ if (!this.dirtyData && this.tick % 5 != 0) {
+ // this won't end up sending, so don't render it!
+ this.tick++;
+ return null;
+ }
+
+ final boolean vanillaMaps = this.shouldUseVanillaMap();
+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper
+ // Paper end
if (this.dirtyData) {
this.dirtyData = false;
mapPatch = this.createPatch(render.buffer); // CraftBukkit
@@ -623,6 +635,7 @@ public class MapItemSavedData extends SavedData {
this.dirtyDecorations = false;
// CraftBukkit start
java.util.Collection<MapDecoration> icons = new java.util.ArrayList<MapDecoration>();
+ if (vanillaMaps) this.addSeenPlayers(icons); // Paper
for (org.bukkit.map.MapCursor cursor : render.cursors) {
if (cursor.isVisible()) {
@@ -658,6 +671,23 @@ public class MapItemSavedData extends SavedData {
private void markDecorationsDirty() {
this.dirtyDecorations = true;
}
+
+ // Paper start
+ private void addSeenPlayers(java.util.Collection<MapDecoration> icons) {
+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.player.getBukkitEntity();
+ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> {
+ // If this cursor is for a player check visibility with vanish system
+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot
+ if (other == null || player.canSee(other)) {
+ icons.add(mapIcon);
+ }
+ });
+ }
+
+ private boolean shouldUseVanillaMap() {
+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().getFirst().getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class;
+ }
+ // Paper end
}
record MapDecorationLocation(Holder<MapDecorationType> type, byte x, byte y, byte rot) {

View file

@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 2 Aug 2021 10:10:40 +0200
Subject: [PATCH] Check distance in entity interactions
diff --git a/net/minecraft/Util.java b/net/minecraft/Util.java
index ae1d53cefb9cede1c93cb8b22122a4a2d2d9a40c..80a7a85e1a03a1ca406259207e1ae3b909b3284f 100644
--- a/net/minecraft/Util.java
+++ b/net/minecraft/Util.java
@@ -130,6 +130,7 @@ public class Util {
.findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
private static Consumer<String> thePauser = string -> {};
+ public static final double COLLISION_EPSILON = 1.0E-7; // Paper - Check distance in entity interactions
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Entry::getKey, Entry::getValue);
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 9bf5addb07f40cc50e80a46c0ee7944e938620fb..635e6e49483194c43b0ab47b5e1bacfe84613c3a 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1385,7 +1385,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.hurtCurrentlyUsedShield(amount);
f1 = amount;
amount = 0.0F;
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity) {
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity && livingEntity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Check distance in entity interactions
this.blockUsingShield(livingEntity);
}
@@ -1470,6 +1470,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
d = damageSource.getSourcePosition().x() - this.getX();
d1 = damageSource.getSourcePosition().z() - this.getZ();
}
+ // Paper start - Check distance in entity interactions; see for loop in knockback method
+ if (Math.abs(d) > 200) {
+ d = Math.random() - Math.random();
+ }
+ if (Math.abs(d1) > 200) {
+ d1 = Math.random() - Math.random();
+ }
+ // Paper end - Check distance in entity interactions
this.knockback(0.4F, d, d1, damageSource.getDirectEntity(), damageSource.getDirectEntity() == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
if (!flag) {
@@ -2342,7 +2350,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING));
Entity entity = damageSource.getDirectEntity();
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity) { // Paper - Fix shield disable inconsistency
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Fix shield disable inconsistency & Check distance in entity interactions
this.blockUsingShield((LivingEntity) entity);
}
}
diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java
index 3bdb3b0984d0fee21b2c094e1d4c1f917ab68f92..54a4bf2f7df87b4a694187ade81ba158f83f0246 100644
--- a/net/minecraft/world/entity/vehicle/AbstractBoat.java
+++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java
@@ -638,7 +638,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
this.waterLevel = this.getY(1.0);
double d2 = this.getWaterLevelAbove() - this.getBbHeight() + 0.101;
if (this.level().noCollision(this, this.getBoundingBox().move(0.0, d2 - this.getY(), 0.0))) {
- this.setPos(this.getX(), d2, this.getZ());
+ this.move(MoverType.SELF, new Vec3(0.0D, d2 - this.getY(), 0.0D)); // Paper - Check distance in entity interactions // TODO Still needed??
this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0));
this.lastYd = 0.0;
}

View file

@ -0,0 +1,244 @@
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -1,0 +_,241 @@
+package ca.spottedleaf.moonrise.paper;
+
+import ca.spottedleaf.moonrise.common.PlatformHooks;
+import ca.spottedleaf.moonrise.paper.util.BaseChunkSystemHooks;
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.DataFixer;
+import com.mojang.serialization.Dynamic;
+import java.util.Collection;
+import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtOps;
+import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.GenerationChunkHolder;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.boss.EnderDragonPart;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.chunk.ProtoChunk;
+import net.minecraft.world.level.chunk.storage.SerializableChunkData;
+import net.minecraft.world.level.entity.EntityTypeTest;
+import net.minecraft.world.phys.AABB;
+import java.util.List;
+import java.util.function.Predicate;
+
+public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
+
+ @Override
+ public String getBrand() {
+ return "Paper";
+ }
+
+ @Override
+ public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) {
+ return blockState.getLightEmission();
+ }
+
+ @Override
+ public Predicate<BlockState> maybeHasLightEmission() {
+ return (final BlockState state) -> {
+ return state.getLightEmission() != 0;
+ };
+ }
+
+ @Override
+ public boolean hasCurrentlyLoadingChunk() {
+ return false;
+ }
+
+ @Override
+ public LevelChunk getCurrentlyLoadingChunk(final GenerationChunkHolder holder) {
+ return null;
+ }
+
+ @Override
+ public void setCurrentlyLoading(final GenerationChunkHolder holder, final LevelChunk levelChunk) {
+
+ }
+
+ @Override
+ public void chunkFullStatusComplete(final LevelChunk newChunk, final ProtoChunk original) {
+
+ }
+
+ @Override
+ public boolean allowAsyncTicketUpdates() {
+ return true;
+ }
+
+ @Override
+ public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel) {
+
+ }
+
+ @Override
+ public void chunkUnloadFromWorld(final LevelChunk chunk) {
+
+ }
+
+ @Override
+ public void chunkSyncSave(final ServerLevel world, final ChunkAccess chunk, final SerializableChunkData data) {
+
+ }
+
+ @Override
+ public void onChunkWatch(final ServerLevel world, final LevelChunk chunk, final ServerPlayer player) {
+
+ }
+
+ @Override
+ public void onChunkUnWatch(final ServerLevel world, final ChunkPos chunk, final ServerPlayer player) {
+
+ }
+
+ @Override
+ public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate, final List<Entity> into) {
+ final Collection<EnderDragonPart> parts = world.dragonParts();
+ if (parts.isEmpty()) {
+ return;
+ }
+
+ for (final EnderDragonPart part : parts) {
+ if (part != entity && part.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(part))) {
+ into.add(part);
+ }
+ }
+ }
+
+ @Override
+ public <T extends Entity> void addToGetEntities(final Level world, final EntityTypeTest<Entity, T> entityTypeTest, final AABB boundingBox, final Predicate<? super T> predicate, final List<? super T> into, final int maxCount) {
+ if (into.size() >= maxCount) {
+ // fix neoforge issue: do not add if list is already full
+ return;
+ }
+
+ final Collection<EnderDragonPart> parts = world.dragonParts();
+ if (parts.isEmpty()) {
+ return;
+ }
+ for (final EnderDragonPart part : parts) {
+ if (!part.getBoundingBox().intersects(boundingBox)) {
+ continue;
+ }
+ final T casted = (T)entityTypeTest.tryCast(part);
+ if (casted != null && (predicate == null || predicate.test(casted))) {
+ into.add(casted);
+ if (into.size() >= maxCount) {
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void entityMove(final Entity entity, final long oldSection, final long newSection) {
+
+ }
+
+ @Override
+ public boolean screenEntity(final ServerLevel world, final Entity entity, final boolean fromDisk, final boolean event) {
+ return true;
+ }
+
+ @Override
+ public boolean configFixMC224294() {
+ return true;
+ }
+
+ @Override
+ public boolean configAutoConfigSendDistance() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.autoConfigSendDistance;
+ }
+
+ @Override
+ public double configPlayerMaxLoadRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkLoadRate;
+ }
+
+ @Override
+ public double configPlayerMaxGenRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkGenerateRate;
+ }
+
+ @Override
+ public double configPlayerMaxSendRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkSendRate;
+ }
+
+ @Override
+ public int configPlayerMaxConcurrentLoads() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.playerMaxConcurrentChunkLoads;
+ }
+
+ @Override
+ public int configPlayerMaxConcurrentGens() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.playerMaxConcurrentChunkGenerates;
+ }
+
+ @Override
+ public long configAutoSaveInterval(final ServerLevel world) {
+ return world.paperConfig().chunks.autoSaveInterval.value();
+ }
+
+ @Override
+ public int configMaxAutoSavePerTick(final ServerLevel world) {
+ return world.paperConfig().chunks.maxAutoSaveChunksPerTick;
+ }
+
+ @Override
+ public boolean configFixMC159283() {
+ return true;
+ }
+
+ @Override
+ public boolean forceNoSave(final ChunkAccess chunk) {
+ return chunk instanceof LevelChunk levelChunk && levelChunk.mustNotSave;
+ }
+
+ @Override
+ public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
+ final int fromVersion, final int toVersion) {
+ return (CompoundTag)dataFixer.update(
+ type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
+ ).getValue();
+ }
+
+ @Override
+ public boolean hasMainChunkLoadHook() {
+ return false;
+ }
+
+ @Override
+ public void mainChunkLoad(final ChunkAccess chunk, final SerializableChunkData chunkData) {
+
+ }
+
+ @Override
+ public List<Entity> modifySavedEntities(final ServerLevel world, final int chunkX, final int chunkZ, final List<Entity> entities) {
+ return entities;
+ }
+
+ @Override
+ public void unloadEntity(final Entity entity) {
+ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, org.bukkit.event.entity.EntityRemoveEvent.Cause.UNLOAD);
+ }
+
+ @Override
+ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
+ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
+ }
+
+ @Override
+ public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
+ return org.spigotmc.TrackingRange.getEntityTrackingRange(entity, currentRange);
+ }
+}

View file

@ -1,262 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 16 Dec 2024 09:03:35 -0800
Subject: [PATCH] Add PaperHooks
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
new file mode 100644
index 0000000000000000000000000000000000000000..2988c418b34d6f699a9c24406cfd6949465b64f0
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -0,0 +1,241 @@
+package ca.spottedleaf.moonrise.paper;
+
+import ca.spottedleaf.moonrise.common.PlatformHooks;
+import ca.spottedleaf.moonrise.paper.util.BaseChunkSystemHooks;
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.DataFixer;
+import com.mojang.serialization.Dynamic;
+import java.util.Collection;
+import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtOps;
+import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.GenerationChunkHolder;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.boss.EnderDragonPart;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.chunk.ProtoChunk;
+import net.minecraft.world.level.chunk.storage.SerializableChunkData;
+import net.minecraft.world.level.entity.EntityTypeTest;
+import net.minecraft.world.phys.AABB;
+import java.util.List;
+import java.util.function.Predicate;
+
+public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
+
+ @Override
+ public String getBrand() {
+ return "Paper";
+ }
+
+ @Override
+ public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) {
+ return blockState.getLightEmission();
+ }
+
+ @Override
+ public Predicate<BlockState> maybeHasLightEmission() {
+ return (final BlockState state) -> {
+ return state.getLightEmission() != 0;
+ };
+ }
+
+ @Override
+ public boolean hasCurrentlyLoadingChunk() {
+ return false;
+ }
+
+ @Override
+ public LevelChunk getCurrentlyLoadingChunk(final GenerationChunkHolder holder) {
+ return null;
+ }
+
+ @Override
+ public void setCurrentlyLoading(final GenerationChunkHolder holder, final LevelChunk levelChunk) {
+
+ }
+
+ @Override
+ public void chunkFullStatusComplete(final LevelChunk newChunk, final ProtoChunk original) {
+
+ }
+
+ @Override
+ public boolean allowAsyncTicketUpdates() {
+ return true;
+ }
+
+ @Override
+ public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel) {
+
+ }
+
+ @Override
+ public void chunkUnloadFromWorld(final LevelChunk chunk) {
+
+ }
+
+ @Override
+ public void chunkSyncSave(final ServerLevel world, final ChunkAccess chunk, final SerializableChunkData data) {
+
+ }
+
+ @Override
+ public void onChunkWatch(final ServerLevel world, final LevelChunk chunk, final ServerPlayer player) {
+
+ }
+
+ @Override
+ public void onChunkUnWatch(final ServerLevel world, final ChunkPos chunk, final ServerPlayer player) {
+
+ }
+
+ @Override
+ public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate, final List<Entity> into) {
+ final Collection<EnderDragonPart> parts = world.dragonParts();
+ if (parts.isEmpty()) {
+ return;
+ }
+
+ for (final EnderDragonPart part : parts) {
+ if (part != entity && part.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(part))) {
+ into.add(part);
+ }
+ }
+ }
+
+ @Override
+ public <T extends Entity> void addToGetEntities(final Level world, final EntityTypeTest<Entity, T> entityTypeTest, final AABB boundingBox, final Predicate<? super T> predicate, final List<? super T> into, final int maxCount) {
+ if (into.size() >= maxCount) {
+ // fix neoforge issue: do not add if list is already full
+ return;
+ }
+
+ final Collection<EnderDragonPart> parts = world.dragonParts();
+ if (parts.isEmpty()) {
+ return;
+ }
+ for (final EnderDragonPart part : parts) {
+ if (!part.getBoundingBox().intersects(boundingBox)) {
+ continue;
+ }
+ final T casted = (T)entityTypeTest.tryCast(part);
+ if (casted != null && (predicate == null || predicate.test(casted))) {
+ into.add(casted);
+ if (into.size() >= maxCount) {
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void entityMove(final Entity entity, final long oldSection, final long newSection) {
+
+ }
+
+ @Override
+ public boolean screenEntity(final ServerLevel world, final Entity entity, final boolean fromDisk, final boolean event) {
+ return true;
+ }
+
+ @Override
+ public boolean configFixMC224294() {
+ return true;
+ }
+
+ @Override
+ public boolean configAutoConfigSendDistance() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.autoConfigSendDistance;
+ }
+
+ @Override
+ public double configPlayerMaxLoadRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkLoadRate;
+ }
+
+ @Override
+ public double configPlayerMaxGenRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkGenerateRate;
+ }
+
+ @Override
+ public double configPlayerMaxSendRate() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingBasic.playerMaxChunkSendRate;
+ }
+
+ @Override
+ public int configPlayerMaxConcurrentLoads() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.playerMaxConcurrentChunkLoads;
+ }
+
+ @Override
+ public int configPlayerMaxConcurrentGens() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().chunkLoadingAdvanced.playerMaxConcurrentChunkGenerates;
+ }
+
+ @Override
+ public long configAutoSaveInterval(final ServerLevel world) {
+ return world.paperConfig().chunks.autoSaveInterval.value();
+ }
+
+ @Override
+ public int configMaxAutoSavePerTick(final ServerLevel world) {
+ return world.paperConfig().chunks.maxAutoSaveChunksPerTick;
+ }
+
+ @Override
+ public boolean configFixMC159283() {
+ return true;
+ }
+
+ @Override
+ public boolean forceNoSave(final ChunkAccess chunk) {
+ return chunk instanceof LevelChunk levelChunk && levelChunk.mustNotSave;
+ }
+
+ @Override
+ public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
+ final int fromVersion, final int toVersion) {
+ return (CompoundTag)dataFixer.update(
+ type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
+ ).getValue();
+ }
+
+ @Override
+ public boolean hasMainChunkLoadHook() {
+ return false;
+ }
+
+ @Override
+ public void mainChunkLoad(final ChunkAccess chunk, final SerializableChunkData chunkData) {
+
+ }
+
+ @Override
+ public List<Entity> modifySavedEntities(final ServerLevel world, final int chunkX, final int chunkZ, final List<Entity> entities) {
+ return entities;
+ }
+
+ @Override
+ public void unloadEntity(final Entity entity) {
+ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, org.bukkit.event.entity.EntityRemoveEvent.Cause.UNLOAD);
+ }
+
+ @Override
+ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
+ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
+ }
+
+ @Override
+ public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
+ return org.spigotmc.TrackingRange.getEntityTrackingRange(entity, currentRange);
+ }
+}
diff --git a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
new file mode 100644
index 0000000000000000000000000000000000000000..34b45bc11124efb22f0f3ae5b2ad8f445c719476
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
@@ -0,0 +1,332 @@
@@ -1,0 +_,332 @@
+package ca.spottedleaf.moonrise.paper.util;
+
+import ca.spottedleaf.concurrentutil.util.Priority;

View file

@ -28,6 +28,14 @@
private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
public static final int LINEAR_LOOKUP_THRESHOLD = 8;
private static final Set<String> ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https");
@@ -113,6 +_,7 @@
.findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
private static Consumer<String> thePauser = string -> {};
+ public static final double COLLISION_EPSILON = 1.0E-7; // Paper - Check distance in entity interactions
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Entry::getKey, Entry::getValue);
@@ -135,7 +_,7 @@
}

View file

@ -47,3 +47,14 @@
return this.z;
}
@@ -235,4 +_,10 @@
public String toShortString() {
return this.getX() + ", " + this.getY() + ", " + this.getZ();
}
+
+ // Paper start - Perf: Optimize isInWorldBounds
+ public final boolean isInsideBuildHeightAndWorldBoundsHorizontal(final net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
+ return this.getX() >= -30000000 && this.getZ() >= -30000000 && this.getX() < 30000000 && this.getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(this.getY());
+ }
+ // Paper end - Perf: Optimize isInWorldBounds
}

View file

@ -1059,7 +1059,7 @@
String string = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde(
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
@@ -1757,10 +_,51 @@
@@ -1757,10 +_,52 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@ -1081,8 +1081,7 @@
@Override
public void onTrackingEnd(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
+ // Spigot start
+ // TODO I don't think this is needed anymore
+ // Spigot start // TODO I don't think this is needed anymore
+ if (entity instanceof Player player) {
+ for (final ServerLevel level : ServerLevel.this.getServer().getAllLevels()) {
+ for (final Optional<net.minecraft.world.level.saveddata.SavedData> savedData : level.getDataStorage().cache.values()) {
@ -1091,7 +1090,9 @@
+ }
+
+ map.carriedByPlayers.remove(player);
+ map.carriedBy.removeIf(holdingPlayer -> holdingPlayer.player == player);
+ if (map.carriedBy.removeIf(holdingPlayer -> holdingPlayer.player == player)) {
+ map.decorations.remove(player.getName().getString());
+ }
+ }
+ }
+ }

View file

@ -1342,7 +1342,7 @@
}
public SectionPos getLastSectionPos() {
@@ -1930,16 +_,41 @@
@@ -1930,21 +_,54 @@
}
@Override
@ -1386,6 +1386,19 @@
}
this.awardStat(Stats.DROP);
}
+ // Paper start - remove player from map on drop
+ if (item.getItem() == net.minecraft.world.item.Items.FILLED_MAP) {
+ final MapItemSavedData mapData = MapItem.getSavedData(item, this.level());
+ if (mapData != null) {
+ mapData.tickCarriedBy(this, item);
+ }
+ }
+ // Paper end - remove player from map on drop
return itemEntity;
}
}
@@ -1955,6 +_,11 @@
return null;
} else {

View file

@ -497,7 +497,7 @@
return false;
} else if (damageSource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
return false;
@@ -1116,10 +_,11 @@
@@ -1116,47 +_,71 @@
amount = 0.0F;
}
@ -512,7 +512,11 @@
this.hurtCurrentlyUsedShield(amount);
f1 = amount;
amount = 0.0F;
@@ -1130,33 +_,56 @@
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity) {
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity && livingEntity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Check distance in entity interactions
this.blockUsingShield(livingEntity);
}
flag = true;
}
@ -584,9 +588,18 @@
this.markHurt();
}
@@ -1186,7 +_,7 @@
@@ -1185,8 +_,16 @@
d = damageSource.getSourcePosition().x() - this.getX();
d1 = damageSource.getSourcePosition().z() - this.getZ();
}
+ // Paper start - Check distance in entity interactions; see for loop in knockback method
+ if (Math.abs(d) > 200) {
+ d = Math.random() - Math.random();
+ }
+ if (Math.abs(d1) > 200) {
+ d1 = Math.random() - Math.random();
+ }
+ // Paper end - Check distance in entity interactions
- this.knockback(0.4F, d, d1);
+ this.knockback(0.4F, d, d1, damageSource.getDirectEntity(), damageSource.getDirectEntity() == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
@ -1110,7 +1123,7 @@
+ this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING));
+ Entity entity = damageSource.getDirectEntity();
+
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity) { // Paper - Fix shield disable inconsistency
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Fix shield disable inconsistency & Check distance in entity interactions
+ this.blockUsingShield((LivingEntity) entity);
+ }
+ }

View file

@ -75,6 +75,15 @@
this.applyEffectsFromBlocks();
this.applyEffectsFromBlocks();
this.tickBubbleColumn();
@@ -598,7 +_,7 @@
this.waterLevel = this.getY(1.0);
double d2 = this.getWaterLevelAbove() - this.getBbHeight() + 0.101;
if (this.level().noCollision(this, this.getBoundingBox().move(0.0, d2 - this.getY(), 0.0))) {
- this.setPos(this.getX(), d2, this.getZ());
+ this.move(MoverType.SELF, new Vec3(0.0D, d2 - this.getY(), 0.0D)); // Paper - Fix some exploit with boats // TODO Still needed?
this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0));
this.lastYd = 0.0;
}
@@ -762,11 +_,18 @@
@Override

View file

@ -241,7 +241,7 @@
@Override
public boolean isClientSide() {
@@ -167,6 +_,13 @@
@@ -167,8 +_,15 @@
return null;
}
@ -253,14 +253,17 @@
+ // Paper end
+
public boolean isInWorldBounds(BlockPos pos) {
return !this.isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos);
- return !this.isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos);
+ return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - Perf: Optimize isInWorldBounds
}
public static boolean isInSpawnableBounds(BlockPos pos) {
@@ -176,21 +_,84 @@
}
private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
- return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
+ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000; // Diff on change warnUnsafeChunk()
+ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000; // Diff on change warnUnsafeChunk() and isInsideBuildHeightAndWorldBoundsHorizontal
}
private static boolean isOutsideSpawnableHeight(int y) {

View file

@ -39,6 +39,14 @@
}
private static void replaceMissingSections(Registry<Biome> biomeRegistry, LevelChunkSection[] sections) {
@@ -123,6 +_,7 @@
return GameEventListenerRegistry.NOOP;
}
+ public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
@Nullable
public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving);
@@ -273,6 +_,7 @@
public boolean tryMarkSaved() {
if (this.unsaved) {

View file

@ -0,0 +1,15 @@
--- a/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -56,6 +_,12 @@
public BlockState getBlockState(BlockPos pos) {
return this.wrapped.getBlockState(pos);
}
+ // Paper start
+ @Override
+ public final BlockState getBlockState(final int x, final int y, final int z) {
+ return this.wrapped.getBlockStateFinal(x, y, z);
+ }
+ // Paper end
@Override
public FluidState getFluidState(BlockPos pos) {

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -85,6 +_,18 @@
@@ -85,14 +_,32 @@
return new ChunkAccess.PackedTicks(this.blockTicks.pack(gametime), this.fluidTicks.pack(gametime));
}
@ -18,4 +18,21 @@
+
@Override
public BlockState getBlockState(BlockPos pos) {
int y = pos.getY();
- int y = pos.getY();
+ // Paper start
+ return getBlockState(pos.getX(), pos.getY(), pos.getZ());
+ }
+ public BlockState getBlockState(final int x, final int y, final int z) {
+ // Paper end
if (this.isOutsideBuildHeight(y)) {
return Blocks.VOID_AIR.defaultBlockState();
} else {
- LevelChunkSection section = this.getSection(this.getSectionIndex(y));
- return section.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : section.getBlockState(pos.getX() & 15, y & 15, pos.getZ() & 15);
+ // Paper start
+ LevelChunkSection section = this.getSections()[this.getSectionIndex(y)];
+ return section.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : section.getBlockState(x & 15, y & 15, z & 15);
+ // Paper end
}
}

View file

@ -1,26 +1,35 @@
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -61,6 +_,7 @@
public byte scale;
public byte[] colors = new byte[16384];
public boolean locked;
+ private final org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - Use Vanilla map renderer when possible
public final List<MapItemSavedData.HoldingPlayer> carriedBy = Lists.newArrayList();
public final Map<Player, MapItemSavedData.HoldingPlayer> carriedByPlayers = Maps.newHashMap();
private final Map<String, MapBanner> bannerMarkers = Maps.newHashMap();
@@ -68,6 +_,13 @@
private final Map<String, MapFrame> frameMarkers = Maps.newHashMap();
private int trackedDecorationCount;
+ // CraftBukkit start
+ public final org.bukkit.craftbukkit.map.CraftMapView mapView;
+ private org.bukkit.craftbukkit.CraftServer server;
+ public java.util.UUID uniqueId = null;
+ private final org.bukkit.craftbukkit.CraftServer server;
+ public java.util.UUID uniqueId;
+ public MapId id;
+ // CraftBukkit end
+
public static SavedData.Factory<MapItemSavedData> factory() {
return new SavedData.Factory<>(() -> {
throw new IllegalStateException("Should never create an empty map saved data");
@@ -82,6 +_,10 @@
@@ -82,6 +_,11 @@
this.trackingPosition = trackingPosition;
this.unlimitedTracking = unlimitedTracking;
this.locked = locked;
+ // CraftBukkit start
+ this.mapView = new org.bukkit.craftbukkit.map.CraftMapView(this);
+ this.server = (org.bukkit.craftbukkit.CraftServer) org.bukkit.Bukkit.getServer();
+ this.vanillaRender.buffer = colors; // Paper - Use Vanilla map renderer when possible
+ // CraftBukkit end
}
@ -76,6 +85,14 @@
int _int = tag.getInt("xCenter");
int _int1 = tag.getInt("zCenter");
byte b = (byte)Mth.clamp(tag.getByte("scale"), 0, 4);
@@ -114,6 +_,7 @@
if (byteArray.length == 16384) {
mapItemSavedData.colors = byteArray;
}
+ mapItemSavedData.vanillaRender.buffer = byteArray; // Paper - Use Vanilla map renderer when possible
RegistryOps<Tag> registryOps = levelRegistry.createSerializationContext(NbtOps.INSTANCE);
@@ -154,6 +_,25 @@
.encodeStart(NbtOps.INSTANCE, this.dimension.location())
.resultOrPartial(LOGGER::error)
@ -115,6 +132,15 @@
}
MapDecorations mapDecorations = mapStack.getOrDefault(DataComponents.MAP_DECORATIONS, MapDecorations.EMPTY);
@@ -267,7 +_,7 @@
this.trackedDecorationCount--;
}
- this.setDecorationsDirty();
+ if (mapDecoration != null) this.setDecorationsDirty(); // Paper - only mark dirty if a change occurs
}
public static void addTargetDecoration(ItemStack stack, BlockPos pos, String type, Holder<MapDecorationType> mapDecorationType) {
@@ -421,7 +_,7 @@
return true;
}
@ -142,11 +168,21 @@
}
}
@@ -540,17 +_,27 @@
@@ -540,17 +_,38 @@
@Nullable
Packet<?> nextUpdatePacket(MapId mapId) {
MapItemSavedData.MapPatch mapPatch;
+ org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit
+ // Paper start
+ if (!this.dirtyData && this.tick % 5 != 0) {
+ // this won't end up sending, so don't render it!
+ this.tick++;
+ return null;
+ }
+
+ final boolean vanillaMaps = this.shouldUseVanillaMap();
+ // Use Vanilla map renderer when possible - much simpler/faster than the CB rendering
+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender;
+ // Paper end
if (this.dirtyData) {
this.dirtyData = false;
- mapPatch = this.createPatch();
@ -157,11 +193,12 @@
Collection<MapDecoration> collection;
- if (this.dirtyDecorations && this.tick++ % 5 == 0) {
+ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet
+ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet // TODO fix this
this.dirtyDecorations = false;
- collection = MapItemSavedData.this.decorations.values();
+ // CraftBukkit start
+ java.util.Collection<MapDecoration> icons = new java.util.ArrayList<MapDecoration>();
+ if (vanillaMaps) this.addSeenPlayers(icons); // Paper
+
+ for (org.bukkit.map.MapCursor cursor : render.cursors) {
+ if (cursor.isVisible()) {
@ -173,3 +210,27 @@
} else {
collection = null;
}
@@ -578,6 +_,23 @@
private void markDecorationsDirty() {
this.dirtyDecorations = true;
}
+
+ // Paper start
+ private void addSeenPlayers(java.util.Collection<MapDecoration> icons) {
+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.player.getBukkitEntity();
+ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> {
+ // If this cursor is for a player check visibility with vanish system
+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot
+ if (other == null || player.canSee(other)) {
+ icons.add(mapIcon);
+ }
+ });
+ }
+
+ private boolean shouldUseVanillaMap() {
+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().getFirst().getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class;
+ }
+ // Paper end
}
record MapDecorationLocation(Holder<MapDecorationType> type, byte x, byte y, byte rot) {