geforkt von Mirrors/Paper
More work
Dieser Commit ist enthalten in:
Ursprung
43227a418f
Commit
8521fdc840
@ -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
Normale Datei
40
patches/server/Add-Heightmap-API.patch
Normale Datei
@ -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
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
|
||||
+ public short keepLoadedRange;
|
||||
+ private void keepLoadedRange() {
|
||||
+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 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
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@ -33,13 +35,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- }
|
||||
+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper
|
||||
|
||||
// WorldServer worldserver = this.E();
|
||||
// WorldServer worldserver = this.F();
|
||||
this.forceTicks = true;
|
||||
// CraftBukkit end
|
||||
+ if (worldserver.getWorld().getKeepSpawnInMemory()) { // Paper
|
||||
|
||||
MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location());
|
||||
BlockPos blockposition = worldserver.getSpawn();
|
||||
BlockPos blockposition = worldserver.getSharedSpawnPos();
|
||||
|
||||
worldloadlistener.updateSpawnPos(new ChunkPos(blockposition));
|
||||
- ServerChunkCache chunkproviderserver = worldserver.getChunkSource();
|
||||
@ -51,11 +53,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
-
|
||||
- while (chunkproviderserver.getTickingGenerated() != 441) {
|
||||
- // CraftBukkit start
|
||||
- // this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
|
||||
- // this.nextTickTime = SystemUtils.getMonotonicMillis() + 10L;
|
||||
- this.executeModerately();
|
||||
- // CraftBukkit end
|
||||
- }
|
||||
-
|
||||
+ // Paper start - configurable spawn reason
|
||||
+ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
|
||||
+ int radiusChunks = radiusBlocks / 16 + ((radiusBlocks & 15) != 0 ? 1 : 0);
|
||||
@ -64,10 +65,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
|
||||
+
|
||||
+ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
|
||||
+ //LOGGER.info("Loaded " + chunkproviderserver.b() + " spawn chunks for world " + worldserver.getWorld().getName()); // Paper
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
// this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
|
||||
// this.nextTickTime = SystemUtils.getMonotonicMillis() + 10L;
|
||||
this.executeModerately();
|
||||
// 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
|
||||
--- 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 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.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerScoreboard;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
@@ -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
|
||||
@ -192,7 +193,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/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 {
|
||||
void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status);
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
+
|
||||
@ -203,8 +204,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/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;
|
||||
public class LoggerChunkProgressListener implements ChunkProgressListener {
|
||||
|
||||
public class LoggerChunkProgressListener implements ChunkProgressListener {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
- private final int maxCount;
|
||||
+ private int maxCount; // Paper - remove final
|
||||
@ -219,15 +220,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+
|
||||
+ @Override
|
||||
+ public void setChunkRadius(int radius) {
|
||||
+ // Paper - copied from above
|
||||
int j = radius * 2 + 1;
|
||||
|
||||
this.maxCount = j * j;
|
||||
+ // Paper end
|
||||
int i = radius * 2 + 1;
|
||||
this.maxCount = i * i;
|
||||
}
|
||||
+ // 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
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@ -236,23 +232,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
|
||||
@Override
|
||||
public void setKeepSpawnInMemory(boolean keepLoaded) {
|
||||
- world.keepSpawnInMemory = keepLoaded;
|
||||
+ // Paper start - Configurable spawn radius
|
||||
+ if (keepLoaded == world.keepSpawnInMemory) {
|
||||
+ // do nothing, nothing has changed
|
||||
+ return;
|
||||
+ }
|
||||
world.keepSpawnInMemory = keepLoaded;
|
||||
+ this.world.keepSpawnInMemory = keepLoaded;
|
||||
// Grab the worlds spawn chunk
|
||||
- BlockPos chunkcoordinates = this.world.getSpawn();
|
||||
+ BlockPos prevSpawn = this.world.getSpawn();
|
||||
BlockPos chunkcoordinates = this.world.getSharedSpawnPos();
|
||||
if (keepLoaded) {
|
||||
- world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
||||
+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
|
||||
- this.world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
|
||||
+ this.world.addTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
|
||||
} else {
|
||||
- // 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
|
||||
+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
|
||||
+ this.world.removeTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
|
||||
}
|
||||
+ // Paper end
|
||||
}
|
@ -8,12 +8,12 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/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
|
||||
- minecraftserver.wrapRunnable(networkmanager::handleDisconnection);
|
||||
+ 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
|
||||
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
|
||||
}
|
||||
|
@ -15,6 +15,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack);
|
||||
- if (!itemstack.isEmpty() && playSound) { // CraftBukkit
|
||||
+ 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
Normale Datei
129
patches/server/Mob-Spawner-API-Enhancements.patch
Normale Datei
@ -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
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -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;
|
||||
+ //TileEntity tileentity = null; // Paper - move up
|
||||
|
||||
if (this.updatingBlockEntities) {
|
||||
tileentity = this.getPendingBlockEntityAt(blockposition);
|
||||
@Nullable
|
||||
public BlockEntity getTileEntity(BlockPos blockposition, boolean validate) {
|
||||
- if (this.capturedTileEntities.containsKey(blockposition)) {
|
||||
- return this.capturedTileEntities.get(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
|
||||
--- a/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) {
|
||||
+ ItemStack item = inv.get(i);
|
||||
+ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) {
|
||||
+ inv.set(i, ItemStack.NULL_ITEM);
|
||||
+ inv.set(i, ItemStack.EMPTY);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+
|
||||
+ if (!keep) {
|
||||
+ inv.set(i, ItemStack.NULL_ITEM);
|
||||
+ inv.set(i, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@ -58,13 +58,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@Override
|
||||
public void die(DamageSource source) {
|
||||
boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
|
||||
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
this.dropExperience();
|
||||
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
|
||||
// we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
|
||||
if (!event.getKeepInventory()) {
|
||||
- this.inventory.clearContent();
|
||||
this.getInventory().clearContent();
|
||||
+ // Paper start - replace logic
|
||||
+ for (NonNullList<ItemStack> inv : this.inventory.getComponents()) {
|
||||
+ for (NonNullList<ItemStack> inv : this.getInventory().getComponents()) {
|
||||
+ processKeep(event, inv);
|
||||
+ }
|
||||
+ processKeep(event, null);
|
@ -16,15 +16,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
- return world.getChunkSource().isChunkLoaded(x, z);
|
||||
+ return world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper
|
||||
- return this.world.getChunkSource().isChunkLoaded(x, z);
|
||||
+ return this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkGenerated(int x, int z) {
|
||||
try {
|
||||
- return isChunkLoaded(x, z) || 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.isChunkLoaded(x, z) || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null;
|
||||
+ 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) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren