mirror of
https://github.com/EngineHub/WorldEdit.git
synced 2025-04-06 14:30:42 +08:00
Send biome updates for chunks when possible (#2443)
* Send biome updates [WIP] * Add other platforms * Ensure that the iterable won't be iterated twice
This commit is contained in:
parent
e7c9e64645
commit
1a12db4fbc
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
@ -174,6 +175,7 @@ import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -969,6 +971,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||
|
||||
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
nativeChunks.add(originalWorld.getChunk(chunk.getBlockX(), chunk.getBlockZ(), ChunkStatus.BIOMES, false));
|
||||
}
|
||||
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that is less likely to break
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
@ -174,6 +175,7 @@ import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -970,6 +972,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||
|
||||
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
nativeChunks.add(originalWorld.getChunk(chunk.getBlockX(), chunk.getBlockZ(), ChunkStatus.BIOMES, false));
|
||||
}
|
||||
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that is less likely to break
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
@ -174,6 +175,7 @@ import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -970,6 +972,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||
|
||||
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
nativeChunks.add(originalWorld.getChunk(chunk.getBlockX(), chunk.getBlockZ(), ChunkStatus.BIOMES, false));
|
||||
}
|
||||
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that is less likely to break
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -329,6 +329,14 @@ public class BukkitWorld extends AbstractWorld {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(Iterable<BlockVector2> chunks) {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.sendBiomeUpdates(getWorld(), chunks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playEffect(Vector3 position, int type, int data) {
|
||||
World world = getWorld();
|
||||
|
@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
@ -314,4 +315,17 @@ public interface BukkitImplAdapter {
|
||||
default void initializeRegistries() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends biome updates for the given chunks.
|
||||
*
|
||||
* <p>This doesn't modify biomes at all, it just sends the current state of the biomes
|
||||
* in the world to all of the nearby players, updating the visual representation of the
|
||||
* biomes on their clients.</p>
|
||||
*
|
||||
* @param world the world
|
||||
* @param chunks a list of chunk coordinates to send biome updates for
|
||||
*/
|
||||
default void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.util.collection.BlockMap;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
@ -50,6 +51,7 @@ public class SideEffectExtent extends AbstractDelegateExtent {
|
||||
private final World world;
|
||||
private final Map<BlockVector3, BlockState> positions = BlockMap.create();
|
||||
private final Set<BlockVector2> dirtyChunks = new HashSet<>();
|
||||
private final Set<BlockVector2> dirtyBiomes = new HashSet<>();
|
||||
private SideEffectSet sideEffectSet = SideEffectSet.defaults();
|
||||
private boolean postEditSimulation;
|
||||
|
||||
@ -97,8 +99,14 @@ public class SideEffectExtent extends AbstractDelegateExtent {
|
||||
return world.setBlock(location, block, postEditSimulation ? INTERNAL_NONE : sideEffectSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
dirtyBiomes.add(BlockVector2.at(position.getBlockX() >> 4, position.getBlockZ() >> 4));
|
||||
return world.setBiome(position, biome);
|
||||
}
|
||||
|
||||
public boolean commitRequired() {
|
||||
return postEditSimulation || !dirtyChunks.isEmpty();
|
||||
return postEditSimulation || !dirtyChunks.isEmpty() || !dirtyBiomes.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -113,6 +121,10 @@ public class SideEffectExtent extends AbstractDelegateExtent {
|
||||
world.fixAfterFastMode(dirtyChunks);
|
||||
}
|
||||
|
||||
if (!dirtyBiomes.isEmpty()) {
|
||||
world.sendBiomeUpdates(dirtyBiomes);
|
||||
}
|
||||
|
||||
if (postEditSimulation) {
|
||||
Iterator<Map.Entry<BlockVector3, BlockState>> positionIterator = positions.entrySet().iterator();
|
||||
while (run.shouldContinue() && positionIterator.hasNext()) {
|
||||
|
@ -94,6 +94,10 @@ public abstract class AbstractWorld implements World {
|
||||
public void fixAfterFastMode(Iterable<BlockVector2> chunks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(Iterable<BlockVector2> chunks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLighting(Iterable<BlockVector2> chunks) {
|
||||
}
|
||||
|
@ -311,6 +311,17 @@ public interface World extends Extent, Keyed {
|
||||
*/
|
||||
void fixAfterFastMode(Iterable<BlockVector2> chunks);
|
||||
|
||||
/**
|
||||
* Sends biome updates for the given chunks.
|
||||
*
|
||||
* <p>This doesn't modify biomes at all, it just sends the current state of the biomes
|
||||
* in the world to all of the nearby players, updating the visual representation of the
|
||||
* biomes on their clients.</p>
|
||||
*
|
||||
* @param chunks a list of chunk coordinates to send biome updates for
|
||||
*/
|
||||
void sendBiomeUpdates(Iterable<BlockVector2> chunks);
|
||||
|
||||
/**
|
||||
* Relight the given chunks if possible.
|
||||
*
|
||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
@ -115,6 +116,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -526,6 +528,15 @@ public class FabricWorld extends AbstractWorld {
|
||||
fixLighting(chunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(Iterable<BlockVector2> chunks) {
|
||||
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
nativeChunks.add(getWorld().getChunk(chunk.getBlockX(), chunk.getBlockZ(), ChunkStatus.BIOMES, false));
|
||||
}
|
||||
((ServerLevel) getWorld()).getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLighting(Iterable<BlockVector2> chunks) {
|
||||
Level world = getWorld();
|
||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
@ -113,6 +114,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -508,6 +510,15 @@ public class ForgeWorld extends AbstractWorld {
|
||||
fixLighting(chunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBiomeUpdates(Iterable<BlockVector2> chunks) {
|
||||
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
nativeChunks.add(getWorld().getChunk(chunk.getBlockX(), chunk.getBlockZ(), ChunkStatus.BIOMES, false));
|
||||
}
|
||||
((ServerLevel) getWorld()).getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLighting(Iterable<BlockVector2> chunks) {
|
||||
ServerLevel world = getWorld();
|
||||
|
Loading…
x
Reference in New Issue
Block a user