9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

Merge branch 'Xiao-MoMi:dev' into dev

This commit is contained in:
jhqwqmc
2025-03-24 16:56:24 +08:00
committed by GitHub
6 changed files with 131 additions and 1 deletions

View File

@@ -210,6 +210,10 @@ performance:
# Disabling this option prevents the plugin from converting custom blocks to vanilla states when chunks are unloaded.
# While this can improve performance, custom blocks will turn into air if the plugin is uninstalled.
restore-vanilla-blocks-on-chunk-unload: true
# When you edit a map locally using CraftEngine fabric mod, the custom block data is not immediately synchronized with the
# server's CraftEngine internal data. Enabling this option will synchronize the data when the chunk is loaded.
# (This option only slightly impacts performance, which has been fully optimized, so you don't need to worry too much.)
sync-custom-blocks-on-chunk-load: false
# If you disable this, it's a must to disable the above option.
restore-custom-blocks-on-chunk-load: true

View File

@@ -121,7 +121,9 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
throw new IllegalArgumentException("stage property not set for sapling");
}
double boneMealSuccessChance = MiscUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45));
if (arguments.containsKey("tags")) {
if (arguments.containsKey("bottom-block-tags")) {
return new SaplingBlockBehavior(Key.of(feature), stageProperty, MiscUtils.getAsStringList(arguments.get("bottom-block-tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList(), boneMealSuccessChance);
} else if (arguments.containsKey("tags")) {
return new SaplingBlockBehavior(Key.of(feature), stageProperty, MiscUtils.getAsStringList(arguments.get("tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList(), boneMealSuccessChance);
} else {
return new SaplingBlockBehavior(Key.of(feature), stageProperty, List.of(DIRT_TAG, FARMLAND), boneMealSuccessChance);

View File

@@ -1823,6 +1823,12 @@ public class Reflections {
)
);
public static final Method method$LevelChunkSection$getBlockState = requireNonNull(
ReflectionUtils.getMethod(
clazz$LevelChunkSection, clazz$BlockState, int.class, int.class, int.class
)
);
public static final Class<?> clazz$StatePredicate = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("world.level.block.state.BlockBehaviour$StatePredicate"),
@@ -5371,4 +5377,55 @@ public class Reflections {
throw new RuntimeException(e);
}
}
public static final Class<?> clazz$SingleValuePalette = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("world.level.chunk.SingleValuePalette")
)
);
public static final Field field$SingleValuePalette$value = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$SingleValuePalette, Object.class, 0
)
);
public static final Class<?> clazz$HashMapPalette = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("world.level.chunk.HashMapPalette"),
BukkitReflectionUtils.assembleMCClass("world.level.chunk.DataPaletteHash")
)
);
public static final Class<?> clazz$CrudeIncrementalIntIdentityHashBiMap = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("util.CrudeIncrementalIntIdentityHashBiMap"),
BukkitReflectionUtils.assembleMCClass("util.RegistryID")
)
);
public static final Field field$CrudeIncrementalIntIdentityHashBiMap$keys = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$CrudeIncrementalIntIdentityHashBiMap, Object.class.arrayType(), 0
)
);
public static final Field field$HashMapPalette$values = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$HashMapPalette, clazz$CrudeIncrementalIntIdentityHashBiMap, 0
)
);
public static final Class<?> clazz$LinearPalette = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("world.level.chunk.LinearPalette"),
BukkitReflectionUtils.assembleMCClass("world.level.chunk.DataPaletteLinear")
)
);
public static final Field field$LinearPalette$values = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$LinearPalette, Object.class.arrayType(), 0
)
);
}

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.world;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
@@ -253,6 +254,55 @@ public class BukkitWorldManager implements WorldManager, Listener {
for (int i = 0; i < ceSections.length; i++) {
CESection ceSection = ceSections[i];
Object section = sections[i];
if (ConfigManager.syncCustomBlocks()) {
Object statesContainer = Reflections.field$LevelChunkSection$states.get(section);
Object data = Reflections.field$PalettedContainer$data.get(statesContainer);
Object palette = Reflections.field$PalettedContainer$Data$palette.get(data);
boolean requiresSync = false;
if (Reflections.clazz$SingleValuePalette.isInstance(palette)) {
Object onlyBlockState = Reflections.field$SingleValuePalette$value.get(palette);
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(onlyBlockState))) {
requiresSync = true;
}
} else if (Reflections.clazz$LinearPalette.isInstance(palette)) {
Object[] blockStates = (Object[]) Reflections.field$LinearPalette$values.get(palette);
for (Object blockState : blockStates) {
if (blockState != null) {
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(blockState))) {
requiresSync = true;
break;
}
}
}
} else if (Reflections.clazz$HashMapPalette.isInstance(palette)) {
Object biMap = Reflections.field$HashMapPalette$values.get(palette);
Object[] blockStates = (Object[]) Reflections.field$CrudeIncrementalIntIdentityHashBiMap$keys.get(biMap);
for (Object blockState : blockStates) {
if (blockState != null) {
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(blockState))) {
requiresSync = true;
break;
}
}
}
} else {
requiresSync = true;
}
if (requiresSync) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
Object mcState = Reflections.method$LevelChunkSection$getBlockState.invoke(section, x, y, z);
int stateId = BlockStateUtils.blockStateToId(mcState);
ImmutableBlockState customState = this.plugin.blockManager().getImmutableBlockState(stateId);
if (customState != null) {
ceSection.setBlockState(x, y, z, customState);
}
}
}
}
}
}
if (ConfigManager.restoreCustomBlocks()) {
if (!ceSection.statesContainer().isEmpty()) {
for (int x = 0; x < 16; x++) {
@@ -286,4 +336,6 @@ public class BukkitWorldManager implements WorldManager, Listener {
}
ceChunk.load();
}
}

View File

@@ -95,6 +95,7 @@ public class ConfigManager implements Reloadable {
protected int performance$max_block_chain_update_limit;
protected boolean performance$chunk_system$restore_vanilla_blocks_on_chunk_unload;
protected boolean performance$chunk_system$restore_custom_blocks_on_chunk_load;
protected boolean performance$chunk_system$sync_custom_blocks_on_chunk_load;
protected boolean furniture$remove_invalid_furniture_on_chunk_load$enable;
protected Set<String> furniture$remove_invalid_furniture_on_chunk_load$list;
@@ -236,6 +237,7 @@ public class ConfigManager implements Reloadable {
performance$light_system$enable = config.getBoolean("performance.light-system.enable", true);
performance$chunk_system$restore_vanilla_blocks_on_chunk_unload = config.getBoolean("performance.chunk-system.restore-vanilla-blocks-on-chunk-unload", true);
performance$chunk_system$restore_custom_blocks_on_chunk_load = config.getBoolean("performance.chunk-system.restore-custom-blocks-on-chunk-load", true);
performance$chunk_system$sync_custom_blocks_on_chunk_load = config.getBoolean("performance.chunk-system.sync-custom-blocks-on-chunk-load", false);
// furniture
furniture$remove_invalid_furniture_on_chunk_load$enable = config.getBoolean("furniture.remove-invalid-furniture-on-chunk-load.enable", false);
@@ -342,6 +344,10 @@ public class ConfigManager implements Reloadable {
return instance.performance$chunk_system$restore_custom_blocks_on_chunk_load;
}
public static boolean syncCustomBlocks() {
return instance.performance$chunk_system$sync_custom_blocks_on_chunk_load;
}
public static List<String> foldersToMerge() {
return instance.resource_pack$merge_external_folders;
}

View File

@@ -24,6 +24,15 @@ public class ChunkPos {
this.longKey = asLong(this.x, this.z);
}
@Override
public String toString() {
return "ChunkPos{" +
"x=" + x +
", z=" + z +
", longKey=" + longKey +
'}';
}
public int x() {
return x;
}