Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-19 09:20:08 +01:00
Cherry-pick WNA, minor changes. 1.16 VERY WIP
First noticed incident of operations ruining ChunkSections. Do not build and use this unless you're testing. Rushed some of the changes, gotta sleep. Would be nice to get a review of this one from @mattbdev and @dordsor21
Dieser Commit ist enthalten in:
Ursprung
4604aa5920
Commit
d232dc28e3
@ -0,0 +1,176 @@
|
||||
package com.boydti.fawe.bukkit.adapter.mc1_14;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_14_R4;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import net.minecraft.server.v1_14_R1.Block;
|
||||
import net.minecraft.server.v1_14_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_14_R1.Chunk;
|
||||
import net.minecraft.server.v1_14_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_14_R1.EnumDirection;
|
||||
import net.minecraft.server.v1_14_R1.IBlockData;
|
||||
import net.minecraft.server.v1_14_R1.NBTBase;
|
||||
import net.minecraft.server.v1_14_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_14_R1.PlayerChunk;
|
||||
import net.minecraft.server.v1_14_R1.TileEntity;
|
||||
import net.minecraft.server.v1_14_R1.World;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FAWEWorldNativeAccess_1_14 implements WorldNativeAccess<Chunk, IBlockData, BlockPosition> {
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private final FAWE_Spigot_v1_14_R4 adapter;
|
||||
private final WeakReference<World> world;
|
||||
private SideEffectSet sideEffectSet;
|
||||
|
||||
public FAWEWorldNativeAccess_1_14(FAWE_Spigot_v1_14_R4 adapter, WeakReference<World> world) {
|
||||
this.adapter = adapter;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private World getWorld() {
|
||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
||||
this.sideEffectSet = sideEffectSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return getWorld().getChunkAt(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getBlockState(Chunk chunk, BlockPosition position) {
|
||||
return chunk.getType(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) {
|
||||
return Block.b(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition getPosition(int x, int y, int z) {
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLightingForBlock(BlockPosition position) {
|
||||
getWorld().getChunkProvider().getLightEngine().a(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTileEntity(BlockPosition position, CompoundTag tag) {
|
||||
// We will assume that the tile entity was created for us,
|
||||
// though we do not do this on the other versions
|
||||
TileEntity tileEntity = getWorld().getTileEntity(position);
|
||||
if (tileEntity == null) {
|
||||
return false;
|
||||
}
|
||||
NBTBase nativeTag = adapter.fromNative(tag);
|
||||
tileEntity.load((NBTTagCompound) nativeTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().notify(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(Chunk chunk) {
|
||||
return chunk.getState().isAtLeast(PlayerChunk.State.TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockChanged(BlockPosition position) {
|
||||
((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position);
|
||||
}
|
||||
|
||||
private static final EnumDirection[] NEIGHBOUR_ORDER = {
|
||||
EnumDirection.WEST, EnumDirection.EAST,
|
||||
EnumDirection.DOWN, EnumDirection.UP,
|
||||
EnumDirection.NORTH, EnumDirection.SOUTH
|
||||
};
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
World world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
world.update(pos, oldState.getBlock());
|
||||
} else {
|
||||
// When we don't want events, manually run the physics without them.
|
||||
// Un-nest neighbour updating
|
||||
for (EnumDirection direction : NEIGHBOUR_ORDER) {
|
||||
BlockPosition shifted = pos.shift(direction);
|
||||
world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false);
|
||||
}
|
||||
}
|
||||
if (newState.isComplexRedstone()) {
|
||||
world.updateAdjacentComparators(pos, newState.getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) {
|
||||
World world = getWorld();
|
||||
// a == updateNeighbors
|
||||
// b == updateDiagonalNeighbors
|
||||
oldState.b(world, pos, NOTIFY);
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
CraftWorld craftWorld = world.getWorld();
|
||||
if (craftWorld != null) {
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(
|
||||
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
|
||||
CraftBlockData.fromData(newState));
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
newState.a(world, pos, NOTIFY);
|
||||
newState.b(world, pos, NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package com.boydti.fawe.bukkit.adapter.mc1_15_2;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_15_R2;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import net.minecraft.server.v1_15_R1.Block;
|
||||
import net.minecraft.server.v1_15_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_15_R1.Chunk;
|
||||
import net.minecraft.server.v1_15_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_15_R1.EnumDirection;
|
||||
import net.minecraft.server.v1_15_R1.IBlockData;
|
||||
import net.minecraft.server.v1_15_R1.NBTBase;
|
||||
import net.minecraft.server.v1_15_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_15_R1.PlayerChunk;
|
||||
import net.minecraft.server.v1_15_R1.TileEntity;
|
||||
import net.minecraft.server.v1_15_R1.World;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IBlockData, BlockPosition> {
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private final FAWE_Spigot_v1_15_R2 adapter;
|
||||
private final WeakReference<World> world;
|
||||
private SideEffectSet sideEffectSet;
|
||||
|
||||
public FAWEWorldNativeAccess_1_15_2(FAWE_Spigot_v1_15_R2 adapter, WeakReference<World> world) {
|
||||
this.adapter = adapter;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private World getWorld() {
|
||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
||||
this.sideEffectSet = sideEffectSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return getWorld().getChunkAt(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getBlockState(Chunk chunk, BlockPosition position) {
|
||||
return chunk.getType(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) {
|
||||
return Block.b(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition getPosition(int x, int y, int z) {
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLightingForBlock(BlockPosition position) {
|
||||
getWorld().getChunkProvider().getLightEngine().a(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTileEntity(BlockPosition position, CompoundTag tag) {
|
||||
// We will assume that the tile entity was created for us,
|
||||
// though we do not do this on the other versions
|
||||
TileEntity tileEntity = getWorld().getTileEntity(position);
|
||||
if (tileEntity == null) {
|
||||
return false;
|
||||
}
|
||||
NBTBase nativeTag = adapter.fromNative(tag);
|
||||
tileEntity.load((NBTTagCompound) nativeTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().notify(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(Chunk chunk) {
|
||||
return chunk.getState().isAtLeast(PlayerChunk.State.TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockChanged(BlockPosition position) {
|
||||
((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position);
|
||||
}
|
||||
|
||||
private static final EnumDirection[] NEIGHBOUR_ORDER = {
|
||||
EnumDirection.WEST, EnumDirection.EAST,
|
||||
EnumDirection.DOWN, EnumDirection.UP,
|
||||
EnumDirection.NORTH, EnumDirection.SOUTH
|
||||
};
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
World world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
world.update(pos, oldState.getBlock());
|
||||
} else {
|
||||
// When we don't want events, manually run the physics without them.
|
||||
// Un-nest neighbour updating
|
||||
for (EnumDirection direction : NEIGHBOUR_ORDER) {
|
||||
BlockPosition shifted = pos.shift(direction);
|
||||
world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false);
|
||||
}
|
||||
}
|
||||
if (newState.isComplexRedstone()) {
|
||||
world.updateAdjacentComparators(pos, newState.getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) {
|
||||
World world = getWorld();
|
||||
// a == updateNeighbors
|
||||
// b == updateDiagonalNeighbors
|
||||
oldState.b(world, pos, NOTIFY);
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
CraftWorld craftWorld = world.getWorld();
|
||||
if (craftWorld != null) {
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState));
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
newState.a(world, pos, NOTIFY);
|
||||
newState.b(world, pos, NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ public class BlockMaterial_1_16_1 implements BlockMaterial {
|
||||
this.material = defaultState.getMaterial();
|
||||
this.craftBlockData = CraftBlockData.fromData(defaultState);
|
||||
this.craftMaterial = craftBlockData.getMaterial();
|
||||
this.isTranslucent = !(boolean) ReflectionUtil.getField(Block.class, block, "v"); //TODO Update Mapping for 1.16.1
|
||||
this.isTranslucent = !(boolean) ReflectionUtil.getField(Block.class, block, "at"); //TODO Update Mapping for 1.16.1
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
|
@ -0,0 +1,174 @@
|
||||
package com.boydti.fawe.bukkit.adapter.mc1_16_1;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_16_R1;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import net.minecraft.server.v1_16_R1.Block;
|
||||
import net.minecraft.server.v1_16_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_16_R1.Chunk;
|
||||
import net.minecraft.server.v1_16_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_16_R1.EnumDirection;
|
||||
import net.minecraft.server.v1_16_R1.IBlockData;
|
||||
import net.minecraft.server.v1_16_R1.NBTBase;
|
||||
import net.minecraft.server.v1_16_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_16_R1.PlayerChunk;
|
||||
import net.minecraft.server.v1_16_R1.TileEntity;
|
||||
import net.minecraft.server.v1_16_R1.World;
|
||||
import org.bukkit.craftbukkit.v1_16_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_16_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlockData, BlockPosition> {
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private final FAWE_Spigot_v1_16_R1 adapter;
|
||||
private final WeakReference<World> world;
|
||||
private SideEffectSet sideEffectSet;
|
||||
|
||||
public FAWEWorldNativeAccess_1_16(FAWE_Spigot_v1_16_R1 adapter, WeakReference<World> world) {
|
||||
this.adapter = adapter;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private World getWorld() {
|
||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
||||
this.sideEffectSet = sideEffectSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return getWorld().getChunkAt(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getBlockState(Chunk chunk, BlockPosition position) {
|
||||
return chunk.getType(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) {
|
||||
return Block.b(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition getPosition(int x, int y, int z) {
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLightingForBlock(BlockPosition position) {
|
||||
getWorld().getChunkProvider().getLightEngine().a(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTileEntity(BlockPosition position, CompoundTag tag) {
|
||||
// We will assume that the tile entity was created for us,
|
||||
// though we do not do this on the other versions
|
||||
TileEntity tileEntity = getWorld().getTileEntity(position);
|
||||
if (tileEntity == null) {
|
||||
return false;
|
||||
}
|
||||
NBTBase nativeTag = adapter.fromNative(tag);
|
||||
tileEntity.load(tileEntity.getBlock(), (NBTTagCompound) nativeTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().notify(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(Chunk chunk) {
|
||||
return chunk.getState().isAtLeast(PlayerChunk.State.TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockChanged(BlockPosition position) {
|
||||
((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position);
|
||||
}
|
||||
|
||||
private static final EnumDirection[] NEIGHBOUR_ORDER = {
|
||||
EnumDirection.WEST, EnumDirection.EAST,
|
||||
EnumDirection.DOWN, EnumDirection.UP,
|
||||
EnumDirection.NORTH, EnumDirection.SOUTH
|
||||
};
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
World world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
world.update(pos, oldState.getBlock());
|
||||
} else {
|
||||
// When we don't want events, manually run the physics without them.
|
||||
// Un-nest neighbour updating
|
||||
for (EnumDirection direction : NEIGHBOUR_ORDER) {
|
||||
BlockPosition shifted = pos.shift(direction);
|
||||
world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false);
|
||||
}
|
||||
}
|
||||
if (newState.isComplexRedstone()) {
|
||||
world.updateAdjacentComparators(pos, newState.getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) {
|
||||
World world = getWorld();
|
||||
// a == updateNeighbors
|
||||
// b == updateDiagonalNeighbors
|
||||
oldState.b(world, pos, NOTIFY, recursionLimit);
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
CraftWorld craftWorld = world.getWorld();
|
||||
if (craftWorld != null) {
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState));
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
newState.a(world, pos, NOTIFY, recursionLimit);
|
||||
newState.b(world, pos, NOTIFY, recursionLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
@ -884,6 +884,16 @@ public class AsyncWorld extends PassthroughExtent implements World {
|
||||
parent.setWaterAnimalSpawnLimit(limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaterAmbientSpawnLimit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWaterAmbientSpawnLimit(int limit) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmbientSpawnLimit() {
|
||||
return parent.getAmbientSpawnLimit();
|
||||
@ -1285,18 +1295,28 @@ public class AsyncWorld extends PassthroughExtent implements World {
|
||||
}
|
||||
|
||||
public long getTicksPerWaterSpawns() {
|
||||
throw new UnsupportedOperationException();
|
||||
return parent.getTicksPerWaterSpawns();
|
||||
}
|
||||
|
||||
public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) {
|
||||
throw new UnsupportedOperationException();
|
||||
parent.setTicksPerWaterSpawns(ticksPerWaterSpawns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTicksPerWaterAmbientSpawns() {
|
||||
return parent.getTicksPerWaterAmbientSpawns();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTicksPerWaterAmbientSpawns(int ticksPerAmbientSpawns) {
|
||||
parent.setTicksPerWaterAmbientSpawns(ticksPerAmbientSpawns);
|
||||
}
|
||||
|
||||
public long getTicksPerAmbientSpawns() {
|
||||
throw new UnsupportedOperationException();
|
||||
return parent.getTicksPerAmbientSpawns();
|
||||
}
|
||||
|
||||
public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) {
|
||||
throw new UnsupportedOperationException();
|
||||
parent.setTicksPerAmbientSpawns(ticksPerAmbientSpawns);
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,15 @@ package com.boydti.fawe.bukkit.wrapper.state;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class AsyncDataContainer implements PersistentDataContainer {
|
||||
private final CompoundTag root;
|
||||
@ -69,6 +69,20 @@ public final class AsyncDataContainer implements PersistentDataContainer {
|
||||
return z != null ? z : defaultValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<NamespacedKey> getKeys() {
|
||||
Set<NamespacedKey> keys = new HashSet<>();
|
||||
this.get(false).keySet().forEach(key -> {
|
||||
String[] keyData = key.split(":", 2);
|
||||
if (keyData.length == 2) {
|
||||
keys.add(new NamespacedKey(keyData[0], keyData[1]));
|
||||
}
|
||||
|
||||
});
|
||||
return keys;
|
||||
}
|
||||
|
||||
public void remove(NamespacedKey key) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
get(false).remove(key.toString());
|
||||
|
@ -24,8 +24,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -34,6 +35,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
@ -77,6 +79,7 @@ public class BukkitWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
private final WeakReference<World> worldRef;
|
||||
private final WorldNativeAccess<?, ?, ?> worldNativeAccess;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
@ -85,6 +88,12 @@ public class BukkitWorld extends AbstractWorld {
|
||||
*/
|
||||
public BukkitWorld(World world) {
|
||||
this.worldRef = new WeakReference<>(world);
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
if (adapter != null) {
|
||||
this.worldNativeAccess = adapter.createWorldNativeAccess(world);
|
||||
} else {
|
||||
this.worldNativeAccess = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -464,27 +473,23 @@ public class BukkitWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
if (adapter != null) {
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) {
|
||||
if (worldNativeAccess != null) {
|
||||
try {
|
||||
return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, sideEffects);
|
||||
return worldNativeAccess.setBlock(position, block, sideEffects);
|
||||
} catch (Exception e) {
|
||||
if (block instanceof BaseBlock && ((BaseBlock) block).getNbtData() != null) {
|
||||
logger.warn("Tried to set a corrupt tile entity at " + position.toString());
|
||||
logger.warn(((BaseBlock) block).getNbtData().toString());
|
||||
}
|
||||
e.printStackTrace();
|
||||
Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny());
|
||||
return true;
|
||||
}
|
||||
logger.warn("Tried to set a corrupt tile entity at " + position.toString() +
|
||||
": " + ((BaseBlock) block).getNbtData(), e);
|
||||
} else {
|
||||
logger.warn("Failed to set block via adapter, falling back to generic", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
@ -497,22 +502,19 @@ public class BukkitWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SideEffect> applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.applySideEffects(BukkitAdapter.adapt(getWorld(), position), previousType, sideEffectSet);
|
||||
return Sets.intersection(
|
||||
adapter.getSupportedSideEffects(),
|
||||
sideEffectSet.getSideEffectsToApply()
|
||||
);
|
||||
}
|
||||
|
||||
public Set<SideEffect> applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType,
|
||||
SideEffectSet sideEffectSet) {
|
||||
if (worldNativeAccess != null) {
|
||||
worldNativeAccess.applySideEffects(position, previousType, sideEffectSet);
|
||||
return Sets.intersection(
|
||||
WorldEditPlugin.getInstance().getInternalPlatform().getSupportedSideEffects(),
|
||||
sideEffectSet.getSideEffectsToApply()
|
||||
);
|
||||
}
|
||||
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useItem(BlockVector3 position, BaseItem item, Direction face) {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
|
@ -30,17 +30,16 @@ import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.DataFixer;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import java.util.Map;
|
||||
@ -98,23 +97,12 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
||||
BaseBlock getBlock(Location location);
|
||||
|
||||
/**
|
||||
* Set the block at the given location.
|
||||
* Create a {@link WorldNativeAccess} for the given world reference.
|
||||
*
|
||||
* @param location the location
|
||||
* @param state the block
|
||||
* @param sideEffectSet side effects to apply
|
||||
* @return true if a block was likely changed
|
||||
* @param world the world reference
|
||||
* @return the native access object
|
||||
*/
|
||||
boolean setBlock(Location location, BlockStateHolder<?> state, SideEffectSet sideEffectSet);
|
||||
|
||||
/**
|
||||
* Applies side effects on the given block.
|
||||
*
|
||||
* @param position position of the block
|
||||
* @param previousType the type of the previous block that was there
|
||||
* @param sideEffectSet side effects to apply
|
||||
*/
|
||||
void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet);
|
||||
WorldNativeAccess<?, ?, ?> createWorldNativeAccess(World world);
|
||||
|
||||
/**
|
||||
* Get the state for the given entity.
|
||||
|
@ -66,10 +66,6 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
||||
return getParent().getBlock(location);
|
||||
}
|
||||
|
||||
default <B extends BlockStateHolder<B>> boolean setBlock(Location location, B state, boolean notifyAndLight) {
|
||||
return getParent().setBlock(location, state, SideEffectSet.none());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
default BaseEntity getEntity(Entity entity) {
|
||||
|
@ -24,10 +24,7 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
|
||||
import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.BlockMaterial_1_14;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitAdapter_1_14;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitGetBlocks_1_14;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.MapChunkUtil_1_14;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.*;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.nbt.LazyCompoundTag_1_14;
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -42,13 +39,13 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.LazyBaseEntity;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.*;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
@ -71,6 +68,7 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
@ -151,26 +149,11 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Location location, BlockStateHolder<?> state, SideEffectSet sideEffectSet) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) {
|
||||
return; //TODO: properly implement SideEffects into FAWE
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SideEffect> getSupportedSideEffects() {
|
||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(Location location, B state, boolean notifyAndLight) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight);
|
||||
}
|
||||
|
||||
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
|
||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
||||
Chunk nmsChunk = craftChunk.getHandle();
|
||||
@ -222,6 +205,12 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new FAWEWorldNativeAccess_1_14(this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getEntityId(Entity entity) {
|
||||
MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType());
|
||||
|
@ -26,10 +26,7 @@ import com.boydti.fawe.beta.IQueueChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
|
||||
import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.BlockMaterial_1_15_2;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.BukkitAdapter_1_15_2;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.BukkitGetBlocks_1_15_2;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.MapChunkUtil_1_15_2;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.*;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2;
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -44,6 +41,7 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.LazyBaseEntity;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
@ -73,6 +71,7 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
@ -160,26 +159,11 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Location location, BlockStateHolder<?> state, SideEffectSet sideEffectSet) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) {
|
||||
return; //TODO: properly implement SideEffects into FAWE
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SideEffect> getSupportedSideEffects() {
|
||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(Location location, B state, boolean notifyAndLight) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight);
|
||||
}
|
||||
|
||||
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
|
||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
||||
Chunk nmsChunk = craftChunk.getHandle();
|
||||
@ -231,6 +215,12 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new FAWEWorldNativeAccess_1_15_2(this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getEntityId(Entity entity) {
|
||||
MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType());
|
||||
|
@ -26,10 +26,7 @@ import com.boydti.fawe.beta.IQueueChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
|
||||
import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.BlockMaterial_1_16_1;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitAdapter_1_16_1;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitGetBlocks_1_16_1;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.MapChunkUtil_1_16_1;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.*;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1;
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -44,6 +41,7 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.LazyBaseEntity;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
@ -72,6 +70,7 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
@ -159,26 +158,11 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Location location, BlockStateHolder<?> state, SideEffectSet sideEffectSet) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) {
|
||||
return; //TODO: properly implement SideEffects into FAWE
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SideEffect> getSupportedSideEffects() {
|
||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(Location location, B state, boolean notifyAndLight) {
|
||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight);
|
||||
}
|
||||
|
||||
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
|
||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
||||
Chunk nmsChunk = craftChunk.getHandle();
|
||||
@ -230,6 +214,12 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new FAWEWorldNativeAccess_1_16(this,
|
||||
new WeakReference<>(((CraftWorld)world).getHandle()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getEntityId(Entity entity) {
|
||||
MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType());
|
||||
|
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.internal.wna;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Natively access and perform operations on the world.
|
||||
*
|
||||
* @param <NC> the native chunk type
|
||||
* @param <NBS> the native block state type
|
||||
* @param <NP> the native position type
|
||||
*/
|
||||
public interface WorldNativeAccess<NC, NBS, NP> {
|
||||
|
||||
default <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
checkNotNull(position);
|
||||
checkNotNull(block);
|
||||
setCurrentSideEffectSet(sideEffects);
|
||||
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
// First set the block
|
||||
NC chunk = getChunk(x >> 4, z >> 4);
|
||||
NP pos = getPosition(x, y, z);
|
||||
NBS old = getBlockState(chunk, pos);
|
||||
NBS newState = toNative(block.toImmutableState());
|
||||
// change block prior to placing if it should be fixed
|
||||
if (sideEffects.shouldApply(SideEffect.VALIDATION)) {
|
||||
newState = getValidBlockForPosition(newState, pos);
|
||||
}
|
||||
NBS successState = setBlockState(chunk, pos, newState);
|
||||
boolean successful = successState != null;
|
||||
|
||||
// Create the TileEntity
|
||||
if (successful || old == newState) {
|
||||
if (block instanceof BaseBlock) {
|
||||
BaseBlock baseBlock = (BaseBlock) block;
|
||||
CompoundTag tag = baseBlock.getNbtData();
|
||||
if (tag != null) {
|
||||
tag = tag.createBuilder()
|
||||
.putString("id", baseBlock.getNbtId())
|
||||
.putInt("x", position.getX())
|
||||
.putInt("y", position.getY())
|
||||
.putInt("z", position.getZ())
|
||||
.build();
|
||||
// update if TE changed as well
|
||||
successful = updateTileEntity(pos, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
|
||||
updateLightingForBlock(pos);
|
||||
}
|
||||
markAndNotifyBlock(pos, chunk, old, newState, sideEffects);
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
default void applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) {
|
||||
setCurrentSideEffectSet(sideEffectSet);
|
||||
NP pos = getPosition(position.getX(), position.getY(), position.getZ());
|
||||
NC chunk = getChunk(position.getX() >> 4, position.getZ() >> 4);
|
||||
NBS oldData = toNative(previousType);
|
||||
NBS newData = getBlockState(chunk, pos);
|
||||
|
||||
if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
|
||||
updateLightingForBlock(pos);
|
||||
}
|
||||
|
||||
markAndNotifyBlock(pos, chunk, oldData, newData, sideEffectSet);
|
||||
}
|
||||
|
||||
// state-keeping functions for WNA
|
||||
// may be thread-unsafe, as this is single-threaded code
|
||||
|
||||
/**
|
||||
* Receive the current side-effect set from the high level call.
|
||||
*
|
||||
* This allows the implementation to branch on the side-effects internally.
|
||||
*
|
||||
* @param sideEffectSet the set of side-effects
|
||||
*/
|
||||
default void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
||||
}
|
||||
|
||||
// access functions
|
||||
|
||||
NC getChunk(int x, int z);
|
||||
|
||||
NBS toNative(BlockState state);
|
||||
|
||||
NBS getBlockState(NC chunk, NP position);
|
||||
|
||||
@Nullable
|
||||
NBS setBlockState(NC chunk, NP position, NBS state);
|
||||
|
||||
NBS getValidBlockForPosition(NBS block, NP position);
|
||||
|
||||
NP getPosition(int x, int y, int z);
|
||||
|
||||
void updateLightingForBlock(NP position);
|
||||
|
||||
boolean updateTileEntity(NP position, CompoundTag tag);
|
||||
|
||||
void notifyBlockUpdate(NP position, NBS oldState, NBS newState);
|
||||
|
||||
boolean isChunkTicking(NC chunk);
|
||||
|
||||
void markBlockChanged(NP position);
|
||||
|
||||
void notifyNeighbors(NP pos, NBS oldState, NBS newState);
|
||||
|
||||
void updateNeighbors(NP pos, NBS oldState, NBS newState, int recursionLimit);
|
||||
|
||||
void onBlockStateChange(NP pos, NBS oldState, NBS newState);
|
||||
|
||||
/**
|
||||
* This is a heavily modified function stripped from MC to apply worldedit-modifications.
|
||||
*
|
||||
* See Forge's World.markAndNotifyBlock
|
||||
*/
|
||||
default void markAndNotifyBlock(NP pos, NC chunk, NBS oldState, NBS newState, SideEffectSet sideEffectSet) {
|
||||
NBS blockState1 = getBlockState(chunk, pos);
|
||||
if (blockState1 != newState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove redundant branches
|
||||
if (isChunkTicking(chunk)) {
|
||||
if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) {
|
||||
notifyBlockUpdate(pos, oldState, newState);
|
||||
} else {
|
||||
// If we want to skip entity AI, just mark the block for sending
|
||||
markBlockChanged(pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) {
|
||||
notifyNeighbors(pos, oldState, newState);
|
||||
}
|
||||
|
||||
// Make connection updates optional
|
||||
if (sideEffectSet.shouldApply(SideEffect.VALIDATION)) {
|
||||
updateNeighbors(pos, oldState, newState, 512);
|
||||
}
|
||||
|
||||
onBlockStateChange(pos, oldState, newState);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* "WNA", or WorldEdit Native Access.
|
||||
*
|
||||
* Contains internal helper functions for sharing code between platforms.
|
||||
*/
|
||||
package com.sk89q.worldedit.internal.wna;
|
@ -24,9 +24,9 @@ import java.util.Locale;
|
||||
public enum SideEffect {
|
||||
LIGHTING(State.ON),
|
||||
NEIGHBORS(State.ON),
|
||||
CONNECTIONS(State.ON),
|
||||
VALIDATION(State.ON),
|
||||
ENTITY_AI(State.OFF),
|
||||
PLUGIN_EVENTS(State.OFF);
|
||||
EVENTS(State.OFF);
|
||||
|
||||
private final String displayName;
|
||||
private final String description;
|
||||
|
@ -502,12 +502,12 @@
|
||||
"worldedit.sideeffect.lighting.description": "Updates block lighting",
|
||||
"worldedit.sideeffect.neighbors": "Neighbors",
|
||||
"worldedit.sideeffect.neighbors.description": "Notifies nearby blocks of changes",
|
||||
"worldedit.sideeffect.connections": "Connections",
|
||||
"worldedit.sideeffect.connections.description": "Updates connections for blocks like fences",
|
||||
"worldedit.sideeffect.validation": "Validation",
|
||||
"worldedit.sideeffect.validation.description": "Validates and fixes inconsistent world state, such as disconnected blocks",
|
||||
"worldedit.sideeffect.entity_ai": "Entity AI",
|
||||
"worldedit.sideeffect.entity_ai.description": "Updates Entity AI paths for the block changes",
|
||||
"worldedit.sideeffect.plugin_events": "Plugin Events",
|
||||
"worldedit.sideeffect.plugin_events.description": "Tells other plugins/mods about these changes when applicable",
|
||||
"worldedit.sideeffect.events": "Mod/Plugin Events",
|
||||
"worldedit.sideeffect.events.description": "Tells other mods/plugins about these changes when applicable",
|
||||
"worldedit.sideeffect.state.on": "On",
|
||||
"worldedit.sideeffect.state.delayed": "Delayed",
|
||||
"worldedit.sideeffect.state.off": "Off",
|
||||
|
@ -7,8 +7,8 @@ applyShadowConfiguration()
|
||||
apply(plugin = "fabric-loom")
|
||||
|
||||
val minecraftVersion = "1.15.2"
|
||||
val yarnMappings = "1.15.2+build.8:v2"
|
||||
val loaderVersion = "0.7.6+build.180"
|
||||
val yarnMappings = "1.15.2+build.14:v2"
|
||||
val loaderVersion = "0.7.8+build.189"
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
|
@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.fabric.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.registry.state.BooleanProperty;
|
||||
|
@ -36,9 +36,10 @@ import com.mojang.datafixers.DataFixerBuilder;
|
||||
import com.mojang.datafixers.Dynamic;
|
||||
import com.mojang.datafixers.schemas.Schema;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import net.minecraft.datafixers.NbtOps;
|
||||
import net.minecraft.datafixers.Schemas;
|
||||
import net.minecraft.datafixers.TypeReferences;
|
||||
import com.sk89q.worldedit.fabric.internal.NBTConverter;
|
||||
import net.minecraft.datafixer.NbtOps;
|
||||
import net.minecraft.datafixer.Schemas;
|
||||
import net.minecraft.datafixer.TypeReferences;
|
||||
import net.minecraft.nbt.FloatTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
|
@ -25,6 +25,7 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.fabric.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.NullWorld;
|
||||
|
@ -202,7 +202,7 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform {
|
||||
}
|
||||
|
||||
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
|
||||
SideEffect.CONNECTIONS,
|
||||
SideEffect.VALIDATION,
|
||||
SideEffect.ENTITY_AI,
|
||||
SideEffect.LIGHTING,
|
||||
SideEffect.NEIGHBORS
|
||||
|
@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.fabric.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.fabric.mixin.AccessorServerPlayerEntity;
|
||||
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
@ -42,10 +43,10 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.network.packet.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.client.network.packet.BlockUpdateS2CPacket;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
|
@ -34,6 +34,8 @@ import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.fabric.internal.FabricWorldNativeAccess;
|
||||
import com.sk89q.worldedit.fabric.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
@ -64,7 +66,6 @@ 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;
|
||||
@ -129,6 +130,7 @@ public class FabricWorld extends AbstractWorld {
|
||||
private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE);
|
||||
|
||||
private final WeakReference<World> worldRef;
|
||||
private final FabricWorldNativeAccess worldNativeAccess;
|
||||
|
||||
/**
|
||||
* Construct a new world.
|
||||
@ -138,6 +140,7 @@ public class FabricWorld extends AbstractWorld {
|
||||
FabricWorld(World world) {
|
||||
checkNotNull(world);
|
||||
this.worldRef = new WeakReference<>(world);
|
||||
this.worldNativeAccess = new FabricWorldNativeAccess(worldRef);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,98 +194,14 @@ 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, SideEffectSet sideEffects) throws WorldEditException {
|
||||
checkNotNull(position);
|
||||
checkNotNull(block);
|
||||
|
||||
World world = getWorldChecked();
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
// First set the block
|
||||
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());
|
||||
net.minecraft.block.BlockState newState = stateId.isPresent() ? Block.getStateFromRawId(stateId.getAsInt()) : FabricAdapter.adapt(block.toImmutableState());
|
||||
net.minecraft.block.BlockState successState = chunk.setBlockState(pos, newState, false);
|
||||
boolean successful = successState != null;
|
||||
|
||||
// Create the TileEntity
|
||||
if (successful || old == newState) {
|
||||
if (block instanceof BaseBlock) {
|
||||
CompoundTag tag = ((BaseBlock) block).getNbtData();
|
||||
if (tag != null) {
|
||||
net.minecraft.nbt.CompoundTag nativeTag = NBTConverter.toNative(tag);
|
||||
BlockEntity tileEntity = getWorld().getWorldChunk(pos).getBlockEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
tileEntity.fromTag(nativeTag);
|
||||
tileEntity.setPos(pos);
|
||||
tileEntity.setWorld(world);
|
||||
successful = true; // update if TE changed as well
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
|
||||
world.getChunkManager().getLightingProvider().checkBlock(pos);
|
||||
}
|
||||
markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects);
|
||||
}
|
||||
|
||||
return successful;
|
||||
return worldNativeAccess.setBlock(position, block, sideEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 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
|
||||
worldNativeAccess.applySideEffects(position, previousType, sideEffectSet);
|
||||
return Sets.intersection(FabricWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric.internal;
|
||||
|
||||
import com.sk89q.worldedit.fabric.FabricAdapter;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.world.ChunkHolder;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FabricWorldNativeAccess implements WorldNativeAccess<WorldChunk, BlockState, BlockPos> {
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private final WeakReference<World> world;
|
||||
|
||||
public FabricWorldNativeAccess(WeakReference<World> world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private World getWorld() {
|
||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChunk getChunk(int x, int z) {
|
||||
return getWorld().getChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getStateFromRawId(stateId)
|
||||
: FabricAdapter.adapt(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(WorldChunk chunk, BlockPos position) {
|
||||
return chunk.getBlockState(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState setBlockState(WorldChunk chunk, BlockPos position, BlockState state) {
|
||||
return chunk.setBlockState(position, state, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getValidBlockForPosition(BlockState block, BlockPos position) {
|
||||
return Block.getRenderingState(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getPosition(int x, int y, int z) {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLightingForBlock(BlockPos position) {
|
||||
getWorld().getChunkManager().getLightingProvider().checkBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTileEntity(BlockPos position, com.sk89q.jnbt.CompoundTag tag) {
|
||||
CompoundTag nativeTag = NBTConverter.toNative(tag);
|
||||
BlockEntity tileEntity = getWorld().getWorldChunk(position).getBlockEntity(position);
|
||||
if (tileEntity == null) {
|
||||
return false;
|
||||
}
|
||||
tileEntity.setLocation(getWorld(), position);
|
||||
tileEntity.fromTag(nativeTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(BlockPos position, BlockState oldState, BlockState newState) {
|
||||
getWorld().updateListeners(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(WorldChunk chunk) {
|
||||
return chunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockChanged(BlockPos position) {
|
||||
((ServerChunkManager) getWorld().getChunkManager()).markForUpdate(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
getWorld().updateNeighbors(pos, oldState.getBlock());
|
||||
if (newState.hasComparatorOutput()) {
|
||||
getWorld().updateHorizontalAdjacent(pos, newState.getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
World world = getWorld();
|
||||
// method_11637 = updateDiagonalNeighbors
|
||||
oldState.method_11637(world, pos, NOTIFY);
|
||||
newState.updateNeighborStates(world, pos, NOTIFY);
|
||||
newState.method_11637(world, pos, NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
getWorld().onBlockChanged(pos, oldState, newState);
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
package com.sk89q.worldedit.fabric.internal;
|
||||
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
@ -44,7 +44,7 @@ import java.util.Set;
|
||||
/**
|
||||
* Converts between JNBT and Minecraft NBT classes.
|
||||
*/
|
||||
final class NBTConverter {
|
||||
public final class NBTConverter {
|
||||
|
||||
private NBTConverter() {
|
||||
}
|
@ -23,15 +23,9 @@ import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.fabric.FabricAdapter;
|
||||
import com.sk89q.worldedit.fabric.FabricPlayer;
|
||||
import com.sk89q.worldedit.fabric.FabricWorldEdit;
|
||||
import net.fabricmc.fabric.api.network.PacketConsumer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -25,6 +25,7 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.forge.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.NullWorld;
|
||||
|
@ -208,7 +208,7 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform {
|
||||
}
|
||||
|
||||
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
|
||||
SideEffect.CONNECTIONS,
|
||||
SideEffect.VALIDATION,
|
||||
SideEffect.ENTITY_AI,
|
||||
SideEffect.LIGHTING,
|
||||
SideEffect.NEIGHBORS
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
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;
|
||||
@ -34,6 +32,9 @@ import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.forge.internal.ForgeWorldNativeAccess;
|
||||
import com.sk89q.worldedit.forge.internal.NBTConverter;
|
||||
import com.sk89q.worldedit.forge.internal.TileEntityUtils;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.util.BiomeMath;
|
||||
@ -105,6 +106,7 @@ import net.minecraft.world.storage.SaveHandler;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -119,7 +121,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* An adapter to Minecraft worlds for WorldEdit.
|
||||
@ -127,13 +129,13 @@ import javax.annotation.Nullable;
|
||||
public class ForgeWorld extends AbstractWorld {
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private static final net.minecraft.block.BlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState();
|
||||
private static final net.minecraft.block.BlockState JUNGLE_LEAF = Blocks.JUNGLE_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE);
|
||||
private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE);
|
||||
|
||||
private final WeakReference<World> worldRef;
|
||||
private final ForgeWorldNativeAccess nativeAccess;
|
||||
|
||||
/**
|
||||
* Construct a new world.
|
||||
@ -143,6 +145,7 @@ public class ForgeWorld extends AbstractWorld {
|
||||
ForgeWorld(World world) {
|
||||
checkNotNull(world);
|
||||
this.worldRef = new WeakReference<>(world);
|
||||
this.nativeAccess = new ForgeWorldNativeAccess(worldRef);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,101 +197,14 @@ public class ForgeWorld extends AbstractWorld {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a heavily modified function stripped from MC to apply worldedit-modifications.
|
||||
*
|
||||
* @see World#markAndNotifyBlock
|
||||
*/
|
||||
public void markAndNotifyBlock(World world, BlockPos pos, @Nullable Chunk chunk, net.minecraft.block.BlockState blockstate,
|
||||
net.minecraft.block.BlockState newState, SideEffectSet sideEffectSet) {
|
||||
Block block = newState.getBlock();
|
||||
net.minecraft.block.BlockState blockstate1 = world.getBlockState(pos);
|
||||
if (blockstate1 == newState) {
|
||||
if (blockstate != blockstate1) {
|
||||
world.markBlockRangeForRenderUpdate(pos, blockstate, blockstate1);
|
||||
}
|
||||
|
||||
// Remove redundant branches
|
||||
if (world.isRemote || chunk == null || chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING)) {
|
||||
if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) {
|
||||
world.notifyBlockUpdate(pos, blockstate, newState, UPDATE | NOTIFY);
|
||||
} else {
|
||||
// If we want to skip entity AI, just call the chunk dirty flag.
|
||||
((ServerChunkProvider) world.getChunkProvider()).markBlockChanged(pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (!world.isRemote && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) {
|
||||
world.notifyNeighbors(pos, blockstate.getBlock());
|
||||
if (newState.hasComparatorInputOverride()) {
|
||||
world.updateComparatorOutputLevel(pos, block);
|
||||
}
|
||||
}
|
||||
|
||||
// Make connection updates optional
|
||||
if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) {
|
||||
blockstate.updateDiagonalNeighbors(world, pos, 2);
|
||||
newState.updateNeighbors(world, pos, 2);
|
||||
newState.updateDiagonalNeighbors(world, pos, 2);
|
||||
}
|
||||
|
||||
// This is disabled for other platforms, but keep it for mods.
|
||||
world.onBlockStateChange(pos, blockstate, blockstate1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
checkNotNull(position);
|
||||
checkNotNull(block);
|
||||
|
||||
World world = getWorldChecked();
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
// First set the block
|
||||
Chunk 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());
|
||||
net.minecraft.block.BlockState newState = stateId.isPresent() ? Block.getStateById(stateId.getAsInt()) : ForgeAdapter.adapt(block.toImmutableState());
|
||||
net.minecraft.block.BlockState successState = chunk.setBlockState(pos, newState, false);
|
||||
boolean successful = successState != null;
|
||||
|
||||
// Create the TileEntity
|
||||
if (successful || old == newState) {
|
||||
if (block instanceof BaseBlock) {
|
||||
CompoundTag tag = ((BaseBlock) block).getNbtData();
|
||||
if (tag != null) {
|
||||
CompoundNBT nativeTag = NBTConverter.toNative(tag);
|
||||
nativeTag.putString("id", ((BaseBlock) block).getNbtId());
|
||||
TileEntityUtils.setTileEntity(world, position, nativeTag);
|
||||
successful = true; // update if TE changed as well
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
|
||||
world.getChunkProvider().getLightManager().checkBlock(pos);
|
||||
}
|
||||
markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects);
|
||||
}
|
||||
|
||||
return successful;
|
||||
return nativeAccess.setBlock(position, block, sideEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 oldData = ForgeAdapter.adapt(previousType);
|
||||
net.minecraft.block.BlockState newData = getWorld().getBlockState(pos);
|
||||
|
||||
if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) {
|
||||
getWorld().getChunkProvider().getLightManager().checkBlock(pos);
|
||||
}
|
||||
markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update
|
||||
nativeAccess.applySideEffects(position, previousType, sideEffectSet);
|
||||
return Sets.intersection(ForgeWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge.internal;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.forge.ForgeAdapter;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.server.ChunkHolder;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ForgeWorldNativeAccess implements WorldNativeAccess<Chunk, BlockState, BlockPos> {
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private final WeakReference<World> world;
|
||||
private SideEffectSet sideEffectSet;
|
||||
|
||||
public ForgeWorldNativeAccess(WeakReference<World> world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
private World getWorld() {
|
||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
||||
this.sideEffectSet = sideEffectSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return getWorld().getChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getStateById(stateId)
|
||||
: ForgeAdapter.adapt(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(Chunk chunk, BlockPos position) {
|
||||
return chunk.getBlockState(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState setBlockState(Chunk chunk, BlockPos position, BlockState state) {
|
||||
return chunk.setBlockState(position, state, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getValidBlockForPosition(BlockState block, BlockPos position) {
|
||||
return Block.getValidBlockForPosition(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getPosition(int x, int y, int z) {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLightingForBlock(BlockPos position) {
|
||||
getWorld().getChunkProvider().getLightManager().checkBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTileEntity(BlockPos position, CompoundTag tag) {
|
||||
CompoundNBT nativeTag = NBTConverter.toNative(tag);
|
||||
return TileEntityUtils.setTileEntity(getWorld(), position, nativeTag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(BlockPos position, BlockState oldState, BlockState newState) {
|
||||
getWorld().notifyBlockUpdate(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(Chunk chunk) {
|
||||
return chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockChanged(BlockPos position) {
|
||||
((ServerChunkProvider) getWorld().getChunkProvider()).markBlockChanged(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
World world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
world.notifyNeighbors(pos, oldState.getBlock());
|
||||
} else {
|
||||
// Manually update each side
|
||||
Block block = oldState.getBlock();
|
||||
world.neighborChanged(pos.west(), block, pos);
|
||||
world.neighborChanged(pos.east(), block, pos);
|
||||
world.neighborChanged(pos.down(), block, pos);
|
||||
world.neighborChanged(pos.up(), block, pos);
|
||||
world.neighborChanged(pos.north(), block, pos);
|
||||
world.neighborChanged(pos.south(), block, pos);
|
||||
}
|
||||
if (newState.hasComparatorInputOverride()) {
|
||||
world.updateComparatorOutputLevel(pos, newState.getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
World world = getWorld();
|
||||
oldState.updateDiagonalNeighbors(world, pos, NOTIFY);
|
||||
newState.updateNeighbors(world, pos, NOTIFY);
|
||||
newState.updateDiagonalNeighbors(world, pos, NOTIFY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
getWorld().onBlockStateChange(pos, oldState, newState);
|
||||
}
|
||||
}
|
@ -24,13 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.IntNBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Utility methods for setting tile entities in the world.
|
||||
*/
|
||||
@ -39,40 +36,22 @@ public final class TileEntityUtils {
|
||||
private TileEntityUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given tag compound with position information.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param position the position
|
||||
*/
|
||||
private static void updateForSet(CompoundNBT tag, BlockVector3 position) {
|
||||
checkNotNull(tag);
|
||||
checkNotNull(position);
|
||||
|
||||
tag.put("x", new IntNBT(position.getBlockX()));
|
||||
tag.put("y", new IntNBT(position.getBlockY()));
|
||||
tag.put("z", new IntNBT(position.getBlockZ()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a tile entity at the given location using the tile entity ID from
|
||||
* the tag.
|
||||
*
|
||||
* @param world the world
|
||||
* @param position the position
|
||||
* @param tag the tag for the tile entity (may be null to do nothing)
|
||||
* @param tag the tag for the tile entity
|
||||
*/
|
||||
static boolean setTileEntity(World world, BlockVector3 position, @Nullable CompoundNBT tag) {
|
||||
if (tag != null) {
|
||||
updateForSet(tag, position);
|
||||
static boolean setTileEntity(World world, BlockPos position, CompoundNBT tag) {
|
||||
TileEntity tileEntity = TileEntity.create(tag);
|
||||
if (tileEntity == null) {
|
||||
return false;
|
||||
}
|
||||
world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity);
|
||||
world.setTileEntity(new BlockPos(position.getX(), position.getY(), position.getZ()), tileEntity);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static CompoundNBT copyNbtData(TileEntity tile) {
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren