256 lines
12 KiB
Diff
256 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: dfsek <dfsek@protonmail.com>
|
|
Date: Sat, 19 Jun 2021 20:15:59 -0700
|
|
Subject: [PATCH] Add more LimitedRegion API
|
|
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java b/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..3160766243e2ce90d07f71d02c7410ff4e9d9562
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java
|
|
@@ -0,0 +1,116 @@
|
|
+package io.papermc.paper.world.generation;
|
|
+
|
|
+import net.minecraft.core.BlockPos;
|
|
+import net.minecraft.nbt.CompoundTag;
|
|
+import net.minecraft.server.level.WorldGenRegion;
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.MobSpawnType;
|
|
+import net.minecraft.world.entity.SpawnGroupData;
|
|
+import net.minecraft.world.level.block.entity.BlockEntity;
|
|
+import org.bukkit.World;
|
|
+import org.bukkit.block.BlockState;
|
|
+import org.bukkit.block.data.BlockData;
|
|
+import org.bukkit.craftbukkit.block.CraftBlockEntityState;
|
|
+import org.bukkit.craftbukkit.block.CraftBlockState;
|
|
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
|
+import org.bukkit.craftbukkit.inventory.CraftMetaBlockState;
|
|
+import org.bukkit.entity.Entity;
|
|
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
+import org.bukkit.util.Vector;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+
|
|
+import java.util.Objects;
|
|
+import java.util.function.Consumer;
|
|
+
|
|
+@Deprecated
|
|
+public class CraftProtoWorld implements ProtoWorld {
|
|
+ private WorldGenRegion region;
|
|
+
|
|
+ public CraftProtoWorld(WorldGenRegion region) {
|
|
+ this.region = region;
|
|
+ }
|
|
+
|
|
+ public void clearReference() {
|
|
+ region = null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setBlockData(int x, int y, int z, @NotNull BlockData data) {
|
|
+ BlockPos position = new BlockPos(x, y, z);
|
|
+ getDelegate().setBlock(position, ((CraftBlockData) data).getState(), 3);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setBlockState(int x, int y, int z, @NotNull BlockState state) {
|
|
+ BlockPos pos = new BlockPos(x, y, z);
|
|
+ if(!state.getBlockData().matches(getDelegate().getBlockState(pos).createCraftBlockData())) {
|
|
+ throw new IllegalArgumentException("BlockData does not match! Expected " + state.getBlockData().getAsString(false) + ", got " + getDelegate().getBlockState(pos).createCraftBlockData().getAsString(false));
|
|
+ }
|
|
+ getDelegate().getBlockEntity(pos).load(((CraftBlockEntityState<?>) state).getSnapshotNBT());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @NotNull BlockState getBlockState(int x, int y, int z) {
|
|
+ BlockEntity entity = getDelegate().getBlockEntity(new BlockPos(x, y, z));
|
|
+ return CraftMetaBlockState.createBlockState(entity.getBlockState().getBukkitMaterial(), entity.saveWithFullMetadata());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void scheduleBlockUpdate(int x, int y, int z) {
|
|
+ BlockPos position = new BlockPos(x, y, z);
|
|
+ getDelegate().scheduleTick(position, getDelegate().getBlockIfLoaded(position), 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void scheduleFluidUpdate(int x, int y, int z) {
|
|
+ BlockPos position = new BlockPos(x, y, z);
|
|
+ getDelegate().scheduleTick(position, getDelegate().getFluidState(position).getType(), 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @NotNull World getWorld() {
|
|
+ // reading/writing the returned Minecraft world causes a deadlock.
|
|
+ // By implementing this, and covering it in warnings, we're assuming people won't be stupid, and
|
|
+ // if they are stupid, they'll figure it out pretty fast.
|
|
+ return getDelegate().getMinecraftWorld().getWorld();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @NotNull BlockData getBlockData(int x, int y, int z) {
|
|
+ return CraftBlockData.fromData(getDelegate().getBlockState(new BlockPos(x, y, z)));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getCenterChunkX() {
|
|
+ return getDelegate().getCenter().x;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getCenterChunkZ() {
|
|
+ return getDelegate().getCenter().z;
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings({"unchecked", "deprecation"})
|
|
+ @Override
|
|
+ public <T extends Entity> @NotNull T spawn(@NotNull Vector location, @NotNull Class<T> clazz, @Nullable Consumer<T> function, CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException {
|
|
+ net.minecraft.world.entity.Entity entity = getDelegate().getMinecraftWorld().getWorld().createEntity(location.toLocation(getWorld()), clazz);
|
|
+ Objects.requireNonNull(entity, "Cannot spawn null entity");
|
|
+ if (entity instanceof Mob mob) {
|
|
+ mob.finalizeSpawn(getDelegate(), getDelegate().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null, null);
|
|
+ }
|
|
+
|
|
+ if (function != null) {
|
|
+ function.accept((T) entity.getBukkitEntity());
|
|
+ }
|
|
+
|
|
+ getDelegate().addFreshEntity(entity, reason);
|
|
+ return (T) entity.getBukkitEntity();
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+ private WorldGenRegion getDelegate() {
|
|
+ return Objects.requireNonNull(region, "Cannot access ProtoWorld after generation!");
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
|
index 94fee76f0b2145e3cf99460c407815bb32bd19d0..671ec060981790043f5685a5b647324ddfee6af2 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
|
@@ -151,7 +151,10 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
|
|
@Override
|
|
public BlockState getBlockState(int x, int y, int z) {
|
|
Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z);
|
|
- return super.getBlockState(x, y, z);
|
|
+ // Paper start
|
|
+ net.minecraft.world.level.block.entity.BlockEntity entity = getHandle().getBlockEntity(new BlockPos(x, y, z));
|
|
+ return org.bukkit.craftbukkit.inventory.CraftMetaBlockState.createBlockState(entity.getBlockState().getBukkitMaterial(), entity.saveWithFullMetadata());
|
|
+ // Paper end
|
|
}
|
|
|
|
@Override
|
|
@@ -169,7 +172,7 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
|
|
@Override
|
|
public void setBlockData(int x, int y, int z, BlockData blockData) {
|
|
Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z);
|
|
- super.setBlockData(x, y, z, blockData);
|
|
+ getHandle().setBlock(new BlockPos(x, y, z), ((org.bukkit.craftbukkit.block.data.CraftBlockData) blockData).getState(), 3); // Paper
|
|
}
|
|
|
|
@Override
|
|
@@ -199,4 +202,45 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
|
|
public void addEntityToWorld(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason) {
|
|
this.entities.add(entity);
|
|
}
|
|
+
|
|
+ // Paper start
|
|
+ @Override
|
|
+ public void setBlockState(int x, int y, int z, BlockState state) {
|
|
+ BlockPos pos = new BlockPos(x, y, z);
|
|
+ if (!state.getBlockData().matches(getHandle().getBlockState(pos).createCraftBlockData())) {
|
|
+ throw new IllegalArgumentException("BlockData does not match! Expected " + state.getBlockData().getAsString(false) + ", got " + getHandle().getBlockState(pos).createCraftBlockData().getAsString(false));
|
|
+ }
|
|
+ getHandle().getBlockEntity(pos).load(((org.bukkit.craftbukkit.block.CraftBlockEntityState<?>) state).getSnapshotNBT());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void scheduleBlockUpdate(int x, int y, int z) {
|
|
+ BlockPos position = new BlockPos(x, y, z);
|
|
+ getHandle().scheduleTick(position, getHandle().getBlockIfLoaded(position), 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void scheduleFluidUpdate(int x, int y, int z) {
|
|
+ BlockPos position = new BlockPos(x, y, z);
|
|
+ getHandle().scheduleTick(position, getHandle().getFluidState(position).getType(), 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public World getWorld() {
|
|
+ // reading/writing the returned Minecraft world causes a deadlock.
|
|
+ // By implementing this, and covering it in warnings, we're assuming people won't be stupid, and
|
|
+ // if they are stupid, they'll figure it out pretty fast.
|
|
+ return getHandle().getMinecraftWorld().getWorld();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getCenterChunkX() {
|
|
+ return centerChunkX;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getCenterChunkZ() {
|
|
+ return centerChunkZ;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
|
index c8e81b0a5495cd138a7b7a4aed98fd64beda59aa..cb49867045b1fdd9802ec815ab6bc17a6923c822 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
|
@@ -205,6 +205,12 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|
for (BlockPos lightPosition : craftData.getLights()) {
|
|
((ProtoChunk) chunk).addLight(new BlockPos((x << 4) + lightPosition.getX(), lightPosition.getY(), (z << 4) + lightPosition.getZ()));
|
|
}
|
|
+
|
|
+ // Paper start
|
|
+ io.papermc.paper.world.generation.CraftProtoWorld protoWorld = new io.papermc.paper.world.generation.CraftProtoWorld(region);
|
|
+ generator.generateDecorations(protoWorld);
|
|
+ protoWorld.clearReference(); // make sure people dont try to use the ProtoWorld after we're done with it.
|
|
+ // Paper end
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
|
|
index 55dd618d8421271063843c6e65dbcaceba9a33de..56f65b49e0ce55ee5aa9d929a98ea055ce27a8a1 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
|
|
@@ -214,11 +214,16 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
|
|
|
|
@Override
|
|
public BlockState getBlockState() {
|
|
- Material stateMaterial = (this.material != Material.SHIELD) ? this.material : CraftMetaBlockState.shieldToBannerHack(this.blockEntityTag); // Only actually used for jigsaws
|
|
- if (this.blockEntityTag != null) {
|
|
- switch (this.material) {
|
|
+ // Paper start
|
|
+ return createBlockState(this.material, this.blockEntityTag);
|
|
+ }
|
|
+ public static BlockState createBlockState(Material material, CompoundTag blockEntityTag) {
|
|
+ Material stateMaterial = (material != Material.SHIELD) ? material : CraftMetaBlockState.shieldToBannerHack(blockEntityTag); // Only actually used for jigsaws
|
|
+ if (blockEntityTag != null) {
|
|
+ switch (material) {
|
|
+ // Paper end
|
|
case SHIELD:
|
|
- this.blockEntityTag.putString("id", "banner");
|
|
+ blockEntityTag.putString("id", "banner"); // Paper
|
|
break;
|
|
case SHULKER_BOX:
|
|
case WHITE_SHULKER_BOX:
|
|
@@ -237,11 +242,11 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
|
|
case GREEN_SHULKER_BOX:
|
|
case RED_SHULKER_BOX:
|
|
case BLACK_SHULKER_BOX:
|
|
- this.blockEntityTag.putString("id", "shulker_box");
|
|
+ blockEntityTag.putString("id", "shulker_box"); // Paper
|
|
break;
|
|
case BEE_NEST:
|
|
case BEEHIVE:
|
|
- this.blockEntityTag.putString("id", "beehive");
|
|
+ blockEntityTag.putString("id", "beehive"); // Paper
|
|
break;
|
|
}
|
|
}
|