mirror of
https://github.com/PaperMC/Paper.git
synced 2025-08-01 12:42:05 -07:00
More work
This commit is contained in:
@@ -1,55 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
||||||
Date: Tue, 1 Jan 2019 02:22:01 -0800
|
|
||||||
Subject: [PATCH] Add Heightmap API
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- @Override
|
|
||||||
- public int getHeight(Heightmap.Types heightmap, int x, int z) {
|
|
||||||
+ public final int getHighestBlockY(final Heightmap.Types heightmap, final int x, final int z) { return this.getHeight(heightmap, x, z); } // Paper - OBFHELPER
|
|
||||||
+ @Override public int getHeight(Heightmap.Types heightmap, int x, int z) { // Paper - OBFHELPER
|
|
||||||
int k;
|
|
||||||
|
|
||||||
if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) {
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
|
||||||
return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ // Paper start - Implement heightmap api
|
|
||||||
+ @Override
|
|
||||||
+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
|
|
||||||
+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas
|
|
||||||
+
|
|
||||||
+ switch (heightmap) {
|
|
||||||
+ case LIGHT_BLOCKING:
|
|
||||||
+ throw new UnsupportedOperationException(); // TODO
|
|
||||||
+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z);
|
|
||||||
+ case ANY:
|
|
||||||
+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z);
|
|
||||||
+ case SOLID:
|
|
||||||
+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z);
|
|
||||||
+ case SOLID_OR_LIQUID:
|
|
||||||
+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z);
|
|
||||||
+ case SOLID_OR_LIQUID_NO_LEAVES:
|
|
||||||
+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z);
|
|
||||||
+ default:
|
|
||||||
+ throw new UnsupportedOperationException();
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
+
|
|
||||||
@Override
|
|
||||||
public Location getSpawnLocation() {
|
|
||||||
BlockPos spawn = world.getSpawn();
|
|
@@ -1,249 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Aikar <aikar@aikar.co>
|
|
||||||
Date: Sat, 21 Jul 2018 14:27:34 -0400
|
|
||||||
Subject: [PATCH] Duplicate UUID Resolve Option
|
|
||||||
|
|
||||||
Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24
|
|
||||||
which was added all the way back in March of 2016, it was unknown (potentially not at the time)
|
|
||||||
that an entity might actually change the seed of the random object.
|
|
||||||
|
|
||||||
At some point, EntitySquid did start setting the seed. Due to this shared random, this caused
|
|
||||||
every entity to use a Random object with a predictable seed.
|
|
||||||
|
|
||||||
This has caused entities to potentially generate with the same UUID....
|
|
||||||
|
|
||||||
Over the years, servers have had entities disappear, but no sign of trouble
|
|
||||||
because CraftBukkit removed the log lines indicating that something was wrong.
|
|
||||||
|
|
||||||
We have fixed the root issue causing duplicate UUID's, however we now have chunk
|
|
||||||
files full of entities that have the same UUID as another entity!
|
|
||||||
|
|
||||||
When these chunks load, the 2nd entity will not be added to the world correctly.
|
|
||||||
|
|
||||||
If that chunk loads in a different order in the future, then it will reverse and the
|
|
||||||
missing one is now the one added to the world and not the other. This results in very
|
|
||||||
inconsistent entity behavior.
|
|
||||||
|
|
||||||
This change allows you to recover any duplicate entity by generating a new UUID for it.
|
|
||||||
This also lets you delete them instead if you don't want to risk having new entities added to
|
|
||||||
the world that you previously did not see.
|
|
||||||
|
|
||||||
But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options.
|
|
||||||
|
|
||||||
It is recommended you regenerate the entities, as these were legit entities, and deserve your love.
|
|
||||||
|
|
||||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
||||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
||||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
|
||||||
private void preventMovingIntoUnloadedChunks() {
|
|
||||||
preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ public enum DuplicateUUIDMode {
|
|
||||||
+ SAFE_REGEN, DELETE, NOTHING, WARN
|
|
||||||
+ }
|
|
||||||
+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN;
|
|
||||||
+ public int duplicateUUIDDeleteRange = 32;
|
|
||||||
+ private void repairDuplicateUUID() {
|
|
||||||
+ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim();
|
|
||||||
+ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange);
|
|
||||||
+ switch (desiredMode.toLowerCase()) {
|
|
||||||
+ case "regen":
|
|
||||||
+ case "regenerate":
|
|
||||||
+ case "saferegen":
|
|
||||||
+ case "saferegenerate":
|
|
||||||
+ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN;
|
|
||||||
+ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)");
|
|
||||||
+ break;
|
|
||||||
+ case "remove":
|
|
||||||
+ case "delete":
|
|
||||||
+ duplicateUUIDMode = DuplicateUUIDMode.DELETE;
|
|
||||||
+ log("Duplicate UUID Resolve: Delete Entity");
|
|
||||||
+ break;
|
|
||||||
+ case "silent":
|
|
||||||
+ case "nothing":
|
|
||||||
+ duplicateUUIDMode = DuplicateUUIDMode.NOTHING;
|
|
||||||
+ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening");
|
|
||||||
+ break;
|
|
||||||
+ case "log":
|
|
||||||
+ case "warn":
|
|
||||||
+ duplicateUUIDMode = DuplicateUUIDMode.WARN;
|
|
||||||
+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)");
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ duplicateUUIDMode = DuplicateUUIDMode.WARN;
|
|
||||||
+ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn");
|
|
||||||
+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)");
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
||||||
@@ -0,0 +0,0 @@
|
|
||||||
package net.minecraft.server.level;
|
|
||||||
|
|
||||||
import co.aikar.timings.Timing; // Paper
|
|
||||||
+import com.destroystokyo.paper.PaperWorldConfig; // Paper
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.ComparisonChain; // Paper
|
|
||||||
@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
+import java.util.HashMap; // Paper
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
+import java.util.Map; // Paper
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CancellationException;
|
|
||||||
+import java.util.UUID; // Paper
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.CompletionException;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
|
||||||
import net.minecraft.world.entity.boss.EnderDragonPart;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
|
||||||
import net.minecraft.world.level.GameRules;
|
|
||||||
+import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
||||||
if (chunk.needsDecoration) {
|
|
||||||
net.minecraft.server.dedicated.DedicatedServer server = this.level.getCraftServer().getServer();
|
|
||||||
if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.Npc) {
|
|
||||||
- entity.remove();
|
|
||||||
+ entity.removed = true; // Paper
|
|
||||||
needsRemoval = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) {
|
|
||||||
- entity.remove();
|
|
||||||
+ entity.removed = true; // Paper
|
|
||||||
needsRemoval = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- if (!(entity instanceof net.minecraft.world.entity.player.Player) && (needsRemoval || !this.level.loadFromChunk(entity))) {
|
|
||||||
- // CraftBukkit end
|
|
||||||
+ // CraftBukkit end
|
|
||||||
+ checkDupeUUID(entity); // Paper
|
|
||||||
+ if (!(entity instanceof net.minecraft.world.entity.player.Player) && (entity.removed || !this.level.loadFromChunk(entity))) { // Paper
|
|
||||||
if (list == null) {
|
|
||||||
list = Lists.newArrayList(new Entity[]{entity});
|
|
||||||
} else {
|
|
||||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
+ // Paper start
|
|
||||||
+ private void checkDupeUUID(Entity entity) {
|
|
||||||
+ PaperWorldConfig.DuplicateUUIDMode mode = level.paperConfig.duplicateUUIDMode;
|
|
||||||
+ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN
|
|
||||||
+ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE
|
|
||||||
+ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ Entity other = level.getEntity(entity.getUUID());
|
|
||||||
+
|
|
||||||
+ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.removed
|
|
||||||
+ && Objects.equals(other.getEncodeId(), entity.getEncodeId())
|
|
||||||
+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig.duplicateUUIDDeleteRange
|
|
||||||
+ ) {
|
|
||||||
+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
|
||||||
+ entity.removed = true;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ if (other != null && !other.removed) {
|
|
||||||
+ switch (mode) {
|
|
||||||
+ case SAFE_REGEN: {
|
|
||||||
+ entity.setUUID(UUID.randomUUID());
|
|
||||||
+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ case DELETE: {
|
|
||||||
+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
|
||||||
+ entity.removed = true;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ default:
|
|
||||||
+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
+
|
|
||||||
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> postProcess(ChunkHolder holder) {
|
|
||||||
ChunkPos chunkcoordintpair = holder.getPos();
|
|
||||||
CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkcoordintpair, 1, (i) -> {
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
@@ -0,0 +0,0 @@ import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import co.aikar.timings.TimingHistory; // Paper
|
|
||||||
import co.aikar.timings.Timings; // Paper
|
|
||||||
+
|
|
||||||
+import com.destroystokyo.paper.PaperWorldConfig; // Paper
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Queues;
|
|
||||||
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
|
||||||
if (entity1 == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
+ // Paper start
|
|
||||||
+ if (entity1.removed) {
|
|
||||||
+ onEntityRemoved(entity1); // remove the existing entity
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper
|
|
||||||
+ // Paper start
|
|
||||||
+ if (DEBUG_ENTITIES && entity.level.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) {
|
|
||||||
+ if (entity1.addedToWorldStack != null) {
|
|
||||||
+ entity1.addedToWorldStack.printStackTrace();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ getAddToWorldStackTrace(entity).printStackTrace();
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
+ public final void setUUID(UUID uuid) { setUUID(uuid); } // Paper - OBFHELPER
|
|
||||||
public void setUUID(UUID uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.stringUUID = this.uuid.toString();
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
||||||
@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
|
|
||||||
if (i != this.chunkPos.x || j != this.chunkPos.z) {
|
|
||||||
LevelChunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.chunkPos.x, this.chunkPos.z, entity);
|
|
||||||
entity.removed = true;
|
|
||||||
+ return; // Paper
|
|
||||||
}
|
|
||||||
|
|
||||||
int k = Mth.floor(entity.getY() / 16.0D);
|
|
@@ -1,53 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Aikar <aikar@aikar.co>
|
|
||||||
Date: Fri, 28 Sep 2018 21:49:53 -0400
|
|
||||||
Subject: [PATCH] Fix issues with entity loss due to unloaded chunks
|
|
||||||
|
|
||||||
Vanilla has risk of losing entities by causing them to be
|
|
||||||
removed from all chunks if they try to move into an unloaded chunk.
|
|
||||||
|
|
||||||
This pretty much means high chance this entity will be lost in this
|
|
||||||
scenario.
|
|
||||||
|
|
||||||
There is another case that adding an entity to the world can fail if
|
|
||||||
the chunk isn't loaded.
|
|
||||||
|
|
||||||
Lots of the server is designed around addEntity never expecting to fail
|
|
||||||
for these reasons, nor is it really logical.
|
|
||||||
|
|
||||||
This change ensures the chunks are always loaded when entities are
|
|
||||||
added to the world, or a valid entity moves between chunks.
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
||||||
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
|
||||||
int k = Mth.floor(entity.getZ() / 16.0D);
|
|
||||||
|
|
||||||
if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) {
|
|
||||||
+ // Paper start - remove entity if its in a chunk more correctly.
|
|
||||||
+ LevelChunk currentChunk = entity.getCurrentChunk();
|
|
||||||
+ if (currentChunk != null) {
|
|
||||||
+ currentChunk.removeEntity(entity);
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
+
|
|
||||||
if (entity.inChunk && this.hasChunk(entity.xChunk, entity.zChunk)) {
|
|
||||||
this.getChunk(entity.xChunk, entity.zChunk).removeEntity(entity, entity.yChunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) {
|
|
||||||
+ if (!entity.valid && !entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { // Paper - always load chunks to register valid entities location
|
|
||||||
if (entity.inChunk) {
|
|
||||||
ServerLevel.LOGGER.warn("Entity {} left loaded chunk area", entity);
|
|
||||||
}
|
|
||||||
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// CraftBukkit end
|
|
||||||
- ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, entity.forcedLoading);
|
|
||||||
+ ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds
|
|
||||||
|
|
||||||
if (!(ichunkaccess instanceof LevelChunk)) {
|
|
||||||
return false;
|
|
@@ -1,24 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
|
||||||
Date: Mon, 27 May 2019 17:35:39 -0500
|
|
||||||
Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative
|
|
||||||
size
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
|
||||||
@@ -0,0 +0,0 @@ public class AreaEffectCloud extends Entity {
|
|
||||||
super.tick();
|
|
||||||
boolean flag = this.isWaiting();
|
|
||||||
float f = this.getRadius();
|
|
||||||
+ // Paper start - fix MC-114618
|
|
||||||
+ if (f < 0.0F) {
|
|
||||||
+ this.remove();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
|
|
||||||
if (this.level.isClientSide) {
|
|
||||||
ParticleOptions particleparam = this.getParticle();
|
|
@@ -1,139 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
|
||||||
Date: Fri, 19 Apr 2019 12:41:13 -0500
|
|
||||||
Subject: [PATCH] Mob Spawner API Enhancements
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
|
||||||
this.spawnPotentials.clear(); // CraftBukkit - SPIGOT-3496, MC-92282
|
|
||||||
}
|
|
||||||
|
|
||||||
+ public boolean isActivated() { return isNearPlayer(); } // Paper - OBFHELPER
|
|
||||||
private boolean isNearPlayer() {
|
|
||||||
BlockPos blockposition = this.getPos();
|
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ public void resetTimer() { delay(); } // Paper - OBFHELPER
|
|
||||||
private void delay() {
|
|
||||||
if (this.maxSpawnDelay <= this.minSpawnDelay) {
|
|
||||||
this.spawnDelay = this.minSpawnDelay;
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(CompoundTag tag) {
|
|
||||||
+ // Paper start - use larger int if set
|
|
||||||
+ if (tag.contains("Paper.Delay")) {
|
|
||||||
+ this.spawnDelay = tag.getInt("Paper.Delay");
|
|
||||||
+ } else {
|
|
||||||
this.spawnDelay = tag.getShort("Delay");
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
this.spawnPotentials.clear();
|
|
||||||
if (tag.contains("SpawnPotentials", 9)) {
|
|
||||||
ListTag nbttaglist = tag.getList("SpawnPotentials", 10);
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
|
||||||
} else if (!this.spawnPotentials.isEmpty()) {
|
|
||||||
this.setNextSpawnData((SpawnData) WeighedRandom.getRandomItem(this.getLevel().random, this.spawnPotentials));
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+ // Paper start - use ints if set
|
|
||||||
+ if (tag.contains("Paper.MinSpawnDelay", 99)) {
|
|
||||||
+ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay");
|
|
||||||
+ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay");
|
|
||||||
+ this.spawnCount = tag.getShort("SpawnCount");
|
|
||||||
+ } else // Paper end
|
|
||||||
if (tag.contains("MinSpawnDelay", 99)) {
|
|
||||||
- this.minSpawnDelay = tag.getShort("MinSpawnDelay");
|
|
||||||
- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay");
|
|
||||||
+ this.minSpawnDelay = tag.getInt("MinSpawnDelay");
|
|
||||||
+ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay");
|
|
||||||
this.spawnCount = tag.getShort("SpawnCount");
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
|
||||||
if (minecraftkey == null) {
|
|
||||||
return tag;
|
|
||||||
} else {
|
|
||||||
- tag.putShort("Delay", (short) this.spawnDelay);
|
|
||||||
- tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay);
|
|
||||||
- tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay);
|
|
||||||
+ // Paper start
|
|
||||||
+ if (spawnDelay > Short.MAX_VALUE) {
|
|
||||||
+ tag.putInt("Paper.Delay", this.spawnDelay);
|
|
||||||
+ }
|
|
||||||
+ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay));
|
|
||||||
+
|
|
||||||
+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) {
|
|
||||||
+ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay);
|
|
||||||
+ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay));
|
|
||||||
+ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay));
|
|
||||||
+ // Paper end
|
|
||||||
tag.putShort("SpawnCount", (short) this.spawnCount);
|
|
||||||
tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities);
|
|
||||||
tag.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange);
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
|
||||||
@@ -0,0 +0,0 @@
|
|
||||||
package org.bukkit.craftbukkit.block;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
+import net.minecraft.core.Registry;
|
|
||||||
+import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
+import net.minecraft.world.level.SpawnData;
|
|
||||||
import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.CreatureSpawner;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
+// Paper start
|
|
||||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
|
||||||
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
|
||||||
+import org.bukkit.inventory.ItemStack;
|
|
||||||
+// Paper end
|
|
||||||
|
|
||||||
public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEntity> implements CreatureSpawner {
|
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
|
|
||||||
public void setSpawnRange(int spawnRange) {
|
|
||||||
this.getSnapshot().getSpawner().spawnRange = spawnRange;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ // Paper start
|
|
||||||
+ @Override
|
|
||||||
+ public boolean isActivated() {
|
|
||||||
+ return this.getSnapshot().getSpawner().isActivated();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ @Override
|
|
||||||
+ public void resetTimer() {
|
|
||||||
+ this.getSnapshot().getSpawner().resetTimer();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ @Override
|
|
||||||
+ public void setSpawnedItem(ItemStack itemStack) {
|
|
||||||
+ Preconditions.checkArgument(itemStack != null && !itemStack.getType().isAir(), "spawners cannot spawn air");
|
|
||||||
+ net.minecraft.world.item.ItemStack item = CraftItemStack.asNMSCopy(itemStack);
|
|
||||||
+ CompoundTag compound = new CompoundTag();
|
|
||||||
+ CompoundTag entity = new CompoundTag();
|
|
||||||
+ entity.putString("id", Registry.ENTITY_TYPE.getKey(net.minecraft.world.entity.EntityType.ITEM).toString());
|
|
||||||
+ entity.put("Item", item.save(new CompoundTag()));
|
|
||||||
+ compound.put("Entity", entity);
|
|
||||||
+ compound.putInt("Weight", this.getSnapshotNBT().contains("Weight", CraftMagicNumbers.NBT.TAG_ANY_NUMBER) ? this.getSnapshotNBT().getInt("Weight") : 1);
|
|
||||||
+ this.getSnapshot().getSpawner().setNextSpawnData(new SpawnData(compound));
|
|
||||||
+ this.getSnapshot().getSpawner().spawnPotentials.clear();
|
|
||||||
+ }
|
|
||||||
+ // Paper end
|
|
||||||
}
|
|
40
patches/server/Add-Heightmap-API.patch
Normal file
40
patches/server/Add-Heightmap-API.patch
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||||
|
Date: Tue, 1 Jan 2019 02:22:01 -0800
|
||||||
|
Subject: [PATCH] Add Heightmap API
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||||
|
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
||||||
|
return this.getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - Implement heightmap api
|
||||||
|
+ @Override
|
||||||
|
+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
|
||||||
|
+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas
|
||||||
|
+
|
||||||
|
+ switch (heightmap) {
|
||||||
|
+ case LIGHT_BLOCKING:
|
||||||
|
+ throw new UnsupportedOperationException(); // TODO
|
||||||
|
+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z);
|
||||||
|
+ case ANY:
|
||||||
|
+ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z);
|
||||||
|
+ case SOLID:
|
||||||
|
+ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z);
|
||||||
|
+ case SOLID_OR_LIQUID:
|
||||||
|
+ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z);
|
||||||
|
+ case SOLID_OR_LIQUID_NO_LEAVES:
|
||||||
|
+ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z);
|
||||||
|
+ default:
|
||||||
|
+ throw new UnsupportedOperationException();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Paper end
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public Location getSpawnLocation() {
|
||||||
|
BlockPos spawn = this.world.getSharedSpawnPos();
|
@@ -10,16 +10,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+
|
|
||||||
+ public short keepLoadedRange;
|
+ public short keepLoadedRange;
|
||||||
+ private void keepLoadedRange() {
|
+ private void keepLoadedRange() {
|
||||||
+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
|
+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
|
||||||
+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
|
+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
|
||||||
+ }
|
+ }
|
||||||
}
|
+
|
||||||
|
private boolean getBoolean(String path, boolean def) {
|
||||||
|
config.addDefault("world-settings.default." + path, def);
|
||||||
|
return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path));
|
||||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -33,13 +35,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
- }
|
- }
|
||||||
+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper
|
+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper
|
||||||
|
|
||||||
// WorldServer worldserver = this.E();
|
// WorldServer worldserver = this.F();
|
||||||
this.forceTicks = true;
|
this.forceTicks = true;
|
||||||
// CraftBukkit end
|
// CraftBukkit end
|
||||||
+ if (worldserver.getWorld().getKeepSpawnInMemory()) { // Paper
|
+ if (worldserver.getWorld().getKeepSpawnInMemory()) { // Paper
|
||||||
|
|
||||||
MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location());
|
MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location());
|
||||||
BlockPos blockposition = worldserver.getSpawn();
|
BlockPos blockposition = worldserver.getSharedSpawnPos();
|
||||||
|
|
||||||
worldloadlistener.updateSpawnPos(new ChunkPos(blockposition));
|
worldloadlistener.updateSpawnPos(new ChunkPos(blockposition));
|
||||||
- ServerChunkCache chunkproviderserver = worldserver.getChunkSource();
|
- ServerChunkCache chunkproviderserver = worldserver.getChunkSource();
|
||||||
@@ -51,11 +53,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
-
|
-
|
||||||
- while (chunkproviderserver.getTickingGenerated() != 441) {
|
- while (chunkproviderserver.getTickingGenerated() != 441) {
|
||||||
- // CraftBukkit start
|
- // CraftBukkit start
|
||||||
- // this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
|
- // this.nextTickTime = SystemUtils.getMonotonicMillis() + 10L;
|
||||||
- this.executeModerately();
|
- this.executeModerately();
|
||||||
- // CraftBukkit end
|
- // CraftBukkit end
|
||||||
- }
|
- }
|
||||||
-
|
|
||||||
+ // Paper start - configurable spawn reason
|
+ // Paper start - configurable spawn reason
|
||||||
+ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
|
+ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
|
||||||
+ int radiusChunks = radiusBlocks / 16 + ((radiusBlocks & 15) != 0 ? 1 : 0);
|
+ int radiusChunks = radiusBlocks / 16 + ((radiusBlocks & 15) != 0 ? 1 : 0);
|
||||||
@@ -64,10 +65,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
|
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
|
||||||
+
|
+
|
||||||
+ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
|
+ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
|
||||||
+ //LOGGER.info("Loaded " + chunkproviderserver.b() + " spawn chunks for world " + worldserver.getWorld().getName()); // Paper
|
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
|
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
// this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
|
// this.nextTickTime = SystemUtils.getMonotonicMillis() + 10L;
|
||||||
this.executeModerately();
|
this.executeModerately();
|
||||||
// Iterator iterator = this.worldServer.values().iterator();
|
// Iterator iterator = this.worldServer.values().iterator();
|
||||||
+ }
|
+ }
|
||||||
@@ -87,16 +88,16 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/mai
|
|||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSoundPacket;
|
@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
|
||||||
import net.minecraft.network.protocol.game.DebugPackets;
|
import net.minecraft.network.protocol.game.DebugPackets;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
+import net.minecraft.server.MCUtil;
|
+import net.minecraft.server.MCUtil;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.ServerScoreboard;
|
import net.minecraft.server.ServerScoreboard;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||||
return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::new, "idcounts")).getFreeAuxValueForMap();
|
return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
+ // Paper start - helper function for configurable spawn radius
|
+ // Paper start - helper function for configurable spawn radius
|
||||||
@@ -192,7 +193,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
|
--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
|
||||||
+++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
|
+++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
|
||||||
@@ -0,0 +0,0 @@ public interface ChunkProgressListener {
|
@@ -0,0 +0,0 @@ public interface ChunkProgressListener {
|
||||||
void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status);
|
void start();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
+
|
+
|
||||||
@@ -203,8 +204,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
|
--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
|
||||||
+++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
|
+++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
|
||||||
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
|
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
|
||||||
public class LoggerChunkProgressListener implements ChunkProgressListener {
|
|
||||||
|
|
||||||
|
public class LoggerChunkProgressListener implements ChunkProgressListener {
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
- private final int maxCount;
|
- private final int maxCount;
|
||||||
+ private int maxCount; // Paper - remove final
|
+ private int maxCount; // Paper - remove final
|
||||||
@@ -219,15 +220,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+
|
+
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public void setChunkRadius(int radius) {
|
+ public void setChunkRadius(int radius) {
|
||||||
+ // Paper - copied from above
|
+ // Paper end
|
||||||
int j = radius * 2 + 1;
|
int i = radius * 2 + 1;
|
||||||
|
this.maxCount = i * i;
|
||||||
this.maxCount = j * j;
|
|
||||||
}
|
}
|
||||||
+ // Paper end
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||||
@@ -236,23 +232,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setKeepSpawnInMemory(boolean keepLoaded) {
|
public void setKeepSpawnInMemory(boolean keepLoaded) {
|
||||||
|
- world.keepSpawnInMemory = keepLoaded;
|
||||||
+ // Paper start - Configurable spawn radius
|
+ // Paper start - Configurable spawn radius
|
||||||
+ if (keepLoaded == world.keepSpawnInMemory) {
|
+ if (keepLoaded == world.keepSpawnInMemory) {
|
||||||
+ // do nothing, nothing has changed
|
+ // do nothing, nothing has changed
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
world.keepSpawnInMemory = keepLoaded;
|
+ this.world.keepSpawnInMemory = keepLoaded;
|
||||||
// Grab the worlds spawn chunk
|
// Grab the worlds spawn chunk
|
||||||
- BlockPos chunkcoordinates = this.world.getSpawn();
|
BlockPos chunkcoordinates = this.world.getSharedSpawnPos();
|
||||||
+ BlockPos prevSpawn = this.world.getSpawn();
|
|
||||||
if (keepLoaded) {
|
if (keepLoaded) {
|
||||||
- world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
- this.world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
||||||
+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
|
+ this.world.addTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
|
||||||
} else {
|
} else {
|
||||||
- // TODO: doesn't work well if spawn changed....
|
- // TODO: doesn't work well if spawn changed....
|
||||||
- world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
- this.world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
||||||
+ // TODO: doesn't work well if spawn changed.... // paper - resolved
|
+ // TODO: doesn't work well if spawn changed.... // paper - resolved
|
||||||
+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
|
+ this.world.removeTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
|
||||||
}
|
}
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
}
|
}
|
@@ -8,12 +8,12 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener
|
|||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
|
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||||
|
|
||||||
this.connection.getClass();
|
Objects.requireNonNull(this.connection);
|
||||||
// CraftBukkit - Don't wait
|
// CraftBukkit - Don't wait
|
||||||
- minecraftserver.wrapRunnable(networkmanager::handleDisconnection);
|
- minecraftserver.wrapRunnable(networkmanager::handleDisconnection);
|
||||||
+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper
|
+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void filterTextPacket(T text, Consumer<T> consumer, BiFunction<TextFilter, T, CompletableFuture<Optional<T>>> backingFilterer) {
|
private <T, R> void filterTextPacket(T text, Consumer<R> consumer, BiFunction<TextFilter, T, CompletableFuture<R>> backingFilterer) {
|
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPrimaryThread() {
|
public boolean isPrimaryThread() {
|
||||||
- return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog)
|
- return Thread.currentThread().equals(console.serverThread) || this.console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog)
|
||||||
+ return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly
|
+ return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly
|
||||||
}
|
}
|
||||||
|
|
@@ -15,6 +15,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack);
|
this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack);
|
||||||
- if (!itemstack.isEmpty() && playSound) { // CraftBukkit
|
- if (!itemstack.isEmpty() && playSound) { // CraftBukkit
|
||||||
+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set
|
+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set
|
||||||
this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F);
|
this.playSound(this.getAddItemSound(), 1.0F, 1.0F);
|
||||||
}
|
}
|
||||||
|
|
129
patches/server/Mob-Spawner-API-Enhancements.patch
Normal file
129
patches/server/Mob-Spawner-API-Enhancements.patch
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||||
|
Date: Fri, 19 Apr 2019 12:41:13 -0500
|
||||||
|
Subject: [PATCH] Mob Spawner API Enhancements
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||||
|
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
private static final int EVENT_SPAWN = 1;
|
||||||
|
- private static WeightedRandomList<SpawnData> EMPTY_POTENTIALS = WeightedRandomList.create();
|
||||||
|
+ public static WeightedRandomList<SpawnData> EMPTY_POTENTIALS = WeightedRandomList.create(); // Paper - private->public
|
||||||
|
public int spawnDelay = 20;
|
||||||
|
public WeightedRandomList<SpawnData> spawnPotentials;
|
||||||
|
public SpawnData nextSpawnData;
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
this.spawnPotentials = BaseSpawner.EMPTY_POTENTIALS; // CraftBukkit - SPIGOT-3496, MC-92282
|
||||||
|
}
|
||||||
|
|
||||||
|
- private boolean isNearPlayer(Level world, BlockPos pos) {
|
||||||
|
+ public boolean isNearPlayer(Level world, BlockPos pos) { // Paper private->public
|
||||||
|
return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- private void delay(Level world, BlockPos pos) {
|
||||||
|
+ public void delay(Level world, BlockPos pos) { // Paper private->public
|
||||||
|
if (this.maxSpawnDelay <= this.minSpawnDelay) {
|
||||||
|
this.spawnDelay = this.minSpawnDelay;
|
||||||
|
} else {
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(@Nullable Level world, BlockPos pos, CompoundTag nbt) {
|
||||||
|
+ // Paper start - use larger int if set
|
||||||
|
+ if (nbt.contains("Paper.Delay")) {
|
||||||
|
+ this.spawnDelay = nbt.getInt("Paper.Delay");
|
||||||
|
+ } else {
|
||||||
|
this.spawnDelay = nbt.getShort("Delay");
|
||||||
|
+ }
|
||||||
|
+ // Paper end
|
||||||
|
List<SpawnData> list = Lists.newArrayList();
|
||||||
|
|
||||||
|
if (nbt.contains("SpawnPotentials", 9)) {
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
this.setSpawnData(world, pos, mobspawnerdata);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ // Paper start - use ints if set
|
||||||
|
+ if (nbt.contains("Paper.MinSpawnDelay", 99)) {
|
||||||
|
+ this.minSpawnDelay = nbt.getInt("Paper.MinSpawnDelay");
|
||||||
|
+ this.maxSpawnDelay = nbt.getInt("Paper.MaxSpawnDelay");
|
||||||
|
+ this.spawnCount = nbt.getShort("SpawnCount");
|
||||||
|
+ } else // Paper end
|
||||||
|
if (nbt.contains("MinSpawnDelay", 99)) {
|
||||||
|
- this.minSpawnDelay = nbt.getShort("MinSpawnDelay");
|
||||||
|
- this.maxSpawnDelay = nbt.getShort("MaxSpawnDelay");
|
||||||
|
+ this.minSpawnDelay = nbt.getInt("MinSpawnDelay"); // Paper - short->int
|
||||||
|
+ this.maxSpawnDelay = nbt.getInt("MaxSpawnDelay"); // Paper - short->int
|
||||||
|
this.spawnCount = nbt.getShort("SpawnCount");
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||||
|
if (minecraftkey == null) {
|
||||||
|
return nbt;
|
||||||
|
} else {
|
||||||
|
- nbt.putShort("Delay", (short) this.spawnDelay);
|
||||||
|
- nbt.putShort("MinSpawnDelay", (short) this.minSpawnDelay);
|
||||||
|
- nbt.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay);
|
||||||
|
+ // Paper start
|
||||||
|
+ if (spawnDelay > Short.MAX_VALUE) {
|
||||||
|
+ nbt.putInt("Paper.Delay", this.spawnDelay);
|
||||||
|
+ }
|
||||||
|
+ nbt.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay));
|
||||||
|
+
|
||||||
|
+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) {
|
||||||
|
+ nbt.putInt("Paper.MinSpawnDelay", this.minSpawnDelay);
|
||||||
|
+ nbt.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ nbt.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay));
|
||||||
|
+ nbt.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay));
|
||||||
|
+ // Paper end
|
||||||
|
nbt.putShort("SpawnCount", (short) this.spawnCount);
|
||||||
|
nbt.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities);
|
||||||
|
nbt.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange);
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java
|
||||||
|
@@ -0,0 +0,0 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
|
||||||
|
public void setSpawnRange(int spawnRange) {
|
||||||
|
this.getSnapshot().getSpawner().spawnRange = spawnRange;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // Paper start
|
||||||
|
+ @Override
|
||||||
|
+ public boolean isActivated() {
|
||||||
|
+ return this.getSnapshot().getSpawner().isNearPlayer(world.getHandle(), getPosition());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void resetTimer() {
|
||||||
|
+ this.getSnapshot().getSpawner().delay(world.getHandle(), getPosition());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void setSpawnedItem(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
|
+ Preconditions.checkArgument(itemStack != null && !itemStack.getType().isAir(), "spawners cannot spawn air");
|
||||||
|
+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemStack);
|
||||||
|
+ net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag();
|
||||||
|
+ net.minecraft.nbt.CompoundTag entity = new net.minecraft.nbt.CompoundTag();
|
||||||
|
+ entity.putString("id", net.minecraft.core.Registry.ENTITY_TYPE.getKey(net.minecraft.world.entity.EntityType.ITEM).toString());
|
||||||
|
+ entity.put("Item", item.save(new net.minecraft.nbt.CompoundTag()));
|
||||||
|
+ compound.put("Entity", entity);
|
||||||
|
+ compound.putInt("Weight", this.getSnapshotNBT().contains("Weight", org.bukkit.craftbukkit.util.CraftMagicNumbers.NBT.TAG_ANY_NUMBER) ? this.getSnapshotNBT().getInt("Weight") : 1);
|
||||||
|
+ this.getSnapshot().getSpawner().setSpawnData(world.getHandle(), getPosition(), new net.minecraft.world.level.SpawnData(compound));
|
||||||
|
+ this.getSnapshot().getSpawner().spawnPotentials= net.minecraft.world.level.BaseSpawner.EMPTY_POTENTIALS;
|
||||||
|
+ }
|
||||||
|
+ // Paper end
|
||||||
|
}
|
@@ -14,19 +14,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||||
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
// CraftBukkit start
|
|
||||||
- if (capturedTileEntities.containsKey(blockposition)) {
|
|
||||||
- return capturedTileEntities.get(blockposition);
|
|
||||||
+ BlockEntity tileentity = null; // Paper
|
|
||||||
+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper
|
|
||||||
+ return tileentity; // Paper
|
|
||||||
}
|
|
||||||
// CraftBukkit end
|
|
||||||
|
|
||||||
- BlockEntity tileentity = null;
|
@Nullable
|
||||||
+ //TileEntity tileentity = null; // Paper - move up
|
public BlockEntity getTileEntity(BlockPos blockposition, boolean validate) {
|
||||||
|
- if (this.capturedTileEntities.containsKey(blockposition)) {
|
||||||
if (this.updatingBlockEntities) {
|
- return this.capturedTileEntities.get(blockposition);
|
||||||
tileentity = this.getPendingBlockEntityAt(blockposition);
|
+ // Paper start - Optimize capturedTileEntities lookup
|
||||||
|
+ net.minecraft.world.level.block.entity.BlockEntity blockEntity;
|
||||||
|
+ if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(blockposition)) != null) {
|
||||||
|
+ return blockEntity;
|
||||||
|
}
|
||||||
|
+ // Paper end
|
||||||
|
// CraftBukkit end
|
||||||
|
return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE));
|
||||||
|
}
|
@@ -11,7 +11,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
|
|||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||||
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
|
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ for (int i = 0; i < inv.size(); ++i) {
|
+ for (int i = 0; i < inv.size(); ++i) {
|
||||||
+ ItemStack item = inv.get(i);
|
+ ItemStack item = inv.get(i);
|
||||||
+ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) {
|
+ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) {
|
||||||
+ inv.set(i, ItemStack.NULL_ITEM);
|
+ inv.set(i, ItemStack.EMPTY);
|
||||||
+ continue;
|
+ continue;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (!keep) {
|
+ if (!keep) {
|
||||||
+ inv.set(i, ItemStack.NULL_ITEM);
|
+ inv.set(i, ItemStack.EMPTY);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
@@ -58,13 +58,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
@Override
|
@Override
|
||||||
public void die(DamageSource source) {
|
public void die(DamageSource source) {
|
||||||
boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
|
boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
|
||||||
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
|
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
|
||||||
this.dropExperience();
|
|
||||||
// we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
|
// we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
|
||||||
if (!event.getKeepInventory()) {
|
if (!event.getKeepInventory()) {
|
||||||
- this.inventory.clearContent();
|
this.getInventory().clearContent();
|
||||||
+ // Paper start - replace logic
|
+ // Paper start - replace logic
|
||||||
+ for (NonNullList<ItemStack> inv : this.inventory.getComponents()) {
|
+ for (NonNullList<ItemStack> inv : this.getInventory().getComponents()) {
|
||||||
+ processKeep(event, inv);
|
+ processKeep(event, inv);
|
||||||
+ }
|
+ }
|
||||||
+ processKeep(event, null);
|
+ processKeep(event, null);
|
@@ -16,15 +16,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChunkLoaded(int x, int z) {
|
public boolean isChunkLoaded(int x, int z) {
|
||||||
- return world.getChunkSource().isChunkLoaded(x, z);
|
- return this.world.getChunkSource().isChunkLoaded(x, z);
|
||||||
+ return world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper
|
+ return this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChunkGenerated(int x, int z) {
|
public boolean isChunkGenerated(int x, int z) {
|
||||||
try {
|
try {
|
||||||
- return isChunkLoaded(x, z) || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null;
|
- return this.isChunkLoaded(x, z) || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null;
|
||||||
+ return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed)
|
+ return this.world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed)
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
Reference in New Issue
Block a user