Apply some feature patches to files instead
They're small and/or really shouldn't be left unapplied
This commit is contained in:
@@ -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);
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1,335 @@
|
||||
--- /dev/null
|
||||
+++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
|
||||
@@ -1,0 +_,332 @@
|
||||
+package ca.spottedleaf.moonrise.paper.util;
|
||||
+
|
||||
+import ca.spottedleaf.concurrentutil.util.Priority;
|
||||
+import com.mojang.logging.LogUtils;
|
||||
+import net.minecraft.server.level.ChunkHolder;
|
||||
+import net.minecraft.server.level.ChunkResult;
|
||||
+import net.minecraft.server.level.FullChunkStatus;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import net.minecraft.server.level.TicketType;
|
||||
+import net.minecraft.world.level.ChunkPos;
|
||||
+import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
+import net.minecraft.world.level.chunk.LevelChunk;
|
||||
+import net.minecraft.world.level.chunk.status.ChunkPyramid;
|
||||
+import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
+import net.minecraft.world.level.chunk.status.ChunkStep;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.slf4j.Logger;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import java.util.function.Consumer;
|
||||
+
|
||||
+public abstract class BaseChunkSystemHooks implements ca.spottedleaf.moonrise.common.util.ChunkSystemHooks {
|
||||
+
|
||||
+ private static final Logger LOGGER = LogUtils.getLogger();
|
||||
+ private static final ChunkStep FULL_CHUNK_STEP = ChunkPyramid.GENERATION_PYRAMID.getStepTo(ChunkStatus.FULL);
|
||||
+ private static final TicketType<Long> CHUNK_LOAD = TicketType.create("chunk_load", Long::compareTo);
|
||||
+
|
||||
+ private long chunkLoadCounter = 0L;
|
||||
+
|
||||
+ private static int getDistance(final ChunkStatus status) {
|
||||
+ return FULL_CHUNK_STEP.getAccumulatedRadiusOf(status);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
|
||||
+ this.scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority) {
|
||||
+ level.chunkSource.mainThreadProcessor.execute(run);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
|
||||
+ final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
|
||||
+ final Consumer<ChunkAccess> onComplete) {
|
||||
+ if (gen) {
|
||||
+ this.scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||
+ return;
|
||||
+ }
|
||||
+ this.scheduleChunkLoad(level, chunkX, chunkZ, ChunkStatus.EMPTY, addTicket, priority, (final ChunkAccess chunk) -> {
|
||||
+ if (chunk == null) {
|
||||
+ if (onComplete != null) {
|
||||
+ onComplete.accept(null);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (chunk.getPersistedStatus().isOrAfter(toStatus)) {
|
||||
+ BaseChunkSystemHooks.this.scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||
+ } else {
|
||||
+ if (onComplete != null) {
|
||||
+ onComplete.accept(null);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
|
||||
+ final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
|
||||
+ if (!Bukkit.isOwnedByCurrentRegion(level.getWorld(), chunkX, chunkZ)) {
|
||||
+ this.scheduleChunkTask(level, chunkX, chunkZ, () -> {
|
||||
+ BaseChunkSystemHooks.this.scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||
+ }, priority);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final int minLevel = 33 + getDistance(toStatus);
|
||||
+ final Long chunkReference = addTicket ? Long.valueOf(++this.chunkLoadCounter) : null;
|
||||
+ final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
+
|
||||
+ if (addTicket) {
|
||||
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
|
||||
+ }
|
||||
+ level.chunkSource.runDistanceManagerUpdates();
|
||||
+
|
||||
+ final Consumer<ChunkAccess> loadCallback = (final ChunkAccess chunk) -> {
|
||||
+ try {
|
||||
+ if (onComplete != null) {
|
||||
+ onComplete.accept(chunk);
|
||||
+ }
|
||||
+ } catch (final Throwable thr) {
|
||||
+ LOGGER.error("Exception handling chunk load callback", thr);
|
||||
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(thr);
|
||||
+ } finally {
|
||||
+ if (addTicket) {
|
||||
+ level.chunkSource.addTicketAtLevel(net.minecraft.server.level.TicketType.UNKNOWN, chunkPos, minLevel, chunkPos);
|
||||
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
+
|
||||
+ if (holder == null || holder.getTicketLevel() > minLevel) {
|
||||
+ loadCallback.accept(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final CompletableFuture<ChunkResult<ChunkAccess>> loadFuture = holder.scheduleChunkGenerationTask(toStatus, level.chunkSource.chunkMap);
|
||||
+
|
||||
+ if (loadFuture.isDone()) {
|
||||
+ loadCallback.accept(loadFuture.join().orElse(null));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ loadFuture.whenCompleteAsync((final ChunkResult<ChunkAccess> result, final Throwable thr) -> {
|
||||
+ if (thr != null) {
|
||||
+ loadCallback.accept(null);
|
||||
+ return;
|
||||
+ }
|
||||
+ loadCallback.accept(result.orElse(null));
|
||||
+ }, (final Runnable r) -> {
|
||||
+ BaseChunkSystemHooks.this.scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
|
||||
+ final FullChunkStatus toStatus, final boolean addTicket,
|
||||
+ final Priority priority, final Consumer<LevelChunk> onComplete) {
|
||||
+ // This method goes unused until the chunk system rewrite
|
||||
+ if (toStatus == FullChunkStatus.INACCESSIBLE) {
|
||||
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
|
||||
+ }
|
||||
+
|
||||
+ if (!Bukkit.isOwnedByCurrentRegion(level.getWorld(), chunkX, chunkZ)) {
|
||||
+ this.scheduleChunkTask(level, chunkX, chunkZ, () -> {
|
||||
+ BaseChunkSystemHooks.this.scheduleTickingState(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||
+ }, priority);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final int minLevel = 33 - (toStatus.ordinal() - 1);
|
||||
+ final int radius = toStatus.ordinal() - 1;
|
||||
+ final Long chunkReference = addTicket ? Long.valueOf(++this.chunkLoadCounter) : null;
|
||||
+ final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
+
|
||||
+ if (addTicket) {
|
||||
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
|
||||
+ }
|
||||
+ level.chunkSource.runDistanceManagerUpdates();
|
||||
+
|
||||
+ final Consumer<LevelChunk> loadCallback = (final LevelChunk chunk) -> {
|
||||
+ try {
|
||||
+ if (onComplete != null) {
|
||||
+ onComplete.accept(chunk);
|
||||
+ }
|
||||
+ } catch (final Throwable thr) {
|
||||
+ LOGGER.error("Exception handling chunk load callback", thr);
|
||||
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(thr);
|
||||
+ } finally {
|
||||
+ if (addTicket) {
|
||||
+ level.chunkSource.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, minLevel, chunkPos);
|
||||
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
+
|
||||
+ if (holder == null || holder.getTicketLevel() > minLevel) {
|
||||
+ loadCallback.accept(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final CompletableFuture<ChunkResult<LevelChunk>> tickingState;
|
||||
+ switch (toStatus) {
|
||||
+ case FULL: {
|
||||
+ tickingState = holder.getFullChunkFuture();
|
||||
+ break;
|
||||
+ }
|
||||
+ case BLOCK_TICKING: {
|
||||
+ tickingState = holder.getTickingChunkFuture();
|
||||
+ break;
|
||||
+ }
|
||||
+ case ENTITY_TICKING: {
|
||||
+ tickingState = holder.getEntityTickingChunkFuture();
|
||||
+ break;
|
||||
+ }
|
||||
+ default: {
|
||||
+ throw new IllegalStateException("Cannot reach here");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (tickingState.isDone()) {
|
||||
+ loadCallback.accept(tickingState.join().orElse(null));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ tickingState.whenCompleteAsync((final ChunkResult<LevelChunk> result, final Throwable thr) -> {
|
||||
+ if (thr != null) {
|
||||
+ loadCallback.accept(null);
|
||||
+ return;
|
||||
+ }
|
||||
+ loadCallback.accept(result.orElse(null));
|
||||
+ }, (final Runnable r) -> {
|
||||
+ BaseChunkSystemHooks.this.scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ChunkHolder> getVisibleChunkHolders(final ServerLevel level) {
|
||||
+ return new ArrayList<>(level.chunkSource.chunkMap.visibleChunkMap.values());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level) {
|
||||
+ return new ArrayList<>(level.chunkSource.chunkMap.updatingChunkMap.values());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getVisibleChunkHolderCount(final ServerLevel level) {
|
||||
+ return level.chunkSource.chunkMap.visibleChunkMap.size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getUpdatingChunkHolderCount(final ServerLevel level) {
|
||||
+ return level.chunkSource.chunkMap.updatingChunkMap.size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasAnyChunkHolders(final ServerLevel level) {
|
||||
+ return this.getUpdatingChunkHolderCount(level) != 0;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkPostNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) {
|
||||
+ return level.chunkSource.chunkMap.getUnloadingChunkHolder(chunkX, chunkZ);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getSendViewDistance(final ServerPlayer player) {
|
||||
+ return this.getViewDistance(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getViewDistance(final ServerPlayer player) {
|
||||
+ final ServerLevel level = player.serverLevel();
|
||||
+ if (level == null) {
|
||||
+ return Bukkit.getViewDistance();
|
||||
+ }
|
||||
+ return level.chunkSource.chunkMap.serverViewDistance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTickViewDistance(final ServerPlayer player) {
|
||||
+ final ServerLevel level = player.serverLevel();
|
||||
+ if (level == null) {
|
||||
+ return Bukkit.getSimulationDistance();
|
||||
+ }
|
||||
+ return level.chunkSource.chunkMap.distanceManager.simulationDistance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addPlayerToDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void updateMaps(final ServerLevel world, final ServerPlayer player) {
|
||||
+
|
||||
+ }
|
||||
+}
|
||||
@@ -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 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user