Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-10-04 20:51:05 +02:00
Add for 1.21
Dieser Commit ist enthalten in:
Ursprung
45a9a557af
Commit
609dd009b4
@ -886,12 +886,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
|
||||
SideEffect.NEIGHBORS,
|
||||
//FAWE start - FAWE-supported side effects
|
||||
SideEffect.HISTORY,
|
||||
SideEffect.HEIGHTMAPS,
|
||||
SideEffect.LIGHTING,
|
||||
SideEffect.VALIDATION,
|
||||
SideEffect.ENTITY_AI,
|
||||
SideEffect.EVENTS,
|
||||
SideEffect.UPDATE
|
||||
SideEffect.NEIGHBORS
|
||||
//FAWE end
|
||||
);
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1;
|
||||
|
||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.PaperweightFaweAdapter;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PaperweightServerLevelDelegateProxy implements InvocationHandler {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
// FAWE start - extent not EditSession
|
||||
private final Extent editSession;
|
||||
//FAWE end
|
||||
private final ServerLevel serverLevel;
|
||||
//FAWE start - use FAWE adapter
|
||||
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter());
|
||||
//FAWE end
|
||||
//FAWE start - force error if method not caught by this instance
|
||||
private final boolean errorOnPassthrough;
|
||||
//FAWE end
|
||||
|
||||
private PaperweightServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel, PaperweightAdapter adapter) {
|
||||
this.editSession = editSession;
|
||||
this.serverLevel = serverLevel;
|
||||
//FAWE start
|
||||
this.errorOnPassthrough = false;
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
public static WorldGenLevel newInstance(EditSession editSession, ServerLevel serverLevel, PaperweightAdapter adapter) {
|
||||
return (WorldGenLevel) Proxy.newProxyInstance(
|
||||
serverLevel.getClass().getClassLoader(),
|
||||
serverLevel.getClass().getInterfaces(),
|
||||
new PaperweightServerLevelDelegateProxy(editSession, serverLevel, adapter)
|
||||
);
|
||||
}
|
||||
|
||||
//FAWE start - force error if method not caught by this instance
|
||||
private PaperweightServerLevelDelegateProxy(Extent extent, ServerLevel serverLevel, boolean errorOnPassthrough) {
|
||||
this.editSession = extent;
|
||||
this.serverLevel = serverLevel;
|
||||
this.errorOnPassthrough = errorOnPassthrough;
|
||||
}
|
||||
|
||||
public static WorldGenLevel newInstance(Extent extent, ServerLevel serverLevel, boolean errorOnPassthrough) {
|
||||
return (WorldGenLevel) Proxy.newProxyInstance(
|
||||
serverLevel.getClass().getClassLoader(),
|
||||
serverLevel.getClass().getInterfaces(),
|
||||
new PaperweightServerLevelDelegateProxy(extent, serverLevel, errorOnPassthrough)
|
||||
);
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
@Nullable
|
||||
private BlockEntity getBlockEntity(BlockPos blockPos) {
|
||||
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
|
||||
if (tileEntity == null) {
|
||||
return null;
|
||||
}
|
||||
BlockEntity newEntity = tileEntity.getType().create(blockPos, getBlockState(blockPos));
|
||||
newEntity.loadWithComponents(
|
||||
(CompoundTag) adapter.fromNativeLin(this.editSession.getFullBlock(
|
||||
blockPos.getX(),
|
||||
blockPos.getY(),
|
||||
blockPos.getZ()
|
||||
).getNbtReference().getValue()),
|
||||
this.serverLevel.registryAccess()
|
||||
);
|
||||
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
private BlockState getBlockState(BlockPos blockPos) {
|
||||
return adapter.adapt(this.editSession.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
||||
}
|
||||
|
||||
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
|
||||
try {
|
||||
return editSession.setBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ(), adapter.adapt(blockState));
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean removeBlock(BlockPos blockPos, boolean bl) {
|
||||
try {
|
||||
return editSession.setBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ(), BlockTypes.AIR.getDefaultState());
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private FluidState getFluidState(BlockPos pos) {
|
||||
return getBlockState(pos).getFluidState();
|
||||
}
|
||||
|
||||
private boolean isWaterAt(BlockPos pos) {
|
||||
return getBlockState(pos).getFluidState().is(FluidTags.WATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
//FAWE start - cannot use switch where method names are equal
|
||||
String methodName = method.getName();
|
||||
if (Refraction.pickName("getBlockState", "a_").equals(methodName)) {
|
||||
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
|
||||
// getBlockState
|
||||
return getBlockState(blockPos);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("getBlockEntity", "c_").equals(methodName)) {
|
||||
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
|
||||
// getBlockEntity
|
||||
return getBlockEntity(blockPos);
|
||||
}
|
||||
}
|
||||
if ("a".equals(methodName) || "setBlock".equals(methodName) || "removeBlock".equals(methodName) || "destroyBlock".equals(
|
||||
methodName)) {
|
||||
if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof BlockState blockState) {
|
||||
// setBlock
|
||||
return setBlock(blockPos, blockState);
|
||||
} else if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Boolean bl) {
|
||||
// removeBlock (and also matches destroyBlock)
|
||||
return removeBlock(blockPos, bl);
|
||||
}
|
||||
}
|
||||
//FAWE start
|
||||
if (Refraction.pickName("getFluidState", "b_").equals(methodName)) { //net.minecraft.world.level.BlockGetter
|
||||
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
|
||||
return getFluidState(blockPos);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("isWaterAt", "z").equals(methodName)) { //net.minecraft.world.level.LevelReader
|
||||
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
|
||||
return isWaterAt(blockPos);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("getEntities", "a_").equals(methodName)) { //net.minecraft.world.level.EntityGetter
|
||||
if (args.length == 2 && args[0] instanceof Entity && args[1] instanceof AABB) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
// Specific passthroughs that we want to allow
|
||||
// net.minecraft.world.level.BlockAndTintGetter
|
||||
if (Refraction.pickName("getRawBrightness", "b").equals(methodName)) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
// net.minecraft.world.level.LevelHeightAccessor
|
||||
if (Refraction.pickName("getMaxBuildHeight", "al").equals(methodName)) {
|
||||
if (args.length == 0) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
}
|
||||
// net.minecraft.world.level.SignalGetter
|
||||
if (Refraction.pickName("hasNeighborSignal", "C").equals(methodName)) {
|
||||
if (args.length == 1 && args[0] instanceof BlockPos) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("getSignal", "c").equals(methodName)) {
|
||||
if (args.length == 2 && args[0] instanceof BlockPos && args[1] instanceof Direction) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("getControlInputSignal", "a").equals(methodName)) {
|
||||
if (args.length == 3 && args[0] instanceof BlockPos && args[1] instanceof Direction && args[2] instanceof Boolean) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
}
|
||||
if (Refraction.pickName("getDirectSignal", "a").equals(methodName)) {
|
||||
if (args.length == 2 && args[0] instanceof BlockPos && args[1] instanceof Direction) {
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
}
|
||||
//FAWE start - force error if method not caught by this instance
|
||||
if (errorOnPassthrough) {
|
||||
LOGGER.error(
|
||||
"""
|
||||
Attempted passthough of method {}.
|
||||
Method argument types: {}
|
||||
Method argument values: {}
|
||||
""",
|
||||
method.getName(),
|
||||
Arrays.stream(args).map(a -> a.getClass().getName()).toList(),
|
||||
Arrays.stream(args).map(Object::toString).toList()
|
||||
);
|
||||
throw new FaweException("Method required passthrough.");
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
return method.invoke(this.serverLevel, args);
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
|
||||
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
|
||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
@ -12,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
@ -21,6 +23,7 @@ import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazy
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.regen.PaperweightRegen;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||
@ -293,9 +296,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
|
||||
SideEffect.HISTORY,
|
||||
SideEffect.HEIGHTMAPS,
|
||||
SideEffect.LIGHTING,
|
||||
SideEffect.NEIGHBORS
|
||||
);
|
||||
|
||||
@Override
|
||||
public Set<SideEffect> getSupportedSideEffects() {
|
||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
||||
return SUPPORTED_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -443,6 +453,10 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
return material.getCraftBlockData();
|
||||
}
|
||||
|
||||
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
|
||||
return Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
|
||||
ServerLevel nmsWorld = getServerLevel(world);
|
||||
@ -624,6 +638,11 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
return new PaperweightPostProcessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, Region region) {
|
||||
return new PaperweightPlacementStateProcessor(extent, mask, region);
|
||||
}
|
||||
|
||||
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
|
||||
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
|
||||
try {
|
||||
|
@ -0,0 +1,143 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PaperweightFaweMutableBlockPlaceContext extends BlockPlaceContext {
|
||||
|
||||
private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(
|
||||
new Vec3(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE),
|
||||
Direction.NORTH,
|
||||
new BlockPos(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE),
|
||||
false
|
||||
);
|
||||
private final ServerLevel level;
|
||||
private BlockHitResult hitResult = null;
|
||||
private Direction direction = null;
|
||||
private BlockPos relativePos;
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public PaperweightFaweMutableBlockPlaceContext(ServerLevel level) {
|
||||
super(
|
||||
level,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
DEFAULT_BLOCK_HIT
|
||||
|
||||
);
|
||||
this.level = level;
|
||||
this.replaceClicked = false;
|
||||
}
|
||||
|
||||
public PaperweightFaweMutableBlockPlaceContext withSetting(BlockHitResult hitResult, Direction direction) {
|
||||
this.hitResult = hitResult;
|
||||
this.direction = direction;
|
||||
this.relativePos = hitResult.getBlockPos().relative(hitResult.getDirection());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public BlockPos getClickedPos() {
|
||||
return this.relativePos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Direction getClickedFace() {
|
||||
return this.hitResult.getDirection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Vec3 getClickLocation() {
|
||||
return this.hitResult.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInside() {
|
||||
return this.hitResult.isInside();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public ItemStack getItemInHand() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public InteractionHand getHand() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Level getLevel() {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Direction getHorizontalDirection() {
|
||||
return this.direction.getAxis() == Direction.Axis.Y ? Direction.NORTH : this.direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecondaryUseActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRotation() {
|
||||
return (float) (this.direction.get2DDataValue() * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlace() {
|
||||
return this.getLevel().getBlockState(this.getClickedPos()).canBeReplaced(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacingClickedOnBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Direction getNearestLookingDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Direction getNearestLookingVerticalDirection() {
|
||||
return direction.getAxis() == Direction.Axis.Y ? Direction.UP : Direction.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Direction[] getNearestLookingDirections() {
|
||||
return new Direction[]{direction};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazy
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
@ -816,15 +817,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (bitMask == 0 && biomes == null && !lightUpdate) {
|
||||
callback = null;
|
||||
} else {
|
||||
int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0;
|
||||
boolean finalLightUpdate = lightUpdate;
|
||||
final int finalBitMask = bitMask;
|
||||
callback = () -> {
|
||||
// Set Modified
|
||||
nmsChunk.setLightCorrect(true); // Set Modified
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.setUnsaved(true);
|
||||
// send to player
|
||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
|
||||
if (!set
|
||||
.getSideEffectSet()
|
||||
.shouldApply(SideEffect.LIGHTING) || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalBitMask == 0 && biomes != null) {
|
||||
this.send();
|
||||
}
|
||||
if (finalizer != null) {
|
||||
|
@ -0,0 +1,99 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||
|
||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PaperweightLevelProxy extends ServerLevel {
|
||||
|
||||
protected ServerLevel serverLevel;
|
||||
private PaperweightPlacementStateProcessor processor;
|
||||
private PaperweightFaweAdapter adapter;
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
private PaperweightLevelProxy() {
|
||||
super(null, null, null, null, null, null, null, true, 0L, null, true, null, null, null, null);
|
||||
throw new IllegalStateException("Cannot be instantiated");
|
||||
}
|
||||
|
||||
public static PaperweightLevelProxy getInstance(ServerLevel serverLevel, PaperweightPlacementStateProcessor processor) {
|
||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||
|
||||
PaperweightLevelProxy newLevel;
|
||||
try {
|
||||
newLevel = (PaperweightLevelProxy) unsafe.allocateInstance(PaperweightLevelProxy.class);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
newLevel.processor = processor;
|
||||
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin.getInstance().getBukkitImplAdapter());
|
||||
newLevel.serverLevel = serverLevel;
|
||||
return newLevel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(@Nonnull BlockPos blockPos) {
|
||||
if (blockPos.getX() == Integer.MAX_VALUE) {
|
||||
return null;
|
||||
}
|
||||
com.sk89q.jnbt.CompoundTag tag = processor.getTileAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
BlockState state = adapter.adapt(processor.getBlockStateAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
||||
if (!(state.getBlock() instanceof EntityBlock entityBlock)) {
|
||||
return null;
|
||||
}
|
||||
BlockEntity tileEntity = entityBlock.newBlockEntity(blockPos, state);
|
||||
tileEntity.loadWithComponents((CompoundTag) adapter.fromNative(tag), serverLevel.registryAccess());
|
||||
return tileEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public BlockState getBlockState(@Nonnull BlockPos blockPos) {
|
||||
if (blockPos.getX() == Integer.MAX_VALUE) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
com.sk89q.worldedit.world.block.BlockState state = processor.getBlockStateAt(
|
||||
blockPos.getX(),
|
||||
blockPos.getY(),
|
||||
blockPos.getZ()
|
||||
);
|
||||
return adapter.adapt(state);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
@Nonnull
|
||||
public FluidState getFluidState(@Nonnull BlockPos pos) {
|
||||
if (pos.getX() == Integer.MAX_VALUE) {
|
||||
return Fluids.EMPTY.defaultFluidState();
|
||||
}
|
||||
return getBlockState(pos).getFluidState();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public boolean isWaterAt(@Nonnull BlockPos pos) {
|
||||
if (pos.getX() == Integer.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
return getBlockState(pos).getFluidState().is(FluidTags.WATER);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
|
||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class PaperweightPlacementStateProcessor extends PlacementStateProcessor {
|
||||
|
||||
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter());
|
||||
private final PaperweightLevelProxy proxyLevel;
|
||||
private final PaperweightFaweMutableBlockPlaceContext mutableBlockPlaceContext;
|
||||
|
||||
public PaperweightPlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
|
||||
super(extent, mask, region);
|
||||
World world = ExtentTraverser.getWorldFromExtent(extent);
|
||||
if (world == null) {
|
||||
throw new UnsupportedOperationException(
|
||||
"World is required for PlacementStateProcessor but none found in given extent.");
|
||||
}
|
||||
BukkitWorld bukkitWorld;
|
||||
if (world instanceof WorldWrapper wrapper) {
|
||||
bukkitWorld = (BukkitWorld) wrapper.getParent();
|
||||
} else {
|
||||
bukkitWorld = (BukkitWorld) world;
|
||||
}
|
||||
this.proxyLevel = PaperweightLevelProxy.getInstance(((CraftWorld) bukkitWorld.getWorld()).getHandle(), this);
|
||||
this.mutableBlockPlaceContext = new PaperweightFaweMutableBlockPlaceContext(proxyLevel);
|
||||
}
|
||||
|
||||
private PaperweightPlacementStateProcessor(
|
||||
Extent extent,
|
||||
BlockTypeMask mask,
|
||||
Map<SecondPass, Character> crossChunkSecondPasses,
|
||||
ServerLevel serverLevel,
|
||||
ThreadLocal<PlacementStateProcessor> threadProcessors,
|
||||
Region region,
|
||||
AtomicBoolean finished
|
||||
) {
|
||||
super(extent, mask, crossChunkSecondPasses, threadProcessors, region, finished);
|
||||
this.proxyLevel = PaperweightLevelProxy.getInstance(serverLevel, this);
|
||||
this.mutableBlockPlaceContext = new PaperweightFaweMutableBlockPlaceContext(proxyLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char getStateAtFor(
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
BlockState state,
|
||||
Vector3 clickPos,
|
||||
Direction clickedFaceDirection,
|
||||
BlockVector3 clickedBlock
|
||||
) {
|
||||
Block block = ((PaperweightBlockMaterial) state.getMaterial()).getBlock();
|
||||
Vec3 pos = new Vec3(clickPos.x(), clickPos.y(), clickPos.z());
|
||||
net.minecraft.core.Direction side = net.minecraft.core.Direction.valueOf(clickedFaceDirection.toString());
|
||||
BlockPos blockPos = new BlockPos(clickedBlock.x(), clickedBlock.y(), clickedBlock.z());
|
||||
net.minecraft.world.level.block.state.BlockState newState = block.getStateForPlacement(mutableBlockPlaceContext.withSetting(
|
||||
new BlockHitResult(pos, side, blockPos, false),
|
||||
side.getOpposite()
|
||||
));
|
||||
return newState == null ? BlockTypesCache.ReservedIDs.AIR : adapter.ibdIDToOrdinal(Block.BLOCK_STATE_REGISTRY.getId(
|
||||
newState));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Extent construct(Extent child) {
|
||||
if (child == getExtent()) {
|
||||
return this;
|
||||
}
|
||||
return new PaperweightPlacementStateProcessor(child, mask, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementStateProcessor fork() {
|
||||
return new PaperweightPlacementStateProcessor(
|
||||
extent,
|
||||
mask,
|
||||
postCompleteSecondPasses,
|
||||
proxyLevel.serverLevel,
|
||||
threadProcessors,
|
||||
region,
|
||||
finished
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren