mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 23:38:25 +01:00
[1.16] Make it run (#3626)
* She compiles! Also readded the armorstand ticking patch, thanks cat * Update mob goal api * Misc fixes to make it run drop per playing mob spawns for now
This commit is contained in:
parent
fe2a0ea500
commit
67522d46ae
31 changed files with 395 additions and 920 deletions
|
@ -315,7 +315,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ GoalKey<Phantom> PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy"));
|
||||
+ GoalKey<Phantom> PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor"));
|
||||
+ GoalKey<Phantom> PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack"));
|
||||
+ /**
|
||||
+ * @deprecated removed in 1.16
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ GoalKey<PigZombie> ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger"));
|
||||
+ /**
|
||||
+ * @deprecated removed in 1.16
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ GoalKey<PigZombie> ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other"));
|
||||
+ GoalKey<PolarBear> POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players"));
|
||||
+ GoalKey<PolarBear> POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by"));
|
||||
|
@ -424,6 +432,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ GoalKey<Creature> WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water"));
|
||||
+ GoalKey<Dolphin> WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump"));
|
||||
+ GoalKey<Zombie> ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack"));
|
||||
+ GoalKey<Creature> STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem"));
|
||||
+ GoalKey<Mob> UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset"));
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
|
|
|
@ -15,14 +15,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
*/
|
||||
public int getSleepTicks();
|
||||
|
||||
+ /**
|
||||
+ * Gets the Location where the player will spawn at their bed, null if
|
||||
+ * they have not slept in one or their current bed spawn is invalid.
|
||||
+ *
|
||||
+ * @return Bed Spawn Location if bed exists, otherwise null.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Location getBedSpawnLocation();
|
||||
+
|
||||
+ // Paper start - Potential bed api
|
||||
+ /**
|
||||
|
@ -35,22 +27,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ @Nullable
|
||||
+ public Location getPotentialBedLocation();
|
||||
+ // Paper end
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the Location where the player will spawn at their bed.
|
||||
+ *
|
||||
+ * @param location where to set the respawn location
|
||||
+ */
|
||||
+ public void setBedSpawnLocation(@Nullable Location location);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the Location where the player will spawn at their bed.
|
||||
+ *
|
||||
+ * @param location where to set the respawn location
|
||||
+ * @param force whether to forcefully set the respawn location even if a
|
||||
+ * valid bed is not present
|
||||
+ */
|
||||
+ public void setBedSpawnLocation(@Nullable Location location, boolean force);
|
||||
+
|
||||
/**
|
||||
* Attempts to make the entity sleep at the given location.
|
||||
|
|
|
@ -33,7 +33,7 @@ diff --git a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java b/
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java
|
||||
+++ b/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java
|
||||
@@ -0,0 +0,0 @@ import java.util.zip.GZIPOutputStream;
|
||||
@@ -0,0 +0,0 @@ import io.netty.buffer.ByteBufInputStream; // Paper
|
||||
|
||||
public class NBTCompressedStreamTools {
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
craftBlock.getNMS().dropNaturally(world, blockposition, ItemStack.b);
|
||||
}
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.x, blockposition.y, blockposition.z);
|
||||
+ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
|
||||
+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSource().getBukkitEntity()).callEvent())
|
||||
+ continue;
|
||||
+ // Paper end
|
||||
|
|
|
@ -133,6 +133,14 @@ diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/ja
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/LoginListener.java
|
||||
+++ b/src/main/java/net/minecraft/server/LoginListener.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.Waitable;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||
// CraftBukkit end
|
||||
+import io.netty.buffer.Unpooled; // Paper
|
||||
|
||||
public class LoginListener implements PacketLoginInListener {
|
||||
|
||||
@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener {
|
||||
private SecretKey loginKey;
|
||||
private EntityPlayer l;
|
||||
|
@ -148,7 +156,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // Paper start - Velocity support
|
||||
+ if (com.destroystokyo.paper.PaperConfig.velocitySupport) {
|
||||
+ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt();
|
||||
+ PacketLoginOutCustomPayload packet = new PacketLoginOutCustomPayload(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new PacketDataSerializer(io.netty.buffer.Unpooled.EMPTY_BUFFER));
|
||||
+ PacketLoginOutCustomPayload packet = new PacketLoginOutCustomPayload(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new PacketDataSerializer(Unpooled.EMPTY_BUFFER));
|
||||
+ this.networkManager.sendPacket(packet);
|
||||
+ return;
|
||||
+ }
|
||||
|
|
176
Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch
Normal file
176
Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch
Normal file
|
@ -0,0 +1,176 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Riley Park <rileysebastianpark@gmail.com>
|
||||
Date: Wed, 15 Aug 2018 01:26:09 -0700
|
||||
Subject: [PATCH] Allow disabling armour stand ticking
|
||||
|
||||
|
||||
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 armorStandEntityLookups() {
|
||||
armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true);
|
||||
}
|
||||
+
|
||||
+ public boolean armorStandTick = true;
|
||||
+ private void armorStandTick() {
|
||||
+ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick);
|
||||
+ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default");
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
public Vector3f leftLegPose;
|
||||
public Vector3f rightLegPose;
|
||||
public boolean canMove = true; // Paper
|
||||
+ // Paper start - Allow ArmorStands not to tick
|
||||
+ public boolean canTick = true;
|
||||
+ public boolean canTickSetByAPI = false;
|
||||
+ private boolean noTickPoseDirty = false;
|
||||
+ private boolean noTickEquipmentDirty = false;
|
||||
+ // Paper end
|
||||
|
||||
public EntityArmorStand(EntityTypes<? extends EntityArmorStand> entitytypes, World world) {
|
||||
super(entitytypes, world);
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
this.rightArmPose = EntityArmorStand.bt;
|
||||
this.leftLegPose = EntityArmorStand.bu;
|
||||
this.rightLegPose = EntityArmorStand.bv;
|
||||
+ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking
|
||||
this.G = 0.0F;
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
this.armorItems.set(enumitemslot.b(), itemstack);
|
||||
}
|
||||
|
||||
+ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
}
|
||||
|
||||
nbttagcompound.set("Pose", this.B());
|
||||
+ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
this.setBasePlate(nbttagcompound.getBoolean("NoBasePlate"));
|
||||
this.setMarker(nbttagcompound.getBoolean("Marker"));
|
||||
this.noclip = !this.A();
|
||||
+ // Paper start - persist no tick
|
||||
+ if (nbttagcompound.hasKey("Paper.CanTickOverride")) {
|
||||
+ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride");
|
||||
+ this.canTickSetByAPI = true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose");
|
||||
|
||||
this.g(nbttagcompound1);
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Paper start
|
||||
+ if (!this.canTick) {
|
||||
+ if (this.noTickPoseDirty) {
|
||||
+ this.noTickPoseDirty = false;
|
||||
+ this.updatePose();
|
||||
+ }
|
||||
+
|
||||
+ if (this.noTickEquipmentDirty) {
|
||||
+ this.noTickEquipmentDirty = false;
|
||||
+ this.updateEntityEquipment();
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
super.tick();
|
||||
+ // Paper start - Split into separate method
|
||||
+ updatePose();
|
||||
+ }
|
||||
+
|
||||
+ public void updatePose() {
|
||||
+ // Paper end
|
||||
Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c);
|
||||
|
||||
if (!this.headPose.equals(vector3f)) {
|
||||
@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
|
||||
public void setHeadPose(Vector3f vector3f) {
|
||||
this.headPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.c, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setBodyPose(Vector3f vector3f) {
|
||||
this.bodyPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.d, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setLeftArmPose(Vector3f vector3f) {
|
||||
this.leftArmPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.e, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setRightArmPose(Vector3f vector3f) {
|
||||
this.rightArmPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.f, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setLeftLegPose(Vector3f vector3f) {
|
||||
this.leftLegPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.g, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setRightLegPose(Vector3f vector3f) {
|
||||
this.rightLegPose = vector3f;
|
||||
this.datawatcher.set(EntityArmorStand.bo, vector3f);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public Vector3f r() {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityLiving.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
|
||||
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
+ public void updateEntityEquipment() { q(); }; // Paper
|
||||
private void q() {
|
||||
Map<EnumItemSlot, ItemStack> map = this.r();
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
@@ -0,0 +0,0 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
|
||||
public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) {
|
||||
return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canTick() {
|
||||
+ return this.getHandle().canTick;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanTick(final boolean tick) {
|
||||
+ this.getHandle().canTick = tick;
|
||||
+ this.getHandle().canTickSetByAPI = true;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -140,7 +140,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ public final Timing chunkUnloadDataSave;
|
||||
+
|
||||
public WorldTimingsHandler(World server) {
|
||||
String name = server.getWorld().getName() +" - ";
|
||||
String name = ((WorldDataServer) server.getWorldData()).getName() + " - ";
|
||||
|
||||
@@ -0,0 +0,0 @@ public class WorldTimingsHandler {
|
||||
|
||||
|
@ -1574,7 +1574,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // apply fixes
|
||||
+
|
||||
+ try {
|
||||
+ chunkData.chunkData = chunkManager.getChunkData(this.world.getWorldProvider().getDimensionManager(),
|
||||
+ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(),
|
||||
+ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone
|
||||
+ } catch (final Throwable ex) {
|
||||
+ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex);
|
||||
|
@ -1973,7 +1973,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+
|
||||
+ for (int i = 0; i < threads; ++i) {
|
||||
+ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms
|
||||
+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorldData().getName());
|
||||
+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName());
|
||||
+ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1);
|
||||
+ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> {
|
||||
+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable);
|
||||
|
|
|
@ -73,7 +73,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
entityplayer.syncInventory();
|
||||
+ // Paper start - Add to collideRule team if needed
|
||||
+ final Scoreboard scoreboard = this.getServer().getWorldServer(DimensionManager.OVERWORLD).getScoreboard();
|
||||
+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard();
|
||||
+ final ScoreboardTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName);
|
||||
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getScoreboardTeam() == null) {
|
||||
+ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeam);
|
||||
|
@ -88,7 +88,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
+ // Paper start - Remove from collideRule team if needed
|
||||
+ if (this.collideRuleTeamName != null) {
|
||||
+ final Scoreboard scoreBoard = this.server.getWorldServer(DimensionManager.OVERWORLD).getScoreboard();
|
||||
+ final Scoreboard scoreBoard = this.server.getWorldServer(World.OVERWORLD).getScoreboard();
|
||||
+ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName);
|
||||
+ if (entityplayer.getScoreboardTeam() == team && team != null) {
|
||||
+ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team);
|
||||
|
@ -105,7 +105,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
+ // Paper start - Remove collideRule team if it exists
|
||||
+ if (this.collideRuleTeamName != null) {
|
||||
+ final Scoreboard scoreboard = this.getServer().getWorldServer(DimensionManager.OVERWORLD).getScoreboard();
|
||||
+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard();
|
||||
+ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName);
|
||||
+ if (team != null) scoreboard.removeTeam(team);
|
||||
+ }
|
||||
|
|
|
@ -9,8 +9,8 @@ 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 {
|
||||
private void armorStandEntityLookups() {
|
||||
armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true);
|
||||
this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick);
|
||||
log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default");
|
||||
}
|
||||
+
|
||||
+ public int waterOverLavaFlowSpeed;
|
||||
|
|
|
@ -95,8 +95,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
+ // Paper start
|
||||
+ }
|
||||
+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver, String s1) {
|
||||
+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) {
|
||||
+ // Paper end
|
||||
entityplayer.syncInventory();
|
||||
// Paper start - Add to collideRule team if needed
|
||||
final Scoreboard scoreboard = this.getServer().getWorldServer(DimensionManager.OVERWORLD).getScoreboard();
|
||||
final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard();
|
||||
|
|
|
@ -9,8 +9,8 @@ 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 {
|
||||
private void perPlayerMobSpawns() {
|
||||
perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public boolean generateFlatBedrock;
|
||||
|
|
|
@ -10,12 +10,20 @@ diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/j
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NetworkManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
|
||||
@@ -0,0 +0,0 @@ import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
+import io.netty.handler.codec.EncoderException; // Paper
|
||||
import io.netty.handler.timeout.TimeoutException;
|
||||
import io.netty.util.AttributeKey;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
|
||||
+ // Paper start
|
||||
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) {
|
||||
+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) {
|
||||
+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) {
|
||||
+ return;
|
||||
+ } else {
|
||||
|
|
|
@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer);
|
||||
+ suggestEvent.setCancelled(suggestions.isEmpty());
|
||||
+ if (!suggestEvent.callEvent()) return;
|
||||
+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper
|
||||
+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper
|
||||
+ // Paper end
|
||||
});
|
||||
});
|
||||
|
@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1);
|
||||
completions.forEach(builder::suggest);
|
||||
- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join()));
|
||||
+ Suggestions suggestions = builder.buildFuture().join();
|
||||
+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join();
|
||||
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer);
|
||||
+ suggestEvent.setCancelled(suggestions.isEmpty());
|
||||
+ if (!suggestEvent.callEvent()) return;
|
||||
|
|
|
@ -587,8 +587,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
private int lastFoodSent = -99999999;
|
||||
private boolean lastSentSaturationZero = true;
|
||||
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
this.canPickUpLoot = true;
|
||||
this.maxHealthCache = this.getMaxHealth();
|
||||
this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
}
|
||||
+ // Paper start
|
||||
+ public BlockPosition getPointInFront(double inFront) {
|
||||
|
@ -1069,8 +1069,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
if (!this.world.paperConfig.perPlayerMobSpawns) {
|
||||
private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER
|
||||
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
List<CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> list = Lists.newArrayList();
|
||||
int j = chunkcoordintpair.x;
|
||||
|
|
|
@ -251,6 +251,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ bukkitMap.put(EntityZombie.class, Zombie.class);
|
||||
+ bukkitMap.put(EntityZombieHusk.class, Husk.class);
|
||||
+ bukkitMap.put(EntityZombieVillager.class, ZombieVillager.class);
|
||||
+ bukkitMap.put(EntityHoglin.class, Hoglin.class);
|
||||
+ bukkitMap.put(EntityPiglin.class, Piglin.class);
|
||||
+ bukkitMap.put(EntityStrider.class, Strider.class);
|
||||
+ bukkitMap.put(EntityZoglin.class, Zoglin.class);
|
||||
+ }
|
||||
+
|
||||
+ public static String getUsableName(Class<?> clazz) {
|
||||
|
@ -857,10 +861,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.entity.ai;
|
||||
+
|
||||
+import com.destroystokyo.paper.entity.ai.GoalKey;
|
||||
+import com.destroystokyo.paper.entity.ai.MobGoalHelper;
|
||||
+import com.destroystokyo.paper.entity.ai.VanillaGoal;
|
||||
+
|
||||
+import net.minecraft.server.EntityInsentient;
|
||||
+import net.minecraft.server.PathfinderGoal;
|
||||
+
|
||||
|
@ -882,11 +882,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+
|
||||
+ @Test
|
||||
+ public void testKeys() {
|
||||
+ List<GoalKey<?>> deprecated = new ArrayList<>();
|
||||
+ List<GoalKey<?>> keys = new ArrayList<>();
|
||||
+ for (Field field : VanillaGoal.class.getFields()) {
|
||||
+ if (field.getType().equals(GoalKey.class)) {
|
||||
+ try {
|
||||
+ keys.add((GoalKey<?>) field.get(null));
|
||||
+ GoalKey<?> goalKey = (GoalKey<?>) field.get(null);
|
||||
+ if (field.getAnnotation(Deprecated.class) != null) {
|
||||
+ deprecated.add(goalKey);
|
||||
+ } else {
|
||||
+ keys.add(goalKey);
|
||||
+ }
|
||||
+ } catch (IllegalAccessException e) {
|
||||
+ System.out.println("Skipping " + field.getName() + ": " + e.getMessage());
|
||||
+ }
|
||||
|
@ -925,6 +931,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ shouldFail = true;
|
||||
+ }
|
||||
+
|
||||
+ if (deprecated.size() != 0) {
|
||||
+ System.out.println("Deprecated (might want to remove them at some point): ");
|
||||
+ deprecated.forEach(System.out::println);
|
||||
+ }
|
||||
+
|
||||
+ if (shouldFail) Assert.fail("See above");
|
||||
+ }
|
||||
+
|
||||
|
@ -939,12 +950,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ classes = scanResult.getSubclasses("net.minecraft.server.EntityInsentient").loadClasses();
|
||||
+ }
|
||||
+
|
||||
+ boolean shouldFail =false;
|
||||
+ boolean shouldFail = false;
|
||||
+ for (Class<?> nmsClass : classes) {
|
||||
+ Class<? extends Mob> bukkitClass = MobGoalHelper.toBukkitClass((Class<? extends EntityInsentient>) nmsClass);
|
||||
+ if(bukkitClass == null) {
|
||||
+ if (bukkitClass == null) {
|
||||
+ shouldFail = true;
|
||||
+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, "+nmsClass.getSimpleName().replace("Entity","")+".class);");
|
||||
+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
|
|
@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+
|
||||
+ private double getFollowRange(EntityLiving entityliving) {
|
||||
+ AttributeInstance attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE);
|
||||
+ AttributeModifiable attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE);
|
||||
+ return attributeinstance == null ? 16.0D : attributeinstance.getValue();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
|
|
@ -193,6 +193,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
return this.getTemperature() - (f + (float) blockposition.getY() - 64.0F) * 0.05F / 30.0F;
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/server/Biomes.java b/src/main/java/net/minecraft/server/Biomes.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/Biomes.java
|
||||
+++ b/src/main/java/net/minecraft/server/Biomes.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Biomes {
|
||||
private static BiomeBase a(int i, String s, BiomeBase biomebase) {
|
||||
IRegistry.a(IRegistry.BIOME, i, s, biomebase);
|
||||
if (biomebase.b()) {
|
||||
- BiomeBase.d.a(biomebase, IRegistry.BIOME.a(IRegistry.BIOME.get(new MinecraftKey(biomebase.l))));
|
||||
+ BiomeBase.reg.a(biomebase, IRegistry.BIOME.a(IRegistry.BIOME.get(new MinecraftKey(biomebase.l))));
|
||||
}
|
||||
|
||||
return biomebase;
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockStateEnum.java
|
||||
|
@ -403,6 +416,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
this.b();
|
||||
this.g.set(false);
|
||||
}));
|
||||
diff --git a/src/main/java/net/minecraft/server/LootEntryAbstract.java b/src/main/java/net/minecraft/server/LootEntryAbstract.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/LootEntryAbstract.java
|
||||
+++ b/src/main/java/net/minecraft/server/LootEntryAbstract.java
|
||||
@@ -0,0 +0,0 @@ public abstract class LootEntryAbstract implements LootEntryChildren {
|
||||
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
- public final void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) {
|
||||
+ public void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { // Paper - remove final
|
||||
if (!org.apache.commons.lang3.ArrayUtils.isEmpty(t0.d)) {
|
||||
jsonobject.add("conditions", jsonserializationcontext.serialize(t0.d));
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/server/LootItemFunctionExplorationMap.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/LootItemFunctionExplorationMap.java
|
||||
|
@ -473,6 +499,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
default String asString() {
|
||||
return this.toString();
|
||||
diff --git a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java
|
||||
+++ b/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java
|
||||
@@ -0,0 +0,0 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
+import io.netty.buffer.ByteBufInputStream; // Paper
|
||||
|
||||
public class NBTCompressedStreamTools {
|
||||
|
||||
@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools {
|
||||
|
||||
public static NBTTagCompound a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException {
|
||||
// Spigot start
|
||||
- if ( datainput instanceof io.netty.buffer.ByteBufInputStream )
|
||||
+ if ( datainput instanceof ByteBufInputStream) // Paper
|
||||
{
|
||||
datainput = new DataInputStream(new org.spigotmc.LimitStream((InputStream) datainput, nbtreadlimiter));
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/NBTTagList.java b/src/main/java/net/minecraft/server/NBTTagList.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NBTTagList.java
|
||||
|
@ -549,6 +596,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
this.e = 0;
|
||||
this.f = 0;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
@@ -0,0 +0,0 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
private static <F extends StructureGenerator<?>> F a(String s, F f0, WorldGenStage.Decoration worldgenstage_decoration) {
|
||||
StructureGenerator.a.put(s.toLowerCase(Locale.ROOT), f0);
|
||||
StructureGenerator.u.put(f0, worldgenstage_decoration);
|
||||
- return (StructureGenerator) IRegistry.a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), (Object) f0);
|
||||
+ return (F) IRegistry.<StructureGenerator<?>>a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), f0); // Paper - decomp fix
|
||||
}
|
||||
|
||||
public StructureGenerator(Codec<C> codec) {
|
||||
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/SystemUtils.java
|
||||
|
|
|
@ -353,7 +353,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // Paper end - no-tick view distance
|
||||
}
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
completablefuture1.thenAcceptAsync((either) -> {
|
||||
either.mapLeft((chunk) -> {
|
||||
|
@ -373,10 +373,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
return completablefuture1;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
}
|
||||
}
|
||||
|
||||
protected void setViewDistance(int i) {
|
||||
- protected void setViewDistance(int i) {
|
||||
- int j = MathHelper.clamp(i + 1, 3, 33);
|
||||
+ public void setViewDistance(int i) { // Paper - public
|
||||
+ int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32
|
||||
|
||||
if (j != this.viewDistance) {
|
||||
|
|
|
@ -361,6 +361,14 @@ diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ServerConnection.java
|
||||
+++ b/src/main/java/net/minecraft/server/ServerConnection.java
|
||||
@@ -0,0 +0,0 @@ import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.ServerSocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
+import io.netty.handler.flush.FlushConsolidationHandler; // Paper
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
@@ -0,0 +0,0 @@ public class ServerConnection {
|
||||
private final List<NetworkManager> connectedChannels = Collections.synchronizedList(Lists.newArrayList());
|
||||
// Paper start - prevent blocking on adding a new network manager while the server is ticking
|
||||
|
@ -378,7 +386,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
;
|
||||
}
|
||||
|
||||
+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new io.netty.handler.flush.FlushConsolidationHandler()); // Paper
|
||||
+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper
|
||||
channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND));
|
||||
NetworkManager networkmanager = new NetworkManager(EnumProtocolDirection.SERVERBOUND);
|
||||
|
||||
|
|
|
@ -42,3 +42,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
builder.add(Pair.of(registrymaterials.c(t0).get(), t0));
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class RegistryMaterials<T> extends IRegistryWritable<T> {
|
||||
|
||||
registrymaterials.bb.entrySet().stream().filter((entry) -> {
|
||||
return registrymaterials.c((ResourceKey) entry.getKey());
|
||||
- }).forEach(com_google_common_collect_immutablemap_builder::put);
|
||||
+ }).forEach(entry1 -> com_google_common_collect_immutablemap_builder.put((java.util.Map.Entry<? extends net.minecraft.server.ResourceKey<T>,? extends T>) entry1)); // Paper - compiler fix (expand method reference + add cast)
|
||||
return com_google_common_collect_immutablemap_builder.build();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,6 +4,43 @@ Date: Sun, 8 Mar 2015 22:55:25 -0600
|
|||
Subject: [PATCH] Optimize TileEntity Ticking
|
||||
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
@@ -0,0 +0,0 @@ public class TimingsExport extends Thread {
|
||||
pair("end", System.currentTimeMillis() / 1000),
|
||||
pair("online-mode", Bukkit.getServer().getOnlineMode()),
|
||||
pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000),
|
||||
- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> {
|
||||
+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().e(), pack -> {
|
||||
// Don't feel like obf helper'ing these, non fatal if its temp missed.
|
||||
return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true)));
|
||||
}))
|
||||
@@ -0,0 +0,0 @@ public class TimingsExport extends Thread {
|
||||
);
|
||||
|
||||
parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> {
|
||||
- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null;
|
||||
- return pair(world.getWorldData().getName(), createObject(
|
||||
+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null;
|
||||
+ return pair(world.getWorld().getName(), createObject(
|
||||
pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> {
|
||||
return pair(rule, world.getWorld().getGameRuleValue(rule));
|
||||
})),
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockChest.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockChest.java
|
||||
@@ -0,0 +0,0 @@ public class BlockChest extends BlockChestAbstract<TileEntityChest> implements I
|
||||
|
||||
public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING;
|
||||
public static final BlockStateEnum<BlockPropertyChestType> c = BlockProperties.aF;
|
||||
- public static final BlockStateBoolean d = BlockProperties.C;
|
||||
+ public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER
|
||||
protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D);
|
||||
protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D);
|
||||
protected static final VoxelShape g = Block.a(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D);
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
|
@ -70,7 +107,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
}
|
||||
|
||||
private void a(SoundEffect soundeffect) {
|
||||
+ if (!this.getBlock().hasProperty(BlockChest.c)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074
|
||||
+ if (!this.getBlock().get(BlockChest.waterlogged())) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074
|
||||
BlockPropertyChestType blockpropertychesttype = (BlockPropertyChestType) this.getBlock().get(BlockChest.c);
|
||||
|
||||
if (blockpropertychesttype != BlockPropertyChestType.LEFT) {
|
||||
|
|
|
@ -290,11 +290,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
}
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
return entityPlayer.mobCounts[enumCreatureType.ordinal()];
|
||||
}
|
||||
|
||||
+ private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER
|
||||
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
||||
double d0 = (double) (chunkcoordintpair.x * 16 + 8);
|
||||
|
|
|
@ -564,7 +564,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
// Spigot end
|
||||
+ // Paper start
|
||||
+ try {
|
||||
+ com.destroystokyo.paper.PaperConfig.init((File) options.valueOf("paper-settings"));
|
||||
+ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings"));
|
||||
+ } catch (Exception e) {
|
||||
+ DedicatedServer.LOGGER.error("Unable to load server configuration", e);
|
||||
+ return false;
|
||||
|
|
|
@ -43,7 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ void a(EntityLiving entityliving, float f); default void rangedAttack(EntityLiving entityliving, float f) { a(entityliving, f); } // Paper - OBFHELPER
|
||||
+
|
||||
+ // - see EntitySkeletonAbstract melee goal
|
||||
+ void q(boolean flag); default void setChargingAttack(boolean charging) { q(charging); }; // Paper
|
||||
+ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
|
|
|
@ -17,10 +17,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ @Override
|
||||
+ public void remove() {
|
||||
+ super.remove();
|
||||
+ if (getHandle().owner != null) {
|
||||
+ getHandle().owner.hookedFish = null;
|
||||
+ if (getHandle().getOwner() != null) {
|
||||
+ getHandle().getOwner().hookedFish = null;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+
|
||||
}
|
||||
|
|
|
@ -4,6 +4,19 @@ Date: Tue, 27 Dec 2016 15:02:42 -0500
|
|||
Subject: [PATCH] String based Action Bar API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/SystemUtils.java
|
||||
+++ b/src/main/java/net/minecraft/server/SystemUtils.java
|
||||
@@ -0,0 +0,0 @@ public class SystemUtils {
|
||||
private static final ExecutorService e = a("Main");
|
||||
private static final ExecutorService f = n();
|
||||
public static LongSupplier a = System::nanoTime;
|
||||
- public static final UUID b = new UUID(0L, 0L);
|
||||
+ public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> a() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
|
@ -15,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ @Override
|
||||
+ public void sendActionBar(String message) {
|
||||
+ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return;
|
||||
+ getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new net.minecraft.server.ChatComponentText(message), net.minecraft.server.ChatMessageType.GAME_INFO));
|
||||
+ getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new net.minecraft.server.ChatComponentText(message), net.minecraft.server.ChatMessageType.GAME_INFO, SystemUtils.getNullUUID()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
|
|
|
@ -551,6 +551,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+package co.aikar.timings;
|
||||
+
|
||||
+import net.minecraft.server.World;
|
||||
+import net.minecraft.server.WorldDataServer;
|
||||
+import net.minecraft.server.WorldServer;
|
||||
+
|
||||
+/**
|
||||
|
@ -608,7 +609,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ public final Timing miscMobSpawning;
|
||||
+
|
||||
+ public WorldTimingsHandler(World server) {
|
||||
+ String name = server.getWorld().getName() +" - ";
|
||||
+ String name = ((WorldDataServer) server.getWorldData()).getName() + " - ";
|
||||
+
|
||||
+ mobSpawn = Timings.ofSafe(name + "mobSpawn");
|
||||
+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload");
|
||||
|
@ -663,7 +664,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+
|
||||
+ public static Timing getTickList(WorldServer worldserver, String timingsType) {
|
||||
+ return Timings.ofSafe(worldserver.getWorld().getName() + " - Scheduled " + timingsType);
|
||||
+ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
|
|
|
@ -117,9 +117,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
// Paper end
|
||||
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
this.l = supplier;
|
||||
this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper
|
||||
this.setViewDistance(i);
|
||||
this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
|
||||
+ // Paper start - use distance map to optimise entity tracker
|
||||
+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length];
|
||||
+ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length];
|
||||
|
@ -161,7 +161,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // Paper end - use distance map to optimise entity tracker
|
||||
}
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
}
|
||||
|
||||
|
|
|
@ -9,19 +9,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/server/EntityVillager.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
|
||||
@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
|
||||
|
||||
return optional.isPresent() ? i - (Long) optional.get() < 24000L : false;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public int getRestocksToday(){
|
||||
+ return this.bL;
|
||||
+ }
|
||||
+ public void setRestocksToday(int restocksToday){
|
||||
+ this.bL = restocksToday;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
private long bH;
|
||||
private int bI;
|
||||
private long bJ;
|
||||
- private int bK;
|
||||
+ private int bK; public int getRestocksToday(){ return this.bK; } public void setRestocksToday(int restocksToday){ this.bK = restocksToday; } // Paper OBFHELPER
|
||||
private long bL;
|
||||
private boolean bM;
|
||||
private static final ImmutableList<MemoryModuleType<?>> bN = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.INTERACTABLE_DOORS, MemoryModuleType.OPENED_DOORS, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_LAST_SEEN_TIME});
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
||||
|
|
|
@ -40,15 +40,6 @@ diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/j
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
player.needsChunkCenterUpdate = false;
|
||||
player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ));
|
||||
}
|
||||
- PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded
|
||||
+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[10], false, true); // unloaded, loaded
|
||||
},
|
||||
(EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
||||
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,825 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kickash32 <kickash32@gmail.com>
|
||||
Date: Mon, 19 Aug 2019 01:27:58 +0500
|
||||
Subject: [PATCH] implement optional per player mob spawns
|
||||
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java
|
||||
+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java
|
||||
@@ -0,0 +0,0 @@ public class WorldTimingsHandler {
|
||||
|
||||
|
||||
public final Timing miscMobSpawning;
|
||||
+ public final Timing playerMobDistanceMapUpdate;
|
||||
|
||||
public final Timing poiUnload;
|
||||
public final Timing chunkUnload;
|
||||
@@ -0,0 +0,0 @@ public class WorldTimingsHandler {
|
||||
|
||||
|
||||
miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc");
|
||||
+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update");
|
||||
|
||||
poiUnload = Timings.ofSafe(name + "Chunk unload - POI");
|
||||
chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk");
|
||||
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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public boolean perPlayerMobSpawns = false;
|
||||
+ private void perPlayerMobSpawns() {
|
||||
+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.util;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
+import net.minecraft.server.ChunkCoordIntPair;
|
||||
+import net.minecraft.server.EntityPlayer;
|
||||
+import net.minecraft.server.SectionPosition;
|
||||
+import org.spigotmc.AsyncCatcher;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+
|
||||
+/** @author Spottedleaf */
|
||||
+public final class PlayerMobDistanceMap {
|
||||
+
|
||||
+ private static final PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>();
|
||||
+
|
||||
+ private final Map<EntityPlayer, SectionPosition> players = new HashMap<>();
|
||||
+ // we use linked for better iteration.
|
||||
+ private final Long2ObjectOpenHashMap<PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer>> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f);
|
||||
+ private int viewDistance;
|
||||
+
|
||||
+ private final PooledHashSets<EntityPlayer> pooledHashSets = new PooledHashSets<>();
|
||||
+
|
||||
+ public PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> getPlayersInRange(final ChunkCoordIntPair chunkPos) {
|
||||
+ return this.getPlayersInRange(chunkPos.x, chunkPos.z);
|
||||
+ }
|
||||
+
|
||||
+ public PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> getPlayersInRange(final int chunkX, final int chunkZ) {
|
||||
+ return this.playerMap.getOrDefault(ChunkCoordIntPair.pair(chunkX, chunkZ), EMPTY_SET);
|
||||
+ }
|
||||
+
|
||||
+ public void update(final List<EntityPlayer> currentPlayers, final int newViewDistance) {
|
||||
+ AsyncCatcher.catchOp("Distance map update");
|
||||
+ final ObjectLinkedOpenHashSet<EntityPlayer> gone = new ObjectLinkedOpenHashSet<>(this.players.keySet());
|
||||
+
|
||||
+ final int oldViewDistance = this.viewDistance;
|
||||
+ this.viewDistance = newViewDistance;
|
||||
+
|
||||
+ for (final EntityPlayer player : currentPlayers) {
|
||||
+ if (player.isSpectator() || !player.affectsSpawning) {
|
||||
+ continue; // will be left in 'gone' (or not added at all)
|
||||
+ }
|
||||
+
|
||||
+ gone.remove(player);
|
||||
+
|
||||
+ final SectionPosition newPosition = player.getPlayerMapSection();
|
||||
+ final SectionPosition oldPosition = this.players.put(player, newPosition);
|
||||
+
|
||||
+ if (oldPosition == null) {
|
||||
+ this.addNewPlayer(player, newPosition, newViewDistance);
|
||||
+ } else {
|
||||
+ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance);
|
||||
+ }
|
||||
+ //this.validatePlayer(player, newViewDistance); // debug only
|
||||
+ }
|
||||
+
|
||||
+ for (final EntityPlayer player : gone) {
|
||||
+ final SectionPosition oldPosition = this.players.remove(player);
|
||||
+ if (oldPosition != null) {
|
||||
+ this.removePlayer(player, oldPosition, oldViewDistance);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // expensive op, only for debug
|
||||
+ private void validatePlayer(final EntityPlayer player, final int viewDistance) {
|
||||
+ int entiesGot = 0;
|
||||
+ int expectedEntries = (2 * viewDistance + 1);
|
||||
+ expectedEntries *= expectedEntries;
|
||||
+
|
||||
+ final SectionPosition currPosition = player.getPlayerMapSection();
|
||||
+
|
||||
+ final int centerX = currPosition.getX();
|
||||
+ final int centerZ = currPosition.getZ();
|
||||
+
|
||||
+ for (final Long2ObjectLinkedOpenHashMap.Entry<PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer>> entry : this.playerMap.long2ObjectEntrySet()) {
|
||||
+ final long key = entry.getLongKey();
|
||||
+ final PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> map = entry.getValue();
|
||||
+
|
||||
+ if (map.referenceCount == 0) {
|
||||
+ throw new IllegalStateException("Invalid map");
|
||||
+ }
|
||||
+
|
||||
+ if (map.set.contains(player)) {
|
||||
+ ++entiesGot;
|
||||
+
|
||||
+ final int chunkX = ChunkCoordIntPair.getX(key);
|
||||
+ final int chunkZ = ChunkCoordIntPair.getZ(key);
|
||||
+
|
||||
+ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ));
|
||||
+
|
||||
+ if (dist > viewDistance) {
|
||||
+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (entiesGot != expectedEntries) {
|
||||
+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void addPlayerTo(final EntityPlayer player, final int chunkX, final int chunkZ) {
|
||||
+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> players) -> {
|
||||
+ if (players == null) {
|
||||
+ return player.cachedSingleMobDistanceMap;
|
||||
+ } else {
|
||||
+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private void removePlayerFrom(final EntityPlayer player, final int chunkX, final int chunkZ) {
|
||||
+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> players) -> {
|
||||
+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private void updatePlayer(final EntityPlayer player, final SectionPosition oldPosition, final SectionPosition newPosition, final int oldViewDistance, final int newViewDistance) {
|
||||
+ final int toX = newPosition.getX();
|
||||
+ final int toZ = newPosition.getZ();
|
||||
+ final int fromX = oldPosition.getX();
|
||||
+ final int fromZ = oldPosition.getZ();
|
||||
+
|
||||
+ final int dx = toX - fromX;
|
||||
+ final int dz = toZ - fromZ;
|
||||
+
|
||||
+ final int totalX = Math.abs(fromX - toX);
|
||||
+ final int totalZ = Math.abs(fromZ - toZ);
|
||||
+
|
||||
+ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) {
|
||||
+ // teleported?
|
||||
+ this.removePlayer(player, oldPosition, oldViewDistance);
|
||||
+ this.addNewPlayer(player, newPosition, newViewDistance);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // x axis is width
|
||||
+ // z axis is height
|
||||
+ // right refers to the x axis of where we moved
|
||||
+ // top refers to the z axis of where we moved
|
||||
+
|
||||
+ if (oldViewDistance == newViewDistance) {
|
||||
+ // same view distance
|
||||
+
|
||||
+ // used for relative positioning
|
||||
+ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise
|
||||
+ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise
|
||||
+
|
||||
+ // The area excluded by overlapping the two view distance squares creates four rectangles:
|
||||
+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section
|
||||
+ // and on the right the "added" section.
|
||||
+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually
|
||||
+ // exclusive to the regions they surround.
|
||||
+
|
||||
+ // 4 points of the rectangle
|
||||
+ int maxX; // exclusive
|
||||
+ int minX; // inclusive
|
||||
+ int maxZ; // exclusive
|
||||
+ int minZ; // inclusive
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle right addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX + (oldViewDistance * right) + right; // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addPlayerTo(player, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle up addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = toX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addPlayerTo(player, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle left removal
|
||||
+
|
||||
+ maxX = toX - (oldViewDistance * right); // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removePlayerFrom(player, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle down removal
|
||||
+
|
||||
+ maxX = fromX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ - (oldViewDistance * up); // exclusive
|
||||
+ minZ = fromZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removePlayerFrom(player, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ // different view distance
|
||||
+ // for now :)
|
||||
+ this.removePlayer(player, oldPosition, oldViewDistance);
|
||||
+ this.addNewPlayer(player, newPosition, newViewDistance);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) {
|
||||
+ final int x = position.getX();
|
||||
+ final int z = position.getZ();
|
||||
+
|
||||
+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) {
|
||||
+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) {
|
||||
+ this.removePlayerFrom(player, x + xoff, z + zoff);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) {
|
||||
+ final int x = position.getX();
|
||||
+ final int z = position.getZ();
|
||||
+
|
||||
+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) {
|
||||
+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) {
|
||||
+ this.addPlayerTo(player, x + xoff, z + zoff);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.util;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
+import java.lang.ref.WeakReference;
|
||||
+import java.util.Iterator;
|
||||
+
|
||||
+/** @author Spottedleaf */
|
||||
+public class PooledHashSets<E> {
|
||||
+
|
||||
+ // we really want to avoid that equals() check as much as possible...
|
||||
+ protected final Object2ObjectOpenHashMap<PooledObjectLinkedOpenHashSet<E>, PooledObjectLinkedOpenHashSet<E>> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f);
|
||||
+
|
||||
+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet<E> current) {
|
||||
+ if (current.referenceCount == 0) {
|
||||
+ throw new IllegalStateException("Cannot decrement reference count for " + current);
|
||||
+ }
|
||||
+ if (current.referenceCount == -1 || --current.referenceCount > 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.mapPool.remove(current);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> findMapWith(final PooledObjectLinkedOpenHashSet<E> current, final E object) {
|
||||
+ final PooledObjectLinkedOpenHashSet<E> cached = current.getAddCache(object);
|
||||
+
|
||||
+ if (cached != null) {
|
||||
+ if (cached.referenceCount != -1) {
|
||||
+ ++cached.referenceCount;
|
||||
+ }
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+
|
||||
+ return cached;
|
||||
+ }
|
||||
+
|
||||
+ if (!current.add(object)) {
|
||||
+ return current;
|
||||
+ }
|
||||
+
|
||||
+ // we use get/put since we use a different key on put
|
||||
+ PooledObjectLinkedOpenHashSet<E> ret = this.mapPool.get(current);
|
||||
+
|
||||
+ if (ret == null) {
|
||||
+ ret = new PooledObjectLinkedOpenHashSet<>(current);
|
||||
+ current.remove(object);
|
||||
+ this.mapPool.put(ret, ret);
|
||||
+ ret.referenceCount = 1;
|
||||
+ } else {
|
||||
+ if (ret.referenceCount != -1) {
|
||||
+ ++ret.referenceCount;
|
||||
+ }
|
||||
+ current.remove(object);
|
||||
+ }
|
||||
+
|
||||
+ current.updateAddCache(object, ret);
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ // rets null if current.size() == 1
|
||||
+ public PooledObjectLinkedOpenHashSet<E> findMapWithout(final PooledObjectLinkedOpenHashSet<E> current, final E object) {
|
||||
+ if (current.set.size() == 1) {
|
||||
+ decrementReferenceCount(current);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> cached = current.getRemoveCache(object);
|
||||
+
|
||||
+ if (cached != null) {
|
||||
+ if (cached.referenceCount != -1) {
|
||||
+ ++cached.referenceCount;
|
||||
+ }
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+
|
||||
+ return cached;
|
||||
+ }
|
||||
+
|
||||
+ if (!current.remove(object)) {
|
||||
+ return current;
|
||||
+ }
|
||||
+
|
||||
+ // we use get/put since we use a different key on put
|
||||
+ PooledObjectLinkedOpenHashSet<E> ret = this.mapPool.get(current);
|
||||
+
|
||||
+ if (ret == null) {
|
||||
+ ret = new PooledObjectLinkedOpenHashSet<>(current);
|
||||
+ current.add(object);
|
||||
+ this.mapPool.put(ret, ret);
|
||||
+ ret.referenceCount = 1;
|
||||
+ } else {
|
||||
+ if (ret.referenceCount != -1) {
|
||||
+ ++ret.referenceCount;
|
||||
+ }
|
||||
+ current.add(object);
|
||||
+ }
|
||||
+
|
||||
+ current.updateRemoveCache(object, ret);
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ public static final class PooledObjectLinkedOpenHashSet<E> implements Iterable<E> {
|
||||
+
|
||||
+ private static final WeakReference NULL_REFERENCE = new WeakReference(null);
|
||||
+
|
||||
+ final ObjectLinkedOpenHashSet<E> set;
|
||||
+ int referenceCount; // -1 if special
|
||||
+ int hash; // optimize hashcode
|
||||
+
|
||||
+ // add cache
|
||||
+ WeakReference<E> lastAddObject = NULL_REFERENCE;
|
||||
+ WeakReference<PooledObjectLinkedOpenHashSet<E>> lastAddMap = NULL_REFERENCE;
|
||||
+
|
||||
+ // remove cache
|
||||
+ WeakReference<E> lastRemoveObject = NULL_REFERENCE;
|
||||
+ WeakReference<PooledObjectLinkedOpenHashSet<E>> lastRemoveMap = NULL_REFERENCE;
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet() {
|
||||
+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f);
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet(final E single) {
|
||||
+ this();
|
||||
+ this.referenceCount = -1;
|
||||
+ this.add(single);
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet<E> other) {
|
||||
+ this.set = other.set.clone();
|
||||
+ this.hash = other.hash;
|
||||
+ }
|
||||
+
|
||||
+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java
|
||||
+ // generated by https://github.com/skeeto/hash-prospector
|
||||
+ static int hash0(int x) {
|
||||
+ x *= 0x36935555;
|
||||
+ x ^= x >>> 16;
|
||||
+ return x;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> getAddCache(final E element) {
|
||||
+ final E currentAdd = this.lastAddObject.get();
|
||||
+
|
||||
+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> map = this.lastAddMap.get();
|
||||
+ if (map == null || map.referenceCount == 0) {
|
||||
+ // we need to ret null if ref count is zero as calling code will assume the map is in use
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return map;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> getRemoveCache(final E element) {
|
||||
+ final E currentRemove = this.lastRemoveObject.get();
|
||||
+
|
||||
+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> map = this.lastRemoveMap.get();
|
||||
+ if (map == null || map.referenceCount == 0) {
|
||||
+ // we need to ret null if ref count is zero as calling code will assume the map is in use
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return map;
|
||||
+ }
|
||||
+
|
||||
+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet<E> map) {
|
||||
+ this.lastAddObject = new WeakReference<>(element);
|
||||
+ this.lastAddMap = new WeakReference<>(map);
|
||||
+ }
|
||||
+
|
||||
+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet<E> map) {
|
||||
+ this.lastRemoveObject = new WeakReference<>(element);
|
||||
+ this.lastRemoveMap = new WeakReference<>(map);
|
||||
+ }
|
||||
+
|
||||
+ boolean add(final E element) {
|
||||
+ boolean added = this.set.add(element);
|
||||
+
|
||||
+ if (added) {
|
||||
+ this.hash += hash0(element.hashCode());
|
||||
+ }
|
||||
+
|
||||
+ return added;
|
||||
+ }
|
||||
+
|
||||
+ boolean remove(Object element) {
|
||||
+ boolean removed = this.set.remove(element);
|
||||
+
|
||||
+ if (removed) {
|
||||
+ this.hash -= hash0(element.hashCode());
|
||||
+ }
|
||||
+
|
||||
+ return removed;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Iterator<E> iterator() {
|
||||
+ return this.set.iterator();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.hash;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object other) {
|
||||
+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (this.referenceCount == 0) {
|
||||
+ return other == this;
|
||||
+ } else {
|
||||
+ if (other == this) {
|
||||
+ // Unfortunately we are never equal to our own instance while in use!
|
||||
+ return false;
|
||||
+ }
|
||||
+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " +
|
||||
+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
this.world.getMethodProfiler().enter("naturalSpawnCount");
|
||||
this.world.timings.countNaturalMobs.startTiming(); // Paper - timings
|
||||
int l = this.chunkMapDistance.b();
|
||||
- SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.z(), this::a);
|
||||
+ // Paper start - per player mob spawning
|
||||
+ SpawnerCreature.d spawnercreature_d; // moved down
|
||||
+ if (this.playerChunkMap.playerMobDistanceMap != null) {
|
||||
+ // update distance map
|
||||
+ this.world.timings.playerMobDistanceMapUpdate.startTiming();
|
||||
+ this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance);
|
||||
+ this.world.timings.playerMobDistanceMapUpdate.stopTiming();
|
||||
+ // re-set mob counts
|
||||
+ for (EntityPlayer player : this.world.players) {
|
||||
+ Arrays.fill(player.mobCounts, 0);
|
||||
+ }
|
||||
+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.z(), this::a, true);
|
||||
+ } else {
|
||||
+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.z(), this::a, false);
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
|
||||
|
||||
this.p = spawnercreature_d;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
public boolean queueHealthUpdatePacket = false;
|
||||
public net.minecraft.server.PacketPlayOutUpdateHealth queuedHealthUpdatePacket;
|
||||
// Paper end
|
||||
+ // Paper start - mob spawning rework
|
||||
+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length;
|
||||
+ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper
|
||||
+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> cachedSingleMobDistanceMap;
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public String displayName;
|
||||
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
this.displayName = this.getName();
|
||||
this.canPickUpLoot = true;
|
||||
this.maxHealthCache = this.getMaxHealth();
|
||||
+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
}
|
||||
|
||||
// Yes, this doesn't match Vanilla, but it's the best we can do for now.
|
||||
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
|
||||
}
|
||||
|
||||
+ public final SectionPosition getPlayerMapSection() { return this.N(); } // Paper - OBFHELPER
|
||||
public SectionPosition N() {
|
||||
return this.cq;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
@@ -0,0 +0,0 @@ public class EntityTypes<T extends Entity> {
|
||||
return this.bk;
|
||||
}
|
||||
|
||||
+ public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER
|
||||
public EnumCreatureType e() {
|
||||
return this.bf;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities;
|
||||
private final Long2ByteMap z;
|
||||
private final Queue<Runnable> A; private final Queue<Runnable> getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER
|
||||
- private int viewDistance;
|
||||
+ int viewDistance; // Paper - private -> package private
|
||||
+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper
|
||||
|
||||
// CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
||||
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
this.l = supplier;
|
||||
this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper
|
||||
this.setViewDistance(i);
|
||||
+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
|
||||
+ }
|
||||
+
|
||||
+ public void updatePlayerMobTypeMap(Entity entity) {
|
||||
+ if (!this.world.paperConfig.perPlayerMobSpawns) {
|
||||
+ return;
|
||||
+ }
|
||||
+ int chunkX = (int)Math.floor(entity.locX()) >> 4;
|
||||
+ int chunkZ = (int)Math.floor(entity.locZ()) >> 4;
|
||||
+ int index = entity.getEntityType().getEnumCreatureType().ordinal();
|
||||
+
|
||||
+ for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) {
|
||||
+ ++player.mobCounts[index];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) {
|
||||
+ return entityPlayer.mobCounts[enumCreatureType.ordinal()];
|
||||
}
|
||||
|
||||
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
||||
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
});
|
||||
|
||||
public static SpawnerCreature.d a(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b) {
|
||||
+ // Paper start - add countMobs parameter
|
||||
+ return countMobs(i, iterable, spawnercreature_b, false);
|
||||
+ }
|
||||
+ public static SpawnerCreature.d countMobs(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) {
|
||||
+ // Paper end - add countMobs parameter
|
||||
SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities();
|
||||
Object2IntOpenHashMap<EnumCreatureType> object2intopenhashmap = new Object2IntOpenHashMap();
|
||||
Iterator iterator = iterable.iterator();
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
}
|
||||
|
||||
object2intopenhashmap.addTo(enumcreaturetype, 1);
|
||||
+ // Paper start
|
||||
+ if (countMobs) {
|
||||
+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards
|
||||
+ int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype);
|
||||
+ int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b;
|
||||
+ int difference = k1 - currEntityCount;
|
||||
+
|
||||
+ if (worldserver.paperConfig.perPlayerMobSpawns) {
|
||||
+ int minDiff = Integer.MAX_VALUE;
|
||||
+ for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) {
|
||||
+ minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff);
|
||||
+ }
|
||||
+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ if (difference > 0) { // Paper
|
||||
if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) {
|
||||
// CraftBukkit end
|
||||
- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> {
|
||||
+ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> {
|
||||
return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess);
|
||||
}, (entityinsentient, ichunkaccess) -> {
|
||||
spawnercreature_d.a(entityinsentient, ichunkaccess);
|
||||
+ },
|
||||
+ limit, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null);
|
||||
+ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, 0, (keyInMap, valueInMap) -> {
|
||||
+ return Integer.valueOf(spawnCount + valueInMap.intValue());
|
||||
});
|
||||
+ } // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
}
|
||||
|
||||
public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) {
|
||||
+ // Paper start - add parameters and int ret type
|
||||
+ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null);
|
||||
+ }
|
||||
+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer<Entity> trackEntity) {
|
||||
+ // Paper end - add parameters and int ret type
|
||||
BlockPosition blockposition = getRandomPosition(worldserver, chunk);
|
||||
|
||||
if (blockposition.getY() >= 1) {
|
||||
- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a);
|
||||
+ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity);
|
||||
}
|
||||
+ return 0; // Paper
|
||||
}
|
||||
|
||||
public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) {
|
||||
+ // Paper start - add maxSpawns parameter and return spawned mobs
|
||||
+ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null);
|
||||
+ }
|
||||
+ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer<Entity> trackEntity) {
|
||||
+ // Paper end - add maxSpawns parameter and return spawned mobs
|
||||
StructureManager structuremanager = worldserver.getStructureManager();
|
||||
ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
|
||||
int i = blockposition.getY();
|
||||
IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn
|
||||
+ int j = 0; // Paper - moved up
|
||||
|
||||
if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn
|
||||
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
|
||||
- int j = 0;
|
||||
+ // Paper - moved up
|
||||
int k = 0;
|
||||
|
||||
while (k < 3) {
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
// Paper start
|
||||
Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomebase_biomemeta, blockposition_mutableblockposition, d2);
|
||||
if (doSpawning == null) {
|
||||
- return;
|
||||
+ return j; // Paper
|
||||
}
|
||||
if (doSpawning.booleanValue() && spawnercreature_c.test(biomebase_biomemeta.c, blockposition_mutableblockposition, ichunkaccess)) { // Paper end
|
||||
EntityInsentient entityinsentient = a(worldserver, biomebase_biomemeta.c);
|
||||
|
||||
if (entityinsentient == null) {
|
||||
- return;
|
||||
+ return j; // Paper
|
||||
}
|
||||
|
||||
entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F);
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
groupdataentity = entityinsentient.prepare(worldserver, worldserver.getDamageScaler(entityinsentient.getChunkCoordinates()), EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null);
|
||||
// CraftBukkit start
|
||||
if (worldserver.addEntity(entityinsentient, SpawnReason.NATURAL)) {
|
||||
- ++j;
|
||||
+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned
|
||||
++k1;
|
||||
spawnercreature_a.run(entityinsentient, ichunkaccess);
|
||||
+ // Paper start
|
||||
+ if (trackEntity != null) {
|
||||
+ trackEntity.accept(entityinsentient);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
// CraftBukkit end
|
||||
- if (j >= entityinsentient.getMaxSpawnGroup()) {
|
||||
- return;
|
||||
+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper
|
||||
+ return j; // Paper
|
||||
}
|
||||
|
||||
if (entityinsentient.c(k1)) {
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
}
|
||||
|
||||
}
|
||||
+ return j; // Paper
|
||||
}
|
||||
|
||||
private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) {
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
|
||||
public static class d {
|
||||
|
||||
- private final int a;
|
||||
+ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER
|
||||
private final Object2IntOpenHashMap<EnumCreatureType> b;
|
||||
private final SpawnerCreatureProbabilities c;
|
||||
- private final Object2IntMap<EnumCreatureType> d;
|
||||
+ private final Object2IntMap<EnumCreatureType> d; final Object2IntMap<EnumCreatureType> getEntityCountsByType() { return this.d; } // Paper - OBFHELPER
|
||||
@Nullable
|
||||
private BlockPosition e;
|
||||
@Nullable
|
||||
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
||||
|
||||
// CraftBukkit start
|
||||
private boolean a(EnumCreatureType enumcreaturetype, int limit) {
|
||||
- int i = limit * this.a / SpawnerCreature.b;
|
||||
+ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method
|
||||
// CraftBukkit end
|
||||
|
||||
return this.b.getInt(enumcreaturetype) < i;
|
Loading…
Reference in a new issue