Additional work towards 1.16 compatibility

- Very basic implementation of the SideEffects system. Will definitely need fine tuning for it to be functional, but is not considered a priority in my opinion.
- Minor changes to the World interface and World implementations related to the SideEffects system. Shouldn't be the cause of any new bugs but be on the lookout.
- Included debug in BukkitImplLoader.java to assist contributors in understanding what needs to be implemented for the adapter to load properly.

Still very WIP but we're a few steps closer. So far, this is coming along better than I anticipated. Hopefully we can keep the momentum.
This commit is contained in:
Matthew Miller
2020-03-08 16:09:36 +10:00
committed by MattBDev
parent 68679e007e
commit 4604aa5920
39 changed files with 877 additions and 176 deletions

View File

@ -61,16 +61,12 @@ tasks.named<Copy>("processResources") {
}
}
<<<<<<< HEAD
addJarManifest(includeClasspath = true)
=======
tasks.named<Jar>("jar") {
manifest {
attributes("Class-Path" to CLASSPATH,
"WorldEdit-Version" to project.version)
}
}
>>>>>>> 18a55bc14... Add new experimental snapshot API (#524)
tasks.named<ShadowJar>("shadowJar") {
archiveClassifier.set("dist-dev")

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.fabric;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
@ -27,13 +28,13 @@ import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries;
import net.minecraft.SharedConstants;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.dedicated.MinecraftDedicatedServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
@ -200,6 +201,18 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform {
return capabilities;
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.CONNECTIONS,
SideEffect.ENTITY_AI,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
);
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SUPPORTED_SIDE_EFFECTS;
}
@Override
public Collection<Actor> getConnectedUsers() {
List<Actor> users = new ArrayList<>();

View File

@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
@ -42,6 +43,8 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -61,6 +64,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
@ -71,6 +75,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldSaveHandler;
import net.minecraft.world.biome.DefaultBiomeFeatures;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
@ -104,6 +109,7 @@ import java.util.Locale;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
@ -185,8 +191,44 @@ public class FabricWorld extends AbstractWorld {
return null;
}
public void markAndNotifyBlock(World world, BlockPos pos, @Nullable WorldChunk worldChunk, net.minecraft.block.BlockState blockState,
net.minecraft.block.BlockState state, SideEffectSet sideEffectSet) {
Block block = state.getBlock();
net.minecraft.block.BlockState blockState2 = world.getBlockState(pos);
if (blockState2 == state) {
if (blockState != blockState2) {
world.checkBlockRerender(pos, blockState, blockState2);
}
if (world.isClient || worldChunk.getLevelType() != null && worldChunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING)) {
if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) {
world.updateListeners(pos, blockState, state, UPDATE | NOTIFY);
} else {
// If we want to skip entity AI, just call the chunk dirty flag.
((ServerChunkManager) world.getChunkManager()).markForUpdate(pos);
}
}
if (!world.isClient && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) {
world.updateNeighbors(pos, blockState.getBlock());
if (state.hasComparatorOutput()) {
world.updateHorizontalAdjacent(pos, block);
}
}
if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) {
blockState.method_11637(world, pos, 2);
state.updateNeighborStates(world, pos, 2);
state.method_11637(world, pos, 2);
}
// This is disabled for other platforms, but keep it for mods.
world.onBlockChanged(pos, blockState, blockState2);
}
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException {
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
checkNotNull(position);
checkNotNull(block);
@ -196,7 +238,7 @@ public class FabricWorld extends AbstractWorld {
int z = position.getBlockZ();
// First set the block
Chunk chunk = world.getChunk(x >> 4, z >> 4);
WorldChunk chunk = world.getChunk(x >> 4, z >> 4);
BlockPos pos = new BlockPos(x, y, z);
net.minecraft.block.BlockState old = chunk.getBlockState(pos);
OptionalInt stateId = BlockStateIdAccess.getBlockStateId(block.toImmutableState());
@ -221,26 +263,27 @@ public class FabricWorld extends AbstractWorld {
}
}
if (successful && notifyAndLight) {
world.getChunkManager().getLightingProvider().enqueueLightUpdate(pos);
world.scheduleBlockRender(pos, old, newState);
world.updateListeners(pos, old, newState, UPDATE | NOTIFY);
world.updateNeighbors(pos, newState.getBlock());
if (old.hasComparatorOutput()) {
world.updateHorizontalAdjacent(pos, newState.getBlock());
if (successful) {
if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
world.getChunkManager().getLightingProvider().checkBlock(pos);
}
markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects);
}
return successful;
}
@Override
public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException {
public Set<SideEffect> applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException {
BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ());
net.minecraft.block.BlockState state = getWorld().getBlockState(pos);
getWorld().updateListeners(pos, FabricAdapter.adapt(previousType), state, 1 | 2);
getWorld().updateNeighbors(pos, state.getBlock());
return true;
net.minecraft.block.BlockState oldData = FabricAdapter.adapt(previousType);
net.minecraft.block.BlockState newData = getWorld().getBlockState(pos);
if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
getWorld().getChunkManager().getLightingProvider().checkBlock(pos);
}
markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update
return Sets.intersection(FabricWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply());
}
@Override