683
This commit is contained in:
parent
e832328b7e
commit
fc5c0dae7f
10 changed files with 56 additions and 46 deletions
39
patches/server/0674-Reset-placed-block-on-exception.patch
Normal file
39
patches/server/0674-Reset-placed-block-on-exception.patch
Normal file
|
@ -0,0 +1,39 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Fri, 7 Jan 2022 11:45:15 +0100
|
||||
Subject: [PATCH] Reset placed block on exception
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index cee3f1200af602b5dfd0b27d05eb01826c5bbb1d..7d76cdc59984b156628273c8357485eb10046007 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -77,6 +77,7 @@ public class BlockItem extends Item {
|
||||
if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) {
|
||||
blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos());
|
||||
}
|
||||
+ final org.bukkit.block.BlockState oldBlockstate = blockstate != null ? blockstate : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); // Paper - Reset placed block on exception
|
||||
// CraftBukkit end
|
||||
|
||||
if (iblockdata == null) {
|
||||
@@ -92,8 +93,20 @@ public class BlockItem extends Item {
|
||||
|
||||
if (iblockdata1.is(iblockdata.getBlock())) {
|
||||
iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1);
|
||||
+ // Paper start - Reset placed block on exception
|
||||
+ try {
|
||||
this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1);
|
||||
BlockItem.updateBlockEntityComponents(world, blockposition, itemstack);
|
||||
+ } catch (Exception e) {
|
||||
+ oldBlockstate.update(true, false);
|
||||
+ if (entityhuman instanceof ServerPlayer player) {
|
||||
+ org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), e);
|
||||
+ player.getBukkitEntity().kickPlayer("Packet processing error");
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ throw e; // Rethrow exception if not placed by a player
|
||||
+ }
|
||||
+ // Paper end - Reset placed block on exception
|
||||
iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack);
|
||||
// CraftBukkit start
|
||||
if (blockstate != null) {
|
|
@ -0,0 +1,35 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Doc <nachito94@msn.com>
|
||||
Date: Mon, 2 Aug 2021 11:24:39 -0400
|
||||
Subject: [PATCH] Add configurable height for slime spawn
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
index b32213c5a3a1ecaf602cf34bed44c537521c2846..f223e78eb1204bbf5f2de38a7ce5b663800f7dc4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
@@ -340,7 +340,11 @@ public class Slime extends Mob implements Enemy {
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
- if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
|
||||
+ // Paper start - Replace rules for Height in Swamp Biome
|
||||
+ final double maxHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
|
||||
+ final double minHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;
|
||||
+ if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
|
||||
+ // Paper end - Replace rules for Height in Swamp Biome
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
@@ -351,7 +355,10 @@ public class Slime extends Mob implements Enemy {
|
||||
ChunkPos chunkcoordintpair = new ChunkPos(pos);
|
||||
boolean flag = world.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
|
||||
|
||||
- if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
|
||||
+ // Paper start - Replace rules for Height in Slime Chunks
|
||||
+ final double maxHeightSlimeChunk = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
|
||||
+ if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
|
||||
+ // Paper end - Replace rules for Height in Slime Chunks
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
}
|
32
patches/server/0676-Fix-xp-reward-for-baby-zombies.patch
Normal file
32
patches/server/0676-Fix-xp-reward-for-baby-zombies.patch
Normal file
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 10:34:02 -0800
|
||||
Subject: [PATCH] Fix xp reward for baby zombies
|
||||
|
||||
The field that tracks the xpReward was not
|
||||
getting reset if the death was cancelled
|
||||
so this resets it after each call to
|
||||
Zombie#getExperienceReward
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index e4fc7f96aac9cc2ed5b4158b6663de397ee1162f..d22464521f41c6a13d6c33f0a361497a3e04197f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -172,11 +172,16 @@ public class Zombie extends Monster {
|
||||
|
||||
@Override
|
||||
public int getExperienceReward() {
|
||||
+ final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
|
||||
if (this.isBaby()) {
|
||||
this.xpReward = (int) ((double) this.xpReward * 2.5D);
|
||||
}
|
||||
|
||||
- return super.getExperienceReward();
|
||||
+ // Paper start - store previous value to reset after calculating XP reward
|
||||
+ int reward = super.getExperienceReward();
|
||||
+ this.xpReward = previousReward;
|
||||
+ return reward;
|
||||
+ // Paper end - store previous value to reset after calculating XP reward
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,62 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brody Beckwith <brody@beckwith.dev>
|
||||
Date: Fri, 14 Jan 2022 00:41:11 -0500
|
||||
Subject: [PATCH] Multi Block Change API Implementation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
index 926ff9be3d9e3f5d620e4c7ccb22b9f64865ff8c..1a37654aff9a9c86c9f7af10a1cf721371f0c5ec 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
@@ -62,6 +62,14 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet<ClientGamePa
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Multi Block Change API
|
||||
+ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<BlockState> blockChanges) {
|
||||
+ this.sectionPos = sectionPos;
|
||||
+ this.positions = blockChanges.keySet().toShortArray();
|
||||
+ this.states = blockChanges.values().toArray(new BlockState[0]);
|
||||
+ }
|
||||
+ // Paper end - Multi Block Change API
|
||||
+
|
||||
private void write(FriendlyByteBuf buf) {
|
||||
buf.writeLong(this.sectionPos.asLong());
|
||||
buf.writeVarInt(this.positions.length);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 81060ef3c9ba90a5bd3ecda65a0e1ac02ce5a9ce..d2f98aeb4a209e9ed4a7b6bddba8a299fc21d002 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -927,6 +927,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.getHandle().connection.send(packet);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void sendMultiBlockChange(final Map<? extends io.papermc.paper.math.Position, BlockData> blockChanges) {
|
||||
+ if (this.getHandle().connection == null) return;
|
||||
+
|
||||
+ Map<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> sectionMap = new HashMap<>();
|
||||
+
|
||||
+ for (Map.Entry<? extends io.papermc.paper.math.Position, BlockData> entry : blockChanges.entrySet()) {
|
||||
+ BlockData blockData = entry.getValue();
|
||||
+ BlockPos blockPos = io.papermc.paper.util.MCUtil.toBlockPos(entry.getKey());
|
||||
+ SectionPos sectionPos = SectionPos.of(blockPos);
|
||||
+
|
||||
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> sectionData = sectionMap.computeIfAbsent(sectionPos, key -> new it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap<>());
|
||||
+ sectionData.put(SectionPos.sectionRelativePos(blockPos), ((CraftBlockData) blockData).getState());
|
||||
+ }
|
||||
+
|
||||
+ for (Map.Entry<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> entry : sectionMap.entrySet()) {
|
||||
+ SectionPos sectionPos = entry.getKey();
|
||||
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> blockData = entry.getValue();
|
||||
+
|
||||
+ net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket packet = new net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket(sectionPos, blockData);
|
||||
+ this.getHandle().connection.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void sendBlockChanges(Collection<BlockState> blocks) {
|
||||
Preconditions.checkArgument(blocks != null, "blocks must not be null");
|
54
patches/server/0678-Fix-NotePlayEvent.patch
Normal file
54
patches/server/0678-Fix-NotePlayEvent.patch
Normal file
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Wallbanks <kieran.wallbanks@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 14:23:50 +0100
|
||||
Subject: [PATCH] Fix NotePlayEvent
|
||||
|
||||
== AT ==
|
||||
public org.bukkit.craftbukkit.block.data.CraftBlockData toNMS(Ljava/lang/Enum;Ljava/lang/Class;)Ljava/lang/Enum;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
index 6215f096849f48843d6e25875b8b71f6827ec0a5..f77d51d10e01fc4eaf5516c05c8be0ef7a425893 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
@@ -94,11 +94,12 @@ public class NoteBlock extends Block {
|
||||
private void playNote(@Nullable Entity entity, BlockState state, Level world, BlockPos pos) {
|
||||
if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || world.getBlockState(pos.above()).isAir()) {
|
||||
// CraftBukkit start
|
||||
- org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
|
||||
- if (event.isCancelled()) {
|
||||
- return;
|
||||
- }
|
||||
+ // org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
|
||||
+ // if (event.isCancelled()) {
|
||||
+ // return;
|
||||
+ // }
|
||||
// CraftBukkit end
|
||||
+ // Paper - move NotePlayEvent call to fix instrument/note changes; TODO any way to cancel the game event?
|
||||
world.blockEvent(pos, this, 0, 0);
|
||||
world.gameEvent(entity, (Holder) GameEvent.NOTE_BLOCK_PLAY, pos);
|
||||
}
|
||||
@@ -138,10 +139,14 @@ public class NoteBlock extends Block {
|
||||
@Override
|
||||
protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
|
||||
NoteBlockInstrument blockpropertyinstrument = (NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT);
|
||||
+ // Paper start - move NotePlayEvent call to fix instrument/note changes
|
||||
+ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, blockpropertyinstrument, state.getValue(NOTE));
|
||||
+ if (event.isCancelled()) return false;
|
||||
+ // Paper end - move NotePlayEvent call to fix instrument/note changes
|
||||
float f;
|
||||
|
||||
if (blockpropertyinstrument.isTunable()) {
|
||||
- int k = (Integer) state.getValue(NoteBlock.NOTE);
|
||||
+ int k = event.getNote().getId(); // Paper - move NotePlayEvent call to fix instrument/note changes
|
||||
|
||||
f = NoteBlock.getPitchFromNote(k);
|
||||
world.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D);
|
||||
@@ -160,7 +165,7 @@ public class NoteBlock extends Block {
|
||||
|
||||
holder = Holder.direct(SoundEvent.createVariableRangeEvent(minecraftkey));
|
||||
} else {
|
||||
- holder = blockpropertyinstrument.getSoundEvent();
|
||||
+ holder = org.bukkit.craftbukkit.block.data.CraftBlockData.toNMS(event.getInstrument(), NoteBlockInstrument.class).getSoundEvent(); // Paper - move NotePlayEvent call to fix instrument/note changes
|
||||
}
|
||||
|
||||
world.playSeededSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, world.random.nextLong());
|
82
patches/server/0679-Freeze-Tick-Lock-API.patch
Normal file
82
patches/server/0679-Freeze-Tick-Lock-API.patch
Normal file
|
@ -0,0 +1,82 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sun, 26 Dec 2021 20:27:43 -0500
|
||||
Subject: [PATCH] Freeze Tick Lock API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 2e0dc24bf6732637b29e21c8817f0d3502a2a89a..8e09bfb7c1b4fb34e6615b0cf774bc8e6cae29fa 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -407,6 +407,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
private org.bukkit.util.Vector origin;
|
||||
@javax.annotation.Nullable
|
||||
private UUID originWorld;
|
||||
+ public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
|
||||
|
||||
public void setOrigin(@javax.annotation.Nonnull Location location) {
|
||||
this.origin = location.toVector();
|
||||
@@ -777,7 +778,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.setRemainingFireTicks(this.remainingFireTicks - 1);
|
||||
}
|
||||
|
||||
- if (this.getTicksFrozen() > 0) {
|
||||
+ if (this.getTicksFrozen() > 0 && !freezeLocked) { // Paper - Freeze Tick Lock API
|
||||
this.setTicksFrozen(0);
|
||||
this.level().levelEvent((Player) null, 1009, this.blockPosition, 1);
|
||||
}
|
||||
@@ -2274,6 +2275,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (fromNetherPortal) {
|
||||
nbttagcompound.putBoolean("Paper.FromNetherPortal", true);
|
||||
}
|
||||
+ if (freezeLocked) {
|
||||
+ nbttagcompound.putBoolean("Paper.FreezeLock", true);
|
||||
+ }
|
||||
// Paper end
|
||||
return nbttagcompound;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -2418,6 +2422,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (spawnReason == null) {
|
||||
spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT;
|
||||
}
|
||||
+ if (nbt.contains("Paper.FreezeLock")) {
|
||||
+ freezeLocked = nbt.getBoolean("Paper.FreezeLock");
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index be044167883611dde0665749d9e243b9c7b6fbd2..7f8e82a1d5fa1ca665a66d2fb1342163f7c7a733 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3458,7 +3458,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
this.level().getProfiler().pop();
|
||||
this.level().getProfiler().push("freezing");
|
||||
- if (!this.level().isClientSide && !this.isDeadOrDying()) {
|
||||
+ if (!this.level().isClientSide && !this.isDeadOrDying() && !this.freezeLocked) { // Paper - Freeze Tick Lock API
|
||||
int i = this.getTicksFrozen();
|
||||
|
||||
if (this.isInPowderSnow && this.canFreeze()) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 97716f0a20fbc5f7048256ad1942e8f56e9fb72b..113ca1d16cb7650d72f488cdaa9e670d51dc85f0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -321,6 +321,17 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return this.getHandle().isFullyFrozen();
|
||||
}
|
||||
|
||||
+ // Paper start - Freeze Tick Lock API
|
||||
+ @Override
|
||||
+ public boolean isFreezeTickingLocked() {
|
||||
+ return this.entity.freezeLocked;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void lockFreezeTicks(boolean locked) {
|
||||
+ this.entity.freezeLocked = locked;
|
||||
+ }
|
||||
+ // Paper end - Freeze Tick Lock API
|
||||
@Override
|
||||
public void remove() {
|
||||
this.entity.pluginRemoved = true;
|
93
patches/server/0680-More-PotionEffectType-API.patch
Normal file
93
patches/server/0680-More-PotionEffectType-API.patch
Normal file
|
@ -0,0 +1,93 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 27 May 2021 21:58:24 -0700
|
||||
Subject: [PATCH] More PotionEffectType API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
index 8dffef71c8b193c0fc84b65a592c93827e341bf7..670a278c1573899f846d33aebc59d2e6616d2c5d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
@@ -123,6 +123,48 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
|
||||
return this.handle.getDescriptionId();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> getEffectAttributes() {
|
||||
+ // re-create map each time because a nms MobEffect can have its attributes modified
|
||||
+ final java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> attributeMap = new java.util.HashMap<>();
|
||||
+ this.handle.getAttributeModifiers().forEach((attribute, attributeModifier) -> {
|
||||
+ attributeMap.put(
|
||||
+ org.bukkit.craftbukkit.attribute.CraftAttribute.stringToBukkit(attribute.toString()),
|
||||
+ // use zero as amplifier to get the base amount, as it is amount = base * (amplifier + 1)
|
||||
+ org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier.create(0))
|
||||
+ );
|
||||
+ });
|
||||
+ return java.util.Map.copyOf(attributeMap);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double getAttributeModifierAmount(org.bukkit.attribute.Attribute attribute, int effectAmplifier) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(effectAmplifier >= 0, "effectAmplifier must be greater than or equal to 0");
|
||||
+ net.minecraft.world.entity.ai.attributes.Attribute nmsAttribute = org.bukkit.craftbukkit.attribute.CraftAttribute.bukkitToMinecraft(attribute);
|
||||
+ com.google.common.base.Preconditions.checkArgument(this.handle.getAttributeModifiers().containsKey(nmsAttribute), attribute + " is not present on " + this.getKey());
|
||||
+ return this.handle.getAttributeModifiers().get(nmsAttribute).create(effectAmplifier).getAmount();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PotionEffectType.Category getEffectCategory() {
|
||||
+ return fromNMS(handle.getCategory());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String translationKey() {
|
||||
+ return this.handle.getDescriptionId();
|
||||
+ }
|
||||
+
|
||||
+ public static PotionEffectType.Category fromNMS(net.minecraft.world.effect.MobEffectCategory mobEffectInfo) {
|
||||
+ return switch (mobEffectInfo) {
|
||||
+ case BENEFICIAL -> PotionEffectType.Category.BENEFICIAL;
|
||||
+ case HARMFUL -> PotionEffectType.Category.HARMFUL;
|
||||
+ case NEUTRAL -> PotionEffectType.Category.NEUTRAL;
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
diff --git a/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6262598f85bd7d9af5546cc0a96531b2f4baf64d
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
|
||||
@@ -0,0 +1,28 @@
|
||||
+package io.papermc.paper.effects;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.minecraft.world.effect.MobEffectCategory;
|
||||
+import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
|
||||
+import org.bukkit.potion.PotionEffectType;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+
|
||||
+public class EffectCategoryTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testEffectCategoriesExist() {
|
||||
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
|
||||
+ assertNotNull(CraftPotionEffectType.fromNMS(mobEffectInfo), mobEffectInfo + " is missing a bukkit equivalent");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testCategoryHasEquivalentColors() {
|
||||
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
|
||||
+ PotionEffectType.Category bukkitEffectCategory = CraftPotionEffectType.fromNMS(mobEffectInfo);
|
||||
+ assertEquals(bukkitEffectCategory.getColor(), PaperAdventure.asAdventure(mobEffectInfo.getTooltipFormatting()), mobEffectInfo.getTooltipFormatting().name() + " doesn't equal " + bukkitEffectCategory.getColor());
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 12 Jul 2021 12:28:29 +0100
|
||||
Subject: [PATCH] Use a CHM for StructureTemplate.Pallete cache
|
||||
|
||||
fixes a CME due to this collection being shared across threads
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index 05ff5d2fc689af238003a381168bf64b51f0d65e..bd401b38239fb7e510f82f458f9336b7da372da0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -859,7 +859,7 @@ public class StructureTemplate {
|
||||
public static final class Palette {
|
||||
|
||||
private final List<StructureTemplate.StructureBlockInfo> blocks;
|
||||
- private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newHashMap();
|
||||
+ private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newConcurrentMap(); // Paper - Fix CME due to this collection being shared across threads
|
||||
|
||||
Palette(List<StructureTemplate.StructureBlockInfo> infos) {
|
||||
this.blocks = infos;
|
|
@ -0,0 +1,170 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 1 Feb 2022 15:51:55 -0700
|
||||
Subject: [PATCH] API for creating command sender which forwards feedback
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e3a5f1ec376319bdfda87fa27ae217bff3914292
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
|
||||
@@ -0,0 +1,111 @@
|
||||
+package io.papermc.paper.commands;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import java.util.UUID;
|
||||
+import java.util.function.Consumer;
|
||||
+import net.kyori.adventure.audience.MessageType;
|
||||
+import net.kyori.adventure.identity.Identity;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import net.minecraft.commands.CommandSource;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.world.phys.Vec2;
|
||||
+import net.minecraft.world.phys.Vec3;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.bukkit.craftbukkit.command.ServerCommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class FeedbackForwardingSender extends ServerCommandSender {
|
||||
+ private final Consumer<? super Component> feedback;
|
||||
+ private final CraftServer server;
|
||||
+
|
||||
+ public FeedbackForwardingSender(final Consumer<? super Component> feedback, final CraftServer server) {
|
||||
+ super(((ServerCommandSender) server.getConsoleSender()).perm);
|
||||
+ this.server = server;
|
||||
+ this.feedback = feedback;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final String message) {
|
||||
+ this.sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final String... messages) {
|
||||
+ for (final String message : messages) {
|
||||
+ this.sendMessage(message);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final Identity identity, final Component message, final MessageType type) {
|
||||
+ this.feedback.accept(message);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String getName() {
|
||||
+ return "FeedbackForwardingSender";
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Component name() {
|
||||
+ return Component.text(this.getName());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isOp() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setOp(final boolean value) {
|
||||
+ throw new UnsupportedOperationException("Cannot change operator status of " + this.getClass().getName());
|
||||
+ }
|
||||
+
|
||||
+ public CommandSourceStack asVanilla() {
|
||||
+ final @Nullable ServerLevel overworld = this.server.getServer().overworld();
|
||||
+ return new CommandSourceStack(
|
||||
+ new Source(this),
|
||||
+ overworld == null ? Vec3.ZERO : Vec3.atLowerCornerOf(overworld.getSharedSpawnPos()),
|
||||
+ Vec2.ZERO,
|
||||
+ overworld,
|
||||
+ 4,
|
||||
+ this.getName(),
|
||||
+ net.minecraft.network.chat.Component.literal(this.getName()),
|
||||
+ this.server.getServer(),
|
||||
+ null
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ private record Source(FeedbackForwardingSender sender) implements CommandSource {
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(final net.minecraft.network.chat.Component message) {
|
||||
+ this.sender.sendMessage(Identity.nil(), PaperAdventure.asAdventure(message));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CommandSender getBukkitSender(final CommandSourceStack stack) {
|
||||
+ return this.sender;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 6348f452a437c10f8291148e9bd4642b5fb09ec2..ab031edcac3865b85637cc9d5b8a939acdc904e4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2129,6 +2129,13 @@ public final class CraftServer implements Server {
|
||||
return this.console.console;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public CommandSender createCommandSender(final java.util.function.Consumer<? super net.kyori.adventure.text.Component> feedback) {
|
||||
+ return new io.papermc.paper.commands.FeedbackForwardingSender(feedback, this);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public EntityMetadataStore getEntityMetadata() {
|
||||
return this.entityMetadata;
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
index 7f22950ae61436e91a59cd29a345809c42bbe739..1e3091687735b461d3b6a313ab8761127981d3e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
@@ -12,7 +12,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public abstract class ServerCommandSender implements CommandSender {
|
||||
- private final PermissibleBase perm;
|
||||
+ public final PermissibleBase perm; // Paper
|
||||
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
||||
|
||||
protected ServerCommandSender() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
index bda9a0b99184adce28bb7851612ed7f4e324826d..61115db85b81e627d11a0de21691a2ca69aafe2c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
@@ -81,6 +81,11 @@ public final class VanillaCommandWrapper extends BukkitCommand {
|
||||
if (sender instanceof ProxiedCommandSender) {
|
||||
return ((ProxiedNativeCommandSender) sender).getHandle();
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (sender instanceof io.papermc.paper.commands.FeedbackForwardingSender feedback) {
|
||||
+ return feedback.asVanilla();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
throw new IllegalArgumentException("Cannot make " + sender + " a vanilla command listener");
|
||||
}
|
363
patches/server/0683-Add-missing-structure-set-seed-configs.patch
Normal file
363
patches/server/0683-Add-missing-structure-set-seed-configs.patch
Normal file
|
@ -0,0 +1,363 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 13 Jan 2022 23:05:53 -0800
|
||||
Subject: [PATCH] Add missing structure set seed configs
|
||||
|
||||
The 4 missing structure set seed configs are strongholds, mineshafts,
|
||||
buried treasure, and ancient cities.
|
||||
|
||||
Strongholds use a ring placement scheme which isn't random so they
|
||||
utilize the world seed by default, this adds a config to override it
|
||||
for just generating the ring positions.
|
||||
|
||||
Mineshafts and Buried Treasure structure sets are special cases
|
||||
where the "salt" that can be defined for them via datapacks has 0
|
||||
effect because the difference between the spacing and separation is 1
|
||||
which is used as the upper bound in the random with salt. So the random
|
||||
always returns the same int (0) so the salt has no effect. This adds
|
||||
seeds/salts to the frequency reducer which has a similar effect.
|
||||
|
||||
Co-authored-by: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index 748caca458eb4eec6ece22d8362e36de252f07dd..c4972e5767488878f7929226258c41c1cc30a47f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -574,7 +574,7 @@ public abstract class ChunkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
- if (structureplacement.isStructureChunk(placementCalculator, chunkcoordintpair.x, chunkcoordintpair.z)) {
|
||||
+ if (structureplacement.isStructureChunk(placementCalculator, chunkcoordintpair.x, chunkcoordintpair.z, structureplacement instanceof net.minecraft.world.level.chunk.ChunkGeneratorStructureState.KeyedRandomSpreadStructurePlacement keyed ? keyed.key : null)) { // Paper - Add missing structure set seed configs
|
||||
if (list.size() == 1) {
|
||||
this.tryGenerateStructure((StructureSet.StructureSelectionEntry) list.get(0), structureAccessor, registryManager, randomstate, structureTemplateManager, placementCalculator.getLevelSeed(), chunk, chunkcoordintpair, sectionposition);
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
index e6c59f986ae89022bd76463209dfa550a3d4fb59..a6b6e5ea191c0e2cd7a2e4f01b89d8af40a83c1b 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
@@ -50,13 +50,14 @@ public class ChunkGeneratorStructureState {
|
||||
private final Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> ringPositions = new Object2ObjectArrayMap();
|
||||
private boolean hasGeneratedPositions;
|
||||
private final List<Holder<StructureSet>> possibleStructureSets;
|
||||
+ public final SpigotWorldConfig conf; // Paper - Add missing structure set seed configs
|
||||
|
||||
public static ChunkGeneratorStructureState createForFlat(RandomState randomstate, long i, BiomeSource worldchunkmanager, Stream<Holder<StructureSet>> stream, SpigotWorldConfig conf) { // Spigot
|
||||
List<Holder<StructureSet>> list = stream.filter((holder) -> {
|
||||
return ChunkGeneratorStructureState.hasBiomesForStructureSet((StructureSet) holder.value(), worldchunkmanager);
|
||||
}).toList();
|
||||
|
||||
- return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, 0L, ChunkGeneratorStructureState.injectSpigot(list, conf)); // Spigot
|
||||
+ return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, 0L, ChunkGeneratorStructureState.injectSpigot(list, conf), conf); // Spigot
|
||||
}
|
||||
|
||||
public static ChunkGeneratorStructureState createForNormal(RandomState randomstate, long i, BiomeSource worldchunkmanager, HolderLookup<StructureSet> holderlookup, SpigotWorldConfig conf) { // Spigot
|
||||
@@ -64,14 +65,24 @@ public class ChunkGeneratorStructureState {
|
||||
return ChunkGeneratorStructureState.hasBiomesForStructureSet((StructureSet) holder_c.value(), worldchunkmanager);
|
||||
}).collect(Collectors.toUnmodifiableList());
|
||||
|
||||
- return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, i, ChunkGeneratorStructureState.injectSpigot(list, conf)); // Spigot
|
||||
+ return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, i, ChunkGeneratorStructureState.injectSpigot(list, conf), conf); // Spigot
|
||||
}
|
||||
+ // Paper start - Add missing structure set seed configs; horrible hack because spigot creates a ton of direct Holders which lose track of the identifying key
|
||||
+ public static final class KeyedRandomSpreadStructurePlacement extends RandomSpreadStructurePlacement {
|
||||
+ public final net.minecraft.resources.ResourceKey<StructureSet> key;
|
||||
+ public KeyedRandomSpreadStructurePlacement(net.minecraft.resources.ResourceKey<StructureSet> key, net.minecraft.core.Vec3i locateOffset, FrequencyReductionMethod frequencyReductionMethod, float frequency, int salt, java.util.Optional<StructurePlacement.ExclusionZone> exclusionZone, int spacing, int separation, net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType spreadType) {
|
||||
+ super(locateOffset, frequencyReductionMethod, frequency, salt, exclusionZone, spacing, separation, spreadType);
|
||||
+ this.key = key;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
|
||||
// Spigot start
|
||||
private static List<Holder<StructureSet>> injectSpigot(List<Holder<StructureSet>> list, SpigotWorldConfig conf) {
|
||||
return list.stream().map((holder) -> {
|
||||
StructureSet structureset = holder.value();
|
||||
- if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig) {
|
||||
+ final Holder<StructureSet> newHolder; // Paper - Add missing structure set seed configs
|
||||
+ if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig && holder.unwrapKey().orElseThrow().location().getNamespace().equals(net.minecraft.resources.ResourceLocation.DEFAULT_NAMESPACE)) { // Paper - Add missing structure set seed configs; check namespace cause datapacks could add structure sets with the same path
|
||||
String name = holder.unwrapKey().orElseThrow().location().getPath();
|
||||
int seed = randomConfig.salt;
|
||||
|
||||
@@ -118,11 +129,27 @@ public class ChunkGeneratorStructureState {
|
||||
case "villages":
|
||||
seed = conf.villageSeed;
|
||||
break;
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ case "ancient_cities":
|
||||
+ seed = conf.ancientCitySeed;
|
||||
+ break;
|
||||
+ case "trail_ruins":
|
||||
+ seed = conf.trailRuinsSeed;
|
||||
+ break;
|
||||
+ case "trial_chambers":
|
||||
+ seed = conf.trialChambersSeed;
|
||||
+ break;
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
- structureset = new StructureSet(structureset.structures(), new RandomSpreadStructurePlacement(randomConfig.locateOffset, randomConfig.frequencyReductionMethod, randomConfig.frequency, seed, randomConfig.exclusionZone, randomConfig.spacing(), randomConfig.separation(), randomConfig.spreadType()));
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ structureset = new StructureSet(structureset.structures(), new KeyedRandomSpreadStructurePlacement(holder.unwrapKey().orElseThrow(), randomConfig.locateOffset, randomConfig.frequencyReductionMethod, randomConfig.frequency, seed, randomConfig.exclusionZone, randomConfig.spacing(), randomConfig.separation(), randomConfig.spreadType()));
|
||||
+ newHolder = Holder.direct(structureset); // I really wish we didn't have to do this here
|
||||
+ } else {
|
||||
+ newHolder = holder;
|
||||
}
|
||||
- return Holder.direct(structureset);
|
||||
+ return newHolder;
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
// Spigot end
|
||||
@@ -139,12 +166,13 @@ public class ChunkGeneratorStructureState {
|
||||
return stream.anyMatch(set::contains);
|
||||
}
|
||||
|
||||
- private ChunkGeneratorStructureState(RandomState noiseConfig, BiomeSource biomeSource, long structureSeed, long concentricRingSeed, List<Holder<StructureSet>> structureSets) {
|
||||
+ private ChunkGeneratorStructureState(RandomState noiseConfig, BiomeSource biomeSource, long structureSeed, long concentricRingSeed, List<Holder<StructureSet>> structureSets, SpigotWorldConfig conf) { // Paper - Add missing structure set seed configs
|
||||
this.randomState = noiseConfig;
|
||||
this.levelSeed = structureSeed;
|
||||
this.biomeSource = biomeSource;
|
||||
this.concentricRingsSeed = concentricRingSeed;
|
||||
this.possibleStructureSets = structureSets;
|
||||
+ this.conf = conf; // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public List<Holder<StructureSet>> possibleStructureSets() {
|
||||
@@ -198,7 +226,13 @@ public class ChunkGeneratorStructureState {
|
||||
HolderSet<Biome> holderset = placement.preferredBiomes();
|
||||
RandomSource randomsource = RandomSource.create();
|
||||
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ if (this.conf.strongholdSeed != null && structureSetEntry.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
|
||||
+ randomsource.setSeed(this.conf.strongholdSeed);
|
||||
+ } else {
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
randomsource.setSeed(this.concentricRingsSeed);
|
||||
+ } // Paper - Add missing structure set seed configs
|
||||
double d0 = randomsource.nextDouble() * Math.PI * 2.0D;
|
||||
int l = 0;
|
||||
int i1 = 0;
|
||||
@@ -275,7 +309,7 @@ public class ChunkGeneratorStructureState {
|
||||
|
||||
for (int l = centerChunkX - chunkCount; l <= centerChunkX + chunkCount; ++l) {
|
||||
for (int i1 = centerChunkZ - chunkCount; i1 <= centerChunkZ + chunkCount; ++i1) {
|
||||
- if (structureplacement.isStructureChunk(this, l, i1)) {
|
||||
+ if (structureplacement.isStructureChunk(this, l, i1, structureplacement instanceof KeyedRandomSpreadStructurePlacement keyed ? keyed.key : null)) { // Paper - Add missing structure set seed configs
|
||||
return true;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
index a4c34e9415632354d33668a38d06453ada4d3c77..cbf13e4f2da6a27619e9bc9a7cd73bb6e69cad2a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
@@ -79,14 +79,30 @@ public abstract class StructurePlacement {
|
||||
return this.exclusionZone;
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add missing structure set seed configs
|
||||
public boolean isStructureChunk(ChunkGeneratorStructureState calculator, int chunkX, int chunkZ) {
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ return this.isStructureChunk(calculator, chunkX, chunkZ, null);
|
||||
+ }
|
||||
+ public boolean isStructureChunk(ChunkGeneratorStructureState calculator, int chunkX, int chunkZ, @org.jetbrains.annotations.Nullable net.minecraft.resources.ResourceKey<StructureSet> structureSetKey) {
|
||||
+ Integer saltOverride = null;
|
||||
+ if (structureSetKey != null) {
|
||||
+ if (structureSetKey == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.MINESHAFTS) {
|
||||
+ saltOverride = calculator.conf.mineshaftSeed;
|
||||
+ } else if (structureSetKey == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.BURIED_TREASURES) {
|
||||
+ saltOverride = calculator.conf.buriedTreasureSeed;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
return this.isPlacementChunk(calculator, chunkX, chunkZ)
|
||||
- && this.applyAdditionalChunkRestrictions(chunkX, chunkZ, calculator.getLevelSeed())
|
||||
+ && this.applyAdditionalChunkRestrictions(chunkX, chunkZ, calculator.getLevelSeed(), saltOverride) // Paper - Add missing structure set seed configs
|
||||
&& this.applyInteractionsWithOtherStructures(calculator, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
- public boolean applyAdditionalChunkRestrictions(int chunkX, int chunkZ, long seed) {
|
||||
- return !(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency);
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ public boolean applyAdditionalChunkRestrictions(int chunkX, int chunkZ, long seed, @org.jetbrains.annotations.Nullable Integer saltOverride) {
|
||||
+ return !(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency, saltOverride);
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public boolean applyInteractionsWithOtherStructures(ChunkGeneratorStructureState calculator, int centerChunkX, int centerChunkZ) {
|
||||
@@ -101,25 +117,31 @@ public abstract class StructurePlacement {
|
||||
|
||||
public abstract StructurePlacementType<?> type();
|
||||
|
||||
- private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
worldgenRandom.setLargeFeatureWithSalt(seed, salt, chunkX, chunkZ);
|
||||
return worldgenRandom.nextFloat() < frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ if (saltOverride == null) { // Paper - Add missing structure set seed configs
|
||||
worldgenRandom.setLargeFeatureSeed(seed, chunkX, chunkZ);
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ } else {
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride);
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
return worldgenRandom.nextDouble() < (double)frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, 10387320);
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride != null ? saltOverride : HIGHLY_ARBITRARY_RANDOM_SALT); // Paper - Add missing structure set seed configs
|
||||
return worldgenRandom.nextFloat() < frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
|
||||
int i = chunkX >> 4;
|
||||
int j = chunkZ >> 4;
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
@@ -147,7 +169,7 @@ public abstract class StructurePlacement {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FrequencyReducer {
|
||||
- boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance);
|
||||
+ boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride); // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public static enum FrequencyReductionMethod implements StringRepresentable {
|
||||
@@ -167,8 +189,8 @@ public abstract class StructurePlacement {
|
||||
this.reducer = generationPredicate;
|
||||
}
|
||||
|
||||
- public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance) {
|
||||
- return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance);
|
||||
+ public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
+ return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance, saltOverride); // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index 41f4416d820ed1ca2d02b457749cbb6c3dbb20af..5485df1a1b59e81f4dcedd21dd972e1fd2759573 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -322,6 +322,18 @@ public class SpigotWorldConfig
|
||||
public int mansionSeed;
|
||||
public int fossilSeed;
|
||||
public int portalSeed;
|
||||
+ // Paper start - add missing structure set configs
|
||||
+ public int ancientCitySeed;
|
||||
+ public int trailRuinsSeed;
|
||||
+ public int trialChambersSeed;
|
||||
+ public int buriedTreasureSeed;
|
||||
+ public Integer mineshaftSeed;
|
||||
+ public Long strongholdSeed;
|
||||
+ private <N extends Number> N getSeed(String path, java.util.function.Function<String, N> toNumberFunc) {
|
||||
+ final String value = this.getString(path, "default");
|
||||
+ return org.apache.commons.lang3.math.NumberUtils.isParsable(value) ? toNumberFunc.apply(value) : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
private void initWorldGenSeeds()
|
||||
{
|
||||
this.villageSeed = this.getInt( "seed-village", 10387312 );
|
||||
@@ -339,6 +351,14 @@ public class SpigotWorldConfig
|
||||
this.mansionSeed = this.getInt( "seed-mansion", 10387319 );
|
||||
this.fossilSeed = this.getInt( "seed-fossil", 14357921 );
|
||||
this.portalSeed = this.getInt( "seed-portal", 34222645 );
|
||||
+ // Paper start - add missing structure set configs
|
||||
+ this.ancientCitySeed = this.getInt("seed-ancientcity", 20083232);
|
||||
+ this.trailRuinsSeed = this.getInt("seed-trailruins", 83469867);
|
||||
+ this.trialChambersSeed = this.getInt("seed-trialchambers", 94251327);
|
||||
+ this.buriedTreasureSeed = this.getInt("seed-buriedtreasure", 10387320); // StructurePlacement#HIGHLY_ARBITRARY_RANDOM_SALT
|
||||
+ this.mineshaftSeed = this.getSeed("seed-mineshaft", Integer::parseInt);
|
||||
+ this.strongholdSeed = this.getSeed("seed-stronghold", Long::parseLong);
|
||||
+ // Paper end
|
||||
this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
|
||||
+ " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed );
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java b/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9061ad5868ac18e76ae4d51d23d101c5e25f7f52
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java
|
||||
@@ -0,0 +1,75 @@
|
||||
+package io.papermc.paper.world.structure;
|
||||
+
|
||||
+import io.papermc.paper.configuration.PaperConfigurations;
|
||||
+import java.io.File;
|
||||
+import java.lang.reflect.Field;
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.core.registries.Registries;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.world.level.levelgen.structure.BuiltinStructureSets;
|
||||
+import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
+import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
|
||||
+import org.bukkit.configuration.file.YamlConfiguration;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+import org.spigotmc.SpigotConfig;
|
||||
+import org.spigotmc.SpigotWorldConfig;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+public class StructureSeedConfigTest extends AbstractTestingBase {
|
||||
+
|
||||
+ @Test
|
||||
+ public void checkStructureSeedDefaults() throws ReflectiveOperationException {
|
||||
+ SpigotConfig.config = new YamlConfiguration() {
|
||||
+ @Override
|
||||
+ public void save(final @NotNull File file) {
|
||||
+ // no-op
|
||||
+ }
|
||||
+ };
|
||||
+ final SpigotWorldConfig config = PaperConfigurations.SPIGOT_WORLD_DEFAULTS.get();
|
||||
+
|
||||
+
|
||||
+ final Registry<StructureSet> structureSets = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE_SET);
|
||||
+ for (final ResourceKey<StructureSet> setKey : structureSets.registryKeySet()) {
|
||||
+ assertEquals(ResourceLocation.DEFAULT_NAMESPACE, setKey.location().getNamespace());
|
||||
+ final StructureSet set = structureSets.getOrThrow(setKey);
|
||||
+ if (setKey == BuiltinStructureSets.STRONGHOLDS) { // special case due to seed matching world seed
|
||||
+ assertEquals(0, set.placement().salt);
|
||||
+ continue;
|
||||
+ }
|
||||
+ int salt = switch (setKey.location().getPath()) {
|
||||
+ case "villages" -> config.villageSeed;
|
||||
+ case "desert_pyramids" -> config.desertSeed;
|
||||
+ case "igloos" -> config.iglooSeed;
|
||||
+ case "jungle_temples" -> config.jungleSeed;
|
||||
+ case "swamp_huts" -> config.swampSeed;
|
||||
+ case "pillager_outposts" -> config.outpostSeed;
|
||||
+ case "ocean_monuments" -> config.monumentSeed;
|
||||
+ case "woodland_mansions" -> config.mansionSeed;
|
||||
+ case "buried_treasures" -> config.buriedTreasureSeed;
|
||||
+ case "mineshafts" -> config.mineshaftSeed == null ? 0 : config.mineshaftSeed; // mineshaft seed is set differently
|
||||
+ case "ruined_portals" -> config.portalSeed;
|
||||
+ case "shipwrecks" -> config.shipwreckSeed;
|
||||
+ case "ocean_ruins" -> config.oceanSeed;
|
||||
+ case "nether_complexes" -> config.netherSeed;
|
||||
+ case "nether_fossils" -> config.fossilSeed;
|
||||
+ case "end_cities" -> config.endCitySeed;
|
||||
+ case "ancient_cities" -> config.ancientCitySeed;
|
||||
+ case "trail_ruins" -> config.trailRuinsSeed;
|
||||
+ case "trial_chambers" -> config.trialChambersSeed;
|
||||
+ default -> throw new AssertionError("Missing structure set seed in SpigotWorldConfig for " + setKey);
|
||||
+ };
|
||||
+ if (setKey == BuiltinStructureSets.BURIED_TREASURES) {
|
||||
+ final Field field = StructurePlacement.class.getDeclaredField("HIGHLY_ARBITRARY_RANDOM_SALT");
|
||||
+ field.trySetAccessible();
|
||||
+ assertEquals(0, set.placement().salt);
|
||||
+ assertEquals(field.get(null), salt, "Mismatched default seed for " + setKey + ". Should be " + field.get(null));
|
||||
+ continue;
|
||||
+ }
|
||||
+ assertEquals(set.placement().salt, salt, "Mismatched default seed for " + setKey + ". Should be " + set.placement().salt);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
Loading…
Add table
Add a link
Reference in a new issue