mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 12:27:59 +01:00
More patches
This commit is contained in:
parent
4047edb114
commit
c42850dbcc
@ -47,10 +47,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable {
|
||||
|
||||
public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) {
|
||||
public ChunkStorage(RegionStorageInfo storageKey, Path directory, DataFixer dataFixer, boolean dsync) {
|
||||
this.fixerUpper = dataFixer;
|
||||
- this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - rewrite chunk system; async chunk IO
|
||||
+ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - rewrite chunk system; async chunk IO & Attempt to recalculate regionfile header if it is corrupt
|
||||
- this.regionFileCache = new RegionFileStorage(storageKey, directory, dsync); // Paper - rewrite chunk system; async chunk IO
|
||||
+ this.regionFileCache = new RegionFileStorage(storageKey, directory, dsync, true); // Paper - rewrite chunk system; async chunk IO & Attempt to recalculate regionfile header if it is corrupt
|
||||
}
|
||||
|
||||
public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) {
|
||||
@ -91,9 +91,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
|
||||
protected final RegionBitmap usedSectors;
|
||||
public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
|
||||
public final Path regionFile; // Paper
|
||||
|
||||
+
|
||||
+ // Paper start - Attempt to recalculate regionfile header if it is corrupt
|
||||
+ private static long roundToSectors(long bytes) {
|
||||
+ long sectors = bytes >>> 12; // 4096 = 2^12
|
||||
@ -447,31 +448,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];
|
||||
|
||||
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
|
||||
public RegionFile(Path file, Path directory, boolean dsync) throws IOException {
|
||||
this(file, directory, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
|
||||
public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
|
||||
this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
|
||||
}
|
||||
+ // Paper start - add can recalc flag
|
||||
+ public RegionFile(Path file, Path directory, boolean dsync, boolean canRecalcHeader) throws IOException {
|
||||
+ this(file, directory, RegionFileVersion.getCompressionFormat(), dsync, canRecalcHeader);
|
||||
+ public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync, boolean canRecalcHeader) throws IOException {
|
||||
+ this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync, canRecalcHeader);
|
||||
+ }
|
||||
+ // Paper end - add can recalc flag
|
||||
|
||||
public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException {
|
||||
+ // Paper start - add can recalc flag
|
||||
+ this(file, directory, outputChunkStreamVersion, dsync, false);
|
||||
public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync) throws IOException {
|
||||
+ this(storageKey, path, directory, compressionFormat, dsync, true);
|
||||
+ }
|
||||
+ public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync, boolean canRecalcHeader) throws IOException {
|
||||
+
|
||||
+ public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync, boolean canRecalcHeader) throws IOException {
|
||||
+ this.canRecalcHeader = canRecalcHeader;
|
||||
+ // Paper end - add can recalc flag
|
||||
this.header = ByteBuffer.allocateDirect(8192);
|
||||
this.regionFile = file; // Paper
|
||||
initOversizedState(); // Paper
|
||||
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
|
||||
RegionFile.LOGGER.warn("Region file {} has truncated header: {}", file, i);
|
||||
RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i);
|
||||
}
|
||||
|
||||
- long j = Files.size(file);
|
||||
+ final long j = Files.size(file); final long regionFileSize = j; // Paper - recalculate header on header corruption
|
||||
- long j = Files.size(path);
|
||||
+ final long j = Files.size(path); final long regionFileSize = j; // Paper - recalculate header on header corruption
|
||||
|
||||
- for (int k = 0; k < 1024; ++k) {
|
||||
- int l = this.offsets.get(k);
|
||||
@ -495,15 +495,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ sectorLength = j1; // Paper - diff on change, we expect this to be sector length of region
|
||||
|
||||
if (i1 < 2) {
|
||||
RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{file, k, i1});
|
||||
RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{path, k, i1});
|
||||
- this.offsets.put(k, 0);
|
||||
+ //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if (j1 == 0) {
|
||||
RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", file, k);
|
||||
RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, k);
|
||||
- this.offsets.put(k, 0);
|
||||
+ //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else if ((long) i1 * 4096L > j) {
|
||||
RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{file, k, i1});
|
||||
RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{path, k, i1});
|
||||
- this.offsets.put(k, 0);
|
||||
+ //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
|
||||
} else {
|
||||
@ -559,6 +559,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
|
||||
private Path getExternalChunkPath(ChunkPos chunkPos) {
|
||||
@ -656,6 +657,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end - recalculate header on regionfile corruption
|
||||
return null;
|
||||
} else {
|
||||
JvmProfiler.INSTANCE.onRegionFileRead(this.info, pos, this.version, j1);
|
||||
- return this.createChunkInputStream(pos, b0, RegionFile.createStream(bytebuffer, j1));
|
||||
+ // Paper start - recalculate header on regionfile corruption
|
||||
+ final DataInputStream ret = this.createChunkInputStream(pos, b0, RegionFile.createStream(bytebuffer, j1));
|
||||
@ -689,7 +691,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
public final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap();
|
||||
private final RegionStorageInfo info;
|
||||
private final Path folder;
|
||||
private final boolean sync;
|
||||
+ private final boolean isChunkData; // Paper
|
||||
@ -699,16 +701,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
// Paper end - cache regionfile does not exist state
|
||||
|
||||
protected RegionFileStorage(Path directory, boolean dsync) { // Paper - protected constructor
|
||||
protected RegionFileStorage(RegionStorageInfo storageKey, Path directory, boolean dsync) { // Paper - protected constructor
|
||||
+ // Paper start - add isChunkData param
|
||||
+ this(directory, dsync, false);
|
||||
+ this(storageKey, directory, dsync, false);
|
||||
+ }
|
||||
+ RegionFileStorage(Path directory, boolean dsync, boolean isChunkData) {
|
||||
+ RegionFileStorage(RegionStorageInfo storageKey, Path directory, boolean dsync, boolean isChunkData) {
|
||||
+ this.isChunkData = isChunkData;
|
||||
+ // Paper end - add isChunkData param
|
||||
this.folder = directory;
|
||||
this.sync = dsync;
|
||||
}
|
||||
this.info = storageKey;
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
// Paper - only create directory if not existing only - moved down
|
||||
Path path = this.folder;
|
||||
@ -722,8 +724,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
// Paper end - cache regionfile does not exist state
|
||||
FileUtil.createDirectoriesSafe(this.folder); // Paper - only create directory if not existing only - moved from above
|
||||
- RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync);
|
||||
+ RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync, this.isChunkData); // Paper - allow for chunk regionfiles to regen header
|
||||
- RegionFile regionfile1 = new RegionFile(this.info, path1, this.folder, this.sync);
|
||||
+ RegionFile regionfile1 = new RegionFile(this.info, path1, this.folder, this.sync, this.isChunkData); // Paper - allow for chunk regionfiles to regen header
|
||||
|
||||
this.regionCache.putAndMoveToFirst(i, regionfile1);
|
||||
// Paper start
|
||||
@ -766,12 +768,12 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVer
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
@@ -0,0 +0,0 @@ import javax.annotation.Nullable;
|
||||
import net.minecraft.util.FastBufferedInputStream;
|
||||
@@ -0,0 +0,0 @@ import org.slf4j.Logger;
|
||||
|
||||
public class RegionFileVersion {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- private static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>();
|
||||
+ public static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>(); // Paper - private -> public
|
||||
private static final Object2ObjectMap<String, RegionFileVersion> VERSIONS_BY_NAME = new Object2ObjectOpenHashMap<>();
|
||||
public static final RegionFileVersion VERSION_GZIP = register(
|
||||
new RegionFileVersion(
|
||||
1, stream -> new FastBufferedInputStream(new GZIPInputStream(stream)), stream -> new BufferedOutputStream(new GZIPOutputStream(stream))
|
@ -177,14 +177,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
|
||||
@@ -0,0 +0,0 @@ public abstract class StateHolder<O, S> {
|
||||
private final ImmutableMap<Property<?>, Comparable<?>> values;
|
||||
private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> values;
|
||||
private Table<Property<?>, Comparable<?>, S> neighbours;
|
||||
protected final MapCodec<S> propertiesCodec;
|
||||
+ protected final io.papermc.paper.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Paper - optimise state lookup
|
||||
|
||||
protected StateHolder(O owner, ImmutableMap<Property<?>, Comparable<?>> entries, MapCodec<S> codec) {
|
||||
protected StateHolder(O owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<S> codec) {
|
||||
this.owner = owner;
|
||||
this.values = entries;
|
||||
this.values = propertyMap;
|
||||
this.propertiesCodec = codec;
|
||||
+ this.optimisedTable = new io.papermc.paper.util.table.ZeroCollidingReferenceStateTable(this, entries); // Paper - optimise state lookup
|
||||
}
|
@ -1117,7 +1117,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block {
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
if (!oldState.is(state.getBlock()) && !world.isClientSide) {
|
||||
- this.updatePowerStrength(world, pos, state);
|
||||
+ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone
|
||||
@ -1134,7 +1134,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block {
|
||||
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
if (!world.isClientSide) {
|
||||
if (state.canSurvive(world, pos)) {
|
||||
- this.updatePowerStrength(world, pos, state);
|
@ -95,7 +95,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
// CraftBukkit end
|
||||
this.dead = true;
|
||||
- this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customCausingEntity(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit
|
||||
+ this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customEventDamager(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit
|
||||
+ this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customEventDamager(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API
|
||||
this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
|
||||
this.spawnLingeringCloud();
|
||||
// CraftBukkit start
|
||||
|
@ -218,14 +218,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.worldData.setDataConfiguration(worlddataconfiguration);
|
||||
this.resources.managers.updateRegistryTags(this.registryAccess());
|
||||
net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper - Custom Potion Mixes
|
||||
this.resources.managers.updateRegistryTags();
|
||||
this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes
|
||||
- this.getPlayerList().saveAll();
|
||||
+ // Paper start
|
||||
+ if (Thread.currentThread() != this.serverThread) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements
|
||||
+ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements // TODO Move this to a different patch
|
||||
+ for (ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||
+ player.getAdvancements().save();
|
||||
+ }
|
||||
@ -537,8 +537,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -0,0 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
-<Configuration status="WARN" packages="com.mojang.util">
|
||||
+<Configuration status="WARN" packages="com.mojang.util" shutdownHook="disable">
|
||||
-<Configuration status="WARN">
|
||||
+<Configuration status="WARN" shutdownHook="disable">
|
||||
<Appenders>
|
||||
<Queue name="ServerGuiConsole">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" />
|
@ -389,7 +389,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- public int tickingBlockCount;
|
||||
- public int tickingFluidCount;
|
||||
-
|
||||
- a() {}
|
||||
- a(final LevelChunkSection chunksection) {}
|
||||
-
|
||||
- public void accept(BlockState iblockdata, int i) {
|
||||
+ // Paper start - unfuck this
|
||||
@ -425,13 +425,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ });
|
||||
}
|
||||
-
|
||||
- a a0 = new a();
|
||||
- a a0 = new a(this);
|
||||
-
|
||||
- this.states.count(a0);
|
||||
- this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount;
|
||||
- this.tickingBlockCount = (short) a0.tickingBlockCount;
|
||||
- this.tickingFluidCount = (short) a0.tickingFluidCount;
|
||||
+ // Paper end
|
||||
+ // Paper end - unfuck this
|
||||
}
|
||||
|
||||
public PalettedContainer<BlockState> getStates() {
|
@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
|
||||
.stable();
|
||||
};
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final BlockPos ZERO = new BlockPos(0, 0, 0);
|
||||
- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000));
|
@ -24,11 +24,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
return null;
|
||||
} else {
|
||||
- Map<Target, BlockPos> map = positions.stream()
|
||||
- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getGoal((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), Function.identity()));
|
||||
- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getTarget((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), Function.identity()));
|
||||
+ // Paper start - Perf: remove streams and optimize collection
|
||||
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
|
||||
+ for (BlockPos pos : positions) {
|
||||
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos));
|
||||
+ for (final BlockPos pos : positions) {
|
||||
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos));
|
||||
+ }
|
||||
+ // Paper end - Perf: remove streams and optimize collection
|
||||
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
|
@ -69,7 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
@Override
|
||||
public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
|
||||
protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
|
||||
Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING);
|
||||
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; prevent retracting when we're facing the wrong way (we were replaced before retraction could occur)
|
||||
+ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below
|
||||
@ -110,23 +110,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
|
||||
}
|
||||
|
||||
protected void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
|
||||
- if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) {
|
||||
+ if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
||||
Block block = state.getBlock();
|
||||
boolean flag = explosion.getIndirectSourceEntity() instanceof Player;
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
|
||||
}
|
||||
|
||||
protected boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
|
||||
- return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem()));
|
||||
+ return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
protected boolean canBeReplaced(BlockState state, Fluid fluid) {
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
return this.legacySolid;
|
||||
}
|
@ -239,7 +239,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.SyncedDataHolder;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@ -247,7 +247,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.teleportTo(worldserver, null);
|
||||
}
|
||||
// Paper end - make end portalling safe
|
@ -5,26 +5,6 @@ Subject: [PATCH] Write SavedData IO async
|
||||
|
||||
Co-Authored-By: Shane Freeder <theboyetronic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java
|
||||
+++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java
|
||||
@@ -0,0 +0,0 @@ public class ThreadedWorldUpgrader {
|
||||
}
|
||||
|
||||
this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5));
|
||||
+ // Paper start - Write SavedData IO async
|
||||
+ this.threadPool.execute(() -> {
|
||||
+ try {
|
||||
+ worldPersistentData.close();
|
||||
+ } catch (IOException exception) {
|
||||
+ LOGGER.error("Failed to close persistent world data", exception);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - Write SavedData IO async
|
||||
}
|
||||
this.threadPool.shutdown();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@ -85,20 +65,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
@@ -0,0 +0,0 @@ public class WorldUpgrader {
|
||||
}
|
||||
}
|
||||
|
||||
- this.overworldDataStorage.save();
|
||||
+ // Paper start - Write SavedData IO async
|
||||
+ try {
|
||||
+ this.overworldDataStorage.close();
|
||||
+ } catch (IOException exception) {
|
||||
+ LOGGER.error("Failed to close persistent world data", exception);
|
||||
+ }
|
||||
+ // Paper end - Write SavedData IO async
|
||||
i = Util.getMillis() - i;
|
||||
WorldUpgrader.LOGGER.info("World optimizaton finished after {} ms", i);
|
||||
this.finished = true;
|
||||
(new WorldUpgrader.PoiUpgrader(this)).upgrade();
|
||||
WorldUpgrader.LOGGER.info("Upgrading blocks");
|
||||
(new WorldUpgrader.ChunkUpgrader()).upgrade();
|
||||
- this.overworldDataStorage.save();
|
||||
+ // Paper start - Write SavedData IO async
|
||||
+ try {
|
||||
+ this.overworldDataStorage.close();
|
||||
+ } catch (final IOException e) {
|
||||
+ LOGGER.error("Failed to close persistent world data", e);
|
||||
+ }
|
||||
+ // Paper end - Write SavedData IO async
|
||||
i = Util.getMillis() - i;
|
||||
WorldUpgrader.LOGGER.info("World optimizaton finished after {} seconds", i / 1000L);
|
||||
this.finished = true;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
|
||||
@ -107,22 +87,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
return this.dirty;
|
||||
}
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - Write SavedData IO async - This is dead
|
||||
public void save(File file) {
|
||||
+ save(file, null).join(); // Paper - Write SavedData IO async - joining is evil, but we assume the old blocking behavior here just for safety
|
||||
+ // Paper start - Write SavedData IO async - joining is evil, but we assume the old blocking behavior here just for safety
|
||||
+ @io.papermc.paper.annotation.DoNotUse
|
||||
public void save(File file, HolderLookup.Provider registryLookup) {
|
||||
+ save(file, registryLookup, null).join();
|
||||
+ }
|
||||
+
|
||||
+ public java.util.concurrent.CompletableFuture<Void> save(File file, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) { // Paper - Write SavedData IO async
|
||||
+ public java.util.concurrent.CompletableFuture<Void> save(File file, HolderLookup.Provider registryLookup, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) {
|
||||
+ // Paper end - Write SavedData IO async
|
||||
if (this.isDirty()) {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
compoundTag.put("data", this.save(new CompoundTag()));
|
||||
compoundTag.put("data", this.save(new CompoundTag(), registryLookup));
|
||||
NbtUtils.addCurrentDataVersion(compoundTag);
|
||||
|
||||
+ Runnable writeRunnable = () -> { // Paper - Write SavedData IO async
|
||||
try {
|
||||
NbtIo.writeCompressed(compoundTag, file.toPath());
|
||||
} catch (IOException var4) {
|
||||
LOGGER.error("Could not save data {}", this, var4);
|
||||
} catch (IOException var5) {
|
||||
LOGGER.error("Could not save data {}", this, var5);
|
||||
}
|
||||
+ }; // Paper - Write SavedData IO async
|
||||
|
||||
@ -137,7 +119,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end - Write SavedData IO async
|
||||
}
|
||||
|
||||
public static record Factory<T extends SavedData>(Supplier<T> constructor, Function<CompoundTag, T> deserializer, DataFixTypes type) {
|
||||
public static record Factory<T extends SavedData>(
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
@ -151,14 +133,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public final Map<String, SavedData> cache = Maps.newHashMap();
|
||||
private final DataFixer fixerUpper;
|
||||
private final HolderLookup.Provider registries;
|
||||
private final File dataFolder;
|
||||
+ protected final java.util.concurrent.ExecutorService ioExecutor; // Paper - Write SavedData IO async
|
||||
|
||||
public DimensionDataStorage(File directory, DataFixer dataFixer) {
|
||||
public DimensionDataStorage(File directory, DataFixer dataFixer, HolderLookup.Provider registryLookup) {
|
||||
this.fixerUpper = dataFixer;
|
||||
this.dataFolder = directory;
|
||||
+ String worldFolder = dataFolder.getParent(); // Paper - Write SavedData IO async
|
||||
+ this.ioExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("DimensionDataIO - " + worldFolder + " - %d").setDaemon(true).build()); // Paper - Write SavedData IO async
|
||||
this.registries = registryLookup;
|
||||
+ this.ioExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("DimensionDataIO - " + dataFolder.getParent() + " - %d").setDaemon(true).build()); // Paper - Write SavedData IO async
|
||||
}
|
||||
|
||||
private File getDataFile(String id) {
|
||||
@ -178,9 +161,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ public void save(boolean async) { // Paper - Write SavedData IO async
|
||||
this.cache.forEach((id, state) -> {
|
||||
if (state != null) {
|
||||
- state.save(this.getDataFile(id));
|
||||
- state.save(this.getDataFile(id), this.registries);
|
||||
+ // Paper start - Write SavedData IO async
|
||||
+ final java.util.concurrent.CompletableFuture<Void> save = state.save(this.getDataFile(id), ioExecutor);
|
||||
+ final java.util.concurrent.CompletableFuture<Void> save = state.save(this.getDataFile(id), this.registries, this.ioExecutor);
|
||||
+ if (!async) {
|
||||
+ save.join();
|
||||
+ }
|
Loading…
Reference in New Issue
Block a user