mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
Merge branch 'IntellectualSites:main' into main
This commit is contained in:
commit
9bb13e0384
@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT"
|
|||||||
griefprevention = "17.0.0"
|
griefprevention = "17.0.0"
|
||||||
griefdefender = "2.1.0-SNAPSHOT"
|
griefdefender = "2.1.0-SNAPSHOT"
|
||||||
residence = "4.5._13.1"
|
residence = "4.5._13.1"
|
||||||
towny = "0.100.2.14"
|
towny = "0.100.3.2"
|
||||||
plotsquared = "7.3.8"
|
plotsquared = "7.3.8"
|
||||||
|
|
||||||
# Third party
|
# Third party
|
||||||
|
@ -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,14 +628,13 @@ 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
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
@ -822,7 +824,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
nmsChunk.mustNotSave = false;
|
nmsChunk.mustNotSave = false;
|
||||||
nmsChunk.setUnsaved(true);
|
nmsChunk.setUnsaved(true);
|
||||||
// send to player
|
// send to player
|
||||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
@ -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,41 +1105,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
biomeData = palettedContainer;
|
|
||||||
} else {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
|
||||||
"type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
data.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
biomeData = data.recreate();
|
|
||||||
}
|
|
||||||
BiomeType[] sectionBiomes;
|
BiomeType[] sectionBiomes;
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
return biomeData;
|
return null;
|
||||||
}
|
}
|
||||||
|
PalettedContainer<Holder<Biome>> biomeData = data.recreate();
|
||||||
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++) {
|
||||||
BiomeType biomeType = sectionBiomes[index];
|
BiomeType biomeType = sectionBiomes[index];
|
||||||
if (biomeType == null) {
|
if (biomeType == null) {
|
||||||
continue;
|
biomeData.set(x, y, z, data.get(x, y, z));
|
||||||
}
|
} else {
|
||||||
biomeData.set(
|
biomeData.set(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return biomeData;
|
return biomeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
final ServerLevel serverLevel;
|
final ServerLevel serverLevel;
|
||||||
final LevelChunk levelChunk;
|
final LevelChunk levelChunk;
|
||||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
private Holder<Biome>[][] biomes = null;
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||||
this.levelChunk = levelChunk;
|
this.levelChunk = levelChunk;
|
||||||
@ -144,7 +144,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,10 +173,15 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||||
if (biomes == null) {
|
if (biomes == null) {
|
||||||
biomes = new PalettedContainer[getSectionCount()];
|
biomes = new Holder[getSectionCount()][];
|
||||||
|
}
|
||||||
|
if (biomes[layer] == null) {
|
||||||
|
biomes[layer] = new Holder[64];
|
||||||
}
|
}
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomes[layer] = palettedContainer.copy();
|
for (int i = 0; i < 64; i++) {
|
||||||
|
biomes[layer][i] = palettedContainer.get(i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
||||||
|
@ -98,7 +98,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;
|
||||||
|
|
||||||
@ -139,8 +139,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",
|
||||||
@ -502,6 +509,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,14 +626,13 @@ 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
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
@ -820,7 +822,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
nmsChunk.mustNotSave = false;
|
nmsChunk.mustNotSave = false;
|
||||||
nmsChunk.setUnsaved(true);
|
nmsChunk.setUnsaved(true);
|
||||||
// send to player
|
// send to player
|
||||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
@ -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,41 +1102,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
biomeData = palettedContainer;
|
|
||||||
} else {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
|
||||||
"type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
data.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
biomeData = data.recreate();
|
|
||||||
}
|
|
||||||
BiomeType[] sectionBiomes;
|
BiomeType[] sectionBiomes;
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
return biomeData;
|
return null;
|
||||||
}
|
}
|
||||||
|
PalettedContainer<Holder<Biome>> biomeData = data.recreate();
|
||||||
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++) {
|
||||||
BiomeType biomeType = sectionBiomes[index];
|
BiomeType biomeType = sectionBiomes[index];
|
||||||
if (biomeType == null) {
|
if (biomeType == null) {
|
||||||
continue;
|
biomeData.set(x, y, z, data.get(x, y, z));
|
||||||
}
|
} else {
|
||||||
biomeData.set(
|
biomeData.set(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return biomeData;
|
return biomeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
final ServerLevel serverLevel;
|
final ServerLevel serverLevel;
|
||||||
final LevelChunk levelChunk;
|
final LevelChunk levelChunk;
|
||||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
private Holder<Biome>[][] biomes = null;
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||||
this.levelChunk = levelChunk;
|
this.levelChunk = levelChunk;
|
||||||
@ -144,7 +144,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,10 +173,15 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||||
if (biomes == null) {
|
if (biomes == null) {
|
||||||
biomes = new PalettedContainer[getSectionCount()];
|
biomes = new Holder[getSectionCount()][];
|
||||||
|
}
|
||||||
|
if (biomes[layer] == null) {
|
||||||
|
biomes[layer] = new Holder[64];
|
||||||
}
|
}
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomes[layer] = palettedContainer.copy();
|
for (int i = 0; i < 64; i++) {
|
||||||
|
biomes[layer][i] = palettedContainer.get(i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
||||||
|
@ -62,7 +62,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;
|
||||||
@ -102,7 +101,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;
|
||||||
|
|
||||||
@ -111,6 +109,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();
|
||||||
@ -149,8 +148,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",
|
||||||
@ -417,7 +423,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();
|
||||||
@ -507,7 +513,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
|
||||||
) {
|
) {
|
||||||
@ -522,6 +527,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,14 +634,13 @@ 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
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
@ -807,7 +830,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
nmsChunk.mustNotSave = false;
|
nmsChunk.mustNotSave = false;
|
||||||
nmsChunk.setUnsaved(true);
|
nmsChunk.setUnsaved(true);
|
||||||
// send to player
|
// send to player
|
||||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
@ -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,41 +1110,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
biomeData = palettedContainer;
|
|
||||||
} else {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
|
||||||
"type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
data.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
biomeData = data.recreate();
|
|
||||||
}
|
|
||||||
BiomeType[] sectionBiomes;
|
BiomeType[] sectionBiomes;
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
return biomeData;
|
return null;
|
||||||
}
|
}
|
||||||
|
PalettedContainer<Holder<Biome>> biomeData = data.recreate();
|
||||||
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++) {
|
||||||
BiomeType biomeType = sectionBiomes[index];
|
BiomeType biomeType = sectionBiomes[index];
|
||||||
if (biomeType == null) {
|
if (biomeType == null) {
|
||||||
continue;
|
biomeData.set(x, y, z, data.get(x, y, z));
|
||||||
}
|
} else {
|
||||||
biomeData.set(
|
biomeData.set(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return biomeData;
|
return biomeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
final ServerLevel serverLevel;
|
final ServerLevel serverLevel;
|
||||||
final LevelChunk levelChunk;
|
final LevelChunk levelChunk;
|
||||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
private Holder<Biome>[][] biomes = null;
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||||
this.levelChunk = levelChunk;
|
this.levelChunk = levelChunk;
|
||||||
@ -144,7 +144,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,10 +173,15 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||||
if (biomes == null) {
|
if (biomes == null) {
|
||||||
biomes = new PalettedContainer[getSectionCount()];
|
biomes = new Holder[getSectionCount()][];
|
||||||
|
}
|
||||||
|
if (biomes[layer] == null) {
|
||||||
|
biomes[layer] = new Holder[64];
|
||||||
}
|
}
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomes[layer] = palettedContainer.copy();
|
for (int i = 0; i < 64; i++) {
|
||||||
|
biomes[layer][i] = palettedContainer.get(i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
||||||
|
@ -59,7 +59,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;
|
||||||
@ -99,7 +98,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;
|
||||||
|
|
||||||
@ -108,6 +106,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
|
||||||
@ -143,8 +142,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",
|
||||||
@ -408,7 +414,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();
|
||||||
@ -498,7 +504,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
|
||||||
) {
|
) {
|
||||||
@ -513,6 +518,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;
|
||||||
@ -496,7 +517,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,11 +566,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(
|
||||||
@ -609,14 +633,13 @@ 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
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||||
levelChunkSections,
|
levelChunkSections,
|
||||||
@ -806,7 +829,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
nmsChunk.mustNotSave = false;
|
nmsChunk.mustNotSave = false;
|
||||||
nmsChunk.setUnsaved(true);
|
nmsChunk.setUnsaved(true);
|
||||||
// send to player
|
// send to player
|
||||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
@ -829,7 +852,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 {
|
||||||
@ -1084,41 +1107,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
biomeData = palettedContainer;
|
|
||||||
} else {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
|
||||||
"type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
data.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
biomeData = data.recreate();
|
|
||||||
}
|
|
||||||
BiomeType[] sectionBiomes;
|
BiomeType[] sectionBiomes;
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
return biomeData;
|
return null;
|
||||||
}
|
}
|
||||||
|
PalettedContainer<Holder<Biome>> biomeData = data.recreate();
|
||||||
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++) {
|
||||||
BiomeType biomeType = sectionBiomes[index];
|
BiomeType biomeType = sectionBiomes[index];
|
||||||
if (biomeType == null) {
|
if (biomeType == null) {
|
||||||
continue;
|
biomeData.set(x, y, z, data.get(x, y, z));
|
||||||
}
|
} else {
|
||||||
biomeData.set(
|
biomeData.set(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return biomeData;
|
return biomeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
final ServerLevel serverLevel;
|
final ServerLevel serverLevel;
|
||||||
final LevelChunk levelChunk;
|
final LevelChunk levelChunk;
|
||||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
private Holder<Biome>[][] biomes = null;
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||||
this.levelChunk = levelChunk;
|
this.levelChunk = levelChunk;
|
||||||
@ -144,7 +144,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,10 +173,15 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||||
if (biomes == null) {
|
if (biomes == null) {
|
||||||
biomes = new PalettedContainer[getSectionCount()];
|
biomes = new Holder[getSectionCount()][];
|
||||||
|
}
|
||||||
|
if (biomes[layer] == null) {
|
||||||
|
biomes[layer] = new Holder[64];
|
||||||
}
|
}
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomes[layer] = palettedContainer.copy();
|
for (int i = 0; i < 64; i++) {
|
||||||
|
biomes[layer][i] = palettedContainer.get(i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
||||||
|
@ -98,7 +98,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;
|
||||||
|
|
||||||
@ -142,8 +142,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",
|
||||||
@ -407,7 +414,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();
|
||||||
@ -497,7 +504,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
|
||||||
) {
|
) {
|
||||||
@ -512,6 +518,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.
|
||||||
*/
|
*/
|
||||||
|
@ -12,6 +12,6 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
|
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
|
||||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240604.210637-112")
|
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240617.192752-122")
|
||||||
compileOnly(libs.paperlib)
|
compileOnly(libs.paperlib)
|
||||||
}
|
}
|
||||||
|
@ -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
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, existingSection,
|
||||||
levelChunkSections,
|
|
||||||
existingSection,
|
|
||||||
newSection,
|
newSection,
|
||||||
getSectionIndex
|
getSectionIndex
|
||||||
)) {
|
)) {
|
||||||
@ -809,7 +830,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
nmsChunk.mustNotSave = false;
|
nmsChunk.mustNotSave = false;
|
||||||
nmsChunk.setUnsaved(true);
|
nmsChunk.setUnsaved(true);
|
||||||
// send to player
|
// send to player
|
||||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
if (finalizer != null) {
|
if (finalizer != null) {
|
||||||
@ -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,41 +1110,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
final int sectionIndex,
|
final int sectionIndex,
|
||||||
final PalettedContainerRO<Holder<Biome>> data
|
final PalettedContainerRO<Holder<Biome>> data
|
||||||
) {
|
) {
|
||||||
PalettedContainer<Holder<Biome>> biomeData;
|
|
||||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
biomeData = palettedContainer;
|
|
||||||
} else {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
|
|
||||||
"type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
data.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
biomeData = data.recreate();
|
|
||||||
}
|
|
||||||
BiomeType[] sectionBiomes;
|
BiomeType[] sectionBiomes;
|
||||||
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
|
||||||
return biomeData;
|
return null;
|
||||||
}
|
}
|
||||||
|
PalettedContainer<Holder<Biome>> biomeData = data.recreate();
|
||||||
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++) {
|
||||||
BiomeType biomeType = sectionBiomes[index];
|
BiomeType biomeType = sectionBiomes[index];
|
||||||
if (biomeType == null) {
|
if (biomeType == null) {
|
||||||
continue;
|
biomeData.set(x, y, z, data.get(x, y, z));
|
||||||
}
|
} else {
|
||||||
biomeData.set(
|
biomeData.set(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType))
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return biomeData;
|
return biomeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
final ServerLevel serverLevel;
|
final ServerLevel serverLevel;
|
||||||
final LevelChunk levelChunk;
|
final LevelChunk levelChunk;
|
||||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
private Holder<Biome>[][] biomes = null;
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||||
this.levelChunk = levelChunk;
|
this.levelChunk = levelChunk;
|
||||||
@ -145,7 +145,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +174,15 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||||
if (biomes == null) {
|
if (biomes == null) {
|
||||||
biomes = new PalettedContainer[getSectionCount()];
|
biomes = new Holder[getSectionCount()][];
|
||||||
|
}
|
||||||
|
if (biomes[layer] == null) {
|
||||||
|
biomes[layer] = new Holder[64];
|
||||||
}
|
}
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||||
biomes[layer] = palettedContainer.copy();
|
for (int i = 0; i < 64; i++) {
|
||||||
|
biomes[layer][i] = palettedContainer.get(i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
||||||
|
@ -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;
|
||||||
@ -77,7 +76,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;
|
||||||
@ -98,7 +96,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;
|
||||||
|
|
||||||
@ -142,8 +140,8 @@ 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"));
|
fieldBiomes = LevelChunkSection.class.getDeclaredField(Refraction.pickName("biomes", "i"));
|
||||||
fieldNonEmptyBlockCount.setAccessible(true);
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
"getVisibleChunkIfPresent",
|
"getVisibleChunkIfPresent",
|
||||||
@ -405,7 +403,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();
|
||||||
@ -495,7 +493,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
|
||||||
) {
|
) {
|
||||||
@ -510,6 +507,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.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fastasyncworldedit.bukkit.regions;
|
package com.fastasyncworldedit.bukkit.regions;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.regions.FaweMask;
|
import com.fastasyncworldedit.core.regions.FaweMask;
|
||||||
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
@ -158,6 +159,9 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweMask getMask(com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
|
public FaweMask getMask(com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
|
||||||
|
if (isWhitelist && Settings.settings().REGION_RESTRICTIONS_OPTIONS.WORLDGUARD_REGION_BLACKLIST) {
|
||||||
|
return new FaweMask(RegionWrapper.GLOBAL());
|
||||||
|
}
|
||||||
final Player player = BukkitAdapter.adapt(wePlayer);
|
final Player player = BukkitAdapter.adapt(wePlayer);
|
||||||
final LocalPlayer localplayer = this.worldguard.wrapPlayer(player);
|
final LocalPlayer localplayer = this.worldguard.wrapPlayer(player);
|
||||||
final Location location = player.getLocation();
|
final Location location = player.getLocation();
|
||||||
|
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
||||||
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
||||||
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
||||||
@ -105,6 +106,8 @@ public class Fawe {
|
|||||||
* Implementation dependent stuff
|
* Implementation dependent stuff
|
||||||
*/
|
*/
|
||||||
this.setupConfigs();
|
this.setupConfigs();
|
||||||
|
FaweLimit.MAX.CONFIRM_LARGE =
|
||||||
|
Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS;
|
||||||
TaskManager.IMP = this.implementation.getTaskManager();
|
TaskManager.IMP = this.implementation.getTaskManager();
|
||||||
|
|
||||||
TaskManager.taskManager().async(() -> {
|
TaskManager.taskManager().async(() -> {
|
||||||
|
@ -791,6 +791,11 @@ public class Settings extends Config {
|
|||||||
})
|
})
|
||||||
public boolean UNSTUCK_ON_GENERATE = true;
|
public boolean UNSTUCK_ON_GENERATE = true;
|
||||||
|
|
||||||
|
@Comment({
|
||||||
|
"If unlimited limits should still require /confirm on large. Defaults to limits.default.confirm-large otherwise."
|
||||||
|
})
|
||||||
|
public boolean LIMIT_UNLIMITED_CONFIRMS = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,22 +21,17 @@ import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
|||||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TransformFactory extends AbstractFactory<ResettableExtent> {
|
public class TransformFactory extends AbstractFactory<ResettableExtent> {
|
||||||
|
|
||||||
private final RichTransformParser richTransformParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new factory.
|
* Create a new factory.
|
||||||
*
|
*
|
||||||
* @param worldEdit the WorldEdit instance
|
* @param worldEdit the WorldEdit instance
|
||||||
*/
|
*/
|
||||||
public TransformFactory(WorldEdit worldEdit) {
|
public TransformFactory(WorldEdit worldEdit) {
|
||||||
super(worldEdit, new NullTransformParser(worldEdit));
|
super(worldEdit, new NullTransformParser(worldEdit), new RichTransformParser(worldEdit));
|
||||||
|
|
||||||
richTransformParser = new RichTransformParser(worldEdit);
|
|
||||||
|
|
||||||
// split and parse each sub-transform
|
// split and parse each sub-transform
|
||||||
register(new RandomTransformParser(worldEdit));
|
register(new RandomTransformParser(worldEdit));
|
||||||
@ -51,68 +46,7 @@ public class TransformFactory extends AbstractFactory<ResettableExtent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
|
protected ResettableExtent getParsed(final String input, final List<ResettableExtent> transforms) {
|
||||||
List<ResettableExtent> transforms = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String component : input.split(" ")) {
|
|
||||||
if (component.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResettableExtent match = richTransformParser.parseFromInput(component, context);
|
|
||||||
if (match != null) {
|
|
||||||
transforms.add(match);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parseFromParsers(context, transforms, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getResettableExtent(input, transforms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseFromParsers(
|
|
||||||
final ParserContext context,
|
|
||||||
final List<ResettableExtent> transforms,
|
|
||||||
final String component
|
|
||||||
) {
|
|
||||||
ResettableExtent match = null;
|
|
||||||
for (InputParser<ResettableExtent> parser : getParsers()) {
|
|
||||||
match = parser.parseFromInput(component, context);
|
|
||||||
|
|
||||||
if (match != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match == null) {
|
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
|
|
||||||
}
|
|
||||||
transforms.add(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a transform without considering parsing through the {@link RichTransformParser}, therefore not accepting
|
|
||||||
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
|
|
||||||
*
|
|
||||||
* @param input input string
|
|
||||||
* @param context input context
|
|
||||||
* @return parsed result
|
|
||||||
* @throws InputParseException if no result found
|
|
||||||
*/
|
|
||||||
public ResettableExtent parseWithoutRich(String input, ParserContext context) throws InputParseException {
|
|
||||||
List<ResettableExtent> transforms = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String component : input.split(" ")) {
|
|
||||||
if (component.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
parseFromParsers(context, transforms, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getResettableExtent(input, transforms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResettableExtent getResettableExtent(final String input, final List<ResettableExtent> transforms) {
|
|
||||||
switch (transforms.size()) {
|
switch (transforms.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
|
@ -37,14 +37,14 @@ public abstract class FaweParser<T> extends InputParser<T> implements AliasedPar
|
|||||||
for (int i = 0; i < toParse.length(); i++) {
|
for (int i = 0; i < toParse.length(); i++) {
|
||||||
char c = toParse.charAt(i);
|
char c = toParse.charAt(i);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ',', '&' -> {
|
case ',', '&', ' ' -> {
|
||||||
if (expression) {
|
if (expression) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String result = toParse.substring(last, i);
|
String result = toParse.substring(last, i);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
inputs.add(result);
|
inputs.add(result);
|
||||||
and.add(c == '&');
|
and.add(c == '&' || c == ' ');
|
||||||
} else {
|
} else {
|
||||||
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", c));
|
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", c));
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.registry.state.AbstractProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -174,27 +173,23 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter {
|
|||||||
ArrayList<HashMap<String, Object>> palette = new ArrayList<>();
|
ArrayList<HashMap<String, Object>> palette = new ArrayList<>();
|
||||||
for (BlockVector3 point : region) {
|
for (BlockVector3 point : region) {
|
||||||
BlockState block = clipboard.getBlock(point);
|
BlockState block = clipboard.getBlock(point);
|
||||||
int combined = block.getInternalId();
|
char ordinal = block.getOrdinalChar();
|
||||||
BlockType type = block.getBlockType();
|
BlockType type = block.getBlockType();
|
||||||
|
|
||||||
if (type == BlockTypes.STRUCTURE_VOID || indexes.containsKey(combined)) {
|
if (type == BlockTypes.STRUCTURE_VOID || indexes.containsKey(ordinal)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexes.put(combined, (Integer) palette.size());
|
indexes.put(ordinal, palette.size());
|
||||||
HashMap<String, Object> paletteEntry = new HashMap<>();
|
HashMap<String, Object> paletteEntry = new HashMap<>();
|
||||||
paletteEntry.put("Name", type.id());
|
paletteEntry.put("Name", type.id());
|
||||||
if (block.getInternalId() != type.getInternalId()) {
|
if (block.getInternalId() != type.getInternalId()) {
|
||||||
Map<String, Object> properties = null;
|
Map<String, Object> properties = null;
|
||||||
for (AbstractProperty property : (List<AbstractProperty<?>>) type.getProperties()) {
|
for (Map.Entry<Property<?>, Object> entry : block.getStates().entrySet()) {
|
||||||
int propIndex = property.getIndex(block.getInternalId());
|
|
||||||
if (propIndex != 0) {
|
|
||||||
if (properties == null) {
|
if (properties == null) {
|
||||||
properties = new HashMap<>();
|
properties = new HashMap<>();
|
||||||
}
|
}
|
||||||
Object value = property.getValues().get(propIndex);
|
properties.put(entry.getKey().getName(), entry.getValue().toString());
|
||||||
properties.put(property.getName(), value.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
paletteEntry.put("Properties", properties);
|
paletteEntry.put("Properties", properties);
|
||||||
@ -211,16 +206,23 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter {
|
|||||||
for (BlockVector3 point : region) {
|
for (BlockVector3 point : region) {
|
||||||
BaseBlock block = clipboard.getFullBlock(point);
|
BaseBlock block = clipboard.getFullBlock(point);
|
||||||
if (block.getBlockType() != BlockTypes.STRUCTURE_VOID) {
|
if (block.getBlockType() != BlockTypes.STRUCTURE_VOID) {
|
||||||
int combined = block.getInternalId();
|
char ordinal = block.getOrdinalChar();
|
||||||
int index = indexes.get(combined);
|
int index = indexes.get(ordinal);
|
||||||
List<Integer> pos = Arrays.asList(point.x() - min.x(),
|
List<Integer> pos = Arrays.asList(
|
||||||
point.y() - min.y(), point.z() - min.z()
|
point.x() - min.x(),
|
||||||
|
point.y() - min.y(),
|
||||||
|
point.z() - min.z()
|
||||||
);
|
);
|
||||||
if (!block.hasNbtData()) {
|
if (!block.hasNbtData()) {
|
||||||
blocks.add(FaweCache.INSTANCE.asMap("state", index, "pos", pos));
|
blocks.add(FaweCache.INSTANCE.asMap("state", index, "pos", pos));
|
||||||
} else {
|
} else {
|
||||||
|
Map<String, Tag> tag = new HashMap<>(block.getNbtData().getValue());
|
||||||
|
tag.remove("x");
|
||||||
|
tag.remove("y");
|
||||||
|
tag.remove("z");
|
||||||
|
CompoundTag cTag = new CompoundTag(tag);
|
||||||
blocks.add(
|
blocks.add(
|
||||||
FaweCache.INSTANCE.asMap("state", index, "pos", pos, "nbt", block.getNbtData()));
|
FaweCache.INSTANCE.asMap("state", index, "pos", pos, "nbt", cTag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,8 +233,16 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter {
|
|||||||
ArrayList<Map<String, Object>> entities = new ArrayList<>();
|
ArrayList<Map<String, Object>> entities = new ArrayList<>();
|
||||||
for (Entity entity : clipboard.getEntities()) {
|
for (Entity entity : clipboard.getEntities()) {
|
||||||
Location loc = entity.getLocation();
|
Location loc = entity.getLocation();
|
||||||
List<Double> pos = Arrays.asList(loc.x(), loc.y(), loc.z());
|
List<Double> pos = Arrays.asList(
|
||||||
List<Integer> blockPos = Arrays.asList(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
loc.x() - min.x(),
|
||||||
|
loc.y() - min.y(),
|
||||||
|
loc.z() - min.z()
|
||||||
|
);
|
||||||
|
List<Integer> blockPos = Arrays.asList(
|
||||||
|
loc.getBlockX() - min.x(),
|
||||||
|
loc.getBlockY() - min.y(),
|
||||||
|
loc.getBlockZ() - min.z()
|
||||||
|
);
|
||||||
BaseEntity state = entity.getState();
|
BaseEntity state = entity.getState();
|
||||||
if (state != null) {
|
if (state != null) {
|
||||||
CompoundTag nbt = state.getNbtData();
|
CompoundTag nbt = state.getNbtData();
|
||||||
|
@ -353,7 +353,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet {
|
|||||||
os.write((byte) (z));
|
os.write((byte) (z));
|
||||||
// only need to store biomes in the 4x4x4 chunks so only need one byte for y still (signed byte -128 -> 127)
|
// only need to store biomes in the 4x4x4 chunks so only need one byte for y still (signed byte -128 -> 127)
|
||||||
// means -512 -> 508. Add 128 to avoid negative value casting.
|
// means -512 -> 508. Add 128 to avoid negative value casting.
|
||||||
os.write((byte) (y + 32));
|
os.write((byte) (y + 128));
|
||||||
os.writeVarInt(from.getInternalId());
|
os.writeVarInt(from.getInternalId());
|
||||||
os.writeVarInt(to.getInternalId());
|
os.writeVarInt(to.getInternalId());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.fastasyncworldedit.core.limit;
|
package com.fastasyncworldedit.core.limit;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -121,7 +122,8 @@ public class FaweLimit {
|
|||||||
MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE;
|
MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE;
|
||||||
MAX.MAX_EXPRESSION_MS = 50;
|
MAX.MAX_EXPRESSION_MS = 50;
|
||||||
MAX.FAST_PLACEMENT = true;
|
MAX.FAST_PLACEMENT = true;
|
||||||
MAX.CONFIRM_LARGE = true;
|
MAX.CONFIRM_LARGE =
|
||||||
|
Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS;
|
||||||
MAX.RESTRICT_HISTORY_TO_REGIONS = false;
|
MAX.RESTRICT_HISTORY_TO_REGIONS = false;
|
||||||
MAX.STRIP_NBT = Collections.emptySet();
|
MAX.STRIP_NBT = Collections.emptySet();
|
||||||
MAX.UNIVERSAL_DISALLOWED_BLOCKS = false;
|
MAX.UNIVERSAL_DISALLOWED_BLOCKS = false;
|
||||||
|
@ -115,7 +115,7 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
|||||||
* A filter block is used to iterate over blocks / positions. Essentially combines BlockVector3,
|
* A filter block is used to iterate over blocks / positions. Essentially combines BlockVector3,
|
||||||
* Extent and BlockState functions in a way that avoids lookups.
|
* Extent and BlockState functions in a way that avoids lookups.
|
||||||
*/
|
*/
|
||||||
ChunkFilterBlock initFilterBlock();
|
ChunkFilterBlock createFilterBlock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of chunks in this queue.
|
* Returns the number of chunks in this queue.
|
||||||
@ -129,7 +129,14 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
|||||||
*/
|
*/
|
||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
|
|
||||||
default ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, Region region, int chunkX, int chunkZ, boolean full) {
|
default ChunkFilterBlock apply(
|
||||||
|
@Nullable ChunkFilterBlock block,
|
||||||
|
Filter filter,
|
||||||
|
Region region,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
boolean full
|
||||||
|
) {
|
||||||
if (!filter.appliesChunk(chunkX, chunkZ)) {
|
if (!filter.appliesChunk(chunkX, chunkZ)) {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@ -139,8 +146,9 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
|||||||
if (newChunk != null) {
|
if (newChunk != null) {
|
||||||
chunk = newChunk;
|
chunk = newChunk;
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
block = this.initFilterBlock();
|
block = this.createFilterBlock();
|
||||||
}
|
}
|
||||||
|
block.initChunk(chunkX, chunkZ);
|
||||||
chunk.filterBlocks(filter, block, region, full);
|
chunk.filterBlocks(filter, block, region, full);
|
||||||
}
|
}
|
||||||
this.submit(chunk);
|
this.submit(chunk);
|
||||||
|
@ -28,6 +28,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
|||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Countable;
|
import com.sk89q.worldedit.util.Countable;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -133,14 +134,16 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS);
|
final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS);
|
||||||
if (size <= 1) {
|
if (size <= 1) {
|
||||||
// if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially
|
// if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially
|
||||||
|
ChunkFilterBlock block = null;
|
||||||
while (chunksIter.hasNext()) {
|
while (chunksIter.hasNext()) {
|
||||||
BlockVector2 pos = chunksIter.next();
|
BlockVector2 pos = chunksIter.next();
|
||||||
getExtent().apply(null, filter, region, pos.x(), pos.z(), full);
|
block = getExtent().apply(block, filter, region, pos.x(), pos.z(), full);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
|
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
|
||||||
try {
|
try {
|
||||||
final Filter newFilter = filter.fork();
|
final Filter newFilter = filter.fork();
|
||||||
|
final Region newRegion = region.clone();
|
||||||
// Create a chunk that we will reuse/reset for each operation
|
// Create a chunk that we will reuse/reset for each operation
|
||||||
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
|
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
|
||||||
queue.setFastMode(fastmode);
|
queue.setFastMode(fastmode);
|
||||||
@ -162,7 +165,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
chunkX = pos.x();
|
chunkX = pos.x();
|
||||||
chunkZ = pos.z();
|
chunkZ = pos.z();
|
||||||
}
|
}
|
||||||
block = queue.apply(block, newFilter, region, chunkX, chunkZ, full);
|
block = queue.apply(block, newFilter, newRegion, chunkX, chunkZ, full);
|
||||||
}
|
}
|
||||||
queue.flush();
|
queue.flush();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -473,7 +473,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChunkFilterBlock initFilterBlock() {
|
public ChunkFilterBlock createFilterBlock() {
|
||||||
return new CharFilterBlock(this);
|
return new CharFilterBlock(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,23 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
protected static final Section FULL = new Section() {
|
protected static final Section FULL = new Section() {
|
||||||
@Override
|
@Override
|
||||||
public char[] get(CharBlocks blocks, int layer) {
|
public char[] get(CharBlocks blocks, int layer) {
|
||||||
return blocks.blocks[layer];
|
char[] arr = blocks.blocks[layer];
|
||||||
|
if (arr == null) {
|
||||||
|
// Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues
|
||||||
|
return EMPTY.get(blocks, layer, false);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore aggressive switch here.
|
// Ignore aggressive switch here.
|
||||||
@Override
|
@Override
|
||||||
public char[] get(CharBlocks blocks, int layer, boolean aggressive) {
|
public char[] get(CharBlocks blocks, int layer, boolean aggressive) {
|
||||||
return blocks.blocks[layer];
|
char[] arr = blocks.blocks[layer];
|
||||||
|
if (arr == null) {
|
||||||
|
// Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues
|
||||||
|
return EMPTY.get(blocks, layer, false);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -71,7 +71,7 @@ public class PolyhedralRegion extends AbstractRegion {
|
|||||||
public PolyhedralRegion(PolyhedralRegion region) {
|
public PolyhedralRegion(PolyhedralRegion region) {
|
||||||
this(region.world);
|
this(region.world);
|
||||||
vertices.addAll(region.vertices);
|
vertices.addAll(region.vertices);
|
||||||
triangles.addAll(region.triangles);
|
region.triangles.forEach(triangle -> triangles.add(triangle.clone()));
|
||||||
vertexBacklog.addAll(region.vertexBacklog);
|
vertexBacklog.addAll(region.vertexBacklog);
|
||||||
|
|
||||||
minimumPoint = region.minimumPoint;
|
minimumPoint = region.minimumPoint;
|
||||||
|
@ -7,10 +7,14 @@ import com.sk89q.worldedit.math.BlockVector3;
|
|||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.regions.polyhedron.Edge;
|
import com.sk89q.worldedit.regions.polyhedron.Edge;
|
||||||
|
|
||||||
public class Triangle {
|
public class Triangle implements Cloneable {
|
||||||
|
|
||||||
public static double RADIUS = 0.5;
|
public static double RADIUS = 0.5;
|
||||||
|
|
||||||
|
private final BlockVector3 pos1;
|
||||||
|
private final BlockVector3 pos2;
|
||||||
|
private final BlockVector3 pos3;
|
||||||
|
|
||||||
private final double[][] verts = new double[3][3];
|
private final double[][] verts = new double[3][3];
|
||||||
private final double[] center = new double[3];
|
private final double[] center = new double[3];
|
||||||
private final double[] radius = new double[3];
|
private final double[] radius = new double[3];
|
||||||
@ -28,6 +32,9 @@ public class Triangle {
|
|||||||
private final double b;
|
private final double b;
|
||||||
|
|
||||||
public Triangle(BlockVector3 pos1, BlockVector3 pos2, BlockVector3 pos3) {
|
public Triangle(BlockVector3 pos1, BlockVector3 pos2, BlockVector3 pos3) {
|
||||||
|
this.pos1 = pos1;
|
||||||
|
this.pos2 = pos2;
|
||||||
|
this.pos3 = pos3;
|
||||||
verts[0] = new double[]{pos1.x(), pos1.y(), pos1.z()};
|
verts[0] = new double[]{pos1.x(), pos1.y(), pos1.z()};
|
||||||
verts[1] = new double[]{pos2.x(), pos2.y(), pos2.z()};
|
verts[1] = new double[]{pos2.x(), pos2.y(), pos2.z()};
|
||||||
verts[2] = new double[]{pos3.x(), pos3.y(), pos3.z()};
|
verts[2] = new double[]{pos3.x(), pos3.y(), pos3.z()};
|
||||||
@ -290,4 +297,9 @@ public class Triangle {
|
|||||||
return dot(normal, vmax) >= 0.0f;
|
return dot(normal, vmax) >= 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Triangle clone() {
|
||||||
|
return new Triangle(pos1, pos2, pos3);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ package com.sk89q.worldedit.command;
|
|||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweVersion;
|
import com.fastasyncworldedit.core.FaweVersion;
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.UpdateNotification;
|
import com.fastasyncworldedit.core.util.UpdateNotification;
|
||||||
import com.intellectualsites.paster.IncendoPaster;
|
import com.intellectualsites.paster.IncendoPaster;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
@ -97,6 +99,8 @@ public class WorldEditCommands {
|
|||||||
.getConfiguration()));
|
.getConfiguration()));
|
||||||
//FAWE start
|
//FAWE start
|
||||||
Fawe.instance().setupConfigs();
|
Fawe.instance().setupConfigs();
|
||||||
|
FaweLimit.MAX.CONFIRM_LARGE =
|
||||||
|
Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS;
|
||||||
//FAWE end
|
//FAWE end
|
||||||
actor.print(Caption.of("worldedit.reload.config"));
|
actor.print(Caption.of("worldedit.reload.config"));
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,16 @@ import com.sk89q.util.StringUtil;
|
|||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser;
|
import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||||
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||||
|
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,4 +72,21 @@ public class BlockFactory extends AbstractFactory<BaseBlock> {
|
|||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Override
|
||||||
|
public BaseBlock parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||||
|
BaseBlock match;
|
||||||
|
|
||||||
|
for (InputParser<BaseBlock> parser : parsers) {
|
||||||
|
match = parser.parseFromInput(input, context);
|
||||||
|
|
||||||
|
if (match != null) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoMatchException(TranslatableComponent.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,13 @@ package com.sk89q.worldedit.extension.factory;
|
|||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.blocks.BaseItem;
|
import com.sk89q.worldedit.blocks.BaseItem;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.DefaultItemParser;
|
import com.sk89q.worldedit.extension.factory.parser.DefaultItemParser;
|
||||||
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||||
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||||
|
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||||
|
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
|
|
||||||
public class ItemFactory extends AbstractFactory<BaseItem> {
|
public class ItemFactory extends AbstractFactory<BaseItem> {
|
||||||
|
|
||||||
@ -35,4 +41,21 @@ public class ItemFactory extends AbstractFactory<BaseItem> {
|
|||||||
super(worldEdit, new DefaultItemParser(worldEdit));
|
super(worldEdit, new DefaultItemParser(worldEdit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Override
|
||||||
|
public BaseItem parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||||
|
BaseItem match;
|
||||||
|
|
||||||
|
for (InputParser<BaseItem> parser : parsers) {
|
||||||
|
match = parser.parseFromInput(input, context);
|
||||||
|
|
||||||
|
if (match != null) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoMatchException(TranslatableComponent.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,16 +53,13 @@ import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser;
|
|||||||
import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser;
|
import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser;
|
import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser;
|
import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
|
||||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
||||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -75,21 +72,13 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
public final class MaskFactory extends AbstractFactory<Mask> {
|
public final class MaskFactory extends AbstractFactory<Mask> {
|
||||||
|
|
||||||
//FAWE start - rich mask parsing
|
|
||||||
private final RichMaskParser richMaskParser;
|
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new mask registry.
|
* Create a new mask registry.
|
||||||
*
|
*
|
||||||
* @param worldEdit the WorldEdit instance
|
* @param worldEdit the WorldEdit instance
|
||||||
*/
|
*/
|
||||||
public MaskFactory(WorldEdit worldEdit) {
|
public MaskFactory(WorldEdit worldEdit) {
|
||||||
super(worldEdit, new BlocksMaskParser(worldEdit));
|
super(worldEdit, new BlocksMaskParser(worldEdit), new RichMaskParser(worldEdit));
|
||||||
|
|
||||||
//FAWE start - rich mask parsing
|
|
||||||
richMaskParser = new RichMaskParser(worldEdit);
|
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
register(new ExistingMaskParser(worldEdit));
|
register(new ExistingMaskParser(worldEdit));
|
||||||
register(new AirMaskParser(worldEdit));
|
register(new AirMaskParser(worldEdit));
|
||||||
@ -125,7 +114,6 @@ public final class MaskFactory extends AbstractFactory<Mask> {
|
|||||||
register(new ZAxisMaskParser(worldEdit));
|
register(new ZAxisMaskParser(worldEdit));
|
||||||
register(new SurfaceAngleMaskParser(worldEdit));
|
register(new SurfaceAngleMaskParser(worldEdit));
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,85 +121,24 @@ public final class MaskFactory extends AbstractFactory<Mask> {
|
|||||||
final String[] split = input.split(" ");
|
final String[] split = input.split(" ");
|
||||||
if (split.length > 1) {
|
if (split.length > 1) {
|
||||||
String prev = input.substring(0, input.lastIndexOf(" ")) + " ";
|
String prev = input.substring(0, input.lastIndexOf(" ")) + " ";
|
||||||
return super.getSuggestions(split[split.length - 1], parserContext).stream().map(s -> prev + s).collect(Collectors.toList());
|
return super
|
||||||
|
.getSuggestions(split[split.length - 1], parserContext)
|
||||||
|
.stream()
|
||||||
|
.map(s -> prev + s)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
return super.getSuggestions(input, parserContext);
|
return super.getSuggestions(input, parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start - rich mask parsing
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
|
protected Mask getParsed(final String input, final List<Mask> masks) {
|
||||||
List<Mask> masks = new ArrayList<>();
|
return switch (masks.size()) {
|
||||||
|
case 0 -> throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
for (String component : input.split(" ")) {
|
case 1 -> masks.get(0).optimize();
|
||||||
if (component.isEmpty()) {
|
default -> new MaskIntersection(masks).optimize();
|
||||||
continue;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
//FAWE start - rich mask parsing
|
|
||||||
Mask match = richMaskParser.parseFromInput(component, context);
|
|
||||||
if (match != null) {
|
|
||||||
masks.add(match);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parseFromParsers(context, masks, component);
|
|
||||||
//FAWE end
|
|
||||||
}
|
|
||||||
|
|
||||||
return getMask(input, masks);
|
|
||||||
}
|
|
||||||
|
|
||||||
//FAWE start - rich mask parsing
|
|
||||||
private void parseFromParsers(
|
|
||||||
final ParserContext context,
|
|
||||||
final List<Mask> masks,
|
|
||||||
final String component
|
|
||||||
) {
|
|
||||||
Mask match = null;
|
|
||||||
for (InputParser<Mask> parser : getParsers()) {
|
|
||||||
match = parser.parseFromInput(component, context);
|
|
||||||
|
|
||||||
if (match != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match == null) {
|
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
|
|
||||||
}
|
|
||||||
masks.add(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a mask without considering parsing through the {@link RichMaskParser}, therefore not accepting
|
|
||||||
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
|
|
||||||
*
|
|
||||||
* @param input input string
|
|
||||||
* @param context input context
|
|
||||||
* @return parsed result
|
|
||||||
* @throws InputParseException if no result found
|
|
||||||
*/
|
|
||||||
public Mask parseWithoutRich(String input, ParserContext context) throws InputParseException {
|
|
||||||
List<Mask> masks = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String component : input.split(" ")) {
|
|
||||||
if (component.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
parseFromParsers(context, masks, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getMask(input, masks);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mask getMask(final String input, final List<Mask> masks) {
|
|
||||||
switch (masks.size()) {
|
|
||||||
case 0:
|
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
|
||||||
case 1:
|
|
||||||
return masks.get(0).optimize();
|
|
||||||
default:
|
|
||||||
return new MaskIntersection(masks).optimize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
package com.sk89q.worldedit.extension.factory;
|
package com.sk89q.worldedit.extension.factory;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.mask.HotbarMaskParser;
|
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser;
|
||||||
@ -44,8 +43,6 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.OffsetPatter
|
|||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomFullClipboardPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomFullClipboardPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomOffsetPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomOffsetPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.TypeSwapPatternParser;
|
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser;
|
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser;
|
||||||
@ -53,24 +50,22 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.SaturatePatt
|
|||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SolidRandomOffsetPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SolidRandomOffsetPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SurfaceRandomOffsetPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SurfaceRandomOffsetPatternParser;
|
||||||
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.TypeSwapPatternParser;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser;
|
||||||
import com.fastasyncworldedit.core.math.random.TrueRandom;
|
import com.fastasyncworldedit.core.math.random.TrueRandom;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser;
|
import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser;
|
import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser;
|
||||||
|
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser;
|
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser;
|
import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser;
|
||||||
import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser;
|
import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
|
||||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
||||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,20 +77,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class PatternFactory extends AbstractFactory<Pattern> {
|
public final class PatternFactory extends AbstractFactory<Pattern> {
|
||||||
|
|
||||||
//FAWE start - rich pattern parsing
|
|
||||||
private final RichPatternParser richPatternParser;
|
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
*
|
*
|
||||||
* @param worldEdit the WorldEdit instance
|
* @param worldEdit the WorldEdit instance
|
||||||
*/
|
*/
|
||||||
public PatternFactory(WorldEdit worldEdit) {
|
public PatternFactory(WorldEdit worldEdit) {
|
||||||
super(worldEdit, new SingleBlockPatternParser(worldEdit));
|
|
||||||
|
|
||||||
//FAWE start - rich pattern parsing
|
//FAWE start - rich pattern parsing
|
||||||
richPatternParser = new RichPatternParser(worldEdit);
|
super(worldEdit, new SingleBlockPatternParser(worldEdit), new RichPatternParser(worldEdit));
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
// split and parse each sub-pattern
|
// split and parse each sub-pattern
|
||||||
@ -139,75 +128,10 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
|
|||||||
register(new SurfaceRandomOffsetPatternParser(worldEdit));
|
register(new SurfaceRandomOffsetPatternParser(worldEdit));
|
||||||
register(new TypeSwapPatternParser(worldEdit));
|
register(new TypeSwapPatternParser(worldEdit));
|
||||||
register(new VoronoiPatternParser(worldEdit));
|
register(new VoronoiPatternParser(worldEdit));
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
|
protected Pattern getParsed(final String input, final List<Pattern> patterns) {
|
||||||
List<Pattern> patterns = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String component : input.split(" ")) {
|
|
||||||
if (component.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//FAWE start - rich pattern parsing
|
|
||||||
Pattern match = richPatternParser.parseFromInput(component, context);
|
|
||||||
if (match != null) {
|
|
||||||
patterns.add(match);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parseFromParsers(context, patterns, component);
|
|
||||||
//FAWE end
|
|
||||||
}
|
|
||||||
|
|
||||||
return getPattern(input, patterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
//FAWE start - rich pattern parsing
|
|
||||||
private void parseFromParsers(
|
|
||||||
final ParserContext context,
|
|
||||||
final List<Pattern> patterns,
|
|
||||||
final String component
|
|
||||||
) {
|
|
||||||
Pattern match = null;
|
|
||||||
for (InputParser<Pattern> parser : getParsers()) {
|
|
||||||
match = parser.parseFromInput(component, context);
|
|
||||||
|
|
||||||
if (match != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match == null) {
|
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
|
|
||||||
}
|
|
||||||
patterns.add(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting
|
|
||||||
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
|
|
||||||
*
|
|
||||||
* @param input input string
|
|
||||||
* @param context input context
|
|
||||||
* @return parsed result
|
|
||||||
* @throws InputParseException if no result found
|
|
||||||
*/
|
|
||||||
public Pattern parseWithoutRich(String input, ParserContext context) throws InputParseException {
|
|
||||||
List<Pattern> patterns = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String component : input.split(" ")) {
|
|
||||||
if (component.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
parseFromParsers(context, patterns, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getPattern(input, patterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pattern getPattern(final String input, final List<Pattern> patterns) {
|
|
||||||
switch (patterns.size()) {
|
switch (patterns.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
|
@ -106,7 +106,8 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce
|
|||||||
@Override
|
@Override
|
||||||
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
||||||
final ChunkFilterBlock filter = getOrCreateFilterBlock.apply(Thread.currentThread().getId());
|
final ChunkFilterBlock filter = getOrCreateFilterBlock.apply(Thread.currentThread().getId());
|
||||||
return filter.filter(chunk, get, set, MaskingExtent.this);
|
filter.initChunk(chunk.getX(), chunk.getZ());
|
||||||
|
return filter.filter(chunk, get, set, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,6 +21,9 @@ package com.sk89q.worldedit.internal.registry;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser;
|
import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser;
|
||||||
|
import com.fastasyncworldedit.core.extension.factory.parser.FaweParser;
|
||||||
|
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
|
||||||
|
import com.sk89q.util.StringUtil;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||||
@ -43,7 +46,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
public abstract class AbstractFactory<E> {
|
public abstract class AbstractFactory<E> {
|
||||||
|
|
||||||
protected final WorldEdit worldEdit;
|
protected final WorldEdit worldEdit;
|
||||||
private final List<InputParser<E>> parsers = new ArrayList<>();
|
//FAWE start
|
||||||
|
protected final List<InputParser<E>> parsers = new ArrayList<>();
|
||||||
|
private final FaweParser<E> richParser;
|
||||||
|
//FWAE end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new factory.
|
* Create a new factory.
|
||||||
@ -52,11 +58,26 @@ public abstract class AbstractFactory<E> {
|
|||||||
* @param defaultParser the parser to fall back to
|
* @param defaultParser the parser to fall back to
|
||||||
*/
|
*/
|
||||||
protected AbstractFactory(WorldEdit worldEdit, InputParser<E> defaultParser) {
|
protected AbstractFactory(WorldEdit worldEdit, InputParser<E> defaultParser) {
|
||||||
|
//FAWE start
|
||||||
|
this(worldEdit, defaultParser, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new factory with a given rich parser for FAWE rich parsing
|
||||||
|
*
|
||||||
|
* @param worldEdit the WorldEdit instance
|
||||||
|
* @param defaultParser the parser to fall back to
|
||||||
|
* @param richParser the rich parser
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
protected AbstractFactory(WorldEdit worldEdit, InputParser<E> defaultParser, FaweParser<E> richParser) {
|
||||||
checkNotNull(worldEdit);
|
checkNotNull(worldEdit);
|
||||||
checkNotNull(defaultParser);
|
checkNotNull(defaultParser);
|
||||||
this.worldEdit = worldEdit;
|
this.worldEdit = worldEdit;
|
||||||
this.parsers.add(defaultParser);
|
this.parsers.add(defaultParser);
|
||||||
|
this.richParser = richParser;
|
||||||
}
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an immutable list of parsers.
|
* Gets an immutable list of parsers.
|
||||||
@ -71,7 +92,7 @@ public abstract class AbstractFactory<E> {
|
|||||||
return Collections.unmodifiableList(parsers);
|
return Collections.unmodifiableList(parsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start - javadoc
|
//FAWE start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string and context to each {@link InputParser} added to this factory. If no result found, throws {@link InputParseException}
|
* Parse a string and context to each {@link InputParser} added to this factory. If no result found, throws {@link InputParseException}
|
||||||
@ -81,20 +102,26 @@ public abstract class AbstractFactory<E> {
|
|||||||
* @return parsed result
|
* @return parsed result
|
||||||
* @throws InputParseException if no result found
|
* @throws InputParseException if no result found
|
||||||
*/
|
*/
|
||||||
//FAWE end
|
|
||||||
public E parseFromInput(String input, ParserContext context) throws InputParseException {
|
public E parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||||
E match;
|
List<E> parsed = new ArrayList<>();
|
||||||
|
for (String component : StringUtil.split(input,' ', '[', ']')) {
|
||||||
for (InputParser<E> parser : parsers) {
|
if (component.isEmpty()) {
|
||||||
match = parser.parseFromInput(input, context);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (richParser != null) {
|
||||||
|
E match = richParser.parseFromInput(component, context);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
return match;
|
parsed.add(match);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parseFromParsers(context, parsed, component);
|
||||||
|
}
|
||||||
|
|
||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
return getParsed(input, parsed);
|
||||||
}
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public List<String> getSuggestions(String input) {
|
public List<String> getSuggestions(String input) {
|
||||||
@ -133,4 +160,48 @@ public abstract class AbstractFactory<E> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
protected void parseFromParsers(final ParserContext context, final List<E> parsed, final String component) {
|
||||||
|
E match = null;
|
||||||
|
for (InputParser<E> parser : getParsers()) {
|
||||||
|
match = parser.parseFromInput(component, context);
|
||||||
|
|
||||||
|
if (match != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match == null) {
|
||||||
|
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
|
||||||
|
}
|
||||||
|
parsed.add(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting
|
||||||
|
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
|
||||||
|
*
|
||||||
|
* @param input input string
|
||||||
|
* @param context input context
|
||||||
|
* @return parsed result
|
||||||
|
* @throws InputParseException if no result found
|
||||||
|
*/
|
||||||
|
public E parseWithoutRich(String input, ParserContext context) throws InputParseException {
|
||||||
|
List<E> parsed = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String component : StringUtil.split(input, ' ', '[', ']')) {
|
||||||
|
if (component.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseFromParsers(context, parsed, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getParsed(input, parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected E getParsed(final String input, final List<E> parsed) {
|
||||||
|
return parsed.isEmpty() ? null : parsed.get(0);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -755,7 +755,6 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
|||||||
) {
|
) {
|
||||||
int chunkX = chunk.getX();
|
int chunkX = chunk.getX();
|
||||||
int chunkZ = chunk.getZ();
|
int chunkZ = chunk.getZ();
|
||||||
block = block.initChunk(chunkX, chunkZ);
|
|
||||||
|
|
||||||
//Chunk entry is an "interior chunk" in regards to the entire region, so filter the chunk whole instead of partially
|
//Chunk entry is an "interior chunk" in regards to the entire region, so filter the chunk whole instead of partially
|
||||||
if ((minX + 15) >> 4 <= chunkX && (maxX - 15) >> 4 >= chunkX && (minZ + 15) >> 4 <= chunkZ && (maxZ - 15) >> 4 >= chunkZ) {
|
if ((minX + 15) >> 4 <= chunkX && (maxX - 15) >> 4 >= chunkX && (minZ + 15) >> 4 <= chunkZ && (maxZ - 15) >> 4 >= chunkZ) {
|
||||||
|
@ -412,8 +412,6 @@ public class EllipsoidRegion extends AbstractRegion {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = block.initChunk(chunk.getX(), chunk.getZ());
|
|
||||||
|
|
||||||
// Get the solid layers
|
// Get the solid layers
|
||||||
int cy = center.y();
|
int cy = center.y();
|
||||||
int diffYFull = MathMan.usqrt(diffY2);
|
int diffYFull = MathMan.usqrt(diffY2);
|
||||||
|
@ -268,7 +268,6 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
) {
|
) {
|
||||||
int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4);
|
int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4);
|
||||||
int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4);
|
int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4);
|
||||||
block = block.initChunk(chunk.getX(), chunk.getZ());
|
|
||||||
for (int layer = minSection; layer <= maxSection; layer++) {
|
for (int layer = minSection; layer <= maxSection; layer++) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
return;
|
return;
|
||||||
@ -483,7 +482,7 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ public class RegionIntersection extends AbstractRegion {
|
|||||||
BlockVector3 regMin = region.getMinimumPoint();
|
BlockVector3 regMin = region.getMinimumPoint();
|
||||||
BlockVector3 regMax = region.getMaximumPoint();
|
BlockVector3 regMax = region.getMaximumPoint();
|
||||||
if (tx >= regMin.x() && bx <= regMax.x() && tz >= regMin.z() && bz <= regMax.z()) {
|
if (tx >= regMin.x() && bx <= regMax.x() && tz >= regMin.z() && bz <= regMax.z()) {
|
||||||
return region.processSet(chunk, get, set, true);
|
set = region.processSet(chunk, get, set, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return set; // default return set as no "blacklist" regions contained the chunk
|
return set; // default return set as no "blacklist" regions contained the chunk
|
||||||
|
Loading…
Reference in New Issue
Block a user