Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-27 19:30:07 +01:00
fix: improve biome setting to avoid writing directly to chunk
- Removes possibility of writing to the LevelChunkSection biomes PalettedContainer whilst it is being read for sending packets - I believe this occured mostly on clipboard operations where blocks are written before biomes, so chunks are being sent whilst writing biomes - This would explain why the error reported in the below issue (and others) is/was so rare - Of course I could be completely wrong about all of this, but given the line in LevelChunkSection#write that the error seems to consistently occur on is when writing biomes to the packet, and that the only place I can find in FAWE where we write to a "live" PalettedContainer is for biomes, I am reasonably confident that this is the cause - Should address #2729
Dieser Commit ist enthalten in:
Ursprung
7635eec2e4
Commit
362e946fdb
@ -511,7 +511,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
PalettedContainer<Holder<Biome>> paletteBiomes = setBiomesToPalettedContainer(
|
||||||
|
biomes,
|
||||||
|
setSectionIndex,
|
||||||
|
existingSection.getBiomes()
|
||||||
|
);
|
||||||
|
if (paletteBiomes != null) {
|
||||||
|
PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,11 +560,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||||
biomeHolderIdMap,
|
biomeHolderIdMap,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
PalettedContainer.Strategy.SECTION_BIOMES,
|
||||||
null
|
null
|
||||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||||
@ -625,15 +628,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
existingSection.getBiomes()
|
existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
|
|
||||||
newSection =
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
PaperweightPlatformAdapter.newChunkSection(
|
layerNo,
|
||||||
layerNo,
|
this::loadPrivately,
|
||||||
this::loadPrivately,
|
setArr,
|
||||||
setArr,
|
adapter,
|
||||||
adapter,
|
biomeRegistry,
|
||||||
biomeRegistry,
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
biomeData
|
);
|
||||||
);
|
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
existingSection,
|
existingSection,
|
||||||
@ -845,7 +847,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
finalizer.run();
|
queueHandler.async(finalizer, null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -1103,9 +1105,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
|
BiomeType[] sectionBiomes;
|
||||||
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
PalettedContainer<Holder<Biome>> biomeData;
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomeData = palettedContainer;
|
biomeData = palettedContainer.copy();
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
||||||
@ -1115,10 +1121,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
);
|
);
|
||||||
biomeData = data.recreate();
|
biomeData = data.recreate();
|
||||||
}
|
}
|
||||||
BiomeType[] sectionBiomes;
|
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
|
||||||
return biomeData;
|
|
||||||
}
|
|
||||||
for (int y = 0, index = 0; y < 4; y++) {
|
for (int y = 0, index = 0; y < 4; y++) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
for (int x = 0; x < 4; x++, index++) {
|
||||||
@ -1130,10 +1132,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
private static final Field fieldNonEmptyBlockCount;
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -138,8 +138,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
|
Field tmpFieldBiomes;
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
try {
|
||||||
|
// It seems to actually be biomes, but is apparently obfuscated to "j"
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("j");
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -497,6 +504,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return new LevelChunkSection(layer, dataPaletteBlocks, biomes);
|
return new LevelChunkSection(layer, dataPaletteBlocks, biomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
|
try {
|
||||||
|
fieldBiomes.set(section, biomes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LOGGER.error("Could not set biomes to chunk section", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
||||||
*/
|
*/
|
||||||
|
@ -510,7 +510,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
PalettedContainer<Holder<Biome>> paletteBiomes = setBiomesToPalettedContainer(
|
||||||
|
biomes,
|
||||||
|
setSectionIndex,
|
||||||
|
existingSection.getBiomes()
|
||||||
|
);
|
||||||
|
if (paletteBiomes != null) {
|
||||||
|
PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,11 +559,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||||
biomeHolderIdMap,
|
biomeHolderIdMap,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES
|
PalettedContainer.Strategy.SECTION_BIOMES
|
||||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||||
newSection = PaperweightPlatformAdapter.newChunkSection(
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
@ -623,15 +626,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
existingSection.getBiomes()
|
existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
|
|
||||||
newSection =
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
PaperweightPlatformAdapter.newChunkSection(
|
layerNo,
|
||||||
layerNo,
|
this::loadPrivately,
|
||||||
this::loadPrivately,
|
setArr,
|
||||||
setArr,
|
adapter,
|
||||||
adapter,
|
biomeRegistry,
|
||||||
biomeRegistry,
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
biomeData
|
);
|
||||||
);
|
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
existingSection,
|
existingSection,
|
||||||
@ -843,7 +845,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
finalizer.run();
|
queueHandler.async(finalizer, null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -1100,9 +1102,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
|
BiomeType[] sectionBiomes;
|
||||||
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
PalettedContainer<Holder<Biome>> biomeData;
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomeData = palettedContainer;
|
biomeData = palettedContainer.copy();
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
||||||
@ -1112,10 +1118,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
);
|
);
|
||||||
biomeData = data.recreate();
|
biomeData = data.recreate();
|
||||||
}
|
}
|
||||||
BiomeType[] sectionBiomes;
|
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
|
||||||
return biomeData;
|
|
||||||
}
|
|
||||||
for (int y = 0, index = 0; y < 4; y++) {
|
for (int y = 0, index = 0; y < 4; y++) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
for (int x = 0; x < 4; x++, index++) {
|
||||||
@ -1127,10 +1129,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,6 @@ import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftChunk;
|
import org.bukkit.craftbukkit.v1_20_R1.CraftChunk;
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -101,7 +100,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
private static final Field fieldNonEmptyBlockCount;
|
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -110,6 +108,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
private static final Field fieldOffers;
|
private static final Field fieldOffers;
|
||||||
private static final MerchantOffers OFFERS = new MerchantOffers();
|
private static final MerchantOffers OFFERS = new MerchantOffers();
|
||||||
@ -148,8 +147,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
|
Field tmpFieldBiomes;
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
try {
|
||||||
|
// It seems to actually be biomes, but is apparently obfuscated to "i"
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i");
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -412,7 +418,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
if (set == null) {
|
if (set == null) {
|
||||||
return newChunkSection(layer, biomeRegistry, biomes);
|
return newChunkSection(biomeRegistry, biomes);
|
||||||
}
|
}
|
||||||
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
||||||
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
||||||
@ -502,7 +508,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation") // Only deprecated in paper
|
@SuppressWarnings("deprecation") // Only deprecated in paper
|
||||||
private static LevelChunkSection newChunkSection(
|
private static LevelChunkSection newChunkSection(
|
||||||
int layer,
|
|
||||||
Registry<Biome> biomeRegistry,
|
Registry<Biome> biomeRegistry,
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
@ -517,6 +522,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
|
try {
|
||||||
|
fieldBiomes.set(section, biomes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LOGGER.error("Could not set biomes to chunk section", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,11 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||||
import net.minecraft.core.*;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.IdMap;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.nbt.IntTag;
|
import net.minecraft.nbt.IntTag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
@ -42,7 +46,14 @@ import net.minecraft.world.level.biome.Biome;
|
|||||||
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.*;
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.LinearPalette;
|
||||||
|
import net.minecraft.world.level.chunk.Palette;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainerRO;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -52,7 +63,17 @@ import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock;
|
|||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.*;
|
import java.util.AbstractSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -497,7 +518,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
PalettedContainer<Holder<Biome>> paletteBiomes = setBiomesToPalettedContainer(
|
||||||
|
biomes,
|
||||||
|
setSectionIndex,
|
||||||
|
existingSection.getBiomes()
|
||||||
|
);
|
||||||
|
if (paletteBiomes != null) {
|
||||||
|
PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,11 +567,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||||
biomeHolderIdMap,
|
biomeHolderIdMap,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES
|
PalettedContainer.Strategy.SECTION_BIOMES
|
||||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||||
newSection = PaperweightPlatformAdapter.newChunkSection(
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
@ -610,15 +634,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
existingSection.getBiomes()
|
existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
|
|
||||||
newSection =
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
PaperweightPlatformAdapter.newChunkSection(
|
layerNo,
|
||||||
layerNo,
|
this::loadPrivately,
|
||||||
this::loadPrivately,
|
setArr,
|
||||||
setArr,
|
adapter,
|
||||||
adapter,
|
biomeRegistry,
|
||||||
biomeRegistry,
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
biomeData
|
);
|
||||||
);
|
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
existingSection,
|
existingSection,
|
||||||
@ -830,7 +853,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
finalizer.run();
|
queueHandler.async(finalizer, null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -1087,9 +1110,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
|
BiomeType[] sectionBiomes;
|
||||||
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
PalettedContainer<Holder<Biome>> biomeData;
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomeData = palettedContainer;
|
biomeData = palettedContainer.copy();
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
||||||
@ -1099,10 +1126,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
);
|
);
|
||||||
biomeData = data.recreate();
|
biomeData = data.recreate();
|
||||||
}
|
}
|
||||||
BiomeType[] sectionBiomes;
|
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
|
||||||
return biomeData;
|
|
||||||
}
|
|
||||||
for (int y = 0, index = 0; y < 4; y++) {
|
for (int y = 0, index = 0; y < 4; y++) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
for (int x = 0; x < 4; x++, index++) {
|
||||||
@ -1114,10 +1137,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.CraftChunk;
|
import org.bukkit.craftbukkit.v1_20_R2.CraftChunk;
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -98,7 +97,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
private static final Field fieldNonEmptyBlockCount;
|
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -107,6 +105,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
* This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||||
@ -142,8 +141,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
|
Field tmpFieldBiomes;
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
try {
|
||||||
|
// It seems to actually be biomes, but is apparently obfuscated to "i"
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i");
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -403,7 +409,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
if (set == null) {
|
if (set == null) {
|
||||||
return newChunkSection(layer, biomeRegistry, biomes);
|
return newChunkSection(biomeRegistry, biomes);
|
||||||
}
|
}
|
||||||
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
||||||
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
||||||
@ -493,7 +499,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation") // Only deprecated in paper
|
@SuppressWarnings("deprecation") // Only deprecated in paper
|
||||||
private static LevelChunkSection newChunkSection(
|
private static LevelChunkSection newChunkSection(
|
||||||
int layer,
|
|
||||||
Registry<Biome> biomeRegistry,
|
Registry<Biome> biomeRegistry,
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
@ -508,6 +513,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
|
try {
|
||||||
|
fieldBiomes.set(section, biomes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LOGGER.error("Could not set biomes to chunk section", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,11 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||||
import net.minecraft.core.*;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.IdMap;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.nbt.IntTag;
|
import net.minecraft.nbt.IntTag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
@ -42,7 +46,14 @@ import net.minecraft.world.level.biome.Biome;
|
|||||||
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.*;
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.LinearPalette;
|
||||||
|
import net.minecraft.world.level.chunk.Palette;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainerRO;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -52,7 +63,17 @@ import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock;
|
|||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.*;
|
import java.util.AbstractSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -497,7 +518,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
PalettedContainer<Holder<Biome>> paletteBiomes = setBiomesToPalettedContainer(
|
||||||
|
biomes,
|
||||||
|
setSectionIndex,
|
||||||
|
existingSection.getBiomes()
|
||||||
|
);
|
||||||
|
if (paletteBiomes != null) {
|
||||||
|
PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,11 +567,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||||
biomeHolderIdMap,
|
biomeHolderIdMap,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES
|
PalettedContainer.Strategy.SECTION_BIOMES
|
||||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||||
newSection = PaperweightPlatformAdapter.newChunkSection(
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
@ -610,15 +634,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
existingSection.getBiomes()
|
existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
|
|
||||||
newSection =
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
PaperweightPlatformAdapter.newChunkSection(
|
layerNo,
|
||||||
layerNo,
|
this::loadPrivately,
|
||||||
this::loadPrivately,
|
setArr,
|
||||||
setArr,
|
adapter,
|
||||||
adapter,
|
biomeRegistry,
|
||||||
biomeRegistry,
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
biomeData
|
);
|
||||||
);
|
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
existingSection,
|
existingSection,
|
||||||
@ -830,7 +853,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
finalizer.run();
|
queueHandler.async(finalizer, null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -1087,9 +1110,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
|
BiomeType[] sectionBiomes;
|
||||||
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
PalettedContainer<Holder<Biome>> biomeData;
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomeData = palettedContainer;
|
biomeData = palettedContainer.copy();
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
||||||
@ -1099,10 +1126,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
);
|
);
|
||||||
biomeData = data.recreate();
|
biomeData = data.recreate();
|
||||||
}
|
}
|
||||||
BiomeType[] sectionBiomes;
|
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
|
||||||
return biomeData;
|
|
||||||
}
|
|
||||||
for (int y = 0, index = 0; y < 4; y++) {
|
for (int y = 0, index = 0; y < 4; y++) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
for (int x = 0; x < 4; x++, index++) {
|
||||||
@ -1114,10 +1137,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
private static final Field fieldNonEmptyBlockCount;
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -141,8 +141,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
|
Field tmpFieldBiomes;
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
try {
|
||||||
|
// It seems to actually be biomes, but is apparently obfuscated to "i"
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i");
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -402,7 +409,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
if (set == null) {
|
if (set == null) {
|
||||||
return newChunkSection(layer, biomeRegistry, biomes);
|
return newChunkSection(biomeRegistry, biomes);
|
||||||
}
|
}
|
||||||
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
||||||
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
||||||
@ -492,7 +499,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation") // Only deprecated in paper
|
@SuppressWarnings("deprecation") // Only deprecated in paper
|
||||||
private static LevelChunkSection newChunkSection(
|
private static LevelChunkSection newChunkSection(
|
||||||
int layer,
|
|
||||||
Registry<Biome> biomeRegistry,
|
Registry<Biome> biomeRegistry,
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
@ -507,6 +513,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
|
try {
|
||||||
|
fieldBiomes.set(section, biomes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LOGGER.error("Could not set biomes to chunk section", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,11 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||||
import net.minecraft.core.*;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.IdMap;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.nbt.IntTag;
|
import net.minecraft.nbt.IntTag;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
@ -43,7 +47,14 @@ import net.minecraft.world.level.biome.Biome;
|
|||||||
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.*;
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.LinearPalette;
|
||||||
|
import net.minecraft.world.level.chunk.Palette;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainerRO;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -53,7 +64,17 @@ import org.bukkit.craftbukkit.block.CraftBlock;
|
|||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.*;
|
import java.util.AbstractSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -499,7 +520,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
PalettedContainer<Holder<Biome>> paletteBiomes = setBiomesToPalettedContainer(
|
||||||
|
biomes,
|
||||||
|
setSectionIndex,
|
||||||
|
existingSection.getBiomes()
|
||||||
|
);
|
||||||
|
if (paletteBiomes != null) {
|
||||||
|
PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,11 +569,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||||
biomeHolderIdMap,
|
biomeHolderIdMap,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES
|
PalettedContainer.Strategy.SECTION_BIOMES
|
||||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||||
newSection = PaperweightPlatformAdapter.newChunkSection(
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
@ -612,18 +636,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
existingSection.getBiomes()
|
existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
|
|
||||||
newSection =
|
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||||
PaperweightPlatformAdapter.newChunkSection(
|
layerNo,
|
||||||
layerNo,
|
this::loadPrivately,
|
||||||
this::loadPrivately,
|
setArr,
|
||||||
setArr,
|
adapter,
|
||||||
adapter,
|
biomeRegistry,
|
||||||
biomeRegistry,
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
biomeData
|
);
|
||||||
);
|
if (!PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, existingSection,
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
|
||||||
levelChunkSections,
|
|
||||||
existingSection,
|
|
||||||
newSection,
|
newSection,
|
||||||
getSectionIndex
|
getSectionIndex
|
||||||
)) {
|
)) {
|
||||||
@ -832,7 +853,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
finalizer.run();
|
queueHandler.async(finalizer, null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -1089,9 +1110,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
|
BiomeType[] sectionBiomes;
|
||||||
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
PalettedContainer<Holder<Biome>> biomeData;
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomeData = palettedContainer;
|
biomeData = palettedContainer.copy();
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
||||||
@ -1101,10 +1126,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
);
|
);
|
||||||
biomeData = data.recreate();
|
biomeData = data.recreate();
|
||||||
}
|
}
|
||||||
BiomeType[] sectionBiomes;
|
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
|
||||||
return biomeData;
|
|
||||||
}
|
|
||||||
for (int y = 0, index = 0; y < 4; y++) {
|
for (int y = 0, index = 0; y < 4; y++) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
for (int x = 0; x < 4; x++, index++) {
|
||||||
@ -1116,10 +1137,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import com.fastasyncworldedit.core.math.BitArrayUnstretched;
|
|||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.mojang.datafixers.util.Either;
|
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||||
@ -76,7 +75,6 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -97,7 +95,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
private static final Field fieldNonEmptyBlockCount;
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -141,8 +139,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
|
Field tmpFieldBiomes;
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
try {
|
||||||
|
// It seems to actually be biomes, but is apparently obfuscated to "i"
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i");
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -400,7 +405,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
if (set == null) {
|
if (set == null) {
|
||||||
return newChunkSection(layer, biomeRegistry, biomes);
|
return newChunkSection(biomeRegistry, biomes);
|
||||||
}
|
}
|
||||||
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
||||||
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
||||||
@ -490,7 +495,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation") // Only deprecated in paper
|
@SuppressWarnings("deprecation") // Only deprecated in paper
|
||||||
private static LevelChunkSection newChunkSection(
|
private static LevelChunkSection newChunkSection(
|
||||||
int layer,
|
|
||||||
Registry<Biome> biomeRegistry,
|
Registry<Biome> biomeRegistry,
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||||
) {
|
) {
|
||||||
@ -505,6 +509,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
return new LevelChunkSection(dataPaletteBlocks, biomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
|
try {
|
||||||
|
fieldBiomes.set(section, biomes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LOGGER.error("Could not set biomes to chunk section", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
||||||
*/
|
*/
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren